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