| 181 | |
| 182 | |
| 183 | class Specification: |
| 184 | def __init__( |
| 185 | self, |
| 186 | name="Unnamed", |
| 187 | minOccurs=0, |
| 188 | maxOccurs="unbounded", |
| 189 | ifcVersion=["IFC2X3", "IFC4", "IFC4X3_ADD2"], |
| 190 | identifier=None, |
| 191 | description=None, |
| 192 | instructions=None, |
| 193 | ): |
| 194 | self.name = name or "Unnamed" |
| 195 | self.applicability: list[Facet] = [] |
| 196 | self.requirements: list[Facet] = [] |
| 197 | self.minOccurs: Union[int, str] = minOccurs |
| 198 | self.maxOccurs: Union[int, str] = maxOccurs |
| 199 | self.ifcVersion = ifcVersion |
| 200 | self.identifier = identifier |
| 201 | self.description = description |
| 202 | self.instructions = instructions |
| 203 | |
| 204 | self.applicable_entities: list[ifcopenshell.entity_instance] = [] |
| 205 | self.passed_entities: set[ifcopenshell.entity_instance] = set() |
| 206 | self.failed_entities: set[ifcopenshell.entity_instance] = set() |
| 207 | self.status = None |
| 208 | self.is_ifc_version = None |
| 209 | |
| 210 | def asdict(self) -> dict[str, Any]: |
| 211 | results: dict[str, Any] = { |
| 212 | "@name": self.name, |
| 213 | "@ifcVersion": self.ifcVersion, |
| 214 | "applicability": {}, |
| 215 | "requirements": {}, |
| 216 | } |
| 217 | for attribute in ["identifier", "description", "instructions"]: |
| 218 | value = getattr(self, attribute) |
| 219 | if value is not None: |
| 220 | results[f"@{attribute}"] = value |
| 221 | for clause_type in ["applicability", "requirements"]: |
| 222 | clause = getattr(self, clause_type) |
| 223 | if not clause: |
| 224 | continue |
| 225 | facets = {} |
| 226 | for facet in clause: |
| 227 | facet_type = type(facet).__name__ |
| 228 | facet_type = facet_type[0].lower() + facet_type[1:] |
| 229 | facets.setdefault(facet_type, []).append(facet.asdict(clause_type)) |
| 230 | # Canonicalise ordering as per XSD requirements |
| 231 | for facet_type in ("entity", "partOf", "classification", "attribute", "property", "material"): |
| 232 | if facet_type in facets: |
| 233 | results[clause_type][facet_type] = facets[facet_type] |
| 234 | if clause_type == "applicability": |
| 235 | for attribute in ["minOccurs", "maxOccurs"]: |
| 236 | value = getattr(self, attribute) |
| 237 | if value is not None: |
| 238 | results[clause_type][f"@{attribute}"] = value |
| 239 | return results |
| 240 | |