1 19 20 package org.apache.cayenne.xml; 21 22 import java.util.Collection ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 27 import javax.xml.parsers.DocumentBuilder ; 28 29 import org.apache.cayenne.CayenneRuntimeException; 30 import org.apache.cayenne.Persistent; 31 import org.apache.cayenne.access.DataContext; 32 import org.apache.cayenne.reflect.PropertyUtils; 33 import org.w3c.dom.Attr ; 34 import org.w3c.dom.Document ; 35 import org.w3c.dom.Element ; 36 import org.w3c.dom.NamedNodeMap ; 37 38 45 final class XMLMappingDescriptor { 46 47 private SerializableEntity rootEntity; 48 private Map entities; 49 private DataContext dataContext; 50 51 57 XMLMappingDescriptor(String mappingUrl) throws CayenneRuntimeException { 58 59 DocumentBuilder builder = XMLUtil.newBuilder(); 61 62 Document document; 63 try { 64 document = builder.parse(mappingUrl); 65 } 66 catch (Exception ex) { 67 throw new CayenneRuntimeException("Error parsing XML at " + mappingUrl, ex); 68 } 69 70 Element root = document.getDocumentElement(); 71 72 if (!"model".equals(root.getNodeName())) { 73 throw new CayenneRuntimeException( 74 "Root of the mapping model must be \"model\""); 75 } 76 77 Map entities = new HashMap (); 78 Iterator it = XMLUtil.getChildren(root).iterator(); 79 while (it.hasNext()) { 80 Element e = (Element ) it.next(); 81 82 SerializableEntity entity = new SerializableEntity(this, e); 83 String tag = e.getAttribute("xmlTag"); 84 entities.put(tag, entity); 85 86 if (rootEntity == null) { 87 rootEntity = entity; 88 } 89 } 90 91 this.entities = entities; 92 } 93 94 SerializableEntity getRootEntity() { 95 return rootEntity; 96 } 97 98 105 Object decode(Element xml, DataContext dataContext) throws CayenneRuntimeException { 106 107 110 this.dataContext = dataContext; 112 113 Object ret = createObject(rootEntity.getDescriptor(), xml); 115 116 for (Iterator it = XMLUtil.getChildren(xml).iterator(); it.hasNext();) { 119 Element value = (Element ) it.next(); 120 decodeProperty(ret, rootEntity.getDescriptor(), value); 121 } 122 123 return ret; 124 } 125 126 132 SerializableEntity getEntity(String name) { 133 return (SerializableEntity) entities.get(name); 134 } 135 136 143 private String getPropertyMappingName(Element entityMapping, String propertyXmlTag) { 144 for (Iterator it = XMLUtil.getChildren(entityMapping).iterator(); it.hasNext();) { 145 Element propertyMapping = (Element ) it.next(); 146 147 if (propertyXmlTag.equals(propertyMapping.getAttribute("xmlTag"))) { 148 return propertyMapping.getAttribute("name"); 149 } 150 } 151 152 return null; 153 } 154 155 164 private void decodeProperty(Object object, Element entityMapping, Element propertyData) 165 throws CayenneRuntimeException { 166 167 String xmlTag = propertyData.getNodeName(); 168 String propertyName = getPropertyMappingName(entityMapping, xmlTag); 169 170 if (propertyName == null) { 172 return; 173 } 174 175 SerializableEntity targetEntityMapping = getEntity(xmlTag); 176 177 if (targetEntityMapping == null) { 179 setProperty(object, propertyName, XMLUtil.getText(propertyData)); 180 } 181 else { 183 184 Object o = createObject(targetEntityMapping.getDescriptor(), propertyData); 185 186 Iterator it = XMLUtil.getChildren(propertyData).iterator(); 189 while (it.hasNext()) { 190 Element child = (Element ) it.next(); 191 decodeProperty(o, targetEntityMapping.getDescriptor(), child); 192 } 193 194 setProperty(object, propertyName, o); 195 } 196 } 197 198 202 private void setProperty(Object object, String propertyName, Object value) { 203 204 208 try { 209 PropertyUtils.setProperty(object, propertyName, value); 210 } 211 catch (CayenneRuntimeException e) { 212 Object existingValue = PropertyUtils.getProperty(object, propertyName); 213 if (existingValue instanceof Collection && !(value instanceof Collection )) { 214 ((Collection ) existingValue).add(value); 215 } 216 else { 217 throw e; 218 } 219 } 220 } 221 222 231 private Object createObject(Element entityMapping, Element objectData) { 232 String className = entityMapping.getAttribute("name"); 233 234 Object object; 235 try { 236 object = Class.forName( 237 className, 238 true, 239 Thread.currentThread().getContextClassLoader()).newInstance(); 240 } 241 catch (Exception ex) { 242 throw new CayenneRuntimeException("Error creating instance of class " 243 + className, ex); 244 } 245 246 if ((null != dataContext) && (object instanceof Persistent)) { 248 dataContext.registerNewObject((Persistent) object); 249 } 250 251 NamedNodeMap attributes = objectData.getAttributes(); 252 for (int i = 0; i < attributes.getLength(); i++) { 253 Attr attribute = (Attr ) attributes.item(i); 254 String propertyName = getPropertyMappingName(entityMapping, attribute 255 .getName()); 256 257 if (propertyName != null) { 258 PropertyUtils.setProperty(object, propertyName, attribute.getValue()); 259 } 260 } 261 262 return object; 263 } 264 } 265 | Popular Tags |