public bool Resolve(ConcurrentDictionary <int, IPersistEntity> references, ExpressMetaData metadata)
        {
            IPersistEntity entity;

            if (references.TryGetValue(ReferenceEntityLabel, out entity))
            {
                var pv = new PropertyValue();
                pv.Init(entity);
                try
                {
                    _referencingEntity.Parse(_referencingPropertyId, pv, _nestedIndex);
                    return(true);
                }
                catch (Exception)
                {
                    var expressType = metadata.ExpressType(_referencingEntity);
                    //TODO put a logger message here
                    //EsentModel.Logger.ErrorFormat("Data Error. Cannot set the property = {0} of entity #{1} = {2} to entity #{3}, schema violation. Ignored",
                    //    expressType.Properties[_referencingPropertyId+1].PropertyInfo.Name,
                    //    _referencingEntity.EntityLabel,
                    //    _referencingEntity.GetType().Name,
                    //    ReferenceEntityLabel);
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
Пример #2
0
        private void SetPropertyFromString(ExpressMetaProperty property, IPersistEntity entity, string value, int[] pos, Type valueType = null)
        {
            var pIndex = property.EntityAttribute.Order - 1;
            var type   = valueType ?? property.PropertyInfo.PropertyType;

            type = GetNonNullableType(type);
            var propVal = new PropertyValue();

            if (type.IsValueType || type == typeof(string))
            {
                if (typeof(IExpressComplexType).IsAssignableFrom(type))
                {
                    var meta      = _metadata.ExpressType(type);
                    var values    = value.Split(_separator, StringSplitOptions.RemoveEmptyEntries);
                    var underType = meta.UnderlyingComplexType;
                    foreach (var v in values)
                    {
                        IPropertyValue pv;
                        if (InitPropertyValue(underType, v, out pv))
                        {
                            entity.Parse(pIndex, pv, pos);
                        }
                    }
                    return;
                }
                if (type.IsEnum)
                {
                    propVal.Init(value, StepParserType.Enum);
                    entity.Parse(pIndex, propVal, pos);
                    return;
                }

                //handle other value types
                if (typeof(IExpressValueType).IsAssignableFrom(type))
                {
                    var meta = _metadata.ExpressType(type);
                    type = meta.UnderlyingType;
                }
                IPropertyValue pVal;
                if (InitPropertyValue(type, value, out pVal))
                {
                    entity.Parse(pIndex, pVal, pos);
                }
                return;
            }

            //lists of value types will be serialized as lists. If this is not an IEnumerable this is not the case
            if (!typeof(IEnumerable).IsAssignableFrom(type) || !type.IsGenericType)
            {
                throw new XbimParserException("Unexpected enumerable type " + type.Name);
            }

            var genType = type.GetGenericArguments()[0];

            if (genType.IsValueType || genType == typeof(string))
            {
                //handle enumerable of value type and string
                var values = value.Split(_separator, StringSplitOptions.RemoveEmptyEntries);
                foreach (var v in values)
                {
                    SetPropertyFromString(property, entity, v, pos, genType);
                }
                return;
            }

            //rectangular nested lists can also be serialized as attribute if defined in configuration
            if (typeof(IEnumerable).IsAssignableFrom(genType))
            {
                //handle rectangular nested lists (like IfcPointList3D)
                var cardinality = property.EntityAttribute.MaxCardinality;
                if (cardinality != property.EntityAttribute.MinCardinality)
                {
                    throw new XbimParserException(property.Name + " is not rectangular so it can't be serialized as a simple text string");
                }

                var values  = value.Split(_separator, StringSplitOptions.RemoveEmptyEntries);
                var valType = GetNonGenericType(genType);
                if (typeof(IExpressValueType).IsAssignableFrom(valType))
                {
                    var expValType = _metadata.ExpressType(valType);
                    if (expValType == null)
                    {
                        throw new XbimParserException("Unexpected data type " + valType.Name);
                    }
                    valType = expValType.UnderlyingType;
                }

                for (var i = 0; i < values.Length; i++)
                {
                    IPropertyValue pValue;
                    InitPropertyValue(valType, values[i], out pValue);
                    var idx = i / cardinality;
                    entity.Parse(pIndex, pValue, new [] { idx });
                }
            }
        }
Пример #3
0
        private void SetPropertyFromElement(ExpressMetaProperty property, IPersistEntity entity, XmlReader input, int[] pos, ExpressType valueType = null)
        {
            var name    = input.LocalName;
            var type    = valueType != null ? valueType.Type : GetNonNullableType(property.PropertyInfo.PropertyType);
            var pIndex  = property.EntityAttribute.Order - 1;
            var expType = valueType ?? GetExpresType(input);

            //select type
            if (typeof(IExpressSelectType).IsAssignableFrom(type) && type.IsInterface)
            {
                //move to inner element which represents the data
                var sDepth = input.Depth;
                while (input.Read())
                {
                    if (input.NodeType == XmlNodeType.EndElement && input.Depth == sDepth)
                    {
                        return;
                    }
                    if (input.NodeType != XmlNodeType.Element)
                    {
                        continue;
                    }
                    expType = GetExpresType(input);
                    if (expType == null)
                    {
                        throw new XbimParserException("Unexpected select data type " + name);
                    }

                    if (typeof(IExpressValueType).IsAssignableFrom(expType.Type))
                    {
                        SetPropertyFromElement(property, entity, input, pos, expType);
                        return;
                    }

                    if (typeof(IPersistEntity).IsAssignableFrom(expType.Type))
                    {
                        SetPropertyFromElement(property, entity, input, pos, expType);
                        return;
                    }

                    //this should either be a defined type or entity
                    throw new XbimParserException("Unexpected select data type " + expType.Name);
                }
                return;
            }

            //defined type
            if (typeof(IExpressValueType).IsAssignableFrom(type))
            {
                var cType = expType.UnderlyingComplexType;

                //if it is just a value we can use 'SetPropertyFromAttribute'
                if (type == property.PropertyInfo.PropertyType && !(cType != null && typeof(IPersistEntity).IsAssignableFrom(cType)))
                {
                    var strValue = input.ReadElementContentAsString();
                    SetPropertyFromString(property, entity, strValue, pos);
                    return;
                }

                if (cType != null)
                {
                    var cInnerValueType = typeof(List <>);
                    cInnerValueType = cInnerValueType.MakeGenericType(cType);
                    var cInnerList = Activator.CreateInstance(cInnerValueType) as IList;
                    if (cInnerList == null)
                    {
                        throw new XbimParserException("Initialization of " + cInnerValueType.Name + " failed.");
                    }

                    if (typeof(IPersistEntity).IsAssignableFrom(cType))
                    {
                        if (!input.IsEmptyElement)
                        {
                            var cDepth = input.Depth;
                            while (input.Read())
                            {
                                if (input.NodeType == XmlNodeType.EndElement && input.Depth == cDepth)
                                {
                                    break;
                                }
                                if (input.NodeType != XmlNodeType.Element)
                                {
                                    continue;
                                }
                                var innerEntity = ReadEntity(input);
                                cInnerList.Add(innerEntity);
                                if (input.NodeType == XmlNodeType.EndElement && input.Depth == cDepth)
                                {
                                    break;
                                }
                            }

                            var cValueVal = Activator.CreateInstance(expType.Type, cInnerList);
                            var cpValue   = new PropertyValue();
                            cpValue.Init(cValueVal);
                            entity.Parse(pIndex, cpValue, null);
                        }
                    }
                    else
                    {
                        var cValuesString = input.ReadElementContentAsString();
                        SetPropertyFromString(property, entity, cValuesString, pos);
                    }
                    return;
                }

                //normal defined type has string based constructor which will set the right value
                var sValue = input.ReadElementContentAsString();
                if (property.EnumerableType == expType.Type)
                {
                    IPropertyValue pValue;
                    InitPropertyValue(expType.UnderlyingType, sValue, out pValue);
                    entity.Parse(pIndex, pValue, pos);
                    return;
                }
                else
                {
                    var pValue    = new PropertyValue();
                    var pValueVal = Activator.CreateInstance(expType.Type, sValue);
                    pValue.Init(pValueVal);
                    entity.Parse(pIndex, pValue, pos);
                    return;
                }
            }

            if (typeof(IPersistEntity).IsAssignableFrom(type) ||
                (typeof(IEnumerable).IsAssignableFrom(type) && property.EntityAttribute.MaxCardinality == 1))
            {
                var value = ReadEntity(input);
                var pVal  = new PropertyValue();

                if (property.IsInverse)
                {
                    pVal.Init(entity);
                    var remotePropName = property.InverseAttributeProperty.RemoteProperty;
                    var remoteProperty = value.ExpressType.Properties.FirstOrDefault(p => p.Value.Name == remotePropName).Value;
                    if (remoteProperty == null)
                    {
                        throw new XbimParserException("Non existing counterpart to " + property.Name);
                    }
                    value.Parse(remoteProperty.EntityAttribute.Order - 1, pVal, null);
                }
                else
                {
                    pVal.Init(value);
                    entity.Parse(pIndex, pVal, null);
                }
                return;
            }

            //enumeration or inverse enumeration
            if (typeof(IEnumerable).IsAssignableFrom(type))
            {
                //do nothing with empty list. If it is mandatory it is initialized anyway
                if (input.IsEmptyElement)
                {
                    return;
                }

                var enumDepth = input.Depth;
                while (input.Read())
                {
                    if (input.NodeType == XmlNodeType.EndElement && input.Depth == enumDepth)
                    {
                        break;
                    }
                    if (input.NodeType != XmlNodeType.Element)
                    {
                        continue;
                    }

                    //position is optional
                    var posAttr = input.GetAttribute("pos");
                    pos = null;
                    if (!string.IsNullOrWhiteSpace(posAttr))
                    {
                        var idx = posAttr.Split(_separator, StringSplitOptions.RemoveEmptyEntries)
                                  .Select(i => Convert.ToInt32(i)).ToList();
                        //remove the last one as it is not used in Parse function
                        if (idx.Count > 0)
                        {
                            idx.RemoveAt(idx.Count - 1);
                        }
                        //only set if it has any values in
                        if (idx.Count > 0)
                        {
                            pos = idx.ToArray();
                        }
                    }

                    //it might be a primitive
                    name = input.LocalName;
                    if (Primitives.ContainsKey(input.LocalName))
                    {
                        var iVal = input.ReadElementContentAsString();
                        var pVal = new PropertyValue();
                        pVal.Init(iVal, Primitives[name]);
                        entity.Parse(pIndex, pVal, pos);
                        if (input.NodeType == XmlNodeType.EndElement && input.Depth == enumDepth)
                        {
                            break;
                        }
                        continue;
                    }

                    var eType = GetExpresType(input);
                    if (eType == null)
                    {
                        throw new XbimParserException("Unexpected type " + name);
                    }
                    SetPropertyFromElement(property, entity, input, pos, eType);
                    if (input.NodeType == XmlNodeType.EndElement && input.Depth == enumDepth)
                    {
                        break;
                    }
                }
                return;
            }
            throw new XbimParserException("Unexpected type: " + type.Name);
        }
Пример #4
0
        private void Parse(IPersistEntity entity, int propIndex, IPropertyValue value, int[] nested)
        {
            try
            {
                entity.Parse(propIndex, value, nested);
            }
            catch (InvalidCastException e)
            {
                var prop  = entity.ExpressType.Properties[propIndex + 1];
                var type  = value.Type;
                var vType = "";
                switch (type)
                {
                case StepParserType.Boolean:
                    vType = "Boolean";
                    break;

                case StepParserType.Enum:
                    vType = "Enumeration value " + value.EnumVal;
                    break;

                case StepParserType.Entity:
                    vType = value.EntityVal.GetType().Name;
                    var vEntity = value.EntityVal as IPersistEntity;
                    if (vEntity != null)
                    {
                        var info = GetErrIdentityInfo(vEntity);
                        if (!string.IsNullOrWhiteSpace(info))
                        {
                            vType = vType + " (" + info + ")";
                        }
                    }

                    break;

                case StepParserType.HexaDecimal:
                    vType = "HexaDecimal";
                    break;

                case StepParserType.Integer:
                    vType = "Integer";
                    break;

                case StepParserType.Real:
                    vType = "Real";
                    break;

                case StepParserType.String:
                    vType = "String";
                    break;

                case StepParserType.Undefined:
                default:
                    vType = "Undefined";
                    break;
                }


                var identity = GetErrIdentityInfo(entity);
                var msg      = String.Format("{0} is not assignable to {1}.{2} ({3})",
                                             vType,
                                             entity.ExpressType.ExpressName,
                                             prop.Name, identity);
                Logger.LogError(new EventId(1000, "Failed Assignment"), e, msg);
            }
        }