diff --git a/Documentation/ImplementersDocumentation/TestCases/attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ids b/Documentation/ImplementersDocumentation/TestCases/attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ids
new file mode 100644
index 00000000..3b6e2425
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ids
@@ -0,0 +1,43 @@
+
+
+
+ Bedrooms need a minimum floor area of 10m2 2/2
+ Generated via code automation in the Ids Repository on github.
+
+
+
+
+
+
+ IFCSPACE
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+
+
+
+ Qto_SpaceBaseQuantities
+
+
+ NetFloorArea
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Documentation/ImplementersDocumentation/TestCases/attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ifc b/Documentation/ImplementersDocumentation/TestCases/attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ifc
new file mode 100644
index 00000000..5eff0efd
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ifc
@@ -0,0 +1,16 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
+FILE_NAME('','2024-01-01T00:00:00',(),(),'','','');
+FILE_SCHEMA(('IFC4'));
+ENDSEC;
+DATA;
+#1=IFCPROJECT('0nAJhbwG5A0uNieL5ozGvv',$,$,$,$,$,$,$,#2);
+#2=IFCUNITASSIGNMENT((#3));
+#3=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
+#4=IFCSPACE('0eA6m4fELI9QBIhP3wiLAp',$,$,'BEDROOM 2',$,$,$,$,$,$,$);
+#5=IFCELEMENTQUANTITY('16MocU_IDOF8_x3Iqllz0d',$,'Qto_SpaceBaseQuantities',$,$,(#6));
+#6=IFCQUANTITYAREA('NetFloorArea',$,$,8.,$);
+#7=IFCRELDEFINESBYPROPERTIES('1xdwj8qGXK4hzoNbvMdXJW',$,$,$,(#4),#5);
+ENDSEC;
+END-ISO-10303-21;
diff --git a/Documentation/ImplementersDocumentation/TestCases/attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ids b/Documentation/ImplementersDocumentation/TestCases/attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ids
new file mode 100644
index 00000000..2298c291
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ids
@@ -0,0 +1,43 @@
+
+
+
+ Bedrooms need a minimum floor area of 10m2 1/2
+ Generated via code automation in the Ids Repository on github.
+
+
+
+
+
+
+ IFCSPACE
+
+
+
+
+ Description
+
+
+
+
+
+
+
+
+
+
+
+ Qto_SpaceBaseQuantities
+
+
+ NetFloorArea
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Documentation/ImplementersDocumentation/TestCases/attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ifc b/Documentation/ImplementersDocumentation/TestCases/attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ifc
new file mode 100644
index 00000000..094fe0b5
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ifc
@@ -0,0 +1,16 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
+FILE_NAME('','2024-01-01T00:00:00',(),(),'','','');
+FILE_SCHEMA(('IFC4'));
+ENDSEC;
+DATA;
+#1=IFCPROJECT('0nAJhbwG5A0uNieL5ozGvv',$,$,$,$,$,$,$,#2);
+#2=IFCUNITASSIGNMENT((#3));
+#3=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
+#4=IFCSPACE('0eA6m4fELI9QBIhP3wiLAp',$,$,'BEDROOM 1',$,$,$,$,$,$,$);
+#5=IFCELEMENTQUANTITY('16MocU_IDOF8_x3Iqllz0d',$,'Qto_SpaceBaseQuantities',$,$,(#6));
+#6=IFCQUANTITYAREA('NetFloorArea',$,$,12.,$);
+#7=IFCRELDEFINESBYPROPERTIES('1xdwj8qGXK4hzoNbvMdXJW',$,$,$,(#4),#5);
+ENDSEC;
+END-ISO-10303-21;
diff --git a/Documentation/ImplementersDocumentation/TestCases/classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ids b/Documentation/ImplementersDocumentation/TestCases/classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ids
new file mode 100644
index 00000000..535a3a8a
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ids
@@ -0,0 +1,35 @@
+
+
+
+ A classification facet can be used for applicability 2/2
+ Generated via code automation in the Ids Repository on github.
+
+
+
+
+
+
+ IFCWALL
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+
+
+ Waldo
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Documentation/ImplementersDocumentation/TestCases/classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ifc b/Documentation/ImplementersDocumentation/TestCases/classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ifc
new file mode 100644
index 00000000..56d789cd
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ifc
@@ -0,0 +1,13 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
+FILE_NAME('','2024-01-01T00:00:00',(),(),'','','');
+FILE_SCHEMA(('IFC4'));
+ENDSEC;
+DATA;
+#1=IFCWALL('1hqIFTRjfV6AWq_bMtnZwI',$,'Foobar',$,$,$,$,$,$);
+#2=IFCCLASSIFICATION($,$,$,'Foobar',$,$,$);
+#3=IFCCLASSIFICATIONREFERENCE($,'1',$,#2,$,$);
+#4=IFCRELASSOCIATESCLASSIFICATION('05rScmOVzMoQXOfbYdtLYj',$,$,$,(#1),#3);
+ENDSEC;
+END-ISO-10303-21;
diff --git a/Documentation/ImplementersDocumentation/TestCases/classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ids b/Documentation/ImplementersDocumentation/TestCases/classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ids
new file mode 100644
index 00000000..dc42cb3d
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ids
@@ -0,0 +1,35 @@
+
+
+
+ A classification facet can be used for applicability 1/2
+ Generated via code automation in the Ids Repository on github.
+
+
+
+
+
+
+ IFCWALL
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+
+
+ Waldo
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Documentation/ImplementersDocumentation/TestCases/classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ifc b/Documentation/ImplementersDocumentation/TestCases/classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ifc
new file mode 100644
index 00000000..fe2c67f8
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ifc
@@ -0,0 +1,13 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
+FILE_NAME('','2024-01-01T00:00:00',(),(),'','','');
+FILE_SCHEMA(('IFC4'));
+ENDSEC;
+DATA;
+#1=IFCWALL('1hqIFTRjfV6AWq_bMtnZwI',$,'Waldo',$,$,$,$,$,$);
+#2=IFCCLASSIFICATION($,$,$,'Foobar',$,$,$);
+#3=IFCCLASSIFICATIONREFERENCE($,'1',$,#2,$,$);
+#4=IFCRELASSOCIATESCLASSIFICATION('05rScmOVzMoQXOfbYdtLYj',$,$,$,(#1),#3);
+ENDSEC;
+END-ISO-10303-21;
diff --git a/Documentation/ImplementersDocumentation/TestCases/property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ids b/Documentation/ImplementersDocumentation/TestCases/property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ids
new file mode 100644
index 00000000..c644e4f6
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ids
@@ -0,0 +1,39 @@
+
+
+
+ External load bearing walls need a fire rating property 2/2
+ Generated via code automation in the Ids Repository on github.
+
+
+
+
+
+
+ IFCWALL
+
+
+
+
+ Pset_WallCommon
+
+
+ LoadBearing
+
+
+ true
+
+
+
+
+
+
+ Pset_WallCommon
+
+
+ FireRating
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Documentation/ImplementersDocumentation/TestCases/property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ifc b/Documentation/ImplementersDocumentation/TestCases/property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ifc
new file mode 100644
index 00000000..890fbae6
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ifc
@@ -0,0 +1,16 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
+FILE_NAME('','2024-01-01T00:00:00',(),(),'','','');
+FILE_SCHEMA(('IFC4'));
+ENDSEC;
+DATA;
+#1=IFCPROJECT('0nAJhbwG5A0uNieL5ozGvv',$,$,$,$,$,$,$,#2);
+#2=IFCUNITASSIGNMENT((#3));
+#3=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
+#4=IFCWALL('1hqIFTRjfV6AWq_bMtnZwI',$,$,$,$,$,$,$,$);
+#5=IFCPROPERTYSET('16MocU_IDOF8_x3Iqllz0d',$,'Pset_WallCommon',$,(#7));
+#6=IFCRELDEFINESBYPROPERTIES('1xdwj8qGXK4hzoNbvMdXJW',$,$,$,(#4),#5);
+#7=IFCPROPERTYSINGLEVALUE('LoadBearing',$,IFCBOOLEAN(.T.),$);
+ENDSEC;
+END-ISO-10303-21;
diff --git a/Documentation/ImplementersDocumentation/TestCases/property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ids b/Documentation/ImplementersDocumentation/TestCases/property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ids
new file mode 100644
index 00000000..7395a09c
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ids
@@ -0,0 +1,39 @@
+
+
+
+ External load bearing walls need a fire rating property 1/2
+ Generated via code automation in the Ids Repository on github.
+
+
+
+
+
+
+ IFCWALL
+
+
+
+
+ Pset_WallCommon
+
+
+ LoadBearing
+
+
+ true
+
+
+
+
+
+
+ Pset_WallCommon
+
+
+ FireRating
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Documentation/ImplementersDocumentation/TestCases/property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ifc b/Documentation/ImplementersDocumentation/TestCases/property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ifc
new file mode 100644
index 00000000..81ab773e
--- /dev/null
+++ b/Documentation/ImplementersDocumentation/TestCases/property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ifc
@@ -0,0 +1,17 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
+FILE_NAME('','2024-01-01T00:00:00',(),(),'','','');
+FILE_SCHEMA(('IFC4'));
+ENDSEC;
+DATA;
+#1=IFCPROJECT('0nAJhbwG5A0uNieL5ozGvv',$,$,$,$,$,$,$,#2);
+#2=IFCUNITASSIGNMENT((#3));
+#3=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
+#4=IFCWALL('1hqIFTRjfV6AWq_bMtnZwI',$,$,$,$,$,$,$,$);
+#5=IFCPROPERTYSET('16MocU_IDOF8_x3Iqllz0d',$,'Pset_WallCommon',$,(#7,#8));
+#6=IFCRELDEFINESBYPROPERTIES('1xdwj8qGXK4hzoNbvMdXJW',$,$,$,(#4),#5);
+#7=IFCPROPERTYSINGLEVALUE('LoadBearing',$,IFCBOOLEAN(.T.),$);
+#8=IFCPROPERTYSINGLEVALUE('FireRating',$,IFCLABEL('1HR'),$);
+ENDSEC;
+END-ISO-10303-21;
diff --git a/Documentation/ImplementersDocumentation/TestCases/scripts.md b/Documentation/ImplementersDocumentation/TestCases/scripts.md
index 0a0dd2e8..0c024028 100644
--- a/Documentation/ImplementersDocumentation/TestCases/scripts.md
+++ b/Documentation/ImplementersDocumentation/TestCases/scripts.md
@@ -214,6 +214,28 @@ Requirements:
Attribute: ''Name''
```
+### Bedrooms need a minimum floor area of 10m2 1/2
+
+Hand authored to close the applicability coverage gap identified in buildingSMART/IDS#181. Mirrors the "Bedrooms should have a minimum area of 10m2" worked example in specifications.md, which uses an Attribute facet in the applicability to select bedrooms by their Description.
+
+``` ids attribute/pass-bedrooms_need_a_minimum_floor_area_of_10m2_1_2.ids
+Bedrooms need a minimum floor area of 10m2 1/2
+Entity: ''IFCSPACE''
+Attribute: ''Description'',Pattern(''.*BEDROOM.*'')
+Requirements:
+Property: ''Qto_SpaceBaseQuantities'',''NetFloorArea'',IFCAREAMEASURE,xs:double MinInclusive(''10'')
+```
+
+### Bedrooms need a minimum floor area of 10m2 2/2
+
+``` ids attribute/fail-bedrooms_need_a_minimum_floor_area_of_10m2_2_2.ids
+Bedrooms need a minimum floor area of 10m2 2/2
+Entity: ''IFCSPACE''
+Attribute: ''Description'',Pattern(''.*BEDROOM.*'')
+Requirements:
+Property: ''Qto_SpaceBaseQuantities'',''NetFloorArea'',IFCAREAMEASURE,xs:double MinInclusive(''10'')
+```
+
### Booleans must be specified as lowercase strings 1/3
``` ids attribute/fail-booleans_must_be_specified_as_lowercase_strings_1_3.ids
@@ -549,6 +571,28 @@ Attribute: ''Name'',Enumeration(''Foo'',''Bar'')
## classification
+### A classification facet can be used for applicability 1/2
+
+Hand authored to close the applicability coverage gap identified in buildingSMART/IDS#181. Every applicability block in the shipped test suite uses only the Entity facet; berlotti confirmed on #181 that "as you see in the XSD there is symmetry in applicability and requirements", so a classification facet should also be usable there. Only classified walls become applicable, so an unclassified wall with the wrong name is never checked, while a classified wall with the wrong name fails.
+
+``` ids classification/pass-a_classification_facet_can_be_used_for_applicability_1_2.ids
+A classification facet can be used for applicability 1/2
+Entity: ''IFCWALL''
+Classification: Pattern(''\w+'')
+Requirements:
+Attribute: ''Name'',''Waldo''
+```
+
+### A classification facet can be used for applicability 2/2
+
+``` ids classification/fail-a_classification_facet_can_be_used_for_applicability_2_2.ids
+A classification facet can be used for applicability 2/2
+Entity: ''IFCWALL''
+Classification: Pattern(''\w+'')
+Requirements:
+Attribute: ''Name'',''Waldo''
+```
+
### A classification facet with no data matches any classification 1/2
``` ids classification/fail-a_classification_facet_with_no_data_matches_any_classification_1_2.ids
@@ -2144,6 +2188,28 @@ Requirements:
Property: ''Foo_Bar'',''Foo'',IFCLABEL
```
+### External load bearing walls need a fire rating property 1/2
+
+Hand authored to close the applicability coverage gap identified in buildingSMART/IDS#181, and to add conformance coverage for the "External load bearing walls need to have a fire rating property for code compliance" worked example in specifications.md, which combines an Entity facet and a Property facet in the applicability with AND (intersection) semantics.
+
+``` ids property/pass-external_load_bearing_walls_need_a_fire_rating_property_1_2.ids
+External load bearing walls need a fire rating property 1/2
+Entity: ''IFCWALL''
+Property: ''Pset_WallCommon'',''LoadBearing'',IFCBOOLEAN,''true''
+Requirements:
+Property: ''Pset_WallCommon'',''FireRating'',IFCLABEL
+```
+
+### External load bearing walls need a fire rating property 2/2
+
+``` ids property/fail-external_load_bearing_walls_need_a_fire_rating_property_2_2.ids
+External load bearing walls need a fire rating property 2/2
+Entity: ''IFCWALL''
+Property: ''Pset_WallCommon'',''LoadBearing'',IFCBOOLEAN,''true''
+Requirements:
+Property: ''Pset_WallCommon'',''FireRating'',IFCLABEL
+```
+
### IDS does not handle string truncation such as for identifiers
``` ids property/fail-ids_does_not_handle_string_truncation_such_as_for_identifiers.ids
diff --git a/RepositoryAutomation/SchemaProject/DocAutomation/IdsScript.cs b/RepositoryAutomation/SchemaProject/DocAutomation/IdsScript.cs
index 0cde24ee..a514e0f8 100644
--- a/RepositoryAutomation/SchemaProject/DocAutomation/IdsScript.cs
+++ b/RepositoryAutomation/SchemaProject/DocAutomation/IdsScript.cs
@@ -183,6 +183,21 @@ private void PopulateApplicability(string app, SpecificationType spec)
case EntityPrefix:
spec.Applicability.Entity = MakeEntity(parts);
break;
+ case AttributePrefix:
+ spec.Applicability.Attribute.Add(MakeAttribute(parts));
+ break;
+ case ClassificationPrefix:
+ spec.Applicability.Classification.Add(MakeClassification(parts));
+ break;
+ case MaterialPrefix:
+ spec.Applicability.Material.Add(MakeMaterial(parts));
+ break;
+ case PartOfPrefix:
+ spec.Applicability.PartOf.Add(MakePartOf(parts));
+ break;
+ case PropertyPrefix:
+ spec.Applicability.Property.Add(MakeProperty(parts));
+ break;
default:
break;
}
@@ -359,6 +374,112 @@ private RequirementsTypeAttribute MakeReqAttribute(IList