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