protected void resolveReference(String id, Object obj)
        {
            Object hlp = idMap[id];

            if (hlp is FwdRef)
            {
                FwdRef f = (FwdRef)hlp;
                do
                {
                    if (f.obj is FvmSerializable)
                    {
                        ((FvmSerializable)f.obj).setProperty(f.index, obj);
                    }
                    else
                    {
                        ((List <object>)f.obj)[f.index] = obj;
                    }
                    f = f.next;
                } while (f != null);
            }
            else if (hlp != null)
            {
                throw new Exception("double ID");
            }
            idMap[id] = obj;
        }
        /**
         * Builds an object from the XML stream. This method is public for usage in conjuction with Marshal
         * subclasses. Precondition: On the start tag of the object or property, so href can be read.
         */

        public Object read(XmlPullParser parser, Object owner, int index, String namespace_, String name,
                           PropertyInfo expected)
        {
            String elementName = parser.getName();
            String href        = parser.getAttributeValue(null, HREF_LABEL);
            Object obj;

            if (href != null)
            {
                if (owner == null)
                {
                    throw new Exception("href at root level?!?");
                }
                href = getIdFromHref(href);
                obj  = idMap[href];
                if (obj == null || obj is FwdRef)
                {
                    FwdRef f = new FwdRef();
                    f.next      = (FwdRef)obj;
                    f.obj       = owner;
                    f.index     = index;
                    idMap[href] = f;
                    obj         = null;
                }
                parser.nextTag(); // start tag
                parser.require(XmlPullParser.END_TAG, null, elementName);
            }
            else
            {
                String nullAttr = parser.getAttributeValue(xsi, NIL_LABEL);
                String id       = parser.getAttributeValue(null, ID_LABEL);
                if (nullAttr == null)
                {
                    nullAttr = parser.getAttributeValue(xsi, NULL_LABEL);
                }
                if (nullAttr != null && SoapEnvelope.stringToBoolean(nullAttr))
                {
                    obj = null;
                    parser.nextTag();
                    parser.require(XmlPullParser.END_TAG, null, elementName);
                }
                else
                {
                    String type = parser.getAttributeValue(xsi, TYPE_LABEL);
                    if (type != null)
                    {
                        int cut = type.IndexOf(':');
                        name = type.Substring(cut + 1);
                        String prefix = cut == -1 ? "" : type.Substring(0, cut);
                        namespace_ = parser.getNamespace(prefix);
                    }
                    else if (name == null && namespace_ == null)
                    {
                        if (parser.getAttributeValue(enc, ARRAY_TYPE_LABEL) != null)
                        {
                            namespace_ = enc;
                            name       = ARRAY_MAPPING_NAME;
                        }
                        else
                        {
                            Object[] names = getInfo(expected.type, null);
                            namespace_ = (String)names[0];
                            name       = (String)names[1];
                        }
                    }
                    // be sure to set this flag if we don't know the types.
                    if (type == null)
                    {
                        implicitTypes = true;
                    }
                    obj = readInstance(parser, namespace_, name, expected);
                    if (obj == null)
                    {
                        obj = readUnknown(parser, namespace_, name);
                    }
                }
                // finally, care about the id....
                if (id != null)
                {
                    resolveReference(id, obj);
                }
            }

            parser.require(XmlPullParser.END_TAG, null, elementName);
            return(obj);
        }