public ChainedTypeSerializer (ICustomDataItemHandler handler, ITypeSerializer serializer)
		{
			this.handler = handler;
			this.serializer = serializer;
		}
		public CustomDataItemWrapper (ICustomDataItemHandler handler, object ob)
		{
			this.itemHandler = handler;
			this.ob = ob;
		}
		public CustomDataItemHandlerChain (ICustomDataItemHandler mainHandler, ICustomDataItemHandler subHandler)
		{
			this.mainHandler = mainHandler;
			this.subHandler = subHandler;
		}
        public void AddMap(RuntimeAddin addin, string xmlMap, string fileId)
        {
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(xmlMap);

            foreach (XmlElement elem in doc.DocumentElement.SelectNodes("DataItem"))
            {
                string tname = elem.GetAttribute("class");
                Type   type  = addin.GetType(tname);
                if (type == null)
                {
                    LoggingService.LogError("[SerializationMap " + fileId + "] Type not found: '" + tname + "'");
                    continue;
                }

                string cname  = elem.GetAttribute("name");
                string ftname = elem.GetAttribute("fallbackType");

                SerializationMap map;
                if (!maps.TryGetValue(type, out map))
                {
                    map         = new SerializationMap(type);
                    maps [type] = map;
                    map.FileId  = fileId;
                    if (cname.Length > 0 || ftname.Length > 0)
                    {
                        DataItemAttribute iat = new DataItemAttribute();
                        if (cname.Length > 0)
                        {
                            iat.Name = cname;
                        }
                        if (ftname.Length > 0)
                        {
                            iat.FallbackType = addin.GetType(ftname, true);
                        }
                        map.TypeAttributes.Add(iat);
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(cname))
                    {
                        throw new InvalidOperationException(string.Format("Type name for type '{0}' in map '{1}' already specified in another serialization map for the same type ({2}).", type, fileId, map.FileId));
                    }
                    if (!string.IsNullOrEmpty(ftname))
                    {
                        throw new InvalidOperationException(string.Format("Fallback type for type '{0}' in map '{1}' already specified in another serialization map for the same type ({2}).", type, fileId, map.FileId));
                    }
                }

                string customDataItem = elem.GetAttribute("customDataItem");
                if (customDataItem.Length > 0)
                {
                    ICustomDataItemHandler ch = (ICustomDataItemHandler)addin.CreateInstance(customDataItem, true);
                    if (map.CustomHandler != null)
                    {
                        map.CustomHandler = new CustomDataItemHandlerChain(map.CustomHandler, ch);
                    }
                    else
                    {
                        map.CustomHandler = ch;
                    }
                }

                ItemMember lastMember = null;
                int        litc       = 0;

                foreach (XmlElement att in elem.SelectNodes("ItemProperty|ExpandedCollection|LiteralProperty|ItemMember"))
                {
                    string     memberName = null;
                    ItemMember prevMember = lastMember;
                    lastMember = null;

                    if (att.Name == "LiteralProperty")
                    {
                        ItemMember mem = new ItemMember();
                        memberName        = mem.Name = "_literal_" + (++litc);
                        mem.Type          = typeof(string);
                        mem.InitValue     = att.GetAttribute("value");
                        mem.DeclaringType = map.Type;
                        map.ExtendedMembers.Add(mem);
                        ItemPropertyAttribute itemAtt = new ItemPropertyAttribute();
                        itemAtt.Name = att.GetAttribute("name");
                        map.AddMemberAttribute(mem, itemAtt);
                        lastMember = mem;
                        continue;
                    }
                    else if (att.Name == "ItemMember")
                    {
                        ItemMember mem = new ItemMember();
                        memberName        = mem.Name = att.GetAttribute("name");
                        mem.Type          = addin.GetType(att.GetAttribute("type"), true);
                        mem.DeclaringType = map.Type;
                        map.ExtendedMembers.Add(mem);
                        lastMember = mem;
                        continue;
                    }
                    else
                    {
                        memberName = att.GetAttribute("member");

                        Type   mt;
                        object mi;
                        if (!FindMember(map, memberName, out mi, out mt))
                        {
                            LoggingService.LogError("[SerializationMap " + fileId + "] Member '" + memberName + "' not found in type '" + tname + "'");
                            continue;
                        }

                        if (att.Name == "ItemProperty")
                        {
                            ItemPropertyAttribute itemAtt = new ItemPropertyAttribute();

                            string val = att.GetAttribute("name");
                            if (val.Length > 0)
                            {
                                itemAtt.Name = val;
                            }

                            val = att.GetAttribute("scope");
                            if (val.Length > 0)
                            {
                                itemAtt.Scope = val;
                            }

                            if (att.Attributes ["defaultValue"] != null)
                            {
                                if (mt.IsEnum)
                                {
                                    itemAtt.DefaultValue = Enum.Parse(mt, att.GetAttribute("defaultValue"));
                                }
                                else
                                {
                                    itemAtt.DefaultValue = Convert.ChangeType(att.GetAttribute("defaultValue"), mt);
                                }
                            }

                            val = att.GetAttribute("serializationDataType");
                            if (val.Length > 0)
                            {
                                itemAtt.SerializationDataType = addin.GetType(val, true);
                            }

                            val = att.GetAttribute("valueType");
                            if (val.Length > 0)
                            {
                                itemAtt.ValueType = addin.GetType(val, true);
                            }

                            val = att.GetAttribute("readOnly");
                            if (val.Length > 0)
                            {
                                itemAtt.ReadOnly = bool.Parse(val);
                            }

                            val = att.GetAttribute("writeOnly");
                            if (val.Length > 0)
                            {
                                itemAtt.WriteOnly = bool.Parse(val);
                            }

                            val = att.GetAttribute("fallbackType");
                            if (val.Length > 0)
                            {
                                itemAtt.FallbackType = addin.GetType(val, true);
                            }

                            val = att.GetAttribute("isExternal");
                            if (val.Length > 0)
                            {
                                itemAtt.IsExternal = bool.Parse(val);
                            }

                            val = att.GetAttribute("skipEmpty");
                            if (val.Length > 0)
                            {
                                itemAtt.SkipEmpty = bool.Parse(val);
                            }

                            map.AddMemberAttribute(mi, itemAtt);
                        }
                        else if (att.Name == "ExpandedCollection")
                        {
                            ExpandedCollectionAttribute eat = new ExpandedCollectionAttribute();
                            map.AddMemberAttribute(mi, eat);
                        }
                    }
                    if (prevMember != null)
                    {
                        prevMember.InsertBefore = memberName;
                    }
                }
            }
        }