Home | History | Annotate | Download | only in serialization
      1 /*
      2  * Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a copy
      5  * of this software and associated documentation files (the "Software"), to deal
      6  * in the Software without restriction, including without limitation the rights
      7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8  * copies of the Software, and to permit persons to whom the Software is
      9  * furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * SOFTWARE.
     21  *
     22  * Contributor(s): John D. Beatty, Dave Dash, Andre Gerard, F. Hunter, Renaud
     23  * Tognelli
     24  */
     25 
     26 package org.ksoap2.serialization;
     27 
     28 import java.util.*;
     29 
     30 /**
     31  * A simple dynamic object that can be used to build soap calls without
     32  * implementing KvmSerializable
     33  * <p/>
     34  * Essentially, this is what goes inside the body of a soap envelope - it is the
     35  * direct subelement of the body and all further subelements
     36  * <p/>
     37  * Instead of this this class, custom classes can be used if they implement the
     38  * KvmSerializable interface.
     39  */
     40 
     41 public class SoapObject extends AttributeContainer implements KvmSerializable, HasInnerText {
     42 
     43     private static final String EMPTY_STRING = "";
     44     /**
     45      * The namespace of this soap object.
     46      */
     47     protected String namespace;
     48     /**
     49      * The name of this soap object.
     50      */
     51     protected String name;
     52     /**
     53      * The Vector of properties (can contain PropertyInfo and SoapObject)
     54      */
     55     protected Vector properties = new Vector();
     56 
     57     protected Object innerText;
     58 
     59     // TODO: accessing properties and attributes would work much better if we
     60     // kept a list of known properties instead of iterating through the list
     61     // each time
     62 
     63     /**
     64      * Creates a new <code>SoapObject</code> instance.
     65      */
     66 
     67     public SoapObject() {
     68         this("", "");
     69     }
     70 
     71     /**
     72      * Creates a new <code>SoapObject</code> instance.
     73      *
     74      * @param namespace the namespace for the soap object
     75      * @param name      the name of the soap object
     76      */
     77 
     78     public SoapObject(String namespace, String name) {
     79         this.namespace = namespace;
     80         this.name = name;
     81     }
     82 
     83     public boolean equals(Object obj) {
     84         if (!(obj instanceof SoapObject)) {
     85             return false;
     86         }
     87 
     88         SoapObject otherSoapObject = (SoapObject) obj;
     89 
     90         if (!name.equals(otherSoapObject.name)
     91                 || !namespace.equals(otherSoapObject.namespace)) {
     92             return false;
     93         }
     94 
     95         int numProperties = properties.size();
     96         if (numProperties != otherSoapObject.properties.size()) {
     97             return false;
     98         }
     99 
    100         // SoapObjects are only considered the same if properties equals and in the same order
    101         for (int propIndex = 0; propIndex < numProperties; propIndex++) {
    102             Object thisProp = this.properties.elementAt(propIndex);
    103             if (!otherSoapObject.isPropertyEqual(thisProp, propIndex)) {
    104                 return false;
    105             }
    106         }
    107 
    108         return attributesAreEqual(otherSoapObject);
    109     }
    110 
    111     /**
    112      * Helper function for SoapObject.equals
    113      * Checks if a given property and index are the same as in this
    114      *
    115      * @param otherProp, index
    116      */
    117     public boolean isPropertyEqual(Object otherProp, int index) {
    118         if (index >= getPropertyCount()) {
    119             return false;
    120         }
    121         Object thisProp = this.properties.elementAt(index);
    122         if (otherProp instanceof PropertyInfo &&
    123                 thisProp instanceof PropertyInfo) {
    124             // Get both PropertInfos and compare values
    125             PropertyInfo otherPropInfo = (PropertyInfo) otherProp;
    126             PropertyInfo thisPropInfo = (PropertyInfo) thisProp;
    127             return otherPropInfo.getName().equals(thisPropInfo.getName()) &&
    128                     otherPropInfo.getValue().equals(thisPropInfo.getValue());
    129         } else if (otherProp instanceof SoapObject && thisProp instanceof SoapObject) {
    130             SoapObject otherPropSoap = (SoapObject) otherProp;
    131             SoapObject thisPropSoap = (SoapObject) thisProp;
    132             return otherPropSoap.equals(thisPropSoap);
    133         }
    134         return false;
    135     }
    136 
    137     public String getName() {
    138         return name;
    139     }
    140 
    141     public String getNamespace() {
    142         return namespace;
    143     }
    144 
    145     /**
    146      * @inheritDoc
    147      */
    148     public Object getProperty(int index) {
    149         Object prop = properties.elementAt(index);
    150         if (prop instanceof PropertyInfo) {
    151             return ((PropertyInfo) prop).getValue();
    152         } else {
    153             return ((SoapObject) prop);
    154         }
    155     }
    156 
    157     /**
    158      * Get the toString value of the property.
    159      */
    160     public String getPropertyAsString(int index) {
    161         PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index);
    162         return propertyInfo.getValue().toString();
    163     }
    164 
    165     /**
    166      * Get the property with the given name
    167      *
    168      * @throws java.lang.RuntimeException if the property does not exist
    169      */
    170     public Object getProperty(String name) {
    171         Integer index = propertyIndex(name);
    172         if (index != null) {
    173             return getProperty(index.intValue());
    174         } else {
    175             throw new RuntimeException("illegal property: " + name);
    176         }
    177     }
    178 
    179     /**
    180      * Get the property with the given name
    181      *
    182      * return null
    183      * if the property does not exist
    184      */
    185     public Object getProperty(String namespace, String name) {
    186         Integer index = propertyIndex(namespace, name);
    187         if (index != null) {
    188             return getProperty(index.intValue());
    189         } else {
    190             throw new RuntimeException("illegal property: " + name);
    191         }
    192     }
    193 
    194     /**
    195      * Get a property using namespace and name without chance of throwing an exception
    196      *
    197      * @return the property if it exists; if not, {@link NullSoapObject} is
    198      * returned
    199      */
    200     public Object getPropertyByNamespaceSafely(final String namespace, final String name) {
    201         Integer i = propertyIndex(namespace, name);
    202         if (i != null) {
    203             return getProperty(i.intValue());
    204         } else {
    205             return new NullSoapObject();
    206         }
    207     }
    208 
    209     /**
    210      * Get the toString value of a property without chance of throwing an
    211      * exception
    212      *
    213      * @return the string value of the property if it exists; if not, #EMPTY_STRING is
    214      * returned
    215      */
    216     public String getPropertyByNamespaceSafelyAsString(final String namespace, final String name) {
    217         Integer i = propertyIndex(namespace, name);
    218         if (i != null) {
    219             Object foo = getProperty(i.intValue());
    220             if (foo == null) {
    221                 return EMPTY_STRING;
    222             } else {
    223                 return foo.toString();
    224             }
    225         } else {
    226             return EMPTY_STRING;
    227         }
    228     }
    229 
    230     /**
    231      * Get a property without chance of throwing an exception. An object can be
    232      * provided to this method; if the property is not found, this object will
    233      * be returned.
    234      *
    235      * @param defaultThing the object to return if the property is not found
    236      * @return the property if it exists; defaultThing if the property does not
    237      * exist
    238      */
    239     public Object getPropertySafely(final String namespace, final String name,
    240             final Object defaultThing) {
    241         Integer i = propertyIndex(namespace, name);
    242         if (i != null) {
    243             return getProperty(i.intValue());
    244         } else {
    245             return defaultThing;
    246         }
    247     }
    248 
    249     /**
    250      * Get the toString value of a property without chance of throwing an
    251      * exception. An object can be provided to this method; if the property is
    252      * not found, this object's string representation will be returned.
    253      *
    254      * @param defaultThing toString of the object to return if the property is not found
    255      * @return the property toString if it exists; defaultThing toString if the
    256      * property does not exist, if the defaultThing is null #EMPTY_STRING
    257      * is returned
    258      */
    259     public String getPropertySafelyAsString(final String namespace, final String name,
    260             final Object defaultThing) {
    261         Integer i = propertyIndex(namespace, name);
    262         if (i != null) {
    263             Object property = getProperty(i.intValue());
    264             if (property != null) {
    265                 return property.toString();
    266             } else {
    267                 return EMPTY_STRING;
    268             }
    269         } else {
    270             if (defaultThing != null) {
    271                 return defaultThing.toString();
    272             } else {
    273                 return EMPTY_STRING;
    274             }
    275         }
    276     }
    277 
    278     /**
    279      * Get the primitive property with the given name.
    280      *
    281      * @return PropertyInfo containing an empty string if property either complex or empty
    282      */
    283     public Object getPrimitiveProperty(final String namespace, final String name) {
    284         Integer index = propertyIndex(namespace, name);
    285         if (index != null) {
    286             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    287             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    288                 return propertyInfo.getValue();
    289             } else {
    290                 propertyInfo = new PropertyInfo();
    291                 propertyInfo.setType(String.class);
    292                 propertyInfo.setValue(EMPTY_STRING);
    293                 propertyInfo.setName(name);
    294                 propertyInfo.setNamespace(namespace);
    295                 return (Object) propertyInfo.getValue();
    296             }
    297         } else {
    298             throw new RuntimeException("illegal property: " + name);
    299         }
    300     }
    301 
    302     /**
    303      * Get the toString value of the primitive property with the given name.
    304      * Returns empty string if property either complex or empty
    305      *
    306      * @return the string value of the property
    307      */
    308     public String getPrimitivePropertyAsString(final String namespace, final String name) {
    309         Integer index = propertyIndex(namespace, name);
    310         if (index != null) {
    311             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    312             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    313                 return propertyInfo.getValue().toString();
    314             } else {
    315                 return EMPTY_STRING;
    316             }
    317         } else {
    318             throw new RuntimeException("illegal property: " + name);
    319         }
    320     }
    321 
    322     /**
    323      * Get the toString value of a primitive property without chance of throwing an
    324      * exception
    325      *
    326      * @return the string value of the property if it exists and is primitive; if not,
    327      * #EMPTY_STRING is
    328      * returned
    329      */
    330     public Object getPrimitivePropertySafely(final String namespace, final String name) {
    331         Integer index = propertyIndex(namespace, name);
    332         if (index != null) {
    333             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    334             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    335                 return propertyInfo.getValue().toString();
    336             } else {
    337                 propertyInfo = new PropertyInfo();
    338                 propertyInfo.setType(String.class);
    339                 propertyInfo.setValue(EMPTY_STRING);
    340                 propertyInfo.setName(name);
    341                 propertyInfo.setNamespace(namespace);
    342                 return (Object) propertyInfo.getValue();
    343             }
    344         } else {
    345             return new NullSoapObject();
    346         }
    347     }
    348 
    349     /**
    350      * Get the toString value of a primitive property without chance of throwing an
    351      * exception
    352      *
    353      * @return the string value of the property if it exists and is primitive; if not,
    354      * #EMPTY_STRING is
    355      * returned
    356      */
    357     public String getPrimitivePropertySafelyAsString(final String namespace, final String name) {
    358         Integer index = propertyIndex(namespace, name);
    359         if (index != null) {
    360             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    361             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    362                 return propertyInfo.getValue().toString();
    363             } else {
    364                 return EMPTY_STRING;
    365             }
    366         } else {
    367             return EMPTY_STRING;
    368         }
    369     }
    370 
    371     /**
    372      * Knows whether the given property exists
    373      */
    374     public boolean hasProperty(final String namespace, final String name) {
    375         if (propertyIndex(namespace, name) != null) {
    376             return true;
    377         } else {
    378             return false;
    379         }
    380     }
    381 
    382     /**
    383      * Get the toString value of the property.
    384      */
    385 
    386     public String getPropertyAsString(String namespace, String name) {
    387         Integer index = propertyIndex(namespace, name);
    388         if (index != null) {
    389             return getProperty(index.intValue()).toString();
    390         } else {
    391             throw new RuntimeException("illegal property: " + name);
    392         }
    393     }
    394 
    395     /**
    396      * Get the toString value of the property.
    397      */
    398 
    399     public String getPropertyAsString(String name) {
    400         Integer index = propertyIndex(name);
    401         if (index != null) {
    402             return getProperty(index.intValue()).toString();
    403         } else {
    404             throw new RuntimeException("illegal property: " + name);
    405         }
    406     }
    407 
    408     /**
    409      * Knows whether the given property exists
    410      */
    411     public boolean hasProperty(final String name) {
    412         if (propertyIndex(name) != null) {
    413             return true;
    414         } else {
    415             return false;
    416         }
    417     }
    418 
    419     /**
    420      * Get a property without chance of throwing an exception
    421      *
    422      * @return the property if it exists; if not, {@link NullSoapObject} is
    423      * returned
    424      */
    425     public Object getPropertySafely(final String name) {
    426         Integer i = propertyIndex(name);
    427         if (i != null) {
    428             return getProperty(i.intValue());
    429         } else {
    430             return new NullSoapObject();
    431         }
    432     }
    433 
    434     /**
    435      * Get the toString value of a property without chance of throwing an
    436      * exception
    437      *
    438      * @return the string value of the property if it exists; if not, #EMPTY_STRING is
    439      * returned
    440      */
    441     public String getPropertySafelyAsString(final String name) {
    442         Integer i = propertyIndex(name);
    443         if (i != null) {
    444             Object foo = getProperty(i.intValue());
    445             if (foo == null) {
    446                 return EMPTY_STRING;
    447             } else {
    448                 return foo.toString();
    449             }
    450         } else {
    451             return EMPTY_STRING;
    452         }
    453     }
    454 
    455     /**
    456      * Get a property without chance of throwing an exception. An object can be
    457      * provided to this method; if the property is not found, this object will
    458      * be returned.
    459      *
    460      * @param defaultThing the object to return if the property is not found
    461      * @return the property if it exists; defaultThing if the property does not
    462      * exist
    463      */
    464     public Object getPropertySafely(final String name, final Object defaultThing) {
    465         Integer i = propertyIndex(name);
    466         if (i != null) {
    467             return getProperty(i.intValue());
    468         } else {
    469             return defaultThing;
    470         }
    471     }
    472 
    473     /**
    474      * Get the toString value of a property without chance of throwing an
    475      * exception. An object can be provided to this method; if the property is
    476      * not found, this object's string representation will be returned.
    477      *
    478      * @param defaultThing toString of the object to return if the property is not found
    479      * @return the property toString if it exists; defaultThing toString if the
    480      * property does not exist, if the defaultThing is null #EMPTY_STRING
    481      * is returned
    482      */
    483     public String getPropertySafelyAsString(final String name,
    484             final Object defaultThing) {
    485         Integer i = propertyIndex(name);
    486         if (i != null) {
    487             Object property = getProperty(i.intValue());
    488             if (property != null) {
    489                 return property.toString();
    490             } else {
    491                 return EMPTY_STRING;
    492             }
    493         } else {
    494             if (defaultThing != null) {
    495                 return defaultThing.toString();
    496             } else {
    497                 return EMPTY_STRING;
    498             }
    499         }
    500     }
    501 
    502     /**
    503      * Get the primitive property with the given name.
    504      *
    505      * @return PropertyInfo containing an empty string if property either complex or empty
    506      */
    507     public Object getPrimitiveProperty(final String name) {
    508         Integer index = propertyIndex(name);
    509         if (index != null) {
    510             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    511             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    512                 return propertyInfo.getValue();
    513             } else {
    514                 propertyInfo = new PropertyInfo();
    515                 propertyInfo.setType(String.class);
    516                 propertyInfo.setValue(EMPTY_STRING);
    517                 propertyInfo.setName(name);
    518                 return (Object) propertyInfo.getValue();
    519             }
    520         } else {
    521             throw new RuntimeException("illegal property: " + name);
    522         }
    523     }
    524 
    525     /**
    526      * Get the toString value of the primitive property with the given name.
    527      * Returns empty string if property either complex or empty
    528      *
    529      * @return the string value of the property
    530      */
    531     public String getPrimitivePropertyAsString(final String name) {
    532         Integer index = propertyIndex(name);
    533         if (index != null) {
    534             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    535             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    536                 return propertyInfo.getValue().toString();
    537             } else {
    538                 return EMPTY_STRING;
    539             }
    540         } else {
    541             throw new RuntimeException("illegal property: " + name);
    542         }
    543     }
    544 
    545     /**
    546      * Get the toString value of a primitive property without chance of throwing an
    547      * exception
    548      *
    549      * @return the string value of the property if it exists and is primitive; if not,
    550      * #EMPTY_STRING is
    551      * returned
    552      */
    553     public Object getPrimitivePropertySafely(final String name) {
    554         Integer index = propertyIndex(name);
    555         if (index != null) {
    556             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    557             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    558                 return propertyInfo.getValue().toString();
    559             } else {
    560                 propertyInfo = new PropertyInfo();
    561                 propertyInfo.setType(String.class);
    562                 propertyInfo.setValue(EMPTY_STRING);
    563                 propertyInfo.setName(name);
    564                 return (Object) propertyInfo.getValue();
    565             }
    566         } else {
    567             return new NullSoapObject();
    568         }
    569     }
    570 
    571     /**
    572      * Get the toString value of a primitive property without chance of throwing an
    573      * exception
    574      *
    575      * @return the string value of the property if it exists and is primitive; if not,
    576      * #EMPTY_STRING is
    577      * returned
    578      */
    579     public String getPrimitivePropertySafelyAsString(final String name) {
    580         Integer index = propertyIndex(name);
    581         if (index != null) {
    582             PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
    583             if (propertyInfo.getType() != SoapObject.class && propertyInfo.getValue() != null) {
    584                 return propertyInfo.getValue().toString();
    585             } else {
    586                 return EMPTY_STRING;
    587             }
    588         } else {
    589             return EMPTY_STRING;
    590         }
    591     }
    592 
    593     private Integer propertyIndex(String name) {
    594         if (name != null) {
    595             for (int i = 0; i < properties.size(); i++) {
    596                 if (name.equals(((PropertyInfo) properties.elementAt(i)).getName())) {
    597                     return new Integer(i);
    598                 }
    599             }
    600         }
    601         return null;
    602     }
    603 
    604 
    605     private Integer propertyIndex(String namespace, String name) {
    606         if (name != null && namespace != null) {
    607             for (int i = 0; i < properties.size(); i++) {
    608                 PropertyInfo info = (PropertyInfo) properties.elementAt(i);
    609                 if (name.equals(info.getName()) && namespace.equals(info.getNamespace())) {
    610                     return new Integer(i);
    611                 }
    612             }
    613         }
    614         return null;
    615     }
    616 
    617     /**
    618      * Returns the number of properties
    619      *
    620      * @return the number of properties
    621      */
    622     public int getPropertyCount() {
    623         return properties.size();
    624     }
    625 
    626     /**
    627      * Places PropertyInfo of desired property into a designated PropertyInfo
    628      * object. Just calls #getPropertyInfo and discards any provided properties.
    629      *
    630      * @param index        index of desired property
    631      * @param properties   this parameter is ignored
    632      * @param propertyInfo designated retainer of desired property
    633      */
    634     public void getPropertyInfo(int index, Hashtable properties, PropertyInfo propertyInfo) {
    635         getPropertyInfo(index, propertyInfo);
    636     }
    637 
    638     /**
    639      * Places PropertyInfo of desired property into a designated PropertyInfo
    640      * object
    641      *
    642      * @param index        index of desired property
    643      * @param propertyInfo designated retainer of desired property
    644      */
    645     public void getPropertyInfo(int index, PropertyInfo propertyInfo) {
    646         Object element = properties.elementAt(index);
    647         if (element instanceof PropertyInfo) {
    648             PropertyInfo p = (PropertyInfo) element;
    649             propertyInfo.name = p.name;
    650             propertyInfo.namespace = p.namespace;
    651             propertyInfo.flags = p.flags;
    652             propertyInfo.type = p.type;
    653             propertyInfo.elementType = p.elementType;
    654             propertyInfo.value = p.value;
    655             propertyInfo.multiRef = p.multiRef;
    656         } else {
    657             // SoapObject
    658             propertyInfo.name = null;
    659             propertyInfo.namespace = null;
    660             propertyInfo.flags = 0;
    661             propertyInfo.type = null;
    662             propertyInfo.elementType = null;
    663             propertyInfo.value = element;
    664             propertyInfo.multiRef = false;
    665         }
    666     }
    667 
    668     public PropertyInfo getPropertyInfo(int index) {
    669         Object element = properties.elementAt(index);
    670         if (element instanceof PropertyInfo) {
    671             PropertyInfo p = (PropertyInfo) element;
    672             return p;
    673         } else {
    674             // SoapObject
    675             return null;
    676         }
    677     }
    678 
    679     /**
    680      * Creates a new SoapObject based on this, allows usage of SoapObjects as
    681      * templates. One application is to set the expected return type of a soap
    682      * call if the server does not send explicit type information.
    683      *
    684      * @return a copy of this.
    685      */
    686     public SoapObject newInstance() {
    687         SoapObject o = new SoapObject(namespace, name);
    688         for (int propIndex = 0; propIndex < properties.size(); propIndex++) {
    689             Object prop = properties.elementAt(propIndex);
    690             if (prop instanceof PropertyInfo) {
    691                 PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(propIndex);
    692                 PropertyInfo propertyInfoClonned = (PropertyInfo) propertyInfo.clone();
    693                 o.addProperty(propertyInfoClonned);
    694             } else if (prop instanceof SoapObject) {
    695                 o.addSoapObject(((SoapObject) prop).newInstance());
    696             }
    697         }
    698         for (int attribIndex = 0; attribIndex < getAttributeCount(); attribIndex++) {
    699             AttributeInfo newAI = new AttributeInfo();
    700             getAttributeInfo(attribIndex, newAI);
    701             AttributeInfo attributeInfo = newAI; // (AttributeInfo)
    702             // attributes.elementAt(attribIndex);
    703             o.addAttribute(attributeInfo);
    704         }
    705         return o;
    706     }
    707 
    708     /**
    709      * Sets a specified property to a certain value.
    710      *
    711      * @param index the index of the specified property
    712      * @param value the new value of the property
    713      */
    714     public void setProperty(int index, Object value) {
    715         Object prop = properties.elementAt(index);
    716         if (prop instanceof PropertyInfo) {
    717             ((PropertyInfo) prop).setValue(value);
    718         }
    719         // TODO: not sure how you want to handle an exception here if the index points to a
    720         // SoapObject
    721     }
    722 
    723     /**
    724      * Adds a property (parameter) to the object. This is essentially a sub
    725      * element.
    726      *
    727      * @param name  The name of the property
    728      * @param value the value of the property
    729      */
    730     public SoapObject addProperty(String name, Object value) {
    731         PropertyInfo propertyInfo = new PropertyInfo();
    732         propertyInfo.name = name;
    733         propertyInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value
    734                 .getClass();
    735         propertyInfo.value = value;
    736         return addProperty(propertyInfo);
    737     }
    738 
    739     /**
    740      * Adds a property (parameter) to the object. This is essentially a sub
    741      * element.
    742      *
    743      * @param namespace The namespace of the property
    744      * @param name      The name of the property
    745      * @param value     the value of the property
    746      */
    747     public SoapObject addProperty(String namespace, String name, Object value) {
    748         PropertyInfo propertyInfo = new PropertyInfo();
    749         propertyInfo.name = name;
    750         propertyInfo.namespace = namespace;
    751         propertyInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value
    752                 .getClass();
    753         propertyInfo.value = value;
    754         return addProperty(propertyInfo);
    755     }
    756 
    757     /**
    758      * Add a property only if the value is not null.
    759      *
    760      * @param namespace The namespace of the property
    761      * @param name      The name of the property
    762      * @param value     the value of the property
    763      */
    764     public SoapObject addPropertyIfValue(String namespace, String name, Object value) {
    765         if (value != null) {
    766             return addProperty(namespace, name, value);
    767         } else {
    768             return this;
    769         }
    770     }
    771 
    772     /**
    773      * Add a property only if the value is not null.
    774      */
    775     public SoapObject addPropertyIfValue(String name, Object value) {
    776         if (value != null) {
    777             return addProperty(name, value);
    778         } else {
    779             return this;
    780         }
    781     }
    782 
    783     /**
    784      * Add a property only if the value is not null.
    785      */
    786     public SoapObject addPropertyIfValue(PropertyInfo propertyInfo, Object value) {
    787         if (value != null) {
    788             propertyInfo.setValue(value);
    789             return addProperty(propertyInfo);
    790         } else {
    791             return this;
    792         }
    793     }
    794 
    795     /**
    796      * Adds a property (parameter) to the object. This is essentially a sub
    797      * element.
    798      *
    799      * @param propertyInfo designated retainer of desired property
    800      */
    801     public SoapObject addProperty(PropertyInfo propertyInfo) {
    802         properties.addElement(propertyInfo);
    803         return this;
    804     }
    805 
    806     /**
    807      * Ad the propertyInfo only if the value of it is not null.
    808      */
    809     public SoapObject addPropertyIfValue(PropertyInfo propertyInfo) {
    810         if (propertyInfo.value != null) {
    811             properties.addElement(propertyInfo);
    812             return this;
    813         } else {
    814             return this;
    815         }
    816     }
    817 
    818     /**
    819      * Adds a SoapObject the properties array. This is a sub element to
    820      * allow nested SoapObjects
    821      *
    822      * @param soapObject to be added as a property of the current object
    823      */
    824     public SoapObject addSoapObject(SoapObject soapObject) {
    825         properties.addElement(soapObject);
    826         return this;
    827     }
    828 
    829     /**
    830      * Generate a {@code String} describing this object.
    831      */
    832     public String toString() {
    833         StringBuffer buf = new StringBuffer(EMPTY_STRING + name + "{");
    834         for (int i = 0; i < getPropertyCount(); i++) {
    835             Object prop = properties.elementAt(i);
    836             if (prop instanceof PropertyInfo) {
    837                 buf.append(EMPTY_STRING)
    838                         .append(((PropertyInfo) prop).getName())
    839                         .append("=")
    840                         .append(getProperty(i))
    841                         .append("; ");
    842             } else {
    843                 buf.append(((SoapObject) prop).toString());
    844             }
    845         }
    846         buf.append("}");
    847         return buf.toString();
    848     }
    849 
    850     public Object getInnerText() {
    851         return innerText;
    852     }
    853 
    854     public void setInnerText(Object innerText) {
    855         this.innerText = innerText;
    856     }
    857 
    858     public void removePropertyInfo(Object info) {
    859         properties.remove(info);
    860     }
    861 }
    862