Skip to contentMethod: setReferenceSavingResolver(ReferenceSavingResolver)
1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jopa.oom;
14:
15: import cz.cvut.kbss.jopa.model.MultilingualString;
16: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
17: import cz.cvut.kbss.jopa.model.metamodel.*;
18: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
19: import cz.cvut.kbss.ontodriver.model.Assertion;
20: import cz.cvut.kbss.ontodriver.model.Axiom;
21:
22: import java.net.URI;
23:
24: /**
25: * @param <T> The attribute specification type, e.g. {@link SingularAttribute}, {@link ListAttribute}
26: * @param <X> Entity class
27: */
28: abstract class FieldStrategy<T extends FieldSpecification<? super X, ?>, X> {
29:
30: final EntityType<X> et;
31: final T attribute;
32: final Descriptor entityDescriptor;
33: final EntityMappingHelper mapper;
34: ReferenceSavingResolver referenceSavingResolver;
35:
36: FieldStrategy(EntityType<X> et, T att, Descriptor entityDescriptor, EntityMappingHelper mapper) {
37: this.et = et;
38: this.attribute = att;
39: this.entityDescriptor = entityDescriptor;
40: this.mapper = mapper;
41: }
42:
43: static <X> FieldStrategy<? extends FieldSpecification<? super X, ?>, X> createFieldStrategy(
44: EntityType<X> et, FieldSpecification<? super X, ?> att,
45: Descriptor entityDescriptor, EntityMappingHelper mapper) {
46: if (att.equals(et.getIdentifier())) {
47: return new IdentifierFieldStrategy<>(et, (Identifier<? super X, ?>) att, entityDescriptor, mapper);
48: }
49: if (att instanceof TypesSpecification) {
50: return new TypesFieldStrategy<>(et, (TypesSpecification<? super X, ?>) att, entityDescriptor, mapper);
51: } else if (att instanceof PropertiesSpecification) {
52: return new PropertiesFieldStrategy<>(et, (PropertiesSpecification<? super X, ?, ?, ?>) att,
53: entityDescriptor,
54: mapper);
55: }
56: final AbstractAttribute<? super X, ?> attribute = (AbstractAttribute<? super X, ?>) att;
57: if (attribute.isCollection()) {
58: switch (attribute.getPersistentAttributeType()) {
59: case ANNOTATION:
60: return createPluralAnnotationPropertyStrategy(et,
61: (AbstractPluralAttribute<? super X, ?, ?>) attribute, entityDescriptor, mapper);
62: case DATA:
63: return createPluralDataPropertyStrategy(et, (AbstractPluralAttribute<? super X, ?, ?>) attribute,
64: entityDescriptor, mapper);
65: case OBJECT:
66: return createPluralObjectPropertyStrategy(et, (AbstractPluralAttribute<? super X, ?, ?>) attribute,
67: entityDescriptor, mapper);
68: default:
69: break;
70: }
71: } else {
72: switch (attribute.getPersistentAttributeType()) {
73: case ANNOTATION:
74: return createSingularAnnotationPropertyStrategy(et, attribute, entityDescriptor, mapper);
75: case DATA:
76: return createSingularDataPropertyStrategy(et, attribute, entityDescriptor, mapper);
77: case OBJECT:
78: return new SingularObjectPropertyStrategy<>(et, attribute, entityDescriptor, mapper);
79: default:
80: break;
81: }
82: }
83: // Shouldn't happen
84: throw new IllegalArgumentException();
85: }
86:
87: private static <Y> FieldStrategy<? extends FieldSpecification<? super Y, ?>, Y> createPluralAnnotationPropertyStrategy(
88: EntityType<Y> et, AbstractPluralAttribute<? super Y, ?, ?> attribute,
89: Descriptor descriptor, EntityMappingHelper mapper) {
90: if (MultilingualString.class.equals(attribute.getElementType().getJavaType())) {
91: return new PluralMultilingualStringFieldStrategy<>(et,
92: (AbstractPluralAttribute<? super Y, ?, MultilingualString>) attribute, descriptor, mapper);
93: } else {
94: return new PluralAnnotationPropertyStrategy<>(et, attribute, descriptor, mapper);
95: }
96: }
97:
98: private static <Y> FieldStrategy<? extends FieldSpecification<? super Y, ?>, Y> createPluralDataPropertyStrategy(
99: EntityType<Y> et, AbstractPluralAttribute<? super Y, ?, ?> attribute,
100: Descriptor descriptor, EntityMappingHelper mapper) {
101: if (MultilingualString.class.equals(attribute.getElementType().getJavaType())) {
102: return new PluralMultilingualStringFieldStrategy<>(et,
103: (AbstractPluralAttribute<? super Y, ?, MultilingualString>) attribute, descriptor, mapper);
104: } else {
105: return new PluralDataPropertyStrategy<>(et, attribute, descriptor, mapper);
106: }
107: }
108:
109: private static <Y> FieldStrategy<? extends FieldSpecification<? super Y, ?>, Y> createPluralObjectPropertyStrategy(
110: EntityType<Y> et, AbstractPluralAttribute<? super Y, ?, ?> attribute,
111: Descriptor descriptor, EntityMappingHelper mapper) {
112: switch (attribute.getCollectionType()) {
113: case LIST:
114: return createOwlListPropertyStrategy(et, (ListAttributeImpl<? super Y, ?>) attribute, descriptor,
115: mapper);
116: case COLLECTION:
117: case SET:
118: return new SimpleSetPropertyStrategy<>(et, attribute, descriptor, mapper);
119: default:
120: throw new UnsupportedOperationException(
121: "Unsupported plural attribute collection type " + attribute.getCollectionType());
122: }
123: }
124:
125: private static <Y> FieldStrategy<? extends FieldSpecification<? super Y, ?>, Y> createOwlListPropertyStrategy(
126: EntityType<Y> et, ListAttributeImpl<? super Y, ?> attribute, Descriptor descriptor,
127: EntityMappingHelper mapper) {
128: switch (attribute.getSequenceType()) {
129: case referenced:
130: return new ReferencedListPropertyStrategy<>(et, attribute, descriptor, mapper);
131: case simple:
132: return new SimpleListPropertyStrategy<>(et, attribute, descriptor, mapper);
133: default:
134: throw new UnsupportedOperationException(
135: "Unsupported list attribute sequence type " + attribute.getSequenceType());
136: }
137: }
138:
139: private static <X> FieldStrategy<? extends FieldSpecification<? super X, ?>, X> createSingularDataPropertyStrategy(
140: EntityType<X> et, AbstractAttribute<? super X, ?> attribute, Descriptor descriptor,
141: EntityMappingHelper mapper) {
142: if (MultilingualString.class.equals(attribute.getJavaType())) {
143: return new SingularMultilingualStringFieldStrategy<>(et,
144: (AbstractAttribute<? super X, MultilingualString>) attribute, descriptor, mapper);
145: } else {
146: return new SingularDataPropertyStrategy<>(et, attribute, descriptor, mapper);
147: }
148: }
149:
150: private static <X> FieldStrategy<? extends FieldSpecification<? super X, ?>, X> createSingularAnnotationPropertyStrategy(
151: EntityType<X> et, AbstractAttribute<? super X, ?> attribute, Descriptor descriptor,
152: EntityMappingHelper mapper) {
153: if (MultilingualString.class.equals(attribute.getJavaType())) {
154: return new SingularMultilingualStringFieldStrategy<>(et,
155: (AbstractAttribute<? super X, MultilingualString>) attribute, descriptor, mapper);
156: } else {
157: return new SingularAnnotationPropertyStrategy<>(et, attribute, descriptor, mapper);
158: }
159: }
160:
161: void setReferenceSavingResolver(ReferenceSavingResolver referenceSavingResolver) {
162: this.referenceSavingResolver = referenceSavingResolver;
163: }
164:
165: /**
166: * Sets the specified value on the specified instance, the field is taken from the attribute represented by this
167: * strategy. </p>
168: * <p>
169: * Note that this method assumes the value and the field are of compatible types, no check is done here.
170: */
171: void setValueOnInstance(Object instance, Object value) {
172: EntityPropertiesUtils.setFieldValue(attribute.getJavaField(), instance, value);
173: }
174:
175: /**
176: * Extracts the attribute value from the specified instance. </p>
177: *
178: * @return Attribute value, possibly {@code null}
179: */
180: Object extractFieldValueFromInstance(Object instance) {
181: return EntityPropertiesUtils.getAttributeValue(attribute, instance);
182: }
183:
184: <E> URI resolveValueIdentifier(E instance, EntityType<E> valEt) {
185: URI id = EntityPropertiesUtils.getIdentifier(instance, valEt);
186: if (id == null) {
187: id = mapper.generateIdentifier(valEt);
188: EntityPropertiesUtils.setIdentifier(id, instance, valEt);
189: }
190: return id;
191: }
192:
193: /**
194: * Gets the context of this attribute assertion.
195: * <p>
196: * Note that this may not (and in case of object properties usually won't) be the context containing the target
197: * object. Rather, it will be the context of the owner entity itself (depending on whether assertions are stored in
198: * subject context or not).
199: *
200: * @return Attribute assertion context
201: * @see Descriptor
202: */
203: URI getAttributeContext() {
204: return entityDescriptor.getAttributeContext(attribute);
205: }
206:
207: /**
208: * Adds value from the specified axioms to this strategy. </p>
209: * <p>
210: * The value(s) is/are then set on entity field using {@link #buildInstanceFieldValue(Object)}.
211: *
212: * @param ax Axiom to extract value from
213: */
214: abstract void addValueFromAxiom(Axiom<?> ax);
215:
216: /**
217: * Sets instance field from values gathered in this strategy.
218: *
219: * @param instance The instance to receive the field value
220: * @throws IllegalArgumentException Access error
221: * @throws IllegalAccessException Access error
222: */
223: abstract void buildInstanceFieldValue(Object instance) throws IllegalAccessException;
224:
225: /**
226: * Extracts values of field represented by this strategy from the specified instance.
227: *
228: * @param instance The instance to extract values from
229: * @param valueBuilder Builder into which the attribute value(s) are extracted
230: * @throws IllegalArgumentException Access error
231: * @throws IllegalAccessException Access error
232: */
233: abstract void buildAxiomValuesFromInstance(X instance, AxiomValueGatherer valueBuilder)
234: throws IllegalAccessException;
235:
236: /**
237: * Creates property assertion appropriate for the attribute represented by this strategy.
238: *
239: * @return Property assertion
240: */
241: abstract Assertion createAssertion();
242: }