Total Complexity | 90 |
Total Lines | 654 |
Duplicated Lines | 4.59 % |
Changes | 2 | ||
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.rulebased.RuleBasedProcessor 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 | /* |
||
87 | public class RuleBasedProcessor implements Processor { |
||
88 | |||
89 | private class WorkerThreadR extends Thread { |
||
90 | @Override |
||
91 | public void run() { |
||
92 | while (RuleBasedProcessor.this.status.getNumberOfREntries() > 0) { |
||
93 | while (RuleBasedProcessor.this.status.getNumberOfREntries() > 0) { |
||
94 | processREntries(); |
||
95 | } |
||
96 | try { |
||
97 | Thread.sleep(threadWaitingTime); |
||
98 | } catch (InterruptedException e) { |
||
99 | throw new IllegalStateException(e); |
||
100 | } |
||
101 | } |
||
102 | } |
||
103 | } |
||
104 | |||
105 | private class WorkerThreadS extends Thread { |
||
106 | @Override |
||
107 | public void run() { |
||
108 | while (RuleBasedProcessor.this.status.getNumberOfSEntries() > 0) { |
||
109 | while (RuleBasedProcessor.this.status.getNumberOfSEntries() > 0) { |
||
110 | processSEntries(); |
||
111 | } |
||
112 | try { |
||
113 | Thread.sleep(threadWaitingTime); |
||
114 | } catch (InterruptedException e) { |
||
115 | throw new IllegalStateException(e); |
||
116 | } |
||
117 | } |
||
118 | } |
||
119 | } |
||
120 | |||
121 | private static final Logger logger = Logger.getLogger(RuleBasedProcessor.class.getName()); |
||
122 | |||
123 | private static final long loggingFrequency = 0x1000000; |
||
124 | private static final long threadWaitingTime = 0x20; |
||
125 | private static final Integer topClassId = IntegerEntityManager.topClassId; |
||
126 | |||
127 | private RChain chainR = null; |
||
128 | private SChain chainS = null; |
||
129 | private IntegerHierarchicalGraph classHierarchy = null; |
||
130 | private IntegerHierarchicalGraph dataPropertyHierarchy = null; |
||
131 | private Map<Integer, Set<Integer>> directTypes = null; |
||
132 | private final IntegerEntityManager entityManager; |
||
133 | private final NormalizedIntegerAxiomFactory factory; |
||
134 | private boolean isReady = false; |
||
135 | private long iteration = 0; |
||
136 | private long loggingCount = loggingFrequency; |
||
137 | private final boolean multiThreadedMode = false; |
||
138 | private IntegerHierarchicalGraph objectPropertyHierarchy = null; |
||
139 | private Map<Integer, Set<Integer>> sameIndividualMap = null; |
||
140 | private ClassifierStatusImpl status = null; |
||
141 | private WorkerThreadR threadR1 = null; |
||
142 | private WorkerThreadR threadR2 = null; |
||
143 | private WorkerThreadS threadS1 = null; |
||
144 | private WorkerThreadS threadS2 = null; |
||
145 | |||
146 | /** |
||
147 | * Constructs a new rule-based processor. |
||
148 | * |
||
149 | * @param originalObjectProperties |
||
150 | * set of original object properties |
||
151 | * @param originalClasses |
||
152 | * set of original classes |
||
153 | * @param normalizedAxiomSet |
||
154 | * set of normalized axioms |
||
155 | * @param expressivity |
||
156 | * expressivity |
||
157 | * @param factory |
||
158 | * factory of normalized integer axioms |
||
159 | * @param entityManager |
||
160 | * entity manager |
||
161 | */ |
||
162 | public RuleBasedProcessor(Set<Integer> originalObjectProperties, Set<Integer> originalClasses, |
||
163 | Set<NormalizedIntegerAxiom> normalizedAxiomSet, OntologyExpressivity expressivity, |
||
164 | NormalizedIntegerAxiomFactory factory, IntegerEntityManager entityManager) { |
||
165 | Objects.requireNonNull(originalObjectProperties); |
||
166 | Objects.requireNonNull(originalClasses); |
||
167 | Objects.requireNonNull(normalizedAxiomSet); |
||
168 | Objects.requireNonNull(expressivity); |
||
169 | Objects.requireNonNull(factory); |
||
170 | Objects.requireNonNull(entityManager); |
||
171 | this.factory = factory; |
||
172 | this.entityManager = entityManager; |
||
173 | |||
174 | CompletionRuleChainSelector selector = new CompletionRuleChainSelector(expressivity); |
||
175 | selector.activateProfiler(); |
||
176 | this.chainR = selector.getRChain(); |
||
177 | this.chainS = selector.getSChain(); |
||
178 | |||
179 | preProcess(createExtendedOntology(originalObjectProperties, originalClasses, normalizedAxiomSet)); |
||
180 | } |
||
181 | |||
182 | public void addAxioms(Set<NormalizedIntegerAxiom> normalizedAxiomSet) { |
||
183 | Objects.requireNonNull(normalizedAxiomSet); |
||
184 | logger.fine("adding axioms ..."); |
||
185 | this.status.getExtendedOntology().load(normalizedAxiomSet); |
||
186 | preProcess(this.status.getExtendedOntology()); |
||
187 | logger.fine("processor reset."); |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * @param hierarchicalGraph |
||
192 | * graph containing direct subsumers |
||
193 | * @return a map with all the direct types for each individual. |
||
194 | */ |
||
195 | private Map<Integer, Set<Integer>> computeDirectTypes(IntegerHierarchicalGraph hierarchicalGraph) { |
||
196 | Map<Integer, Set<Integer>> ret = new HashMap<>(); |
||
197 | Set<Integer> individuals = getEntityManager().getIndividuals(); |
||
198 | individuals.forEach(indiv -> { |
||
199 | Set<Integer> subsumers = hierarchicalGraph.getParents(getEntityManager().getAuxiliaryNominal(indiv).get()); |
||
200 | subsumers.forEach(elem -> { |
||
201 | if (getEntityManager().getAuxiliaryNominals().contains(elem)) { |
||
202 | throw new IllegalStateException("An individual has another individual as direct subsumer."); |
||
203 | } |
||
204 | }); |
||
205 | ret.put(indiv, Collections.unmodifiableSet(subsumers)); |
||
206 | }); |
||
207 | return ret; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * This is a graph reachability algorithm that returns all elements d |
||
212 | * reachable from an element c using a path where each segment is from any |
||
213 | * of the properties in R. |
||
214 | * |
||
215 | * @param c |
||
216 | * first element in the path |
||
217 | * @return the set of all nodes reachable from c using any possible segment |
||
218 | */ |
||
219 | private Set<Integer> computeReachability(Integer c) { |
||
220 | Set<Integer> ret = new HashSet<>(); |
||
221 | Set<Integer> toVisit = new HashSet<>(); |
||
222 | toVisit.add(c); |
||
223 | while (!toVisit.isEmpty()) { |
||
224 | Integer elem = toVisit.iterator().next(); |
||
225 | toVisit.remove(elem); |
||
226 | ret.add(elem); |
||
227 | Set<Integer> newToVisit = new HashSet<>(); |
||
228 | this.status.getObjectPropertiesByFirst(elem).forEach(r -> { |
||
229 | IntegerBinaryRelation relation = this.status.getRelationSet().get(r); |
||
230 | newToVisit.addAll(relation.getByFirst(elem)); |
||
231 | }); |
||
232 | newToVisit.removeAll(ret); |
||
233 | toVisit.addAll(newToVisit); |
||
234 | } |
||
235 | return ret; |
||
236 | } |
||
237 | |||
238 | private Set<Integer> computeReachability(Integer c, Map<Integer, Set<Integer>> reachableNodeCache) { |
||
239 | Set<Integer> reachableNodes = reachableNodeCache.get(c); |
||
240 | if (Objects.isNull(reachableNodes)) { |
||
241 | reachableNodes = computeReachability(c); |
||
242 | reachableNodeCache.put(c, reachableNodes); |
||
243 | } |
||
244 | return reachableNodes; |
||
245 | } |
||
246 | |||
247 | private Map<Integer, Set<Integer>> computeSameIndividualMap(IntegerHierarchicalGraph hierarchicalGraph) { |
||
248 | Map<Integer, Set<Integer>> ret = new HashMap<>(); |
||
249 | Set<Integer> individuals = getEntityManager().getIndividuals(); |
||
250 | individuals.forEach(indiv -> { |
||
251 | Set<Integer> equivalentClasses = hierarchicalGraph |
||
252 | .getEquivalents(getEntityManager().getAuxiliaryNominal(indiv).get()); |
||
253 | Set<Integer> equivalents = new HashSet<>(); |
||
254 | equivalentClasses.forEach(elem -> { |
||
255 | if (getEntityManager().getAuxiliaryNominals().contains(elem)) { |
||
256 | equivalents.add(getEntityManager().getIndividual(elem).get()); |
||
257 | } |
||
258 | }); |
||
259 | ret.put(indiv, Collections.unmodifiableSet(equivalents)); |
||
260 | }); |
||
261 | return ret; |
||
262 | } |
||
263 | |||
264 | /** |
||
265 | * Convenience method to create a map entry. This method returns a map |
||
266 | * entry. |
||
267 | * |
||
268 | * @param key |
||
269 | * key |
||
270 | * @param value |
||
271 | * value |
||
272 | * @return a map entry created using the paramenters |
||
273 | */ |
||
274 | private Map.Entry<String, String> createEntry(String key, String value) { |
||
275 | return new AbstractMap.SimpleEntry<String, String>(key, value); |
||
276 | } |
||
277 | |||
278 | private ExtendedOntology createExtendedOntology(Set<Integer> originalObjectPropertySet, |
||
279 | Set<Integer> originalClassSet, Set<NormalizedIntegerAxiom> axioms) { |
||
280 | SubPropertyNormalizer subPropNormalizer = new SubPropertyNormalizer(getOntologyObjectFactory(), |
||
281 | getEntityManager()); |
||
282 | Set<NormalizedIntegerAxiom> saturatedNormalizedAxiomSet = subPropNormalizer.apply(axioms); |
||
283 | ExtendedOntology extendedOntology = new ExtendedOntologyImpl(); |
||
284 | extendedOntology.load(saturatedNormalizedAxiomSet); |
||
285 | originalObjectPropertySet.forEach(elem -> extendedOntology.addObjectProperty(elem)); |
||
286 | originalClassSet.forEach(elem -> extendedOntology.addClass(elem)); |
||
287 | return extendedOntology; |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Returns the class graph. |
||
292 | * |
||
293 | * @return the class graph. |
||
294 | */ |
||
295 | protected IntegerSubsumerGraph getClassGraph() { |
||
296 | return this.status.getClassGraph(); |
||
297 | } |
||
298 | |||
299 | @Override |
||
300 | public IntegerHierarchicalGraph getClassHierarchy() { |
||
301 | if (!isReady()) { |
||
302 | throw new UnclassifiedOntologyException(); |
||
303 | } |
||
304 | return this.classHierarchy; |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * Returns information about how the processor configuration. |
||
309 | * |
||
310 | * @return information about how the processor configuration |
||
311 | */ |
||
312 | public List<Map.Entry<String, String>> getConfigurationInfo() { |
||
313 | List<Map.Entry<String, String>> ret = new ArrayList<>(); |
||
314 | ret.add(createEntry("processor", getClass().getSimpleName())); |
||
315 | ret.add(createEntry("iterations per log entry", "" + loggingFrequency)); |
||
316 | ret.add(createEntry("classes read (including TOP and BOTTOM classes)", |
||
317 | "" + getEntityManager().getEntities(IntegerEntityType.CLASS, false).size())); |
||
318 | ret.add(createEntry("object properties read (including TOP and BOTTOM object properties)", |
||
319 | "" + getEntityManager().getEntities(IntegerEntityType.OBJECT_PROPERTY, false).size())); |
||
320 | ret.add(createEntry("auxiliary classes created (including nominals)", |
||
321 | "" + getEntityManager().getEntities(IntegerEntityType.CLASS, true).size())); |
||
322 | ret.add(createEntry("auxiliary classes created for nominals", "" + getEntityManager().getIndividuals().size())); |
||
323 | ret.add(createEntry("auxiliary object properties created", |
||
324 | "" + getEntityManager().getEntities(IntegerEntityType.OBJECT_PROPERTY, true).size())); |
||
325 | ret.add(createEntry("chain S", this.chainS.toString())); |
||
326 | ret.add(createEntry("chain R", this.chainR.toString())); |
||
327 | return ret; |
||
328 | } |
||
329 | |||
330 | @Override |
||
331 | public IntegerHierarchicalGraph getDataPropertyHierarchy() throws UnclassifiedOntologyException { |
||
332 | if (!isReady()) { |
||
333 | throw new UnclassifiedOntologyException(); |
||
334 | } |
||
335 | return this.dataPropertyHierarchy; |
||
336 | } |
||
337 | |||
338 | /** |
||
339 | * Computes the descendants using only a hierarchical graph. |
||
340 | * |
||
341 | * @param hierarchicalGraph |
||
342 | * a hierarchical graph containing parents and children |
||
343 | * @param vertex |
||
344 | * starting vertex to compute the descendants |
||
345 | * @return the descendants according the graph |
||
346 | */ |
||
347 | View Code Duplication | private Set<Integer> getDescendants(IntegerHierarchicalGraph hierarchicalGraph, Integer vertex) { |
|
|
|||
348 | Set<Integer> visited = new HashSet<>(); |
||
349 | Set<Integer> queue = new HashSet<>(); |
||
350 | queue.add(vertex); |
||
351 | while (!queue.isEmpty()) { |
||
352 | Integer elem = queue.iterator().next(); |
||
353 | queue.remove(elem); |
||
354 | visited.add(elem); |
||
355 | Set<Integer> children = new HashSet<>(); |
||
356 | children.addAll(hierarchicalGraph.getChildren(elem)); |
||
357 | children.removeAll(visited); |
||
358 | queue.addAll(children); |
||
359 | } |
||
360 | return visited; |
||
361 | } |
||
362 | |||
363 | @Override |
||
364 | public Map<Integer, Set<Integer>> getDirectTypes() { |
||
365 | if (!isReady()) { |
||
366 | throw new UnclassifiedOntologyException(); |
||
367 | } |
||
368 | return Collections.unmodifiableMap(this.directTypes); |
||
369 | } |
||
370 | |||
371 | protected IntegerEntityManager getEntityManager() { |
||
372 | return this.entityManager; |
||
373 | } |
||
374 | |||
375 | protected IntegerSubsumerGraph getObjectPropertyGraph() { |
||
376 | return this.status.getObjectPropertyGraph(); |
||
377 | } |
||
378 | |||
379 | @Override |
||
380 | public IntegerHierarchicalGraph getObjectPropertyHierarchy() { |
||
381 | if (!isReady()) { |
||
382 | throw new UnclassifiedOntologyException(); |
||
383 | } |
||
384 | return this.objectPropertyHierarchy; |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * Returns the ontology object factory. |
||
389 | * |
||
390 | * @return the ontology object factory. |
||
391 | */ |
||
392 | public NormalizedIntegerAxiomFactory getOntologyObjectFactory() { |
||
393 | return this.factory; |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * Returns the binary relation for a given id, or and empty relation if the |
||
398 | * id is unknown. |
||
399 | * |
||
400 | * @param relationId |
||
401 | * relation id |
||
402 | * @return the binary relation for the given id, or an empty relation if no |
||
403 | * relation is already defined |
||
404 | */ |
||
405 | protected IntegerBinaryRelation getRelation(Integer relationId) { |
||
406 | Objects.requireNonNull(relationId); |
||
407 | return this.status.getRelationSet().get(relationId); |
||
408 | } |
||
409 | |||
410 | /** |
||
411 | * Returns a set containing all relation ids. |
||
412 | * |
||
413 | * @return the set of all relation ids |
||
414 | */ |
||
415 | protected Set<Integer> getRelationIdSet() { |
||
416 | return Collections.unmodifiableSet(this.status.getRelationSet().getElements()); |
||
417 | } |
||
418 | |||
419 | @Override |
||
420 | public Map<Integer, Set<Integer>> getSameIndividualMap() { |
||
421 | if (!isReady()) { |
||
422 | throw new UnclassifiedOntologyException(); |
||
423 | } |
||
424 | return Collections.unmodifiableMap(this.sameIndividualMap); |
||
425 | } |
||
426 | |||
427 | /** |
||
428 | * Returns information about the processor status. |
||
429 | * |
||
430 | * @return information about the processor status. |
||
431 | */ |
||
432 | public List<Map.Entry<String, String>> getStatusInfo() { |
||
433 | List<Map.Entry<String, String>> ret = new ArrayList<>(); |
||
434 | ret.add(createEntry("iteration", "" + this.iteration)); |
||
435 | ret.add(createEntry("Q_S", "" + this.status.getNumberOfSEntries())); |
||
436 | ret.add(createEntry("Q_R", "" + this.status.getNumberOfREntries())); |
||
437 | ret.add(createEntry("S", "" + this.status.getDeepSizeOfS())); |
||
438 | ret.add(createEntry("R", "" + this.status.getDeepSizeOfR())); |
||
439 | ret.add(createEntry("V", "" + this.status.getSizeOfV())); |
||
440 | ret.add(createEntry("subV", "" + this.status.getDeepSizeOfV())); |
||
441 | return ret; |
||
442 | } |
||
443 | |||
444 | @Override |
||
445 | public boolean isReady() { |
||
446 | return this.isReady; |
||
447 | } |
||
448 | |||
449 | /** |
||
450 | * Post processes the data after the classification phase. |
||
451 | */ |
||
452 | protected void postProcess() { |
||
453 | removeAuxiliaryObjectProperties(); |
||
454 | this.objectPropertyHierarchy = new IntegerHierarchicalGraphImpl(getObjectPropertyGraph()); |
||
455 | |||
456 | removeAuxiliaryClassesExceptNominals(); |
||
457 | IntegerHierarchicalGraph hierarchicalGraph = new IntegerHierarchicalGraphImpl(this.status.getClassGraph()); |
||
458 | processNominals(hierarchicalGraph); |
||
459 | this.directTypes = computeDirectTypes(hierarchicalGraph); |
||
460 | this.sameIndividualMap = computeSameIndividualMap(hierarchicalGraph); |
||
461 | |||
462 | removeAuxiliaryNominals(); |
||
463 | this.classHierarchy = new IntegerHierarchicalGraphImpl(this.status.getClassGraph()); |
||
464 | }; |
||
465 | |||
466 | /** |
||
467 | * The configuration follows the following steps: |
||
468 | * <ul> |
||
469 | * <li>creates the property hierarchy</li> |
||
470 | * <li>prepares all the queues to run the algorithm</li> |
||
471 | * </ul> |
||
472 | * |
||
473 | * @param ontology |
||
474 | * ontology |
||
475 | */ |
||
476 | protected void preProcess(ExtendedOntology ontology) { |
||
477 | logger.fine("configuring processor ..."); |
||
478 | |||
479 | this.isReady = false; |
||
480 | this.status = new ClassifierStatusImpl(getEntityManager(), ontology); |
||
481 | this.dataPropertyHierarchy = new IntegerHierarchicalGraphImpl(new IntegerSubsumerGraphImpl( |
||
482 | IntegerEntityManager.bottomDataPropertyId, IntegerEntityManager.topDataPropertyId)); |
||
483 | Set<Integer> classNameSet = new HashSet<>(); |
||
484 | classNameSet.addAll(this.status.getExtendedOntology().getClassSet()); |
||
485 | classNameSet.forEach(className -> { |
||
486 | this.status.addNewSEntry(className, className); |
||
487 | this.status.addNewSEntry(className, topClassId); |
||
488 | }); |
||
489 | |||
490 | logger.fine("processor configured."); |
||
491 | logger.fine(showConfigurationInfo()); |
||
492 | |||
493 | int numberOfCores = Runtime.getRuntime().availableProcessors(); |
||
494 | logger.fine("number of cores : " + numberOfCores); |
||
495 | |||
496 | // uncomment the following two lines to allow multithreaded mode |
||
497 | // int suggestedNumberOfThreads = (numberOfCores / 2) - 1; |
||
498 | // this.multiThreadedMode = suggestedNumberOfThreads >= 4; |
||
499 | |||
500 | if (this.multiThreadedMode) { |
||
501 | logger.fine("running processor on multiple threads."); |
||
502 | } else { |
||
503 | logger.fine("running processor on a single thread."); |
||
504 | } |
||
505 | } |
||
506 | |||
507 | @Override |
||
508 | public boolean process() { |
||
509 | boolean ret = false; |
||
510 | if (this.multiThreadedMode) { |
||
511 | ret = processMultiThreaded(); |
||
512 | } else { |
||
513 | ret = processSingleThreaded(); |
||
514 | } |
||
515 | if (ret) { |
||
516 | if (this.loggingCount < 1) { |
||
517 | this.loggingCount = loggingFrequency; |
||
518 | logger.fine(showStatusInfo()); |
||
519 | } |
||
520 | } |
||
521 | return ret; |
||
522 | }; |
||
523 | |||
524 | private boolean processMultiThreaded() { |
||
525 | if (!this.isReady) { |
||
526 | if (Objects.nonNull(this.threadS1) && Objects.nonNull(this.threadS2) && Objects.nonNull(this.threadR1) |
||
527 | && Objects.nonNull(this.threadR2) && this.threadS1.getState().equals(Thread.State.TERMINATED) |
||
528 | && this.threadS2.getState().equals(Thread.State.TERMINATED) |
||
529 | && this.threadR1.getState().equals(Thread.State.TERMINATED) |
||
530 | && this.threadR2.getState().equals(Thread.State.TERMINATED) |
||
531 | && (this.status.getNumberOfSEntries() == 0) && (this.status.getNumberOfREntries() == 0)) { |
||
532 | |||
533 | logger.fine(showStatusInfo()); |
||
534 | postProcess(); |
||
535 | logger.fine(showConfigurationInfo()); |
||
536 | this.isReady = true; |
||
537 | } else { |
||
538 | |||
539 | if ((Objects.isNull(this.threadS1)) || (Objects.nonNull(this.threadS1) |
||
540 | && this.threadS1.getState().equals(Thread.State.TERMINATED))) { |
||
541 | this.threadS1 = new WorkerThreadS(); |
||
542 | this.threadS1.start(); |
||
543 | logger.finest("starting new thread S-1 ..."); |
||
544 | } |
||
545 | |||
546 | if ((Objects.isNull(this.threadS2)) || (Objects.nonNull(this.threadS2) |
||
547 | && this.threadS2.getState().equals(Thread.State.TERMINATED))) { |
||
548 | this.threadS2 = new WorkerThreadS(); |
||
549 | this.threadS2.start(); |
||
550 | logger.finest("starting new thread S-2 ..."); |
||
551 | } |
||
552 | |||
553 | if ((Objects.isNull(this.threadR1)) || (Objects.nonNull(this.threadR1) |
||
554 | && this.threadR1.getState().equals(Thread.State.TERMINATED))) { |
||
555 | this.threadR1 = new WorkerThreadR(); |
||
556 | this.threadR1.start(); |
||
557 | logger.finest("starting new thread R-1 ..."); |
||
558 | } |
||
559 | |||
560 | if ((Objects.isNull(this.threadR2)) || (Objects.nonNull(this.threadR2) |
||
561 | && this.threadR2.getState().equals(Thread.State.TERMINATED))) { |
||
562 | this.threadR2 = new WorkerThreadR(); |
||
563 | this.threadR2.start(); |
||
564 | logger.finest("starting new thread R-2 ..."); |
||
565 | } |
||
566 | |||
567 | try { |
||
568 | if (this.status.getNumberOfREntries() < this.status.getNumberOfSEntries()) { |
||
569 | if ((this.iteration % 2) == 0) { |
||
570 | this.threadR1.join(); |
||
571 | } else { |
||
572 | this.threadR2.join(); |
||
573 | } |
||
574 | } else { |
||
575 | if ((this.iteration % 2) == 0) { |
||
576 | this.threadS1.join(); |
||
577 | } else { |
||
578 | this.threadS2.join(); |
||
579 | } |
||
580 | } |
||
581 | } catch (InterruptedException e) { |
||
582 | throw new IllegalStateException(e); |
||
583 | } |
||
584 | } |
||
585 | } |
||
586 | return !this.isReady; |
||
587 | } |
||
588 | |||
589 | /** |
||
590 | * Processes the nominals after the execution of the classification |
||
591 | * algorithm. It requires a hierarchical graph to get the descendants. |
||
592 | * |
||
593 | * @param hierarchicalGraph |
||
594 | * the hierarchical graph |
||
595 | */ |
||
596 | View Code Duplication | private void processNominals(IntegerHierarchicalGraph hierarchicalGraph) { |
|
597 | Map<Integer, Set<Integer>> reachabilityCache = new HashMap<>(); |
||
598 | Set<Integer> nominals = getEntityManager().getAuxiliaryNominals(); |
||
599 | nominals.forEach(indiv -> { |
||
600 | Set<Integer> descendants = getDescendants(hierarchicalGraph, indiv); |
||
601 | descendants.forEach(c -> { |
||
602 | descendants.forEach(d -> { |
||
603 | Collection<Integer> sC = getClassGraph().getSubsumers(c); |
||
604 | Collection<Integer> sD = getClassGraph().getSubsumers(d); |
||
605 | if (!(sD.containsAll(sC))) { |
||
606 | if (computeReachability(c, reachabilityCache).contains(d)) { |
||
607 | sD.forEach(elem -> this.status.getClassGraph().addAncestor(c, elem)); |
||
608 | } |
||
609 | nominals.forEach(nominal -> { |
||
610 | if (computeReachability(nominal, reachabilityCache).contains(d)) { |
||
611 | sD.forEach(elem -> this.status.getClassGraph().addAncestor(c, elem)); |
||
612 | } |
||
613 | }); |
||
614 | } |
||
615 | }); |
||
616 | }); |
||
617 | }); |
||
618 | } |
||
619 | |||
620 | private boolean processREntries() { |
||
621 | boolean ret = false; |
||
622 | REntry entry = null; |
||
623 | try { |
||
624 | entry = this.status.removeNextREntry(); |
||
625 | } catch (NoSuchElementException e) { |
||
626 | } |
||
627 | if (Objects.nonNull(entry)) { |
||
628 | ret = true; |
||
629 | int property = entry.getProperty(); |
||
630 | int leftClass = entry.getLeftClass(); |
||
631 | int rightClass = entry.getRightClass(); |
||
632 | boolean applied = this.status.addToR(property, leftClass, rightClass); |
||
633 | if (applied) { |
||
634 | this.chainR.apply(this.status, property, leftClass, rightClass); |
||
635 | this.loggingCount--; |
||
636 | this.iteration++; |
||
637 | } |
||
638 | } |
||
639 | return ret; |
||
640 | } |
||
641 | |||
642 | private boolean processSEntries() { |
||
643 | boolean ret = false; |
||
644 | SEntry entry = null; |
||
645 | try { |
||
646 | entry = this.status.removeNextSEntry(); |
||
647 | } catch (NoSuchElementException e) { |
||
648 | } |
||
649 | if (Objects.nonNull(entry)) { |
||
650 | ret = true; |
||
651 | int subClass = entry.getSubClass(); |
||
652 | int superClass = entry.getSuperClass(); |
||
653 | boolean applied = this.status.addToS(subClass, superClass); |
||
654 | if (applied) { |
||
655 | this.chainS.apply(this.status, subClass, superClass); |
||
656 | this.loggingCount--; |
||
657 | this.iteration++; |
||
658 | } |
||
659 | } |
||
660 | return ret; |
||
661 | } |
||
662 | |||
663 | private boolean processSingleThreaded() { |
||
664 | if (!this.isReady) { |
||
665 | if ((this.status.getNumberOfSEntries() == 0) && (this.status.getNumberOfREntries() == 0)) { |
||
666 | logger.fine(showStatusInfo()); |
||
667 | postProcess(); |
||
668 | logger.fine(showConfigurationInfo()); |
||
669 | this.isReady = true; |
||
670 | } else { |
||
671 | if (this.status.getNumberOfSEntries() > this.status.getNumberOfREntries()) { |
||
672 | processSEntries(); |
||
673 | } else { |
||
674 | processREntries(); |
||
675 | } |
||
676 | } |
||
677 | } |
||
678 | return !this.isReady; |
||
679 | } |
||
680 | |||
681 | private void removeAuxiliaryClassesExceptNominals() { |
||
682 | Set<Integer> reqClasses = new HashSet<>(); |
||
683 | getClassGraph().getElements().forEach(elem -> { |
||
684 | if (!getEntityManager().isAuxiliary(elem)) { |
||
685 | reqClasses.add(elem); |
||
686 | } |
||
687 | }); |
||
688 | reqClasses.addAll(getEntityManager().getAuxiliaryNominals()); |
||
689 | this.status.getClassGraph().retainAll(reqClasses); |
||
690 | } |
||
691 | |||
692 | private void removeAuxiliaryNominals() { |
||
693 | Set<Integer> reqClasses = new HashSet<>(); |
||
694 | reqClasses.addAll(getClassGraph().getElements()); |
||
695 | reqClasses.removeAll(getEntityManager().getAuxiliaryNominals()); |
||
696 | this.status.getClassGraph().retainAll(reqClasses); |
||
697 | } |
||
698 | |||
699 | /** |
||
700 | * This method removes the auxiliary object properties that were not |
||
701 | * generated as inverse of another one. |
||
702 | */ |
||
703 | private void removeAuxiliaryObjectProperties() { |
||
704 | Set<Integer> reqObjectProperties = new HashSet<>(); |
||
705 | getObjectPropertyGraph().getElements().forEach(elem -> { |
||
706 | if (!getEntityManager().isAuxiliary(elem)) { |
||
707 | reqObjectProperties.add(elem); |
||
708 | } |
||
709 | }); |
||
710 | this.status.getObjectPropertyGraph().retainAll(reqObjectProperties); |
||
711 | } |
||
712 | |||
713 | public String showConfigurationInfo() { |
||
714 | StringBuffer sbuf = new StringBuffer(); |
||
715 | getConfigurationInfo().forEach(entry -> { |
||
716 | sbuf.append(entry.getKey()); |
||
717 | sbuf.append(" = "); |
||
718 | sbuf.append(entry.getValue()); |
||
719 | sbuf.append("\n"); |
||
720 | }); |
||
721 | return sbuf.toString(); |
||
722 | } |
||
723 | |||
724 | public String showStatusInfo() { |
||
725 | StringBuffer sbuf = new StringBuffer(); |
||
726 | getStatusInfo().forEach(entry -> { |
||
727 | sbuf.append(entry.getKey()); |
||
728 | sbuf.append("="); |
||
729 | sbuf.append(entry.getValue()); |
||
730 | sbuf.append(" "); |
||
731 | }); |
||
732 | return sbuf.toString(); |
||
733 | } |
||
734 | |||
735 | public void outputSetS(Writer writer) throws IOException { |
||
736 | this.status.outputSetS(writer); |
||
737 | } |
||
738 | |||
739 | public void outputSetR(Writer writer) throws IOException { |
||
740 | this.status.outputSetR(writer); |
||
741 | } |
||
744 |