public void onStartElement()

in axis-rt-core/src/main/java/org/apache/axis/encoding/ser/ArrayDeserializer.java [78:359]


    public void onStartElement(String namespace, String localName,
                             String prefix, Attributes attributes,
                             DeserializationContext context)
        throws SAXException
    {
        // Deserializing the xml array requires processing the
        // xsi:type= attribute, the soapenc:arrayType attribute,
        // and the xsi:type attributes of the individual elements.
        //
        // The xsi:type=<qName> attribute is used to determine the java
        // type of the array to instantiate.  Axis expects it
        // to be set to the generic "soapenc:Array" or to
        // a specific qName.  If the generic "soapenc:Array"
        // specification is used, Axis determines the array
        // type by examining the soapenc:arrayType attribute.
        //
        // The soapenc:arrayType=<qname><dims> is used to determine
        // i) the number of dimensions, 
        // ii) the length of each dimension,
        // iii) the default xsi:type of each of the elements.
        //
        // If the arrayType attribute is missing, Axis assumes
        // a single dimension array with length equal to the number
        // of nested elements.  In such cases, the default xsi:type of 
        // the elements is determined using the array xsi:type.
        //
        // The xsi:type attributes of the individual elements of the
        // array are used to determine the java type of the element.
        // If the xsi:type attribute is missing for an element, the 
        // default xsi:type value is used.

        if (log.isDebugEnabled()) {
            log.debug("Enter: ArrayDeserializer::startElement()");
        }

        soapConstants = context.getSOAPConstants();

        // Get the qname for the array type=, set it to null if
        // the generic type is used.
        QName typeQName = context.getTypeFromAttributes(namespace,
                                                        localName,
                                                        attributes);
        if (typeQName == null) {
            typeQName = getDefaultType();
        }

        if (typeQName != null &&
            Constants.equals(Constants.SOAP_ARRAY, typeQName)) {
            typeQName = null;
        }

        // Now get the arrayType value
        QName arrayTypeValue = context.getQNameFromString(
                      Constants.getValue(attributes,
                                         Constants.URIS_SOAP_ENC,
                                         soapConstants.getAttrItemType()));

        // The first part of the arrayType expression is 
        // the default item type qname.
        // The second part is the dimension information
        String dimString = null;
        QName innerQName = null;
        String innerDimString = "";
        if (arrayTypeValue != null) {
            if (soapConstants != SOAPConstants.SOAP12_CONSTANTS) {
                // Doing SOAP 1.1
                // Array dimension noted like this : [][x]
                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 multi-dim array set to soapenc:Array
                if (arrayTypeValueLocalPart.endsWith("]")) {
                    defaultItemType = Constants.SOAP_ARRAY;
                    int bracket = arrayTypeValueLocalPart.indexOf("[");
                    innerQName = new QName(arrayTypeValueNamespaceURI,
                                           arrayTypeValueLocalPart.substring(0, bracket));
                    innerDimString = arrayTypeValueLocalPart.substring(bracket);
                } else {
                    defaultItemType = new QName(arrayTypeValueNamespaceURI,
                                                arrayTypeValueLocalPart);
                }

            } else {
                String arraySizeValue = attributes.getValue(soapConstants.getEncodingURI(), Constants.ATTR_ARRAY_SIZE);
                int leftStarIndex = arraySizeValue.lastIndexOf('*');

                // Skip to num if any
                if (leftStarIndex != -1) {
                    // "*" => ""
                    if (leftStarIndex == 0 && arraySizeValue.length() == 1) {
                        // "* *" => ""
                    } else if (leftStarIndex == (arraySizeValue.length() - 1)) {
                        throw new IllegalArgumentException(
                          Messages.getMessage("badArraySize00",
                                               "" + arraySizeValue));
                        // "* N" => "N"
                    } 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 no type QName and no defaultItemType qname, use xsd:anyType
        if (defaultItemType == null && typeQName == null) {
            Class destClass = context.getDestinationClass();
            if (destClass != null && destClass.isArray()) {
                // This will get set OK down below...
            } else {
                defaultItemType = Constants.XSD_ANYTYPE;
            }
        }
        
        // Determine the class type for the array.
        arrayClass = null;
        if (typeQName != null) {
            arrayClass = context.getTypeMapping().
                getClassForQName(typeQName);
        } 
        
        if (typeQName == null || arrayClass == null) {
            // type= information is not sufficient.
            // Get an array of the default item type.
            Class arrayItemClass = null;
            QName compQName = defaultItemType;

            // Nested array, use the innermost qname
            String dims = "[]";
            if (innerQName != null) {
                compQName = innerQName;

                if (soapConstants == SOAPConstants.SOAP12_CONSTANTS) {
                    // With SOAP 1.2 Array, we append [] for each * found
                    int offset = 0;
                    while ((offset = innerDimString.indexOf('*', offset)) != -1) {
                        dims += "[]";
                        offset ++;
                    }
                } else {
                    // With SOAP 1.1 Array, we can append directly the complete innerDimString
                    dims += innerDimString;
                }
            }

            // item Class
            arrayItemClass = context.getTypeMapping().getClassForQName(compQName);
            if (arrayItemClass != null) {
                try {
                    // Append the dimension found to the classname computed from the itemClass
                    // to form the array classname
                    //
                    String loadableArrayClassName = JavaUtils.getLoadableClassName(
                            JavaUtils.getTextClassName(arrayItemClass.getName()) + dims);
                    arrayClass = ClassUtils.forName(loadableArrayClassName,
                                                    true,
                                                    arrayItemClass.getClassLoader());
                } catch (Exception e) {
                    throw new SAXException(
                            Messages.getMessage("noComponent00",
                                                "" + defaultItemType));
                }
            }
        }
        if (arrayClass == null) {
            arrayClass = context.getDestinationClass();
        }

        if (arrayClass == null) {
            throw new SAXException(
               Messages.getMessage("noComponent00",  "" + defaultItemType));
        }

        if (dimString == null || dimString.length() == 0) {
            // Size determined using length of the members
            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()) {
                        // If the array is passed as a multi-dimensional array
                        // (i.e. int[2][3]) then store all of the 
                        // mult-dim lengths.
                        // The valueReady method uses this array to set the
                        // proper mult-dim element.
                        mDimLength = new ArrayList();
                        mDimLength.add(new Integer(length));
                        
                        while(tokenizer.hasMoreTokens()) {
                            mDimLength.add(
                                new Integer(
                                    Integer.parseInt(tokenizer.nextToken())));
                        }
                    }

                // Create an ArrayListExtension class to store the ArrayList
                // plus converted objects.
                ArrayList list = new ArrayListExtension(arrayClass, length);

                // This is expensive as our array may not grown this big.
                // Prevents problems when XML claims a huge size
                // that it doesn't actually fill.
                //for (int i = 0; i < length; i++) {
                //    list.add(null);
                //}
                value = list;

            }
            catch (NumberFormatException e)
            {
                throw new IllegalArgumentException(
                        Messages.getMessage("badInteger00", dimString));
            }
        }

        // If soapenc:offset specified, set the current index accordingly
        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()");
        }
    }