package org.etk.kernel.container.xml.object; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.jibx.runtime.BindingDirectory; import org.jibx.runtime.IBindingFactory; import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.IUnmarshallingContext; public class XMLObject { public static String CURRENT_VERSION = "1.0"; private static Map cacheFields = new HashMap(); private Map fields = new HashMap(); private String type; public XMLObject() { } public XMLObject(Object obj) throws Exception { Class clazz = obj.getClass(); Map fields = getFields(clazz); setType(obj.getClass().getName()); Iterator i = fields.values().iterator(); while (i.hasNext()) { Field field = (Field) i.next(); Object value = field.get(obj); addField(new XMLField(field.getName(), field.getType(), value)); } } public String getType() { return type; } public void setType(String s) { type = s; } public XMLField getField(String name) { return (XMLField) fields.get(name); } public void addField(Object o) { XMLField field = (XMLField) o; fields.put(field.getName(), field); } public void addField(XMLField field) { fields.put(field.getName(), field); } public Iterator getFieldIterator() { return fields.values().iterator(); } public Collection getFields() { return fields.values(); } public void setFields(Collection fieldsArg) { Iterator i = fieldsArg.iterator(); while (i.hasNext()) { XMLField field = (XMLField) i.next(); this.fields.put(field.getName(), field); } } public void setFields(Map fields) { this.fields.putAll(fields); } public Object getFieldValue(String fieldName) throws Exception { XMLField field = (XMLField) this.fields.get(fieldName); if (field != null) return field.getObjectValue(); return null; } public void renameField(String oldName, String newName) { XMLField field = (XMLField) this.fields.remove(oldName); field.setName(newName); this.fields.put(newName, field); } public void removeField(String name) { this.fields.remove(name); } public void addField(String name, Class fieldType, Object obj) throws Exception { addField(new XMLField(name, fieldType, obj)); } public String toString() { StringBuffer b = new StringBuffer(); b.append("type: ").append(type).append("\n"); Iterator i = fields.values().iterator(); while (i.hasNext()) { XMLField field = (XMLField) i.next(); b.append(field.toString()).append("\n"); } return b.toString(); } public Object toObject() throws Exception { Class clazz = Class.forName(type); Map fields = getFields(clazz); Object instance = clazz.newInstance(); Iterator i = this.fields.values().iterator(); while (i.hasNext()) { XMLField xmlfield = (XMLField) i.next(); try { Object value = xmlfield.getObjectValue(); Field field = (Field) fields.get(xmlfield.getName()); field.set(instance, value); } catch (Exception ex) { System.err.println("ERROR: Cannot set field: " + xmlfield.getName() + " of " + type); throw ex; } } return instance; } public String toXML() throws Exception { return toXML("UTF-8"); } public String toXML(String encoding) throws Exception { return new String(toByteArray(encoding), encoding); } public byte[] toByteArray() throws Exception { return toByteArray("UTF-8"); } public byte[] toByteArray(String encoding) throws Exception { IBindingFactory bfact = BindingDirectory.getFactory(XMLObject.class); IMarshallingContext mctx = bfact.createMarshallingContext(); mctx.setIndent(2); ByteArrayOutputStream os = new ByteArrayOutputStream(); mctx.marshalDocument(this, encoding, null, os); return os.toByteArray(); } static public XMLObject getXMLObject(InputStream is) throws Exception { IBindingFactory bfact = BindingDirectory.getFactory(XMLObject.class); IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); XMLObject xmlobject = (XMLObject) uctx.unmarshalDocument(is, "UTF-8"); return xmlobject; } static public Object getObject(InputStream is) throws Exception { return getXMLObject(is).toObject(); } static Map getFields(Class clazz) { Map fields = (Map) cacheFields.get(clazz); if (fields != null) return fields; synchronized (cacheFields) { fields = new HashMap(); findFields(fields, clazz); cacheFields.put(clazz, fields); } return fields; } static void findFields(Map fields, Class clazz) { if (clazz.getName().startsWith("java.lang")) return; findFields(fields, clazz.getSuperclass()); Field[] field = clazz.getDeclaredFields(); for (int i = 0; i < field.length; i++) { int modifier = field[i].getModifiers(); if (Modifier.isStatic(modifier) || Modifier.isTransient(modifier)) continue; field[i].setAccessible(true); fields.put(field[i].getName(), field[i]); } } }