Skip to content

Package: ListHandler$MergeResult

ListHandler$MergeResult

nameinstructionbranchcomplexitylinemethod
ListHandler.MergeResult(int, Resource)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%

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.ontodriver.sesame;
16:
17: import java.util.ArrayList;
18: import java.util.Collection;
19: import java.util.List;
20:
21: import cz.cvut.kbss.ontodriver.model.NamedResource;
22: import cz.cvut.kbss.ontodriver.sesame.util.SesameUtils;
23:
24: import cz.cvut.kbss.ontodriver.exception.IntegrityConstraintViolatedException;
25: import cz.cvut.kbss.ontodriver.sesame.connector.Connector;
26: import cz.cvut.kbss.ontodriver.sesame.exceptions.SesameDriverException;
27: import cz.cvut.kbss.ontodriver.descriptor.ListDescriptor;
28: import cz.cvut.kbss.ontodriver.descriptor.ListValueDescriptor;
29: import cz.cvut.kbss.ontodriver.descriptor.ReferencedListDescriptor;
30: import cz.cvut.kbss.ontodriver.descriptor.ReferencedListValueDescriptor;
31: import cz.cvut.kbss.ontodriver.descriptor.SimpleListDescriptor;
32: import cz.cvut.kbss.ontodriver.descriptor.SimpleListValueDescriptor;
33: import cz.cvut.kbss.ontodriver.model.Axiom;
34: import org.eclipse.rdf4j.model.*;
35:
36: /**
37: * Base class for list handlers.
38: * <p>
39: * List handlers are responsible for loading and persisting lists.
40: *
41: * @param <T> List descriptor type
42: * @param <V> List value descriptor type
43: */
44: abstract class ListHandler<T extends ListDescriptor, V extends ListValueDescriptor> {
45:
46: protected final Connector connector;
47: protected final ValueFactory vf;
48:
49: ListHandler(Connector connector, ValueFactory vf) {
50: this.connector = connector;
51: this.vf = vf;
52: }
53:
54: /**
55: * Loads axioms representing list described by the specified list
56: * descriptor.
57: *
58: * @return Collection of axioms representing sequence values
59: * @throws SesameDriverException When storage access error occurs
60: */
61: List<Axiom<NamedResource>> loadList(T listDescriptor) throws SesameDriverException {
62: final List<Axiom<NamedResource>> axioms = new ArrayList<>();
63: final SesameIterator it = createIterator(listDescriptor);
64: while (it.hasNext()) {
65: axioms.add(it.nextAxiom());
66: }
67: return axioms;
68: }
69:
70: abstract SesameIterator createIterator(T listDescriptor) throws SesameDriverException;
71:
72: /**
73: * Persists list values specified by the descriptor.
74: * <p>
75: * The values are saved in the order in which they appear in the descriptor.
76: *
77: * @param listValueDescriptor Describes values to persist
78: * @throws SesameDriverException When storage access error occurs
79: */
80: void persistList(V listValueDescriptor) throws SesameDriverException {
81: if (listValueDescriptor.getValues().isEmpty()) {
82: return;
83: }
84: final Collection<Statement> statements = new ArrayList<>(listValueDescriptor.getValues()
85: .size());
86: final IRI head = createListHead(listValueDescriptor, statements);
87: statements.addAll(createListRest(head, listValueDescriptor));
88: connector.addStatements(statements);
89: }
90:
91: abstract IRI createListHead(V valueDescriptor, Collection<Statement> listStatements) throws SesameDriverException;
92:
93: abstract List<Statement> createListRest(IRI head, V valueDescriptor) throws SesameDriverException;
94:
95: /**
96: * Updates list with values specified by the descriptor.
97: *
98: * @param listValueDescriptor Describes the updated values
99: * @throws SesameDriverException When storage access error occurs
100: */
101: void updateList(V listValueDescriptor) throws SesameDriverException {
102: if (listValueDescriptor.getValues().isEmpty()) {
103: clearList(listValueDescriptor);
104: } else if (isOldListEmpty(owner(listValueDescriptor), hasList(listValueDescriptor),
105: listValueDescriptor.getListProperty().isInferred(), context(listValueDescriptor))) {
106: persistList(listValueDescriptor);
107: } else {
108: mergeList(listValueDescriptor);
109: }
110: }
111:
112: private boolean isOldListEmpty(Resource owner, IRI hasListProperty, boolean includeInferred,
113: IRI context) throws SesameDriverException {
114: final Collection<Statement> stmts = connector.findStatements(owner, hasListProperty, null,
115: includeInferred, context);
116: return stmts.isEmpty();
117: }
118:
119: abstract void clearList(V listDescriptor) throws SesameDriverException;
120:
121: private void mergeList(V listDescriptor) throws SesameDriverException {
122: final SesameIterator it = iterator(listDescriptor);
123: final MergeResult mergeResult = mergeWithOriginalList(listDescriptor, it);
124: removeObsoletes(it);
125: assert mergeResult.i > 0;
126: assert mergeResult.previous != null;
127: if (mergeResult.i < listDescriptor.getValues().size()) {
128: appendNewNodes(listDescriptor, mergeResult);
129: }
130: }
131:
132: abstract SesameIterator iterator(V listDescriptor) throws SesameDriverException;
133:
134: abstract MergeResult mergeWithOriginalList(V listDescriptor, SesameIterator it) throws SesameDriverException;
135:
136: abstract void appendNewNodes(V listDescriptor, MergeResult mergeResult) throws SesameDriverException;
137:
138: private void removeObsoletes(SesameIterator it) throws SesameDriverException {
139: while (it.hasNext()) {
140: it.nextNode();
141: it.remove();
142: }
143: }
144:
145: Resource extractListNode(Collection<Statement> stmts, IRI nodeAssertion)
146: throws SesameDriverException {
147: if (stmts.size() > 1) {
148: throw new IntegrityConstraintViolatedException(
149: "Invalid number of values found for assertion " + nodeAssertion + ". Expected 1, got " +
150: stmts.size());
151: }
152: final Value val = stmts.iterator().next().getObject();
153: if (!(val instanceof Resource)) {
154: throw new IntegrityConstraintViolatedException(
155: "Invalid property value. Expected object property value, got literal.");
156: }
157: return (Resource) val;
158: }
159:
160: IRI context(ListDescriptor listDescriptor) {
161: return sesameIri(listDescriptor.getContext());
162: }
163:
164: IRI owner(ListDescriptor listDescriptor) {
165: return sesameIri(listDescriptor.getListOwner().getIdentifier());
166: }
167:
168: IRI hasList(ListDescriptor listDescriptor) {
169: return sesameIri(listDescriptor.getListProperty().getIdentifier());
170: }
171:
172: IRI hasNext(ListDescriptor listDescriptor) {
173: return sesameIri(listDescriptor.getNextNode().getIdentifier());
174: }
175:
176: IRI sesameIri(java.net.URI uri) {
177: return SesameUtils.toSesameIri(uri, vf);
178: }
179:
180: /**
181: * Creates handler for simple lists.
182: *
183: * @param connector Storage connector
184: * @param vf Sesame value factory
185: * @return List handler
186: */
187: static ListHandler<SimpleListDescriptor, SimpleListValueDescriptor> createForSimpleList(
188: Connector connector, ValueFactory vf) {
189: assert connector != null;
190: assert vf != null;
191:
192: return new SimpleListHandler(connector, vf);
193: }
194:
195: /**
196: * Creates handler for referenced lists.
197: *
198: * @param connector Storage connector
199: * @param vf Sesame value factory
200: * @return List handler
201: */
202: static ListHandler<ReferencedListDescriptor, ReferencedListValueDescriptor> createForReferencedList(
203: Connector connector, ValueFactory vf) {
204: assert connector != null;
205: assert vf != null;
206:
207: return new ReferencedListHandler(connector, vf);
208: }
209:
210: static final class MergeResult {
211: protected int i;
212: Resource previous;
213:
214: MergeResult(int i, Resource node) {
215: this.i = i;
216: this.previous = node;
217: }
218: }
219: }