Ejemplo n.º 1
0
        public static DocProject LoadFile(string filePath)
        {
            List <object> instances = new List <object>();
            string        ext       = System.IO.Path.GetExtension(filePath).ToLower();
            string        schema    = "";
            DocProject    project   = null;

            switch (ext)
            {
            case ".ifcdoc":
                using (FileStream streamDoc = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    Dictionary <long, object> dictionaryInstances = null;
                    StepSerializer            formatDoc           = new StepSerializer(typeof(DocProject), SchemaDOC.Types);
                    project = (DocProject)formatDoc.ReadObject(streamDoc, out dictionaryInstances);
                    instances.AddRange(dictionaryInstances.Values);
                    schema = formatDoc.Schema;
                }
                break;

            case ".ifcdocxml":
                using (FileStream streamDoc = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    Dictionary <string, object> dictionaryInstances = null;
                    XmlSerializer formatDoc = new XmlSerializer(typeof(DocProject));
                    project = (DocProject)formatDoc.ReadObject(streamDoc, out dictionaryInstances);
                    instances.AddRange(dictionaryInstances.Values);
                }
                break;

            default:
                MessageBox.Show("Unsupported file type " + ext, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                break;

#if MDB
            case ".mdb":
                using (FormatMDB format = new FormatMDB(this.m_file, SchemaDOC.Types, this.m_instances))
                {
                    format.Load();
                }
                break;
#endif
            }
            if (project == null)
            {
                return(null);
            }

            double schemaVersion = 0;
            if (!string.IsNullOrEmpty(schema))
            {
                string[] fields = schema.Split("_".ToCharArray());
                int      i      = 0;
                if (fields.Length > 1)
                {
                    if (int.TryParse(fields[1], out i))
                    {
                        schemaVersion = i;
                    }
                    if (fields.Length > 2 && int.TryParse(fields[2], out i))
                    {
                        schemaVersion += i / 10.0;
                    }
                }
            }
            List <SEntity> listDelete = new List <SEntity>();
            List <DocTemplateDefinition> listTemplate = new List <DocTemplateDefinition>();

            foreach (object o in instances)
            {
                if (o is DocSchema)
                {
                    DocSchema docSchema = (DocSchema)o;

                    // renumber page references
                    foreach (DocPageTarget docTarget in docSchema.PageTargets)
                    {
                        if (docTarget.Definition != null)                         // fix it up -- NULL bug from older .ifcdoc files
                        {
                            int page = docSchema.GetDefinitionPageNumber(docTarget);
                            int item = docSchema.GetPageTargetItemNumber(docTarget);
                            docTarget.Name = page + "," + item + " " + docTarget.Definition.Name;

                            foreach (DocPageSource docSource in docTarget.Sources)
                            {
                                docSource.Name = docTarget.Name;
                            }
                        }
                    }
                }
                else if (o is DocExchangeDefinition)
                {
                    // files before V4.9 had Description field; no longer needed so use regular Documentation field again.
                    DocExchangeDefinition docexchange = (DocExchangeDefinition)o;
                    if (docexchange._Description != null)
                    {
                        docexchange.Documentation = docexchange._Description;
                        docexchange._Description  = null;
                    }
                }
                else if (o is DocTemplateDefinition)
                {
                    // files before V5.0 had Description field; no longer needed so use regular Documentation field again.
                    DocTemplateDefinition doctemplate = (DocTemplateDefinition)o;
                    if (doctemplate._Description != null)
                    {
                        doctemplate.Documentation = doctemplate._Description;
                        doctemplate._Description  = null;
                    }

                    listTemplate.Add((DocTemplateDefinition)o);
                }
                else if (o is DocConceptRoot)
                {
                    // V12.0: ensure template is defined
                    DocConceptRoot docConcRoot = (DocConceptRoot)o;
                    if (docConcRoot.ApplicableTemplate == null && docConcRoot.ApplicableEntity != null)
                    {
                        docConcRoot.ApplicableTemplate      = new DocTemplateDefinition();
                        docConcRoot.ApplicableTemplate.Type = docConcRoot.ApplicableEntity.Name;
                    }
                }
                else if (o is DocTemplateUsage)
                {
                    // V12.0: ensure template is defined
                    DocTemplateUsage docUsage = (DocTemplateUsage)o;
                    if (docUsage.Definition == null)
                    {
                        docUsage.Definition = new DocTemplateDefinition();
                    }
                }
                else if (o is DocLocalization)
                {
                    DocLocalization localization = o as DocLocalization;
                    if (!string.IsNullOrEmpty(localization.Name))
                    {
                        localization.Name = localization.Name.Trim();
                    }
                }
                // ensure all objects have valid guid
                DocObject docObject = o as DocObject;
                if (docObject != null)
                {
                    if (docObject.Uuid == Guid.Empty)
                    {
                        docObject.Uuid = Guid.NewGuid();
                    }
                    if (!string.IsNullOrEmpty(docObject.Documentation))
                    {
                        docObject.Documentation = docObject.Documentation.Trim();
                    }

                    if (schemaVersion < 12.1)
                    {
                        DocChangeSet docChangeSet = docObject as DocChangeSet;
                        if (docChangeSet != null)
                        {
                            docChangeSet.ChangesEntities.RemoveAll(x => !isUnchanged(x));
                        }
                        else
                        {
                            if (schemaVersion < 12)
                            {
                                DocEntity entity = docObject as DocEntity;
                                if (entity != null)
                                {
                                    entity.ClearDefaultMember();
                                }
                            }
                        }
                    }
                }
            }

            if (project == null)
            {
                return(null);
            }

            if (schemaVersion > 0 && schemaVersion < 12.1)
            {
                Dictionary <string, DocPropertyEnumeration> encounteredPropertyEnumerations = new Dictionary <string, DocPropertyEnumeration>();
                foreach (DocSchema docSchema in project.Sections.SelectMany(x => x.Schemas))
                {
                    extractListingsV12_1(project, docSchema, encounteredPropertyEnumerations);
                }
            }
            foreach (DocModelView docModelView in project.ModelViews)
            {
                // sort alphabetically (V11.3+)
                docModelView.SortConceptRoots();
            }

            // upgrade to Publications (V9.6)
            if (project.Annotations.Count == 4)
            {
                project.Publications.Clear();

                DocAnnotation docCover    = project.Annotations[0];
                DocAnnotation docContents = project.Annotations[1];
                DocAnnotation docForeword = project.Annotations[2];
                DocAnnotation docIntro    = project.Annotations[3];

                DocPublication docPub = new DocPublication();
                docPub.Name          = "Default";
                docPub.Documentation = docCover.Documentation;
                docPub.Owner         = docCover.Owner;
                docPub.Author        = docCover.Author;
                docPub.Code          = docCover.Code;
                docPub.Copyright     = docCover.Copyright;
                docPub.Status        = docCover.Status;
                docPub.Version       = docCover.Version;

                docPub.Annotations.Add(docForeword);
                docPub.Annotations.Add(docIntro);

                project.Publications.Add(docPub);

                docCover.Delete();
                docContents.Delete();
                project.Annotations.Clear();
            }
            project.SortProject();
            return(project);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates change log entries in current project based on a previous project.
        /// </summary>
        /// <param name="projectPrev">The previous project for which definitions are compared.</param>
        /// <param name="projectCurr">The current project where change log entries are generated.</param>
        public static void Generate(DocProject projectPrev, DocProject projectCurr)
        {
            // copy over any previous change logs
            foreach(DocChangeSet prevCS in projectPrev.ChangeSets)
            {
                DocChangeSet currCS = new DocChangeSet();
                currCS.Name = prevCS.Name;
                currCS.Documentation = prevCS.Documentation;
                currCS.VersionBaseline = prevCS.VersionBaseline;
                currCS.VersionCompared = prevCS.VersionCompared;
                projectCurr.ChangeSets.Add(currCS);

                foreach(DocChangeAction prevCA in prevCS.ChangesEntities)
                {
                    DocChangeAction currCA = prevCA.Copy();
                    currCS.ChangesEntities.Add(currCA);
                }

                if (prevCS.ChangesProperties != null)
                {
                    foreach (DocChangeAction prevCA in prevCS.ChangesProperties)
                    {
                        DocChangeAction currCA = prevCA.Copy();
                        currCS.ChangesProperties.Add(currCA);
                    }
                }

                if (prevCS.ChangesQuantities != null)
                {
                    foreach (DocChangeAction prevCA in prevCS.ChangesQuantities)
                    {
                        DocChangeAction currCA = prevCA.Copy();
                        currCS.ChangesQuantities.Add(currCA);
                    }
                }
            }

            // build maps            
            Dictionary<string, DocObject> mapNew = new Dictionary<string, DocObject>();
            foreach (DocSection docSection in projectCurr.Sections)
            {
                foreach (DocSchema docSchema in docSection.Schemas)
                {
                    foreach (DocEntity docEntity in docSchema.Entities)
                    {
                        mapNew.Add(docEntity.Name, docEntity);
                    }
                    foreach (DocType docType in docSchema.Types)
                    {
                        mapNew.Add(docType.Name, docType);
                    }
                }
            }
            Dictionary<string, DocObject> mapOld = new Dictionary<string, DocObject>();
            foreach (DocSection docSection in projectPrev.Sections)
            {
                foreach (DocSchema docSchema in docSection.Schemas)
                {
                    foreach (DocEntity docEntity in docSchema.Entities)
                    {
                        mapOld.Add(docEntity.Name, docEntity);
                    }
                    foreach (DocType docType in docSchema.Types)
                    {
                        mapOld.Add(docType.Name, docType);
                    }
                }
            }

            DocChangeSet docChangeSet = new DocChangeSet();
            projectCurr.ChangeSets.Add(docChangeSet);
            docChangeSet.Name = projectPrev.Sections[0].Code;
            docChangeSet.VersionBaseline = projectPrev.Sections[0].Version;

            // iterate through each schema (new and old)
            for (int iSection = 4; iSection < 8; iSection++)
            {
                DocSection docSection = projectCurr.Sections[iSection];
                DocSection docSectionBase = projectPrev.Sections[iSection];

                DocChangeAction docChangeSection = new DocChangeAction();
                docChangeSet.ChangesEntities.Add(docChangeSection);
                docChangeSection.Name = docSection.Name;

                DocChangeAction docChangeSectionProperties = new DocChangeAction();
                docChangeSet.ChangesProperties.Add(docChangeSectionProperties);
                docChangeSectionProperties.Name = docSection.Name;

                DocChangeAction docChangeSectionQuantities = new DocChangeAction();
                docChangeSet.ChangesQuantities.Add(docChangeSectionQuantities);
                docChangeSectionQuantities.Name = docSection.Name;

                foreach (DocSchema docSchema in docSection.Schemas)
                {
                    // find equivalent schema
                    DocSchema docSchemaBase = null;
                    foreach (DocSchema docSchemaEach in docSectionBase.Schemas)
                    {
                        if (docSchemaEach.Name.Equals(docSchema.Name))
                        {
                            docSchemaBase = docSchemaEach;
                            break;
                        }
                    }

                    DocChangeAction docChangeSchema = new DocChangeAction();
                    docChangeSection.Changes.Add(docChangeSchema);
                    docChangeSchema.Name = docSchema.Name;

                    DocChangeAction docChangeSchemaProperties = new DocChangeAction();
                    docChangeSectionProperties.Changes.Add(docChangeSchemaProperties);
                    docChangeSchemaProperties.Name = docSchema.Name;

                    DocChangeAction docChangeSchemaQuantities = new DocChangeAction();
                    docChangeSectionQuantities.Changes.Add(docChangeSchemaQuantities);
                    docChangeSchemaQuantities.Name = docSchema.Name;

                    if (docSchemaBase == null)
                    {
                        // new schema
                        docChangeSchema.Action = DocChangeActionEnum.ADDED;
                    }
                    else
                    {
                        // existing schema


                        // compare types
                        foreach (DocType docType in docSchema.Types)
                        {
                            DocChangeAction docChangeType = new DocChangeAction();
                            docChangeSchema.Changes.Add(docChangeType);
                            docChangeType.Name = docType.Name;

                            // find equivalent type
                            DocType docTypeBase = null;
                            foreach (DocType docTypeEach in docSchemaBase.Types)
                            {
                                if (docTypeEach.Name.Equals(docType.Name))
                                {
                                    docTypeBase = docTypeEach;
                                    break;
                                }
                            }

                            if (docTypeBase == null)
                            {
                                // new type
                                docChangeType.Action = DocChangeActionEnum.ADDED;

                                // check if it was moved from another schema                                
                                foreach (DocSection docOtherSection in projectPrev.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocType docOtherType in docOtherSchema.Types)
                                        {
                                            if (docOtherType.Name.Equals(docType.Name))
                                            {
                                                docChangeType.Action = DocChangeActionEnum.MOVED;
                                                docChangeType.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docOtherSchema.Name.ToUpper(), docSchema.Name.ToUpper()));
                                                docTypeBase = docOtherType;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            
                            if(docTypeBase != null)
                            {
                                // existing type

                                // if enumeration, check enums
                                if (docType is DocEnumeration)
                                {
                                    DocEnumeration docEnumeration = (DocEnumeration)docType;
                                    DocEnumeration docEnumerationBase = (DocEnumeration)docTypeBase;

                                    // find constants added
                                    foreach (DocConstant docConstant in docEnumeration.Constants)
                                    {
                                        // find equivalent constant
                                        DocConstant docConstantBase = null;
                                        foreach (DocConstant docConstantEach in docEnumerationBase.Constants)
                                        {
                                            if (docConstantEach.Name.Equals(docConstant.Name))
                                            {
                                                docConstantBase = docConstantEach;
                                                break;
                                            }
                                        }

                                        // for constants, only generate additions or deletions for brevity
                                        if (docConstantBase == null)
                                        {
                                            // new entity
                                            DocChangeAction docChangeConstant = new DocChangeAction();
                                            docChangeType.Changes.Add(docChangeConstant);
                                            docChangeConstant.Name = docConstant.Name;
                                            docChangeConstant.Action = DocChangeActionEnum.ADDED;
                                        }
                                    }

                                    // find constants removed
                                    foreach (DocConstant docConstantBase in docEnumerationBase.Constants)
                                    {
                                        // find equivalent constant
                                        DocConstant docConstant = null;
                                        foreach (DocConstant docConstantEach in docEnumeration.Constants)
                                        {
                                            if (docConstantEach.Name.Equals(docConstantBase.Name))
                                            {
                                                docConstant = docConstantEach;
                                                break;
                                            }
                                        }

                                        // for constants, only generate additions or deletions for brevity
                                        if (docConstant == null)
                                        {
                                            // deleted
                                            DocChangeAction docChangeConstant = new DocChangeAction();
                                            docChangeType.Changes.Add(docChangeConstant);
                                            docChangeConstant.Name = docConstantBase.Name;
                                            docChangeConstant.Action = DocChangeActionEnum.DELETED;
                                            docChangeConstant.ImpactSPF = true;
                                            docChangeConstant.ImpactXML = true;
                                        }
                                    }

                                }
                                else if (docType is DocSelect)
                                {
                                    DocSelect docEnumeration = (DocSelect)docType;
                                    DocSelect docEnumerationBase = (DocSelect)docTypeBase;

                                    // find select items added
                                    foreach (DocSelectItem docConstant in docEnumeration.Selects)
                                    {
                                        // find equivalent constant
                                        DocSelectItem docConstantBase = null;
                                        foreach (DocSelectItem docConstantEach in docEnumerationBase.Selects)
                                        {
                                            if (docConstantEach.Name.Equals(docConstant.Name))
                                            {
                                                docConstantBase = docConstantEach;
                                                break;
                                            }
                                        }

                                        // for constants, only generate additions or deletions for brevity
                                        if (docConstantBase == null)
                                        {
                                            // new entity
                                            DocChangeAction docChangeConstant = new DocChangeAction();
                                            docChangeType.Changes.Add(docChangeConstant);
                                            docChangeConstant.Name = docConstant.Name;
                                            docChangeConstant.Action = DocChangeActionEnum.ADDED;
                                        }
                                    }

                                    // find select items removed
                                    foreach (DocSelectItem docConstantBase in docEnumerationBase.Selects)
                                    {
                                        // find equivalent constant
                                        DocSelectItem docConstant = null;
                                        foreach (DocSelectItem docConstantEach in docEnumeration.Selects)
                                        {
                                            if (docConstantEach.Name.Equals(docConstantBase.Name))
                                            {
                                                docConstant = docConstantEach;
                                                break;
                                            }
                                        }

                                        // for selects, only generate additions or deletions for brevity
                                        if (docConstant == null)
                                        {
                                            // deleted select
                                            DocChangeAction docChangeConstant = new DocChangeAction();
                                            docChangeType.Changes.Add(docChangeConstant);
                                            docChangeConstant.Name = docConstantBase.Name;
                                            docChangeConstant.Action = DocChangeActionEnum.DELETED;

                                            // if a supertype of the deleted select has been added, then it's compatible (e.g. IfcMetricValueSelect: +IfcValue, -IfcText)                                            
                                            if (!SelectIncludes(docEnumeration, docConstantBase.Name, mapNew))
                                            {
                                                docChangeConstant.ImpactSPF = true;
                                                docChangeConstant.ImpactXML = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }


                        // compare entities
                        foreach (DocEntity docEntity in docSchema.Entities)
                        {
                            if (docEntity.Name.Equals("IfcWindowLiningProperties"))
                            {
                                docEntity.ToString();
                            }

                            DocChangeAction docChangeEntity = new DocChangeAction();
                            docChangeSchema.Changes.Add(docChangeEntity);
                            docChangeEntity.Name = docEntity.Name;

                            // find equivalent entity
                            DocEntity docEntityBase = null;
                            foreach (DocEntity docEntityEach in docSchemaBase.Entities)
                            {
                                if (docEntityEach.Name.Equals(docEntity.Name))
                                {
                                    docEntityBase = docEntityEach;
                                    break;
                                }
                            }

                            if (docEntityBase == null)
                            {
                                // new entity
                                docChangeEntity.Action = DocChangeActionEnum.ADDED;

                                // check if it was moved from another schema                                
                                foreach (DocSection docOtherSection in projectPrev.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocEntity docOtherEntity in docOtherSchema.Entities)
                                        {
                                            if (docOtherEntity.Name.Equals(docEntity.Name))
                                            {
                                                docEntityBase = docOtherEntity; // still compare attributes if moved (e.g. IfcRelSequence)

                                                docChangeEntity.Action = DocChangeActionEnum.MOVED;
                                                docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docOtherSchema.Name.ToUpper(), docSchema.Name.ToUpper()));
                                                break;
                                            }
                                        }
                                    }
                                }

                            }

                            if (docEntityBase != null)
                            {
                                // existing entity

                                // compare abstract vs. non-abstract
                                if (docEntity.IsAbstract() != docEntityBase.IsAbstract())
                                {
                                    docChangeEntity.Action = DocChangeActionEnum.MODIFIED;

                                    if (docEntityBase.IsAbstract())
                                    {
                                        docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, "ABSTRACT", null));
                                    }
                                    else
                                    {
                                        docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, null, "ABSTRACT"));
                                    }
                                }

                                // compare attributes by index

                                // only report non-abstract entities; e.g. attributes may be demoted without file impact
                                if (!docEntity.IsAbstract())
                                {
                                    List<DocAttribute> listAttributeNew = new List<DocAttribute>();
                                    List<DocAttribute> listAttributeOld = new List<DocAttribute>();
                                    BuildAttributeListDirect(listAttributeNew, mapNew, docEntity);
                                    BuildAttributeListDirect(listAttributeOld, mapOld, docEntityBase);

                                    for (int iAttribute = 0; iAttribute < listAttributeNew.Count; iAttribute++)
                                    {
                                        DocAttribute docAttribute = listAttributeNew[iAttribute];

                                        // we only care about direct attributes
                                        DocChangeAction docChangeAttribute = new DocChangeAction();
                                        docChangeEntity.Changes.Add(docChangeAttribute);
                                        docChangeAttribute.Name = docAttribute.Name;

                                        if (iAttribute >= listAttributeOld.Count)
                                        {
                                            // new attribute added
                                            docChangeAttribute.Action = DocChangeActionEnum.ADDED;
                                        }
                                        else
                                        {
                                            DocAttribute docAttributeBase = listAttributeOld[iAttribute];

                                            // compare for changes
                                            if (!docAttribute.Name.Equals(docAttributeBase.Name))
                                            {
                                                docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                                docChangeAttribute.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.NAME, docAttributeBase.Name, docAttribute.Name));

                                                docChangeAttribute.ImpactXML = true; // no impact to SPF though
                                            }

                                            if (!docAttribute.DefinedType.Equals(docAttributeBase.DefinedType))
                                            {
                                                DocChangeAspect docAspect = new DocChangeAspect(DocChangeAspectEnum.TYPE, docAttributeBase.DefinedType, docAttribute.DefinedType);
                                                docChangeAttribute.Aspects.Add(docAspect);
                                                docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;

                                                // check for compatibility
                                                // assume incompatible unless we can prove types are compatible
                                                bool impact = true;

                                                // ok if new type is a supertype of the old type
                                                DocObject docNew = null;
                                                if (mapNew.TryGetValue(docAspect.NewValue, out docNew))
                                                {
                                                    DocObject docOld = null;
                                                    if (mapOld.TryGetValue(docAspect.OldValue, out docOld))
                                                    {
                                                        if (docNew is DocEntity)
                                                        {
                                                            DocEntity docNewEnt = (DocEntity)docNew;

                                                            if (docOld is DocEntity)
                                                            {
                                                                DocEntity docOldEnt = (DocEntity)docOld;

                                                                while (docNewEnt != null)
                                                                {
                                                                    if (docNewEnt.Name.Equals(docOldEnt.Name))
                                                                    {
                                                                        impact = false; // subtype
                                                                    }

                                                                    if (docNewEnt.BaseDefinition != null)
                                                                    {
                                                                        docNewEnt = mapNew[docNewEnt.BaseDefinition] as DocEntity;
                                                                    }
                                                                    else
                                                                    {
                                                                        docNewEnt = null;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        else if (docNew is DocSelect)
                                                        {
                                                            DocSelect docNewSelect = (DocSelect)docNew;
                                                            foreach (DocSelectItem docNewSelectItem in docNewSelect.Selects)
                                                            {
                                                                if (docNewSelectItem.Name.Equals(docOld.Name))
                                                                {
                                                                    impact = false; // included in select
                                                                }
                                                            }
                                                        }
                                                        else if (docNew is DocEnumeration)
                                                        {
                                                            // ok if new enumeration contains all of old enumerations (e.g. IfcInternalOrExternalEnum -> IfcSpaceTypeEnum)                                                            
                                                            DocEnumeration docNewEnum = (DocEnumeration)docNew;
                                                            if (docOld is DocEnumeration)
                                                            {
                                                                impact = false;

                                                                DocEnumeration docOldEnum = (DocEnumeration)docOld;
                                                                foreach (DocConstant docOldConstant in docOldEnum.Constants)
                                                                {
                                                                    bool match = false;
                                                                    foreach (DocConstant docNewConstant in docNewEnum.Constants)
                                                                    {
                                                                        if (docOldConstant.Name.Equals(docNewConstant.Name))
                                                                        {
                                                                            match = true;
                                                                            break;
                                                                        }
                                                                    }

                                                                    if (!match)
                                                                    {
                                                                        impact = true;
                                                                        break;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        else if (docNew is DocDefined)
                                                        {
                                                            DocDefined docNewDefined = (DocDefined)docNew;

                                                            // compare underlying types
                                                            if (docOld is DocDefined)
                                                            {
                                                                DocDefined docOldDefined = (DocDefined)docOld;

                                                                if (docNewDefined.DefinedType.Equals(docOldDefined.DefinedType))
                                                                {
                                                                    // e.g. IfcLabel -> IfcIdentifier
                                                                    impact = false;
                                                                }
                                                            }
                                                        }
                                                    }
                                                }

                                                if (docNew is DocDefined && ((DocDefined)docNew).DefinedType == docAspect.OldValue)
                                                {
                                                    impact = false;
                                                }

                                                //todo: add generic check that traverses multiple levels of defined types; in the interest of hitting deadline, hard-coded hack for now
                                                if (docNew != null && docNew.Name == "IfcPositiveInteger" && docAspect.OldValue == "INTEGER")
                                                {
                                                    impact = false;
                                                }
                                                if (docNew != null && docNew.Name == "IfcBinary" && docAspect.OldValue == "BINARY (32)")
                                                {
                                                    impact = false;
                                                }

                                                if(impact)
                                                {
                                                    impact.ToString();
                                                }

                                                docChangeAttribute.ImpactSPF = impact;
                                                docChangeAttribute.ImpactXML = impact;
                                            }

                                            if (docAttribute.AttributeFlags != docAttributeBase.AttributeFlags)
                                            {
                                                docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;

                                                if ((docAttributeBase.AttributeFlags & 1) != 0)
                                                {
                                                    docChangeAttribute.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, "OPTIONAL", null));
                                                }
                                                else
                                                {
                                                    docChangeAttribute.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, null, "OPTIONAL"));
                                                }
                                            }

                                            if (docAttribute.AggregationType != docAttributeBase.AggregationType)
                                            {
                                                docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                                docChangeAttribute.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.AGGREGATION, docAttributeBase.GetAggregation().ToString(), docAttribute.GetAggregation().ToString()));
                                            }
                                        }
                                    }

                                    // report deleted attributes
                                    for (int iAttribute = listAttributeNew.Count; iAttribute < listAttributeOld.Count; iAttribute++)
                                    {
                                        DocAttribute docAttributeBase = listAttributeOld[iAttribute];

                                        DocChangeAction docChangeAttribute = new DocChangeAction();
                                        docChangeEntity.Changes.Add(docChangeAttribute);
                                        docChangeAttribute.Name = docAttributeBase.Name;
                                        docChangeAttribute.Action = DocChangeActionEnum.DELETED;
                                        docChangeAttribute.ImpactSPF = true;

                                        // deleted attributes don't affect XML
                                    }



                                    // now inverse - order doesn't matter - compare by name

                                    listAttributeNew.Clear();
                                    listAttributeOld.Clear();
                                    BuildAttributeListInverse(listAttributeNew, mapNew, docEntity);
                                    BuildAttributeListInverse(listAttributeOld, mapOld, docEntityBase);

                                    for (int iAttribute = 0; iAttribute < listAttributeNew.Count; iAttribute++)
                                    {
                                        DocAttribute docAttribute = listAttributeNew[iAttribute];

                                        DocChangeAction docChangeAttribute = new DocChangeAction();
                                        docChangeEntity.Changes.Add(docChangeAttribute);
                                        docChangeAttribute.Name = docAttribute.Name;
                                        docChangeAttribute.Status = "INVERSE";

                                        DocAttribute docAttributeBase = null;
                                        foreach(DocAttribute docAttrOld in listAttributeOld)
                                        {
                                            if(docAttrOld.Name == docAttribute.Name)
                                            {
                                                docAttributeBase = docAttrOld;
                                                break;
                                            }
                                        }

                                        if (docAttributeBase == null)
                                        {
                                            // new attribute added
                                            docChangeAttribute.Action = DocChangeActionEnum.ADDED;
                                        }
                                        else
                                        {
                                            if (!docAttribute.DefinedType.Equals(docAttributeBase.DefinedType))
                                            {
                                                DocChangeAspect docAspect = new DocChangeAspect(DocChangeAspectEnum.TYPE, docAttributeBase.DefinedType, docAttribute.DefinedType);
                                                docChangeAttribute.Aspects.Add(docAspect);
                                                docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                                docChangeAttribute.ImpactSPF = false;
                                                docChangeAttribute.ImpactXML = false;
                                            }

                                            if (docAttribute.AggregationType != docAttributeBase.AggregationType)
                                            {
                                                docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                                docChangeAttribute.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.AGGREGATION, docAttributeBase.GetAggregation().ToString(), docAttribute.GetAggregation().ToString()));
                                            }
                                        }
                                    }

                                    // report deleted attributes
                                    for (int iAttribute = 0; iAttribute < listAttributeOld.Count; iAttribute++)
                                    {
                                        DocAttribute docAttributeBase = listAttributeOld[iAttribute];

                                        DocAttribute docAttributeCurr = null;
                                        foreach(DocAttribute docAttrNew in listAttributeNew)
                                        {
                                            if(docAttrNew.Name == docAttributeBase.Name)
                                            {
                                                docAttributeCurr = docAttrNew;
                                                break;
                                            }
                                        }

                                        if (docAttributeCurr == null)
                                        {
                                            DocChangeAction docChangeAttribute = new DocChangeAction();
                                            docChangeEntity.Changes.Add(docChangeAttribute);
                                            docChangeAttribute.Name = docAttributeBase.Name;
                                            docChangeAttribute.Action = DocChangeActionEnum.DELETED;
                                            docChangeAttribute.Status = "INVERSE";
                                        }
                                    }

                                }
                            }
                        }

                        // now find deleted entities
                        foreach (DocEntity docEntityBase in docSchemaBase.Entities)
                        {
                            // find equivalent
                            DocEntity docEntity = null;
                            foreach (DocEntity docEntityEach in docSchema.Entities)
                            {
                                if (docEntityEach.Name.Equals(docEntityBase.Name))
                                {
                                    docEntity = docEntityEach;
                                    break;
                                }
                            }

                            if (docEntity == null)
                            {
                                // entity may have moved to other schema; check other schemas
                                DocSchema docThatSchema = null;
                                foreach (DocSection docOtherSection in projectCurr.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocEntity docOtherEntity in docOtherSchema.Entities)
                                        {
                                            if (docOtherEntity.Name.Equals(docEntityBase.Name))
                                            {
                                                docEntity = docOtherEntity;
                                                docThatSchema = docOtherSchema;
                                            }
                                        }
                                    }
                                }

                                DocChangeAction docChangeEntity = new DocChangeAction();
                                docChangeSchema.Changes.Add(docChangeEntity);
                                docChangeEntity.Name = docEntityBase.Name;

                                if (docEntity != null)
                                {
                                    // moved from another schema
                                    docChangeEntity.Action = DocChangeActionEnum.MOVED;
                                    docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docSchema.Name.ToUpper(), docThatSchema.Name.ToUpper()));
                                }
                                else
                                {
                                    // otherwise, deleted
                                    docChangeEntity.Action = DocChangeActionEnum.DELETED;

                                    // if non-abstract, it impacts file
                                    if (!docEntityBase.IsAbstract())
                                    {
                                        docChangeEntity.ImpactSPF = true;
                                        docChangeEntity.ImpactXML = true;
                                    }
                                }
                            }
                        }

                        // property sets
                        foreach (DocPropertySet docPset in docSchema.PropertySets)
                        {
                            DocChangeAction docChangePset = new DocChangeAction();
                            docChangeSchemaProperties.Changes.Add(docChangePset);
                            docChangePset.Name = docPset.Name;

                            // find equivalent pset
                            DocPropertySet docPsetBase = null;
                            foreach (DocPropertySet docEntityEach in docSchemaBase.PropertySets)
                            {
                                if (docEntityEach.Name.Equals(docPset.Name))
                                {
                                    docPsetBase = docEntityEach;
                                    break;
                                }
                            }

                            if (docPsetBase == null)
                            {
                                // new entity
                                docChangePset.Action = DocChangeActionEnum.ADDED;

                                // check if it was moved from another schema                                
                                foreach (DocSection docOtherSection in projectPrev.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocPropertySet docOtherPset in docOtherSchema.PropertySets)
                                        {
                                            if (docOtherPset.Name.Equals(docPset.Name))
                                            {
                                                docPsetBase = docOtherPset; // still compare attributes if moved (e.g. IfcRelSequence)

                                                docChangePset.Action = DocChangeActionEnum.MOVED;
                                                docChangePset.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docOtherSchema.Name.ToUpper(), docSchema.Name.ToUpper()));
                                            }
                                        }
                                    }
                                }

                            }

                            if (docPsetBase != null)
                            {
                                // existing entity

                                // compare abstract vs. non-abstract
                                if (docPset.ApplicableType != docPsetBase.ApplicableType)
                                {
                                    docChangePset.Action = DocChangeActionEnum.MODIFIED;
                                    docChangePset.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, docPsetBase.ApplicableType, docPset.ApplicableType));
                                }

                                // compare attributes by index

                                // only report non-abstract entities; e.g. attributes may be demoted without file impact


                                foreach (DocProperty docAttribute in docPset.Properties)
                                {
                                    // we only care about direct attributes
                                    DocChangeAction docChangeAttribute = new DocChangeAction();
                                    docChangePset.Changes.Add(docChangeAttribute);
                                    docChangeAttribute.Name = docAttribute.Name;

                                    DocProperty docAttributeBase = null;
                                    foreach (DocProperty docEachProperty in docPsetBase.Properties)
                                    {
                                        if (docEachProperty.Name.Equals(docAttribute.Name))
                                        {
                                            docAttributeBase = docEachProperty;
                                            break;
                                        }
                                    }

                                    if (docAttributeBase == null)
                                    {
                                        // new attribute added
                                        docChangeAttribute.Action = DocChangeActionEnum.ADDED;
                                    }
                                    else
                                    {
                                        // compare for changes
                                        if (!docAttribute.PropertyType.Equals(docAttributeBase.PropertyType))
                                        {
                                            DocChangeAspect docAspect = new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, docAttributeBase.PropertyType.ToString(), docAttribute.PropertyType.ToString());
                                            docChangeAttribute.Aspects.Add(docAspect);
                                            docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                        }

                                        if (docAttribute.PrimaryDataType != null && !docAttribute.PrimaryDataType.Trim().Equals(docAttributeBase.PrimaryDataType.Trim()))
                                        {
                                            DocChangeAspect docAspect = new DocChangeAspect(DocChangeAspectEnum.TYPE, docAttributeBase.PrimaryDataType, docAttribute.PrimaryDataType);
                                            docChangeAttribute.Aspects.Add(docAspect);
                                            docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                        }
                                    }
                                }

                                // report deleted properties
                                foreach (DocProperty docAttributeBase in docPsetBase.Properties)
                                {
                                    DocProperty docAttribute = null;
                                    foreach (DocProperty docEachProperty in docPset.Properties)
                                    {
                                        if (docEachProperty.Name.Equals(docAttributeBase.Name))
                                        {
                                            docAttribute = docEachProperty;
                                            break;
                                        }
                                    }

                                    if (docAttribute == null)
                                    {
                                        DocChangeAction docChangeAttribute = new DocChangeAction();
                                        docChangePset.Changes.Add(docChangeAttribute);
                                        docChangeAttribute.Name = docAttributeBase.Name;
                                        docChangeAttribute.Action = DocChangeActionEnum.DELETED;
                                    }
                                }
                            }

                        }

                        // now find deleted psets
                        foreach (DocPropertySet docEntityBase in docSchemaBase.PropertySets)
                        {
                            // find equivalent
                            DocPropertySet docEntity = null;
                            foreach (DocPropertySet docEntityEach in docSchema.PropertySets)
                            {
                                if (docEntityEach.Name.Equals(docEntityBase.Name))
                                {
                                    docEntity = docEntityEach;
                                    break;
                                }
                            }

                            if (docEntity == null)
                            {
                                // entity may have moved to other schema; check other schemas
                                DocSchema docThatSchema = null;
                                foreach (DocSection docOtherSection in projectCurr.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocPropertySet docOtherEntity in docOtherSchema.PropertySets)
                                        {
                                            if (docOtherEntity.Name.Equals(docEntityBase.Name))
                                            {
                                                docEntity = docOtherEntity;
                                                docThatSchema = docOtherSchema;
                                            }
                                        }
                                    }
                                }

                                DocChangeAction docChangeEntity = new DocChangeAction();
                                docChangeSchemaProperties.Changes.Add(docChangeEntity);
                                docChangeEntity.Name = docEntityBase.Name;

                                if (docEntity != null)
                                {
                                    // moved from another schema
                                    docChangeEntity.Action = DocChangeActionEnum.MOVED;
                                    docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docSchema.Name.ToUpper(), docThatSchema.Name.ToUpper()));
                                }
                                else
                                {
                                    // otherwise, deleted
                                    docChangeEntity.Action = DocChangeActionEnum.DELETED;
                                }
                            }
                        }
                        // end property sets


                        // quantity sets
                        foreach (DocQuantitySet docQset in docSchema.QuantitySets)
                        {
                            DocChangeAction docChangeQset = new DocChangeAction();
                            docChangeSchemaQuantities.Changes.Add(docChangeQset);
                            docChangeQset.Name = docQset.Name;

                            // find equivalent pset
                            DocQuantitySet docQsetBase = null;
                            foreach (DocQuantitySet docEntityEach in docSchemaBase.QuantitySets)
                            {
                                if (docEntityEach.Name.Equals(docQset.Name))
                                {
                                    docQsetBase = docEntityEach;
                                    break;
                                }
                            }

                            if (docQsetBase == null)
                            {
                                // new entity
                                docChangeQset.Action = DocChangeActionEnum.ADDED;

                                // check if it was moved from another schema                                
                                foreach (DocSection docOtherSection in projectPrev.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocQuantitySet docOtherQset in docOtherSchema.QuantitySets)
                                        {
                                            if (docOtherQset.Name.Equals(docQset.Name))
                                            {
                                                docQsetBase = docOtherQset; // still compare attributes if moved (e.g. IfcRelSequence)

                                                docChangeQset.Action = DocChangeActionEnum.MOVED;
                                                docChangeQset.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docOtherSchema.Name.ToUpper(), docSchema.Name.ToUpper()));
                                            }
                                        }
                                    }
                                }

                            }

                            if (docQsetBase != null)
                            {
                                // existing entity

                                // compare abstract vs. non-abstract
                                if (docQset.ApplicableType != docQsetBase.ApplicableType)
                                {
                                    docChangeQset.Action = DocChangeActionEnum.MODIFIED;
                                    docChangeQset.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, docQsetBase.ApplicableType, docQset.ApplicableType));
                                }

                                // compare attributes by index

                                // only report non-abstract entities; e.g. attributes may be demoted without file impact


                                foreach (DocQuantity docAttribute in docQset.Quantities)
                                {
                                    // we only care about direct attributes
                                    DocChangeAction docChangeAttribute = new DocChangeAction();
                                    docChangeQset.Changes.Add(docChangeAttribute);
                                    docChangeAttribute.Name = docAttribute.Name;

                                    DocQuantity docAttributeBase = null;
                                    foreach (DocQuantity docEachProperty in docQsetBase.Quantities)
                                    {
                                        if (docEachProperty.Name.Equals(docAttribute.Name))
                                        {
                                            docAttributeBase = docEachProperty;
                                            break;
                                        }
                                    }

                                    if (docAttributeBase == null)
                                    {
                                        // new attribute added
                                        docChangeAttribute.Action = DocChangeActionEnum.ADDED;
                                    }
                                    else
                                    {
                                        // compare for changes
                                        if (!docAttribute.QuantityType.Equals(docAttributeBase.QuantityType))
                                        {
                                            DocChangeAspect docAspect = new DocChangeAspect(DocChangeAspectEnum.INSTANTIATION, docAttributeBase.QuantityType.ToString(), docAttribute.QuantityType.ToString());
                                            docChangeAttribute.Aspects.Add(docAspect);
                                            docChangeAttribute.Action = DocChangeActionEnum.MODIFIED;
                                        }
                                    }
                                }

                                // report deleted quantities
                                foreach (DocQuantity docAttributeBase in docQsetBase.Quantities)
                                {
                                    DocQuantity docAttribute = null;
                                    foreach (DocQuantity docEachQuantity in docQset.Quantities)
                                    {
                                        if (docEachQuantity.Name.Equals(docAttributeBase.Name))
                                        {
                                            docAttribute = docEachQuantity;
                                            break;
                                        }
                                    }

                                    if (docAttribute == null)
                                    {
                                        DocChangeAction docChangeAttribute = new DocChangeAction();
                                        docChangeQset.Changes.Add(docChangeAttribute);
                                        docChangeAttribute.Name = docAttributeBase.Name;
                                        docChangeAttribute.Action = DocChangeActionEnum.DELETED;
                                    }
                                }
                            }

                        }

                        // now find deleted qsets
                        foreach (DocQuantitySet docEntityBase in docSchemaBase.QuantitySets)
                        {
                            // find equivalent
                            DocQuantitySet docEntity = null;
                            foreach (DocQuantitySet docEntityEach in docSchema.QuantitySets)
                            {
                                if (docEntityEach.Name.Equals(docEntityBase.Name))
                                {
                                    docEntity = docEntityEach;
                                    break;
                                }
                            }

                            if (docEntity == null)
                            {
                                // entity may have moved to other schema; check other schemas
                                DocSchema docThatSchema = null;
                                foreach (DocSection docOtherSection in projectCurr.Sections)
                                {
                                    foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                    {
                                        foreach (DocQuantitySet docOtherEntity in docOtherSchema.QuantitySets)
                                        {
                                            if (docOtherEntity.Name.Equals(docEntityBase.Name))
                                            {
                                                docEntity = docOtherEntity;
                                                docThatSchema = docOtherSchema;
                                            }
                                        }
                                    }
                                }

                                DocChangeAction docChangeEntity = new DocChangeAction();
                                docChangeSchemaQuantities.Changes.Add(docChangeEntity);
                                docChangeEntity.Name = docEntityBase.Name;

                                if (docEntity != null)
                                {
                                    // moved from another schema
                                    docChangeEntity.Action = DocChangeActionEnum.MOVED;
                                    docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docSchema.Name.ToUpper(), docThatSchema.Name.ToUpper()));
                                }
                                else
                                {
                                    // otherwise, deleted
                                    docChangeEntity.Action = DocChangeActionEnum.DELETED;
                                }
                            }
                        }
                        // end quantity sets

                    }
                }

                foreach (DocSchema docSchemaBase in docSectionBase.Schemas)
                {
                    // find equivalent schema
                    DocSchema docSchema = null;
                    foreach (DocSchema docSchemaEach in docSection.Schemas)
                    {
                        if (docSchemaEach.Name.Equals(docSchemaBase.Name))
                        {
                            docSchema = docSchemaEach;
                            break;
                        }
                    }

                    if (docSchema == null)
                    {
                        DocChangeAction docChangeSchema = new DocChangeAction();
                        docChangeSchema.Name = docSchemaBase.Name;
                        docChangeSchema.Action = DocChangeActionEnum.DELETED;
                        docChangeSection.Changes.Add(docChangeSchema);

                        // list all deleted types
                        foreach (DocType docTypeBase in docSchemaBase.Types)
                        {
                            DocChangeAction docChangeType = new DocChangeAction();
                            docChangeSchema.Changes.Add(docChangeType);
                            docChangeType.Name = docTypeBase.Name;

                            // each entity either moved or deleted

                            // entity may have moved to other schema; check other schemas
                            DocSchema docThatSchema = null;
                            foreach (DocSection docOtherSection in projectCurr.Sections)
                            {
                                foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                {
                                    foreach (DocType docOtherType in docOtherSchema.Types)
                                    {
                                        if (docOtherType.Name.Equals(docTypeBase.Name))
                                        {
                                            docThatSchema = docOtherSchema;
                                        }
                                    }
                                }
                            }

                            if (docThatSchema != null)
                            {
                                docChangeType.Action = DocChangeActionEnum.MOVED;
                                docChangeType.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docSchemaBase.Name, docThatSchema.Name));
                            }
                            else
                            {
                                docChangeType.Action = DocChangeActionEnum.DELETED;

                                // deleting a type does not impact file
                            }
                        }


                        // list all deleted entities
                        foreach (DocEntity docEntityBase in docSchemaBase.Entities)
                        {
                            DocChangeAction docChangeEntity = new DocChangeAction();
                            docChangeSchema.Changes.Add(docChangeEntity);
                            docChangeEntity.Name = docEntityBase.Name;

                            // each entity either moved or deleted

                            // entity may have moved to other schema; check other schemas
                            DocSchema docThatSchema = null;
                            foreach (DocSection docOtherSection in projectCurr.Sections)
                            {
                                foreach (DocSchema docOtherSchema in docOtherSection.Schemas)
                                {
                                    foreach (DocEntity docOtherEntity in docOtherSchema.Entities)
                                    {
                                        if (docOtherEntity.Name.Equals(docEntityBase.Name))
                                        {
                                            docThatSchema = docOtherSchema;
                                        }
                                    }
                                }
                            }

                            if (docThatSchema != null)
                            {
                                docChangeEntity.Action = DocChangeActionEnum.MOVED;
                                docChangeEntity.Aspects.Add(new DocChangeAspect(DocChangeAspectEnum.SCHEMA, docSchemaBase.Name, docThatSchema.Name));
                            }
                            else
                            {
                                docChangeEntity.Action = DocChangeActionEnum.DELETED;
                                docChangeEntity.ImpactSPF = true;
                                docChangeEntity.ImpactXML = true;
                            }
                        }
                    }
                }

            }


        }