1 7 package org.jboss.xml.binding; 8 9 import org.xml.sax.Attributes ; 10 import org.jboss.logging.Logger; 11 import org.jboss.xml.binding.parser.JBossXBParser; 12 import org.apache.xerces.xs.XSTypeDefinition; 13 14 import javax.xml.namespace.QName ; 15 import java.util.Map ; 16 import java.util.HashMap ; 17 import java.util.Collections ; 18 import java.util.LinkedList ; 19 import java.util.StringTokenizer ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 23 31 public class ObjectModelBuilder 32 implements ContentNavigator, JBossXBParser.ContentHandler 33 { 34 37 private static final Logger log = Logger.getLogger(ObjectModelBuilder.class); 38 39 43 private static final Object IGNORED = new Object (); 44 45 private Object root; 46 47 50 private Stack all = new StackImpl(); 51 54 private Stack accepted = new StackImpl(); 55 56 private GenericObjectModelFactory curFactory; 57 private String curNameSwitchingFactory; 58 private String curNsSwitchingFactory; 59 private Stack nameSwitchingFactory; 60 private Stack nsSwitchingFactory; 61 62 65 private GenericObjectModelFactory defaultFactory; 66 69 private Map factoriesToNs = Collections.EMPTY_MAP; 70 71 private Map prefixToUri = new HashMap (); 72 73 76 private StringBuffer value = new StringBuffer (); 77 78 private XSTypeDefinition currentType; 79 80 82 public void mapFactoryToNamespace(GenericObjectModelFactory factory, String namespaceUri) 83 { 84 if(factoriesToNs == Collections.EMPTY_MAP) 85 { 86 factoriesToNs = new HashMap (); 87 } 88 factoriesToNs.put(namespaceUri, factory); 89 } 90 91 public void init(GenericObjectModelFactory defaultFactory, Object root) 92 { 93 this.defaultFactory = defaultFactory; 94 95 all.clear(); 96 accepted.clear(); 97 value.delete(0, value.length()); 98 this.root = root; 99 } 100 101 131 132 134 public Map getPrefixToNamespaceMap() 135 { 136 return Collections.unmodifiableMap(prefixToUri); 137 } 138 139 public String resolveNamespacePrefix(String prefix) 140 { 141 String uri; 142 LinkedList prefixStack = (LinkedList ) prefixToUri.get(prefix); 143 if(prefixStack != null && !prefixStack.isEmpty()) 144 { 145 uri = (String ) prefixStack.getFirst(); 146 } 147 else 148 { 149 uri = null; 150 } 151 return uri; 152 } 153 154 159 public QName resolveQName(String value) 160 { 161 StringTokenizer st = new StringTokenizer (value, ":"); 162 if(st.countTokens() == 1) 163 { 164 return new QName (value); 165 } 166 167 if(st.countTokens() != 2) 168 { 169 throw new IllegalArgumentException ("Illegal QName: " + value); 170 } 171 172 String prefix = st.nextToken(); 173 String local = st.nextToken(); 174 String nsURI = resolveNamespacePrefix(prefix); 175 176 return new QName (nsURI, local); 177 } 178 179 public String getChildContent(String namespaceURI, String qName) 180 { 181 throw new UnsupportedOperationException (); 183 } 185 186 public XSTypeDefinition getType() 187 { 188 return currentType; 189 } 190 191 193 public void startPrefixMapping(String prefix, String uri) 194 { 195 LinkedList prefixStack = (LinkedList ) prefixToUri.get(prefix); 196 if(prefixStack == null || prefixStack.isEmpty()) 197 { 198 prefixStack = new LinkedList (); 199 prefixToUri.put(prefix, prefixStack); 200 } 201 prefixStack.addFirst(uri); 202 } 203 204 public void endPrefixMapping(String prefix) 205 { 206 LinkedList prefixStack = (LinkedList ) prefixToUri.get(prefix); 207 if(prefixStack != null) 208 { 209 prefixStack.removeFirst(); 210 } 211 } 212 213 public Object getRoot() 214 { 215 if(!all.isEmpty()) 216 { 217 all.pop(); 218 accepted.pop(); 219 } 220 return root; 221 } 222 223 public void startElement(String namespaceURI, String localName, String qName, Attributes atts, XSTypeDefinition type) 224 { 225 Object parent = accepted.isEmpty() ? root : accepted.peek(); 226 227 currentType = type; 229 230 Object element; 231 if(!namespaceURI.equals(curNsSwitchingFactory)) 232 { 233 if(curNsSwitchingFactory != null) 234 { 235 if(nsSwitchingFactory == null) 236 { 237 nsSwitchingFactory = new StackImpl(); 238 nameSwitchingFactory = new StackImpl(); 239 } 240 nsSwitchingFactory.push(curNsSwitchingFactory); 241 nameSwitchingFactory.push(curNameSwitchingFactory); 242 } 243 curNsSwitchingFactory = namespaceURI; 244 curNameSwitchingFactory = localName; 245 curFactory = getFactory(namespaceURI); 246 247 element = curFactory.newRoot(parent, this, namespaceURI, localName, atts); 248 } 249 else 250 { 251 element = curFactory.newChild(parent, this, namespaceURI, localName, atts); 252 } 253 254 if(element == null) 255 { 256 all.push(IGNORED); 257 258 if(log.isTraceEnabled()) 259 { 260 log.trace("ignored " + namespaceURI + ':' + qName); 261 } 262 } 263 else 264 { 265 all.push(element); 266 accepted.push(element); 267 268 if(log.isTraceEnabled()) 269 { 270 log.trace("accepted " + namespaceURI + ':' + qName); 271 } 272 } 273 } 274 275 public void endElement(String namespaceURI, String localName, String qName) 276 { 277 if(value.length() > 0) 278 { 279 Object element; 280 try 281 { 282 element = accepted.peek(); 283 } 284 catch(java.util.NoSuchElementException e) 285 { 286 log.error("value=" + value, e); 287 throw e; 288 } 289 curFactory.setValue(element, this, namespaceURI, localName, value.toString().trim()); 290 value.delete(0, value.length()); 291 } 292 293 if(localName.equals(curNameSwitchingFactory) && namespaceURI.equals(curNsSwitchingFactory)) 294 { 295 if(nsSwitchingFactory == null || nsSwitchingFactory.isEmpty()) 296 { 297 curNameSwitchingFactory = null; 298 curNsSwitchingFactory = null; 299 } 300 else 301 { 302 curNameSwitchingFactory = (String )nameSwitchingFactory.pop(); 303 curNsSwitchingFactory = (String )nsSwitchingFactory.pop(); 304 } 305 306 curFactory = getFactory(curNsSwitchingFactory); 307 } 308 309 Object element = all.pop(); 310 if(element != IGNORED) 311 { 312 element = accepted.pop(); 313 Object parent = (accepted.isEmpty() ? null : accepted.peek()); 314 315 if(parent != null) 316 { 317 curFactory.addChild(parent, element, this, namespaceURI, localName); 318 } 319 else 320 { 321 root = curFactory.completedRoot(element, this, namespaceURI, localName); 322 } 323 } 324 } 325 326 public void characters(char[] ch, int start, int length) 327 { 328 value.append(ch, start, length); 329 } 330 331 333 private GenericObjectModelFactory getFactory(String namespaceUri) 334 { 335 GenericObjectModelFactory factory = (GenericObjectModelFactory)factoriesToNs.get(namespaceUri); 336 if(factory == null) 337 { 338 factory = defaultFactory; 339 } 340 return factory; 341 } 342 343 static Object invokeFactory(Object factory, Method method, Object [] args) 344 { 345 try 346 { 347 return method.invoke(factory, args); 348 } 349 catch(InvocationTargetException e) 350 { 351 log.error("Failed to invoke method " + method.getName(), e.getTargetException()); 352 throw new IllegalStateException ("Failed to invoke method " + method.getName()); 353 } 354 catch(Exception e) 355 { 356 log.error("Failed to invoke method " + method.getName(), e); 357 throw new IllegalStateException ("Failed to invoke method " + method.getName()); 358 } 359 } 360 361 static Method getMethodForElement(Object factory, String name, Class [] params) 362 { 363 Method method = null; 364 try 365 { 366 method = factory.getClass().getMethod(name, params); 367 } 368 catch(NoSuchMethodException e) 369 { 370 } 371 catch(SecurityException e) 372 { 373 throw new IllegalStateException (e.getMessage()); 374 } 375 376 return method; 377 } 378 379 private static interface Stack 380 { 381 void clear(); 382 383 void push(Object o); 384 385 Object pop(); 386 387 Object peek(); 388 389 boolean isEmpty(); 390 } 391 392 private static class StackImpl 393 implements Stack 394 { 395 private LinkedList list = new LinkedList (); 396 397 public void clear() 398 { 399 list.clear(); 400 } 401 402 public void push(Object o) 403 { 404 list.addLast(o); 405 } 406 407 public Object pop() 408 { 409 return list.removeLast(); 410 } 411 412 public Object peek() 413 { 414 return list.getLast(); 415 } 416 417 public boolean isEmpty() 418 { 419 return list.isEmpty(); 420 } 421 } 422 } 423 | Popular Tags |