String currentLoc = null;
if (path != null) {
_attributes.clear();
if (wrappers == null) {
wrappers = new SafeStack();
}
try {
while (path != null) {
String elemName = null;
int idx = path.indexOf('/');
if (idx > 0) {
elemName = path.substring(0, idx);
path = path.substring(idx+1);
}
else {
elemName = path;
path = null;
}
//-- save current location without namespace
//-- information for now.
if (currentLoc == null)
currentLoc = elemName;
else
currentLoc = currentLoc + "/" + elemName;
String elemQName = elemName;
if ((nsPrefix != null) && (nsPrefix.length() > 0)) {
elemQName = nsPrefix + ':' + elemName;
}
wrappers.push(new WrapperInfo(elemName, elemQName, currentLoc));
_attributes.clear();
if (nestedAttCount > 0) {
for (int na = 0; na < nestedAtts.length; na++) {
if (nestedAtts[na] == null) continue;
String tmpPath = nestedAtts[na].getLocationPath();
if (tmpPath.equals(currentLoc)) {
processAttribute(object, nestedAtts[na],_attributes);
nestedAtts[na] = null;
--nestedAttCount;
}
}
}
handler.startElement(nsURI, elemName, elemQName, _attributes);
}
}
catch(SAXException sx) {
throw new MarshalException(sx);
}
}
//-- </Wrapper>
char[] chars = null;
Class objType = obj.getClass();
if (objType.isArray() && (objType.getComponentType() == Byte.TYPE)) {
//-- handle base64/hexbinary content
final String schemaType = descriptor.getSchemaType();
if (HexDecoder.DATA_TYPE.equals(schemaType)) {
chars = new String(HexDecoder.encode((byte[]) obj)).toCharArray();
} else {
chars = Base64Encoder.encode((byte[]) obj);
}
} else {
//-- all other types
String str = obj.toString();
if ((str != null) && (str.length() > 0)) {
chars = str.toCharArray();
}
}
if ((chars != null) && (chars.length > 0)) {
try {
handler.characters(chars, 0, chars.length);
}
catch(org.xml.sax.SAXException sx) {
throw new MarshalException(sx);
}
}
}
}
//-- element references
else if (descriptor.isReference()) {
Object id = getObjectID(object);
if (id != null) {
char[] chars = id.toString().toCharArray();
try {
handler.characters(chars, 0, chars.length);
}
catch(org.xml.sax.SAXException sx) {
throw new MarshalException(sx);
}
}
}
// special case for byte[]
else if (byteArray) {
//-- Base64Encoding / HexBinary
String schemaType = descriptor.getSchemaType();
String componentType = descriptor.getComponentType();
char[] chars = new char[0];
if ((descriptor.isMultivalued() && HexDecoder.DATA_TYPE.equals(componentType)) ||
HexDecoder.DATA_TYPE.equals(schemaType)) {
chars = new String(HexDecoder.encode((byte[]) object)).toCharArray();
} else {
chars = Base64Encoder.encode((byte[]) object);
}
try {
handler.characters(chars, 0, chars.length);
} catch (org.xml.sax.SAXException sx) {
throw new MarshalException(sx);
}
}
/* special case for Strings and primitives */
else if (isPrimitive(_class)) {
char[] chars;
if (_class == java.math.BigDecimal.class) {
chars = convertBigDecimalToString(object).toCharArray();
} else {
chars = object.toString().toCharArray();
}
try {
handler.characters(chars,0,chars.length);
}
catch(org.xml.sax.SAXException sx) {
throw new MarshalException(sx);
}
}
else if (isEnum(_class)) {
char[] chars = object.toString().toCharArray();
try {
handler.characters(chars,0,chars.length);
}
catch(org.xml.sax.SAXException sx) {
throw new MarshalException(sx);
}
}
}
//---------------------------
//-- handle daughter elements
//---------------------------
if (isNil || descriptor.isReference()) {
descriptors = NO_FIELD_DESCRIPTORS;
}
else {
descriptors = classDesc.getElementDescriptors();
}
++depth;
//-- marshal elements
for (int i = firstNonNullIdx; i < descriptors.length; i++) {
XMLFieldDescriptor elemDescriptor = descriptors[i];
Object obj = null;
boolean nil = false;
//-- used previously cached value?
if ((i == firstNonNullIdx) && (firstNonNullValue != null)) {
obj = firstNonNullValue;
} else {
//-- obtain value from handler
try {
obj = elemDescriptor.getHandler().getValue(object);
} catch (IllegalStateException ise) {
LOG.warn("Error marshalling " + object, ise);
continue;
}
}
if (obj == null
|| (obj instanceof Enumeration && !((Enumeration) obj).hasMoreElements())) {
if (elemDescriptor.isNillable() && (elemDescriptor.isRequired())) {
nil = true;
} else {
continue;
}
}
//-- handle XML path
String path = elemDescriptor.getLocationPath();
String currentLoc = null;
//-- Wrapper/Location cleanup
if (wrappers != null) {
try {
while (!wrappers.empty()) {
WrapperInfo wInfo = (WrapperInfo)wrappers.peek();
if (path != null) {
if (wInfo.location.equals(path)) {
path = null;
break;
}
else if (path.startsWith(wInfo.location + "/")) {
path = path.substring(wInfo.location.length()+1);
currentLoc = wInfo.location;
break;
}
}
handler.endElement(nsURI, wInfo.localName, wInfo.qName);
wrappers.pop();
}
}
catch(SAXException sx) {
throw new MarshalException(sx);
}
}
if (path != null) {
_attributes.clear();
if (wrappers == null) {
wrappers = new SafeStack();
}
try {
while (path != null) {
String elemName = null;
int idx = path.indexOf('/');
if (idx > 0) {
elemName = path.substring(0, idx);
path = path.substring(idx+1);
}
else {
elemName = path;
path = null;
}
//-- save current location without namespace
//-- information for now.
if (currentLoc == null)
currentLoc = elemName;
else
currentLoc = currentLoc + "/" + elemName;
String elemQName = elemName;
if ((nsPrefix != null) && (nsPrefix.length() > 0)) {
elemQName = nsPrefix + ':' + elemName;
}
wrappers.push(new WrapperInfo(elemName, elemQName, currentLoc));
_attributes.clear();
if (nestedAttCount > 0) {
for (int na = 0; na < nestedAtts.length; na++) {
if (nestedAtts[na] == null) continue;
String tmpPath = nestedAtts[na].getLocationPath();
if (tmpPath.equals(currentLoc)) {
processAttribute(object, nestedAtts[na],_attributes);
nestedAtts[na] = null;
--nestedAttCount;
}
}
}
handler.startElement(nsURI, elemName, elemQName, _attributes);
}
}
catch(SAXException sx) {
throw new MarshalException(sx);
}
}
if (nil) {
obj = new NilObject(classDesc, elemDescriptor);
}
final Class type = obj.getClass();
MarshalState myState = mstate.createMarshalState(object, name);
myState.nestedAtts = nestedAtts;
myState.nestedAttCount = nestedAttCount;
//-- handle byte arrays
if (type.isArray() && (type.getComponentType() == Byte.TYPE)) {
marshal(obj, elemDescriptor, handler, myState);
} else if (type.isArray() && elemDescriptor.isDerivedFromXSList()) {
Object buffer = processXSListType(obj, elemDescriptor);
String elemName = elemDescriptor.getXMLName();
String elemQName = elemName;
if ((nsPrefix != null) && (nsPrefix.length() > 0)) {
elemQName = nsPrefix + ':' + elemName;
}
char[] chars = buffer.toString().toCharArray();
try {
handler.startElement(nsURI, elemName, elemQName, _attributes);
handler.characters(chars,0,chars.length);
handler.endElement(nsURI, elemName, elemQName);
}
catch(org.xml.sax.SAXException sx) {
throw new MarshalException(sx);
}
}
//-- handle all other collection types
else if (isCollection(type)) {
boolean processCollection = true;
if (_saveMapKeys) {
MapHandler mapHandler = MapHandlers.getHandler(type);
if (mapHandler != null) {
processCollection = false;
MapItem item = new MapItem();
Enumeration keys = mapHandler.keys(obj);
while (keys.hasMoreElements()) {
item.setKey(keys.nextElement());
item.setValue(mapHandler.get(obj, item.getKey()));
marshal(item, elemDescriptor, handler, myState);
}
}
}
if (processCollection) {
CollectionHandler colHandler = getCollectionHandler(type);
Enumeration enumeration = colHandler.elements(obj);
while (enumeration.hasMoreElements()) {
Object item = enumeration.nextElement();
if (item != null) {
marshal(item, elemDescriptor, handler, myState);
}
}
}
}
//-- otherwise just marshal object as is
else {
marshal(obj, elemDescriptor, handler, myState);
}
if (nestedAttCount > 0) {
nestedAttCount = myState.nestedAttCount;
}
}
//-- Wrapper/Location cleanup for elements
if (wrappers != null) {
try {
while (!wrappers.empty()) {
WrapperInfo wInfo = (WrapperInfo) wrappers.peek();
boolean popStack = true;
if (nestedAttCount > 0) {
for (int na = 0; na < nestedAtts.length; na++) {
// TODO[LL]: refactor to avoid check against null
if (nestedAtts[na] == null) continue;
String nestedAttributePath = nestedAtts[na].getLocationPath();
if (nestedAttributePath.startsWith(wInfo.location + "/")) {
popStack = false;
break;
}
}
}
if (popStack) {
handler.endElement(nsURI, wInfo.localName, wInfo.qName);
wrappers.pop();
} else {
break;
}
}
}
catch(SAXException sx) {
throw new MarshalException(sx);
}
}
// TODO: Handling additional attributes at the end causes elements to be marshalled in the wrong
// order when element 'text' is null, but their attribute value is not null. Can this be fixed
// to process element attributes even when the element text value is null?
if (wrappers != null && !wrappers.isEmpty()) {
dealWithNestedAttributesNested(object, handler, nsPrefix, nsURI,
nestedAttCount, nestedAtts, wrappers);
}
dealWithNestedAttributes(object, handler, nsPrefix, nsURI,
nestedAttCount, nestedAtts, new SafeStack());
//-- finish element
try {
if (!containerField) {
handler.endElement(nsURI, name, qName);