Example #1
0
        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
        }
Example #2
0
        public Compiler(DocProject project, DocModelView[] views, DocExchangeDefinition exchange)
        {
            this.m_project  = project;
            this.m_views    = views;
            this.m_exchange = exchange;

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

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