package org.jboss.axis.encoding.ser;
import org.jboss.axis.Constants;
import org.jboss.axis.MessageContext;
import org.jboss.axis.encoding.DeserializationContext;
import org.jboss.axis.encoding.Deserializer;
import org.jboss.axis.encoding.DeserializerImpl;
import org.jboss.axis.encoding.DeserializerTarget;
import org.jboss.axis.message.SOAPHandler;
import org.jboss.axis.soap.SOAPConstants;
import org.jboss.axis.utils.ClassUtils;
import org.jboss.axis.utils.JavaUtils;
import org.jboss.axis.utils.Messages;
import org.jboss.axis.wsdl.symbolTable.SchemaUtils;
import org.jboss.logging.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;
public class ArrayDeserializer extends DeserializerImpl
{
private static Logger log = Logger.getLogger(ArrayDeserializer.class.getName());
public QName arrayType = null;
public int curIndex = 0;
QName defaultItemType;
int length;
Class arrayClass = null;
ArrayList mDimLength = null; ArrayList mDimFactor = null; SOAPConstants soapConstants = SOAPConstants.SOAP11_CONSTANTS;
public void onStartElement(String namespace, String localName,
String prefix, Attributes attributes,
DeserializationContext context)
throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: ArrayDeserializer::startElement()");
}
MessageContext msgContext = context.getMessageContext();
if (msgContext != null)
{
soapConstants = msgContext.getSOAPConstants();
}
QName typeQName = context.getTypeFromAttributes(namespace,
localName,
attributes);
if (typeQName == null)
{
typeQName = getDefaultType();
}
if (typeQName != null &&
Constants.equals(Constants.SOAP_ARRAY, typeQName))
{
typeQName = null;
}
QName arrayTypeValue = context.getQNameFromString(Constants.getValue(attributes,
Constants.URIS_SOAP_ENC,
soapConstants.getAttrItemType()));
String dimString = null;
QName innerQName = null;
String innerDimString = "";
if (arrayTypeValue != null)
{
if (soapConstants != SOAPConstants.SOAP12_CONSTANTS)
{
String arrayTypeValueNamespaceURI =
arrayTypeValue.getNamespaceURI();
String arrayTypeValueLocalPart =
arrayTypeValue.getLocalPart();
int leftBracketIndex =
arrayTypeValueLocalPart.lastIndexOf('[');
int rightBracketIndex =
arrayTypeValueLocalPart.lastIndexOf(']');
if (leftBracketIndex == -1
|| rightBracketIndex == -1
|| rightBracketIndex < leftBracketIndex)
{
throw new IllegalArgumentException(Messages.getMessage("badArrayType00",
"" + arrayTypeValue));
}
dimString =
arrayTypeValueLocalPart.substring(leftBracketIndex + 1,
rightBracketIndex);
arrayTypeValueLocalPart =
arrayTypeValueLocalPart.substring(0, leftBracketIndex);
if (arrayTypeValueLocalPart.endsWith("]"))
{
defaultItemType = Constants.SOAP_ARRAY;
innerQName = new QName(arrayTypeValueNamespaceURI,
arrayTypeValueLocalPart.substring(0,
arrayTypeValueLocalPart.indexOf("[")));
innerDimString = arrayTypeValueLocalPart.substring(arrayTypeValueLocalPart.indexOf("["));
}
else
{
defaultItemType = new QName(arrayTypeValueNamespaceURI,
arrayTypeValueLocalPart);
}
}
else
{
String arraySizeValue = attributes.getValue(soapConstants.getEncodingURI(), Constants.ATTR_ARRAY_SIZE);
int leftStarIndex = arraySizeValue.lastIndexOf('*');
if (leftStarIndex != -1)
{
if (leftStarIndex == 0 && arraySizeValue.length() == 1)
{
}
else if (leftStarIndex == (arraySizeValue.length() - 1))
{
throw new IllegalArgumentException(Messages.getMessage("badArraySize00",
"" + arraySizeValue));
}
else
{
dimString = arraySizeValue.substring(leftStarIndex + 2);
innerQName = arrayTypeValue;
innerDimString = arraySizeValue.substring(0, leftStarIndex + 1);
}
}
else
{
dimString = arraySizeValue;
}
if (innerDimString == null || innerDimString.length() == 0)
{
defaultItemType = arrayTypeValue;
}
else
{
defaultItemType = Constants.SOAP_ARRAY12;
}
}
}
if (defaultItemType == null && typeQName == null)
{
defaultItemType = Constants.XSD_ANYTYPE;
}
arrayClass = null;
if (typeQName != null)
{
arrayClass = context.getTypeMapping().
getClassForQName(typeQName);
}
else
{
Class arrayItemClass = null;
QName compQName = defaultItemType;
String dims = "[]";
if (innerQName != null)
{
compQName = innerQName;
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
{
int offset = 0;
while ((offset = innerDimString.indexOf('*', offset)) != -1)
{
dims += "[]";
offset++;
}
}
else
{
dims += innerDimString;
}
}
arrayItemClass = context.getTypeMapping().
getClassForQName(compQName);
if (arrayItemClass != null)
{
try
{
String textClassName = JavaUtils.getTextClassName(arrayItemClass.getName()) + dims;
String loadableClassName = JavaUtils.getLoadableClassName(textClassName);
arrayClass = ClassUtils.forName(loadableClassName);
}
catch (Exception e)
{
throw new SAXException(Messages.getMessage("noComponent00",
"" + defaultItemType));
}
}
}
if (arrayClass == null)
{
throw new SAXException(Messages.getMessage("noComponent00", "" + defaultItemType));
}
if (dimString == null || dimString.length() == 0)
{
value = new ArrayListExtension(arrayClass);
}
else
{
try
{
StringTokenizer tokenizer;
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
{
tokenizer = new StringTokenizer(dimString);
}
else
{
tokenizer = new StringTokenizer(dimString, "[],");
}
length = Integer.parseInt(tokenizer.nextToken());
if (tokenizer.hasMoreTokens())
{
mDimLength = new ArrayList();
mDimLength.add(new Integer(length));
while (tokenizer.hasMoreTokens())
{
mDimLength.add(new Integer(Integer.parseInt(tokenizer.nextToken())));
}
}
ArrayList list = new ArrayListExtension(arrayClass, length);
for (int i = 0; i < length; i++)
{
list.add(null);
}
value = list;
}
catch (NumberFormatException e)
{
throw new IllegalArgumentException(Messages.getMessage("badInteger00", dimString));
}
}
String offset = Constants.getValue(attributes,
Constants.URIS_SOAP_ENC,
Constants.ATTR_OFFSET);
if (offset != null)
{
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
{
throw new SAXException(Messages.getMessage("noSparseArray"));
}
int leftBracketIndex = offset.lastIndexOf('[');
int rightBracketIndex = offset.lastIndexOf(']');
if (leftBracketIndex == -1
|| rightBracketIndex == -1
|| rightBracketIndex < leftBracketIndex)
{
throw new SAXException(Messages.getMessage("badOffset00", offset));
}
curIndex =
convertToIndex(offset.substring(leftBracketIndex + 1,
rightBracketIndex),
"badOffset00");
}
if (log.isDebugEnabled())
{
log.debug("Exit: ArrayDeserializer::startElement()");
}
}
public SOAPHandler onStartChild(String namespace,
String localName,
String prefix,
Attributes attributes,
DeserializationContext context)
throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: ArrayDeserializer.onStartChild()");
}
if (attributes != null)
{
String pos =
Constants.getValue(attributes,
Constants.URIS_SOAP_ENC,
Constants.ATTR_POSITION);
if (pos != null)
{
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
{
throw new SAXException(Messages.getMessage("noSparseArray"));
}
int leftBracketIndex = pos.lastIndexOf('[');
int rightBracketIndex = pos.lastIndexOf(']');
if (leftBracketIndex == -1
|| rightBracketIndex == -1
|| rightBracketIndex < leftBracketIndex)
{
throw new SAXException(Messages.getMessage("badPosition00", pos));
}
curIndex =
convertToIndex(pos.substring(leftBracketIndex + 1,
rightBracketIndex),
"badPosition00");
}
if (context.isNil(attributes))
{
setChildValue(null, new Integer(curIndex++));
return null;
}
}
QName itemType = context.getTypeFromAttributes(namespace,
localName,
attributes);
Deserializer dSer = null;
if (itemType != null && (context.getCurElement().getHref() == null))
{
dSer = context.getDeserializerForType(itemType);
}
if (dSer == null)
{
QName defaultType = defaultItemType;
Class javaType = null;
if (arrayClass != null &&
arrayClass.isArray() &&
defaultType == null)
{
javaType = arrayClass.getComponentType();
defaultType = context.getTypeMapping().getTypeQName(javaType);
}
if (itemType == null && dSer == null)
{
if (defaultType != null && SchemaUtils.isSimpleSchemaType(defaultType))
{
dSer = context.getDeserializer(javaType, defaultType);
}
}
if (dSer == null)
{
dSer = new DeserializerImpl();
if (itemType == null)
{
dSer.setDefaultType(defaultType);
}
}
}
dSer.registerValueTarget(new DeserializerTarget(this, new Integer(curIndex)));
addChildDeserializer(dSer);
curIndex++;
if (log.isDebugEnabled())
{
log.debug("Exit: ArrayDeserializer.onStartChild()");
}
return (SOAPHandler)dSer;
}
public void characters(char[] chars, int i, int i1) throws SAXException
{
for (int idx = i; i < i1; i++)
{
if (!Character.isWhitespace(chars[idx]))
throw new SAXException(Messages.getMessage("charsInArray"));
}
}
public void setChildValue(Object value, Object hint) throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: ArrayDeserializer::setValue(" + value + ", " + hint + ")");
}
ArrayList list = (ArrayList)this.value;
int offset = ((Integer)hint).intValue();
if (this.mDimLength == null)
{
while (list.size() <= offset)
{
list.add(null);
}
list.set(offset, value);
}
else
{
ArrayList mDimIndex = toMultiIndex(offset);
for (int i = 0; i < mDimLength.size(); i++)
{
int length = ((Integer)mDimLength.get(i)).intValue();
int index = ((Integer)mDimIndex.get(i)).intValue();
while (list.size() < length)
{
list.add(null);
}
if (i < mDimLength.size() - 1)
{
if (list.get(index) == null)
{
list.set(index, new ArrayList());
}
list = (ArrayList)list.get(index);
}
else
{
list.set(index, value);
}
}
}
}
public void valueComplete() throws SAXException
{
if (componentsReady())
{
try
{
if (arrayClass != null)
{
value = JavaUtils.convert(value, arrayClass);
}
}
catch (RuntimeException e)
{
}
}
super.valueComplete();
}
private int convertToIndex(String text, String exceptKey)
throws SAXException
{
StringTokenizer tokenizer = new StringTokenizer(text, "[],");
int index = 0;
try
{
if (mDimLength == null)
{
index = Integer.parseInt(tokenizer.nextToken());
if (tokenizer.hasMoreTokens())
{
throw new SAXException(Messages.getMessage(exceptKey, text));
}
}
else
{
int dim = -1;
ArrayList work = new ArrayList();
while (tokenizer.hasMoreTokens())
{
dim++;
if (dim >= mDimLength.size())
{
throw new SAXException(Messages.getMessage(exceptKey, text));
}
int workIndex = Integer.parseInt(tokenizer.nextToken());
if (workIndex < 0 ||
workIndex >=
((Integer)mDimLength.get(dim)).intValue())
{
throw new SAXException(Messages.getMessage(exceptKey, text));
}
work.add(new Integer(workIndex));
}
index = toSingleIndex(work); }
}
catch (SAXException e)
{
throw e;
}
catch (Exception e)
{
throw new SAXException(Messages.getMessage(exceptKey, text));
}
return index;
}
private ArrayList toMultiIndex(int single)
{
if (mDimLength == null)
return null;
if (mDimFactor == null)
{
mDimFactor = new ArrayList();
for (int i = 0; i < mDimLength.size(); i++)
{
int factor = 1;
for (int j = i + 1; j < mDimLength.size(); j++)
{
factor *= ((Integer)mDimLength.get(j)).intValue();
}
mDimFactor.add(new Integer(factor));
}
}
ArrayList rc = new ArrayList();
for (int i = 0; i < mDimLength.size(); i++)
{
int factor = ((Integer)mDimFactor.get(i)).intValue();
rc.add(new Integer(single / factor));
single = single % factor;
}
return rc;
}
private int toSingleIndex(ArrayList indexArray)
{
if (mDimLength == null || indexArray == null)
return -1;
if (mDimFactor == null)
{
mDimFactor = new ArrayList();
for (int i = 0; i < mDimLength.size(); i++)
{
int factor = 1;
for (int j = i + 1; j < mDimLength.size(); j++)
{
factor *= ((Integer)mDimLength.get(j)).intValue();
}
mDimFactor.add(new Integer(factor));
}
}
int single = 0;
for (int i = 0; i < indexArray.size(); i++)
{
single += ((Integer)mDimFactor.get(i)).intValue() *
((Integer)indexArray.get(i)).intValue();
}
return single;
}
public class ArrayListExtension extends ArrayList
implements JavaUtils.ConvertCache
{
private HashMap table = null;
private Class arrayClass = null;
ArrayListExtension(Class arrayClass)
{
super();
this.arrayClass = arrayClass;
if (arrayClass == null ||
arrayClass.isInterface() ||
java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers()))
{
arrayClass = null;
}
}
ArrayListExtension(Class arrayClass, int length)
{
super(length);
this.arrayClass = arrayClass;
if (arrayClass == null ||
arrayClass.isInterface() ||
java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers()))
{
arrayClass = null;
}
}
public void setConvertedValue(Class cls, Object value)
{
if (table == null)
table = new HashMap();
table.put(cls, value);
}
public Object getConvertedValue(Class cls)
{
if (table == null)
return null;
return table.get(cls);
}
public Class getDestClass()
{
return arrayClass;
}
}
}