1 7 package org.jboss.xb.binding; 8 9 import org.jboss.xb.binding.metadata.unmarshalling.BasicElementBinding; 10 import org.jboss.xb.binding.metadata.unmarshalling.ElementBinding; 11 import org.jboss.xb.binding.metadata.unmarshalling.XmlValueBinding; 12 import org.jboss.xb.binding.metadata.unmarshalling.XmlValueContainer; 13 import org.jboss.xb.binding.metadata.unmarshalling.AttributeBinding; 14 import org.jboss.logging.Logger; 15 import org.xml.sax.Attributes ; 16 17 import javax.xml.namespace.QName ; 18 import java.util.Collection ; 19 import java.util.ArrayList ; 20 import java.util.HashSet ; 21 import java.util.Set ; 22 import java.lang.reflect.Constructor ; 23 import java.lang.reflect.Method ; 24 import java.lang.reflect.Field ; 25 26 30 public class MetadataDrivenObjectModelFactory 31 implements GenericObjectModelFactory 32 { 33 private static final Logger log = Logger.getLogger(MetadataDrivenObjectModelFactory.class); 34 35 public Object newChild(Object parent, 36 UnmarshallingContext ctx, 37 String namespaceURI, 38 String localName, 39 Attributes attrs) 40 { 41 boolean trace = log.isTraceEnabled(); 42 if(trace) 43 { 44 log.trace("newChild " + namespaceURI + ":" + localName + " for " + parent); 45 } 46 47 Object child; 48 49 ElementBinding metadata = (ElementBinding)ctx.getMetadata(); 50 if(metadata == null) 51 { 52 throw new JBossXBRuntimeException( 53 "Binding metadata is not available for element {" + namespaceURI + ":" + localName + "}" 54 ); 55 } 56 57 if(Collection .class.isAssignableFrom(metadata.getJavaType())) 58 { 59 Collection col; 60 if(parent instanceof Immutable) 61 { 62 Immutable imm = (Immutable)parent; 63 col = (Collection )imm.getChild(localName); 64 if(col == null) 65 { 66 col = (Collection )newInstance(metadata); 67 imm.addChild(localName, col); 68 } 69 } 70 else 71 { 72 col = (Collection )getFieldValue(metadata, parent); 73 if(col == null) 74 { 75 col = (Collection )newInstance(metadata); 76 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), parent, col); 77 } 78 } 79 80 child = col; 81 } 82 else if(!Util.isAttributeType(metadata.getJavaType())) 83 { 84 child = newInstance(metadata); 85 if(!(child instanceof Immutable)) 86 { 87 if(parent instanceof Collection ) 88 { 89 ((Collection )parent).add(child); 90 } 91 else if(parent instanceof Immutable) 92 { 93 ((Immutable)parent).addChild(localName, child); 94 } 95 else if(metadata.getFieldType() != null && Collection .class.isAssignableFrom(metadata.getFieldType())) 96 { 97 Collection col = (Collection )getFieldValue(metadata, parent); 98 if(col == null) 99 { 100 if(Set .class.isAssignableFrom(metadata.getFieldType())) 101 { 102 col = new HashSet (); 103 } 104 else 105 { 106 col = new ArrayList (); 107 } 108 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), parent, col); 109 } 110 col.add(child); 111 } 112 else 113 { 114 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), parent, child); 115 } 116 } 117 118 if(attrs != null && attrs.getLength() > 0) 119 { 120 for(int i = 0; i < attrs.getLength(); ++i) 121 { 122 QName attrName = new QName (attrs.getURI(i), attrs.getLocalName(i)); 123 AttributeBinding attrBinding = metadata.getAttribute(attrName); 124 if(attrBinding != null) 125 { 126 Object unmarshalledValue = SimpleTypeBindings.unmarshal(attrs.getValue(i), 127 attrBinding.getJavaType() 128 ); 129 130 if(child instanceof Immutable) 131 { 132 ((Immutable)child).addChild(attrName.getLocalPart(), unmarshalledValue); 133 } 134 else 135 { 136 setFieldValue(attrBinding.getAttributeName(), 137 attrBinding.getField(), 138 attrBinding.getSetter(), 139 child, 140 unmarshalledValue 141 ); 142 } 143 } 144 } 145 } 146 } 147 else 148 { 149 child = null; 150 } 151 152 return child; 153 } 154 155 public void addChild(Object parent, Object child, UnmarshallingContext ctx, String namespaceURI, String localName) 156 { 157 if(child instanceof Immutable) 158 { 159 ElementBinding metadata = (ElementBinding)ctx.getMetadata(); 160 161 child = ((Immutable)child).newInstance(); 162 if(parent instanceof Collection ) 163 { 164 ((Collection )parent).add(child); 165 } 166 else if(metadata.getFieldType() == null || Collection .class.isAssignableFrom(metadata.getFieldType())) 167 { 168 Collection col; 169 if(parent instanceof Immutable) 170 { 171 Immutable imm = (Immutable)parent; 172 col = (Collection )imm.getChild(localName); 173 if(col == null) 174 { 175 col = new ArrayList (); 176 imm.addChild(localName, col); 177 } 178 } 179 else 180 { 181 col = (Collection )getFieldValue(metadata, parent); 182 if(col == null) 183 { 184 col = new ArrayList (); 185 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), parent, col); 186 } 187 } 188 189 col.add(child); 190 } 191 else if(parent instanceof Immutable) 192 { 193 ((Immutable)parent).addChild(localName, child); 194 } 195 else 196 { 197 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), parent, child); 198 } 199 } 200 } 201 202 public void setValue(Object o, UnmarshallingContext ctx, String namespaceURI, String localName, String value) 203 { 204 ElementBinding metadata = (ElementBinding)ctx.getMetadata(); 205 206 if(Collection .class.isAssignableFrom(metadata.getJavaType())) 208 { 209 ((Collection )o).add(value); 210 } 211 else 212 { 213 if(Util.isAttributeType(metadata.getJavaType())) 214 { 215 Object unmarshalledValue = SimpleTypeBindings.unmarshal(value, metadata.getJavaType()); 216 if(o instanceof Collection ) 217 { 218 ((Collection )o).add(unmarshalledValue); 219 } 220 else if(o instanceof Immutable) 221 { 222 ((Immutable)o).addChild(localName, unmarshalledValue); 223 } 224 else 225 { 226 if(Collection .class.isAssignableFrom(metadata.getFieldType())) 227 { 228 Collection col = (Collection )getFieldValue(metadata, o); 229 if(col == null) 230 { 231 col = new ArrayList (); 232 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), o, col); 233 } 234 col.add(unmarshalledValue); 235 } 236 else 237 { 238 setFieldValue(metadata.getName(), metadata.getField(), metadata.getSetter(), o, unmarshalledValue); 239 } 240 } 241 } 242 else 243 { 244 XmlValueBinding valueBinding = metadata.getValue(); 245 if(valueBinding == null) 246 { 247 throw new JBossXBRuntimeException( 248 "Required value binding is not customized for " + metadata.getName() + ": value=" + value 249 ); 250 } 251 252 unmarshalValue(valueBinding, value, o); 253 } 254 } 255 } 256 257 public Object newRoot(Object root, 258 UnmarshallingContext ctx, 259 String namespaceURI, 260 String localName, 261 Attributes attrs) 262 { 263 if(root == null) 264 { 265 BasicElementBinding metadata = (BasicElementBinding)ctx.getMetadata(); 266 if(metadata == null) 267 { 268 throw new JBossXBRuntimeException( 269 "Binding metadata is not available for top-level element {" + namespaceURI + ":" + localName + "}" 270 ); 271 } 272 root = newInstance(metadata); 273 } 274 return root; 275 } 276 277 public Object completeRoot(Object root, UnmarshallingContext ctx, String namespaceURI, String localName) 278 { 279 return root instanceof Immutable ? ((Immutable)root).newInstance() : root; 280 } 281 282 284 private static void unmarshalValue(XmlValueBinding valueBinding, String value, Object o) 285 { 286 Object unmarshalled; 287 if(valueBinding.getValue() != null) 288 { 289 unmarshalled = newInstance(valueBinding); 290 unmarshalValue(valueBinding.getValue(), value, unmarshalled); 291 292 if(unmarshalled instanceof Immutable) 293 { 294 unmarshalled = ((Immutable)unmarshalled).newInstance(); 295 } 296 } 297 else 298 { 299 unmarshalled = SimpleTypeBindings.unmarshal(value, valueBinding.getJavaType()); 300 } 301 302 if(o instanceof Immutable) 304 { 305 ((Immutable)o).addChild(valueBinding.getName().getLocalPart(), unmarshalled); 306 } 307 else 308 { 309 setFieldValue(valueBinding.getName(), 310 valueBinding.getField(), 311 valueBinding.getSetter(), 312 o, 313 unmarshalled 314 ); 315 } 316 } 317 318 private static final void setFieldValue(QName elementName, 319 Field field, 320 Method setter, 321 Object parent, 322 Object child) 323 { 324 if(setter != null) 325 { 326 try 327 { 328 setter.invoke(parent, new Object []{child}); 329 } 330 catch(Exception e) 331 { 332 throw new JBossXBRuntimeException("Failed to set value (" + 333 child.getClass().getName() + 334 ":" + 335 child + 336 ") using setter " + 337 setter.getName() + 338 " in (" + 339 parent.getClass() + 340 ":" + 341 parent + "): " + e.getMessage(), e 342 ); 343 } 344 } 345 else if(field != null) 346 { 347 try 348 { 349 field.set(parent, child); 350 } 351 catch(IllegalAccessException e) 352 { 353 throw new JBossXBRuntimeException("Illegal access exception setting value (" + 354 child.getClass() + 355 ":" + 356 child + 357 ") using field " + 358 field.getName() + 359 " in (" + 360 parent.getClass() + 361 ":" + 362 parent + "): " + e.getMessage(), e 363 ); 364 } 365 } 366 else 367 { 368 throw new JBossXBRuntimeException("Element/attribute " + 369 elementName + 370 " is not bound to any field!" 371 ); 372 } 373 } 374 375 private static final Object getFieldValue(ElementBinding metadata, Object parent) 376 { 377 Object value; 378 if(metadata.getGetter() != null) 379 { 380 try 381 { 382 value = metadata.getGetter().invoke(parent, null); 383 } 384 catch(Exception e) 385 { 386 throw new JBossXBRuntimeException("Failed to get value using getter " + 387 metadata.getGetter().getName() + 388 " from " + 389 parent.getClass() + 390 ":" + 391 parent + ": " + e.getMessage(), e 392 ); 393 } 394 } 395 else if(metadata.getField() != null) 396 { 397 try 398 { 399 value = metadata.getField().get(parent); 400 } 401 catch(IllegalAccessException e) 402 { 403 throw new JBossXBRuntimeException("Illegal access exception getting value using field " + 404 metadata.getField().getName() + 405 " from " + 406 parent.getClass() + 407 ":" + 408 parent + ": " + e.getMessage(), e 409 ); 410 } 411 } 412 else 413 { 414 throw new JBossXBRuntimeException("Element " + 415 metadata.getName() + 416 " is not bound to any field!" 417 ); 418 } 419 420 return value; 421 } 422 423 private static final Object newInstance(XmlValueContainer metadata) 424 { 425 boolean trace = log.isTraceEnabled(); 426 427 Object instance; 428 Class javaType = metadata.getJavaType(); 429 if(trace) 430 { 431 log.trace("newInstance " + javaType + " for " + metadata.getName()); 432 } 433 try 434 { 435 Constructor ctor = javaType.getConstructor(null); 436 instance = ctor.newInstance(null); 437 } 438 catch(NoSuchMethodException e) 439 { 440 instance = new Immutable(javaType); 441 } 442 catch(Exception e) 443 { 444 throw new JBossXBRuntimeException( 445 "Failed to create an instance of " + metadata.getName() + " of type " + metadata.getJavaType() 446 ); 447 } 448 if(trace) 449 { 450 log.trace("newInstance=" + instance); 451 } 452 return instance; 453 } 454 } 455 | Popular Tags |