001: /*
002: This file is part of BORG.
003:
004: BORG is free software; you can redistribute it and/or modify
005: it under the terms of the GNU General Public License as published by
006: the Free Software Foundation; either version 2 of the License, or
007: (at your option) any later version.
008:
009: BORG is distributed in the hope that it will be useful,
010: but WITHOUT ANY WARRANTY; without even the implied warranty of
011: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: GNU General Public License for more details.
013:
014: You should have received a copy of the GNU General Public License
015: along with BORG; if not, write to the Free Software
016: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017:
018: Copyright 2004 by Mohan Embar - http://www.thisiscool.com/
019: */
020:
021: package net.sf.borg.model.db.remote;
022:
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import net.sf.borg.common.XTree;
029: import net.sf.borg.model.BorgOption;
030: import net.sf.borg.model.beans.Address;
031: import net.sf.borg.model.beans.AddressXMLAdapter;
032: import net.sf.borg.model.beans.Appointment;
033: import net.sf.borg.model.beans.AppointmentXMLAdapter;
034: import net.sf.borg.model.beans.BeanXMLAdapter;
035: import net.sf.borg.model.beans.KeyedBean;
036: import net.sf.borg.model.beans.Memo;
037: import net.sf.borg.model.beans.MemoXMLAdapter;
038: import net.sf.borg.model.beans.Project;
039: import net.sf.borg.model.beans.ProjectXMLAdapter;
040: import net.sf.borg.model.beans.Subtask;
041: import net.sf.borg.model.beans.SubtaskXMLAdapter;
042: import net.sf.borg.model.beans.Task;
043: import net.sf.borg.model.beans.TaskXMLAdapter;
044: import net.sf.borg.model.beans.Tasklog;
045: import net.sf.borg.model.beans.TasklogXMLAdapter;
046:
047: /**
048: * Helps marshal and unmarshal between objects and XML.
049: */
050: public class XmlObjectHelper {
051: public static XTree toXml(Object o) {
052: return toXml(null, o);
053: }
054:
055: public static Object fromXml(XTree xml) throws Exception {
056: if (xml == null)
057: return null;
058:
059: String name = xml.name();
060: if (name.equals("Null"))
061: return null;
062:
063: for (int i = 0; i < XML_CLASSES.length; ++i) {
064: if (XML_CLASSES[i].getObjectRootName().equals(name))
065: return XML_CLASSES[i].toObject(xml);
066: }
067:
068: throw new IllegalArgumentException(xml.name());
069: }
070:
071: // private //
072: private static final PrimitiveXmlObjectHelper NULL_HELPER = new PrimitiveXmlObjectHelper(
073: null, "Null");
074:
075: private static final IXmlObjectHelper[] XML_CLASSES = {
076: new BorgOptionXmlObjectHelper(),
077: new CollectionXmlObjectHelper(),
078: new PrimitiveXmlObjectHelper(String.class, "String"),
079: new PrimitiveXmlObjectHelper(Boolean.class, "Boolean"),
080: new PrimitiveXmlObjectHelper(Integer.class, "Integer"),
081: new RemoteParmsXmlObjectHelper(),
082: new ComposedObjectXmlObjectHelper(),
083: new BeanXmlObjectHelper(Address.class, "Address",
084: new AddressXMLAdapter()),
085: new BeanXmlObjectHelper(Appointment.class, "Appointment",
086: new AppointmentXMLAdapter()),
087: new BeanXmlObjectHelper(Task.class, "Task",
088: new TaskXMLAdapter()),
089: new BeanXmlObjectHelper(Memo.class, "Memo",
090: new MemoXMLAdapter()),
091: new BeanXmlObjectHelper(Project.class, "Project",
092: new ProjectXMLAdapter()),
093: new BeanXmlObjectHelper(Tasklog.class, "Tasklog",
094: new TasklogXMLAdapter()),
095: new BeanXmlObjectHelper(Subtask.class, "Subtask",
096: new SubtaskXMLAdapter()) };
097:
098: private static void addPrimitive(XTree xml, String name, String val) {
099: xml.appendChild(name, val);
100: }
101:
102: private static String getStringPrimitive(XTree xml, String name) {
103: XTree child = xml.child(name);
104: if (child == null)
105: throw new IllegalArgumentException(xml.name() + "/" + name);
106: return child.value();
107: }
108:
109: private static XTree createTree(XTree parent, String name) {
110: XTree tree = null;
111: if (parent == null) {
112: tree = new XTree();
113: tree.name(name);
114: } else {
115: tree = parent.appendChild(name);
116: }
117: return tree;
118: }
119:
120: private XmlObjectHelper() {
121: }
122:
123: public static XTree toXml(XTree parent, Object o) {
124: IXmlObjectHelper helper = null;
125: if (o == null)
126: helper = NULL_HELPER;
127: else {
128: for (int i = 0; i < XML_CLASSES.length; ++i) {
129: if (XML_CLASSES[i].getObjectClass().isAssignableFrom(
130: o.getClass())) {
131: helper = XML_CLASSES[i];
132: break;
133: }
134: }
135: }
136:
137: if (helper == null)
138: throw new IllegalArgumentException();
139:
140: XTree tree = createTree(parent, helper.getObjectRootName());
141: helper.populate(tree, o);
142: return tree;
143: }
144:
145: // //////////////////////////////////////////////////////////
146: // nested interface IXmlObjectHelper
147:
148: private static interface IXmlObjectHelper {
149: public Class getObjectClass();
150:
151: public String getObjectRootName();
152:
153: public void populate(XTree xtree, Object o);
154:
155: public Object toObject(XTree xml) throws Exception;
156: }
157:
158: // end nested class IXmlObjectHelper
159: // //////////////////////////////////////////////////////////
160:
161: // //////////////////////////////////////////////////////////
162: // nested class BorgOptionXmlObjectHelper
163:
164: private static class BorgOptionXmlObjectHelper implements
165: IXmlObjectHelper {
166: public final Class getObjectClass() {
167: return BorgOption.class;
168: }
169:
170: public final String getObjectRootName() {
171: return "BorgOption";
172: }
173:
174: public final void populate(XTree xtree, Object o) {
175: BorgOption val = (BorgOption) o;
176: addPrimitive(xtree, "Key", val.getKey());
177: addPrimitive(xtree, "Value", val.getValue());
178: }
179:
180: public final Object toObject(XTree xml) throws Exception {
181: String key = getStringPrimitive(xml, "Key");
182: String value = getStringPrimitive(xml, "Value");
183: return new BorgOption(key, value);
184: }
185: }
186:
187: // end nested class BorgOptionXmlObjectHelper
188:
189: private static class PrimitiveXmlObjectHelper implements
190: IXmlObjectHelper {
191: public Class getObjectClass() {
192: return cls;
193: }
194:
195: public final String getObjectRootName() {
196: return name;
197: }
198:
199: public final void populate(XTree xtree, Object o) {
200: if (o != null)
201: xtree.value(o.toString());
202: }
203:
204: public Object toObject(XTree xml) throws Exception {
205: String val = xml.value();
206: Object o = null;
207: if (name.equals("String"))
208: o = val;
209: else if (name.equals("Integer"))
210: o = Integer.valueOf(val);
211: else if (name.equals("Boolean"))
212: o = Boolean.valueOf(val);
213: return o;
214: }
215:
216: // internal //
217: PrimitiveXmlObjectHelper(Class cls, String name) {
218: this .cls = cls;
219: this .name = name;
220: }
221:
222: // private //
223: private Class cls;
224:
225: private String name;
226: }
227:
228: // end nested class PrimitiveXmlObjectHelper
229: // //////////////////////////////////////////////////////////
230:
231: // //////////////////////////////////////////////////////////
232: // nested class CollectionXmlObjectHelper
233:
234: private static class CollectionXmlObjectHelper implements
235: IXmlObjectHelper {
236: public Class getObjectClass() {
237: return Collection.class;
238: }
239:
240: public final String getObjectRootName() {
241: return "Collection";
242: }
243:
244: public final void populate(XTree xtree, Object o) {
245: Collection col = (Collection) o;
246: Iterator itr = col.iterator();
247: while (itr.hasNext()) {
248: Object oChild = itr.next();
249: toXml(xtree, oChild);
250: }
251: }
252:
253: public Object toObject(XTree xml) throws Exception {
254: // FUTURE: With the current XTree implementation,
255: // this operation requires O(n^2) time to execute, where
256: // n is the number of children.
257: List lst = new ArrayList();
258: int numChildren = xml.numChildren();
259: for (int i = 1; i <= numChildren; ++i) {
260: XTree child = xml.child(i);
261: Object oChild = fromXml(child);
262: lst.add(oChild);
263: }
264: return lst;
265: }
266: }
267:
268: // end nested class CollectionXmlObjectHelper
269: // //////////////////////////////////////////////////////////
270:
271: // //////////////////////////////////////////////////////////
272: // nested class RemoteParmsXmlObjectHelper
273:
274: private static class RemoteParmsXmlObjectHelper implements
275: IXmlObjectHelper {
276: public Class getObjectClass() {
277: return IRemoteProxy.Parms.class;
278: }
279:
280: public final String getObjectRootName() {
281: return "RemoteParms";
282: }
283:
284: public final void populate(XTree xtree, Object o) {
285: IRemoteProxy.Parms parms = (IRemoteProxy.Parms) o;
286: addPrimitive(xtree, "Class", parms.getClassString());
287: addPrimitive(xtree, "Command", parms.getCommand());
288: addPrimitive(xtree, "User", parms.getUser());
289: toXml(xtree, parms.getArgs());
290: }
291:
292: public Object toObject(XTree xml) throws Exception {
293: String classString = getStringPrimitive(xml, "Class");
294: String command = getStringPrimitive(xml, "Command");
295: String user = getStringPrimitive(xml, "User");
296: Object args = fromXml(xml.child(4));
297: return new IRemoteProxy.Parms(classString, command, args,
298: user);
299: }
300: }
301:
302: // end nested class RemoteParmsXmlObjectHelper
303: // //////////////////////////////////////////////////////////
304:
305: // //////////////////////////////////////////////////////////
306: // nested class ComposedObjectXmlObjectHelper
307:
308: private static class ComposedObjectXmlObjectHelper implements
309: IXmlObjectHelper {
310: public Class getObjectClass() {
311: return IRemoteProxy.ComposedObject.class;
312: }
313:
314: public final String getObjectRootName() {
315: return "ComposedObject";
316: }
317:
318: public final void populate(XTree xtree, Object o) {
319: IRemoteProxy.ComposedObject co = (IRemoteProxy.ComposedObject) o;
320: toXml(xtree, co.getO1());
321: toXml(xtree, co.getO2());
322: }
323:
324: public Object toObject(XTree xml) throws Exception {
325: Object o1 = fromXml(xml.child(1));
326: Object o2 = fromXml(xml.child(2));
327: return new IRemoteProxy.ComposedObject(o1, o2);
328: }
329: }
330:
331: // end nested class ComposedObjectXmlObjectHelper
332: // //////////////////////////////////////////////////////////
333:
334: // //////////////////////////////////////////////////////////
335: // nested class KeyedBeanXmlObjectHelper
336:
337: private static class BeanXmlObjectHelper implements
338: IXmlObjectHelper {
339: public Class getObjectClass() {
340: return cls;
341: }
342:
343: public final String getObjectRootName() {
344: return objectRootName;
345: }
346:
347: public final void populate(XTree xtree, Object o) {
348: XTree xml = xmlAdapter.toXml((KeyedBean) o);
349: xtree.adopt(xml);
350: }
351:
352: public Object toObject(XTree xml) {
353: KeyedBean keyedBean = xmlAdapter.fromXml(xml);
354: return keyedBean;
355: }
356:
357: // "package"
358: BeanXmlObjectHelper(Class cls, String objectRootName,
359: BeanXMLAdapter xmlAdapter) {
360: this .cls = cls;
361: this .objectRootName = objectRootName;
362: this .xmlAdapter = xmlAdapter;
363: }
364:
365: // private //
366: private Class cls;
367:
368: private String objectRootName;
369:
370: private BeanXMLAdapter xmlAdapter;
371: }
372:
373: // end nested class KeyedBeanXmlObjectHelper
374: // //////////////////////////////////////////////////////////
375: }
|