public XbimParserState(IPersistEntity entity, ILogger logger = null) { _currentInstance = new Part21Entity(entity); _processStack.Push(_currentInstance); _logger = logger; _metadata = entity.Model.Metadata; }
public XbimParserState(IPersistEntity entity, ILogger logger = null) { _logger = logger ?? XbimLogging.CreateLogger <EsentModel>(); _currentInstance = new Part21Entity(entity); _processStack.Push(_currentInstance); _metadata = entity.Model.Metadata; }
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); } }
/// <summary> /// Writes full model into output writer as STEP21 file /// </summary> /// <param name="model">Model to be serialized</param> /// <param name="output">Output writer</param> /// <param name="metadata">Metadata to be used for serialization</param> /// <param name="map">Optional map can be used to map occurrences in the file</param> private void Write(TextWriter output) { ExpressMetaData metadata = Metadata; var header = Header ?? new StepFileHeader(StepFileHeader.HeaderCreationMode.InitWithXbimDefaults, this); string fallBackSchema = EntityFactory.SchemasIds.FirstOrDefault(); if (!header.FileSchema.Schemas.Any()) { foreach (var id in EntityFactory.SchemasIds) { header.FileSchema.Schemas.Add(id); } } Part21Writer.WriteHeader(header, output, fallBackSchema); foreach (var entity in Instances) { if (_comments.TryGetValue(entity.EntityLabel, out string comment)) { comment = comment.Trim('\r', '\n'); comment = comment.Replace("\r\n", "\r\n* "); output.WriteLine(); output.WriteLine($"/**"); output.WriteLine("* " + comment); output.WriteLine($"* {GetMetaComment(entity)}*/"); } Part21Writer.WriteEntity(entity, output, metadata, null); output.WriteLine(); } Part21Writer.WriteFooter(output); }
/// <summary> /// This function writes model entities to the defined XML output. /// </summary> /// <param name="model">Model to be used for serialization. If no entities are specified IModel.Instances will be used as a /// source of entities to be serialized.</param> /// <param name="output">Output XML</param> /// <param name="entities">Optional entities enumerable. If you define this enumerable it will be /// used instead of all entities from IModel.Instances. This allows to define different way of entities retrieval /// like volatile instances from persisted DB model</param> public void Write(IModel model, XmlWriter output, IEnumerable <IPersistEntity> entities = null) { _metadata = model.Metadata; try { _written = new HashSet <long>(); output.WriteStartDocument(); output.WriteStartElement("ex", "iso_10303_28", Iso10303Urn); output.WriteAttributeString("version", "2.0"); output.WriteAttributeString("xmlns", "xsi", null, Xsi); output.WriteAttributeString("xmlns", "xlink", null, Xlink); output.WriteAttributeString("xmlns", "ex", null, Iso10303Urn); output.WriteAttributeString("xsi", "schemaLocation", null, string.Format("{0} {1}", Iso10303Urn, ExXsd)); _fileHeader = model.Header; WriteISOHeader(output); //Write out the uos output.WriteStartElement("uos", Namespace); output.WriteAttributeString("id", "uos_1"); output.WriteAttributeString("description", "Xbim IfcXml Export"); output.WriteAttributeString("configuration", "i_ifc2x3"); output.WriteAttributeString("edo", ""); output.WriteAttributeString("xmlns", "ex", null, Iso10303Urn); output.WriteAttributeString("xmlns", "ifc", null, Namespace); output.WriteAttributeString("xsi", "schemaLocation", null, string.Format("{0} {1}", Namespace, IfcXsd)); //use specified entities enumeration or just all instances in the model if (entities != null) { foreach (var entity in entities) { Write(entity, output); } } else { foreach (var entity in model.Instances) { Write(entity, output); } } output.WriteEndElement(); //uos output.WriteEndElement(); //iso_10303_28 output.WriteEndDocument(); } catch (Exception e) { throw new Exception("Failed to write IfcXml file", e); } finally { _written = null; } }
protected XbimP21Parser(ExpressMetaData metadata) { Metadata = metadata; const int entityApproxCount = 5000; _entities = new Dictionary <long, IPersist>(entityApproxCount); _deferredReferences = new List <DeferredReference>(entityApproxCount / 2); //assume 50% deferred ErrorCount = 0; }
private static Type GetImplementation <T>(ExpressMetaData metadata) { var implementations = metadata.TypesImplementing(typeof(T)).ToList(); var ids = new HashSet <short>(implementations.Select(i => i.TypeId)); var root = implementations.AsQueryable() .FirstOrDefault(i => !ids.Contains(i.SuperType.TypeId)); return(root.Type); }
/// <summary> /// This function writes model entities to the defined XML output. /// </summary> /// <param name="model">Model to be used for serialization. If no entities are specified IModel.Instances will be used as a /// source of entities to be serialized.</param> /// <param name="output">Output XML</param> /// <param name="entities">Optional entities enumerable. If you define this enumerable it will be /// used instead of all entities from IModel.Instances. This allows to define different way of entities retrieval /// like volatile instances from persisted DB model</param> public void Write(IModel model, XmlWriter output, IEnumerable <IPersistEntity> entities = null) { _metadata = model.Metadata; try { _written = new HashSet <long>(); output.WriteStartDocument(); output.WriteStartElement(_rootElementName, _ns); //xmlns declarations output.WriteAttributeString("xmlns", "xsi", null, Xsi); output.WriteAttributeString("xmlns", "xlink", null, Xlink); output.WriteAttributeString("xmlns", _nsPrefix, null, _ns); if (!string.IsNullOrWhiteSpace(_nsLocation)) { output.WriteAttributeString("schemaLocation", Xsi, string.Format("{0} {1}", _ns, _nsLocation)); } //root attributes output.WriteAttributeString("id", "uos_1"); if (!string.IsNullOrWhiteSpace(_expressUri)) { output.WriteAttributeString("express", _expressUri); } if (!string.IsNullOrWhiteSpace(_configurationUri)) { output.WriteAttributeString("configuration", _configurationUri); } _fileHeader = model.Header; WriteHeader(output); //use specified entities enumeration or just all instances in the model entities = entities ?? model.Instances; foreach (var entity in entities) { WriteEntity(entity, output, true); } output.WriteEndElement(); //root element output.WriteEndDocument(); } catch (Exception e) { throw new Exception("Failed to write XML file", e); } finally { _written = null; } }
protected void Init(IEntityFactory factory) { _factory = factory; InstanceCache = new PersistedEntityInstanceCache(this, factory); InstancesLocal = new XbimInstanceCollection(this); var r = new Random(); UserDefinedId = (short)r.Next(short.MaxValue); // initialise value at random to reduce chance of duplicates Metadata = ExpressMetaData.GetMetadata(factory.GetType().Module); ModelFactors = new XbimModelFactors(Math.PI / 180, 1e-3, 1e-5); }
/// <summary> /// Writes full model into output writer as STEP21 file /// </summary> /// <param name="model">Model to be serialized</param> /// <param name="output">Output writer</param> /// <param name="metadata">Metadata to be used for serialization</param> /// <param name="map">Optional map can be used to map occurrences in the file</param> /// <param name="progress">A progress delegate</param> public static void Write(IModel model, TextWriter output, ExpressMetaData metadata, IDictionary <int, int> map = null, ReportProgressDelegate progress = null) { var header = model.Header ?? new StepFileHeader(StepFileHeader.HeaderCreationMode.InitWithXbimDefaults, model); string fallBackSchema = null; if (header.FileSchema == null || !header.FileSchema.Schemas.Any()) { var instance = model.Instances.FirstOrDefault(); if (instance != null) { var eft = instance.GetType().GetTypeInfo().Assembly.GetTypes().Where(t => typeof(IEntityFactory).GetTypeInfo().IsAssignableFrom(t)).FirstOrDefault(); if (eft == null) { throw new XbimException("It wasn't possible to find valid schema definition"); } var ef = Activator.CreateInstance(eft) as IEntityFactory; if (ef == null) { throw new XbimException("It wasn't possible to find valid schema definition"); } fallBackSchema = string.Join(",", ef.SchemasIds); } } WriteHeader(header, output, fallBackSchema); var count = model.Instances.Count; var counter = 0; var report = progress != null; foreach (var entity in model.Instances) { WriteEntity(entity, output, metadata, map); output.WriteLine(); if (report) { counter++; // report every 1000 entities if (counter % 1000 == 0) { var percent = (int)((float)counter / (float)count); progress(percent, null); } } } WriteFooter(output); if (progress != null) { progress(100, null); } }
public void Init(ExpressMetaData metadata) { MetaData = metadata; if (ClassMappings == null) { return; } foreach (var classMapping in ClassMappings) { classMapping.Init(this); } }
public XbimP21Parser(Stream strm, ExpressMetaData metadata, long streamSize) : base(strm) { Metadata = metadata; var entityApproxCount = 5000; if (streamSize > 0) { _streamSize = streamSize; entityApproxCount = Convert.ToInt32(_streamSize / 50); //average 50 bytes per entity. } _entities = new Dictionary <long, IPersist>(entityApproxCount); _deferredReferences = new List <DeferredReference>(entityApproxCount / 2); //assume 50% deferred ErrorCount = 0; }
private ExpressType GetExpressType(ExpressMetaData schema, string classString) { var v = schema.ExpressType(classString.ToUpper()); if (v != null) { return(v); } // warn once only; if (_failedLookupMessages.Contains(classString.ToUpper())) { return(null); } Log.Error($"{classString} is not a recognised class in {schema.Module.Name}."); _failedLookupMessages.Add(classString.ToUpper()); return(null); }
/// <summary> /// Constructor of the reader for IFC2x3 XML. XSD is different for different versions of IFC and there is a major difference /// between IFC2x3 and IFC4 to there are two different classes to deal with this. /// </summary>x /// <param name="create">Delegate which will be used to create new entities</param> /// <param name="finish">Delegate which will be called once the entity is finished (no changes will be made to it) /// This is useful for a DB when this is the point when it can be serialized to DB</param> /// <param name="metadata">Metadata model used to inspect Express types and their properties</param> public IfcXmlReader(GetOrCreateEntity create, FinishEntity finish, ExpressMetaData metadata) { if (create == null) { throw new ArgumentNullException("create"); } if (finish == null) { throw new ArgumentNullException("finish"); } if (metadata == null) { throw new ArgumentNullException("metadata"); } _create = create; _finish = finish; _metadata = metadata; }
public MemoryModel(IEntityFactory entityFactory, int labelFrom = 0) { if (entityFactory == null) { throw new ArgumentNullException("entityFactory"); } _entityFactory = entityFactory; _instances = new EntityCollection(this, labelFrom); Header = new StepFileHeader(StepFileHeader.HeaderCreationMode.InitWithXbimDefaults); foreach (var schemasId in _instances.Factory.SchemasIds) { Header.FileSchema.Schemas.Add(schemasId); } ModelFactors = new XbimModelFactors(Math.PI / 180, 1e-3, 1e-5); Metadata = ExpressMetaData.GetMetadata(entityFactory.GetType().Module); IsTransactional = true; }
/// <summary> /// Constructor of the reader for IFC2x3 XML. XSD is different for different versions of IFC and there is a major difference /// between IFC2x3 and IFC4 to there are two different classes to deal with this. /// </summary>x /// <param name="getOrCreate">Delegate which will be used to getOrCreate new entities</param> /// <param name="finish">Delegate which will be called once the entity is finished (no changes will be made to it) /// This is useful for a DB when this is the point when it can be serialized to DB</param> /// <param name="metadata">Metadata model used to inspect Express types and their properties</param> public XbimXmlReader4(GetOrCreateEntity getOrCreate, FinishEntity finish, ExpressMetaData metadata) { if (getOrCreate == null) { throw new ArgumentNullException("getOrCreate"); } if (finish == null) { throw new ArgumentNullException("finish"); } if (metadata == null) { throw new ArgumentNullException("metadata"); } _getOrCreate = getOrCreate; _finish = finish; _metadata = metadata; }
public override string ToString() { ExpressMetaData md = null; if (Model != null) { md = Model.Metadata; } else { md = ExpressMetaData.GetMetadata(GetType().Module); } using (var sw = new StringWriter()) { Part21Writer.WriteEntity(this, sw, md); return(sw.ToString()); } }
private static void WriteEntity(IPersistEntity entity, TextWriter output, ExpressMetaData metadata) { var expressType = metadata.ExpressType(entity); output.Write("#{0}={1}(", entity.EntityLabel, expressType.ExpressNameUpper); var first = true; foreach (var ifcProperty in expressType.Properties.Values) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State == EntityAttributeState.DerivedOverride) { if (!first) { output.Write(','); } output.Write('*'); first = false; } else { // workaround for IfcCartesianPointList3D from IFC4x1 if (entity is IfcCartesianPointList3D && ifcProperty.Name == "TagList") { continue; } var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); if (!first) { output.Write(','); } Part21Writer.WriteProperty(propType, propVal, output, null, metadata); first = false; } } output.Write(");"); }
/// <summary> /// Constructor of the reader for IFC2x3 XML. XSD is different for different versions of IFC and there is a major difference /// between IFC2x3 and IFC4 to there are two different classes to deal with this. /// </summary>x /// <param name="getOrCreate">Delegate which will be used to getOrCreate new entities</param> /// <param name="finish">Delegate which will be called once the entity is finished (no changes will be made to it) /// This is useful for a DB when this is the point when it can be serialized to DB</param> /// <param name="metadata">Metadata model used to inspect Express types and their properties</param> /// <param name="logger">A Logger</param> public XbimXmlReader4(GetOrCreateEntity getOrCreate, FinishEntity finish, ExpressMetaData metadata, ILogger logger) { if (getOrCreate == null) { throw new ArgumentNullException("getOrCreate"); } if (finish == null) { throw new ArgumentNullException("finish"); } if (metadata == null) { throw new ArgumentNullException("metadata"); } _getOrCreate = getOrCreate; _finish = finish; _metadata = metadata; Logger = logger ?? XbimLogging.CreateLogger <XbimXmlReader4>();; }
/// <summary> /// Writes full model into output writer as STEP21 file /// </summary> /// <param name="model">Model to be serialized</param> /// <param name="output">Output writer</param> /// <param name="metadata">Metadata to be used for serialization</param> /// <param name="map">Optional map can be used to map occurrences in the file</param> public static void Write(IModel model, TextWriter output, ExpressMetaData metadata, IDictionary <int, int> map = null) { var header = model.Header ?? new StepFileHeader(StepFileHeader.HeaderCreationMode.InitWithXbimDefaults); string fallBackSchema = null; if (header.FileSchema == null || !header.FileSchema.Schemas.Any()) { var instance = model.Instances.FirstOrDefault(); if (instance != null) { var eft = instance.GetType().Assembly.GetTypes().Where(t => typeof(IEntityFactory).IsAssignableFrom(t)).FirstOrDefault(); if (eft == null) { throw new XbimException("It wasn't possible to find valid schema definition"); } var ef = Activator.CreateInstance(eft) as IEntityFactory; if (ef == null) { throw new XbimException("It wasn't possible to find valid schema definition"); } fallBackSchema = string.Join(",", ef.SchemasIds); } } WriteHeader(header, output, fallBackSchema); var esent = model as EsentModel; var instances = esent != null? esent.InstanceHandles.Select(h => esent.GetInstanceVolatile(h.EntityLabel)) : model.Instances; foreach (var entity in instances) { WriteEntity(entity, output, metadata, map); output.WriteLine(); } WriteFooter(output); }
private void PopulateTree() { // this is done through the metadata in order to ensure that class relationships are loaded var module4 = (typeof(Xbim.Ifc4.Kernel.IfcProduct)).Module; var meta4 = ExpressMetaData.GetMetadata(module4); var product4 = meta4.ExpressType("IFCPRODUCT"); TypesTree.Items.Add(new ObjectViewModel() { Header = "Ifc4.IfcProduct", Tag = new ExpressTypeExpander(product4, Model), IsChecked = true }); // this is done through the metadata in order to ensure that class relationships are loaded var module2X3 = (typeof(Xbim.Ifc2x3.Kernel.IfcProduct)).Module; var meta2X3 = ExpressMetaData.GetMetadata(module2X3); var product2X3 = meta2X3.ExpressType("IFCPRODUCT"); TypesTree.Items.Add(new ObjectViewModel() { Header = "Ifc2x3.IfcProduct", Tag = new ExpressTypeExpander(product2X3, Model), IsChecked = true }); }
private static void WriteEntityRecursive(IPersistEntity entity, ExpressMetaData metadata, TextWriter writer, HashSet <int> written) { if (written.Contains(entity.EntityLabel)) { return; } Part21Writer.WriteEntity(entity, writer, metadata); written.Add(entity.EntityLabel); var references = entity as IContainsEntityReferences; if (references == null) { return; } foreach (var item in references.References) { WriteEntityRecursive(item, metadata, writer, written); } }
/// <summary> /// Writes the entity to a TextWriter in the Part21 format /// </summary> /// <param name="output">The TextWriter</param> /// <param name="entity">The entity to write</param> /// <param name="metadata"></param> /// <param name="map"></param> public static void WriteEntity(IPersistEntity entity, TextWriter output, ExpressMetaData metadata, IDictionary <int, int> map = null) { var expressType = metadata.ExpressType(entity); if (map != null && map.Keys.Contains(entity.EntityLabel)) { return; //if the entity is replaced in the map do not write it } output.Write("#{0}={1}(", entity.EntityLabel, expressType.ExpressNameUpper); var first = true; foreach (var ifcProperty in expressType.Properties.Values) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State == EntityAttributeState.DerivedOverride) { if (!first) { output.Write(','); } output.Write('*'); first = false; } else { var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); if (!first) { output.Write(','); } WriteProperty(propType, propVal, output, map, metadata); first = false; } } output.Write(");"); }
private ValidationResult CheckMeasureType(string typeName, ExpressMetaData metadata, bool reference) { // null or empty is a valid value if (string.IsNullOrWhiteSpace(typeName)) { return(null); } typeName = typeName.ToUpperInvariant(); var err = new ValidationResult { IssueSource = "Measure type validation", IssueType = ValidationFlags.Properties, }; if (!metadata.TryGetExpressType(typeName, out ExpressType eType)) { err.Message = $"Type {typeName} is not an IFC type."; return(err); } var type = eType.Type; if (!reference && !typeof(IIfcValue).IsAssignableFrom(type)) { err.Message = $"Type {typeName} is not applicable. This must be assignable to 'IfcValue'"; return(err); } if (reference && !typeof(IIfcObjectReferenceSelect).IsAssignableFrom(type)) { err.Message = $"Type {typeName} is not applicable. This must be assignable to 'IfcObjectReferenceSelect'"; return(err); } return(null); }
public static void Export() { var valType = typeof(IfcValue); var types = valType.Assembly.GetTypes() .Where(t => t.IsValueType && valType.IsAssignableFrom(t)) .OrderBy(t => t.Name); using (var w = File.CreateText("MeasureTypeEnum.csv")) { // header w.WriteLine($"Identifier, Name"); foreach (var t in types) { w.WriteLine($"{t.Name}, {Format(t.Name)}"); } } types = valType.Assembly.GetTypes() .Where(t => !t.IsAbstract && typeof(IfcObjectReferenceSelect).IsAssignableFrom(t)) .OrderBy(t => t.Name); using (var w = File.CreateText("ReferenceTypeEnum.csv")) { // header w.WriteLine($"Identifier, Name"); foreach (var t in types) { w.WriteLine($"{t.Name}, {Format(t.Name)}"); } } var meta = ExpressMetaData.GetMetadata(valType.Module); var product = meta.ExpressType("IFCPRODUCT"); var element = meta.ExpressType("IFCELEMENT"); var spatial = meta.ExpressType("IFCSPATIALELEMENT"); var stack = new Stack <ExpressType>(new [] { element, spatial }); var enumCounter = 5000; using (var w = File.CreateText("ApplicableIfcTypes.csv")) { // header w.WriteLine($"ID, Identifier, Name, Parent"); // root w.WriteLine($"{product.TypeId}, {product.Name}, {Format(product.Name)}, NULL"); while (stack.Count != 0) { var type = stack.Pop(); if (type.SubTypes != null && type.SubTypes.Any()) { foreach (var t in type.SubTypes) { stack.Push(t); } } w.WriteLine($"{type.TypeId}, {type.Name}, {Format(type.Name)}, {type.SuperType.TypeId}"); // predefined types var pdt = type.Properties.Select(kvp => kvp.Value).FirstOrDefault(p => string.Equals(p.Name, "PredefinedType")); if (pdt == null) { continue; } var pdtType = pdt.PropertyInfo.PropertyType; if (pdtType.IsGenericType) { pdtType = Nullable.GetUnderlyingType(pdtType); } var values = Enum.GetNames(pdtType); foreach (var value in values) { w.WriteLine($"{++enumCounter}, {value}, {value}, {type.TypeId}"); } } } }
public XbimGeometryHandleCollection(IEnumerable <XbimGeometryHandle> enumerable, ExpressMetaData metadata) : base(enumerable) { _metadata = metadata; }
/// <summary> /// Writes the in memory data of the entity to a stream /// </summary> /// <param name = "entityStream"></param> /// <param name = "entityWriter"></param> /// <param name = "item"></param> /// <param name="metadata"></param> private static int WriteEntityToSteam(MemoryStream entityStream, BinaryWriter entityWriter, IPersistEntity item, ExpressMetaData metadata) { entityWriter.Seek(0, SeekOrigin.Begin); entityWriter.Write(0); item.WriteEntity(entityWriter, metadata); var len = Convert.ToInt32(entityStream.Position); entityWriter.Seek(0, SeekOrigin.Begin); entityWriter.Write(len); entityWriter.Seek(0, SeekOrigin.Begin); return(len); }
private static void WriteProperty(Type propType, object propVal, BinaryWriter entityWriter, ExpressMetaData metadata) { Type itemType; if (propVal == null) //null or a value type that maybe null { entityWriter.Write(Convert.ToByte(P21ParseAction.SetNonDefinedValue)); } else if (propVal is IOptionalItemSet && !((IOptionalItemSet)propVal).Initialized) { entityWriter.Write(Convert.ToByte(P21ParseAction.SetNonDefinedValue)); } else if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable <>)) //deal with undefined types (nullables) { var complexType = propVal as IExpressComplexType; if (complexType != null) { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var compVal in complexType.Properties) { WriteProperty(compVal.GetType(), compVal, entityWriter, metadata); } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); } else if ((propVal is IExpressValueType)) { var expressVal = (IExpressValueType)propVal; WriteValueType(expressVal.UnderlyingSystemType, expressVal.Value, entityWriter); } else { WriteValueType(propVal.GetType(), propVal, entityWriter); } } else if (typeof(IExpressComplexType).IsAssignableFrom(propType)) { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var compVal in ((IExpressComplexType)propVal).Properties) { WriteProperty(compVal.GetType(), compVal, entityWriter, metadata); } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); } else if (typeof(IExpressValueType).IsAssignableFrom(propType)) //value types with a single property (IfcLabel, IfcInteger) { var realType = propVal.GetType(); if (realType != propType) //we have a type but it is a select type use the actual value but write out explicitly { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginNestedType)); entityWriter.Write(realType.Name.ToUpper()); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); WriteProperty(realType, propVal, entityWriter, metadata); entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); entityWriter.Write(Convert.ToByte(P21ParseAction.EndNestedType)); } else //need to write out underlying property value { var expressVal = (IExpressValueType)propVal; WriteValueType(expressVal.UnderlyingSystemType, expressVal.Value, entityWriter); } } else if (typeof(IExpressEnumerable).IsAssignableFrom(propType) && (itemType = propType.GetItemTypeFromGenericType()) != null) //only process lists that are real lists, see cartesianpoint { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var item in ((IExpressEnumerable)propVal)) { WriteProperty(itemType, item, entityWriter, metadata); } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); } else if (typeof(IPersistEntity).IsAssignableFrom(propType)) //all writable entities must support this interface and ExpressType have been handled so only entities left { var val = ((IPersistEntity)propVal).EntityLabel; if (val <= UInt16.MaxValue) { entityWriter.Write((byte)P21ParseAction.SetObjectValueUInt16); entityWriter.Write(Convert.ToUInt16(val)); } else if (val <= Int32.MaxValue) { entityWriter.Write((byte)P21ParseAction.SetObjectValueInt32); entityWriter.Write(Convert.ToInt32(val)); } //else if (val <= Int64.MaxValue) //{ // //This is a very large model and it is unlikely we will be able to handle this number of entities, // //it is possible they have just created big labels and it needs to be renumbered // //Entity Label could be redfined as a long bu this is a large overhead if never required, let's see... // throw new XbimException("Entity Label is Init64, this is not currently supported"); // //entityWriter.Write((byte)P21ParseAction.SetObjectValueInt64); // //entityWriter.Write(val); //} else { throw new Exception("Entity Label exceeds maximim value for a an int32 long number"); } } else if (propType.IsValueType || propType == typeof(string)) //it might be an in-built value type double, string etc { WriteValueType(propVal.GetType(), propVal, entityWriter); } else if (typeof(IExpressSelectType).IsAssignableFrom(propType)) // a select type get the type of the actual value { if (propVal.GetType().IsValueType) //we have a value type, so write out explicitly { var type = metadata.ExpressType(propVal.GetType()); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginNestedType)); entityWriter.Write(type.ExpressNameUpper); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); WriteProperty(propVal.GetType(), propVal, entityWriter, metadata); entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); entityWriter.Write(Convert.ToByte(P21ParseAction.EndNestedType)); } else //could be anything so re-evaluate actual type { WriteProperty(propVal.GetType(), propVal, entityWriter, metadata); } } else { throw new Exception(string.Format("Entity has illegal property {0} of type {1}", propType.Name, propType.Name)); } }
internal static void WriteEntity(this IPersistEntity entity, BinaryWriter entityWriter, ExpressMetaData metadata) { var expressType = metadata.ExpressType(entity); // entityWriter.Write(Convert.ToByte(P21ParseAction.NewEntity)); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var ifcProperty in expressType.Properties.Values) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State == EntityAttributeState.DerivedOverride) { entityWriter.Write(Convert.ToByte(P21ParseAction.SetOverrideValue)); } else { var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); WriteProperty(propType, propVal, entityWriter, metadata); } } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); entityWriter.Write(Convert.ToByte(P21ParseAction.EndEntity)); }
internal static void WriteEntity(this IPersistEntity entity, TextWriter tw, byte[] propertyData, ExpressMetaData metadata) { var type = metadata.ExpressType(entity); tw.Write("#{0}={1}", entity.EntityLabel, type.ExpressNameUpper); var br = new BinaryReader(new MemoryStream(propertyData)); var action = (P21ParseAction)br.ReadByte(); var comma = false; //the first property while (action != P21ParseAction.EndEntity) { switch (action) { case P21ParseAction.BeginList: tw.Write("("); break; case P21ParseAction.EndList: tw.Write(")"); break; case P21ParseAction.BeginComplex: tw.Write("&SCOPE"); break; case P21ParseAction.EndComplex: tw.Write("ENDSCOPE"); break; case P21ParseAction.SetIntegerValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadInt64().ToString()); break; case P21ParseAction.SetHexValue: if (comma) { tw.Write(","); } comma = true; tw.Write(Convert.ToString(br.ReadInt64(), 16)); break; case P21ParseAction.SetFloatValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadDouble().AsPart21()); break; case P21ParseAction.SetStringValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadString()); break; case P21ParseAction.SetEnumValue: if (comma) { tw.Write(","); } comma = true; tw.Write("." + br.ReadString() + "."); break; case P21ParseAction.SetBooleanValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadBoolean() ? ".T." : ".F."); break; case P21ParseAction.SetNonDefinedValue: if (comma) { tw.Write(","); } comma = true; tw.Write("$"); break; case P21ParseAction.SetOverrideValue: if (comma) { tw.Write(","); } comma = true; tw.Write("*"); break; case P21ParseAction.SetObjectValueUInt16: if (comma) { tw.Write(","); } comma = true; tw.Write("#" + br.ReadUInt16()); break; case P21ParseAction.SetObjectValueInt32: if (comma) { tw.Write(","); } comma = true; tw.Write("#" + br.ReadInt32()); break; case P21ParseAction.SetObjectValueInt64: if (comma) { tw.Write(","); } comma = true; tw.Write("#" + br.ReadInt64()); break; case P21ParseAction.BeginNestedType: if (comma) { tw.Write(","); } comma = false; tw.Write(br.ReadString() + "("); break; case P21ParseAction.EndNestedType: comma = true; tw.Write(")"); break; case P21ParseAction.EndEntity: tw.Write(");"); break; case P21ParseAction.NewEntity: comma = false; tw.Write("("); break; default: throw new Exception("Invalid Property Record #" + entity.EntityLabel + " EntityType: " + entity.GetType().Name); } action = (P21ParseAction)br.ReadByte(); } tw.WriteLine(); }