001: // You can redistribute this software and/or modify it under the terms of
002: // the Ozone Core License version 1 published by ozone-db.org.
003: //
004: // The original code and portions created by SMB are
005: // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006: //
007: // $Id: XML2ObjectContentHandler.java,v 1.1 2001/12/18 10:31:31 per_nyfelt Exp $
008:
009: package org.ozoneDB.core.xml;
010:
011: import java.io.*;
012: import java.util.*;
013: import java.lang.reflect.*;
014:
015: import org.xml.sax.*;
016: import org.apache.xerces.parsers.SAXParser;
017:
018: import org.ozoneDB.OzoneProxy;
019: import org.ozoneDB.core.ObjectID;
020:
021: /**
022: * This class handles the XML and transform it into an Object.
023: *
024: * @version $Revision: 1.1 $
025: * @author <a href="http://www.softwarebuero.de">SMB</a>
026: */
027: public class XML2ObjectContentHandler implements ContentHandler, Consts {
028:
029: public static final boolean debug = false;
030:
031: //
032: // member
033: //
034:
035: /**
036: */
037: protected Locator locator;
038:
039: /**
040: * Cache for the ref-elements.
041: */
042: protected static Hashtable objCache = new Hashtable();
043:
044: /**
045: * All objs, members, values etc. are saved in these stack.
046: */
047: protected Stack stack;
048:
049: /**
050: * CH (ContentHandler) is for handling a special part of the XML
051: * in a special ContentHandler. (e.g. HashtableContentHandler)
052: */
053: protected XML2ObjectContentHandler CH = null;
054:
055: /**
056: */
057: protected XML2ObjectDelegate delegate;
058:
059: //
060: // construcor
061: //
062:
063: /**
064: */
065: public XML2ObjectContentHandler() {
066: CH = this ;
067: }
068:
069: /**
070: */
071: public XML2ObjectContentHandler(XML2ObjectDelegate delegate) {
072: this ();
073: this .delegate = delegate;
074: }
075:
076: //
077: // methods
078: //
079:
080: /**
081: * The method setDocumentLocator sets the locator.
082: *
083: * @param locator
084: */
085: public void setDocumentLocator(Locator locator) {
086: this .locator = locator;
087: }
088:
089: /**
090: * ... start Document
091: */
092: public void startDocument() {
093: if (debug) {
094: System.out.println("Start parsing ..");
095: }
096: }
097:
098: /**
099: * ... end Document
100: */
101: public void endDocument() {
102: if (debug) {
103: System.out.println("End parsing ..");
104: }
105: }
106:
107: /**
108: * The method startElement handels all startElements.
109: * It refers to the methods, which process the individual startElement
110: * in detail.
111: *
112: * @param namespaceURI
113: * @param localName
114: * @param rawName (the tagname)
115: * @param atts (the attributes of the tag)
116: */
117: public void startElement(String namespaceURI, String localName,
118: String rawName, Attributes atts) {
119:
120: if (rawName.equals(TAG_OBJ)) {
121: CH.objStartElement(atts);
122: } else if (rawName.equals(TAG_MEMBER)) {
123: CH.memberStartElement(atts);
124: } else if (rawName.equals(TAG_VALUE)) {
125: CH.valueStartElement(atts);
126: } else if (rawName.equals(TAG_VALUEOBJ)) {
127: CH.valueObjStartElement(atts);
128: } else if (rawName.equals(TAG_VALUEARRAY)) {
129: CH.valueArrayStartElement(atts);
130: } else if (rawName.equals(TAG_SUPERCLASS)) {
131: CH.super classStartElement(atts);
132: }
133: }
134:
135: /**
136: * The method endElement handles all endElements.
137: * It refers to the methods, which process the individual endElement
138: * in detail.
139: *
140: * @param namespaceURI
141: * @param localName
142: * @param rawName (the tagname)
143: */
144: public void endElement(String namespaceURI, String localName,
145: String rawName) {
146:
147: if (CH.stack.size() <= 1 && rawName.equals(TAG_VALUEOBJ)) {
148:
149: Hashtable hash = (Hashtable) CH.stack.pop();
150:
151: CH = this ;
152: stack.push(hash);
153: }
154:
155: if (rawName.equals(TAG_OBJ)) {
156: CH.objEndElement();
157: } else if (rawName.equals(TAG_MEMBER)) {
158: CH.memberEndElement();
159: } else if (rawName.equals(TAG_VALUE)) {
160: CH.valueEndElement();
161: } else if (rawName.equals(TAG_VALUEOBJ)) {
162: CH.valueObjEndElement();
163: } else if (rawName.equals(TAG_VALUEARRAY)) {
164: CH.valueArrayEndElement();
165: } else if (rawName.equals(TAG_SUPERCLASS)) {
166: CH.super classEndElement();
167: }
168: }
169:
170: /**
171: * The method characters handles the text-elements.
172: *
173: * @param ch (char-array)
174: * @param start (start of the array)
175: * @param end (end of the array)
176: */
177: public void characters(char[] ch, int start, int end) {
178: CH.values(ch, start, end);
179: }
180:
181: /**
182: */
183: public void processingInstruction(String target, String data) {
184: if (debug) {
185: System.out.println("Target: " + target + " Data: " + data);
186: }
187: }
188:
189: /**
190: */
191: public void startPrefixMapping(String prefix, String uri) {
192: if (debug) {
193: System.out.println("Prefix: " + prefix + " Uri: " + uri);
194: }
195: }
196:
197: /**
198: */
199: public void endPrefixMapping(String prefix) {
200: if (debug) {
201: System.out.println("EndPrefix: " + prefix);
202: }
203: }
204:
205: /**
206: */
207: public void ignorableWhitespace(char[] ch, int start, int end) {
208: if (debug) {
209: String s = new String(ch, start, end);
210: System.out.println("Ignor chars: " + s);
211: }
212: }
213:
214: /**
215: */
216: public void skippedEntity(String name) {
217: if (debug) {
218: System.out.println("Skip entity " + name);
219: }
220: }
221:
222: //
223: // handle elements
224: //
225:
226: /**
227: * The method objStartElement refers to handleObjStartElement.
228: * @param atts (the attributes)
229: */
230: protected void objStartElement(Attributes atts) {
231: handleObjStartElement(atts);
232: }
233:
234: /**
235: * The method memberStartElement refers to handleMemberStartElement.
236: * @param atts (the attributes)
237: */
238: protected void memberStartElement(Attributes atts) {
239: handleMemberStartElement(atts);
240: }
241:
242: /**
243: * The method valueStartElement refers to handleValueStartElement.
244: * @param atts (the attributes)
245: */
246: protected void valueStartElement(Attributes atts) {
247: handleValueStartElement(atts);
248: }
249:
250: /**
251: * The method valueObjStartElement refers to handleValueObjStartElement.
252: * @param atts (the attributes)
253: */
254: protected void valueObjStartElement(Attributes atts) {
255: handleValueObjStartElement(atts);
256: }
257:
258: /**
259: * The method valueArrayStartElement refers to handleValueArrayStartElement.
260: * @param atts (the attributes)
261: */
262: protected void valueArrayStartElement(Attributes atts) {
263: handleValueArrayStartElement(atts);
264: }
265:
266: /**
267: * The method superclassStartElement refers to handleSuperclassStartElement.
268: * @param atts (the attributes)
269: */
270: protected void super classStartElement(Attributes atts) {
271: handleSuperclassStartElement(atts);
272: }
273:
274: /**
275: * The method values refers to handleValues.
276: *
277: * @param ch (char-array)
278: * @param start (start of the array)
279: * @param end (end of the array)
280: */
281: protected void values(char[] ch, int start, int end) {
282: handleValues(ch, start, end);
283: }
284:
285: /**
286: * The method objEndElement refers to handleObjEndElement.
287: */
288: protected void objEndElement() {
289: handleObjEndElement();
290: }
291:
292: /**
293: * The method memberEndElement refers to handleMemberEndElement.
294: */
295: protected void memberEndElement() {
296: handleMemberEndElement();
297: }
298:
299: /**
300: * The method valueEndElement refers to handleValueEndElement.
301: */
302: protected void valueEndElement() {
303: handleValueEndElement();
304: }
305:
306: /**
307: * The method valueObjEndElement refers to handleValueObjEndElement.
308: */
309: protected void valueObjEndElement() {
310: handleValueObjEndElement();
311: }
312:
313: /**
314: * The method valueArrayEndElement refers to handleValueArrayEndElement.
315: */
316: protected void valueArrayEndElement() {
317: handleValueArrayEndElement();
318: }
319:
320: /**
321: * The method superclassEndElement refers to handleSuperclassEndElement.
322: */
323: protected void super classEndElement() {
324: handleSuperclassEndElement();
325: }
326:
327: /**
328: * The method handleObjStartElement creates a new object
329: * and put it in the stack.
330: *
331: * @param atts (the attributes)
332: */
333: protected void handleObjStartElement(Attributes atts) {
334: ObjElement oe;
335:
336: try {
337:
338: stack = new Stack();
339: oe = new ObjElement(atts);
340:
341: stack.push(oe);
342: objCache.put(oe.getId(), oe.getObject());
343:
344: } catch (ClassNotFoundException cnfe) {
345: System.err.println("handleObjStartElement: " + cnfe);
346: } catch (InstantiationException ie) {
347: System.err.println("handleObjStartElement: " + ie);
348: } catch (IllegalAccessException iae) {
349: System.err.println("handleObjStartElement: " + iae);
350: }
351: }
352:
353: /**
354: * The method handleObjEndElement gets the finished Object from the stack.
355: */
356: protected void handleObjEndElement() {
357: ObjElement oe = (ObjElement) stack.pop();
358: delegate.handleObject(oe);
359: }
360:
361: /**
362: * This methode handles an OzoneProxy member.
363: *
364: * @param memberName (name of the member)
365: * @param proxy (the OzoneProxy object)
366: */
367: protected void handleOzoneProxyMember(Attributes atts) {
368: String proxyType = atts.getValue(ATTR_PROXY_TYPE);
369: String href = atts.getValue(ATTR_XLINK_HREF_RAW);
370:
371: ObjectID objID = new ObjectID((new Long(href)).longValue());
372:
373: try {
374:
375: Class proxyClass = Thread.currentThread()
376: .getContextClassLoader().loadClass(proxyType);
377: OzoneProxy proxy = (OzoneProxy) proxyClass.newInstance();
378:
379: Field remoteID = proxyClass.getField(REMOTE_ID);
380: remoteID.set(proxy, objID);
381:
382: ValueObjElement voe = new ValueObjElement(proxy);
383: stack.push(voe);
384:
385: } catch (ClassNotFoundException cnfe) {
386: System.err.println("handleOzoneProxyMember: " + cnfe);
387: } catch (InstantiationException ie) {
388: System.err.println("handleOzoneProxyMember: " + ie);
389: } catch (IllegalAccessException iae) {
390: System.err.println("handleOzoneProxyMember: " + iae);
391: } catch (NoSuchFieldException nsfe) {
392: System.err.println("handleOzoneProxyMember: " + nsfe);
393: }
394: }
395:
396: /**
397: * The method handleMemberStartElement creates a MemberElement
398: * and put it the stack.
399: *
400: * @param atts (the attributes)
401: */
402: protected void handleMemberStartElement(Attributes atts) {
403: MemberElement me = new MemberElement(atts);
404: stack.push(me);
405:
406: if (atts.getValue(ATTR_PROXY_TYPE) != null) //member is an OzoneProxy
407: handleOzoneProxyMember(atts);
408: }
409:
410: /**
411: * The method handleMemberEndElement gets the finished MemberElement and the value
412: * from the stack and put it in the object.
413: */
414: protected void handleMemberEndElement() {
415: Object value = null;
416:
417: if (stack.peek() instanceof ValueObjElement)
418: value = ((ValueObjElement) stack.pop()).getObject();
419: else if (stack.peek() instanceof MemberElement)
420: value = null;
421: else
422: value = stack.pop();
423:
424: if (stack.peek() instanceof MemberElement) {
425:
426: MemberElement me = (MemberElement) stack.pop();
427:
428: Object obj = stack.peek();
429: Class objClass = obj.getClass();
430:
431: if (stack.peek() instanceof ObjElement) {
432: obj = ((ObjElement) stack.peek()).getObject();
433: objClass = obj.getClass();
434: } else if (stack.peek() instanceof ValueObjElement) {
435: obj = ((ValueObjElement) stack.peek()).getObject();
436: objClass = obj.getClass();
437: } else if (stack.peek() instanceof SuperclassElement) {
438: obj = ((SuperclassElement) stack.peek()).getObject();
439: objClass = ((SuperclassElement) stack.peek())
440: .getSuperclass();
441: }
442:
443: try {
444:
445: Field fd = objClass.getDeclaredField(me.getName());
446: fd.setAccessible(true);
447:
448: fd.set(obj, value);
449:
450: } catch (NoSuchFieldException nsfe) { // wrong Class
451: System.err.println("handleMemberEndElement: " + nsfe);
452: } catch (IllegalAccessException iae) { //no access for this member
453: System.err.println("handleMemberEndElement: " + iae);
454: }
455: }
456: }
457:
458: /**
459: * The method handleValueStartElement creates a ValueElement
460: * and put it the stack.
461: *
462: * @param atts (the attributes)
463: */
464: protected void handleValueStartElement(Attributes atts) {
465: String ref = atts.getValue(ATTR_REF);
466: if (ref != null) {
467: Object refObj = objCache.get(ref);
468: stack.push(new RefElement(refObj));
469: return;
470: }
471:
472: ValueElement ve = new ValueElement(atts);
473:
474: stack.push(ve);
475: }
476:
477: /**
478: * The method handleValues gets the ValueElement from the stack.
479: * All values in the ValueElement are saved as String.
480: *
481: * @param ch (char-array)
482: * @param start (start of the array)
483: * @param end (end of the array)
484: */
485: public void handleValues(char[] ch, int start, int end) {
486: if (stack == null || stack.empty())
487: return;
488:
489: if ((stack.peek() instanceof ValueElement)) {
490: String value = new String(ch, start, end);
491: ValueElement ve = (ValueElement) stack.pop();
492:
493: if (ve.getStrValue() != null) // if ValueElement.value has already a value,
494: value = ve.getStrValue() + value; // then append (new)value to (old)value
495:
496: ve.setStrValue(value);
497:
498: stack.push(ve);
499: }
500: }
501:
502: /**
503: * The method handleValueEndElement gets the ValueElement from the stack.
504: * It casts the value (as String) in the special type and put the real
505: * value in the stack back.
506: */
507: protected void handleValueEndElement() {
508: Object value;
509:
510: if (stack.peek() instanceof RefElement) {
511: value = ((RefElement) (stack.pop())).getRefObj();
512:
513: } else {
514: ValueElement ve = (ValueElement) stack.pop();
515:
516: if (ve.getStrValue() == null)
517: value = null;
518: else {
519: value = castValue(ve.getType(), ve.getStrValue());
520: objCache.put(ve.getId(), value);
521: }
522: }
523:
524: stack.push(value);
525: }
526:
527: /**
528: * The method castValues casts the valueString into the real type.
529: *
530: * @param type (the type)
531: * @param valueString (start of the array)
532: */
533: protected Object castValue(String type, String valueStr) {
534:
535: if ((type.equals("java.lang.Boolean"))
536: || (type.equals("boolean"))) {
537: Boolean value = new Boolean(valueStr);
538: return value;
539: }
540:
541: if ((type.equals("java.lang.Byte")) || (type.equals("byte"))) {
542: Byte value = new Byte(valueStr);
543: return value;
544: }
545:
546: if ((type.equals("java.lang.Character"))
547: || (type.equals("char"))) {
548: Character value = new Character(valueStr.charAt(0));
549: return value;
550: }
551:
552: if ((type.equals("java.lang.Short")) || (type.equals("short"))) {
553: Short value = new Short(valueStr);
554: return value;
555: }
556:
557: if ((type.equals("java.lang.Integer")) || (type.equals("int"))) {
558: Integer value = new Integer(valueStr);
559: return value;
560: }
561:
562: if ((type.equals("java.lang.Long")) || (type.equals("long"))) {
563: Long value = new Long(valueStr);
564: return value;
565: }
566:
567: if ((type.equals("java.lang.Float")) || (type.equals("float"))) {
568: Float value = new Float(valueStr);
569: return value;
570: }
571:
572: if ((type.equals("java.lang.Double"))
573: || (type.equals("double"))) {
574: Double value = new Double(valueStr);
575: return value;
576: }
577:
578: if (type.equals("java.lang.String")) {
579: String value = new String(valueStr);
580: return value;
581: }
582:
583: return null;
584: }
585:
586: /**
587: * The method handleValueObjStartElement creates a ValueObjElement
588: * and put it in the stack.
589: * If the valueObj is from type java.util.Hashtable:
590: * -> new ContentHandler which creates a Hashtable
591: * (It is because of can not creating innerClasses!!)
592: *
593: * @param atts (the attributes)
594: */
595: protected void handleValueObjStartElement(Attributes atts) {
596: String ref = atts.getValue("ref");
597: if (ref != null) {
598: Object refObj = objCache.get(ref);
599: stack.push(refObj);
600: return;
601: }
602:
603: try {
604:
605: ValueObjElement voe = new ValueObjElement(atts);
606:
607: if (voe.getType().equals("java.util.Hashtable")) {
608: System.out.println("new HashContentHandler");
609: CH = new HashtableContentHandler(locator,
610: (Hashtable) voe.getObject());
611: } else {
612: stack.push(voe);
613: objCache.put(voe.getId(), voe.getObject());
614: }
615:
616: } catch (ClassNotFoundException cnfe) {
617: System.err.println("handleValueObjStartElement: " + cnfe);
618: } catch (InstantiationException ie) {
619: System.err.println("handleValueObjStartElement: " + ie);
620: } catch (IllegalAccessException iae) {
621: System.err.println("handleValueObjStartElement: " + iae);
622: }
623: }
624:
625: /**
626: */
627: protected void handleValueObjEndElement() {
628: }
629:
630: /**
631: * The method handleValueArrayStartElement creates a ValueArrayElement
632: * and put it in the stack.
633: *
634: * @param atts (the attributes)
635: */
636: protected void handleValueArrayStartElement(Attributes atts) {
637: String ref = atts.getValue("ref");
638: if (ref != null) {
639: Object refObj = objCache.get(ref);
640: stack.push(new RefElement(refObj));
641: return;
642: }
643:
644: ValueArrayElement vae = new ValueArrayElement(atts);
645: stack.push(vae);
646: }
647:
648: /**
649: * The method handleValueArrayEndElement joins the values to an array.
650: */
651: protected void handleValueArrayEndElement() {
652: Object array;
653: if (stack.peek() instanceof RefElement) {
654: array = ((RefElement) (stack.pop())).getRefObj();
655: stack.push(array);
656: return;
657: }
658:
659: try {
660: Vector vaValues = new Vector();
661: while (!(stack.peek() instanceof ValueArrayElement)) {
662: vaValues.addElement(stack.pop());
663: }
664:
665: ValueArrayElement vae = (ValueArrayElement) stack.pop();
666: Class vaClass = Class.forName(vae.getType())
667: .getComponentType();
668: array = Array.newInstance(vaClass, vaValues.size());
669:
670: int k = vaValues.size() - 1; // k-- otherwise -> wrong sequence
671: for (int j = 0; j < vaValues.size(); j++, k--) {
672: Array.set(array, j, vaValues.elementAt(k));
673: }
674:
675: objCache.put(vae.getId(), array);
676: stack.push(array);
677:
678: } catch (ClassNotFoundException cnfe) {
679: System.err.println("handleValueArrayStartElement: " + cnfe);
680: }
681: }
682:
683: /**
684: * The method handleSuperclassStartElement creates a SuperclassElement
685: * and put into the stack.
686: *
687: * @param atts (the attributes)
688: */
689: protected void handleSuperclassStartElement(Attributes atts) {
690: try {
691: Object obj = stack.peek();
692:
693: if (stack.peek() instanceof ObjElement) {
694: obj = ((ObjElement) stack.peek()).getObject();
695: } else if (stack.peek() instanceof ValueObjElement) {
696: obj = ((ValueObjElement) stack.peek()).getObject();
697: } else if (stack.peek() instanceof SuperclassElement) {
698: obj = ((SuperclassElement) stack.peek()).getObject();
699: }
700:
701: SuperclassElement sce = new SuperclassElement(obj, atts);
702: stack.push(sce);
703: } catch (ClassNotFoundException cnfe) {
704: System.err.println("handleSuperclassStartElement: " + cnfe);
705: }
706: }
707:
708: /**
709: * The method handleSuperclassEndElement pop the superclass in the stack.
710: */
711: protected void handleSuperclassEndElement() {
712: stack.pop();
713: }
714:
715: // ------------ TEST -------------
716: // -- System.out.println(STACK) --
717: // -------------------------------
718: protected void showStack(Stack s) {
719: try {
720: System.out
721: .println("------------------------------ (start)");
722: for (int i = s.size() - 1; i >= 0; i--) {
723: System.out.print(" " + i + ". " + s.elementAt(i));
724: System.out.println();
725: }
726: System.out.println("------------------------------ (end)");
727: } catch (Exception e) {
728: System.err.println("showStack: " + e);
729: }
730: }
731:
732: }
|