All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ws.jaxme.impl.JMUnmarshallerHandlerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2003,2004  The Apache Software Foundation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.

 */
package org.apache.ws.jaxme.impl;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.DatatypeConverterInterface;
import javax.xml.bind.JAXBException;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.helpers.ParseConversionEventImpl;
import javax.xml.bind.helpers.ValidationEventImpl;
import javax.xml.bind.helpers.ValidationEventLocatorImpl;
import javax.xml.namespace.QName;

import org.apache.ws.jaxme.JMManager;
import org.apache.ws.jaxme.JMUnmarshaller;
import org.apache.ws.jaxme.JMUnmarshallerHandler;
import org.apache.ws.jaxme.Observer;
import org.apache.ws.jaxme.ValidationEvents;
import org.apache.ws.jaxme.util.NamespaceSupport;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/** 

Implementation of a JMUnmarshallerHandler; the * UnmarshallerHandler receives SAX events which he silently * discards, as long as the first startElement * event is seen. Depending on namespace URI and local name, * the Unmarshallerhandler creates a new instance of JMHandler * and from now on forwards all SAX events to the JMHandler.

*/ public class JMUnmarshallerHandlerImpl implements JMUnmarshallerHandler { /** State for parsing a simple, atomic element. */ private static final int STATE_SIMPLE_ATOMIC = 1; /** State for parsing a complex element. The outer * {@link JMSAXGroupParser} will always be parsing * a complex element. */ private static final int STATE_COMPLEX_CONTENT = 3; /** State for parsing an anonymous group. This is * mostly comparable to parsing a complex element, * except that the group doesn't have an outer * start and end element. */ private static final int STATE_GROUP = 4; private final JMUnmarshaller unmarshaller; private Locator locator; private NamespaceSupport nss = new NamespaceSupport(); private final List groupParsers = new ArrayList(); private JMSAXGroupParser activeParser; private int level; private int endLevel; private int state; private final StringBuffer sb = new StringBuffer(); private Observer observer; private Object result; public int getLevel() { return level; } /** Removes the currently active parser from the stack. */ private boolean removeActiveParser() { int size = groupParsers.size(); groupParsers.remove(--size); if (size == 0) { return false; } activeParser = (JMSAXGroupParser) groupParsers.get(--size); if (activeParser instanceof JMSAXElementParser) { state = STATE_COMPLEX_CONTENT; endLevel = ((JMSAXElementParser) activeParser).getEndLevel(); } else { state = STATE_GROUP; } return true; } /** Sets an observer, which will be notified, when the element has * been parsed. */ public void setObserver(Observer pObserver) { observer = pObserver; } /** Returns the observer, which will be notified, when the element has * been parsed. */ public Observer getObserver() { return observer; } /** Creates a new instance, controlled by the given * {@link JMUnmarshaller}. */ public JMUnmarshallerHandlerImpl(JMUnmarshaller pUnmarshaller) { unmarshaller = pUnmarshaller; } /** Returns the {@link JMUnmarshaller}, which created this * handler. */ public JMUnmarshaller getJMUnmarshaller() { return unmarshaller; } public void setDocumentLocator(Locator pLocator) { locator = pLocator; } public void startDocument() throws SAXException { } public void endDocument() throws SAXException { } public void startPrefixMapping(String pPrefix, String pURI) throws SAXException { nss.declarePrefix(pPrefix, pURI); } public void endPrefixMapping(String pPrefix) throws SAXException { nss.undeclarePrefix(pPrefix); } /** Tests, whether the group parser accepts the element. * If so, adds the group parser to the stack. */ public boolean testGroupParser(JMSAXGroupParser pParser, String pNamespaceURI, String pLocalName, String pQName, Attributes pAttrs) throws SAXException { groupParsers.add(pParser); activeParser = pParser; state = STATE_GROUP; if (pParser.startElement(pNamespaceURI, pLocalName, pQName, pAttrs)) { return true; } else { removeActiveParser(); return false; } } /** Adds a parser for an nested element to the stack of parsers. */ public void addElementParser(JMSAXElementParser pParser) { endLevel = pParser.getEndLevel(); groupParsers.add(pParser); activeParser = pParser; state = STATE_COMPLEX_CONTENT; if (pParser.isAtomic()) { sb.setLength(0); } } public void startElement(String pNamespaceURI, String pLocalName, String pQName, Attributes pAttrs) throws SAXException { if (level++ == 0) { JAXBContextImpl context = unmarshaller.getJAXBContextImpl(); JMManager manager; QName qName = new QName(pNamespaceURI, pLocalName); try { manager = context.getManager(qName); } catch (JAXBException e) { throw new SAXException("Unable to instantiate manager for element " + qName, e); } Object o = manager.getElementS(); JMSAXElementParser parser = manager.getHandler(); parser.init(this, o, pNamespaceURI, pLocalName, 1); parser.setAttributes(pAttrs); groupParsers.clear(); result = o; addElementParser(parser); } else { if (state == STATE_COMPLEX_CONTENT || state == STATE_GROUP) { for (;;) { if (activeParser.startElement(pNamespaceURI, pLocalName, pQName, pAttrs)) { return; } if (state == STATE_GROUP) { if (removeActiveParser()) { continue; } } break; } } QName qName = new QName(pNamespaceURI, pLocalName); validationEvent(ValidationEvent.WARNING, "Unexpected element: '" + qName + "'", ValidationEvents.EVENT_UNEXPECTED_CHILD_ELEMENT, null); } } public void endElement(String pNamespaceURI, String pLocalName, String pQName) throws SAXException { int lvl = level--; switch (state) { case STATE_GROUP: while (state == STATE_GROUP) { if (activeParser.isFinished()) { removeActiveParser(); } } if (state != STATE_COMPLEX_CONTENT) { break; } case STATE_COMPLEX_CONTENT: JMSAXElementParser elementParser = (JMSAXElementParser) activeParser; if (lvl != endLevel) { if (endLevel > lvl) { validationEvent(ValidationEvent.ERROR, "Premature endElement: " + new QName(pNamespaceURI, pLocalName), ValidationEvents.EVENT_PREMATURE_END_ELEMENT, null); while (endLevel > lvl) { terminateComplexType(pNamespaceURI, pLocalName, pQName, elementParser); } } else { throw new IllegalStateException("Expected level " + endLevel + ", got " + lvl); } } if (elementParser.isAtomic()) { elementParser.endElement(pNamespaceURI, pLocalName, pQName, sb.toString()); } if (pNamespaceURI.equals(elementParser.getNamespaceURI()) && pLocalName.equals(elementParser.getLocalName())) { if (activeParser.isFinished()) { terminateComplexType(pNamespaceURI, pLocalName, pQName, elementParser); return; } } break; case STATE_SIMPLE_ATOMIC: { String s = sb.toString(); resetAtomicState(); activeParser.endElement(pNamespaceURI, pLocalName, pQName, s); return; } default: throw new IllegalStateException("Invalid state: " + state); } QName qName = new QName(pNamespaceURI, pLocalName); validationEvent(ValidationEvent.WARNING, "Unexpected end element: '" + qName + "'", ValidationEvents.EVENT_PREMATURE_END_ELEMENT, null); } private void terminateComplexType(String pNamespaceURI, String pLocalName, String pQName, JMSAXElementParser elementParser) throws SAXException { if (removeActiveParser()) { activeParser.endElement(pNamespaceURI, pLocalName, pQName, elementParser.result); } else { if (observer != null) { observer.notify(result); } } } public void characters(char[] pChars, int pOffset, int pLen) throws SAXException { switch (state) { case STATE_SIMPLE_ATOMIC: sb.append(pChars, pOffset, pLen); return; case STATE_COMPLEX_CONTENT: if (((JMSAXElementParser) activeParser).isAtomic()) { sb.append(pChars, pOffset, pLen); return; } // Fall through case STATE_GROUP: activeParser.addText(pChars, pOffset, pLen); break; default: throw new IllegalStateException("Invalid state: " + state); } } public void ignorableWhitespace(char[] pChars, int pStart, int pLen) throws SAXException { characters(pChars, pStart, pLen); } public void processingInstruction(String pTarget, String pData) throws SAXException { validationEvent(ValidationEvent.WARNING, "Don't know how to handle processing instructions.", ValidationEvents.EVENT_PROCESSING_INSTRUCTION, null); } /** Posts a {@link javax.xml.bind.ParseConversionEvent}. */ public void parseConversionEvent(String pMsg, Exception pException) throws SAXException { ParseConversionEventImpl event = new ParseConversionEventImpl(ValidationEvent.FATAL_ERROR, pMsg, null); handleEvent(event, pException); } /** Posts a {@link ValidationEvent}. */ public void validationEvent(int pSeverity, String pMsg, String pErrorCode, Exception pException) throws SAXException { org.apache.ws.jaxme.impl.ValidationEventImpl event = new org.apache.ws.jaxme.impl.ValidationEventImpl(pSeverity, pMsg, null); event.setErrorCode(pErrorCode); handleEvent(event, pException); } private void handleEvent(ValidationEventImpl pEvent, Exception pException) throws SAXException { if (locator != null) { pEvent.setLocator(new ValidationEventLocatorImpl(locator)); } if (pException != null) { pEvent.setLinkedException(pException); } ValidationEventHandler eventHandler; try { eventHandler = unmarshaller.getEventHandler(); } catch (JAXBException e) { throw new SAXException(e); } if (eventHandler == null || !eventHandler.handleEvent(pEvent)) { String msg = pEvent.getMessage(); if (pEvent instanceof org.apache.ws.jaxme.impl.ValidationEventImpl) { String errorCode = ((org.apache.ws.jaxme.impl.ValidationEventImpl) pEvent).getErrorCode(); if (errorCode != null) { msg = errorCode + ": " + msg; } } throw new SAXParseException(msg, locator, pException); } } public void skippedEntity(String pName) throws SAXException { validationEvent(ValidationEvent.WARNING, "Don't know how to handle skipped entities.", ValidationEvents.EVENT_SKIPPED_ENTITY, null); } public Object getResult() throws JAXBException, IllegalStateException { if (groupParsers.size() > 0 || result == null) { throw new IllegalStateException("Parsing the element is not yet finished."); } return result; } public NamespaceSupport getNamespaceSupport() { return nss; } public Locator getDocumentLocator() { return locator; } public DatatypeConverterInterface getDatatypeConverter() { return unmarshaller.getDatatypeConverter(); } /** Indicates, that the handler is parsing a simple, atomic element. */ public void addSimpleAtomicState() { activeParser = null; sb.setLength(0); state = STATE_SIMPLE_ATOMIC; } /** Restores the state after parsing an atomic element. */ private void resetAtomicState() { activeParser = (JMSAXGroupParser) groupParsers.get(groupParsers.size()-1); if (activeParser instanceof JMSAXElementParser) { state = STATE_COMPLEX_CONTENT; } else { state = STATE_GROUP; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy