internal bool TrySetObjectValue(IPersist host, int paramIndex, int refId, int[] listNextLevel)
 {
     if (_deferListItems)
     {
         return(false);
     }
     try
     {
         if (host != null && Entities.TryGetValue(refId, out IPersist refEntity))
         {
             PropertyValue.Init(refEntity);
             host.Parse(paramIndex, PropertyValue, listNextLevel);
             return(true);
         }
     }
     catch (Exception e)
     {
         // return silently if this kind of error has already been reported
         if (_errors.AddPropertyNotSet(host, paramIndex, PropertyValue, e))
         {
             Logger?.LogError(LogEventIds.FailedPropertySetter, e, "Entity #{0,-5} {1}, error at parameter {2}", refId, host.GetType().Name.ToUpper(), paramIndex + 1);
             ErrorCount++;
         }
     }
     return(false);
 }
        private void EndElement(XmlReader input, XmlNodeType prevInputType, string prevInputName, out IPersistEntity writeEntity)
        {
            try
            {
                // before end element, we need to deal with SetCollection
                var collectionProperty = _currentNode as XmlCollectionProperty;
                if (collectionProperty != null)
                {
                    // SetCollection will handle SetValue for Collection
                    var cType = collectionProperty.CType;
                    switch (cType)
                    {
                    case CollectionType.List:
                    case CollectionType.ListUnique:
                        collectionProperty.Entities.Sort(XmlCollectionProperty.CompareNodes);
                        break;

                    case CollectionType.Set:
                        break;

                    default:
                        throw new Exception("Unknown list type, " + cType);
                    }

                    foreach (var item in collectionProperty.Entities)
                    {
                        var entity = item as XmlEntity;
                        if (entity == null)
                        {
                            continue;
                        }
                        var node            = entity;
                        var collectionOwner = entity.Parent.Parent as XmlEntity;
                        var collection      = entity.Parent as XmlCollectionProperty; //the collection to add to;
                        if (collectionOwner == null)
                        {
                            continue;
                        }
                        IPersist ifcCollectionOwner = collectionOwner.Entity;
                        var      pv = new PropertyValue();
                        pv.Init(node.Entity);
                        if (collection != null)
                        {
                            ifcCollectionOwner.Parse(collection.PropertyIndex - 1, pv, null);
                        }
                    }
                }
                else if (_currentNode.Parent is XmlProperty)
                {
                    var propNode = (XmlProperty)_currentNode.Parent;
                    var entity   = _currentNode as XmlEntity;
                    if (entity != null)
                    {
                        var entityNode = entity;
                        propNode.SetValue(entityNode.Entity);
                    }
                    else if (_currentNode is XmlExpressType)
                    {
                        //create ExpressType, call ifcparse with propindex and object
                        //((XmlProperty)_currentNode.Parent).SetValue((XmlExpressType)_currentNode);

                        var expressNode = (XmlExpressType)_currentNode;
                        if (expressNode.Type != propNode.Property.PropertyType)
                        {
                            //propNode.SetValue(expressNode);
                            ExpressType expressType;
                            if (IsIfcType(input.LocalName, out expressType))
                            //we have an IPersistIfc
                            {
                                var param = new object[1];
                                param[0] = expressNode.Value;
                                var ent = (IPersist)Activator.CreateInstance(expressType.Type, param);

                                propNode.SetValue(ent);
                            }
                        }
                        else
                        {
                            propNode.SetValue(expressNode.Value, Primitives[expressNode.Type.Name]);
                        }
                    }
                    else if (_currentNode is XmlBasicType)
                    {
                        //set PropertyValue to write type boolean, integer, call ifcparse with string

                        var basicNode = (XmlBasicType)_currentNode;
                        propNode.SetValue(basicNode.Value, basicNode.Type);
                    }
                }


                else if (prevInputType == XmlNodeType.Element && prevInputName == input.LocalName &&
                         _currentNode is XmlProperty && _currentNode.Parent is XmlEntity)
                {
                    // WE SHOULDNT EXECUTE THE FOLLOWING CODE IF THIS PROPERTY ALREADY CALLED SETVALUE
                    var node    = (XmlProperty)_currentNode;
                    var propVal = new PropertyValue();
                    var t       = node.Property.PropertyType;
                    if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        t = Nullable.GetUnderlyingType(t);
                    }
                    IExpressValueType et = null;
                    if (t != null && typeof(IExpressValueType).IsAssignableFrom(t))
                    {
                        et = (IExpressValueType)(Activator.CreateInstance(t));
                    }

                    var pt = StepParserType.Undefined;
                    if (et != null)
                    {
                        pt = Primitives[et.UnderlyingSystemType.Name];
                    }
                    else
                    {
                        if (t != null && t.IsEnum)
                        {
                            pt = StepParserType.Enum;
                        }
                        else if (t != null && Primitives.ContainsKey(t.Name))
                        {
                            pt = Primitives[t.Name];
                        }
                    }

                    if (pt != StepParserType.Undefined)
                    {
                        switch (pt.ToString().ToLower())
                        {
                        case "string":
                            propVal.Init("'" + input.Value + "'", pt);
                            break;

                        case "boolean":
                            propVal.Init(Convert.ToBoolean(input.Value) ? ".T." : ".F", pt);
                            break;

                        default:
                            propVal.Init(input.Value, pt);
                            break;
                        }

                        ((XmlEntity)node.Parent).Entity.Parse(node.PropertyIndex - 1, propVal, null);
                    }
                }

                else if (_currentNode.Parent is XmlCollectionProperty && !(_currentNode.Parent is XmlUosCollection))
                {
                    var entity = _currentNode as XmlEntity;
                    if (entity != null)
                    {
                        ((XmlCollectionProperty)entity.Parent).Entities.Add(entity);
                    }
                    else if (_currentNode is XmlExpressType)
                    {
                        var expressNode = (XmlExpressType)_currentNode;
                        //actualEntityType is the actual type of the value to create
                        var actualEntityType = expressNode.Type;
                        //Determine if the Express Type is a Nullable, if so get the type of the Nullable
                        if (actualEntityType.IsGenericType && actualEntityType.GetGenericTypeDefinition() == typeof(Nullable <>))
                        {
                            actualEntityType = Nullable.GetUnderlyingType(actualEntityType);
                        }

                        //need to resolve what the Parser type is
                        //if the generic type of the collection is different from the actualEntityType then we need to create an entity and call Ifc Parse
                        //otherwise we need to call Ifcparse with a string value and the type of the underlying type
                        var collection                   = (XmlCollectionProperty)_currentNode.Parent; //the collection to add to;
                        var collectionValueType          = collection.Property.PropertyType;
                        var collectionGenericType        = GetItemTypeFromGenericType(collectionValueType);
                        var genericTypeIsSameAsValueType = (collectionGenericType == actualEntityType);
                        var pv = new PropertyValue();

                        if (genericTypeIsSameAsValueType) //call IfcParse with string value and parser type
                        {
                            var actualEntityValue = (IExpressValueType)(Activator.CreateInstance(actualEntityType));
                            //resolve the underlying type
                            var parserType = Primitives[actualEntityValue.UnderlyingSystemType.Name];
                            if (parserType == StepParserType.String)
                            {
                                pv.Init("'" + expressNode.Value + "'", parserType);
                            }
                            else
                            {
                                pv.Init(expressNode.Value, parserType);
                            }
                        }
                        else //call IfcParse with an entity
                        {
                            var param = new object[1];
                            param[0] = expressNode.Value;
                            var actualEntityValue = (IExpressValueType)(Activator.CreateInstance(expressNode.Type, param));
                            pv.Init(actualEntityValue);
                        }

                        var collectionOwner = _currentNode.Parent.Parent as XmlEntity; //go to owner of collection
                        if (collectionOwner != null)
                        {
                            IPersist ifcCollectionOwner = collectionOwner.Entity;
                            ifcCollectionOwner.Parse(collection.PropertyIndex - 1, pv, null);
                        }
                    }
                    else if (_currentNode is XmlBasicType)
                    {
                        var basicNode       = (XmlBasicType)_currentNode;
                        var collectionOwner = _currentNode.Parent.Parent as XmlEntity;
                        var collection      = (XmlCollectionProperty)_currentNode.Parent; //the collection to add to;
                        if (collectionOwner != null)
                        {
                            IPersist ifcCollectionOwner = collectionOwner.Entity;
                            var      pv = new PropertyValue();
                            pv.Init(basicNode.Value, basicNode.Type);
                            ifcCollectionOwner.Parse(collection.PropertyIndex - 1, pv, null);
                        }
                    }
                }


                writeEntity = null;
                if (_currentNode.Parent == null)
                {
                    return;
                }
                var currentNode = _currentNode as XmlEntity;
                if (currentNode != null)
                {
                    writeEntity = currentNode.Entity;
                }
                _currentNode = _currentNode.Parent;
            }
            catch (Exception e)
            {
                throw new Exception("Error reading IfcXML data at node " + input.LocalName, e);
            }
        }