public Compiler(DocProject project, DocModelView[] views, DocExchangeDefinition exchange, bool psets) { this.m_project = project; this.m_views = views; this.m_exchange = exchange; this.m_psets = psets; // version needs to be included for extracting XML namespace (Major.Minor.Addendum.Corrigendum) string version = project.GetSchemaVersion(); ConstructorInfo conContract = (typeof(AssemblyVersionAttribute).GetConstructor(new Type[] { typeof(string) })); CustomAttributeBuilder cabAssemblyVersion = new CustomAttributeBuilder(conContract, new object[] { version }); string schemaid = project.GetSchemaIdentifier(); string assembly = "buildingSmart." + schemaid; string module = assembly + ".dll"; this.m_rootnamespace = assembly + "."; this.m_assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(assembly), AssemblyBuilderAccess.RunAndSave, new CustomAttributeBuilder[] { cabAssemblyVersion }); this.m_module = this.m_assembly.DefineDynamicModule(module, module); this.m_definitions = new Dictionary <string, DocObject>(); this.m_types = new Dictionary <string, Type>(); this.m_fields = new Dictionary <Type, Dictionary <string, FieldInfo> >(); this.m_templates = new Dictionary <DocTemplateDefinition, MethodInfo>(); this.m_namespaces = new Dictionary <string, string>(); Dictionary <DocObject, bool> included = null; if (this.m_views != null) { included = new Dictionary <DocObject, bool>(); foreach (DocModelView docView in this.m_views) { this.m_project.RegisterObjectsInScope(docView, included); } } if (psets) { foreach (DocPropertyEnumeration docPropEnum in project.PropertyEnumerations) { DocEnumeration docType = docPropEnum.ToEnumeration(); if (!this.m_definitions.ContainsKey(docType.Name)) { this.m_definitions.Add(docType.Name, docType); } } } foreach (DocSection docSection in project.Sections) { foreach (DocSchema docSchema in docSection.Schemas) { foreach (DocEntity docEntity in docSchema.Entities) { if (included == null || included.ContainsKey(docEntity)) { if (!this.m_definitions.ContainsKey(docEntity.Name)) { this.m_definitions.Add(docEntity.Name, docEntity); this.m_namespaces.Add(docEntity.Name, docSchema.Name); } } } foreach (DocType docType in docSchema.Types) { if (included == null || included.ContainsKey(docType)) { if (!this.m_definitions.ContainsKey(docType.Name)) { this.m_definitions.Add(docType.Name, docType); this.m_namespaces.Add(docType.Name, docSchema.Name); } } } } } // second pass: if (psets) { foreach (DocSection docSection in project.Sections) { foreach (DocSchema docSchema in docSection.Schemas) { foreach (DocPropertySet docPset in docSchema.PropertySets) { DocEntity docType = docPset.ToEntity(this.m_definitions); if (!this.m_definitions.ContainsKey(docType.Name)) { this.m_definitions.Add(docType.Name, docType); this.m_namespaces.Add(docType.Name, docSchema.Name); } } foreach (DocQuantitySet docQset in docSchema.QuantitySets) { DocEntity docType = docQset.ToEntity(this.m_definitions); if (!this.m_definitions.ContainsKey(docType.Name)) { this.m_definitions.Add(docType.Name, docType); this.m_namespaces.Add(docType.Name, docSchema.Name); } } } } } // first register types and fields foreach (string key in this.m_definitions.Keys) { Type typereg = RegisterType(key); // localization -- use custom attributes for now -- ideal way would be to use assembly resources, though has bugs in .net 4.0 if (typereg is TypeBuilder) { TypeBuilder tb = (TypeBuilder)typereg; DocObject docObj = this.m_definitions[key]; foreach (DocLocalization docLocal in docObj.Localization) { CustomAttributeBuilder cab = docLocal.ToCustomAttributeBuilder(); if (cab != null) { tb.SetCustomAttribute(cab); } } } } // now register template functions (may depend on fields existing) // find associated ConceptRoot for model view, define validation function if (this.m_views != null) { foreach (DocModelView view in this.m_views) { string viewname = view.Code; foreach (DocConceptRoot root in view.ConceptRoots) { Type tOpen = null; if (this.m_types.TryGetValue(root.ApplicableEntity.Name, out tOpen) && tOpen is TypeBuilder) { TypeBuilder tb = (TypeBuilder)tOpen; // new: generate type for concept root //if (view.Name != null && root.Name != null) { /* * string typename = this.m_rootnamespace + "." + view.Name.Replace(" ", "_") + "." + root.Name.Replace(" ", "_"); * //Type tbConceptRoot = RegisterType(typename); * TypeBuilder tbRoot = this.m_module.DefineType(typename, attr, typebase); */ // add typebuilder to map temporarily in case referenced by an attribute within same class or base class //this.m_types.Add(typename, tb); foreach (DocTemplateUsage concept in root.Concepts) { CompileConcept(concept, view, tb); } } } } } } //Dictionary<string, Stream> mapResStreams = new Dictionary<string, Stream>(); //Dictionary<string, ResXResourceWriter> mapResources = new Dictionary<string, ResXResourceWriter>(); // seal types once all are built List <TypeBuilder> listBase = new List <TypeBuilder>(); foreach (string key in this.m_definitions.Keys) { Type tOpen = this.m_types[key]; while (tOpen is TypeBuilder) { listBase.Add((TypeBuilder)tOpen); tOpen = tOpen.BaseType; } // seal in base class order for (int i = listBase.Count - 1; i >= 0; i--) { Type tClosed = listBase[i].CreateType(); this.m_types[tClosed.Name] = tClosed; } listBase.Clear(); // record bindings DocDefinition docDef = this.m_definitions[key] as DocDefinition; if (docDef != null) { docDef.RuntimeType = this.m_types[key]; if (docDef is DocEntity) { DocEntity docEnt = (DocEntity)docDef; foreach (DocAttribute docAttr in docEnt.Attributes) { docAttr.RuntimeField = docDef.RuntimeType.GetProperty(docAttr.Name); } } #if false // bug in .net framework 4.0+ -- can't read resources dynamically defined // capture localization foreach (DocLocalization docLocal in docDef.Localization) { if (!String.IsNullOrEmpty(docLocal.Locale)) { string major = docLocal.Locale.Substring(0, 2).ToLower(); ResXResourceWriter reswriter = null; if (!mapResources.TryGetValue(major, out reswriter)) { MemoryStream stream = new MemoryStream(); mapResStreams.Add(major, stream); reswriter = new ResXResourceWriter(stream); mapResources.Add(major, reswriter); } ResXDataNode node = new ResXDataNode(docDef.Name, docLocal.Name); node.Comment = docLocal.Documentation; reswriter.AddResource(node); } } #endif } } #if false foreach (string locale in mapResStreams.Keys) { ResXResourceWriter writer = mapResources[locale]; writer.Generate(); Stream stream = mapResStreams[locale]; stream.Seek(0, SeekOrigin.Begin); m_module.DefineManifestResource("Resources." + locale + ".resx", stream, ResourceAttributes.Public); } #endif }
/// <summary> /// Saves all content to folder hierarchy /// </summary> /// <param name="project"></param> /// <param name="path"></param> public static void Save(DocProject project, string path, Dictionary <string, DocObject> mapEntity, FolderStorageOptions options) { bool bExportSchema = ((options & FolderStorageOptions.Schemas) != 0); bool bExportExchanges = ((options & FolderStorageOptions.Exchanges) != 0); bool bExportExamples = ((options & FolderStorageOptions.Examples) != 0); bool bExportLocalize = ((options & FolderStorageOptions.Localization) != 0); Compiler compiler = new Compiler(project, null, null, false); System.Reflection.Emit.AssemblyBuilder assembly = compiler.Assembly; // -exchanges (or mvd?) // {exchange}.mvdxml - definition // {exchange}.cs - C# partial classes for capturing exchange --- later // templates.mvdxml - shared templates // -figures -- manually added // -formats // -json // -step // -ttl // -xml // -samples // {sample}.ifcxml - ifcxml is native format for easier browsing, comparing, and validating // {sample}.htm - documentation for example // {sample}.png - preview image of example // {sample} - subdirectory if children // -schemas // {version} // {schema} // {class}.cs - definition in C# // {class}.htm - documentation in HTML // schema.cs - functions and // schema.htm - documentation of schema in HTML // schema.svg - diagram of schema in SVG // templates.ifcxml - property and quantity templates // localization // {locale}.txt - localized definitions // ifc.csproj if (bExportSchema) { string pathClasses = path + @"\schemas\" + project.GetSchemaIdentifier(); System.IO.Directory.CreateDirectory(pathClasses); FormatCSC.GenerateCode(project, pathClasses, mapEntity, DocCodeEnum.All); // generate ifcxml for templates DocumentationISO.DoExport(project, null, pathClasses + @"\templates.ifcxml", null, null, DocDefinitionScopeEnum.Default, null, mapEntity); // XSD configuration // not needed -- can re-read from C# classes //DocumentationISO.DoExport(project, null, pathClasses + @"\xsdconfig.xml", null, null, DocDefinitionScopeEnum.Default, null, mapEntity); } if (bExportExchanges) { string pathExchanges = path + @"\exchanges"; System.IO.Directory.CreateDirectory(pathExchanges); foreach (DocModelView docView in project.ModelViews) { string pathView = pathExchanges + @"\" + DocumentationISO.MakeLinkName(docView); DocumentationISO.DoExport(project, null, pathView + ".mvdxml", new DocModelView[] { docView }, null, DocDefinitionScopeEnum.Default, null, mapEntity); //... future: once it works flawlessly...FormatCSC.GenerateExchange(project, docView, pathView, mapEntity); } } if (bExportExamples) { // compile schema into assembly Type typeProject = Compiler.CompileProject(project); string pathSamples = path + @"\examples"; string pathSamplesWeb = "examples"; System.IO.Directory.CreateDirectory(pathSamples); using (StreamWriter writerIndex = new StreamWriter(Stream.Null)) //...pathSamples + @"\index.htm")) { writerIndex.WriteLine("<html><body>"); writerIndex.WriteLine("<table>"); foreach (DocExample docExam in project.Examples) { // generate ifcxml for each sample ExportExample(pathSamples, pathSamplesWeb, typeProject, docExam, writerIndex); } writerIndex.WriteLine("</table>"); writerIndex.WriteLine("</body></html>"); } } // terms, abbreviations, references, bibliography, ... #if false string pathTerms = path + @"\terms"; System.IO.Directory.CreateDirectory(pathSamples); foreach (DocTerm docTerm in this.m_project.Terms) { } #endif // localization SortedList <string, string> listLocale = new SortedList <string, string>(); foreach (DocObject eachobj in mapEntity.Values) { if (eachobj.Localization != null) { foreach (DocLocalization doclocal in eachobj.Localization) { // only deal with languages, not regions if (doclocal.Locale != null && doclocal.Locale.Length >= 2) { string language = doclocal.Locale.Substring(0, 2); if (!listLocale.ContainsKey(language)) { listLocale.Add(language, doclocal.Locale); } } } } } if (bExportLocalize) { string pathLocalize = path + @"\localize"; System.IO.Directory.CreateDirectory(pathLocalize); foreach (string locale in listLocale.Keys) { string pathLocale = path + @"\localize\" + locale + ".txt"; using (FormatCSV format = new FormatCSV(pathLocale)) { format.Instance = project; format.Locales = new string[] { locale }; format.Scope = DocDefinitionScopeEnum.Default; format.Save(); } } } }
public Compiler(DocProject project, DocModelView[] views, DocExchangeDefinition exchange) { this.m_project = project; this.m_views = views; this.m_exchange = exchange; string schemaid = project.GetSchemaIdentifier(); this.m_assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(schemaid), AssemblyBuilderAccess.RunAndSave); this.m_module = this.m_assembly.DefineDynamicModule("IFC4.dll", "IFC4.dll"); this.m_definitions = new Dictionary <string, DocObject>(); this.m_types = new Dictionary <string, Type>(); this.m_fields = new Dictionary <Type, Dictionary <string, FieldInfo> >(); this.m_templates = new Dictionary <DocTemplateDefinition, MethodInfo>(); this.m_namespaces = new Dictionary <string, string>(); Dictionary <DocObject, bool> included = null; if (this.m_views != null) { included = new Dictionary <DocObject, bool>(); foreach (DocModelView docView in this.m_views) { this.m_project.RegisterObjectsInScope(docView, included); } } foreach (DocSection docSection in project.Sections) { foreach (DocSchema docSchema in docSection.Schemas) { foreach (DocEntity docEntity in docSchema.Entities) { if (included == null || included.ContainsKey(docEntity)) { if (!this.m_definitions.ContainsKey(docEntity.Name)) { this.m_definitions.Add(docEntity.Name, docEntity); this.m_namespaces.Add(docEntity.Name, docSchema.Name); } } } foreach (DocType docType in docSchema.Types) { if (included == null || included.ContainsKey(docType)) { if (!this.m_definitions.ContainsKey(docType.Name)) { this.m_definitions.Add(docType.Name, docType); this.m_namespaces.Add(docType.Name, docSchema.Name); } } } } } // first register types and fields foreach (string key in this.m_definitions.Keys) { RegisterType(key); } // now register template functions (may depend on fields existing) // find associated ConceptRoot for model view, define validation function if (this.m_views != null) { foreach (DocModelView view in this.m_views) { string viewname = view.Code; foreach (DocConceptRoot root in view.ConceptRoots) { Type tOpen = null; if (this.m_types.TryGetValue(root.ApplicableEntity.Name, out tOpen) && tOpen is TypeBuilder) { TypeBuilder tb = (TypeBuilder)tOpen; foreach (DocTemplateUsage concept in root.Concepts) { CompileConcept(concept, view, tb); } } } } } // seal types once all are built List <TypeBuilder> listBase = new List <TypeBuilder>(); foreach (string key in this.m_definitions.Keys) { Type tOpen = this.m_types[key]; while (tOpen is TypeBuilder) { listBase.Add((TypeBuilder)tOpen); tOpen = tOpen.BaseType; } // seal in base class order for (int i = listBase.Count - 1; i >= 0; i--) { Type tClosed = listBase[i].CreateType(); this.m_types[tClosed.Name] = tClosed; } listBase.Clear(); // record bindings DocDefinition docDef = this.m_definitions[key] as DocDefinition; if (docDef != null) { docDef.RuntimeType = this.m_types[key]; if (docDef is DocEntity) { DocEntity docEnt = (DocEntity)docDef; foreach (DocAttribute docAttr in docEnt.Attributes) { docAttr.RuntimeField = docDef.RuntimeType.GetField(docAttr.Name); } } } } }
public string FormatDefinitions(DocProject docProject, DocPublication docPublication, Dictionary <string, DocObject> map, Dictionary <DocObject, bool> included) { // clear containers listPropertiesOutput.Clear(); addedIndividuals.Clear(); attribInverses.Clear(); subTypesOfEntity.Clear(); StringBuilder sb = new StringBuilder(); string ifcversion = docProject.GetSchemaIdentifier(); //string ifcns = "http://www.buildingsmart-tech.org/ifcOWL/" + ifcversion; //string ifcns = "http://ifcowl.openbimstandards.org/" + ifcversion; string ifcns = "http://www.buildingsmart-tech.org/ifc/" + ifcversion; // namespace definitions sb.AppendLine("@prefix : <" + ifcns + "#> ."); sb.AppendLine("@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> ."); sb.AppendLine("@prefix dce: <http://purl.org/dc/elements/1.1/> ."); sb.AppendLine("@prefix owl: <http://www.w3.org/2002/07/owl#> ."); sb.AppendLine("@prefix xsd: <http://www.w3.org/2001/XMLSchema#> ."); sb.AppendLine("@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ."); sb.AppendLine("@prefix vann: <http://purl.org/vocab/vann/> ."); sb.AppendLine("@prefix list: <https://w3id.org/list#> ."); sb.AppendLine("@prefix expr: <https://w3id.org/express#> ."); sb.AppendLine("@prefix ifc: <" + ifcns + "#> ."); sb.AppendLine("@prefix cc: <http://creativecommons.org/ns#> ."); sb.AppendLine(""); // ontology definition sb.AppendLine("<" + ifcns + ">"); sb.AppendLine("\ta owl:Ontology ;"); sb.AppendLine("\trdfs:comment \"Ontology automatically generated from the EXPRESS schema using the IfcDoc functions developed by Pieter Pauwels ([email protected]) and Walter Terkaj ([email protected]) \" ;"); sb.AppendLine("\tcc:license <http://creativecommons.org/licenses/by/3.0/> ;"); sb.AppendLine("\tdce:contributor \"Jakob Beetz ([email protected])\" , \"Maria Poveda Villalon ([email protected])\" ;"); // \"Aleksandra Sojic ([email protected])\" , sb.AppendLine("\tdce:creator \"Pieter Pauwels ([email protected])\" , \"Walter Terkaj ([email protected])\" ;"); sb.AppendLine("\tdce:date \"2015/10/02\" ;"); sb.AppendLine("\tdce:description \"OWL ontology for the IFC conceptual data schema and exchange file format for Building Information Model (BIM) data\" ;"); sb.AppendLine("\tdce:identifier \"" + ifcversion + "\" ;"); sb.AppendLine("\tdce:language \"en\" ;"); sb.AppendLine("\tdce:title \"" + ifcversion + "\" ;"); sb.AppendLine("\tvann:preferredNamespacePrefix \"ifc\" ;"); sb.AppendLine("\tvann:preferredNamespaceUri \"" + ifcns + "\" ;"); sb.AppendLine("\towl:imports <https://w3id.org/express> ."); sb.AppendLine(); // check which Inverse Attributes must be discarded because of conflicts // get subtypes of an entity foreach (DocSection docSection in docProject.Sections) { foreach (DocSchema docSchema in docSection.Schemas) { foreach (DocEntity docEntity in docSchema.Entities) { // get supertype/subtype if (docEntity.BaseDefinition != null) { if (!subTypesOfEntity.ContainsKey(docEntity.BaseDefinition)) { subTypesOfEntity.Add(docEntity.BaseDefinition, new HashSet <string>()); } subTypesOfEntity[docEntity.BaseDefinition].Add(docEntity.Name); } // check attributes foreach (DocAttribute docAttr in docEntity.Attributes) { if (docAttr.Inverse != null) { var key = new Tuple <string, string>(docAttr.Inverse, docAttr.DefinedType); if (!attribInverses.ContainsKey(key)) { attribInverses.Add(key, 1); } else { attribInverses[key] += 1; } } } } } } // generate definitions foreach (DocSection docSection in docProject.Sections) { foreach (DocSchema docSchema in docSection.Schemas) { foreach (DocType docType in docSchema.Types) { bool use = false; included.TryGetValue(docType, out use); if (use) { if (docType is DocDefined) { DocDefined docDefined = (DocDefined)docType; string text = this.FormatDefinedFull(docDefined, true); sb.Append(text); } else if (docType is DocSelect) { DocSelect docSelect = (DocSelect)docType; string text = this.FormatSelectFull(docSelect, map, included, true); sb.Append(text); } else if (docType is DocEnumeration) { DocEnumeration docEnumeration = (DocEnumeration)docType; string text = this.FormatEnumerationFull(docEnumeration, true); sb.Append(text); } } } foreach (DocEntity docEntity in docSchema.Entities) { bool use = false; included.TryGetValue(docEntity, out use); if (use) { string text = this.FormatEntityFull(docEntity, map, included, true); sb.Append(text); } } } } listPropertiesOutput.Clear(); return(sb.ToString()); }