// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

/**
 * ListBucket.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis2 version: 1.5.1  Built on : Oct 19, 2009 (10:59:34 EDT)
 */

package com.amazon.s3;

/**
*  ListBucket bean class
*/

public class ListBucket implements org.apache.axis2.databinding.ADBBean {

    public static final javax.xml.namespace.QName MY_QNAME = new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "ListBucket", "ns1");

    private static java.lang.String generatePrefix(java.lang.String namespace) {
        if (namespace.equals("http://s3.amazonaws.com/doc/2006-03-01/")) {
            return "ns1";
        }
        return org.apache.axis2.databinding.utils.BeanUtil.getUniquePrefix();
    }

    /**
    * field for Bucket
    */

    protected java.lang.String localBucket;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getBucket() {
        return localBucket;
    }

    /**
       * Auto generated setter method
       * @param param Bucket
       */
    public void setBucket(java.lang.String param) {

        this.localBucket = param;

    }

    /**
    * field for Prefix
    */

    protected java.lang.String localPrefix;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localPrefixTracker = false;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getPrefix() {
        return localPrefix;
    }

    /**
       * Auto generated setter method
       * @param param Prefix
       */
    public void setPrefix(java.lang.String param) {

        if (param != null) {
            //update the setting tracker
            localPrefixTracker = true;
        } else {
            localPrefixTracker = false;

        }

        this.localPrefix = param;

    }

    /**
    * field for Marker
    */

    protected java.lang.String localMarker;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localMarkerTracker = false;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getMarker() {
        return localMarker;
    }

    /**
       * Auto generated setter method
       * @param param Marker
       */
    public void setMarker(java.lang.String param) {

        if (param != null) {
            //update the setting tracker
            localMarkerTracker = true;
        } else {
            localMarkerTracker = false;

        }

        this.localMarker = param;

    }

    /**
    * field for MaxKeys
    */

    protected int localMaxKeys;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localMaxKeysTracker = false;

    /**
    * Auto generated getter method
    * @return int
    */
    public int getMaxKeys() {
        return localMaxKeys;
    }

    /**
       * Auto generated setter method
       * @param param MaxKeys
       */
    public void setMaxKeys(int param) {

        // setting primitive attribute tracker to true

        if (param == java.lang.Integer.MIN_VALUE) {
            localMaxKeysTracker = false;

        } else {
            localMaxKeysTracker = true;
        }

        this.localMaxKeys = param;

    }

    /**
    * field for Delimiter
    */

    protected java.lang.String localDelimiter;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localDelimiterTracker = false;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getDelimiter() {
        return localDelimiter;
    }

    /**
       * Auto generated setter method
       * @param param Delimiter
       */
    public void setDelimiter(java.lang.String param) {

        if (param != null) {
            //update the setting tracker
            localDelimiterTracker = true;
        } else {
            localDelimiterTracker = false;

        }

        this.localDelimiter = param;

    }

    /**
    * field for AWSAccessKeyId
    */

    protected java.lang.String localAWSAccessKeyId;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localAWSAccessKeyIdTracker = false;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getAWSAccessKeyId() {
        return localAWSAccessKeyId;
    }

    /**
       * Auto generated setter method
       * @param param AWSAccessKeyId
       */
    public void setAWSAccessKeyId(java.lang.String param) {

        if (param != null) {
            //update the setting tracker
            localAWSAccessKeyIdTracker = true;
        } else {
            localAWSAccessKeyIdTracker = false;

        }

        this.localAWSAccessKeyId = param;

    }

    /**
    * field for Timestamp
    */

    protected java.util.Calendar localTimestamp;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localTimestampTracker = false;

    /**
    * Auto generated getter method
    * @return java.util.Calendar
    */
    public java.util.Calendar getTimestamp() {
        return localTimestamp;
    }

    /**
       * Auto generated setter method
       * @param param Timestamp
       */
    public void setTimestamp(java.util.Calendar param) {

        if (param != null) {
            //update the setting tracker
            localTimestampTracker = true;
        } else {
            localTimestampTracker = false;

        }

        this.localTimestamp = param;

    }

    /**
    * field for Signature
    */

    protected java.lang.String localSignature;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localSignatureTracker = false;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getSignature() {
        return localSignature;
    }

    /**
       * Auto generated setter method
       * @param param Signature
       */
    public void setSignature(java.lang.String param) {

        if (param != null) {
            //update the setting tracker
            localSignatureTracker = true;
        } else {
            localSignatureTracker = false;

        }

        this.localSignature = param;

    }

    /**
    * field for Credential
    */

    protected java.lang.String localCredential;

    /*  This tracker boolean wil be used to detect whether the user called the set method
    *   for this attribute. It will be used to determine whether to include this field
    *   in the serialized XML
    */
    protected boolean localCredentialTracker = false;

    /**
    * Auto generated getter method
    * @return java.lang.String
    */
    public java.lang.String getCredential() {
        return localCredential;
    }

    /**
       * Auto generated setter method
       * @param param Credential
       */
    public void setCredential(java.lang.String param) {

        if (param != null) {
            //update the setting tracker
            localCredentialTracker = true;
        } else {
            localCredentialTracker = false;

        }

        this.localCredential = param;

    }

    /**
    * isReaderMTOMAware
    * @return true if the reader supports MTOM
    */
    public static boolean isReaderMTOMAware(javax.xml.stream.XMLStreamReader reader) {
        boolean isReaderMTOMAware = false;

        try {
            isReaderMTOMAware = java.lang.Boolean.TRUE.equals(reader.getProperty(org.apache.axiom.om.OMConstants.IS_DATA_HANDLERS_AWARE));
        } catch (java.lang.IllegalArgumentException e) {
            isReaderMTOMAware = false;
        }
        return isReaderMTOMAware;
    }

    /**
    *
    * @param parentQName
    * @param factory
    * @return org.apache.axiom.om.OMElement
    */
    public org.apache.axiom.om.OMElement getOMElement(final javax.xml.namespace.QName parentQName, final org.apache.axiom.om.OMFactory factory)
        throws org.apache.axis2.databinding.ADBException {

        org.apache.axiom.om.OMDataSource dataSource = new org.apache.axis2.databinding.ADBDataSource(this, MY_QNAME) {

            public void serialize(org.apache.axis2.databinding.utils.writer.MTOMAwareXMLStreamWriter xmlWriter) throws javax.xml.stream.XMLStreamException {
                ListBucket.this.serialize(MY_QNAME, factory, xmlWriter);
            }
        };
        return new org.apache.axiom.om.impl.llom.OMSourcedElementImpl(MY_QNAME, factory, dataSource);

    }

    public void serialize(final javax.xml.namespace.QName parentQName, final org.apache.axiom.om.OMFactory factory,
        org.apache.axis2.databinding.utils.writer.MTOMAwareXMLStreamWriter xmlWriter) throws javax.xml.stream.XMLStreamException,
        org.apache.axis2.databinding.ADBException {
        serialize(parentQName, factory, xmlWriter, false);
    }

    public void serialize(final javax.xml.namespace.QName parentQName, final org.apache.axiom.om.OMFactory factory,
        org.apache.axis2.databinding.utils.writer.MTOMAwareXMLStreamWriter xmlWriter, boolean serializeType) throws javax.xml.stream.XMLStreamException,
        org.apache.axis2.databinding.ADBException {

        java.lang.String prefix = null;
        java.lang.String namespace = null;

        prefix = parentQName.getPrefix();
        namespace = parentQName.getNamespaceURI();

        if ((namespace != null) && (namespace.trim().length() > 0)) {
            java.lang.String writerPrefix = xmlWriter.getPrefix(namespace);
            if (writerPrefix != null) {
                xmlWriter.writeStartElement(namespace, parentQName.getLocalPart());
            } else {
                if (prefix == null) {
                    prefix = generatePrefix(namespace);
                }

                xmlWriter.writeStartElement(prefix, parentQName.getLocalPart(), namespace);
                xmlWriter.writeNamespace(prefix, namespace);
                xmlWriter.setPrefix(prefix, namespace);
            }
        } else {
            xmlWriter.writeStartElement(parentQName.getLocalPart());
        }

        if (serializeType) {

            java.lang.String namespacePrefix = registerPrefix(xmlWriter, "http://s3.amazonaws.com/doc/2006-03-01/");
            if ((namespacePrefix != null) && (namespacePrefix.trim().length() > 0)) {
                writeAttribute("xsi", "http://www.w3.org/2001/XMLSchema-instance", "type", namespacePrefix + ":ListBucket", xmlWriter);
            } else {
                writeAttribute("xsi", "http://www.w3.org/2001/XMLSchema-instance", "type", "ListBucket", xmlWriter);
            }

        }

        namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
        if (!namespace.equals("")) {
            prefix = xmlWriter.getPrefix(namespace);

            if (prefix == null) {
                prefix = generatePrefix(namespace);

                xmlWriter.writeStartElement(prefix, "Bucket", namespace);
                xmlWriter.writeNamespace(prefix, namespace);
                xmlWriter.setPrefix(prefix, namespace);

            } else {
                xmlWriter.writeStartElement(namespace, "Bucket");
            }

        } else {
            xmlWriter.writeStartElement("Bucket");
        }

        if (localBucket == null) {
            // write the nil attribute

            throw new org.apache.axis2.databinding.ADBException("Bucket cannot be null!!");

        } else {

            xmlWriter.writeCharacters(localBucket);

        }

        xmlWriter.writeEndElement();
        if (localPrefixTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "Prefix", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "Prefix");
                }

            } else {
                xmlWriter.writeStartElement("Prefix");
            }

            if (localPrefix == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("Prefix cannot be null!!");

            } else {

                xmlWriter.writeCharacters(localPrefix);

            }

            xmlWriter.writeEndElement();
        }
        if (localMarkerTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "Marker", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "Marker");
                }

            } else {
                xmlWriter.writeStartElement("Marker");
            }

            if (localMarker == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("Marker cannot be null!!");

            } else {

                xmlWriter.writeCharacters(localMarker);

            }

            xmlWriter.writeEndElement();
        }
        if (localMaxKeysTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "MaxKeys", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "MaxKeys");
                }

            } else {
                xmlWriter.writeStartElement("MaxKeys");
            }

            if (localMaxKeys == java.lang.Integer.MIN_VALUE) {

                throw new org.apache.axis2.databinding.ADBException("MaxKeys cannot be null!!");

            } else {
                xmlWriter.writeCharacters(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localMaxKeys));
            }

            xmlWriter.writeEndElement();
        }
        if (localDelimiterTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "Delimiter", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "Delimiter");
                }

            } else {
                xmlWriter.writeStartElement("Delimiter");
            }

            if (localDelimiter == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("Delimiter cannot be null!!");

            } else {

                xmlWriter.writeCharacters(localDelimiter);

            }

            xmlWriter.writeEndElement();
        }
        if (localAWSAccessKeyIdTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "AWSAccessKeyId", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "AWSAccessKeyId");
                }

            } else {
                xmlWriter.writeStartElement("AWSAccessKeyId");
            }

            if (localAWSAccessKeyId == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("AWSAccessKeyId cannot be null!!");

            } else {

                xmlWriter.writeCharacters(localAWSAccessKeyId);

            }

            xmlWriter.writeEndElement();
        }
        if (localTimestampTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "Timestamp", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "Timestamp");
                }

            } else {
                xmlWriter.writeStartElement("Timestamp");
            }

            if (localTimestamp == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("Timestamp cannot be null!!");

            } else {

                xmlWriter.writeCharacters(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localTimestamp));

            }

            xmlWriter.writeEndElement();
        }
        if (localSignatureTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "Signature", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "Signature");
                }

            } else {
                xmlWriter.writeStartElement("Signature");
            }

            if (localSignature == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("Signature cannot be null!!");

            } else {

                xmlWriter.writeCharacters(localSignature);

            }

            xmlWriter.writeEndElement();
        }
        if (localCredentialTracker) {
            namespace = "http://s3.amazonaws.com/doc/2006-03-01/";
            if (!namespace.equals("")) {
                prefix = xmlWriter.getPrefix(namespace);

                if (prefix == null) {
                    prefix = generatePrefix(namespace);

                    xmlWriter.writeStartElement(prefix, "Credential", namespace);
                    xmlWriter.writeNamespace(prefix, namespace);
                    xmlWriter.setPrefix(prefix, namespace);

                } else {
                    xmlWriter.writeStartElement(namespace, "Credential");
                }

            } else {
                xmlWriter.writeStartElement("Credential");
            }

            if (localCredential == null) {
                // write the nil attribute

                throw new org.apache.axis2.databinding.ADBException("Credential cannot be null!!");

            } else {

                xmlWriter.writeCharacters(localCredential);

            }

            xmlWriter.writeEndElement();
        }
        xmlWriter.writeEndElement();

    }

    /**
     * Util method to write an attribute with the ns prefix
     */
    private void writeAttribute(java.lang.String prefix, java.lang.String namespace, java.lang.String attName, java.lang.String attValue,
        javax.xml.stream.XMLStreamWriter xmlWriter) throws javax.xml.stream.XMLStreamException {
        if (xmlWriter.getPrefix(namespace) == null) {
            xmlWriter.writeNamespace(prefix, namespace);
            xmlWriter.setPrefix(prefix, namespace);

        }

        xmlWriter.writeAttribute(namespace, attName, attValue);

    }

    /**
      * Util method to write an attribute without the ns prefix
      */
    private void writeAttribute(java.lang.String namespace, java.lang.String attName, java.lang.String attValue, javax.xml.stream.XMLStreamWriter xmlWriter)
        throws javax.xml.stream.XMLStreamException {
        if (namespace.equals("")) {
            xmlWriter.writeAttribute(attName, attValue);
        } else {
            registerPrefix(xmlWriter, namespace);
            xmlWriter.writeAttribute(namespace, attName, attValue);
        }
    }

    /**
      * Util method to write an attribute without the ns prefix
      */
    private void writeQNameAttribute(java.lang.String namespace, java.lang.String attName, javax.xml.namespace.QName qname, javax.xml.stream.XMLStreamWriter xmlWriter)
        throws javax.xml.stream.XMLStreamException {

        java.lang.String attributeNamespace = qname.getNamespaceURI();
        java.lang.String attributePrefix = xmlWriter.getPrefix(attributeNamespace);
        if (attributePrefix == null) {
            attributePrefix = registerPrefix(xmlWriter, attributeNamespace);
        }
        java.lang.String attributeValue;
        if (attributePrefix.trim().length() > 0) {
            attributeValue = attributePrefix + ":" + qname.getLocalPart();
        } else {
            attributeValue = qname.getLocalPart();
        }

        if (namespace.equals("")) {
            xmlWriter.writeAttribute(attName, attributeValue);
        } else {
            registerPrefix(xmlWriter, namespace);
            xmlWriter.writeAttribute(namespace, attName, attributeValue);
        }
    }

    /**
     *  method to handle Qnames
     */

    private void writeQName(javax.xml.namespace.QName qname, javax.xml.stream.XMLStreamWriter xmlWriter) throws javax.xml.stream.XMLStreamException {
        java.lang.String namespaceURI = qname.getNamespaceURI();
        if (namespaceURI != null) {
            java.lang.String prefix = xmlWriter.getPrefix(namespaceURI);
            if (prefix == null) {
                prefix = generatePrefix(namespaceURI);
                xmlWriter.writeNamespace(prefix, namespaceURI);
                xmlWriter.setPrefix(prefix, namespaceURI);
            }

            if (prefix.trim().length() > 0) {
                xmlWriter.writeCharacters(prefix + ":" + org.apache.axis2.databinding.utils.ConverterUtil.convertToString(qname));
            } else {
                // i.e this is the default namespace
                xmlWriter.writeCharacters(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(qname));
            }

        } else {
            xmlWriter.writeCharacters(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(qname));
        }
    }

    private void writeQNames(javax.xml.namespace.QName[] qnames, javax.xml.stream.XMLStreamWriter xmlWriter) throws javax.xml.stream.XMLStreamException {

        if (qnames != null) {
            // we have to store this data until last moment since it is not possible to write any
            // namespace data after writing the charactor data
            java.lang.StringBuffer stringToWrite = new java.lang.StringBuffer();
            java.lang.String namespaceURI = null;
            java.lang.String prefix = null;

            for (int i = 0; i < qnames.length; i++) {
                if (i > 0) {
                    stringToWrite.append(" ");
                }
                namespaceURI = qnames[i].getNamespaceURI();
                if (namespaceURI != null) {
                    prefix = xmlWriter.getPrefix(namespaceURI);
                    if ((prefix == null) || (prefix.length() == 0)) {
                        prefix = generatePrefix(namespaceURI);
                        xmlWriter.writeNamespace(prefix, namespaceURI);
                        xmlWriter.setPrefix(prefix, namespaceURI);
                    }

                    if (prefix.trim().length() > 0) {
                        stringToWrite.append(prefix).append(":").append(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(qnames[i]));
                    } else {
                        stringToWrite.append(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(qnames[i]));
                    }
                } else {
                    stringToWrite.append(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(qnames[i]));
                }
            }
            xmlWriter.writeCharacters(stringToWrite.toString());
        }

    }

    /**
    * Register a namespace prefix
    */
    private java.lang.String registerPrefix(javax.xml.stream.XMLStreamWriter xmlWriter, java.lang.String namespace) throws javax.xml.stream.XMLStreamException {
        java.lang.String prefix = xmlWriter.getPrefix(namespace);

        if (prefix == null) {
            prefix = generatePrefix(namespace);

            while (xmlWriter.getNamespaceContext().getNamespaceURI(prefix) != null) {
                prefix = org.apache.axis2.databinding.utils.BeanUtil.getUniquePrefix();
            }

            xmlWriter.writeNamespace(prefix, namespace);
            xmlWriter.setPrefix(prefix, namespace);
        }

        return prefix;
    }

    /**
    * databinding method to get an XML representation of this object
    *
    */
    public javax.xml.stream.XMLStreamReader getPullParser(javax.xml.namespace.QName qName) throws org.apache.axis2.databinding.ADBException {

        java.util.ArrayList elementList = new java.util.ArrayList();
        java.util.ArrayList attribList = new java.util.ArrayList();

        elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Bucket"));

        if (localBucket != null) {
            elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localBucket));
        } else {
            throw new org.apache.axis2.databinding.ADBException("Bucket cannot be null!!");
        }
        if (localPrefixTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Prefix"));

            if (localPrefix != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localPrefix));
            } else {
                throw new org.apache.axis2.databinding.ADBException("Prefix cannot be null!!");
            }
        }
        if (localMarkerTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Marker"));

            if (localMarker != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localMarker));
            } else {
                throw new org.apache.axis2.databinding.ADBException("Marker cannot be null!!");
            }
        }
        if (localMaxKeysTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "MaxKeys"));

            elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localMaxKeys));
        }
        if (localDelimiterTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Delimiter"));

            if (localDelimiter != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localDelimiter));
            } else {
                throw new org.apache.axis2.databinding.ADBException("Delimiter cannot be null!!");
            }
        }
        if (localAWSAccessKeyIdTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "AWSAccessKeyId"));

            if (localAWSAccessKeyId != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localAWSAccessKeyId));
            } else {
                throw new org.apache.axis2.databinding.ADBException("AWSAccessKeyId cannot be null!!");
            }
        }
        if (localTimestampTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Timestamp"));

            if (localTimestamp != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localTimestamp));
            } else {
                throw new org.apache.axis2.databinding.ADBException("Timestamp cannot be null!!");
            }
        }
        if (localSignatureTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Signature"));

            if (localSignature != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localSignature));
            } else {
                throw new org.apache.axis2.databinding.ADBException("Signature cannot be null!!");
            }
        }
        if (localCredentialTracker) {
            elementList.add(new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Credential"));

            if (localCredential != null) {
                elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(localCredential));
            } else {
                throw new org.apache.axis2.databinding.ADBException("Credential cannot be null!!");
            }
        }

        return new org.apache.axis2.databinding.utils.reader.ADBXMLStreamReaderImpl(qName, elementList.toArray(), attribList.toArray());

    }

    /**
     *  Factory class that keeps the parse method
     */
    public static class Factory {

        /**
        * static method to create the object
        * Precondition:  If this object is an element, the current or next start element starts this object and any intervening reader events are ignorable
        *                If this object is not an element, it is a complex type and the reader is at the event just after the outer start element
        * Postcondition: If this object is an element, the reader is positioned at its end element
        *                If this object is a complex type, the reader is positioned at the end element of its outer element
        */
        public static ListBucket parse(javax.xml.stream.XMLStreamReader reader) throws java.lang.Exception {
            ListBucket object = new ListBucket();

            int event;
            java.lang.String nillableValue = null;
            java.lang.String prefix = "";
            java.lang.String namespaceuri = "";
            try {

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "type") != null) {
                    java.lang.String fullTypeName = reader.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "type");
                    if (fullTypeName != null) {
                        java.lang.String nsPrefix = null;
                        if (fullTypeName.indexOf(":") > -1) {
                            nsPrefix = fullTypeName.substring(0, fullTypeName.indexOf(":"));
                        }
                        nsPrefix = nsPrefix == null ? "" : nsPrefix;

                        java.lang.String type = fullTypeName.substring(fullTypeName.indexOf(":") + 1);

                        if (!"ListBucket".equals(type)) {
                            //find namespace for the prefix
                            java.lang.String nsUri = reader.getNamespaceContext().getNamespaceURI(nsPrefix);
                            return (ListBucket)com.amazon.s3.ExtensionMapper.getTypeObject(nsUri, type, reader);
                        }

                    }

                }

                // Note all attributes that were handled. Used to differ normal attributes
                // from anyAttributes.
                java.util.Vector handledAttributes = new java.util.Vector();

                reader.next();

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Bucket").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setBucket(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {
                    // A start element we are not expecting indicates an invalid parameter was passed
                    throw new org.apache.axis2.databinding.ADBException("Unexpected subelement " + reader.getLocalName());
                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Prefix").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setPrefix(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Marker").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setMarker(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "MaxKeys").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setMaxKeys(org.apache.axis2.databinding.utils.ConverterUtil.convertToInt(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                    object.setMaxKeys(java.lang.Integer.MIN_VALUE);

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Delimiter").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setDelimiter(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "AWSAccessKeyId").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setAWSAccessKeyId(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Timestamp").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setTimestamp(org.apache.axis2.databinding.utils.ConverterUtil.convertToDateTime(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Signature").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setSignature(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement() && new javax.xml.namespace.QName("http://s3.amazonaws.com/doc/2006-03-01/", "Credential").equals(reader.getName())) {

                    java.lang.String content = reader.getElementText();

                    object.setCredential(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(content));

                    reader.next();

                }  // End of if for expected property start element

                else {

                }

                while (!reader.isStartElement() && !reader.isEndElement())
                    reader.next();

                if (reader.isStartElement())
                    // A start element we are not expecting indicates a trailing invalid property
                    throw new org.apache.axis2.databinding.ADBException("Unexpected subelement " + reader.getLocalName());

            } catch (javax.xml.stream.XMLStreamException e) {
                throw new java.lang.Exception(e);
            }

            return object;
        }

    }//end of factory class

}
