Total Complexity | 76 |
Total Lines | 636 |
Duplicated Lines | 4.56 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like de.tudresden.inf.lat.jcel.core.algorithm.cel.CelProcessor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | /* |
||
98 | public class CelProcessor implements Processor { |
||
99 | |||
100 | private static final Integer bottomClassId = IntegerEntityManager.bottomClassId; |
||
101 | private static final Integer bottomObjectPropertyId = IntegerEntityManager.bottomObjectPropertyId; |
||
102 | private static final Logger logger = Logger.getLogger(CelProcessor.class.getName()); |
||
103 | private static final Integer topClassId = IntegerEntityManager.topClassId; |
||
104 | private static final Integer topObjectPropertyId = IntegerEntityManager.topObjectPropertyId; |
||
105 | |||
106 | private final NormalizedIntegerAxiomFactory axiomFactory; |
||
107 | private IntegerSubsumerGraphImpl classGraph = null; |
||
108 | private IntegerHierarchicalGraph classHierarchy = null; |
||
109 | private IntegerHierarchicalGraph dataPropertyHierarchy = null; |
||
110 | private Map<Integer, Set<Integer>> directTypes = null; |
||
111 | private final IntegerEntityManager entityManager; |
||
112 | private CelExtendedOntology extendedOntology = null; |
||
113 | private boolean isReady = false; |
||
114 | private IntegerSubsumerGraphImpl objectPropertyGraph = null; |
||
115 | private IntegerHierarchicalGraph objectPropertyHierarchy = null; |
||
116 | private Map<Integer, Set<Integer>> propertyUsedByClass = null; |
||
117 | private final Deque<ExtensionEntry> queueEntries = new ArrayDeque<ExtensionEntry>(); |
||
118 | private final Deque<Integer> queueKeys = new ArrayDeque<Integer>(); |
||
119 | private IntegerRelationMapImpl relationSet = null; |
||
120 | private Map<Integer, Set<Integer>> sameIndividualMap = null; |
||
121 | private Map<Integer, Set<Integer>> transitiveSubsumed = null; |
||
122 | |||
123 | /** |
||
124 | * Constructs a new CEL processor. |
||
125 | * |
||
126 | * @param originalObjectProperties |
||
127 | * set of object properties |
||
128 | * @param originalClasses |
||
129 | * set of classes |
||
130 | * @param normalizedAxiomSet |
||
131 | * set of axioms |
||
132 | * @param factory |
||
133 | * factory |
||
134 | * @param entityManager |
||
135 | * entity manager |
||
136 | */ |
||
137 | public CelProcessor(Set<Integer> originalObjectProperties, Set<Integer> originalClasses, |
||
138 | Set<NormalizedIntegerAxiom> normalizedAxiomSet, NormalizedIntegerAxiomFactory factory, |
||
139 | IntegerEntityManager entityManager) { |
||
140 | Objects.requireNonNull(originalObjectProperties); |
||
141 | Objects.requireNonNull(originalClasses); |
||
142 | Objects.requireNonNull(normalizedAxiomSet); |
||
143 | Objects.requireNonNull(factory); |
||
144 | Objects.requireNonNull(entityManager); |
||
145 | this.axiomFactory = factory; |
||
146 | this.entityManager = entityManager; |
||
147 | preProcess(originalObjectProperties, originalClasses, normalizedAxiomSet); |
||
148 | } |
||
149 | |||
150 | private void addToQueue(Integer className, Collection<ExtensionEntry> entrySet) { |
||
151 | entrySet.forEach(entry -> { |
||
152 | this.queueKeys.push(className); |
||
153 | this.queueEntries.push(entry); |
||
154 | }); |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * @param hierarchicalGraph |
||
159 | * graph containing direct subsumers |
||
160 | * @return a map with all the direct types for each individual. |
||
161 | */ |
||
162 | private Map<Integer, Set<Integer>> computeDirectTypes(IntegerHierarchicalGraph hierarchicalGraph) { |
||
163 | Map<Integer, Set<Integer>> ret = new HashMap<>(); |
||
164 | Set<Integer> individuals = getEntityManager().getEntities(IntegerEntityType.INDIVIDUAL, false); |
||
165 | individuals.forEach(indiv -> { |
||
166 | Set<Integer> subsumers = hierarchicalGraph.getParents(getEntityManager().getAuxiliaryNominal(indiv).get()); |
||
167 | subsumers.forEach(elem -> { |
||
168 | if (getEntityManager().getAuxiliaryNominals().contains(elem)) { |
||
169 | throw new IllegalStateException("An individual has another individual as direct subsumer."); |
||
170 | } |
||
171 | }); |
||
172 | ret.put(indiv, Collections.unmodifiableSet(subsumers)); |
||
173 | }); |
||
174 | return ret; |
||
175 | } |
||
176 | |||
177 | private Map<Integer, Set<Integer>> computeSameIndividualMap(IntegerHierarchicalGraph hierarchicalGraph) { |
||
178 | Map<Integer, Set<Integer>> ret = new HashMap<>(); |
||
179 | Set<Integer> individuals = getEntityManager().getEntities(IntegerEntityType.INDIVIDUAL, false); |
||
180 | individuals.forEach(indiv -> { |
||
181 | Set<Integer> equivalentClasses = hierarchicalGraph |
||
182 | .getEquivalents(getEntityManager().getAuxiliaryNominal(indiv).get()); |
||
183 | Set<Integer> equivalents = new HashSet<>(); |
||
184 | equivalentClasses.forEach(elem -> { |
||
185 | if (getEntityManager().getAuxiliaryNominals().contains(elem)) { |
||
186 | equivalents.add(getEntityManager().getIndividual(elem).get()); |
||
187 | } |
||
188 | }); |
||
189 | ret.put(indiv, Collections.unmodifiableSet(equivalents)); |
||
190 | }); |
||
191 | return ret; |
||
192 | } |
||
193 | |||
194 | private IntegerSubsumerGraphImpl createClassGraph(Set<Integer> originalClassSet, |
||
195 | Set<NormalizedIntegerAxiom> axiomSet) { |
||
196 | |||
197 | Set<Integer> classIdSet = new HashSet<>(); |
||
198 | classIdSet.addAll(originalClassSet); |
||
199 | axiomSet.forEach(axiom -> classIdSet.addAll(axiom.getClassesInSignature())); |
||
200 | IntegerSubsumerGraphImpl ret = new IntegerSubsumerGraphImpl(bottomClassId, topClassId); |
||
201 | classIdSet.forEach(index -> ret.addAncestor(index, topClassId)); |
||
202 | ret.addAncestor(topClassId, topClassId); |
||
203 | return ret; |
||
204 | } |
||
205 | |||
206 | private IntegerSubsumerGraphImpl createObjectPropertyGraph(Set<Integer> originalPropertySet, |
||
207 | Set<NormalizedIntegerAxiom> axiomSet) { |
||
208 | IntegerSubsumerGraphImpl ret = new IntegerSubsumerGraphImpl(bottomObjectPropertyId, topObjectPropertyId); |
||
209 | Set<Integer> propertyIdSet = new HashSet<>(); |
||
210 | propertyIdSet.addAll(originalPropertySet); |
||
211 | axiomSet.forEach(axiom -> propertyIdSet.addAll(axiom.getObjectPropertiesInSignature())); |
||
212 | propertyIdSet.forEach(index -> ret.addAncestor(index, topObjectPropertyId)); |
||
213 | axiomSet.forEach(axiom -> { |
||
214 | if (axiom instanceof RI2Axiom) { |
||
215 | RI2Axiom current = (RI2Axiom) axiom; |
||
216 | ret.addAncestor(current.getSubProperty(), current.getSuperProperty()); |
||
217 | } |
||
218 | }); |
||
219 | makeTransitiveClosure(ret); |
||
220 | return ret; |
||
221 | } |
||
222 | |||
223 | private Map<Integer, Set<Integer>> createPropertyUseMap() { |
||
224 | Map<Integer, Set<Integer>> ret = new HashMap<>(); |
||
225 | getClassGraph().getElements().forEach(cA -> { |
||
226 | Set<Integer> propertySet = new HashSet<>(); |
||
227 | getObjectPropertyGraph().getElements().forEach(r -> { |
||
228 | if (!(this.relationSet.getBySecond(r, cA).isEmpty())) { |
||
229 | propertySet.add(r); |
||
230 | } |
||
231 | }); |
||
232 | ret.put(cA, propertySet); |
||
233 | }); |
||
234 | return ret; |
||
235 | } |
||
236 | |||
237 | private IntegerRelationMapImpl createRelationSet(Collection<Integer> collection) { |
||
238 | IntegerRelationMapImpl ret = new IntegerRelationMapImpl(); |
||
239 | collection.forEach(index -> ret.add(index)); |
||
240 | return ret; |
||
241 | } |
||
242 | |||
243 | private Map<Integer, Set<Integer>> createTransitiveSubsumed() { |
||
244 | Map<Integer, Set<Integer>> ret = new HashMap<>(); |
||
245 | getObjectPropertyGraph().getElements().forEach(r -> { |
||
246 | Set<Integer> related = new HashSet<>(); |
||
247 | getObjectPropertyGraph().getElements().forEach(s -> { |
||
248 | if (isReflexiveTransitiveSubsumed(r, s)) { |
||
249 | related.add(s); |
||
250 | } |
||
251 | }); |
||
252 | ret.put(r, related); |
||
253 | }); |
||
254 | return ret; |
||
255 | } |
||
256 | |||
257 | /** |
||
258 | * Returns the class graph. |
||
259 | * |
||
260 | * @return the class graph. |
||
261 | */ |
||
262 | protected IntegerSubsumerGraph getClassGraph() { |
||
263 | return this.classGraph; |
||
264 | } |
||
265 | |||
266 | @Override |
||
267 | public IntegerHierarchicalGraph getClassHierarchy() { |
||
268 | if (!isReady()) { |
||
269 | throw new UnclassifiedOntologyException(); |
||
270 | } |
||
271 | return this.classHierarchy; |
||
272 | } |
||
273 | |||
274 | @Override |
||
275 | public IntegerHierarchicalGraph getDataPropertyHierarchy() throws UnclassifiedOntologyException { |
||
276 | if (!isReady()) { |
||
277 | throw new UnclassifiedOntologyException(); |
||
278 | } |
||
279 | return this.dataPropertyHierarchy; |
||
280 | } |
||
281 | |||
282 | /** |
||
283 | * Computes the descendants using only a hierarchical graph. |
||
284 | * |
||
285 | * @param hierarchicalGraph |
||
286 | * a hierarchical graph containing parents and children |
||
287 | * @param vertex |
||
288 | * starting vertex to compute the descendants |
||
289 | * @return the descendants according the graph |
||
290 | */ |
||
291 | View Code Duplication | private Set<Integer> getDescendants(IntegerHierarchicalGraph hierarchicalGraph, Integer vertex) { |
|
|
|||
292 | Set<Integer> visited = new HashSet<>(); |
||
293 | Set<Integer> queue = new HashSet<>(); |
||
294 | queue.add(vertex); |
||
295 | while (!queue.isEmpty()) { |
||
296 | Integer elem = queue.iterator().next(); |
||
297 | queue.remove(elem); |
||
298 | visited.add(elem); |
||
299 | Set<Integer> children = new HashSet<>(); |
||
300 | children.addAll(hierarchicalGraph.getChildren(elem)); |
||
301 | children.removeAll(visited); |
||
302 | queue.addAll(children); |
||
303 | } |
||
304 | return visited; |
||
305 | } |
||
306 | |||
307 | @Override |
||
308 | public Map<Integer, Set<Integer>> getDirectTypes() { |
||
309 | if (!isReady()) { |
||
310 | throw new UnclassifiedOntologyException(); |
||
311 | } |
||
312 | return Collections.unmodifiableMap(this.directTypes); |
||
313 | } |
||
314 | |||
315 | /** |
||
316 | * Returns the id generator. |
||
317 | * |
||
318 | * @return the id generator. |
||
319 | */ |
||
320 | protected IntegerEntityManager getEntityManager() { |
||
321 | return this.entityManager; |
||
322 | } |
||
323 | |||
324 | protected CelExtendedOntology getExtendedOntology() { |
||
325 | return this.extendedOntology; |
||
326 | } |
||
327 | |||
328 | protected IntegerSubsumerGraph getObjectPropertyGraph() { |
||
329 | return this.objectPropertyGraph; |
||
330 | } |
||
331 | |||
332 | @Override |
||
333 | public IntegerHierarchicalGraph getObjectPropertyHierarchy() { |
||
334 | if (!isReady()) { |
||
335 | throw new UnclassifiedOntologyException(); |
||
336 | } |
||
337 | return this.objectPropertyHierarchy; |
||
338 | } |
||
339 | |||
340 | public NormalizedIntegerAxiomFactory getOntologyObjectFactory() { |
||
341 | return this.axiomFactory; |
||
342 | } |
||
343 | |||
344 | private Set<Integer> getPropertyUsedByClass(Integer cA) { |
||
345 | return this.propertyUsedByClass.get(cA); |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * Returns the binary relation for a given id, or and empty relation if the |
||
350 | * id is unknown. |
||
351 | * |
||
352 | * @param relationId |
||
353 | * relation id |
||
354 | * @return the binary relation for the given id, or an empty relation if no |
||
355 | * relation is already defined |
||
356 | */ |
||
357 | protected IntegerBinaryRelation getRelation(Integer relationId) { |
||
358 | Objects.requireNonNull(relationId); |
||
359 | return this.relationSet.get(relationId); |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Returns a set containing all relation ids. |
||
364 | * |
||
365 | * @return the set of all relation ids |
||
366 | */ |
||
367 | protected Set<Integer> getRelationIdSet() { |
||
368 | return Collections.unmodifiableSet(this.relationSet.getElements()); |
||
369 | } |
||
370 | |||
371 | @Override |
||
372 | public Map<Integer, Set<Integer>> getSameIndividualMap() { |
||
373 | if (!isReady()) { |
||
374 | throw new UnclassifiedOntologyException(); |
||
375 | } |
||
376 | return Collections.unmodifiableMap(this.sameIndividualMap); |
||
377 | } |
||
378 | |||
379 | /** |
||
380 | * This is a graph reachability algorithm that tests whether an element d is |
||
381 | * reachable from an element c using a path where each segment is from any |
||
382 | * of the properties in R. |
||
383 | * |
||
384 | * @param c |
||
385 | * first element in the path |
||
386 | * @param d |
||
387 | * last element in the path |
||
388 | * @return <code>true</code> if it is possible to reach d from c using any |
||
389 | * possible segment, <code>false</code> otherwise |
||
390 | */ |
||
391 | private boolean isConnectedTo(Integer c, Integer d) { |
||
392 | Set<Integer> visited = new HashSet<>(); |
||
393 | Set<Integer> toVisit = new HashSet<>(); |
||
394 | toVisit.add(c); |
||
395 | while (!toVisit.isEmpty()) { |
||
396 | Integer elem = toVisit.iterator().next(); |
||
397 | toVisit.remove(elem); |
||
398 | visited.add(elem); |
||
399 | Set<Integer> newToVisit = new HashSet<>(); |
||
400 | getPropertyUsedByClass(elem).forEach(r -> { |
||
401 | IntegerBinaryRelation relation = this.relationSet.get(r); |
||
402 | newToVisit.addAll(relation.getByFirst(elem)); |
||
403 | }); |
||
404 | newToVisit.removeAll(visited); |
||
405 | toVisit.addAll(newToVisit); |
||
406 | } |
||
407 | return visited.contains(d); |
||
408 | } |
||
409 | |||
410 | @Override |
||
411 | public boolean isReady() { |
||
412 | return this.isReady; |
||
413 | } |
||
414 | |||
415 | private boolean isReflexiveTransitiveSubsumed(Integer leftPropertyName, Integer rightPropertyName) { |
||
416 | return Objects.nonNull(this.objectPropertyGraph) |
||
417 | && this.objectPropertyGraph.containsPair(leftPropertyName, rightPropertyName); |
||
418 | } |
||
419 | |||
420 | private void makeTransitiveClosure(IntegerSubsumerGraphImpl graph) { |
||
421 | boolean hasChanged = true; |
||
422 | while (hasChanged) { |
||
423 | hasChanged = false; |
||
424 | for (Integer elem : graph.getElements()) { |
||
425 | Collection<Integer> subsumerSet = graph.getSubsumers(elem); |
||
426 | Set<Integer> allSubsumers = new HashSet<>(); |
||
427 | allSubsumers.add(elem); |
||
428 | for (Integer otherElem : subsumerSet) { |
||
429 | allSubsumers.addAll(graph.getSubsumers(otherElem)); |
||
430 | } |
||
431 | allSubsumers.removeAll(subsumerSet); |
||
432 | if (!allSubsumers.isEmpty()) { |
||
433 | hasChanged = true; |
||
434 | for (Integer subsumer : allSubsumers) { |
||
435 | graph.addAncestor(elem, subsumer); |
||
436 | } |
||
437 | } |
||
438 | } |
||
439 | } |
||
440 | } |
||
441 | |||
442 | /** |
||
443 | * Post processes the data after the classification phase. |
||
444 | */ |
||
445 | protected void postProcess() { |
||
446 | removeAuxiliaryObjectProperties(); |
||
447 | this.objectPropertyHierarchy = new IntegerHierarchicalGraphImpl(this.objectPropertyGraph); |
||
448 | this.objectPropertyGraph = null; |
||
449 | |||
450 | removeAuxiliaryClassesExceptNominals(); |
||
451 | IntegerHierarchicalGraph hierarchicalGraph = new IntegerHierarchicalGraphImpl(this.classGraph); |
||
452 | processNominals(hierarchicalGraph); |
||
453 | this.directTypes = computeDirectTypes(hierarchicalGraph); |
||
454 | this.sameIndividualMap = computeSameIndividualMap(hierarchicalGraph); |
||
455 | |||
456 | removeAuxiliaryNominals(); |
||
457 | this.classHierarchy = new IntegerHierarchicalGraphImpl(this.classGraph); |
||
458 | this.classGraph = null; |
||
459 | } |
||
460 | |||
461 | private void prepareQueue(CelExtendedOntology ontology) { |
||
462 | Set<Integer> classNameSet = new HashSet<>(); |
||
463 | classNameSet.addAll(ontology.getClassSet()); |
||
464 | classNameSet.forEach(className -> { |
||
465 | addToQueue(className, ontology.getClassEntries(className)); |
||
466 | addToQueue(className, ontology.getClassEntries(topClassId)); |
||
467 | }); |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * The configuration follows the following steps: |
||
472 | * <ul> |
||
473 | * <li>normalizes the ontology creating auxiliary entities</li> |
||
474 | * <li>creates an extended ontonlogy based on the normalized ontology</li> |
||
475 | * <li>adds the classes</li> |
||
476 | * <li>creates the property hierarchy</li> |
||
477 | * <li>prepares all the queues to run the algorithm</li> |
||
478 | * </ul> |
||
479 | * |
||
480 | * @param originalObjectProperties |
||
481 | * set of object properties |
||
482 | * @param originalClasses |
||
483 | * set of classes |
||
484 | * @param normalizedAxiomSet |
||
485 | * set of axioms, i.e. the ontology |
||
486 | * |
||
487 | */ |
||
488 | protected void preProcess(Set<Integer> originalObjectProperties, Set<Integer> originalClasses, |
||
489 | Set<NormalizedIntegerAxiom> normalizedAxiomSet) { |
||
490 | Objects.requireNonNull(originalObjectProperties); |
||
491 | Objects.requireNonNull(originalClasses); |
||
492 | Objects.requireNonNull(normalizedAxiomSet); |
||
493 | this.isReady = false; |
||
494 | |||
495 | logger.fine("using " + getClass().getSimpleName() + " ..."); |
||
496 | |||
497 | logger.fine("configuring processor ..."); |
||
498 | |||
499 | this.dataPropertyHierarchy = new IntegerHierarchicalGraphImpl(new IntegerSubsumerGraphImpl( |
||
500 | IntegerEntityManager.bottomDataPropertyId, IntegerEntityManager.topDataPropertyId)); |
||
501 | |||
502 | // These sets include the declared entities that are not present in the |
||
503 | // normalized axioms. |
||
504 | Set<Integer> originalClassSet = new HashSet<>(); |
||
505 | originalClassSet.addAll(originalClasses); |
||
506 | originalClassSet.add(bottomClassId); |
||
507 | originalClassSet.add(topClassId); |
||
508 | |||
509 | Set<Integer> originalObjectPropertySet = new HashSet<>(); |
||
510 | originalObjectPropertySet.addAll(originalObjectProperties); |
||
511 | originalObjectPropertySet.add(bottomObjectPropertyId); |
||
512 | originalObjectPropertySet.add(topObjectPropertyId); |
||
513 | |||
514 | logger.finer("normalizing ontology ..."); |
||
515 | Set<NormalizedIntegerAxiom> ontology = new HashSet<>(); |
||
516 | ontology.addAll(normalizedAxiomSet); |
||
517 | |||
518 | logger.finer("auxiliary classes created (including nominals) : " |
||
519 | + getEntityManager().getEntities(IntegerEntityType.CLASS, true).size()); |
||
520 | logger.finer("auxiliary classes created for nominals : " + (getEntityManager().getIndividuals().size())); |
||
521 | logger.finer("auxiliary object properties created : " |
||
522 | + getEntityManager().getEntities(IntegerEntityType.OBJECT_PROPERTY, true).size()); |
||
523 | |||
524 | logger.finer("creating extended ontology ..."); |
||
525 | this.extendedOntology = new CelExtendedOntology(); |
||
526 | this.extendedOntology.load(ontology); |
||
527 | |||
528 | logger.finer("creating class graph ..."); |
||
529 | this.classGraph = createClassGraph(originalClassSet, ontology); |
||
530 | |||
531 | logger.finer("creating property graph ..."); |
||
532 | this.objectPropertyGraph = createObjectPropertyGraph(originalObjectPropertySet, ontology); |
||
533 | |||
534 | this.relationSet = createRelationSet(this.objectPropertyGraph.getElements()); |
||
535 | |||
536 | this.propertyUsedByClass = createPropertyUseMap(); |
||
537 | |||
538 | this.transitiveSubsumed = createTransitiveSubsumed(); |
||
539 | |||
540 | logger.finer("preparing queue ..."); |
||
541 | this.queueKeys.clear(); |
||
542 | this.queueEntries.clear(); |
||
543 | prepareQueue(this.extendedOntology); |
||
544 | |||
545 | logger.fine("processor configured."); |
||
546 | } |
||
547 | |||
548 | @Override |
||
549 | public boolean process() { |
||
550 | if (!this.isReady) { |
||
551 | if (!this.queueKeys.isEmpty()) { |
||
552 | process(this.queueKeys.pop(), this.queueEntries.pop()); |
||
553 | } else if (!this.isReady) { |
||
554 | postProcess(); |
||
555 | this.isReady = true; |
||
556 | } |
||
557 | } |
||
558 | return !this.isReady; |
||
559 | } |
||
560 | |||
561 | private void process(Integer cA, ExtensionEntry eX) { |
||
562 | if (eX.isImplication()) { |
||
563 | processImplication(cA, eX.asImplication().get()); |
||
564 | } else if (eX.isExistential()) { |
||
565 | processExistential(cA, eX.asExistential().get()); |
||
566 | } else { |
||
567 | throw new RuntimeException("Internal error: entry was not recognized " + eX); |
||
568 | } |
||
569 | } |
||
570 | |||
571 | private void processBottom(Integer className) { |
||
572 | this.classGraph.addAncestor(className, bottomClassId); |
||
573 | |||
574 | this.relationSet.getElements().forEach(relation -> { |
||
575 | this.relationSet.getBySecond(relation, className).forEach(firstComponent -> { |
||
576 | if (!this.classGraph.containsPair(firstComponent, bottomClassId)) { |
||
577 | processBottom(firstComponent); |
||
578 | } |
||
579 | }); |
||
580 | }); |
||
581 | } |
||
582 | |||
583 | private void processExistential(Integer cA, ExistentialEntry eX) { |
||
584 | Integer r = eX.getPropertyId(); |
||
585 | Integer cB = eX.getClassId(); |
||
586 | Integer bottom = bottomClassId; |
||
587 | |||
588 | if (!this.relationSet.contains(r, cA, cB)) { |
||
589 | |||
590 | if (this.classGraph.containsPair(cB, bottom) && !this.classGraph.containsPair(cA, bottom)) { |
||
591 | |||
592 | processBottom(cA); |
||
593 | |||
594 | } |
||
595 | |||
596 | processNewEdge(cA, r, cB); |
||
597 | } |
||
598 | } |
||
599 | |||
600 | private void processImplication(Integer cA, ImplicationEntry eX) { |
||
601 | Set<Integer> vecB = eX.getOperands(); |
||
602 | Integer cB = eX.getSuperClass(); |
||
603 | Collection<Integer> sSofA = this.classGraph.getSubsumers(cA); |
||
604 | Integer bottom = bottomClassId; |
||
605 | |||
606 | if (sSofA.containsAll(vecB) && !sSofA.contains(cB)) { |
||
607 | |||
608 | if (cB.equals(bottom)) { |
||
609 | |||
610 | processBottom(cA); |
||
611 | |||
612 | } else { |
||
613 | |||
614 | this.classGraph.addAncestor(cA, cB); |
||
615 | |||
616 | addToQueue(cA, getExtendedOntology().getClassEntries(cB)); |
||
617 | |||
618 | Set<Integer> propertySet = getPropertyUsedByClass(cA); |
||
619 | |||
620 | propertySet.forEach(r -> { |
||
621 | |||
622 | Set<ExtensionEntry> existentialEntries = getExtendedOntology().getExistentialEntries(r, cB); |
||
623 | |||
624 | Collection<Integer> classSet = this.relationSet.getBySecond(r, cA); |
||
625 | |||
626 | classSet.forEach(cAprime -> addToQueue(cAprime, existentialEntries)); |
||
627 | |||
628 | }); |
||
629 | } |
||
630 | } |
||
631 | } |
||
632 | |||
633 | private void processNewEdge(Integer cA, Integer r, Integer cB) { |
||
634 | this.transitiveSubsumed.get(r).forEach(s -> { |
||
635 | |||
636 | this.relationSet.add(s, cA, cB); |
||
637 | getPropertyUsedByClass(cB).add(s); |
||
638 | |||
639 | this.classGraph.getSubsumers(cB) |
||
640 | .forEach(cBprime -> addToQueue(cA, getExtendedOntology().getExistentialEntries(s, cBprime))); |
||
641 | |||
642 | getExtendedOntology().getSubPropertyAxiomSetByRight(s).forEach(axiom -> { |
||
643 | |||
644 | Integer t = axiom.getLeftSubProperty(); |
||
645 | Integer u = axiom.getSuperProperty(); |
||
646 | |||
647 | Collection<Integer> classSet = this.relationSet.getBySecond(t, cA); |
||
648 | |||
649 | classSet.forEach(cAprime -> { |
||
650 | |||
651 | if (!this.relationSet.contains(u, cAprime, cB)) { |
||
652 | processNewEdge(cAprime, u, cB); |
||
653 | } |
||
654 | |||
655 | }); |
||
656 | |||
657 | }); |
||
658 | |||
659 | getExtendedOntology().getSubPropertyAxiomSetByLeft(s).forEach(axiom -> { |
||
660 | |||
661 | Integer t = axiom.getRightSubProperty(); |
||
662 | Integer u = axiom.getSuperProperty(); |
||
663 | |||
664 | Collection<Integer> classSet = this.relationSet.getByFirst(t, cB); |
||
665 | |||
666 | classSet.forEach(cBprime -> { |
||
667 | |||
668 | if (!this.relationSet.contains(u, cA, cBprime)) { |
||
669 | processNewEdge(cA, u, cBprime); |
||
670 | } |
||
671 | |||
672 | }); |
||
673 | |||
674 | }); |
||
675 | }); |
||
676 | } |
||
677 | |||
678 | /** |
||
679 | * Processes the nominals after the execution of the classification |
||
680 | * algorithm. It requires a hierarchical graph to get the descendants. |
||
681 | * |
||
682 | * @param hierarchicalGraph |
||
683 | * the hierarchical graph |
||
684 | */ |
||
685 | View Code Duplication | private void processNominals(IntegerHierarchicalGraph hierarchicalGraph) { |
|
686 | Set<Integer> nominals = getEntityManager().getAuxiliaryNominals(); |
||
687 | nominals.forEach(indiv -> { |
||
688 | Set<Integer> descendants = getDescendants(hierarchicalGraph, indiv); |
||
689 | descendants.forEach(c -> { |
||
690 | descendants.forEach(d -> { |
||
691 | Collection<Integer> sC = getClassGraph().getSubsumers(c); |
||
692 | Collection<Integer> sD = getClassGraph().getSubsumers(d); |
||
693 | if (!(sD.containsAll(sC))) { |
||
694 | if (isConnectedTo(c, d)) { |
||
695 | sD.forEach(elem -> this.classGraph.addAncestor(c, elem)); |
||
696 | } |
||
697 | nominals.forEach(nominal -> { |
||
698 | if (isConnectedTo(nominal, d)) { |
||
699 | sD.forEach(elem -> this.classGraph.addAncestor(c, elem)); |
||
700 | } |
||
701 | }); |
||
702 | } |
||
703 | }); |
||
704 | }); |
||
705 | }); |
||
706 | } |
||
707 | |||
708 | private void removeAuxiliaryClassesExceptNominals() { |
||
709 | Set<Integer> reqClasses = new HashSet<>(); |
||
710 | getClassGraph().getElements().forEach(elem -> { |
||
711 | if (!getEntityManager().isAuxiliary(elem)) { |
||
712 | reqClasses.add(elem); |
||
713 | } |
||
714 | }); |
||
715 | reqClasses.addAll(getEntityManager().getAuxiliaryNominals()); |
||
716 | this.classGraph.retainAll(reqClasses); |
||
717 | } |
||
718 | |||
719 | private void removeAuxiliaryNominals() { |
||
720 | Set<Integer> reqClasses = new HashSet<>(); |
||
721 | reqClasses.addAll(getClassGraph().getElements()); |
||
722 | reqClasses.removeAll(getEntityManager().getAuxiliaryNominals()); |
||
723 | this.classGraph.retainAll(reqClasses); |
||
724 | } |
||
725 | |||
726 | private void removeAuxiliaryObjectProperties() { |
||
727 | Set<Integer> reqObjectProperties = new HashSet<>(); |
||
728 | getObjectPropertyGraph().getElements().forEach(elem -> { |
||
729 | if (!getEntityManager().isAuxiliary(elem)) { |
||
730 | reqObjectProperties.add(elem); |
||
731 | } |
||
732 | }); |
||
733 | this.objectPropertyGraph.retainAll(reqObjectProperties); |
||
734 | } |
||
737 |