1 56 57 package org.objectstyle.cayenne.xml; 58 59 import java.util.ArrayList ; 60 import java.util.Collection ; 61 import java.util.Collections ; 62 import java.util.HashMap ; 63 import java.util.Iterator ; 64 import java.util.List ; 65 import java.util.Map ; 66 import java.util.Set ; 67 68 import org.apache.commons.beanutils.BeanUtils; 69 import org.apache.commons.beanutils.PropertyUtils; 70 import org.jdom.Document; 71 import org.jdom.Element; 72 import org.jdom.input.SAXBuilder; 73 import org.objectstyle.cayenne.CayenneRuntimeException; 74 75 82 final class XMLMappingUtil { 83 84 85 protected Element root; 86 87 88 protected Map entities; 89 90 96 public XMLMappingUtil(String mappingUrl) throws CayenneRuntimeException { 97 98 SAXBuilder parser = new SAXBuilder(); 100 Document mapping; 101 102 try { 103 mapping = parser.build(mappingUrl); 104 } 105 catch (Exception ex) { 106 throw new CayenneRuntimeException("Error parsing XML", ex); 107 } 108 109 setRoot(mapping.getRootElement()); 110 } 111 112 117 private void setRoot(Element root) { 118 119 if (!"model".equals(root.getName())) { 120 throw new CayenneRuntimeException( 121 "Root of the mapping model must be \"model\""); 122 } 123 124 this.root = root; 125 126 entities = new HashMap (); 127 for (Iterator it = getEntities().iterator(); it.hasNext();) { 128 Element e = (Element) it.next(); 129 130 entities.put(e.getAttributeValue("xmlTag"), e); 131 } 132 } 133 134 139 private List getEntities() { 140 return Collections.unmodifiableList(root.getChildren()); 141 } 142 143 148 private Set getEntityNames() { 149 return Collections.unmodifiableSet(entities.keySet()); 150 } 151 152 158 private Element getRootEntity() { 160 return (Element) getEntities().get(0); 161 } 162 163 171 private Element encodeEntity(Object object, Element entity) 172 throws CayenneRuntimeException { 173 174 Element ret = new Element(entity.getAttributeValue("xmlTag")); 176 177 for (Iterator it = entity.getChildren().iterator(); it.hasNext();) { 180 Element property = (Element) it.next(); 181 String xmlTag = property.getAttributeValue("xmlTag"); 182 String propertyName = property.getAttributeValue("name"); 183 184 Object propertyValue = getProperty(object, propertyName); 185 186 if (getEntityNames().contains(xmlTag) == false) { 190 193 XMLEncoder encoder = new XMLEncoder(); 194 195 encoder.encodeProperty(xmlTag, propertyValue); 198 Element e = encoder.getRoot(); 199 e.removeAttribute("type"); 200 201 ret.addContent(e); 203 } 204 else { 205 206 if (propertyValue instanceof Collection ) { 207 208 List encodedObjects = encodeCollection( 209 (Collection ) propertyValue, 210 getEntity(xmlTag)); 211 212 for (Iterator it2 = encodedObjects.iterator(); it2.hasNext();) { 213 Element element = (Element) it2.next(); 214 ret.addContent(element); 215 } 216 } 217 else { 218 ret.addContent(encodeEntity(propertyValue, getEntity(xmlTag))); 219 } 220 } 221 } 222 223 return ret; 224 } 225 226 234 private List encodeCollection(Collection collection, Element entity) 235 throws CayenneRuntimeException { 236 237 List ret = new ArrayList (); 238 239 for (Iterator it = collection.iterator(); it.hasNext();) { 241 Object element = it.next(); 242 243 ret.add(encodeEntity(element, entity)); 244 } 245 246 return ret; 247 } 248 249 257 public Element encode(Object object) throws CayenneRuntimeException { 258 return encodeEntity(object, getRootEntity()); 259 } 260 261 267 private Element getEntity(String name) { 268 return (Element) entities.get(name); 269 } 270 271 279 private String getEntityRef(Element rootEntity, String ref) { 282 for (Iterator it = rootEntity.getChildren().iterator(); it.hasNext();) { 283 Element child = (Element) it.next(); 284 285 if (child.getAttributeValue("xmlTag").equals(ref)) { 286 return child.getAttributeValue("name"); 287 } 288 } 289 290 return null; 291 } 292 293 301 private void decodeProperty(Object object, Element entity, Element encProperty) 302 throws CayenneRuntimeException { 303 304 List children = encProperty.getChildren(); 305 String xmlTag = encProperty.getName(); 306 307 if (children.isEmpty()) { 310 for (Iterator it = entity.getChildren().iterator(); it.hasNext();) { 313 Element e = (Element) it.next(); 314 315 if (e.getAttributeValue("xmlTag").equals(xmlTag)) { 317 318 setProperty(object, e.getAttributeValue("name"), encProperty 321 .getText()); 322 } 323 } 324 } 325 326 else { 329 Object o = newInstance(getEntity(xmlTag).getAttributeValue("name")); 331 332 for (Iterator it = children.iterator(); it.hasNext();) { 335 Element child = (Element) it.next(); 336 337 decodeProperty(o, getEntity(xmlTag), child); 338 } 339 340 Object property = getProperty(object, getEntityRef(entity, xmlTag)); 343 344 if (property instanceof Collection ) { 345 Collection c = (Collection ) property; 346 c.add(o); 347 } 348 else { 349 setProperty(object, getEntityRef(entity, xmlTag), o); 350 } 351 } 352 } 353 354 361 public Object decode(Element xml) throws CayenneRuntimeException { 362 363 List values = xml.getChildren(); 366 367 Object ret = newInstance(getRootEntity().getAttributeValue("name")); 369 370 for (Iterator it = values.iterator(); it.hasNext();) { 373 Element value = (Element) it.next(); 374 375 decodeProperty(ret, getRootEntity(), value); 376 } 377 378 return ret; 379 } 380 381 389 private void setProperty(Object object, String property, Object value) 390 throws CayenneRuntimeException { 391 try { 392 BeanUtils.setProperty(object, property, value); 393 } 394 catch (Exception ex) { 395 throw new CayenneRuntimeException("Error setting property " + property, ex); 396 } 397 } 398 399 407 private Object getProperty(Object object, String property) 408 throws CayenneRuntimeException { 409 try { 410 return PropertyUtils.getNestedProperty(object, property); 411 } 412 catch (Exception ex) { 413 throw new CayenneRuntimeException("Error reading property '" 414 + property 415 + "'.", ex); 416 } 417 } 418 419 427 private Object newInstance(String className) throws CayenneRuntimeException { 428 try { 429 return Class.forName(className).newInstance(); 430 } 431 catch (Exception ex) { 432 throw new CayenneRuntimeException("Error creating instance of class " 433 + className, ex); 434 } 435 } 436 } | Popular Tags |