Package: PolymorphicEntityTypeResolver
PolymorphicEntityTypeResolver
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
PolymorphicEntityTypeResolver(NamedResource, EntityTypeImpl, Collection) |
|
|
|
|
|
||||||||||||||||||||
addMatchingType(EntityType, Set) |
|
|
|
|
|
||||||||||||||||||||
determineActualEntityType() |
|
|
|
|
|
||||||||||||||||||||
findMatchingEntityType(AbstractIdentifiableType, Set) |
|
|
|
|
|
||||||||||||||||||||
lambda$new$0(Axiom) |
|
|
|
|
|
||||||||||||||||||||
resolveMatchingEntityTypes() |
|
|
|
|
|
Coverage
1: /**
2: * Copyright (C) 2016 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.oom.metamodel;
16:
17: import cz.cvut.kbss.jopa.model.metamodel.AbstractIdentifiableType;
18: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
19: import cz.cvut.kbss.jopa.model.metamodel.EntityTypeImpl;
20: import cz.cvut.kbss.jopa.model.metamodel.Type;
21: import cz.cvut.kbss.jopa.oom.exceptions.AmbiguousEntityTypeException;
22: import cz.cvut.kbss.ontodriver.model.Axiom;
23: import cz.cvut.kbss.ontodriver.model.NamedResource;
24:
25: import java.net.URI;
26: import java.util.Collection;
27: import java.util.HashSet;
28: import java.util.Set;
29: import java.util.stream.Collectors;
30:
31: public class PolymorphicEntityTypeResolver<T> {
32:
33: private final NamedResource individual;
34: private final Set<URI> types;
35: private final EntityTypeImpl<T> root;
36:
37: private final Set<EntityType<? extends T>> matches = new HashSet<>(2);
38:
39: public PolymorphicEntityTypeResolver(NamedResource individual, EntityTypeImpl<T> root,
40: Collection<Axiom<URI>> typeAxioms) {
41: this.individual = individual;
42: this.types = typeAxioms.stream().map(a -> a.getValue().getValue()).collect(Collectors.toSet());
43: this.root = root;
44: }
45:
46: /**
47: * Returns entity type suitable for instance loading. This entity type is
48: * <ul>
49: * <li>either the specified {@code root} in case the type axioms contain type corresponding to the root entity
50: * type,
51: * <li>or the most specific non-abstract entity type from the hierarchy of the specified root entity type
52: * present in the specified type axioms.
53: * </ul>
54: *
55: * @return The specified root entity type or the most specific non-abstract unique entity type
56: * @throws AmbiguousEntityTypeException When multiple entity types match the specified types
57: */
58: public EntityType<? extends T> determineActualEntityType() {
59:• if (types.contains(root.getIRI().toURI()) && !root.isAbstract()) {
60: return root;
61: }
62: resolveMatchingEntityTypes();
63:• if (matches.size() > 1) {
64: throw new AmbiguousEntityTypeException(
65: "Unable to determine unique entity type for loading individual " + individual +
66: ". Matching types are " + matches + '.');
67: }
68:• return !matches.isEmpty() ? matches.iterator().next() : null;
69: }
70:
71: /**
72: * The algorithm uses DFS with remembering the path taken. If a matching entity type is found, but there already
73: * exists a more general one (an ancestor of the ET), then the ancestor is removed from the matches, because it is
74: * superseded by the more specific entity type just found.
75: */
76: private void resolveMatchingEntityTypes() {
77: findMatchingEntityType(root, new HashSet<>());
78: }
79:
80: private void findMatchingEntityType(AbstractIdentifiableType<? extends T> parent,
81: Set<EntityType<? extends T>> ancestors) {
82:• for (AbstractIdentifiableType<? extends T> subtype : parent.getSubtypes()) {
83: final Set<EntityType<? extends T>> updatedAncestors = new HashSet<>(ancestors);
84:• if (subtype.getPersistenceType() == Type.PersistenceType.ENTITY && !subtype.isAbstract()) {
85: final EntityTypeImpl<? extends T> et = (EntityTypeImpl<? extends T>) subtype;
86: final URI etUri = et.getIRI().toURI();
87:• if (types.contains(etUri)) {
88: addMatchingType(et, ancestors);
89: }
90: updatedAncestors.add(et);
91: }
92: findMatchingEntityType(subtype, updatedAncestors);
93: }
94: }
95:
96: private void addMatchingType(EntityType<? extends T> et, Set<EntityType<? extends T>> ancestors) {
97: matches.add(et);
98: ancestors.forEach(matches::remove);
99: }
100: }