1 56 57 package org.objectstyle.cayenne.xml; 58 59 import java.io.Reader ; 60 import java.util.ArrayList ; 61 import java.util.Collection ; 62 import java.util.HashMap ; 63 import java.util.Iterator ; 64 import java.util.List ; 65 import java.util.Map ; 66 67 import org.apache.commons.beanutils.ConstructorUtils; 68 import org.apache.commons.beanutils.PropertyUtils; 69 import org.jdom.Document; 70 import org.jdom.Element; 71 import org.jdom.input.SAXBuilder; 72 import org.objectstyle.cayenne.CayenneRuntimeException; 73 import org.objectstyle.cayenne.DataObject; 74 import org.objectstyle.cayenne.access.DataContext; 75 76 82 public class XMLDecoder { 83 84 static final Map classMapping = new HashMap (); 85 86 static { 87 classMapping.put("boolean", Boolean .class); 88 classMapping.put("int", Integer .class); 89 classMapping.put("char", Character .class); 90 classMapping.put("float", Float .class); 91 classMapping.put("byte", Byte .class); 92 classMapping.put("short", Short .class); 93 classMapping.put("long", Long .class); 94 classMapping.put("double", Double .class); 95 } 96 97 98 private Element root; 99 100 101 private DataContext dc; 102 103 private List decodedCollections = new ArrayList (); 105 106 112 public XMLDecoder() { 113 this(null); 114 } 115 116 122 public XMLDecoder(DataContext dc) { 123 this.dc = dc; 124 } 125 126 132 public Boolean decodeBoolean(String xmlTag) { 133 String val = decodeString(xmlTag); 134 135 if (null == val) { 136 return null; 137 } 138 139 return Boolean.valueOf(val); 140 } 141 142 148 public Double decodeDouble(String xmlTag) { 149 String val = decodeString(xmlTag); 150 151 if (null == val) { 152 return null; 153 } 154 155 return Double.valueOf(val); 156 } 157 158 164 public Float decodeFloat(String xmlTag) { 165 String val = decodeString(xmlTag); 166 167 if (null == val) { 168 return null; 169 } 170 171 return Float.valueOf(val); 172 } 173 174 180 public Integer decodeInteger(String xmlTag) { 181 String val = decodeString(xmlTag); 182 183 if (null == val) { 184 return null; 185 } 186 187 return Integer.valueOf(val); 188 } 189 190 196 public Object decodeObject(String xmlTag) { 197 Element child = root.getChild(xmlTag); 199 200 return decodeObject(child); 201 } 202 203 209 private Object decodeObject(Element child) { 210 211 if (null == child) { 212 return null; 213 } 214 215 String type = child.getAttributeValue("type"); 216 if (null == type) { 217 throw new CayenneRuntimeException("No type specified for tag '" 219 + child.getName() 220 + "'."); 221 } 222 223 Class objectClass = (Class ) classMapping.get(type); 225 if (null == objectClass) { 226 try { 227 objectClass = Class.forName(type); 228 } 229 catch (Exception e) { 230 throw new CayenneRuntimeException("Unrecognized class '" 231 + objectClass 232 + "'", e); 233 } 234 } 235 236 try { 237 if ((((null != child.getParentElement()) && (child 247 .getParentElement() 248 .getChildren(child.getName()) 249 .size() > 1)) || ((null != child.getAttributeValue("forceList")) && (child 250 .getAttributeValue("forceList") 251 .toUpperCase().equals("YES")))) 252 && (false == decodedCollections.contains(child))) { 253 return decodeCollection(child); 254 } 255 256 else if (XMLSerializable.class.isAssignableFrom(objectClass)) { 259 XMLSerializable ret = (XMLSerializable) objectClass.newInstance(); 260 ret.decodeFromXML(this); 261 262 return ret; 263 } 264 265 else if (ConstructorUtils.getAccessibleConstructor(objectClass, String .class) != null) { 268 return ConstructorUtils.invokeConstructor(objectClass, child.getText()); 274 } 275 276 else { 279 throw new CayenneRuntimeException( 280 "Error decoding tag '" 281 + child.getName() 282 + "': " 283 + "specified class does not have a constructor taking either a String or an XMLDecoder"); 284 } 285 } 286 catch (Exception e) { 287 throw new CayenneRuntimeException("Error decoding tag '" 288 + child.getName() 289 + "'", e); 290 } 291 } 292 293 299 public String decodeString(String xmlTag) { 300 return root.getChildText(xmlTag); 303 } 304 305 312 public Object decode(Reader xml) throws CayenneRuntimeException { 313 314 Document data = parse(xml); 316 317 return decodeElement(data.getRootElement()); 319 } 320 321 332 public Object decode(Reader xml, String mappingUrl) throws CayenneRuntimeException { 333 Document data = parse(xml); 335 336 XMLMappingUtil mu = new XMLMappingUtil(mappingUrl); 338 Object ret = mu.decode(data.getRootElement()); 339 340 if (null != dc) { 341 dc.registerNewObject((DataObject) ret); 342 } 343 344 return ret; 345 } 346 347 355 private Object decodeElement(Element element) throws CayenneRuntimeException { 356 357 Element oldRoot = root; 360 root = element; 361 362 Object object; 365 366 try { 367 object = decodeObject(element); 368 } 369 catch (Throwable th) { 370 throw new CayenneRuntimeException("Error instantiating object", th); 371 } 372 373 if ((null != dc) && (object instanceof DataObject)) { 374 dc.registerNewObject((DataObject) object); 375 } 376 377 root = oldRoot; 378 decodedCollections.clear(); 379 380 return object; 381 } 382 383 391 private Collection decodeCollection(Element xml) throws CayenneRuntimeException { 392 393 Collection ret; 394 try { 395 String parentClass = xml.getParentElement().getAttributeValue("type"); 396 Object property = Class.forName(parentClass).newInstance(); 397 Collection c = (Collection ) PropertyUtils.getNestedProperty(property, xml 398 .getName()); 399 400 ret = (Collection ) c.getClass().newInstance(); 401 } 402 catch (Exception ex) { 403 throw new CayenneRuntimeException( 404 "Could not create collection with no-arg constructor.", 405 ex); 406 } 407 408 for (Iterator it = xml.getParentElement().getChildren(xml.getName()).iterator(); it 412 .hasNext();) { 413 Element e = (Element) it.next(); 415 decodedCollections.add(e); 416 Object o = decodeElement(e); 417 418 ret.add(o); 420 } 421 422 return ret; 423 } 424 425 432 public List decodeList(Reader xml) { 433 return decodeList(xml, null); 434 } 435 436 446 public List decodeList(Reader xml, String mappingUrl) throws CayenneRuntimeException { 447 Element listRoot = parse(xml).getRootElement(); 448 449 List ret; 450 try { 451 String parentClass = listRoot.getAttributeValue("type"); 452 ret = (List ) Class.forName(parentClass).newInstance(); 453 } 454 catch (Exception ex) { 455 throw new CayenneRuntimeException( 456 "Could not create collection with no-arg constructor.", 457 ex); 458 } 459 460 XMLMappingUtil mu = null; 461 if (null != mappingUrl) { 462 mu = new XMLMappingUtil(mappingUrl); 463 } 464 465 for (Iterator it = listRoot.getChildren().iterator(); it.hasNext();) { 469 Element e = (Element) it.next(); 471 decodedCollections.add(e); 472 Object o; 473 474 if (null == mu) { 476 o = decodeElement(e); 477 } 478 else { 479 o = mu.decode(e); 480 } 481 482 if ((null != dc) && (o instanceof DataObject)) { 484 dc.registerNewObject((DataObject) o); 485 } 486 487 ret.add(o); 489 } 490 491 return ret; 492 } 493 494 501 private Document parse(Reader in) throws CayenneRuntimeException { 502 503 SAXBuilder parser = new SAXBuilder(); 506 507 try { 508 return parser.build(in); 509 } 510 catch (Exception ex) { 511 throw new CayenneRuntimeException("Error parsing XML", ex); 512 } 513 } 514 } | Popular Tags |