1 19 20 21 package org.apache.cayenne.xml; 22 23 import java.io.Reader ; 24 import java.lang.reflect.Constructor ; 25 import java.text.ParseException ; 26 import java.text.SimpleDateFormat ; 27 import java.util.ArrayList ; 28 import java.util.Collection ; 29 import java.util.Date ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 35 import javax.xml.parsers.DocumentBuilder ; 36 37 import org.apache.cayenne.CayenneRuntimeException; 38 import org.apache.cayenne.Persistent; 39 import org.apache.cayenne.access.DataContext; 40 import org.apache.cayenne.reflect.PropertyUtils; 41 import org.apache.cayenne.util.Util; 42 import org.w3c.dom.Document ; 43 import org.w3c.dom.Element ; 44 import org.xml.sax.InputSource ; 45 46 52 public class XMLDecoder { 53 54 static final Map classMapping = new HashMap (); 55 56 static { 57 classMapping.put("boolean", Boolean .class); 58 classMapping.put("int", Integer .class); 59 classMapping.put("char", Character .class); 60 classMapping.put("float", Float .class); 61 classMapping.put("byte", Byte .class); 62 classMapping.put("short", Short .class); 63 classMapping.put("long", Long .class); 64 classMapping.put("double", Double .class); 65 } 66 67 68 private Element root; 69 70 71 private DataContext dataContext; 72 73 private List decodedCollections = new ArrayList (); 75 76 82 public XMLDecoder() { 83 this(null); 84 } 85 86 92 public XMLDecoder(DataContext dc) { 93 this.dataContext = dc; 94 } 95 96 102 public Boolean decodeBoolean(String xmlTag) { 103 String val = decodeString(xmlTag); 104 105 if (null == val) { 106 return null; 107 } 108 109 return Boolean.valueOf(val); 110 } 111 112 118 public Double decodeDouble(String xmlTag) { 119 String val = decodeString(xmlTag); 120 121 if (null == val) { 122 return null; 123 } 124 125 return Double.valueOf(val); 126 } 127 128 134 public Float decodeFloat(String xmlTag) { 135 String val = decodeString(xmlTag); 136 137 if (null == val) { 138 return null; 139 } 140 141 return Float.valueOf(val); 142 } 143 144 150 public Integer decodeInteger(String xmlTag) { 151 String val = decodeString(xmlTag); 152 153 if (null == val) { 154 return null; 155 } 156 157 return Integer.valueOf(val); 158 } 159 160 166 public Object decodeObject(String xmlTag) { 167 Element child = XMLUtil.getChild(root, xmlTag); 169 170 return decodeObject(child); 171 } 172 173 179 private Object decodeObject(Element child) { 180 181 if (null == child) { 182 return null; 183 } 184 185 String type = child.getAttribute("type"); 186 if (Util.isEmptyString(type)) { 187 throw new CayenneRuntimeException("No type specified for tag '" 189 + child.getNodeName() 190 + "'."); 191 } 192 193 Class objectClass = (Class ) classMapping.get(type); 195 if (null == objectClass) { 196 try { 197 objectClass = Class.forName(type); 198 } 199 catch (Exception e) { 200 throw new CayenneRuntimeException("Unrecognized class '" 201 + objectClass 202 + "'", e); 203 } 204 } 205 206 try { 207 if ((((null != child.getParentNode()) && (XMLUtil.getChildren( 217 child.getParentNode(), 218 child.getNodeName()).size() > 1)) || (child 219 .getAttribute("forceList") 220 .toUpperCase().equals("YES"))) 221 && (!decodedCollections.contains(child))) { 222 return decodeCollection(child); 223 } 224 225 if (XMLSerializable.class.isAssignableFrom(objectClass)) { 228 Element oldRoot = root; 234 root = child; 235 236 XMLSerializable ret = (XMLSerializable) objectClass.newInstance(); 237 ret.decodeFromXML(this); 238 239 root = oldRoot; 241 242 return ret; 243 } 244 245 String text = XMLUtil.getText(child); 246 247 if (Date .class.isAssignableFrom(objectClass)) { 249 try { 250 return new SimpleDateFormat (XMLUtil.DEFAULT_DATE_FORMAT).parse(text); 251 } 252 catch (ParseException e) { 253 255 try { 256 return new SimpleDateFormat ("E MMM dd hh:mm:ss z yyyy").parse(text); 257 } 258 catch (ParseException eOld) { 259 260 throw e; 262 } 263 } 264 } 265 266 Constructor c = objectClass.getConstructor(new Class [] { 268 String .class 269 }); 270 return c.newInstance(new Object [] { 271 text 272 }); 273 } 274 catch (Exception e) { 275 throw new CayenneRuntimeException("Error decoding tag '" 276 + child.getNodeName() 277 + "'", e); 278 } 279 } 280 281 287 public String decodeString(String xmlTag) { 288 Element child = XMLUtil.getChild(root, xmlTag); 291 return child != null ? XMLUtil.getText(child) : null; 292 } 293 294 301 public Object decode(Reader xml) throws CayenneRuntimeException { 302 303 Document data = parse(xml); 305 306 return decodeElement(data.getDocumentElement()); 308 } 309 310 320 public Object decode(Reader xml, String mappingUrl) throws CayenneRuntimeException { 321 Document data = parse(xml); 323 324 XMLMappingDescriptor mu = new XMLMappingDescriptor(mappingUrl); 326 327 Object ret = mu.decode(data.getDocumentElement(), dataContext); 328 329 return ret; 330 } 331 332 340 private Object decodeElement(Element element) throws CayenneRuntimeException { 341 342 Element oldRoot = root; 345 root = element; 346 347 Object object; 350 351 try { 352 object = decodeObject(element); 353 } 354 catch (Throwable th) { 355 throw new CayenneRuntimeException("Error instantiating object", th); 356 } 357 358 if ((null != dataContext) && (object instanceof Persistent)) { 359 dataContext.registerNewObject((Persistent) object); 360 } 361 362 root = oldRoot; 363 decodedCollections.clear(); 364 365 return object; 366 } 367 368 376 private Collection decodeCollection(Element xml) throws CayenneRuntimeException { 377 378 Collection ret; 379 try { 380 String parentClass = ((Element ) xml.getParentNode()).getAttribute("type"); 381 Object property = Class.forName(parentClass).newInstance(); 382 Collection c = (Collection ) PropertyUtils.getProperty(property, xml 383 .getNodeName()); 384 385 ret = (Collection ) c.getClass().newInstance(); 386 } 387 catch (Exception ex) { 388 throw new CayenneRuntimeException( 389 "Could not create collection with no-arg constructor.", 390 ex); 391 } 392 393 Iterator it = XMLUtil 397 .getChildren(xml.getParentNode(), xml.getNodeName()) 398 .iterator(); 399 while (it.hasNext()) { 400 Element e = (Element ) it.next(); 402 decodedCollections.add(e); 403 Object o = decodeElement(e); 404 405 ret.add(o); 407 } 408 409 return ret; 410 } 411 412 419 public static List decodeList(Reader xml) throws CayenneRuntimeException { 420 return decodeList(xml, null, null); 421 } 422 423 431 public static List decodeList(Reader xml, DataContext dc) 432 throws CayenneRuntimeException { 433 return decodeList(xml, null, dc); 434 } 435 436 446 public static List decodeList(Reader xml, String mappingUrl) 447 throws CayenneRuntimeException { 448 return decodeList(xml, mappingUrl, null); 449 } 450 451 462 public static List decodeList(Reader xml, String mappingUrl, DataContext dataContext) 463 throws CayenneRuntimeException { 464 465 XMLDecoder decoder = new XMLDecoder(dataContext); 466 Element listRoot = parse(xml).getDocumentElement(); 467 468 List ret; 469 try { 470 String parentClass = listRoot.getAttribute("type"); 471 ret = (List ) Class.forName(parentClass).newInstance(); 472 } 473 catch (Exception ex) { 474 throw new CayenneRuntimeException( 475 "Could not create collection with no-arg constructor.", 476 ex); 477 } 478 479 XMLMappingDescriptor mu = null; 480 if (mappingUrl != null) { 481 mu = new XMLMappingDescriptor(mappingUrl); 482 } 483 484 Iterator it = XMLUtil.getChildren(listRoot).iterator(); 488 while (it.hasNext()) { 489 Element e = (Element ) it.next(); 491 decoder.decodedCollections.add(e); 492 493 Object o; 495 496 if (mu != null) { 497 o = mu.decode(e, dataContext); 498 } 499 else { 500 o = decoder.decodeElement(e); 502 } 503 504 ret.add(o); 505 } 506 507 return ret; 508 } 509 510 517 private static Document parse(Reader in) throws CayenneRuntimeException { 518 DocumentBuilder builder = XMLUtil.newBuilder(); 519 520 try { 521 return builder.parse(new InputSource (in)); 522 } 523 catch (Exception ex) { 524 throw new CayenneRuntimeException("Error parsing XML", ex); 525 } 526 } 527 } 528 | Popular Tags |