org.eclipse.persistence.internal.oxm.record.deferred.DeferredContentHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 180e602
/*******************************************************************************
* Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.internal.oxm.record.deferred;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.internal.oxm.record.ExtendedContentHandler;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.oxm.record.XMLReader;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
/**
* Purpose: ContentHandler to store events until we know if we are dealing with a simple, complex or empty element.
*
Responsibilities:
* - Store events until will know if the element is simple, complex or empty
*
- Return control to the original unmarshalRecord
*
*/
public abstract class DeferredContentHandler implements ExtendedContentHandler, LexicalHandler {
private int levelIndex;
private List events;
private UnmarshalRecord parent;
private boolean startOccurred;
private boolean charactersOccurred;
private boolean attributesOccurred;
public DeferredContentHandler(UnmarshalRecord parentRecord) {
levelIndex = 0;
events = new ArrayList();
this.parent = parentRecord;
}
@Override
public void setNil(boolean isNil) {}
protected abstract void processEmptyElement() throws SAXException;
protected abstract void processComplexElement() throws SAXException;
protected abstract void processSimpleElement() throws SAXException;
protected void processEmptyElementWithAttributes() throws SAXException {
processEmptyElement();
}
protected void executeEvents(UnmarshalRecord unmarshalRecord) throws SAXException {
for (int i = 0; i < events.size(); i++) {
SAXEvent nextEvent = events.get(i);
nextEvent.processEvent(unmarshalRecord);
}
XMLReader parentXMLReader = parent.getXMLReader();
if (parentXMLReader.getContentHandler().equals(this)) {
parentXMLReader.setContentHandler(unmarshalRecord);
parentXMLReader.setLexicalHandler(unmarshalRecord);
}
}
public void startPrefixMapping(String prefix, String uri) throws SAXException {
StartPrefixMappingEvent event = new StartPrefixMappingEvent(prefix, uri);
events.add(event);
}
public void endPrefixMapping(String prefix) throws SAXException {
EndPrefixMappingEvent event = new EndPrefixMappingEvent(prefix);
events.add(event);
}
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
levelIndex++;
//Copy attributes because some parsers reuse the Attributes object across start element events
Attributes copiedAttrs = buildAttributeList(atts);
StartElementEvent event = new StartElementEvent(uri, localName, qName, copiedAttrs);
events.add(event);
if (startOccurred) {
//we know it's complex and non-null
processComplexElement();
return;
}
startOccurred = true;
}
protected AttributeList buildAttributeList(Attributes attrs) throws SAXException {
int attrsLength = attrs.getLength();
AttributeList attributes = new AttributeList(attrsLength);
for (int i = 0; i < attrsLength; i++) {
String qName = attrs.getQName(i);
String uri = attrs.getURI(i);
attributes.addAttribute(attrs.getLocalName(i), qName, uri, attrs.getType(i), attrs.getValue(i), i);
if(!javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(uri) && (null != qName && !qName.startsWith(javax.xml.XMLConstants.XMLNS_ATTRIBUTE))) {
attributesOccurred = true;
}
}
return attributes;
}
public void endElement(String uri, String localName, String qName) throws SAXException {
levelIndex--;
EndElementEvent event = new EndElementEvent(uri, localName, qName);
events.add(event);
if (charactersOccurred) {
//we know it is a simple element
processSimpleElement();
} else if(startOccurred){
//we know it is an empty element
if(attributesOccurred) {
processEmptyElementWithAttributes();
} else {
processEmptyElement();
}
}
if ((levelIndex == 0) && (parent != null)) {
XMLReader xmlReader = parent.getXMLReader();
xmlReader.setContentHandler(parent);
xmlReader.setLexicalHandler(parent);
}
}
public void setDocumentLocator(Locator locator) {
DocumentLocatorEvent event = new DocumentLocatorEvent(locator);
events.add(event);
}
public void startDocument() throws SAXException {
StartDocumentEvent event = new StartDocumentEvent();
events.add(event);
}
public void endDocument() throws SAXException {
EndDocumentEvent event = new EndDocumentEvent();
events.add(event);
}
public void characters(char[] ch, int start, int length) throws SAXException {
charactersOccurred = true;
CharactersEvent event = new CharactersEvent(ch, start, length);
events.add(event);
}
public void characters(CharSequence characters) {
charactersOccurred = true;
CharactersEvent event = new CharactersEvent(characters);
events.add(event);
}
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
IgnorableWhitespaceEvent event = new IgnorableWhitespaceEvent(ch, start, length);
events.add(event);
}
public void processingInstruction(String target, String data) throws SAXException {
ProcessingInstructionEvent event = new ProcessingInstructionEvent(target, data);
events.add(event);
}
public void skippedEntity(String name) throws SAXException {
SkippedEntityEvent event = new SkippedEntityEvent(name);
events.add(event);
}
public void startDTD(String name, String publicId, String systemId) throws SAXException {
StartDTDEvent event = new StartDTDEvent(name, publicId, systemId);
events.add(event);
}
public void endDTD() throws SAXException {
EndDTDEvent event = new EndDTDEvent();
events.add(event);
}
public void startEntity(String name) throws SAXException {
StartEntityEvent event = new StartEntityEvent(name);
events.add(event);
}
public void endEntity(String name) throws SAXException {
EndEntityEvent event = new EndEntityEvent(name);
events.add(event);
}
public void startCDATA() throws SAXException {
StartCDATAEvent event = new StartCDATAEvent();
events.add(event);
}
public void endCDATA() throws SAXException {
EndCDATAEvent event = new EndCDATAEvent();
events.add(event);
}
public void comment(char[] ch, int start, int length) throws SAXException {
CommentEvent event = new CommentEvent(ch, start, length);
events.add(event);
}
protected UnmarshalRecord getParent() {
return parent;
}
protected List getEvents() {
return events;
}
// Made static final for performance reasons.
/**
* Implementation of Attributes - used to pass along a given node's attributes
* to the startElement method of the reader's content handler.
*/
private static final class AttributeList implements org.xml.sax.Attributes {
private String[] localNames;
private String[] uris;
private String[] values;
private String[] types;
private ArrayList qNames;
public AttributeList(int size) {
qNames = new ArrayList(size);
localNames = new String[size];
uris = new String[size];
types= new String[size];
values = new String[size];
}
public void addAttribute(String localName, String qName, String uri, String type, String value, int index) {
qNames.add(index, qName);
localNames[index] = localName;
uris[index] = uri;
types[index] = type;
values[index] = value;
}
public String getQName(int index) {
return qNames.get(index);
}
public String getType(String namespaceUri, String localName) {
for(int i=0;i