mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 02:24:05 +09:00
added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
This commit is contained in:
@@ -0,0 +1,483 @@
|
||||
package org.newdawn.slick.util.xml;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.newdawn.slick.util.Log;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
/**
|
||||
* Provides a method of parsing XML into an existing data model. This does not
|
||||
* provide the same functionality as JAXB or the variety of XML bindings out there. This
|
||||
* is a utility to map XML onto an existing data model. The idea being that the design level
|
||||
* model should not be driven by the XML schema thats defined. The two arn't always equal
|
||||
* and often you end up with a set of class that represent your XML that you then have
|
||||
* to traverse to extract into your normal data model.
|
||||
*
|
||||
* This utility hopes to take a piece of XML and map it onto a previously designed data
|
||||
* model. At the moment it's way to tied to the structure of the XML but this will
|
||||
* hopefully change with time.
|
||||
*
|
||||
* XML element names must be mapped to class names. This can be done in two ways either:
|
||||
*
|
||||
* - Specify an explict mapping with addElementMapping()
|
||||
* - Specify the default package name and use the element name as the class name
|
||||
*
|
||||
* Each attribute in an element is mapped into a property of the element class, preferably
|
||||
* through a set<AttrName> bean method, but alternatively by direct injection into private
|
||||
* fields.
|
||||
*
|
||||
* Each child element is added to the target class by call the method add() on it with a single
|
||||
* parameter of the type generated for the child element.
|
||||
*
|
||||
* Classes can optionally implement setXMLElementName(String) and setXMLElementContent(String) to
|
||||
* recieve the name and content respectively of the XMLElement they were parsed from. This can
|
||||
* help when mapping two elements to a single class.
|
||||
*
|
||||
* To reiterate, I'm not sure this is a good idea yet. It helps me as a utility since I've done
|
||||
* this several times in the past but in the general case it may not be perfect. Consider a custom
|
||||
* parser using XMLParser or JAXB (et al) seriously instead.
|
||||
*
|
||||
* @author kevin
|
||||
*
|
||||
*/
|
||||
public class ObjectTreeParser {
|
||||
/** The mapping of XML element names to class names */
|
||||
private HashMap nameToClass = new HashMap();
|
||||
/** The default package where classes will be searched for */
|
||||
private String defaultPackage;
|
||||
/** The list of elements to ignore */
|
||||
private ArrayList ignored = new ArrayList();
|
||||
/** The name of the method to add an child object to it's parent */
|
||||
private String addMethod = "add";
|
||||
|
||||
/**
|
||||
* Create an object tree parser with no default package
|
||||
*/
|
||||
public ObjectTreeParser() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an object tree parser specifing the default package
|
||||
* where classes will be search for using the XML element name
|
||||
*
|
||||
* @param defaultPackage The default package to be searched
|
||||
*/
|
||||
public ObjectTreeParser(String defaultPackage) {
|
||||
this.defaultPackage = defaultPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mapping between XML element name and class name
|
||||
*
|
||||
* @param elementName The name of the XML element
|
||||
* @param elementClass The class to be created for the given element
|
||||
*/
|
||||
public void addElementMapping(String elementName, Class elementClass) {
|
||||
nameToClass.put(elementName, elementClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a name to the list of elements ignored
|
||||
*
|
||||
* @param elementName The name to ignore
|
||||
*/
|
||||
public void addIgnoredElement(String elementName) {
|
||||
ignored.add(elementName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the method to use to add child objects to their
|
||||
* parents. This is sometimes useful to not clash with the existing
|
||||
* data model methods.
|
||||
*
|
||||
* @param methodName The name of the method to call
|
||||
*/
|
||||
public void setAddMethodName(String methodName) {
|
||||
addMethod = methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default package which will be search for classes by their XML
|
||||
* element name.
|
||||
*
|
||||
* @param defaultPackage The default package to be searched
|
||||
*/
|
||||
public void setDefaultPackage(String defaultPackage) {
|
||||
this.defaultPackage = defaultPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML document located by the slick resource loader using the
|
||||
* reference given.
|
||||
*
|
||||
* @param ref The reference to the XML document
|
||||
* @return The root element of the newly parse document
|
||||
* @throws SlickXMLException Indicates a failure to parse the XML, most likely the
|
||||
* XML is malformed in some way.
|
||||
*/
|
||||
public Object parse(String ref) throws SlickXMLException {
|
||||
return parse(ref, ResourceLoader.getResourceAsStream(ref));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML document that can be read from the given input stream
|
||||
*
|
||||
* @param name The name of the document
|
||||
* @param in The input stream from which the document can be read
|
||||
* @return The root element of the newly parse document
|
||||
* @throws SlickXMLException Indicates a failure to parse the XML, most likely the
|
||||
* XML is malformed in some way.
|
||||
*/
|
||||
public Object parse(String name, InputStream in) throws SlickXMLException {
|
||||
XMLParser parser = new XMLParser();
|
||||
XMLElement root = parser.parse(name, in);
|
||||
|
||||
return traverse(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML document located by the slick resource loader using the
|
||||
* reference given.
|
||||
*
|
||||
* @param ref The reference to the XML document
|
||||
* @param target The top level object that represents the root node
|
||||
* @return The root element of the newly parse document
|
||||
* @throws SlickXMLException Indicates a failure to parse the XML, most likely the
|
||||
* XML is malformed in some way.
|
||||
*/
|
||||
public Object parseOnto(String ref, Object target) throws SlickXMLException {
|
||||
return parseOnto(ref, ResourceLoader.getResourceAsStream(ref), target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML document that can be read from the given input stream
|
||||
*
|
||||
* @param name The name of the document
|
||||
* @param in The input stream from which the document can be read
|
||||
* @param target The top level object that represents the root node
|
||||
* @return The root element of the newly parse document
|
||||
* @throws SlickXMLException Indicates a failure to parse the XML, most likely the
|
||||
* XML is malformed in some way.
|
||||
*/
|
||||
public Object parseOnto(String name, InputStream in, Object target) throws SlickXMLException {
|
||||
XMLParser parser = new XMLParser();
|
||||
XMLElement root = parser.parse(name, in);
|
||||
|
||||
return traverse(root, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deterine the name of the class that should be used for a given
|
||||
* XML element name.
|
||||
*
|
||||
* @param name The name of the XML element
|
||||
* @return The class to be used or null if none can be found
|
||||
*/
|
||||
private Class getClassForElementName(String name) {
|
||||
Class clazz = (Class) nameToClass.get(name);
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
if (defaultPackage != null) {
|
||||
try {
|
||||
return Class.forName(defaultPackage+"."+name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// ignore, it's just not there
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the XML element specified generating the appropriate object structure
|
||||
* for it and it's children
|
||||
*
|
||||
* @param current The XML element to process
|
||||
* @return The object created for the given element
|
||||
* @throws SlickXMLException
|
||||
*/
|
||||
private Object traverse(XMLElement current) throws SlickXMLException {
|
||||
return traverse(current, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the XML element specified generating the appropriate object structure
|
||||
* for it and it's children
|
||||
*
|
||||
* @param current The XML element to process
|
||||
* @param instance The instance to parse onto, normally null
|
||||
* @return The object created for the given element
|
||||
* @throws SlickXMLException
|
||||
*/
|
||||
private Object traverse(XMLElement current, Object instance) throws SlickXMLException {
|
||||
String name = current.getName();
|
||||
if (ignored.contains(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class clazz;
|
||||
|
||||
if (instance == null) {
|
||||
clazz = getClassForElementName(name);
|
||||
} else {
|
||||
clazz = instance.getClass();
|
||||
}
|
||||
|
||||
if (clazz == null) {
|
||||
throw new SlickXMLException("Unable to map element "+name+" to a class, define the mapping");
|
||||
}
|
||||
|
||||
try {
|
||||
if (instance == null) {
|
||||
instance = clazz.newInstance();
|
||||
|
||||
Method elementNameMethod = getMethod(clazz, "setXMLElementName", new Class[] {String.class});
|
||||
if (elementNameMethod != null) {
|
||||
invoke(elementNameMethod, instance, new Object[] {name});
|
||||
}
|
||||
Method contentMethod = getMethod(clazz, "setXMLElementContent", new Class[] {String.class});
|
||||
if (contentMethod != null) {
|
||||
invoke(contentMethod, instance, new Object[] {current.getContent()});
|
||||
}
|
||||
}
|
||||
|
||||
String[] attrs = current.getAttributeNames();
|
||||
for (int i=0;i<attrs.length;i++) {
|
||||
String methodName = "set"+attrs[i];
|
||||
|
||||
Method method = findMethod(clazz, methodName);
|
||||
|
||||
if (method == null) {
|
||||
Field field = findField(clazz, attrs[i]);
|
||||
if (field != null) {
|
||||
String value = current.getAttribute(attrs[i]);
|
||||
Object typedValue = typeValue(value, field.getType());
|
||||
setField(field, instance, typedValue);
|
||||
} else {
|
||||
Log.info("Unable to find property on: "+clazz+" for attribute: "+attrs[i]);
|
||||
}
|
||||
} else {
|
||||
String value = current.getAttribute(attrs[i]);
|
||||
Object typedValue = typeValue(value, method.getParameterTypes()[0]);
|
||||
invoke(method, instance, new Object[] {typedValue});
|
||||
}
|
||||
}
|
||||
|
||||
XMLElementList children = current.getChildren();
|
||||
for (int i=0;i<children.size();i++) {
|
||||
XMLElement element = children.get(i);
|
||||
|
||||
Object child = traverse(element);
|
||||
if (child != null) {
|
||||
String methodName = addMethod;
|
||||
|
||||
Method method = findMethod(clazz, methodName, child.getClass());
|
||||
if (method == null) {
|
||||
Log.info("Unable to find method to add: "+child+" to "+clazz);
|
||||
} else {
|
||||
invoke(method, instance, new Object[] {child});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
} catch (InstantiationException e) {
|
||||
throw new SlickXMLException("Unable to instance "+clazz+" for element "+name+", no zero parameter constructor?", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SlickXMLException("Unable to instance "+clazz+" for element "+name+", no zero parameter constructor?", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a given value to a given type
|
||||
*
|
||||
* @param value The value to convert
|
||||
* @param clazz The class that the returned object must be
|
||||
* @return The value as the given type
|
||||
* @throws SlickXMLException Indicates there is no automatic way of converting the value to the type
|
||||
*/
|
||||
private Object typeValue(String value, Class clazz) throws SlickXMLException {
|
||||
if (clazz == String.class) {
|
||||
return value;
|
||||
}
|
||||
|
||||
try {
|
||||
clazz = mapPrimitive(clazz);
|
||||
return clazz.getConstructor(new Class[] {String.class}).newInstance(new Object[] {value});
|
||||
} catch (Exception e) {
|
||||
throw new SlickXMLException("Failed to convert: "+value+" to the expected primitive type: "+clazz, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a primitive class type to it's real object wrapper
|
||||
*
|
||||
* @param clazz The primitive type class
|
||||
* @return The object wrapper class
|
||||
*/
|
||||
private Class mapPrimitive(Class clazz) {
|
||||
if (clazz == Integer.TYPE) {
|
||||
return Integer.class;
|
||||
}
|
||||
if (clazz == Double.TYPE) {
|
||||
return Double.class;
|
||||
}
|
||||
if (clazz == Float.TYPE) {
|
||||
return Float.class;
|
||||
}
|
||||
if (clazz == Boolean.TYPE) {
|
||||
return Boolean.class;
|
||||
}
|
||||
if (clazz == Long.TYPE) {
|
||||
return Long.class;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unsupported primitive: "+clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a field in a class by it's name. Note that this method is
|
||||
* only needed because the general reflection method is case
|
||||
* sensitive
|
||||
*
|
||||
* @param clazz The clazz to search
|
||||
* @param name The name of the field to search for
|
||||
* @return The field or null if none could be located
|
||||
*/
|
||||
private Field findField(Class clazz, String name) {
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (int i=0;i<fields.length;i++) {
|
||||
if (fields[i].getName().equalsIgnoreCase(name)) {
|
||||
if (fields[i].getType().isPrimitive()) {
|
||||
return fields[i];
|
||||
}
|
||||
if (fields[i].getType() == String.class) {
|
||||
return fields[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a method in a class by it's name. Note that this method is
|
||||
* only needed because the general reflection method is case
|
||||
* sensitive
|
||||
*
|
||||
* @param clazz The clazz to search
|
||||
* @param name The name of the method to search for
|
||||
* @return The method or null if none could be located
|
||||
*/
|
||||
private Method findMethod(Class clazz, String name) {
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (int i=0;i<methods.length;i++) {
|
||||
if (methods[i].getName().equalsIgnoreCase(name)) {
|
||||
Method method = methods[i];
|
||||
Class[] params = method.getParameterTypes();
|
||||
|
||||
if (params.length == 1) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a method on a class with a single given parameter.
|
||||
*
|
||||
* @param clazz The clazz to search through
|
||||
* @param name The name of the method to locate
|
||||
* @param parameter The type the single parameter must have
|
||||
* @return The method or null if none could be located
|
||||
*/
|
||||
private Method findMethod(Class clazz, String name, Class parameter) {
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (int i=0;i<methods.length;i++) {
|
||||
if (methods[i].getName().equalsIgnoreCase(name)) {
|
||||
Method method = methods[i];
|
||||
Class[] params = method.getParameterTypes();
|
||||
|
||||
if (params.length == 1) {
|
||||
if (method.getParameterTypes()[0].isAssignableFrom(parameter)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a field value on a object instance
|
||||
*
|
||||
* @param field The field to be set
|
||||
* @param instance The instance of the object to set it on
|
||||
* @param value The value to set
|
||||
* @throws SlickXMLException Indicates a failure to set or access the field
|
||||
*/
|
||||
private void setField(Field field, Object instance, Object value) throws SlickXMLException {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(instance, value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SlickXMLException("Failed to set: "+field+" for an XML attribute, is it valid?", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SlickXMLException("Failed to set: "+field+" for an XML attribute, is it valid?", e);
|
||||
} finally {
|
||||
field.setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a method on a object
|
||||
*
|
||||
* @param method The method to call
|
||||
* @param instance The objet to call the method on
|
||||
* @param params The parameters to pass
|
||||
* @throws SlickXMLException Indicates a failure to call or access the method
|
||||
*/
|
||||
private void invoke(Method method, Object instance, Object[] params) throws SlickXMLException {
|
||||
try {
|
||||
method.setAccessible(true);
|
||||
method.invoke(instance, params);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new SlickXMLException("Failed to invoke: "+method+" for an XML attribute, is it valid?", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new SlickXMLException("Failed to invoke: "+method+" for an XML attribute, is it valid?", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new SlickXMLException("Failed to invoke: "+method+" for an XML attribute, is it valid?", e);
|
||||
} finally {
|
||||
method.setAccessible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a method on a given class. Only here for tidy purposes,
|
||||
* hides the the big exceptions.
|
||||
*
|
||||
* @param clazz The class to search
|
||||
* @param name The name of the method
|
||||
* @param params The parameters for the method
|
||||
* @return The method or null if none can be found
|
||||
*/
|
||||
private Method getMethod(Class clazz, String name, Class[] params) {
|
||||
try {
|
||||
return clazz.getMethod(name, params);
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.newdawn.slick.util.xml;
|
||||
|
||||
import org.newdawn.slick.SlickException;
|
||||
|
||||
/**
|
||||
* An exception to describe failures in XML. Made a special case because with XML
|
||||
* to object parsing you might want to handle it differently
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class SlickXMLException extends SlickException {
|
||||
|
||||
/**
|
||||
* Create a new exception
|
||||
*
|
||||
* @param message The message describing the failure
|
||||
*/
|
||||
public SlickXMLException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new exception
|
||||
*
|
||||
* @param message The message describing the failure
|
||||
* @param e The exception causing this failure
|
||||
*/
|
||||
public SlickXMLException(String message, Throwable e) {
|
||||
super(message, e);
|
||||
}
|
||||
|
||||
}
|
||||
260
lib/slick-source/org/newdawn/slick/util/xml/XMLElement.java
Normal file
260
lib/slick-source/org/newdawn/slick/util/xml/XMLElement.java
Normal file
@@ -0,0 +1,260 @@
|
||||
package org.newdawn.slick.util.xml;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
/**
|
||||
* A utility wrapper round the standard DOM XML element. This provides a more simple API
|
||||
* for accessing attributes, children and providing defaults when schemas arn't used - which
|
||||
* is generally a little simpler for most of us.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class XMLElement {
|
||||
/** The Java DOM implementation XML element */
|
||||
private Element dom;
|
||||
/** The list of children initialised on first access */
|
||||
private XMLElementList children;
|
||||
/** The name of the element */
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Create a new element wrapped round a DOM element
|
||||
*
|
||||
* @param xmlElement The DOM element to present
|
||||
*/
|
||||
XMLElement(Element xmlElement) {
|
||||
dom = xmlElement;
|
||||
name = dom.getTagName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the names of the attributes specified on this element
|
||||
*
|
||||
* @return The names of the elements specified
|
||||
*/
|
||||
public String[] getAttributeNames() {
|
||||
NamedNodeMap map = dom.getAttributes();
|
||||
String[] names = new String[map.getLength()];
|
||||
|
||||
for (int i=0;i<names.length;i++) {
|
||||
names[i] = map.item(i).getNodeName();
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this element
|
||||
*
|
||||
* @return The name of this element
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @return The value given for the attribute
|
||||
*/
|
||||
public String getAttribute(String name) {
|
||||
return dom.getAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @param def The default value to return if the attribute is specified
|
||||
* @return The value given for the attribute
|
||||
*/
|
||||
public String getAttribute(String name, String def) {
|
||||
String value = dom.getAttribute(name);
|
||||
if ((value == null) || (value.length() == 0)) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element as an integer.
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @return The value given for the attribute
|
||||
* @throws SlickXMLException Indicates a failure to convert the value into an integer
|
||||
*/
|
||||
public int getIntAttribute(String name) throws SlickXMLException {
|
||||
try {
|
||||
return Integer.parseInt(getAttribute(name));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SlickXMLException("Value read: '"+getAttribute(name)+"' is not an integer",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element as an integer.
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @param def The default value to return if the attribute is specified
|
||||
* @return The value given for the attribute
|
||||
* @throws SlickXMLException Indicates a failure to convert the value into an integer
|
||||
*/
|
||||
public int getIntAttribute(String name, int def) throws SlickXMLException {
|
||||
try {
|
||||
return Integer.parseInt(getAttribute(name,""+def));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SlickXMLException("Value read: '"+getAttribute(name, ""+def)+"' is not an integer",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element as an double.
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @return The value given for the attribute
|
||||
* @throws SlickXMLException Indicates a failure to convert the value into an double
|
||||
*/
|
||||
public double getDoubleAttribute(String name) throws SlickXMLException {
|
||||
try {
|
||||
return Double.parseDouble(getAttribute(name));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SlickXMLException("Value read: '"+getAttribute(name)+"' is not a double",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element as an double.
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @param def The default value to return if the attribute is specified
|
||||
* @return The value given for the attribute
|
||||
* @throws SlickXMLException Indicates a failure to convert the value into an double
|
||||
*/
|
||||
public double getDoubleAttribute(String name, double def) throws SlickXMLException {
|
||||
try {
|
||||
return Double.parseDouble(getAttribute(name,""+def));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SlickXMLException("Value read: '"+getAttribute(name, ""+def)+"' is not a double",e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element as a boolean.
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @return The value given for the attribute
|
||||
* @throws SlickXMLException Indicates a failure to convert the value into an boolean
|
||||
*/
|
||||
public boolean getBooleanAttribute(String name) throws SlickXMLException {
|
||||
String value = getAttribute(name);
|
||||
if (value.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
}
|
||||
if (value.equalsIgnoreCase("false")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new SlickXMLException("Value read: '"+getAttribute(name)+"' is not a boolean");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the value specified for a given attribute on this element as a boolean.
|
||||
*
|
||||
* @param name The name of the attribute whose value should be retrieved
|
||||
* @param def The default value to return if the attribute is specified
|
||||
* @return The value given for the attribute
|
||||
* @throws SlickXMLException Indicates a failure to convert the value into an boolean
|
||||
*/
|
||||
public boolean getBooleanAttribute(String name, boolean def) throws SlickXMLException {
|
||||
String value = getAttribute(name,""+def);
|
||||
if (value.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
}
|
||||
if (value.equalsIgnoreCase("false")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new SlickXMLException("Value read: '"+getAttribute(name, ""+def)+"' is not a boolean");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text content of the element, i.e. the bit between the tags
|
||||
*
|
||||
* @return The text content of the node
|
||||
*/
|
||||
public String getContent() {
|
||||
String content = "";
|
||||
|
||||
NodeList list = dom.getChildNodes();
|
||||
for (int i=0;i<list.getLength();i++) {
|
||||
if (list.item(i) instanceof Text) {
|
||||
content += (list.item(i).getNodeValue());
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete list of children for this node
|
||||
*
|
||||
* @return The list of children for this node
|
||||
*/
|
||||
public XMLElementList getChildren() {
|
||||
if (children != null) {
|
||||
return children;
|
||||
}
|
||||
|
||||
NodeList list = dom.getChildNodes();
|
||||
children = new XMLElementList();
|
||||
|
||||
for (int i=0;i<list.getLength();i++) {
|
||||
if (list.item(i) instanceof Element) {
|
||||
children.add(new XMLElement((Element) list.item(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of children with a given element name
|
||||
*
|
||||
* @param name The name of the element type that should be retrieved
|
||||
* @return A list of elements
|
||||
*/
|
||||
public XMLElementList getChildrenByName(String name) {
|
||||
XMLElementList selected = new XMLElementList();
|
||||
XMLElementList children = getChildren();
|
||||
|
||||
for (int i=0;i<children.size();i++) {
|
||||
if (children.get(i).getName().equals(name)) {
|
||||
selected.add(children.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
String value = "[XML "+getName();
|
||||
String[] attrs = getAttributeNames();
|
||||
|
||||
for (int i=0;i<attrs.length;i++) {
|
||||
value += " "+attrs[i]+"="+getAttribute(attrs[i]);
|
||||
}
|
||||
|
||||
value += "]";
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.newdawn.slick.util.xml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A simple typed list.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class XMLElementList {
|
||||
/** The list of elements */
|
||||
private ArrayList list = new ArrayList();
|
||||
|
||||
/**
|
||||
* Create a new list
|
||||
*/
|
||||
public XMLElementList() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to the list
|
||||
*
|
||||
* @param element The element to be added
|
||||
*/
|
||||
public void add(XMLElement element) {
|
||||
list.add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of elements in the list
|
||||
*
|
||||
* @return The number of elements in the list
|
||||
*/
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element at a specified index
|
||||
*
|
||||
* @param i The index of the element
|
||||
* @return The element at the specified index
|
||||
*/
|
||||
public XMLElement get(int i) {
|
||||
return (XMLElement) list.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this list contains the given element
|
||||
*
|
||||
* @param element The element to check for
|
||||
* @return True if the element is in the list
|
||||
*/
|
||||
public boolean contains(XMLElement element) {
|
||||
return list.contains(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the elements in this list to another collection
|
||||
*
|
||||
* @param collection The collection the elements should be added to
|
||||
*/
|
||||
public void addAllTo(Collection collection) {
|
||||
collection.addAll(list);
|
||||
}
|
||||
}
|
||||
63
lib/slick-source/org/newdawn/slick/util/xml/XMLParser.java
Normal file
63
lib/slick-source/org/newdawn/slick/util/xml/XMLParser.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package org.newdawn.slick.util.xml;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* A simple utility wrapper around the Java DOM implementation to hopefully
|
||||
* make XML parsing that bit easier without requiring YAL.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class XMLParser {
|
||||
/** The factory used to to create document builders that parse XML into the DOM */
|
||||
private static DocumentBuilderFactory factory;
|
||||
|
||||
/**
|
||||
* Create a new parser
|
||||
*/
|
||||
public XMLParser() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML document located by the slick resource loader using the
|
||||
* reference given.
|
||||
*
|
||||
* @param ref The reference to the XML document
|
||||
* @return The root element of the newly parse document
|
||||
* @throws SlickException Indicates a failure to parse the XML, most likely the
|
||||
* XML is malformed in some way.
|
||||
*/
|
||||
public XMLElement parse(String ref) throws SlickException {
|
||||
return parse(ref, ResourceLoader.getResourceAsStream(ref));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML document that can be read from the given input stream
|
||||
*
|
||||
* @param name The name of the document
|
||||
* @param in The input stream from which the document can be read
|
||||
* @return The root element of the newly parse document
|
||||
* @throws SlickXMLException Indicates a failure to parse the XML, most likely the
|
||||
* XML is malformed in some way.
|
||||
*/
|
||||
public XMLElement parse(String name, InputStream in) throws SlickXMLException {
|
||||
try {
|
||||
if (factory == null) {
|
||||
factory = DocumentBuilderFactory.newInstance();
|
||||
}
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = builder.parse(in);
|
||||
|
||||
return new XMLElement(doc.getDocumentElement());
|
||||
} catch (Exception e) {
|
||||
throw new SlickXMLException("Failed to parse document: "+name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
lib/slick-source/org/newdawn/slick/util/xml/package.html
Normal file
3
lib/slick-source/org/newdawn/slick/util/xml/package.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<BODY>
|
||||
Some utilities for reading XML using Java DOM and for mapping XML onto existing data models
|
||||
</BODY>
|
||||
Reference in New Issue
Block a user