From 861f584ab694f064f03afc1e0c4f712b5822b4a5 Mon Sep 17 00:00:00 2001 From: Andy Ward Date: Tue, 31 Oct 2023 11:23:33 +0000 Subject: [PATCH] Merged PR 1863: Switched Schema mapping to be dynamically generated e.g. for AirTerminals in IFC2x3 Switched Schema mapping to be dynamically generated e.g. for AirTerminals in IFC2x3 Previously was an incomplete fixed mapping table See bS IDS Issue [116](https://github.com/buildingSMART/IDS/issues/116) --- .../Helpers/SchemaTypeMap.cs | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/Xbim.IDS.Validator.Core/Helpers/SchemaTypeMap.cs b/Xbim.IDS.Validator.Core/Helpers/SchemaTypeMap.cs index 1f08274..ddd7615 100644 --- a/Xbim.IDS.Validator.Core/Helpers/SchemaTypeMap.cs +++ b/Xbim.IDS.Validator.Core/Helpers/SchemaTypeMap.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using Xbim.Common; +using Xbim.Common.Metadata; using Xbim.InformationSpecifications.Helpers; namespace Xbim.IDS.Validator.Core.Helpers @@ -41,51 +43,51 @@ internal class SchemaTypeMap return null; } + + private static Lazy> lazySchemaMap = new Lazy>(() => BuildSchemaInferenceMappings()); + + static IDictionary _ifc2x3Inferences => lazySchemaMap.Value; + // Inferences: New types in later schemas that can be inferred in older schemas using Type information + static IDictionary BuildSchemaInferenceMappings() + { + var baseSchema = ExpressMetaData.GetMetadata(typeof(Ifc2x3.EntityFactoryIfc2x3).Module); + var targetSchema = ExpressMetaData.GetMetadata(typeof(Ifc4.EntityFactoryIfc4).Module); + + var implicitlyMapped = GetMappings(baseSchema, targetSchema); + + var dict = new Dictionary(); + + foreach( var mapping in implicitlyMapped ) + { + var inference = new SchemaInference(SchemaInfo.SchemaIfc2x3[mapping.NewType.SuperType.ExpressName], SchemaInfo.SchemaIfc2x3[mapping.DefinedBy.ExpressName]); + dict.Add(mapping.NewType.ExpressNameUpper, inference); + } + return dict; - static IDictionary _ifc2x3Inferences = new Dictionary() + } + + + + private static IEnumerable<(ExpressType NewType, ExpressType DefinedBy)> GetMappings(ExpressMetaData baseSchema, ExpressMetaData targetSchema) { - //Terminals - ["IFCAIRTERMINAL"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcAirTerminalType"]), - // AV - IFC4 - // Comms Appliance - IFC4 - ["IFCELECTRICAPPLIANCE"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcElectricApplianceType"]), - ["IFCFIRESUPPRESSIONTERMINAL"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcFireSuppressionTerminalType"]), - ["IFCLAMP"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcLampType"]), - ["IFCLIGHTFIXTURE"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcLightFixtureType"]), - // Medical - ["IFCOUTLET"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcOutletType"]), - ["IFCSANITARYTERMINAL"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcSanitaryTerminalType"]), - ["IFCSPACEHEATER"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcSpaceHeaterType"]), - ["IFCWASTETERMINAL"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowTerminal"], SchemaInfo.SchemaIfc2x3["IfcWasteTerminalType"]), - - // Segments - ["IFCPIPESEGMENT"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowSegment"], SchemaInfo.SchemaIfc2x3["IfcPipeSegmentType"]), - ["IFCDUCTSEGMENT"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowSegment"], SchemaInfo.SchemaIfc2x3["IfcDuctSegmentType"]), - ["IFCCABLECARRIERSEGMENT"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowSegment"], SchemaInfo.SchemaIfc2x3["IfcCableCarrierSegmentType"]), - ["IFCCABLESEGMENT"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowSegment"], SchemaInfo.SchemaIfc2x3["IfcCableSegmentType"]), - - // Energy Conversion - ["IFCBOILER"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcEnergyConversionDevice"], SchemaInfo.SchemaIfc2x3["IfcBoilerType"]), - ["IFCCHILLER"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcEnergyConversionDevice"], SchemaInfo.SchemaIfc2x3["IfcChillerType"]), - ["IFCCOOLEDBEAM"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcEnergyConversionDevice"], SchemaInfo.SchemaIfc2x3["IfcCooledBeamType"]), - ["IFCTRANSFORMER"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcEnergyConversionDevice"], SchemaInfo.SchemaIfc2x3["IfcTransformerType"]), - ["IFCUNITARYEQUIPMENT"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcEnergyConversionDevice"], SchemaInfo.SchemaIfc2x3["IfcUnitaryEquipmentType"]), - // Storage - ["IFCTANK"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowStorageDevice"], SchemaInfo.SchemaIfc2x3["IfcTankType"]), - - // Flow Controllers - ["IFCAIRTERMINALBOX"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcAirTerminalBoxType"]), - ["IFCDAMPER"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcDamperType"]), - // Missing ElectricDistributionBoard is 4x only - ["IFCELECTRICTIMECONTROL"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcElectricTimeControlType"]), - ["IFCFLOWMETER"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcFlowMeterType"]), - ["IFCPROTECTIVEDEVICE"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcProtectiveDeviceType"]), - ["IFCSWITCHINGDEVICE"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcSwitchingDeviceType"]), - ["IFCVALVE"] = new SchemaInference(SchemaInfo.SchemaIfc2x3["IfcFlowController"], SchemaInfo.SchemaIfc2x3["IfcValveType"]), - // + var products = targetSchema.ExpressType("IFCPRODUCT"); - }; + foreach (var type in products.AllSubTypes) + { + if (baseSchema.ExpressType(type.ExpressNameUpper) == null) + { + // New in the targer schema. Check if a Type exists by convention we can use + var baseSchemaType = baseSchema.ExpressType(type.ExpressNameUpper + "TYPE"); + if (baseSchemaType != null) + { + // New but with Type we can use to discriminate in base schema + yield return (type, baseSchemaType); + } + + } + } + } // Substitutions: where a type is deprecated / removed and there's a forwarding type we can use