| 260 | } // namespace |
| 261 | |
| 262 | void POSTFIX_SCHEMA(JsonSerializer)::finalize() { |
| 263 | json output; |
| 264 | |
| 265 | IfcSchema::IfcProject::list::ptr projects = file->instances_by_type<IfcSchema::IfcProject>(); |
| 266 | if (projects->size() != 1) { |
| 267 | Logger::Message(Logger::LOG_ERROR, "Expected a single IfcProject"); |
| 268 | return; |
| 269 | } |
| 270 | IfcSchema::IfcProject* project = *projects->begin(); |
| 271 | |
| 272 | auto catch_exceptions = [this](const auto& fn) { |
| 273 | try { |
| 274 | return fn(); |
| 275 | } catch (const std::exception& e) { |
| 276 | Logger::Error(e); |
| 277 | static std::invoke_result_t<decltype(fn)> v; |
| 278 | return v; |
| 279 | } |
| 280 | }; |
| 281 | |
| 282 | output["id"] = catch_exceptions([&]() { return file->header().file_name()->name(); }); |
| 283 | output["projectId"] = catch_exceptions([&]() { return project->GlobalId(); }); |
| 284 | output["author"] = catch_exceptions([&]() { return file->header().file_name()->author().empty() ? "unknown" : file->header().file_name()->author().front(); }); |
| 285 | output["createdAt"] = catch_exceptions([&]() { return file->header().file_name()->time_stamp(); }); |
| 286 | output["schema"] = catch_exceptions([&]() { return file->header().file_schema()->schema_identifiers().front(); }); // without schema we would not be here |
| 287 | output["creatingApplication"] = catch_exceptions([&]() { return file->header().file_name()->originating_system(); }); |
| 288 | output["properties"] = json::array(); |
| 289 | output["propertySets"] = json::array(); |
| 290 | output["units"] = json::array(); |
| 291 | output["projectUnits"] = json::object(); |
| 292 | output["metaObjects"] = json::array(); |
| 293 | output["groups"] = json::array(); |
| 294 | |
| 295 | // Maps for deduplication of properties and quantities |
| 296 | std::map<const IfcUtil::IfcBaseEntity*, size_t> property_to_index; |
| 297 | std::unordered_map<json, std::size_t> json_to_index; |
| 298 | |
| 299 | // Obtain sequence of units because properties, quantities reference them by index. |
| 300 | // IfcUnit is a select of IfcDerivedUnit, IfcMonetaryUnit and IfcNamedUnit. |
| 301 | // Unfortunately, instances_by_type() does not support select types directly (even though there isn't a real reason for that). |
| 302 | IfcSchema::IfcUnit::list::ptr units(new IfcSchema::IfcUnit::list); |
| 303 | units->push(file->instances_by_type<IfcSchema::IfcDerivedUnit>()->as<IfcSchema::IfcUnit>()); |
| 304 | units->push(file->instances_by_type<IfcSchema::IfcMonetaryUnit>()->as<IfcSchema::IfcUnit>()); |
| 305 | units->push(file->instances_by_type<IfcSchema::IfcNamedUnit>()->as<IfcSchema::IfcUnit>()); |
| 306 | |
| 307 | auto format_property = [&](const IfcUtil::IfcBaseEntity* prop_) { |
| 308 | json jprop; |
| 309 | /* |
| 310 | { |
| 311 | "name": "LoadBearing", |
| 312 | "ifcPropertyType": "IfcPropertySingleValue", |
| 313 | "ifcValueType": "IfcBoolean", |
| 314 | "value": "True", |
| 315 | "valueType": "boolean" |
| 316 | }, |
| 317 | */ |
| 318 | if (auto* prop = prop_->as<IfcSchema::IfcProperty>()) { |
| 319 | jprop["name"] = prop->Name(); |
nothing calls this directly
no test coverage detected