else {
descriptors = classDesc.getElementDescriptors();
}
++depth;
Stack wrappers = null;
//-- 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;
}
//-- obtain value from handler
else {
try {
obj = elemDescriptor.getHandler().getValue(object);
}
catch(IllegalStateException ise) {
continue;
}
}
if (obj == null) {
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 Stack();
}
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();
//-- handle byte arrays
if (type.isArray() && (type.getComponentType() == Byte.TYPE)) {
marshal(obj, elemDescriptor, handler);
}
//-- 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);
}
}
}
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);
}
}
}
}
//-- otherwise just marshal object as is
else marshal(obj, elemDescriptor, handler);
}
//-- Wrapper/Location cleanup for elements
if (wrappers != null) {
try {
while (!wrappers.empty()) {
WrapperInfo wInfo = (WrapperInfo)wrappers.pop();
handler.endElement(nsURI, wInfo.localName, wInfo.qName);
}
}
catch(SAXException sx) {
throw new MarshalException(sx);
}
}
//-- Handle any additional attribute locations that were
//-- not handled when dealing with wrapper elements
if (nestedAttCount > 0) {
if (wrappers == null) wrappers = new Stack();
for (int i = 0; i < nestedAtts.length; i++) {
if (nestedAtts[i] == null) continue;
String path = nestedAtts[i].getLocationPath();
//-- Make sure attribute has value before continuing
//-- We really could use a FieldHandler#hasValue()
//-- method (since sometimes getValue() methods may
//-- be expensive and we don't always want to call it
//-- multiple times)
if (nestedAtts[i].getHandler().getValue(object) == null) {
nestedAtts[i] = null;
-- nestedAttCount;
continue;
}
String currentLoc = null;
try {
while (path != null) {
int idx = path.indexOf('/');
String elemName = null;
if (idx > 0) {
elemName = path.substring(0,idx);
path = path.substring(idx+1);
}
else {
elemName = path;
path = null;
}
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, null));
_attributes.clear();
if (path == null) {
processAttribute(object, nestedAtts[i],_attributes);
nestedAtts[i] = null;
--nestedAttCount;
}
if (nestedAttCount > 0) {
for (int na = i+1; 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);
}
while (!wrappers.empty()) {
WrapperInfo wInfo = (WrapperInfo)wrappers.pop();
handler.endElement(nsURI, wInfo.localName, wInfo.qName);
}
} catch (Exception e) {
throw new MarshalException(e);
}