if (value == null)
throw new IOException(Messages.getMessage("cantDoNullArray00"));
MessageContext msgContext = context.getMessageContext();
SchemaVersion schema = SchemaVersion.SCHEMA_2001;
SOAPConstants soap = SOAPConstants.SOAP11_CONSTANTS;
if(msgContext != null) {
schema = msgContext.getSchemaVersion();
soap = msgContext.getSOAPConstants();
}
Class cls = value.getClass();
Collection list = null;
if (!cls.isArray()) {
if (!(value instanceof Collection)) {
throw new IOException(
Messages.getMessage("cantSerialize00", cls.getName()));
}
list = (Collection)value;
}
// Get the componentType of the array/list
Class componentType;
if (list == null) {
componentType = cls.getComponentType();
} else {
componentType = Object.class;
}
// Check to see if componentType is also an array.
// If so, set the componentType to the most nested non-array
// componentType. Increase the dims string by "[]"
// each time through the loop.
// Note from Rich Scheuerle:
// This won't handle Lists of Lists or
// arrays of Lists....only arrays of arrays.
String dims = "";
while (componentType.isArray()) {
componentType = componentType.getComponentType();
dims += "[]";
}
// Get the QName of the componentType.
// If not found, look at the super classes
QName componentQName = context.getQNameForClass(componentType);
if (componentQName == null) {
Class searchCls = componentType;
while(searchCls != null && componentQName == null) {
searchCls = searchCls.getSuperclass();
componentQName = context.getQNameForClass(searchCls);
}
if (componentQName != null) {
componentType = searchCls;
}
}
if (componentQName == null) {
throw new IOException(
Messages.getMessage("noType00", componentType.getName()));
}
String prefix = context.getPrefixForURI(componentQName.getNamespaceURI());
String compType = prefix + ":" + componentQName.getLocalPart();
int len = (list == null) ? Array.getLength(value) : list.size();
String arrayType = compType + dims + "[" + len + "]";
// Discover whether array can be serialized directly as a two-dimensional
// array (i.e. arrayType=int[2,3]) versus an array of arrays.
// Benefits:
// - Less text passed on the wire.
// - Easier to read wire format
// - Tests the deserialization of multi-dimensional arrays.
// Drawbacks:
// - Is not safe! It is possible that the arrays are multiply
// referenced. Transforming into a 2-dim array will cause the
// multi-referenced information to be lost. Plus there is no
// way to determine whether the arrays are multi-referenced.
// Thus the code is currently disabled (see enable2Dim below).
//
// Currently the support is ENABLED because it is necessary for
// interoperability (echo2DStringArray). It is 'safe' for now
// because Axis treats arrays as non multi-ref (see the note
// in SerializationContextImpl.isPrimitive(...) )
// More complicated processing is necessary for 3-dim arrays, etc.
//
int dim2Len = -1;
boolean enable2Dim = true; // Enabled 2-Dim processing
if (enable2Dim && !dims.equals("")) {
if (cls.isArray() && len > 0) {
boolean okay = true;
// Make sure all of the component arrays are the same size
for (int i=0; i < len && okay; i++) {
Object elementValue = Array.get(value, i);
if (elementValue == null)
okay = false;
else if (dim2Len < 0) {
dim2Len = Array.getLength(elementValue);
if (dim2Len <= 0) {
okay = false;
}
} else if (dim2Len != Array.getLength(elementValue)) {
okay = false;
}
}
// Update the arrayType to use mult-dim array encoding
if (okay) {
dims = dims.substring(0, dims.length()-2);
arrayType = compType + dims + "[" + len + "," + dim2Len + "]";
} else {
dim2Len = -1;
}
}
}
// Need to distinguish if this is array processing for an
// actual schema array or for a maxOccurs usage.
// For the maxOccurs case, the currentXMLType of the context is
// the same as the componentQName.
boolean maxOccursUsage = (msgContext != null && !msgContext.isEncoded()) &&
componentQName.equals(context.getCurrentXMLType());
if (!maxOccursUsage) {
AttributesImpl attrs;
if (attributes == null) {
attrs = new AttributesImpl();
} else if (attributes instanceof AttributesImpl) {
attrs = (AttributesImpl)attributes;
} else {
attrs = new AttributesImpl(attributes);
}
if (attrs.getIndex(soap.getEncodingURI(),
Constants.ATTR_ARRAY_TYPE) == -1) {
String encprefix =
context.getPrefixForURI(soap.getEncodingURI());
attrs.addAttribute(soap.getEncodingURI(),
Constants.ATTR_ARRAY_TYPE,
encprefix + ":arrayType",
"CDATA",
arrayType);
}