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