1
2
3
4 package org.xanot;
5
6 import org.apache.log4j.Logger;
7
8 import org.xanot.structure.AttributeSetRule;
9 import org.xanot.structure.CloseCollectionInstanceRule;
10 import org.xanot.structure.CloseInstanceRule;
11 import org.xanot.structure.CreateInstanceRule;
12 import org.xanot.structure.ParentReferenceRule;
13 import org.xanot.structure.PropertyCollectionSetRule;
14 import org.xanot.structure.PropertySetRule;
15
16 import org.xanot.util.StackMap;
17 import org.xanot.util.UniquePairs;
18
19 import org.xml.sax.Attributes;
20 import org.xml.sax.SAXException;
21 import org.xml.sax.SAXParseException;
22 import org.xml.sax.helpers.DefaultHandler;
23
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26
27 import java.math.BigInteger;
28
29 import java.text.ParseException;
30 import java.text.SimpleDateFormat;
31
32 import java.util.ArrayList;
33 import java.util.Date;
34 import java.util.StringTokenizer;
35 import java.util.Collection;
36
37 /***
38 * SAX xml handler. This is the actual engine that maps xml data into the model
39 * based on rules profided by rule builder.
40 *
41 * @author Ferdinand Neman (newm4n _at_ gmail.com)
42 */
43 public class XanotSAXHandler extends DefaultHandler {
44 Logger log = Logger.getLogger(XanotSAXHandler.class);
45
46 private RuleBuilder ruleBuilder = null;
47
48 private StackMap<String, Object> stack = null;
49
50 private Object rootObject = null;
51
52 private String characterData = "";
53
54 private Collection<SAXParseException> warnings = new ArrayList<SAXParseException>();
55
56 private Collection<SAXParseException> errors = new ArrayList<SAXParseException>();
57
58 private Collection<SAXParseException> fatals = new ArrayList<SAXParseException>();
59
60 private boolean stopOnWarning = true;
61
62 private boolean stopOnError = true;
63
64 private boolean stopOnFatal = true;
65
66 /***
67 * Creates a new XanotSAXHandler object.
68 *
69 * @param ruleBuilder
70 * Rule builder that provides maping rule.
71 */
72 public XanotSAXHandler(RuleBuilder ruleBuilder) {
73 setRuleBuilder(ruleBuilder);
74 }
75
76 /***
77 * Get the instance of root object. Call this method after the parsing
78 * process have fully finished.
79 *
80 * @return Returns the rootObject.
81 */
82 public Object getRootObject() {
83 return rootObject;
84 }
85
86 /***
87 * Get the rule builder that providing rules.
88 *
89 * @return Returns the ruleBuilder.
90 */
91 public RuleBuilder getRuleBuilder() {
92 return ruleBuilder;
93 }
94
95 /***
96 * Set the rule builder that providing rules.
97 *
98 * @param ruleBuilder
99 * The ruleBuilder to set.
100 */
101 public void setRuleBuilder(RuleBuilder ruleBuilder) {
102 if (ruleBuilder == null) {
103 throw new NullPointerException();
104 }
105
106 this.ruleBuilder = ruleBuilder;
107 }
108
109 /***
110 * Triggered by SAX parser when encountered character data in the xml.
111 *
112 * @param ch
113 * Character data
114 * @param start
115 * Start offset in the array
116 * @param length
117 * Length of data starting from the offset.
118 * @throws SAXException
119 * Thrown if anything goes wrong on the parsing.
120 */
121 @Override
122 public void characters(char[] ch, int start, int length)
123 throws SAXException {
124 String data = new String(ch, start, length).trim();
125
126 if (data.length() > 0) {
127 characterData = data;
128 log.debug("Character : \"" + characterData + "\"");
129 }
130 }
131
132 /***
133 * Triggered by SAX parser when the xml document ends.
134 *
135 * @throws SAXException
136 * Thrown if anything goes wrong on the parsing.
137 */
138 @Override
139 public void endDocument() throws SAXException {
140 stack = null;
141 }
142
143 /***
144 * Triggered by SAX parser when an end tag is encounter.
145 *
146 * @param uri
147 * URI element
148 * @param localName
149 * Local name
150 * @param qName
151 * Tag name
152 * @throws SAXException
153 * Thrown if anything goes wrong on the parsing.
154 */
155 @Override
156 public void endElement(String uri, String localName, String qName)
157 throws SAXException {
158 String path = stack.getStringKeyPath() + "/" + qName;
159 String[] paths = getPosiblePathAlternatives(path);
160
161 log.debug("Closing tag </" + qName + ">");
162 log.debug("------------------------------");
163 log.debug("Current stack path " + stack.getStringKeyPath());
164
165 PropertySetRule[] propertyRules = ruleBuilder.getPropertySetRule(paths);
166 log.debug("PropertySetRule effected : " + propertyRules.length);
167
168 PropertyCollectionSetRule[] propertyCollectionSetRule = ruleBuilder
169 .getPropertyCollectionSetRule(paths);
170 log.debug("PropertyCollectionSetRule effected : "
171 + propertyCollectionSetRule.length);
172
173 boolean propertyWins = false;
174
175 if ((propertyRules.length > 0)
176 || (propertyCollectionSetRule.length > 0)) {
177 propertyWins = true;
178 }
179
180 CloseInstanceRule[] closeInstanceRule = ruleBuilder
181 .getCloseInstanceRule(getPosiblePathAlternatives(stack
182 .getStringKeyPath()));
183 log.debug("CloseInstanceRules effected : " + closeInstanceRule.length);
184
185 CloseCollectionInstanceRule[] closePropColRule = ruleBuilder
186 .getCloseCollectionInstanceRule(getPosiblePathAlternatives(stack
187 .getStringKeyPath()));
188 log.debug("CloseCollectionInstanceRule effected : "
189 + closePropColRule.length);
190
191 if (propertyWins) {
192 log
193 .debug("Only PropertySetRule or PropertyCollectionSetRule is executed");
194 }
195
196 if ((closeInstanceRule.length > 0) && !propertyWins) {
197 Object parentObj = stack.peekParentValue();
198 Class parentClass = parentObj.getClass();
199
200 for (CloseInstanceRule closeRule : closeInstanceRule) {
201 log.debug("MATCH CloseInstanceRule. " + closeRule.getPath());
202
203 Method setter = getSetterMethod(parentClass, closeRule
204 .getPropertyName());
205
206 if (setter == null) {
207 log.error("Not found setter method for property "
208 + closeRule.getPropertyName() + " on class "
209 + parentClass.getName());
210 } else {
211 try {
212 log.debug("Setter Method " + setter.getName()
213 + " on class " + parentClass.getName()
214 + " is invoked with parameter "
215 + stack.getValue(stack.size() - 1).getClass());
216 setter.invoke(parentObj, new Object[] { stack
217 .getValue(stack.size() - 1) });
218 } catch (IllegalArgumentException e) {
219 log.error("Setter Method "
220 + setter.getName()
221 + " on class "
222 + parentClass.getName()
223 + " is not accepting argument of type "
224 + stack.getValue(stack.size() - 1).getClass()
225 .getName(), e);
226 } catch (IllegalAccessException e) {
227 log.error("Setter Method " + setter.getName()
228 + " on class " + parentClass.getName()
229 + " is not accessible.", e);
230 } catch (InvocationTargetException e) {
231 log.error("Setter Method " + setter.getName()
232 + " on class " + parentClass.getName()
233 + " is not invocable on instance.", e);
234 }
235 }
236 }
237
238 Object o = stack.pop();
239 log.debug("POP " + o.getClass().getName() + ". Stack : "
240 + stack.size());
241 } else if ((closePropColRule.length > 0) && !propertyWins) {
242 Object topObject = stack.getValue(stack.size() - 1);
243 Class topClass = topObject.getClass();
244 Object parentObj = stack.peekParentValue();
245 Class parentClass = parentObj.getClass();
246 UniquePairs pairs = new UniquePairs();
247
248 for (CloseCollectionInstanceRule ccir : closePropColRule) {
249 log.debug("MATCH PropertyCollectionSetRule. " + ccir.getPath());
250
251 Method setterMethod = null;
252
253 for (Method met : parentClass.getMethods()) {
254 if (met.getName().equals(ccir.getMethodName())) {
255 setterMethod = met;
256
257 break;
258 }
259 }
260
261 if (setterMethod != null) {
262 if (!pairs.isPairExist(setterMethod, topObject)) {
263 pairs.addPair(setterMethod, topObject);
264
265 Class[] paramTypes = setterMethod.getParameterTypes();
266
267 if (paramTypes.length == 1) {
268 Class paramType = paramTypes[0];
269
270 if (paramType.equals(topClass)) {
271 try {
272 log.debug("Setter Method "
273 + setterMethod.getName()
274 + " on class "
275 + parentClass.getName()
276 + " is invoked with parameter "
277 + topClass.getName());
278
279 if (topObject == null) {
280 log.fatal("Null top object");
281 System.exit(-1);
282 }
283
284 if (parentObj == null) {
285 log.fatal("Null parent object");
286 System.exit(-1);
287 }
288
289 setterMethod.invoke(parentObj, topObject);
290 } catch (IllegalArgumentException e) {
291 log
292 .error(
293 "Setter Method "
294 + setterMethod
295 .getName()
296 + " on class "
297 + parentClass
298 .getName()
299 + " is not accepting argument of type "
300 + topClass
301 .getName(),
302 e);
303 } catch (IllegalAccessException e) {
304 log.error("Setter Method "
305 + setterMethod.getName()
306 + " on class "
307 + parentClass.getName()
308 + " is not accessible.", e);
309 } catch (InvocationTargetException e) {
310 log.error("Setter Method "
311 + setterMethod.getName()
312 + " on class "
313 + parentClass.getName()
314 + " is not invocable on instance.",
315 e);
316 }
317 } else {
318 log
319 .error("Method "
320 + ccir.getMethodName()
321 + " in class "
322 + topClass.getName()
323 + " is not accepting parameter of type "
324 + topClass.getName());
325 }
326 } else {
327 log
328 .error("Method "
329 + ccir.getMethodName()
330 + " in class "
331 + topClass.getName()
332 + " requires more than 1 parameters or no parameter at all.");
333 }
334 } else {
335 log.debug("Avoiding Multicall Bug");
336 }
337 } else {
338 log.error("Cannot find method " + ccir.getMethodName()
339 + " in class " + topClass.getName());
340 }
341 }
342
343 Object o = stack.pop();
344 log.debug("POP " + o.getClass().getName() + ". Stack : "
345 + stack.size());
346 } else if ((propertyRules.length > 0) && propertyWins) {
347 Object topObject = stack.getValue(stack.size() - 1);
348 Class topClass = topObject.getClass();
349
350 for (PropertySetRule propRule : propertyRules) {
351 log.debug("MATCH PropertySetRule. " + propRule.getPath());
352
353 Method getMet = getGetterMethod(topClass, propRule
354 .getPropertyName());
355 Method setMet = getSetterMethod(topClass, propRule
356 .getPropertyName());
357
358 if (getMet != null) {
359 Class retType = getMet.getReturnType();
360 Object param = null;
361
362 try {
363 if (retType.getName().equals("boolean")
364 || retType.equals(Boolean.class)) {
365 param = new Boolean(characterData);
366 } else if (retType.getName().equals("char")
367 || retType.equals(Character.class)) {
368 param = new Character(characterData.charAt(0));
369 } else if (retType.getName().equals("byte")
370 || retType.equals(Byte.class)) {
371 param = new Byte(characterData);
372 } else if (retType.getName().equals("short")
373 || retType.equals(Short.class)) {
374 param = new Short(characterData);
375 } else if (retType.getName().equals("int")
376 || retType.equals(Integer.class)) {
377 param = new Integer(characterData);
378 } else if (retType.getName().equals("long")
379 || retType.equals(Long.class)) {
380 param = new Long(characterData);
381 } else if (retType.getName().equals("float")
382 || retType.equals(Float.class)) {
383 param = new Float(characterData);
384 } else if (retType.getName().equals("double")
385 || retType.equals(Double.class)) {
386 param = new Double(characterData);
387 } else if (retType.equals(String.class)) {
388 param = characterData;
389 } else if (retType.equals(Date.class)) {
390 SimpleDateFormat sdf = new SimpleDateFormat(
391 propRule.getDateFormat());
392 param = sdf.parse(characterData);
393 } else if (retType.equals(BigInteger.class)) {
394 param = new BigInteger(characterData);
395 } else {
396 log
397 .error("Xanot is too dumb tobe able to initialize class "
398 + retType.getName()
399 + " with string data. Path : "
400 + path);
401 }
402
403 if (param != null) {
404 if (setMet != null) {
405 try {
406 log.debug("Setter Method "
407 + setMet.getName() + " on class "
408 + topClass.getName()
409 + " is invoked with parameter "
410 + param.toString());
411 setMet.invoke(topObject,
412 new Object[] { param });
413 } catch (IllegalArgumentException e) {
414 log
415 .error(
416 "Setter Method "
417 + setMet.getName()
418 + " on class "
419 + topClass
420 .getName()
421 + " is not accepting argument of type "
422 + stack
423 .getValue(
424 stack
425 .size() - 1)
426 .getClass()
427 .getName(),
428 e);
429 } catch (IllegalAccessException e) {
430 log.error("Setter Method "
431 + setMet.getName() + " on class "
432 + topClass.getName()
433 + " is not accessible.", e);
434 } catch (InvocationTargetException e) {
435 log.error("Setter Method "
436 + setMet.getName() + " on class "
437 + topClass.getName()
438 + " is not invocable on instance.",
439 e);
440 }
441 } else {
442 log.error("Setter method for property "
443 + propRule.getPropertyName()
444 + " is not exist in class "
445 + topClass.getName());
446 }
447 }
448 } catch (ParseException pe) {
449 log
450 .error("Xanot is too dumb tobe able to parse data \""
451 + characterData
452 + "\" to date format '"
453 + propRule.getDateFormat()
454 + "'. Path : " + path);
455 } catch (NumberFormatException nfe) {
456 log
457 .error("Xanot is too dumb tobe able to parse data \""
458 + characterData
459 + "\" to numerical value. Path : "
460 + path);
461 }
462 } else {
463 log.error("Getter Method " + getMet.getName()
464 + " on class " + topClass.getName()
465 + " is not exist.");
466 }
467 }
468 } else if ((propertyCollectionSetRule.length > 0) && propertyWins) {
469 Object topObject = stack.getValue(stack.size() - 1);
470 Class topClass = topObject.getClass();
471
472 for (PropertyCollectionSetRule colRule : propertyCollectionSetRule) {
473 log.debug("MATCH PropertyCollectionSetRule. "
474 + colRule.getPath());
475
476 Method setterMethod = null;
477
478 for (Method met : topClass.getMethods()) {
479 if (met.getName().equals(colRule.getMethodName())) {
480 setterMethod = met;
481
482 break;
483 }
484 }
485
486 if (setterMethod != null) {
487 Class[] paramTypes = setterMethod.getParameterTypes();
488
489 if (paramTypes.length == 1) {
490 Class paramType = paramTypes[0];
491 Object param = null;
492
493 try {
494 if (paramType.getName().equals("boolean")
495 || paramType.equals(Boolean.class)) {
496 param = new Boolean(characterData);
497 } else if (paramType.getName().equals("char")
498 || paramType.equals(Character.class)) {
499 param = new Character(characterData.charAt(0));
500 } else if (paramType.getName().equals("byte")
501 || paramType.equals(Byte.class)) {
502 param = new Byte(characterData);
503 } else if (paramType.getName().equals("short")
504 || paramType.equals(Short.class)) {
505 param = new Short(characterData);
506 } else if (paramType.getName().equals("int")
507 || paramType.equals(Integer.class)) {
508 param = new Integer(characterData);
509 } else if (paramType.getName().equals("long")
510 || paramType.equals(Long.class)) {
511 param = new Long(characterData);
512 } else if (paramType.getName().equals("float")
513 || paramType.equals(Float.class)) {
514 param = new Float(characterData);
515 } else if (paramType.getName().equals("double")
516 || paramType.equals(Double.class)) {
517 param = new Double(characterData);
518 } else if (paramType.equals(String.class)) {
519 param = characterData;
520 } else if (paramType.equals(Date.class)) {
521 SimpleDateFormat sdf = new SimpleDateFormat(
522 colRule.getDateFormat());
523 param = sdf.parse(characterData);
524 } else if (paramType.equals(BigInteger.class)) {
525 param = new BigInteger(characterData);
526 } else {
527 log
528 .error("Xanot is too dumb tobe able to initialize class "
529 + paramType.getName()
530 + " with string data. Path : "
531 + path);
532 }
533
534 if (param != null) {
535 try {
536 log.debug("Setter Method "
537 + setterMethod.getName()
538 + " on class " + topClass.getName()
539 + " is invoked with parameter "
540 + param.toString());
541 setterMethod.invoke(topObject,
542 new Object[] { param });
543 } catch (IllegalArgumentException e) {
544 log
545 .error(
546 "Setter Method "
547 + setterMethod
548 .getName()
549 + " on class "
550 + topClass
551 .getName()
552 + " is not accepting argument of type "
553 + stack
554 .getValue(
555 stack
556 .size() - 1)
557 .getClass()
558 .getName(),
559 e);
560 } catch (IllegalAccessException e) {
561 log.error("Setter Method "
562 + setterMethod.getName()
563 + " on class " + topClass.getName()
564 + " is not accessible.", e);
565 } catch (InvocationTargetException e) {
566 log.error("Setter Method "
567 + setterMethod.getName()
568 + " on class " + topClass.getName()
569 + " is not invocable on instance.",
570 e);
571 }
572 }
573 } catch (ParseException pe) {
574 log
575 .error("Xanot is too dumb tobe able to parse data \""
576 + characterData
577 + "\" to date format '"
578 + colRule.getDateFormat()
579 + "'. Path : " + path);
580 } catch (NumberFormatException nfe) {
581 log
582 .error("Xanot is too dumb tobe able to parse data \""
583 + characterData
584 + "\" to numerical value. Path : "
585 + path);
586 }
587 } else {
588 log
589 .error("Method "
590 + colRule.getMethodName()
591 + " in class "
592 + topClass.getName()
593 + " requires more than 1 parameters or no parameter at all.");
594 }
595 } else {
596 log.error("Cannot find method " + colRule.getMethodName()
597 + " in class " + topClass.getName());
598 }
599 }
600 } else {
601 if (stack.size() > 1) {
602 log.warn("</" + qName + "> is not handled.");
603 } else {
604 log.debug("XML END");
605 }
606 }
607 }
608
609 /***
610 * Get a setter method from a specific property name on a class.
611 *
612 * @param klass
613 * Class to inspect
614 * @param property
615 * Property name
616 * @return Setter method or null if there's no such setter method for the
617 * specified property
618 */
619 public Method getSetterMethod(Class klass, String property) {
620 for (Method met : klass.getMethods()) {
621 String setSetter = "set"
622 + Character.toUpperCase(property.charAt(0))
623 + property.substring(1);
624
625 if (met.getName().equals(setSetter)) {
626 return met;
627 }
628 }
629
630 return null;
631 }
632
633 /***
634 * Get a getter method from a specific property name on a class.
635 *
636 * @param klass
637 * Class to inspect
638 * @param property
639 * Property name
640 * @return Getter method or null if there's no such getter method for the
641 * specified property
642 */
643 public Method getGetterMethod(Class klass, String property) {
644 for (Method met : klass.getMethods()) {
645 String isGetter = "is" + Character.toUpperCase(property.charAt(0))
646 + property.substring(1);
647 String getGetter = "get"
648 + Character.toUpperCase(property.charAt(0))
649 + property.substring(1);
650
651 if (met.getName().equals(isGetter)
652 || met.getName().equals(getGetter)) {
653 return met;
654 }
655 }
656
657 return null;
658 }
659
660 /***
661 * Triggered by SAX if it encouter an error when parsing.
662 *
663 * @param e
664 * The cause
665 * @throws SAXException
666 * Thrown if anything goes wrong on the parsing.
667 */
668 @Override
669 public void error(SAXParseException e) throws SAXException {
670 errors.add(e);
671 if (isStopOnError()) {
672 throw new SAXException("Parser catches an Error", e);
673 }
674 super.error(e);
675 }
676
677 /***
678 * Triggered by SAX if it encouter a fatal error when parsing.
679 *
680 * @param e
681 * The cause
682 * @throws SAXException
683 * Thrown if anything goes wrong on the parsing.
684 */
685 @Override
686 public void fatalError(SAXParseException e) throws SAXException {
687 fatals.add(e);
688 if (isStopOnFatal()) {
689 throw new SAXException("Parser catches a Fatal Error", e);
690 }
691 super.fatalError(e);
692 }
693
694 /***
695 * Triggered by SAX parser when it start parsing.
696 *
697 * @throws SAXException
698 * Thrown if anything goes wrong on the parsing.
699 */
700 @Override
701 public void startDocument() throws SAXException {
702 errors.clear();
703 fatals.clear();
704 warnings.clear();
705 stack = new StackMap<String, Object>();
706 }
707
708 /***
709 * Triggered by SAX parser when it encounter the starting of xml element.
710 *
711 * @param uri
712 * The URI
713 * @param localName
714 * Local Name
715 * @param qName
716 * Tag name
717 * @param attributes
718 * Collection of attributes.
719 * @throws SAXException
720 * Thrown if anything goes wrong on the parsing.
721 */
722 @Override
723 public void startElement(String uri, String localName, String qName,
724 Attributes attributes) throws SAXException {
725 String path = stack.getStringKeyPath() + "/" + qName;
726 String[] paths = getPosiblePathAlternatives(path);
727
728 CreateInstanceRule[] createInstanceRules = ruleBuilder
729 .getCreateInstanceRule(paths);
730
731 log.debug("\n++++++++++++++++++++++++++++++");
732 log.debug("Start Element : <" + qName + ">");
733 log.debug("Path : " + path);
734
735 characterData = "";
736
737 if (createInstanceRules.length > 0) {
738 log.debug("CreateInstanceRule path : "
739 + createInstanceRules[0].getPath());
740
741
742 CreateInstanceRule cir = createInstanceRules[0];
743
744 if (cir != null) {
745 try {
746 Object instance = cir.createInstance();
747
748
749
750
751 if ((rootObject == null) && (stack.size() == 0)) {
752 rootObject = instance;
753
754
755 }
756
757 stack.push(qName, instance);
758 log.debug("Instantiated " + instance.getClass().getName());
759 log.debug("PUSH " + instance.getClass().getName()
760 + ". Stack : " + stack.size());
761
762
763 if (stack.size() > 1) {
764 ParentReferenceRule[] parentReferenceRules = ruleBuilder
765 .getParentReferenceRule(paths);
766 if (parentReferenceRules.length > 0) {
767 Object parent = stack.peekParentValue();
768 for (ParentReferenceRule ppr : parentReferenceRules) {
769 Method getMet = getGetterMethod(instance
770 .getClass(), ppr.getAttributeName());
771 Method setMet = getSetterMethod(instance
772 .getClass(), ppr.getAttributeName());
773 if (getMet.getReturnType().isAssignableFrom(
774 parent.getClass())) {
775 try {
776 setMet.invoke(instance,
777 new Object[] { parent });
778 } catch (Exception e) {
779 log
780 .error(
781 "Canot set parent reference on "
782 + instance
783 .getClass()
784 .getName()
785 + "."
786 + setMet
787 .getName()
788 + " with parameter of type "
789 + parent
790 .getClass()
791 .getName()
792 + ". ParentReference not set.",
793 e);
794 }
795 } else {
796 log
797 .error("Unable to create parent reference for ");
798 }
799 }
800 }
801 }
802
803
804 for (int i = 0; i < attributes.getLength(); i++) {
805 String attrName = attributes.getQName(i);
806 String attrValue = attributes.getValue(i);
807
808 log.debug("Initializing attributes. Tag : " + attrName);
809
810 AttributeSetRule[] attrRules = ruleBuilder
811 .getAttributeSetRule(paths);
812
813 for (AttributeSetRule asr : attrRules) {
814 if (asr.getXmlAttributeName().equals(attrName)) {
815 String prop = asr.getPropertyName();
816 Method setter = null;
817 setter = getSetterMethod(cir.getBaseClass(),
818 prop);
819
820 if (setter != null) {
821 Class[] paramTypes = setter
822 .getParameterTypes();
823
824 if (paramTypes.length == 1) {
825 Class paramType = paramTypes[0];
826 Object param = null;
827
828 try {
829 if (paramType.getName().equals(
830 "boolean")
831 || paramType
832 .equals(Boolean.class)) {
833 param = new Boolean(attrValue);
834 } else if (paramType.getName()
835 .equals("char")
836 || paramType
837 .equals(Character.class)) {
838 param = new Character(attrValue
839 .charAt(0));
840 } else if (paramType.getName()
841 .equals("byte")
842 || paramType
843 .equals(Byte.class)) {
844 param = new Byte(attrValue);
845 } else if (paramType.getName()
846 .equals("short")
847 || paramType
848 .equals(Short.class)) {
849 param = new Short(attrValue);
850 } else if (paramType.getName()
851 .equals("int")
852 || paramType
853 .equals(Integer.class)) {
854 param = new Integer(attrValue);
855 } else if (paramType.getName()
856 .equals("long")
857 || paramType
858 .equals(Long.class)) {
859 param = new Long(attrValue);
860 } else if (paramType.getName()
861 .equals("float")
862 || paramType
863 .equals(Float.class)) {
864 param = new Float(attrValue);
865 } else if (paramType.getName()
866 .equals("double")
867 || paramType
868 .equals(Double.class)) {
869 param = new Double(attrValue);
870 } else if (paramType
871 .equals(String.class)) {
872 param = attrValue;
873 } else if (paramType
874 .equals(Date.class)) {
875 SimpleDateFormat sdf = new SimpleDateFormat(
876 asr.getDateFormat());
877 param = sdf.parse(attrValue);
878 } else if (paramType
879 .equals(BigInteger.class)) {
880 param = new BigInteger(
881 attrValue);
882 } else {
883 log
884 .error("Xanot is too dumb tobe able to initialize class "
885 + paramType
886 .getName()
887 + " with string data. Path : "
888 + path);
889 }
890
891 if (param != null) {
892 try {
893 log
894 .debug("Setter Method "
895 + setter
896 .getName()
897 + " on class "
898 + cir
899 .getBaseClass()
900 .getName()
901 + " is invoked with parameter "
902 + param
903 .toString());
904 setter
905 .invoke(
906 instance,
907 new Object[] { param });
908 } catch (IllegalArgumentException e) {
909 log
910 .error(
911 "Setter Method "
912 + setter
913 .getName()
914 + " on class "
915 + cir
916 .getBaseClass()
917 .getName()
918 + " is not accepting argument of type "
919 + stack
920 .getValue(
921 stack
922 .size() - 1)
923 .getClass()
924 .getName(),
925 e);
926 } catch (IllegalAccessException e) {
927 log
928 .error(
929 "Setter Method "
930 + setter
931 .getName()
932 + " on class "
933 + cir
934 .getBaseClass()
935 .getName()
936 + " is not accessible.",
937 e);
938 } catch (InvocationTargetException e) {
939 log
940 .error(
941 "Setter Method "
942 + setter
943 .getName()
944 + " on class "
945 + cir
946 .getBaseClass()
947 .getName()
948 + " is not invocable on instance.",
949 e);
950 }
951 }
952 } catch (ParseException pe) {
953 log
954 .error("Xanot is too dumb tobe able to parse data \""
955 + attrValue
956 + "\" to date format '"
957 + asr
958 .getDateFormat()
959 + "'. Path : "
960 + path);
961 } catch (NumberFormatException nfe) {
962 log
963 .error("Xanot is too dumb tobe able to parse data \""
964 + attrValue
965 + "\" to numerical value. Path : "
966 + path);
967 }
968 } else {
969 log
970 .error("Method "
971 + setter.getName()
972 + " in class "
973 + cir.getBaseClass()
974 .getName()
975 + " requires more than 1 parameters or no parameter at all.");
976 }
977 } else {
978 log.error("Setter method for property "
979 + prop + " is not exist in class "
980 + cir.getBaseClass().getName());
981 }
982 }
983 }
984 }
985 } catch (InstantiationException ie) {
986 log
987 .fatal(
988 "Class "
989 + cir.getClass().getName()
990 + " cannot be instantiate. Probably abstract or interface.",
991 ie);
992 System.exit(-1);
993 } catch (IllegalAccessException iae) {
994 log.fatal("Class " + cir.getClass().getName()
995 + " cannot be accessed.", iae);
996 System.exit(-1);
997 }
998 }
999 }
1000
1001
1002
1003
1004 }
1005
1006 /***
1007 * Generate all posible path as alternative to the given path.
1008 *
1009 * @param path
1010 * Path
1011 * @return Alternative paths including the given path.
1012 */
1013 private String[] getPosiblePathAlternatives(String path) {
1014 ArrayList<String> al = new ArrayList<String>();
1015 StringTokenizer stok = new StringTokenizer(path, "/");
1016
1017 while (stok.hasMoreTokens()) {
1018 al.add(stok.nextToken());
1019 }
1020
1021 String[] tokens = al.toArray(new String[al.size()]);
1022
1023 for (int i = 0; i < tokens.length; i++) {
1024 tokens[i] = buildupPath(tokens, i);
1025 }
1026
1027 String[] newToken = new String[tokens.length + 2];
1028 System.arraycopy(tokens, 0, newToken, 1, tokens.length);
1029 newToken[newToken.length - 1] = "..";
1030
1031 newToken[0] = newToken[1];
1032 newToken[1] = ".." + newToken[0];
1033
1034 return newToken;
1035 }
1036
1037 /***
1038 * Buildup complete path out of a string tokens.
1039 *
1040 * @param tokens
1041 * String tokens
1042 * @param count
1043 * Number of tokens
1044 * @return A complete path
1045 */
1046 private String buildupPath(String[] tokens, int count) {
1047 StringBuilder sb = new StringBuilder();
1048
1049 if (count == 0) {
1050 for (int i = 0; i < tokens.length; i++) {
1051 sb.append("/");
1052 sb.append(tokens[i]);
1053 }
1054 } else {
1055 sb.append("..");
1056
1057 for (int i = count; i < tokens.length; i++) {
1058 sb.append("/");
1059 sb.append(tokens[i]);
1060 }
1061 }
1062
1063 return sb.toString();
1064 }
1065
1066 /***
1067 * Triggered by SAX parser when it encounters an Error
1068 *
1069 * @param e
1070 * The cause
1071 * @throws SAXException
1072 * Thrown if anything goes wrong on the parsing.
1073 */
1074 @Override
1075 public void warning(SAXParseException e) throws SAXException {
1076 warnings.add(e);
1077 if (isStopOnWarning()) {
1078 throw new SAXException("Parser catches a warning", e);
1079 }
1080 }
1081
1082 /***
1083 * Get collection of warnings, collected when the parsing is running.
1084 *
1085 * @return Collection warning.
1086 */
1087 public Collection<SAXParseException> getWarnings() {
1088 return warnings;
1089 }
1090
1091 /***
1092 * Set collection of warnings. It is not to be used manually by user since
1093 * the collection will be emptied eachtime the parsing starts.
1094 *
1095 * @param warnings
1096 * Collection warning.
1097 */
1098 public void setWarnings(Collection<SAXParseException> warnings) {
1099 if (warnings == null) {
1100 throw new NullPointerException();
1101 }
1102 this.warnings = warnings;
1103 }
1104
1105 /***
1106 * Get collection of errors, collected when the parsing is running
1107 *
1108 * @return Collection of errors.
1109 */
1110 public Collection<SAXParseException> getErrors() {
1111 return errors;
1112 }
1113
1114 /***
1115 * Set collection of errors. It is not to be used manually by user since the
1116 * collection will be emptied eachtime the parsing starts.
1117 *
1118 * @param errors
1119 * Collection of errors
1120 */
1121 public void setErrors(Collection<SAXParseException> errors) {
1122 if (errors == null) {
1123 throw new NullPointerException();
1124 }
1125 this.errors = errors;
1126 }
1127
1128 /***
1129 * Get collection of fatal errors, collected when the parsing is running
1130 *
1131 * @return Collection of fatal errors.
1132 */
1133 public Collection<SAXParseException> getFatals() {
1134 return fatals;
1135 }
1136
1137 /***
1138 * Set collection of fatal errors. It is not to be used manually by user
1139 * since the collection will be emptied eachtime the parsing starts.
1140 *
1141 * @param fatals
1142 * Collection of fatal errors.
1143 */
1144 public void setFatals(Collection<SAXParseException> fatals) {
1145 if (fatals == null) {
1146 throw new NullPointerException();
1147 }
1148 this.fatals = fatals;
1149 }
1150
1151 /***
1152 * Check wether parsing should halt on any warning.
1153 *
1154 * @return True if halt on warning, false if otherwise.
1155 */
1156 public boolean isStopOnWarning() {
1157 return stopOnWarning;
1158 }
1159
1160 /***
1161 * Set to stp
1162 *
1163 * @param stopOnWarning
1164 */
1165 public void setStopOnWarning(boolean stopOnWarning) {
1166 this.stopOnWarning = stopOnWarning;
1167 }
1168
1169 public boolean isStopOnError() {
1170 return stopOnError;
1171 }
1172
1173 public void setStopOnError(boolean stopOnError) {
1174 this.stopOnError = stopOnError;
1175 }
1176
1177 public boolean isStopOnFatal() {
1178 return stopOnFatal;
1179 }
1180
1181 public void setStopOnFatal(boolean stopOnFatal) {
1182 this.stopOnFatal = stopOnFatal;
1183 }
1184 }