Completed
Branch master (2d821a)
by Julian
49:45
created

de.tudresden.inf.lat.jcel.core.algorithm.rulebased.RuleBasedProcessor   F

Complexity

Total Complexity 90

Size/Duplication

Total Lines 654
Duplicated Lines 4.59 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 30
loc 654
rs 2
eloc 387
wmc 90

40 Methods

Rating   Name   Duplication   Size   Complexity  
A outputSetR(Writer) 0 2 1
A WorkerThreadS.run() 0 10 4
A processSEntries() 0 19 4
A processREntries() 0 20 4
A showStatusInfo() 0 9 1
A createEntry(String,String) 0 2 1
A computeReachability(Integer) 0 17 2
A RuleBasedProcessor(Set,Set,Set,OntologyExpressivity,NormalizedIntegerAxiomFactory,IntegerEntityManager) 0 18 1
A getConfigurationInfo() 0 16 1
A createExtendedOntology(Set,Set,Set) 0 10 1
A getRelation(Integer) 0 3 1
A getStatusInfo() 0 10 1
A getEntityManager() 0 2 1
A WorkerThreadR.run() 0 10 4
A processNominals(IntegerHierarchicalGraph) 16 16 4
A preProcess(ExtendedOntology) 0 28 2
A getOntologyObjectFactory() 0 2 1
A processSingleThreaded() 0 16 5
A removeAuxiliaryNominals() 0 5 1
A process() 0 15 4
A getDescendants(IntegerHierarchicalGraph,Integer) 14 14 2
A computeSameIndividualMap(IntegerHierarchicalGraph) 0 15 2
A addAxioms(Set) 0 6 1
A getRelationIdSet() 0 2 1
A computeDirectTypes(IntegerHierarchicalGraph) 0 13 2
A outputSetS(Writer) 0 2 1
A getObjectPropertyGraph() 0 2 1
A postProcess() 0 12 1
A computeReachability(Integer,Map) 0 7 2
F processMultiThreaded() 0 63 24
A removeAuxiliaryObjectProperties() 0 8 2
A removeAuxiliaryClassesExceptNominals() 0 9 2
A getClassGraph() 0 2 1
A getObjectPropertyHierarchy() 0 6 2
A getClassHierarchy() 0 6 2
A isReady() 0 3 1
A getSameIndividualMap() 0 6 2
A getDataPropertyHierarchy() 0 6 2
A showConfigurationInfo() 0 9 1
A getDirectTypes() 0 6 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

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:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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
/*
2
 *
3
 * Copyright (C) 2009-2017 Julian Mendez
4
 *
5
 *
6
 * This file is part of jcel.
7
 *
8
 *
9
 * The contents of this file are subject to the GNU Lesser General Public License
10
 * version 3
11
 *
12
 *
13
 * This program is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Lesser General Public License as published by
15
 * the Free Software Foundation, either version 3 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU Lesser General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Lesser General Public License
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 *
27
 * Alternatively, the contents of this file may be used under the terms
28
 * of the Apache License, Version 2.0, in which case the
29
 * provisions of the Apache License, Version 2.0 are applicable instead of those
30
 * above.
31
 *
32
 *
33
 * Licensed under the Apache License, Version 2.0 (the "License");
34
 * you may not use this file except in compliance with the License.
35
 * You may obtain a copy of the License at
36
 *
37
 *     http://www.apache.org/licenses/LICENSE-2.0
38
 *
39
 * Unless required by applicable law or agreed to in writing, software
40
 * distributed under the License is distributed on an "AS IS" BASIS,
41
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42
 * See the License for the specific language governing permissions and
43
 * limitations under the License.
44
 *
45
 */
46
47
package de.tudresden.inf.lat.jcel.core.algorithm.rulebased;
48
49
import java.io.IOException;
50
import java.io.Writer;
51
import java.util.AbstractMap;
52
import java.util.ArrayList;
53
import java.util.Collection;
54
import java.util.Collections;
55
import java.util.HashMap;
56
import java.util.HashSet;
57
import java.util.List;
58
import java.util.Map;
59
import java.util.NoSuchElementException;
60
import java.util.Objects;
61
import java.util.Set;
62
import java.util.logging.Logger;
63
64
import de.tudresden.inf.lat.jcel.core.algorithm.common.Processor;
65
import de.tudresden.inf.lat.jcel.core.algorithm.common.UnclassifiedOntologyException;
66
import de.tudresden.inf.lat.jcel.core.completion.common.REntry;
67
import de.tudresden.inf.lat.jcel.core.completion.common.SEntry;
68
import de.tudresden.inf.lat.jcel.core.graph.IntegerBinaryRelation;
69
import de.tudresden.inf.lat.jcel.core.graph.IntegerHierarchicalGraph;
70
import de.tudresden.inf.lat.jcel.core.graph.IntegerHierarchicalGraphImpl;
71
import de.tudresden.inf.lat.jcel.core.graph.IntegerSubsumerGraph;
72
import de.tudresden.inf.lat.jcel.core.graph.IntegerSubsumerGraphImpl;
73
import de.tudresden.inf.lat.jcel.core.saturation.SubPropertyNormalizer;
74
import de.tudresden.inf.lat.jcel.coreontology.axiom.ExtendedOntology;
75
import de.tudresden.inf.lat.jcel.coreontology.axiom.ExtendedOntologyImpl;
76
import de.tudresden.inf.lat.jcel.coreontology.axiom.NormalizedIntegerAxiom;
77
import de.tudresden.inf.lat.jcel.coreontology.axiom.NormalizedIntegerAxiomFactory;
78
import de.tudresden.inf.lat.jcel.coreontology.datatype.IntegerEntityManager;
79
import de.tudresden.inf.lat.jcel.coreontology.datatype.IntegerEntityType;
80
import de.tudresden.inf.lat.jcel.coreontology.datatype.OntologyExpressivity;
81
82
/**
83
 * An object of this class is an implementation of a classification algorithm.
84
 * 
85
 * @author Julian Mendez
86
 */
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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
	}
742
743
}
744