1 17 package org.apache.ws.jaxme.impl; 18 19 import java.util.ArrayList ; 20 import java.util.List ; 21 22 import javax.xml.bind.DatatypeConverterInterface; 23 import javax.xml.bind.JAXBException; 24 import javax.xml.bind.ValidationEvent; 25 import javax.xml.bind.ValidationEventHandler; 26 import javax.xml.bind.helpers.ParseConversionEventImpl; 27 import javax.xml.bind.helpers.ValidationEventImpl; 28 import javax.xml.bind.helpers.ValidationEventLocatorImpl; 29 import javax.xml.namespace.QName ; 30 31 import org.apache.ws.jaxme.JMManager; 32 import org.apache.ws.jaxme.JMUnmarshaller; 33 import org.apache.ws.jaxme.JMUnmarshallerHandler; 34 import org.apache.ws.jaxme.Observer; 35 import org.apache.ws.jaxme.ValidationEvents; 36 import org.apache.ws.jaxme.util.NamespaceSupport; 37 import org.xml.sax.Attributes ; 38 import org.xml.sax.Locator ; 39 import org.xml.sax.SAXException ; 40 import org.xml.sax.SAXParseException ; 41 42 43 50 public class JMUnmarshallerHandlerImpl implements JMUnmarshallerHandler { 51 53 private static final int STATE_SIMPLE_ATOMIC = 1; 54 58 private static final int STATE_COMPLEX_CONTENT = 3; 59 64 private static final int STATE_GROUP = 4; 65 66 private final JMUnmarshaller unmarshaller; 67 private Locator locator; 68 private NamespaceSupport nss = new NamespaceSupport(); 69 private final List groupParsers = new ArrayList (); 70 private JMSAXGroupParser activeParser; 71 private int level; 72 private int endLevel; 73 private int state; 74 private final StringBuffer sb = new StringBuffer (); 75 private Observer observer; 76 private Object result; 77 78 public int getLevel() { return level; } 79 80 82 private boolean removeActiveParser() { 83 int size = groupParsers.size(); 84 groupParsers.remove(--size); 85 if (size == 0) { 86 return false; 87 } 88 activeParser = (JMSAXGroupParser) groupParsers.get(--size); 89 if (activeParser instanceof JMSAXElementParser) { 90 state = STATE_COMPLEX_CONTENT; 91 endLevel = ((JMSAXElementParser) activeParser).getEndLevel(); 92 } else { 93 state = STATE_GROUP; 94 } 95 return true; 96 } 97 98 101 public void setObserver(Observer pObserver) { 102 observer = pObserver; 103 } 104 105 108 public Observer getObserver() { 109 return observer; 110 } 111 112 115 public JMUnmarshallerHandlerImpl(JMUnmarshaller pUnmarshaller) { 116 unmarshaller = pUnmarshaller; 117 } 118 119 122 public JMUnmarshaller getJMUnmarshaller() { 123 return unmarshaller; 124 } 125 126 public void setDocumentLocator(Locator pLocator) { 127 locator = pLocator; 128 } 129 130 public void startDocument() throws SAXException { 131 } 132 133 public void endDocument() throws SAXException { 134 } 135 136 public void startPrefixMapping(String pPrefix, String pURI) throws SAXException { 137 nss.declarePrefix(pPrefix, pURI); 138 } 139 140 public void endPrefixMapping(String pPrefix) throws SAXException { 141 nss.undeclarePrefix(pPrefix); 142 } 143 144 147 public boolean testGroupParser(JMSAXGroupParser pParser, 148 String pNamespaceURI, String pLocalName, 149 String pQName, Attributes pAttrs) 150 throws SAXException { 151 groupParsers.add(pParser); 152 activeParser = pParser; 153 state = STATE_GROUP; 154 if (pParser.startElement(pNamespaceURI, pLocalName, pQName, pAttrs)) { 155 return true; 156 } else { 157 removeActiveParser(); 158 return false; 159 } 160 } 161 162 164 public void addElementParser(JMSAXElementParser pParser) { 165 endLevel = pParser.getEndLevel(); 166 groupParsers.add(pParser); 167 activeParser = pParser; 168 state = STATE_COMPLEX_CONTENT; 169 if (pParser.isAtomic()) { 170 sb.setLength(0); 171 } 172 } 173 174 public void startElement(String pNamespaceURI, String pLocalName, 175 String pQName, Attributes pAttrs) throws SAXException { 176 if (level++ == 0) { 177 JAXBContextImpl context = unmarshaller.getJAXBContextImpl(); 178 JMManager manager; 179 QName qName = new QName (pNamespaceURI, pLocalName); 180 try { 181 manager = context.getManager(qName); 182 } catch (JAXBException e) { 183 throw new SAXException ("Unable to instantiate manager for element " + qName, e); 184 } 185 Object o = manager.getElementS(); 186 JMSAXElementParser parser = manager.getHandler(); 187 parser.init(this, o, pNamespaceURI, pLocalName, 1); 188 parser.setAttributes(pAttrs); 189 groupParsers.clear(); 190 result = o; 191 addElementParser(parser); 192 } else { 193 if (state == STATE_COMPLEX_CONTENT || state == STATE_GROUP) { 194 for (;;) { 195 if (activeParser.startElement(pNamespaceURI, pLocalName, pQName, pAttrs)) { 196 return; 197 } 198 if (state == STATE_GROUP) { 199 if (removeActiveParser()) { 200 continue; 201 } 202 } 203 break; 204 } 205 } 206 QName qName = new QName (pNamespaceURI, pLocalName); 207 validationEvent(ValidationEvent.WARNING, 208 "Unexpected element: '" + qName + "'", 209 ValidationEvents.EVENT_UNEXPECTED_CHILD_ELEMENT, 210 null); 211 } 212 } 213 214 public void endElement(String pNamespaceURI, String pLocalName, String pQName) throws SAXException { 215 int lvl = level--; 216 switch (state) { 217 case STATE_GROUP: 218 while (state == STATE_GROUP) { 219 if (activeParser.isFinished()) { 220 removeActiveParser(); 221 } 222 } 223 if (state != STATE_COMPLEX_CONTENT) { 224 break; 225 } 226 case STATE_COMPLEX_CONTENT: 227 JMSAXElementParser elementParser = (JMSAXElementParser) activeParser; 228 if (lvl != endLevel) { 229 if (endLevel > lvl) { 230 validationEvent(ValidationEvent.ERROR, 231 "Premature endElement: " + new QName (pNamespaceURI, pLocalName), 232 ValidationEvents.EVENT_PREMATURE_END_ELEMENT, 233 null); 234 while (endLevel > lvl) { 235 terminateComplexType(pNamespaceURI, pLocalName, pQName, 236 elementParser); 237 } 238 } else { 239 throw new IllegalStateException ("Expected level " + endLevel 240 + ", got " + lvl); 241 } 242 } 243 if (elementParser.isAtomic()) { 244 elementParser.endElement(pNamespaceURI, pLocalName, pQName, sb.toString()); 245 } 246 if (pNamespaceURI.equals(elementParser.getNamespaceURI()) && 247 pLocalName.equals(elementParser.getLocalName())) { 248 if (activeParser.isFinished()) { 249 terminateComplexType(pNamespaceURI, pLocalName, pQName, 250 elementParser); 251 return; 252 } 253 } 254 break; 255 case STATE_SIMPLE_ATOMIC: { 256 String s = sb.toString(); 257 resetAtomicState(); 258 activeParser.endElement(pNamespaceURI, pLocalName, pQName, s); 259 return; 260 } 261 default: 262 throw new IllegalStateException ("Invalid state: " + state); 263 } 264 QName qName = new QName (pNamespaceURI, pLocalName); 265 validationEvent(ValidationEvent.WARNING, 266 "Unexpected end element: '" + qName + "'", 267 ValidationEvents.EVENT_PREMATURE_END_ELEMENT, 268 null); 269 } 270 271 private void terminateComplexType(String pNamespaceURI, String pLocalName, String pQName, 272 JMSAXElementParser elementParser) throws SAXException { 273 if (removeActiveParser()) { 274 activeParser.endElement(pNamespaceURI, pLocalName, pQName, elementParser.result); 275 } else { 276 if (observer != null) { 277 observer.notify(result); 278 } 279 } 280 } 281 282 public void characters(char[] pChars, int pOffset, int pLen) throws SAXException { 283 switch (state) { 284 case STATE_SIMPLE_ATOMIC: 285 sb.append(pChars, pOffset, pLen); 286 return; 287 case STATE_COMPLEX_CONTENT: 288 if (((JMSAXElementParser) activeParser).isAtomic()) { 289 sb.append(pChars, pOffset, pLen); 290 return; 291 } 292 case STATE_GROUP: 294 activeParser.addText(pChars, pOffset, pLen); 295 break; 296 default: 297 throw new IllegalStateException ("Invalid state: " + state); 298 } 299 } 300 301 public void ignorableWhitespace(char[] pChars, int pStart, int pLen) throws SAXException { 302 characters(pChars, pStart, pLen); 303 } 304 305 public void processingInstruction(String pTarget, String pData) throws SAXException { 306 validationEvent(ValidationEvent.WARNING, 307 "Don't know how to handle processing instructions.", 308 ValidationEvents.EVENT_PROCESSING_INSTRUCTION, 309 null); 310 } 311 312 314 public void parseConversionEvent(String pMsg, Exception pException) throws SAXException { 315 ParseConversionEventImpl event = new ParseConversionEventImpl(ValidationEvent.FATAL_ERROR, pMsg, null); 316 handleEvent(event, pException); 317 } 318 319 321 public void validationEvent(int pSeverity, String pMsg, String pErrorCode, 322 Exception pException) throws SAXException { 323 org.apache.ws.jaxme.impl.ValidationEventImpl event = new org.apache.ws.jaxme.impl.ValidationEventImpl(pSeverity, pMsg, null); 324 event.setErrorCode(pErrorCode); 325 handleEvent(event, pException); 326 } 327 328 private void handleEvent(ValidationEventImpl pEvent, Exception pException) throws SAXException { 329 if (locator != null) { 330 pEvent.setLocator(new ValidationEventLocatorImpl(locator)); 331 } 332 if (pException != null) { 333 pEvent.setLinkedException(pException); 334 } 335 ValidationEventHandler eventHandler; 336 try { 337 eventHandler = unmarshaller.getEventHandler(); 338 } catch (JAXBException e) { 339 throw new SAXException (e); 340 } 341 if (eventHandler == null || !eventHandler.handleEvent(pEvent)) { 342 String msg = pEvent.getMessage(); 343 if (pEvent instanceof org.apache.ws.jaxme.impl.ValidationEventImpl) { 344 String errorCode = ((org.apache.ws.jaxme.impl.ValidationEventImpl) pEvent).getErrorCode(); 345 if (errorCode != null) { 346 msg = errorCode + ": " + msg; 347 } 348 } 349 throw new SAXParseException (msg, locator, pException); 350 } 351 } 352 353 public void skippedEntity(String pName) throws SAXException { 354 validationEvent(ValidationEvent.WARNING, 355 "Don't know how to handle skipped entities.", 356 ValidationEvents.EVENT_SKIPPED_ENTITY, 357 null); 358 } 359 360 public Object getResult() throws JAXBException, IllegalStateException { 361 if (groupParsers.size() > 0 || result == null) { 362 throw new IllegalStateException ("Parsing the element is not yet finished."); 363 } 364 return result; 365 } 366 367 public NamespaceSupport getNamespaceSupport() { 368 return nss; 369 } 370 371 public Locator getDocumentLocator() { 372 return locator; 373 } 374 375 public DatatypeConverterInterface getDatatypeConverter() { 376 return unmarshaller.getDatatypeConverter(); 377 } 378 379 381 public void addSimpleAtomicState() { 382 activeParser = null; 383 sb.setLength(0); 384 state = STATE_SIMPLE_ATOMIC; 385 } 386 387 389 private void resetAtomicState() { 390 activeParser = (JMSAXGroupParser) groupParsers.get(groupParsers.size()-1); 391 if (activeParser instanceof JMSAXElementParser) { 392 state = STATE_COMPLEX_CONTENT; 393 } else { 394 state = STATE_GROUP; 395 } 396 } 397 } 398 | Popular Tags |