Skip to content

Method: hasValue()

1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jopa.oom;
19:
20: import cz.cvut.kbss.jopa.exceptions.CardinalityConstraintViolatedException;
21: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
22: import cz.cvut.kbss.jopa.model.metamodel.AbstractAttribute;
23: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
24: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
25: import cz.cvut.kbss.jopa.utils.IdentifierTransformer;
26: import cz.cvut.kbss.ontodriver.model.*;
27: import org.slf4j.Logger;
28: import org.slf4j.LoggerFactory;
29:
30: import java.net.URI;
31: import java.util.Collection;
32: import java.util.Collections;
33: import java.util.Set;
34:
35: class SingularObjectPropertyStrategy<X> extends FieldStrategy<AbstractAttribute<? super X, ?>, X> {
36:
37: private static final Logger LOG = LoggerFactory.getLogger(SingularObjectPropertyStrategy.class);
38:
39: private Object value;
40:
41: SingularObjectPropertyStrategy(EntityType<X> et, AbstractAttribute<? super X, ?> att,
42: Descriptor descriptor, EntityMappingHelper mapper) {
43: super(et, att, descriptor, mapper);
44: }
45:
46: @Override
47: void addAxiomValue(Axiom<?> ax) {
48: assert ax.getValue().getValue() instanceof NamedResource;
49: final NamedResource valueIdentifier = (NamedResource) ax.getValue().getValue();
50: final Class<?> targetType = attribute.getJavaType();
51: final Object newValue;
52: if (IdentifierTransformer.isValidIdentifierType(targetType)) {
53: newValue = IdentifierTransformer.transformToIdentifier(valueIdentifier.getIdentifier(), targetType);
54: } else if (targetType.isEnum()) {
55: assert attribute.getConverter() != null;
56: assert attribute.getConverter().supportsAxiomValueType(NamedResource.class);
57: // Maybe we should catch the exception and just skip the value if it is not convertible to be consistent
58: // with the 'else' branch behavior?
59: newValue = attribute.getConverter().convertToAttribute(valueIdentifier);
60: } else {
61: newValue = mapper.getEntityFromCacheOrOntology(targetType, valueIdentifier.getIdentifier(),
62: entityDescriptor.getAttributeDescriptor(attribute));
63: if (newValue == null) {
64: LOG.trace("Value of axiom {} could not be loaded as entity filling attribute {}.", ax, attribute);
65: return;
66: }
67: }
68: verifyCardinality(ax.getSubject());
69: this.value = newValue;
70: }
71:
72: private void verifyCardinality(NamedResource subject) {
73: if (value != null) {
74: throw new CardinalityConstraintViolatedException(
75: "Expected single value of attribute " + attribute.getName() + " of instance " + subject +
76: ", but got multiple.");
77: }
78: }
79:
80: @Override
81: void lazilyAddAxiomValue(Axiom<?> ax) {
82: final Class<?> targetType = attribute.getJavaType();
83: if (IdentifierTransformer.isValidIdentifierType(targetType) || targetType.isEnum()) {
84: addAxiomValue(ax);
85: } else {
86: this.value = LAZILY_LOADED_REFERENCE_PLACEHOLDER;
87: }
88: }
89:
90: @Override
91: boolean hasValue() {
92:• return value != null;
93: }
94:
95: @Override
96: void buildInstanceFieldValue(Object instance) {
97: if (value == LAZILY_LOADED_REFERENCE_PLACEHOLDER) {
98: return;
99: }
100: setValueOnInstance(instance, value);
101: }
102:
103: @Override
104: void buildAxiomValuesFromInstance(X instance, AxiomValueGatherer valueBuilder) {
105: final Object extractedValue = extractFieldValueFromInstance(instance);
106: if (referenceSavingResolver.shouldSaveReference(extractedValue, getAttributeValueContext())) {
107: final Value<NamedResource> val = extractReferenceIdentifier(extractedValue);
108: valueBuilder.addValue(createAssertion(), val, getAttributeWriteContext());
109: } else {
110: referenceSavingResolver
111: .registerPendingReference(valueBuilder.getSubjectIdentifier(), createAssertion(), extractedValue,
112: getAttributeWriteContext());
113: // This will cause the existing property assertion to be removed
114: valueBuilder.addValue(createAssertion(), Value.nullValue(), getAttributeWriteContext());
115: }
116: }
117:
118: private Set<URI> getAttributeValueContext() {
119: return entityDescriptor.getAttributeDescriptor(attribute).getContexts();
120: }
121:
122: private <V> Value<NamedResource> extractReferenceIdentifier(final V value) {
123: if (value == null) {
124: return Value.nullValue();
125: }
126: final Class<?> valueType = attribute.getJavaType();
127: if (IdentifierTransformer.isValidIdentifierType(valueType)) {
128: return new Value<>(NamedResource.create(IdentifierTransformer.valueAsUri(value)));
129: } else if (valueType.isEnum()) {
130: assert attribute.getConverter() != null;
131: return new Value<>((NamedResource) attribute.getConverter().convertToAxiomValue(value));
132: }
133: final EntityType<? super V> valEt = (EntityType<? super V>) mapper.getEntityType(valueType);
134: assert valEt != null;
135:
136: final URI id = EntityPropertiesUtils.getIdentifier(value, valEt);
137: return id != null ? new Value<>(NamedResource.create(id)) : Value.nullValue();
138: }
139:
140: @Override
141: Set<Axiom<?>> buildAxiomsFromInstance(X instance) {
142: final Object extractedValue = extractFieldValueFromInstance(instance);
143: final Value<NamedResource> val = extractReferenceIdentifier(extractedValue);
144: if (Value.nullValue().equals(val)) {
145: return Collections.emptySet();
146: }
147: return Collections.singleton(
148: new AxiomImpl<>(NamedResource.create(EntityPropertiesUtils.getIdentifier(instance, et)),
149: createAssertion(), val));
150: }
151:
152: @Override
153: Collection<Value<?>> toAxiomValue(Object value) {
154: return Collections.singleton(extractReferenceIdentifier(value));
155: }
156:
157: @Override
158: Assertion createAssertion() {
159: return Assertion.createObjectPropertyAssertion(attribute.getIRI().toURI(), attribute.isInferred());
160: }
161: }