1 42 package org.jfree.xml.parser; 43 44 import java.awt.BasicStroke ; 45 import java.awt.Color ; 46 import java.awt.Font ; 47 import java.awt.GradientPaint ; 48 import java.awt.Insets ; 49 import java.awt.Paint ; 50 import java.awt.RenderingHints ; 51 import java.awt.Stroke ; 52 import java.awt.geom.Point2D ; 53 import java.awt.geom.Rectangle2D ; 54 import java.util.ArrayList ; 55 import java.util.HashMap ; 56 import java.util.LinkedList ; 57 import java.util.List ; 58 import java.util.Stack ; 59 import java.util.Vector ; 60 61 import org.jfree.util.ObjectUtilities; 62 import org.jfree.xml.FrontendDefaultHandler; 63 import org.jfree.xml.ParseException; 64 import org.jfree.xml.ElementDefinitionException; 65 import org.jfree.xml.parser.coretypes.BasicStrokeReadHandler; 66 import org.jfree.xml.parser.coretypes.ColorReadHandler; 67 import org.jfree.xml.parser.coretypes.FontReadHandler; 68 import org.jfree.xml.parser.coretypes.GenericReadHandler; 69 import org.jfree.xml.parser.coretypes.GradientPaintReadHandler; 70 import org.jfree.xml.parser.coretypes.InsetsReadHandler; 71 import org.jfree.xml.parser.coretypes.ListReadHandler; 72 import org.jfree.xml.parser.coretypes.Point2DReadHandler; 73 import org.jfree.xml.parser.coretypes.Rectangle2DReadHandler; 74 import org.jfree.xml.parser.coretypes.RenderingHintsReadHandler; 75 import org.jfree.xml.parser.coretypes.StringReadHandler; 76 import org.jfree.xml.util.ManualMappingDefinition; 77 import org.jfree.xml.util.MultiplexMappingDefinition; 78 import org.jfree.xml.util.MultiplexMappingEntry; 79 import org.jfree.xml.util.ObjectFactory; 80 import org.jfree.xml.util.SimpleObjectFactory; 81 import org.xml.sax.Attributes ; 82 import org.xml.sax.SAXException ; 83 84 87 public abstract class RootXmlReadHandler extends FrontendDefaultHandler { 88 89 90 private Stack currentHandlers; 91 92 93 private Stack outerScopes; 94 95 96 private XmlReadHandler rootHandler; 97 98 99 private HashMap objectRegistry; 100 101 102 private SimpleObjectFactory classToHandlerMapping; 103 104 private boolean rootHandlerInitialized; 105 106 109 public RootXmlReadHandler() { 110 this.objectRegistry = new HashMap (); 111 this.classToHandlerMapping = new SimpleObjectFactory(); 112 } 113 114 protected void addDefaultMappings () { 115 116 final MultiplexMappingEntry[] paintEntries = new MultiplexMappingEntry[2]; 117 paintEntries[0] = new MultiplexMappingEntry("color", Color .class.getName()); 118 paintEntries[1] = new MultiplexMappingEntry("gradientPaint", GradientPaint .class.getName()); 119 addMultiplexMapping(Paint .class, "type", paintEntries); 120 addManualMapping(Color .class, ColorReadHandler.class); 121 addManualMapping(GradientPaint .class, GradientPaintReadHandler.class); 122 123 final MultiplexMappingEntry[] point2DEntries = new MultiplexMappingEntry[2]; 124 point2DEntries[0] = new MultiplexMappingEntry("float", Point2D.Float .class.getName()); 125 point2DEntries[1] = new MultiplexMappingEntry("double", Point2D.Double .class.getName()); 126 addMultiplexMapping(Point2D .class, "type", point2DEntries); 127 addManualMapping(Point2D.Float .class, Point2DReadHandler.class); 128 addManualMapping(Point2D.Double .class, Point2DReadHandler.class); 129 130 final MultiplexMappingEntry[] rectangle2DEntries = new MultiplexMappingEntry[2]; 131 rectangle2DEntries[0] = new MultiplexMappingEntry( 132 "float", Rectangle2D.Float .class.getName() 133 ); 134 rectangle2DEntries[1] = new MultiplexMappingEntry( 135 "double", Rectangle2D.Double .class.getName() 136 ); 137 addMultiplexMapping(Rectangle2D .class, "type", rectangle2DEntries); 138 addManualMapping(Rectangle2D.Float .class, Rectangle2DReadHandler.class); 139 addManualMapping(Rectangle2D.Double .class, Rectangle2DReadHandler.class); 140 141 final MultiplexMappingEntry[] listEntries = new MultiplexMappingEntry[4]; 143 listEntries[0] = new MultiplexMappingEntry("array-list", ArrayList .class.getName()); 144 listEntries[1] = new MultiplexMappingEntry("linked-list", LinkedList .class.getName()); 145 listEntries[2] = new MultiplexMappingEntry("vector", Vector .class.getName()); 146 listEntries[3] = new MultiplexMappingEntry("stack", Stack .class.getName()); 147 addMultiplexMapping(List .class, "type", listEntries); 148 addManualMapping(LinkedList .class, ListReadHandler.class); 149 addManualMapping(Vector .class, ListReadHandler.class); 150 addManualMapping(ArrayList .class, ListReadHandler.class); 151 addManualMapping(Stack .class, ListReadHandler.class); 152 153 final MultiplexMappingEntry[] strokeEntries = new MultiplexMappingEntry[1]; 154 strokeEntries[0] = new MultiplexMappingEntry("basic", BasicStroke .class.getName()); 155 addMultiplexMapping(Stroke .class, "type", strokeEntries); 156 addManualMapping(BasicStroke .class, BasicStrokeReadHandler.class); 157 158 addManualMapping(Font .class, FontReadHandler.class); 159 addManualMapping(Insets .class, InsetsReadHandler.class); 160 addManualMapping(RenderingHints .class, RenderingHintsReadHandler.class); 161 addManualMapping(String .class, StringReadHandler.class); 162 } 163 164 169 public abstract ObjectFactory getFactoryLoader(); 170 171 177 protected void addManualMapping(final Class classToRead, final Class handler) { 178 if (handler == null) { 179 throw new NullPointerException ("handler must not be null."); 180 } 181 if (classToRead == null) { 182 throw new NullPointerException ("classToRead must not be null."); 183 } 184 if (!XmlReadHandler.class.isAssignableFrom(handler)) { 185 throw new IllegalArgumentException ("The given handler is no XmlReadHandler."); 186 } 187 this.classToHandlerMapping.addManualMapping 188 (new ManualMappingDefinition(classToRead, handler.getName(), null)); 189 } 190 191 198 protected void addMultiplexMapping(final Class baseClass, 199 final String typeAttr, 200 final MultiplexMappingEntry[] mdef) { 201 202 this.classToHandlerMapping.addMultiplexMapping( 203 new MultiplexMappingDefinition(baseClass, typeAttr, mdef) 204 ); 205 } 206 207 213 public void setHelperObject(final String key, final Object value) { 214 if (value == null) { 215 this.objectRegistry.remove(key); 216 } 217 else { 218 this.objectRegistry.put(key, value); 219 } 220 } 221 222 229 public Object getHelperObject(final String key) { 230 return this.objectRegistry.get(key); 231 } 232 233 244 public XmlReadHandler createHandler(final Class classToRead, final String tagName, final Attributes atts) 245 throws XmlReaderException { 246 247 final XmlReadHandler retval = findHandlerForClass(classToRead, atts, new ArrayList ()); 248 if (retval == null) { 249 throw new NullPointerException ("Unable to find handler for class: " + classToRead); 250 } 251 retval.init(this, tagName); 252 return retval; 253 } 254 255 266 private XmlReadHandler findHandlerForClass(final Class classToRead, final Attributes atts, 267 final ArrayList history) 268 throws XmlReaderException { 269 final ObjectFactory genericFactory = getFactoryLoader(); 270 271 if (history.contains(classToRead)) { 272 throw new IllegalStateException ("Circular reference detected: " + history); 273 } 274 history.add(classToRead); 275 ManualMappingDefinition manualDefinition = 277 this.classToHandlerMapping.getManualMappingDefinition(classToRead); 278 if (manualDefinition == null) { 279 manualDefinition = genericFactory.getManualMappingDefinition(classToRead); 280 } 281 if (manualDefinition != null) { 282 return loadHandlerClass(manualDefinition.getReadHandler()); 284 } 285 286 MultiplexMappingDefinition mplex = 289 getFactoryLoader().getMultiplexDefinition(classToRead); 290 if (mplex == null) { 291 mplex = this.classToHandlerMapping.getMultiplexDefinition(classToRead); 292 } 293 if (mplex != null) { 294 final String attributeValue = atts.getValue(mplex.getAttributeName()); 295 if (attributeValue == null) { 296 throw new XmlReaderException( 297 "Multiplexer type attribute is not defined: " + mplex.getAttributeName() 298 + " for " + classToRead 299 ); 300 } 301 final MultiplexMappingEntry entry = 302 mplex.getEntryForType(attributeValue); 303 if (entry == null) { 304 throw new XmlReaderException( 305 "Invalid type attribute value: " + mplex.getAttributeName() + " = " 306 + attributeValue 307 ); 308 } 309 final Class c = loadClass(entry.getTargetClass()); 310 if (!c.equals(mplex.getBaseClass())) { 311 return findHandlerForClass(c, atts, history); 312 } 313 } 314 315 if (this.classToHandlerMapping.isGenericHandler(classToRead)) { 318 return new GenericReadHandler 319 (this.classToHandlerMapping.getFactoryForClass(classToRead)); 320 } 321 if (getFactoryLoader().isGenericHandler(classToRead)) { 322 return new GenericReadHandler 323 (getFactoryLoader().getFactoryForClass(classToRead)); 324 } 325 return null; 326 } 327 328 333 protected void setRootHandler(final XmlReadHandler handler) { 334 this.rootHandler = handler; 335 this.rootHandlerInitialized = false; 336 } 337 338 343 protected XmlReadHandler getRootHandler() { 344 return this.rootHandler; 345 } 346 347 357 public void recurse(final XmlReadHandler handler, final String tagName, final Attributes attrs) 358 throws XmlReaderException, SAXException { 359 360 this.outerScopes.push(this.currentHandlers); 361 this.currentHandlers = new Stack (); 362 this.currentHandlers.push(handler); 363 handler.startElement(tagName, attrs); 364 365 } 366 367 377 public void delegate(final XmlReadHandler handler, final String tagName, final Attributes attrs) 378 throws XmlReaderException, SAXException { 379 this.currentHandlers.push(handler); 380 handler.init(this, tagName); 381 handler.startElement(tagName, attrs); 382 } 383 384 392 public void unwind(final String tagName) throws SAXException , XmlReaderException { 393 this.currentHandlers.pop(); 395 if (this.currentHandlers.isEmpty() && !this.outerScopes.isEmpty()) { 396 this.currentHandlers = (Stack ) this.outerScopes.pop(); 399 } 400 else if (!this.currentHandlers.isEmpty()) { 401 getCurrentHandler().endElement(tagName); 403 } 404 } 405 406 411 protected XmlReadHandler getCurrentHandler() { 412 return (XmlReadHandler) this.currentHandlers.peek(); 413 } 414 415 420 public void startDocument() throws SAXException { 421 this.outerScopes = new Stack (); 422 this.currentHandlers = new Stack (); 423 this.currentHandlers.push(this.rootHandler); 424 } 425 426 436 public void startElement(final String uri, final String localName, 437 final String qName, final Attributes attributes) 438 throws SAXException { 439 if (rootHandlerInitialized == false) { 440 rootHandler.init(this, qName); 441 rootHandlerInitialized = true; 442 } 443 444 try { 445 getCurrentHandler().startElement(qName, attributes); 446 } 447 catch (XmlReaderException xre) { 448 throw new ParseException(xre, getLocator()); 449 } 450 } 451 452 461 public void characters(final char[] ch, final int start, final int length) throws SAXException { 462 try { 463 getCurrentHandler().characters(ch, start, length); 464 } 465 catch (SAXException se) { 466 throw se; 467 } 468 catch (Exception e) { 469 throw new ParseException(e, getLocator()); 470 } 471 } 472 473 482 public void endElement(final String uri, final String localName, final String qName) 483 throws SAXException { 484 try { 485 getCurrentHandler().endElement(qName); 486 } 487 catch (XmlReaderException xre) { 488 throw new ParseException(xre, getLocator()); 489 } 490 } 491 492 500 protected XmlReadHandler loadHandlerClass(final String className) 501 throws XmlReaderException { 502 try { 503 final Class c = loadClass(className); 504 return (XmlReadHandler) c.newInstance(); 505 } 506 catch (Exception e) { 507 throw new XmlReaderException("LoadHanderClass: Unable to instantiate " + className, e); 509 } 510 } 511 512 520 protected Class loadClass(final String className) 521 throws XmlReaderException { 522 if (className == null) { 523 throw new XmlReaderException("LoadHanderClass: Class name not defined"); 524 } 525 try { 526 final Class c = ObjectUtilities.getClassLoader(getClass()).loadClass(className); 527 return c; 528 } 529 catch (Exception e) { 530 throw new XmlReaderException("LoadHanderClass: Unable to load " + className, e); 532 } 533 } 534 535 public Object getResult () throws SAXException 536 { 537 if (this.rootHandler != null) { 538 try 539 { 540 return this.rootHandler.getObject(); 541 } 542 catch (XmlReaderException e) 543 { 544 throw new ElementDefinitionException(e); 545 } 546 } 547 return null; 548 } 549 } 550 | Popular Tags |