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); } }
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 }); } } }
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); }
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); } }