package com.tecnick.tmxjavabridge;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
* <p>
* Reads resource text data directly from a TMX (XML) file.
* </p>
* <p>
* First, the TMXResourceBundle 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.
* </p>
* <p>
* <b>TMX info: </b> http://www.lisa.org/tmx/
* </p>
*
* <h4>Implementation notes</h4>
* <p>
* You instantiate the TMXResourceBundle 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. <br>
* 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).
* </p>
*
* Copyright (c) 2004-2005
* Tecnick.com S.r.l (www.tecnick.com)
* Via Ugo Foscolo n.19 - 09045 Quartu Sant'Elena (CA) - ITALY
* www.tecnick.com - info@tecnick.com <br/>
* Project homepage: <a href="http://tmxjavabridge.sourceforge.net" target="_blank">http://tmxjavabridge.sourceforge.net</a><br/>
* License: http://www.gnu.org/copyleft/lesser.html LGPL
*
* @author Nicola Asuni [www.tecnick.com].
* @version 1.1.005
*/
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, supports also URI resources or JAR resources
* @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 <tu> attributes
Attr temp_attr = null; // <tu> attribute
NodeList listOfTUVs = null; // list of <tuv> elements
NodeList listOfSEG = null; // list of <seg> elements
Element SEGElements = null; // <seg> element
int numberOfTUVs = 0; // number of <tuv> 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().equalsIgnoreCase(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 <seg> value on <tu tuid=\"" + temp_key
+ "\"> 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 Document parseXmlFile(String filename, boolean validating) {
Document doc = null;
DocumentBuilderFactory factory = null;
// Create a builder factory
try {
factory = DocumentBuilderFactory.newInstance();
} catch (FactoryConfigurationError e) {
System.err.println(e);
return null;
}
factory.setValidating(validating);
// Create the builder and parse the file
try {
try {
// try to get the file from jar
InputStream instream = getClass().getResourceAsStream(filename);
doc = factory.newDocumentBuilder().parse(instream);
} catch (Exception ejar) {
try {
// try to get the file as external URI
doc = factory.newDocumentBuilder().parse(filename);
} catch (IOException euri) {
try {
// try to get the file as local filename
doc = factory.newDocumentBuilder().parse(new File(filename));
} catch (IOException efile) {
try {
// try to resolve the path as relative to local class folder
String[] classPath = System.getProperties().getProperty("java.class.path", ".").split(";");
String newpath = classPath[0] + "/" + filename;
doc = factory.newDocumentBuilder().parse(new File(newpath));
} catch (IOException epath) {
// unable to get the input file
System.err.println("IOException:" + epath);
}
}
}
}
} catch (ParserConfigurationException e) {
System.err.println("[" + filename + "] ParserConfigurationException:" + e);
} catch (SAXException e) {
System.err.println("[" + filename + "] SAXException:" + e);
}
return doc;
}
/**
* 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();
}
}