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

de.tudresden.inf.lat.jcel.core.algorithm.cel.CelProcessor   F

Complexity

Total Complexity 76

Size/Duplication

Total Lines 636
Duplicated Lines 4.56 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 29
loc 636
rs 2.32
eloc 351
wmc 76

40 Methods

Rating   Name   Duplication   Size   Complexity  
A processBottom(Integer) 0 7 2
A removeAuxiliaryClassesExceptNominals() 0 9 2
A getRelationIdSet() 0 2 1
A processExistential(Integer,ExistentialEntry) 0 14 4
A process(Integer,ExtensionEntry) 0 7 3
A CelProcessor(Set,Set,Set,NormalizedIntegerAxiomFactory,IntegerEntityManager) 0 11 1
A isConnectedTo(Integer,Integer) 0 17 2
A getSameIndividualMap() 0 6 2
B preProcess(Set,Set,Set) 0 58 1
A processNewEdge(Integer,Integer,Integer) 0 37 3
A computeDirectTypes(IntegerHierarchicalGraph) 0 13 2
A getRelation(Integer) 0 3 1
A processNominals(IntegerHierarchicalGraph) 15 15 4
A getDataPropertyHierarchy() 0 6 2
A createObjectPropertyGraph(Set,Set) 0 15 2
A getObjectPropertyGraph() 0 2 1
A prepareQueue(CelExtendedOntology) 0 6 1
A getPropertyUsedByClass(Integer) 0 2 1
A getDescendants(IntegerHierarchicalGraph,Integer) 14 14 2
A createClassGraph(Set,Set) 0 10 1
A addToQueue(Integer,Collection) 0 4 1
B makeTransitiveClosure(IntegerSubsumerGraphImpl) 0 16 6
A getClassGraph() 0 2 1
A computeSameIndividualMap(IntegerHierarchicalGraph) 0 15 2
A getOntologyObjectFactory() 0 2 1
A removeAuxiliaryNominals() 0 5 1
A createRelationSet(Collection) 0 4 1
A postProcess() 0 14 1
A isReady() 0 3 1
A createPropertyUseMap() 0 12 2
A getExtendedOntology() 0 2 1
A getDirectTypes() 0 6 2
A processImplication(Integer,ImplicationEntry) 0 27 4
A removeAuxiliaryObjectProperties() 0 8 2
A isReflexiveTransitiveSubsumed(Integer,Integer) 0 3 1
A createTransitiveSubsumed() 0 12 2
A getObjectPropertyHierarchy() 0 6 2
A process() 0 11 4
A getClassHierarchy() 0 6 2
A getEntityManager() 0 2 1

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.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
/*
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.cel;
48
49
import java.util.ArrayDeque;
50
import java.util.Collection;
51
import java.util.Collections;
52
import java.util.Deque;
53
import java.util.HashMap;
54
import java.util.HashSet;
55
import java.util.Map;
56
import java.util.Objects;
57
import java.util.Set;
58
import java.util.logging.Logger;
59
60
import de.tudresden.inf.lat.jcel.core.algorithm.common.Processor;
61
import de.tudresden.inf.lat.jcel.core.algorithm.common.UnclassifiedOntologyException;
62
import de.tudresden.inf.lat.jcel.core.graph.IntegerBinaryRelation;
63
import de.tudresden.inf.lat.jcel.core.graph.IntegerHierarchicalGraph;
64
import de.tudresden.inf.lat.jcel.core.graph.IntegerHierarchicalGraphImpl;
65
import de.tudresden.inf.lat.jcel.core.graph.IntegerRelationMapImpl;
66
import de.tudresden.inf.lat.jcel.core.graph.IntegerSubsumerGraph;
67
import de.tudresden.inf.lat.jcel.core.graph.IntegerSubsumerGraphImpl;
68
import de.tudresden.inf.lat.jcel.coreontology.axiom.NormalizedIntegerAxiom;
69
import de.tudresden.inf.lat.jcel.coreontology.axiom.NormalizedIntegerAxiomFactory;
70
import de.tudresden.inf.lat.jcel.coreontology.axiom.RI2Axiom;
71
import de.tudresden.inf.lat.jcel.coreontology.datatype.IntegerEntityManager;
72
import de.tudresden.inf.lat.jcel.coreontology.datatype.IntegerEntityType;
73
74
/**
75
 * Classifies an ontology using the CEL algorithm. The rules are:
76
 *
77
 * <ul>
78
 * <li>CR1 : <b>if</b> A<sub>1</sub>, &hellip; , A<sub>n</sub> &isin; S(X)
79
 * <b>and</b> A<sub>1</sub> \u2293 &hellip; \u2293 A<sub>n</sub> \u2291 B &isin;
80
 * O <b>and</b> B &notin; S(X) <b>then</b> S(X) := S(X) &cup; {B}</li>
81
 * <li>CR2 : <b>if</b> A &isin; S(X) <b>and</b> A \u2291 &exist; r <i>.</i> B
82
 * &isin; O <b>and</b> (X,B) &notin; R(r) <b>then</b> R(r) := R(r) &cup;{(X,B)}
83
 * </li>
84
 * <li>CR3 : <b>if</b> (X,Y) &isin; R(r) <b>and</b> A &isin; S(Y) <b>and</b>
85
 * &exist; r <i>.</i> A \u2291 B &isin; O <b>and</b> B &notin; S(X) <b>then</b>
86
 * S(X) := S(X) &cup; {B}</li>
87
 * <li>CR4 : <b>if</b> (X,Y) &isin; R(r) <b>and</b> &perp; &isin; S(Y)
88
 * <b>and</b> &perp; &notin; S(X) <b>then</b> S(X) := S(X) &cup; {&perp;}</li>
89
 * <li>CR5 : <b>if</b> (X,Y) &isin; R(r) <b>and</b> r \u2291 s &isin; O
90
 * <b>and</b> (X,Y) &notin; R(s) <b>then</b> R(s) := R(s) &cup; {(X,Y)}</li>
91
 * <li>CR6 : <b>if</b> (X,Y) &isin; R(r) <b>and</b> (Y,Z) &isin; R(s) <b>and</b>
92
 * r \u2218 s \u2291 t &isin; O <b>and</b> (X,Z) &notin; R(t) <b>then</b> R(t)
93
 * := R(t) &cup; {(X,Z)}</li>
94
 * </ul>
95
 *
96
 * @author Julian Mendez
97
 */
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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
	}
735
736
}
737