//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v1.0.6-b27-fcs
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2012.06.11 at 10:34:16 AM PDT
//
package com.sun.identity.wsfederation.jaxb.entityconfig.impl.runtime;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.xml.bind.JAXBException;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.helpers.NotIdentifiableEventImpl;
import javax.xml.bind.helpers.ValidationEventLocatorImpl;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import com.sun.xml.bind.JAXBAssertionError;
import com.sun.xml.bind.JAXBObject;
import com.sun.xml.bind.marshaller.IdentifiableObject;
import com.sun.xml.bind.marshaller.Messages;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
import com.sun.xml.bind.serializer.AbortSerializationException;
import com.sun.xml.bind.serializer.Util;
/**
* XMLSerializer that produces SAX2 events.
*
* To marshal an object, create an instance of SAXMarshaller
* and call the serializeElements method of the XMLSerializable
* object that you want to marshal.
*
* @author Kohsuke Kawaguchi
*/
public class SAXMarshaller implements XMLSerializer
{
/**
* "Attributes" object that is passed to the startElement event.
* One object is reused throughout the marshalling.
*/
private final AttributesImpl attributes = new AttributesImpl();
/** This object receives SAX2 events generated from the marshaller. */
private final ContentHandler writer;
/** Marshaller object to which this object belongs. */
private final MarshallerImpl owner;
/** Objects referenced through IDREF. */
private final Set idReferencedObjects = new HashSet();
/** Objects with ID. */
private final Set objectsWithId = new HashSet();
/** Object currently marshalling itself. */
private JAXBObject currentTarget;
/**
* Creates a marshalling context by designating the ContentHandler
* that receives generated SAX2 events.
*/
public SAXMarshaller( ContentHandler _writer, NamespacePrefixMapper prefixMapper, MarshallerImpl _owner ) {
this.writer = _writer;
this.owner = _owner;
this.nsContext = new NamespaceContextImpl(
prefixMapper!=null?prefixMapper:defaultNamespacePrefixMapper);
}
/** namespace context. */
private final NamespaceContextImpl nsContext;
public NamespaceContext2 getNamespaceContext() { return nsContext; }
//
//
// name stack
//
//
/** Element name stack implemented as an array of (uri,local) pairs. */
private String[] elementStack = new String[16];;
private int elementLen=0;
private void pushElement( String uri, String local ) {
if(elementStack.length==elementLen) {
// reallocate buffer
String[] buf = new String[elementStack.length*2];
System.arraycopy( elementStack, 0, buf, 0, elementStack.length );
elementStack = buf;
}
elementStack[elementLen++] = uri;
elementStack[elementLen++] = local;
}
private void popElement() { elementLen-=2; }
private String getCurrentElementUri() { return elementStack[elementLen-2]; }
private String getCurrentElementLocal() { return elementStack[elementLen-1]; }
/**
* Starts marshalling of an element.
* Calling this method will push the internal state into the
* internal stack.
*/
public void startElement( String uri, String local ) throws SAXException {
boolean isRoot = false;
String suggestion = null;
if( elementLen==0 ) {
isRoot = true;
// this is the root element. suggest this as the default namespace
suggestion = "";
}
writePendingText();
nsContext.startElement();
pushElement(uri,local); // memorize element name
// declare this uri
nsContext.declareNamespace(uri,suggestion,false);
// if this is the root element, declare user-specified namespace URIs.
if( isRoot ) {
// work defensively. we are calling an user-defined method.
String[] uris = nsContext.getNamespacePrefixMapper().getPreDeclaredNamespaceUris();
if( uris!=null ) {
for( int i=0; i<uris.length; i++ ) {
if( uris[i]!=null )
nsContext.declareNamespace(uris[i],null,false);
}
}
}
}
private final PrefixCallback startPrefixCallback = new PrefixCallback() {
public void onPrefixMapping( String prefix, String nsUri ) throws SAXException {
writer.startPrefixMapping(prefix,nsUri);
}
};
private final PrefixCallback endPrefixCallback = new PrefixCallback() {
public void onPrefixMapping( String prefix, String nsUri ) throws SAXException {
writer.endPrefixMapping(prefix);
}
};
public void endNamespaceDecls() throws SAXException {
nsContext.endNamespaceDecls();
}
/**
* Switches to the "marshal child texts/elements" mode.
* This method has to be called after the 1st pass is completed.
*/
public void endAttributes() throws SAXException {
// calculate QName of the element
String uri = getCurrentElementUri();
String local = getCurrentElementLocal();
String prefix = nsContext.getPrefix(uri);
_assert(prefix!=null); // since we've declared it, it should be available
String qname;
if(prefix.length()!=0 )
qname = prefix+':'+local;
else
qname = local;
// fire startPrefixMapping events
nsContext.iterateDeclaredPrefixes(startPrefixCallback);
// fire the startElement event
writer.startElement( uri, local, qname, attributes );
// reset attributes
attributes.clear();
// prepare to collect texts
textBuf.setLength(0);
}
/**
* Ends marshalling of an element.
* Pops the internal stack.
*/
public void endElement() throws SAXException {
writePendingText();
String uri = getCurrentElementUri();
String local = getCurrentElementLocal();
String prefix = nsContext.getPrefix(uri);
_assert(prefix!=null); // we've declared it earlier.
String qname;
if(prefix.length()!=0)
qname = prefix+':'+local;
else
qname = local;
writer.endElement( uri, local, qname );
// pop namespace bindings and
// fire endPrefixMapping events
nsContext.iterateDeclaredPrefixes(endPrefixCallback);
popElement();
// prepare to collect texts
textBuf.setLength(0);
nsContext.endElement();
}
/** Buffer for collecting characters. */
private final StringBuffer textBuf = new StringBuffer();
/**
* Marshalls text.
*
* <p>
* This method can be called (i) after the startAttribute method
* and (ii) before the endAttribute method, to marshal attribute values.
* If the method is called more than once, those texts are considered
* as separated by whitespaces. For example,
*
* <pre>
* c.startAttribute();
* c.text("abc");
* c.text("def");
* c.endAttribute("","foo");
* </pre>
*
* will generate foo="abc def".
*
* <p>
* Similarly, this method can be called after the endAttributes
* method to marshal texts inside elements. The same rule about
* multiple invokations apply to this case, too. For example,
*
* <pre>
* c.startElement("","foo");
* c.endAttributes();
* c.text("abc");
* c.text("def");
* c.startElement("","bar");
* c.endAttributes();
* c.endElement();
* c.text("ghi");
* c.endElement();
* </pre>
*
* will generate <code>&lt;foo>abc def&lt;bar/>ghi&lt;/foo></code>.
*/
public void text( String text, String fieldName ) throws SAXException {
// If the assertion fails, it must be a bug of xjc.
// right now, we are not expecting the text method to be called.
if(text==null) {
reportError(Util.createMissingObjectError(currentTarget,fieldName));
return;
}
if(textBuf.length()!=0)
textBuf.append(' ');
textBuf.append(text);
}
/**
* Writes pending text (characters inside elements) to the writer.
* This method is called from startElement and endElement.
*/
private void writePendingText() throws SAXException {
// assert(textBuf!=null);
int len = textBuf.length();
if(len!=0)
writer.characters( textBuf.toString().toCharArray(), 0, len );
}
/**
* Starts marshalling of an attribute.
*
* The marshalling of an attribute will be done by
* <ol>
* <li>call the startAttribute method
* <li>call the text method (several times if necessary)
* <li>call the endAttribute method
* </ol>
*
* No two attributes can be marshalled at the same time.
* Note that the whole attribute marshalling must be happened
* after the startElement method and before the endAttributes method.
*/
public void startAttribute( String uri, String local ) {
// initialize the buffer to collect attribute value
textBuf.setLength(0);
// remember the attribute name. We'll use this value later.
this.attNamespaceUri = uri;
this.attLocalName = local;
}
// used to keep attribute names until the endAttribute method is called.
private String attNamespaceUri;
private String attLocalName;
public void endAttribute() {
// use CDATA as the attribute type. This preserves
// successive processors to collapse whitespaces.
// (we cannot prevent characters like #xD to be replaced to
// #x20, though).
//
// strictly speaking, attribute value normalization should be
// provessed by XML parser, so it's unclear whether XML writer
// uses this type value.
//
// in any way, CDATA type is the safest choice here.
String qname;
if(attNamespaceUri.length()==0) {
// default namespace. don't need prefix
qname = attLocalName;
} else {
qname = nsContext.declareNamespace(attNamespaceUri,null,true)+':'+attLocalName;
}
attributes.addAttribute(attNamespaceUri,attLocalName,qname,"CDATA",textBuf.toString());
}
public String onID( IdentifiableObject owner, String value ) throws SAXException {
objectsWithId.add(owner);
return value;
}
public String onIDREF( IdentifiableObject obj ) throws SAXException {
idReferencedObjects.add(obj);
String id = obj.____jaxb____getId();
if(id==null) {
reportError( new NotIdentifiableEventImpl(
ValidationEvent.ERROR,
Messages.format(Messages.ERR_NOT_IDENTIFIABLE),
new ValidationEventLocatorImpl(obj) ) );
}
return id;
}
void reconcileID() throws AbortSerializationException {
// find objects that were not a part of the object graph
idReferencedObjects.removeAll(objectsWithId);
for( Iterator itr=idReferencedObjects.iterator(); itr.hasNext(); ) {
IdentifiableObject o = (IdentifiableObject)itr.next();
reportError( new NotIdentifiableEventImpl(
ValidationEvent.ERROR,
Messages.format(Messages.ERR_DANGLING_IDREF,o.____jaxb____getId()),
new ValidationEventLocatorImpl(o) ) );
}
// clear the garbage
idReferencedObjects.clear();
objectsWithId.clear();
}
public void childAsBody( JAXBObject o, String fieldName ) throws SAXException {
if(o==null) {
// if null is passed, it usually means that the content tree object
// doesn't have some of its required property.
reportMissingObjectError(fieldName);
// as a marshaller, we should be generous, so we'll continue to marshal
// this document by skipping this missing object.
return;
}
JAXBObject oldTarget = currentTarget;
currentTarget = o;
owner.context.getGrammarInfo().castToXMLSerializable(o).serializeBody(this);
currentTarget = oldTarget;
}
public void childAsAttributes( JAXBObject o, String fieldName ) throws SAXException {
if(o==null) {
reportMissingObjectError(fieldName);
return;
}
JAXBObject oldTarget = currentTarget;
currentTarget = o;
owner.context.getGrammarInfo().castToXMLSerializable(o).serializeAttributes(this);
currentTarget = oldTarget;
}
public void childAsURIs( JAXBObject o, String fieldName ) throws SAXException {
if(o==null) {
reportMissingObjectError(fieldName);
return;
}
JAXBObject oldTarget = currentTarget;
currentTarget = o;
owner.context.getGrammarInfo().castToXMLSerializable(o).serializeURIs(this);
currentTarget = oldTarget;
}
public void reportError( ValidationEvent ve ) throws AbortSerializationException {
ValidationEventHandler handler;
try {
handler = owner.getEventHandler();
} catch( JAXBException e ) {
throw new AbortSerializationException(e);
}
if(!handler.handleEvent(ve)) {
if(ve.getLinkedException() instanceof Exception)
throw new AbortSerializationException((Exception)ve.getLinkedException());
else
throw new AbortSerializationException(ve.getMessage());
}
}
public void reportMissingObjectError(String fieldName) throws SAXException {
reportError(Util.createMissingObjectError(currentTarget,fieldName));
}
private static void _assert( boolean b ) {
if(!b)
throw new JAXBAssertionError();
}
/**
* Default {@link NamespacePrefixMapper} implementation used when
* it is not specified by the user.
*/
private static NamespacePrefixMapper defaultNamespacePrefixMapper = new NamespacePrefixMapper() {
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if( namespaceUri.equals("http://www.w3.org/2001/XMLSchema-instance") )
return "xsi";
return suggestion;
}
};
}