| 2172 | } |
| 2173 | |
| 2174 | void IfcFile::process_deletion_(IfcUtil::IfcBaseClass* entity) { |
| 2175 | |
| 2176 | aggregate_of_instance::ptr references = instances_by_reference(entity->id()); |
| 2177 | |
| 2178 | // Alter entity instances with INVERSE relations to the entity being |
| 2179 | // deleted. This is necessary to maintain a valid IFC file, because |
| 2180 | // dangling references to it's entities name should be removed. At this |
| 2181 | // moment, inversely related instances affected by the removal of the |
| 2182 | // entity being deleted are not deleted themselves. |
| 2183 | if (references) { |
| 2184 | for (aggregate_of_instance::it iit = references->begin(); iit != references->end(); ++iit) { |
| 2185 | IfcUtil::IfcBaseEntity* related_instance = (IfcUtil::IfcBaseEntity*)*iit; |
| 2186 | |
| 2187 | if (std::find(batch_deletion_ids_.begin(), batch_deletion_ids_.end(), related_instance->id()) != batch_deletion_ids_.end()) { |
| 2188 | continue; |
| 2189 | } |
| 2190 | |
| 2191 | const auto& decl = related_instance->declaration(); |
| 2192 | for (size_t i = 0; i < (decl.as_entity() ? decl.as_entity()->attribute_count() : 1); ++i) { |
| 2193 | auto attr = related_instance->get_attribute_value(i); |
| 2194 | if (attr.isNull()) { |
| 2195 | continue; |
| 2196 | } |
| 2197 | |
| 2198 | IfcUtil::ArgumentType attr_type = attr.type(); |
| 2199 | switch (attr_type) { |
| 2200 | case IfcUtil::Argument_ENTITY_INSTANCE: { |
| 2201 | IfcUtil::IfcBaseClass* instance_attribute = attr; |
| 2202 | if (instance_attribute == entity) { |
| 2203 | related_instance->set_attribute_value(i, Blank{}); |
| 2204 | } |
| 2205 | } break; |
| 2206 | case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: { |
| 2207 | aggregate_of_instance::ptr instance_list = attr; |
| 2208 | if (instance_list->contains(entity)) { |
| 2209 | instance_list->remove(entity); |
| 2210 | if ((instance_list->size() == 0U) && related_instance->declaration().as_entity()->attribute_by_index(i)->optional()) { |
| 2211 | // @todo we can also check the lower bound of the attribute type before setting to null. |
| 2212 | related_instance->set_attribute_value(i, Blank{}); |
| 2213 | } else { |
| 2214 | related_instance->set_attribute_value(i, instance_list); |
| 2215 | } |
| 2216 | } |
| 2217 | } break; |
| 2218 | case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: { |
| 2219 | aggregate_of_aggregate_of_instance::ptr instance_list_list = attr; |
| 2220 | if (instance_list_list->contains(entity)) { |
| 2221 | aggregate_of_aggregate_of_instance::ptr new_list(new aggregate_of_aggregate_of_instance); |
| 2222 | for (aggregate_of_aggregate_of_instance::outer_it it = instance_list_list->begin(); it != instance_list_list->end(); ++it) { |
| 2223 | std::vector<IfcUtil::IfcBaseClass*> instances = *it; |
| 2224 | std::vector<IfcUtil::IfcBaseClass*>::iterator jt; |
| 2225 | while ((jt = std::find(instances.begin(), instances.end(), entity)) != instances.end()) { |
| 2226 | instances.erase(jt); |
| 2227 | } |
| 2228 | new_list->push(instances); |
| 2229 | } |
| 2230 | related_instance->set_attribute_value(i, new_list); |
| 2231 | } |
nothing calls this directly
no test coverage detected