/// <summary>
        /// 
        /// </summary>
        /// <param name="p21Instance"></param>
        /// <returns></returns>
        public static uint Add(P21Instance p21Instance)
        {
            if (p21Instance == null) return 0;

            if (p21Instance.IsDerived) return 0;

            if (p21Instance.EIN <= 0)
            {

                Instance._index = Instance._index + Instance._interval;
            }
            //else
            //{
            //    throw new NotSupportedException();
            //}
            //else
            //{
            //    Instance._index = p21Instance.EIN;
            //}

            return Add(Instance._index, p21Instance);
        }
        private object ConvertSwitch(P21Instance p21Instance, Parameter attribute)
        {
            object retValue = null;
            switch (attribute.ParameterType)
            {
                #region case

                case SParamType.ENTITY:

                    #region entity

                    var pop = attribute as ParamEntity;
                    if (pop == null) return null;
                    var value
                        = _dataSection.ContainsKey(pop.EntityInstance.EntityInstanceName)
                              ? _dataSection[pop.EntityInstance.EntityInstanceName]
                              : ConvertInstance(pop.EntityInstance);
                    AddReferenced(p21Instance, value);
                    retValue = value;
                    break;

                    #endregion entity

                case SParamType.NUMBER:
                    if (attribute.SchemaAttDef.Type is SParamNamed)
                    {
                        SParamNamed sParam = attribute.SchemaAttDef.Type as SParamNamed;
                        var aparam =
                            //Activator.CreateInstance(_ifcAssemblyName, _ifcAssemblyName + "." + sParam.NamedRefString)
                            Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + sParam.NamedRefString)
                                     .Unwrap() as NUMBER;
                        aparam.Value = ((ParamReal)attribute).RealValue;
                        retValue = aparam;
                    }
                    else
                    {
                        NUMBER realValue = ((ParamReal)attribute).RealValue;
                        retValue = realValue;
                    }
                    break;
                case SParamType.REAL:

                    #region real

                    if (attribute.SchemaAttDef.Type is SParamNamed)
                    {
                        SParamNamed sParam = attribute.SchemaAttDef.Type as SParamNamed;
                        var aparam =
                            Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + sParam.NamedRefString)
                                     .Unwrap() as REAL;
                        aparam.Value = ((ParamReal)attribute).RealValue;
                        retValue = aparam;
                    }
                    else
                    {
                        REAL realValue = ((ParamReal)attribute).RealValue;
                        retValue = realValue;
                    }
                    break;

                    #endregion real

                case SParamType.INTEGER:

                    #region integer

                    if (attribute.SchemaAttDef.Type is SParamNamed)
                    {
                        SParamNamed sParam = attribute.SchemaAttDef.Type as SParamNamed;
                        var aparam =
                            Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + sParam.NamedRefString)
                                     .Unwrap() as INTEGER;
                        aparam.Value = ((ParamInteger)attribute).IntegerValue;
                        retValue = aparam;
                    }
                    else
                    {
                        INTEGER intValue = ((ParamInteger)attribute).IntegerValue;
                        //fieldInfo.SetValue(ains, intValue);
                        retValue = intValue;
                    }
                    break;

                    #endregion integer

                case SParamType.STRING:

                    #region string

                    if (attribute.SchemaAttDef.Type is SParamNamed)
                    {
                        SParamNamed sParam = attribute.SchemaAttDef.Type as SParamNamed;
                        var aparam =
                            Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + sParam.NamedRefString)
                                     .Unwrap() as STRING;
                        aparam.Value = ((ParamString)attribute).StringValue;
                        retValue = aparam;
                    }
                    else
                    {
                        //throw new NotImplementedException();
                        //STRING strValue = ((ParamString)attribute).StringValue;
                        ////fieldInfo.SetValue(ains, strValue);
                        //retValue = strValue;
                    }
                    break;

                    #endregion string

                case SParamType.ENUMERATION:

                    #region enumeration

                    string estr = ((ParamEnum)attribute).EnumerationValueString;
                    SParamNamed eparam = attribute.SchemaAttDef.Type as SParamNamed;

                    var fi = _ifcAssembly.GetType(_ifcAssembly.GetName().Name + "." + eparam.NamedRefString).GetField(estr);
                    retValue = fi.GetValue(null);
                    break;

                    #endregion enumeration

                case SParamType.LOGICAL:
                case SParamType.BOOLEAN:

                    #region boolean

                    if (attribute.SchemaAttDef.Type is SParamNamed)
                    {
                        SParamNamed sParam = attribute.SchemaAttDef.Type as SParamNamed;
                        var aparam =
                            Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + sParam.NamedRefString)
                                     .Unwrap();
                        if (aparam is BOOLEAN)
                        {
                            if (((ParamBoolean)attribute).BoolValue == 1)
                            {
                                ((BOOLEAN)aparam).Value = true;
                            }
                            else
                            {
                                ((BOOLEAN)aparam).Value = false;
                            }
                        }
                        else if (aparam is LOGICAL)
                        {
                            ((LOGICAL)aparam).Value = ((ParamBoolean)attribute).BoolValue;
                        }
                        else
                        {
                            throw new InvalidDataException();
                        }
                        retValue = aparam;
                    }
                    else
                    {
                        if (attribute.SchemaAttDef.Type.ParamType == SParamType.BOOLEAN)
                        {
                            BOOLEAN bvalue;
                            if (((ParamBoolean)attribute).BoolValue == 1)
                            {
                                bvalue = true;
                            }
                            else
                                bvalue = false;
                            retValue = bvalue;
                        }
                        else if (attribute.SchemaAttDef.Type.ParamType == SParamType.LOGICAL)
                        {
                            LOGICAL bvalue = new LOGICAL();
                            bvalue.Value = ((ParamBoolean)attribute).BoolValue;
                            retValue = bvalue;
                        }
                        else
                        {
                            throw new InvalidDataException();
                        }
                    }
                    break;

                    #endregion boolean

                case SParamType.SELECT:

                    #region select

                    SParamNamed selectParam = attribute.SchemaAttDef.Type as SParamNamed;

                    var selectAtt =
                        Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + selectParam.NamedRefString)
                                 .Unwrap();

                    ParamSelect paramSelect = attribute as ParamSelect;

                    Type insType = _ifcAssembly.GetType(_ifcAssembly.GetName().Name + "." + paramSelect.SelectName, false, true);
                    var pSelect =
                        //Activator.CreateInstance(insType);
                        Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + insType.Name).Unwrap();

                    switch (paramSelect.SelectValue.ParameterType)
                    {
                        case SParamType.INTEGER:
                            var ri = paramSelect.SelectValue as ParamInteger;
                            ((INTEGER)pSelect).Value = ri.IntegerValue;
                            break;
                        case SParamType.REAL:
                            var rr = paramSelect.SelectValue as ParamReal;
                            ((REAL)pSelect).Value = rr.RealValue;
                            break;
                        case SParamType.STRING:
                            var rs = paramSelect.SelectValue as ParamString;
                            ((STRING)pSelect).Value = rs.StringValue;
                            break;
                        case SParamType.BOOLEAN:
                            var rb = paramSelect.SelectValue as ParamBoolean;
                            ((BOOLEAN)pSelect).Value = rb.BoolValue == 1;
                            break;
                        default:
                            throw new NotImplementedException();
                        //                            break;
                    }
                    Type tSelect = selectAtt.GetType();
                    tSelect.GetField("Value").SetValue(selectAtt, pSelect);

                    retValue = selectAtt;
                    break;

                    #endregion select

                case SParamType.TYPE:

                    #region Type in Collection form

                    SParamNamed tParamName = attribute.SchemaAttDef.Type as SParamNamed;

                    if (tParamName == null)
                    {
                        throw new InvalidCastException();
                    }
                    if (tParamName.NamedReference is STypeCollection)
                    {
                        var stc = tParamName.NamedReference as STypeCollection;

                        var aparam =
                            Activator.CreateInstance(_ifcAssembly.GetName().Name,
                                                     _ifcAssembly.GetName().Name + "." + tParamName.NamedRefString).Unwrap()
                            as IList;

                        ParamList tParamList = attribute as ParamList;

                        switch (stc.CollectionType)
                        {
                            case SParamType.INTEGER:
                                foreach (var pitem in tParamList.ParameterList)
                                {
                                    var p = pitem as ParamInteger;
                                    INTEGER p21Int = p.IntegerValue;
                                    aparam.Add(p21Int);
                                }

                                break;
                            case SParamType.REAL:
                                foreach (var pitem in tParamList.ParameterList)
                                {
                                    var p = pitem as ParamReal;
                                    REAL p21real = p.RealValue;
                                    aparam.Add(p21real);
                                }
                                break;
                            default:
                                throw new NotImplementedException();
                            //                                break;
                        }
                        //fieldInfo.SetValue(ains, aparam);
                        retValue = aparam;
                        //throw new NotImplementedException();
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }

                    break;

                    #endregion Type in Collection form

                case SParamType.UNSET:

                    break;
                case SParamType.SELFDERIVED:

                    #region derived

                    if (attribute.SchemaAttDef.Type is SParamNamed)
                    {
                        var sde = attribute.SchemaAttDef.Type as SParamNamed;
                        var aparam =
                            Activator.CreateInstance(_ifcAssembly.GetName().Name, _ifcAssembly.GetName().Name + "." + sde.NamedRefString)
                                     .Unwrap();

                        if (aparam.GetType().IsClass)
                        {
                            ((P21Base)aparam).IsDerived = true;
                        }
                        else
                        {
                            Type apType = aparam.GetType();
                            var pbase = new P21Base { IsDerived = true };
                            apType.GetField("Value").SetValue(aparam, pbase);
                        }

                        //aparam.isDerived = true;
                        retValue = aparam;
                    }
                    else
                    {
                        var sde = attribute.SchemaAttDef.Type as SParameter;
                        var aparam =
                            Activator.CreateInstance(EbConstants.Part21NSName,
                                                     EbConstants.Part21NSName + "." + sde.ParamTypeString).Unwrap() as
                            P21Base;
                        aparam.IsDerived = true;
                        retValue = aparam;
                    }

                    break;

                    #endregion derived

                case SParamType.ARRAY:
                case SParamType.LIST:
                case SParamType.SET:
                case SParamType.BAG:

                    #region array

                    SParamCollection collection = attribute.SchemaAttDef.Type as SParamCollection;
                    SParameter pRef = collection.ParamReference;
                    ParamList pList = attribute as ParamList;

                    IList ppList;
                    Type spnType;
                    if (pRef is SParamNamed)
                    {
                        SParamNamed spn = pRef as SParamNamed;
                        //spnType = Type.GetType(_ifcAssemblyName + "." + spn.NamedRefString);
                        spnType = _ifcAssembly.GetType(_ifcAssembly.GetName().Name + "." + spn.NamedRefString);

                        var a = typeof(System.Collections.Generic.List<>);

                        Type listType = a.MakeGenericType(spnType);
                        // Type.GetType("System.Collections.Generic.List").MakeGenericType(spnType);
                        //Type.GetType("System.Collections.Generic.List").MakeGenericType(spnType);
                        ppList = Activator.CreateInstance(listType) as IList;
                    }
                    else if (pRef is SParamCollection)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        //string assm = EbConstants.Part21NSName+"." + pRef.ParamTypeString + ", " + p21Assembly.FullName;
                        spnType = P21Assembly.GetType(EbConstants.Part21NSName + "." + pRef.ParamTypeString);
                        //Type.GetType(assm);

                        var a = typeof(System.Collections.Generic.List<>);
                        Type listType = a.MakeGenericType(spnType);
                        //Type.GetType("System.Collections.Generic.List").MakeGenericType(spnType);
                        //Type.GetType("System.Collections.Generic.List").MakeGenericType(spnType);
                        ppList = Activator.CreateInstance(listType) as IList;
                    }

                    if (pList.ParameterList.Count > 0)
                    {
                        foreach (var pItem in pList.ParameterList)
                        {
                            var convItem = ConvertSwitch(p21Instance, pItem);
                            if (convItem == null) continue;

                            if (spnType.IsClass)
                                ppList.Add(convItem);
                            else
                            {
                                var sAtt = Activator.CreateInstance(spnType);
                                Type tSel = sAtt.GetType();
                                while (!(convItem is P21Base))
                                {
                                    convItem = convItem.GetType().GetField("Value").GetValue(convItem);
                                }

                                tSel.GetField("Value").SetValue(sAtt, convItem);
                                ppList.Add(sAtt);
                            }
                        }
                    }

                    //fieldInfo.SetValue(ains, ppList);

                    retValue = ppList;
                    break;

                    #endregion array

                default:
                    throw new NotImplementedException();
                //                    break;

                #endregion case
            }

            return retValue;
        }
        private void ConvertAttribute(Parameter att, P21Instance p21Instance)
        {
            if (att.ParameterType == SParamType.UNSET) return;
            var attName = att.SchemaAttDef.Name;
            FieldInfo fieldInfo = p21Instance.GetType().GetField(attName);

            object attribute = ConvertSwitch(p21Instance, att);

            if (attribute == null) return;

            if (fieldInfo.FieldType.IsClass)
                fieldInfo.SetValue(p21Instance, attribute);
            else
            {
                if (fieldInfo.FieldType == attribute.GetType())
                {
                    fieldInfo.SetValue(p21Instance, attribute);
                }
                else
                {
                    Type tSelect = fieldInfo.FieldType;
                    var selectAtt = Activator.CreateInstance(tSelect);
                    tSelect.GetField("Value").SetValue(selectAtt, attribute);
                    fieldInfo.SetValue(p21Instance, selectAtt);
                }
            }
        }
        private void AddToData(P21Instance p21Instance)
        {
            if (p21Instance.EIN == 0)
            {
                MessageBox.Show("what?");
            }

            _dataSection.TryAdd(p21Instance.EIN, p21Instance);

            var name = p21Instance.GetType().Name;

            if (!_dataByType.ContainsKey(name))
            {
                _dataByType.TryAdd(name, new ConcurrentDictionary<uint, P21Instance>());
            }
            _dataByType[p21Instance.GetType().Name].TryAdd(p21Instance.EIN, p21Instance);
        }
 private void AddReferenced(P21Instance host, P21Instance attribute)
 {
     if (!_referencedEntities.ContainsKey(attribute.EIN))
     {
         _referencedEntities.TryAdd(attribute.EIN, new ConcurrentDictionary<uint, P21Instance>());
     }
     _referencedEntities[attribute.EIN].TryAdd(host.EIN, host);
 }
        public static uint Add(uint index, P21Instance p21Instance)
        {
            if (p21Instance == null) return 0;
            if (Instance._dataSection.ContainsKey(index)) return 0;
            if (!Instance._dataSection.TryAdd(index, p21Instance)) return 0;

            var name = p21Instance.GetType().Name;

            if (!Instance._dataByType.ContainsKey(name))
            {
                Instance._dataByType.TryAdd(name, new ConcurrentDictionary<uint, P21Instance>());
            }
            Instance._dataByType[p21Instance.GetType().Name].TryAdd(p21Instance.EIN, p21Instance);

            p21Instance.EIN = index;

            foreach (FieldInfo field in p21Instance.GetType().GetFields())
            {
                var ins = field.GetValue(p21Instance) as P21Instance;
                if (ins != null)
                {
                    Add(ins);
                    continue;
                }

                if (field.FieldType.IsValueType)
                {
                    var sel = field.GetValue(p21Instance);
                    var selval = sel.GetType().GetField("Value");
                    if (selval != null)
                    {
                        var select = selval.GetValue(sel) as P21Instance;

                        if (select != null)
                        {
                            Add(select);
                            continue;
                        }
                    }

                }

                if (!field.FieldType.IsGenericType) continue;
                var listIns = field.GetValue(p21Instance) as IList;
                if (listIns == null) continue;
                foreach (var instance in listIns)
                {
                    //if(instance == null) continue;

                    if (instance.GetType().IsSubclassOf(typeof(P21Instance)))
                    {
                        Add((P21Instance)instance);
                        continue;

                    }

                    var valField = instance.GetType().GetField("Value");
                    if (valField != null)
                    {
                        var select = valField.GetValue(instance) as P21Instance;

                        if (select != null)
                        {
                            Add(select);
                            continue;
                        }
                    }

                }
                //string a = listIns.ToString();
            }

            return p21Instance.EIN;
        }