package tmxtest;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
*
Reads resource text data directly from a TMX (XML) file.
* First, the XMLTMXResourceBundle class instantiates itself with two parameters:
* a TMX file name and a target language name. Then, using a DOM parser, it
* reads all of a translation unit's properties for the key information and
* specified language data and populates a hashtable with them.
* TMX info: http://www.lisa.org/tmx/
* Reference: Masaki Itagaki article (http://www.lisa.org/tmx/m_itagaki.html)
*
* Implementation notes
* You instantiate the XMLTMXResourceBundle class in a program to read data from a
* TMX file. Once the class is instantiated, it reads all the data in a TMX file
* and loads into a DOM tree. Then it populates a hashtable so the
* handleGetObject() method can be called to find text information based on a
* key just as a standard ResourceBundle class does.
* Instantiating the TMXResouceBundle class is the same as instantiating the
* PropertyResourceBundle class. First you obtain a system language code (e.g.:
* from a locale's information). In TMX the value of the attribute must be one of the
* ISO language identifiers (a two- or three-letter code) or one of the standard
* locale identifiers (a two- or three-letter language code, a dash, and a
* two-letter region code).
* @author Nicola Asuni [www.tecnick.com].
* @version 1.0
*/
public class TMXResourceBundle
extends ResourceBundle {
/**
* The hastable that will contain data loaded from XML
*/
protected Hashtable hashcontents = null;
/**
* Number of translation units (tu) items
*/
protected int numberOfItems = 0;
/**
* Vector to store tu items keys
*/
protected Vector vectOfItems;
/**
* TMX to Hashtable conversion.
* Reads XML and store data in HashTable.
* @param xmlfile the TMX (XML) file to read
* @param language ISO language identifier (a two- or three-letter code)
*/
public TMXResourceBundle(String xmlfile, String language) {
String temp_key = null; // store hashtable key names
String temp_value = null; // store hashtable values
NamedNodeMap temp_list = null; // list of attributes
Attr temp_attr = null; // attribute
NodeList listOfTUVs = null; // list of elements
NodeList listOfSEG = null; // list of elements
Element SEGElements = null; // element
int numberOfTUVs = 0; // number of elements
// Create Document with parser
Document document = parseXmlFile(xmlfile, false);
// handle document error
if (document == null) {
hashcontents = new Hashtable(); //initialize a void hashtable
return;
}
// Make a list of Term Units and count the number of items
NodeList listOfTermUnits = document.getElementsByTagName("tu");
numberOfItems = listOfTermUnits.getLength();
// set tu keys vector size
vectOfItems = new Vector(numberOfItems);
// set hash size
hashcontents = new Hashtable(numberOfItems);
for (int i = 0; i < numberOfItems; i++) {
temp_value = null;
// set a key
temp_list = listOfTermUnits.item(i).getAttributes();
temp_attr = (Attr) temp_list.getNamedItem("tuid");
temp_key = temp_attr.getValue();
vectOfItems.add(temp_key); // store key on vector
// get a value
// Make a TUV list => "listOfTUVs"
Node TUVs = listOfTermUnits.item(i);
if (TUVs.getNodeType() == Node.ELEMENT_NODE) {
Element TUVElements = (Element) TUVs;
listOfTUVs = TUVElements.getElementsByTagName("tuv");
numberOfTUVs = listOfTUVs.getLength();
}
// Check each TUV. If it's a specified lang, then get a SEG value
for (int j = 0; j < numberOfTUVs; j++) {
temp_list = listOfTUVs.item(j).getAttributes();
temp_attr = (Attr) temp_list.getNamedItem("xml:lang");
if (temp_attr.getValue().equals(language)) {
// -- Get a SEG value
SEGElements = (Element) listOfTUVs.item(j);
listOfSEG = SEGElements.getElementsByTagName("seg");
try {
temp_value = listOfSEG.item(0).getFirstChild().getNodeValue();
} catch (Exception e) {
// in case of error print error message and set value to void string
System.err.println(this.getClass().getName() + "(\"" + xmlfile
+ "\", \""
+ language + "\") :: "
+ "Void value on key");
temp_value = "";
}
}
}
// Populate hashtable
if ((temp_key != null) && (temp_value != null)) {
hashcontents.put(temp_key, temp_value);
}
} // for loop
} // convert
/**
* Parses an XML file and returns a DOM document.
*
* @param filename the name of XML file
* @param validating If true, the contents is validated against the DTD specified in the file.
* @return the parsed document
*/
public static Document parseXmlFile(String filename, boolean validating) {
try {
// Create a builder factory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validating);
// Create the builder and parse the file
Document doc = factory.newDocumentBuilder().parse(new File(filename));
return doc;
} catch (SAXException e) {
// A parsing error occurred; the xml input is not valid
System.err.println("[" + filename + "] SAXException:" + e);
} catch (ParserConfigurationException e) {
System.err.println("[" + filename + "] ParserConfigurationException:" + e);
} catch (IOException e) {
System.err.println("[" + filename + "] IOException:" + e);
}
return null;
}
/**
* Get key value, return default if void.
* @param key name of key
* @param def default value
* @return parameter value or default
*/
public String getString(String key, String def) {
String param_value = "";
try {
param_value = this.getString(key);
if ((param_value != null) && (param_value.length() > 0)) {
return param_value;
}
} catch (Exception e) {
// for any exception return the default value
return def;
}
return def;
}
/**
* handleGetObject implementation
* @param key the resource key
* @return the content associated to the specified key
* @throws MissingResourceException
*/
public final Object handleGetObject(String key)
throws MissingResourceException {
return hashcontents.get(key);
}
/**
* Returns the number of translation units
* @return number of Items
*/
public int getNumberOfItems() {
return numberOfItems;
}
/**
* Define getKeys method
* @return item elements
*/
public Enumeration getKeys() {
return vectOfItems.elements();
}
}