Skip to content

Method: static {...}

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.ontodriver.jena.list;
19:
20: import cz.cvut.kbss.ontodriver.descriptor.ListDescriptor;
21: import cz.cvut.kbss.ontodriver.exception.IntegrityConstraintViolatedException;
22: import cz.cvut.kbss.ontodriver.jena.connector.StorageConnector;
23: import cz.cvut.kbss.ontodriver.jena.exception.ListProcessingException;
24: import cz.cvut.kbss.ontodriver.model.Axiom;
25: import org.apache.jena.rdf.model.Property;
26: import org.apache.jena.rdf.model.RDFNode;
27: import org.apache.jena.rdf.model.Resource;
28: import org.apache.jena.rdf.model.Statement;
29:
30: import java.util.Collection;
31: import java.util.Collections;
32: import java.util.NoSuchElementException;
33: import java.util.Set;
34:
35: import static org.apache.jena.rdf.model.ResourceFactory.createProperty;
36: import static org.apache.jena.rdf.model.ResourceFactory.createResource;
37:
38: abstract class AbstractListIterator<T> {
39:
40: final StorageConnector connector;
41:
42: final Property hasListProperty;
43: final Property hasNextProperty;
44:
45: final String context;
46:
47: int index;
48: private boolean removed = false;
49:
50: Resource previousNode;
51: Resource currentNode;
52: Collection<Statement> cursor;
53:
54: AbstractListIterator(ListDescriptor descriptor, StorageConnector connector) {
55: this.hasListProperty = createProperty(descriptor.getListProperty().getIdentifier().toString());
56: this.hasNextProperty = createProperty(descriptor.getNextNode().getIdentifier().toString());
57: this.context = descriptor.getContext() != null ? descriptor.getContext().toString() : null;
58: this.connector = connector;
59: this.index = -1;
60: this.currentNode = createResource(descriptor.getListOwner().getIdentifier().toString());
61: moveCursor(currentNode);
62: }
63:
64: protected Set<String> contexts() {
65: return context != null ? Collections.singleton(context) : Collections.emptySet();
66: }
67:
68: void moveCursor(Resource from) {
69: this.cursor = connector.find(from, first() ? hasListProperty : hasNextProperty, null, contexts());
70: }
71:
72: void resolveNextListNode() {
73: verifySuccessorCount();
74: final RDFNode node = cursor.iterator().next().getObject();
75: if (!node.isURIResource()) {
76: throw new ListProcessingException("Expected successor of node " + currentNode + " to be a named resource.");
77: }
78: final Resource item = node.asResource();
79: index++;
80: this.removed = false;
81: this.previousNode = currentNode;
82: this.currentNode = item;
83: moveCursor(currentNode);
84: }
85:
86: boolean first() {
87: return index == -1;
88: }
89:
90: boolean hasNext() {
91: return !cursor.isEmpty();
92: }
93:
94: void verifySuccessorCount() {
95: if (!hasNext()) {
96: throw new NoSuchElementException("No more elements available.");
97: }
98: if (cursor.size() > 1) {
99: throw new IntegrityConstraintViolatedException(
100: "Encountered multiple successors of list node " + currentNode.getURI());
101: }
102: }
103:
104: void remove(Resource subject, Property property, RDFNode object) {
105: connector.remove(subject, property, object, context);
106: }
107:
108: abstract Axiom<T> nextAxiom();
109:
110: abstract T nextValue();
111:
112: /**
113: * Only returns current node.
114: * <p>
115: * Does not advance the iterator like {@link #nextAxiom()} and {@link #nextValue()} do.
116: *
117: * @return Current list node
118: */
119: Resource getCurrentNode() {
120: return currentNode;
121: }
122:
123: /**
124: * Removes the current node without reconnecting the subsequent nodes to the previous one.
125: */
126: void removeWithoutReconnect() {
127: if (first()) {
128: throw new IllegalStateException("Cannot call remove before calling next.");
129: }
130: if (removed) {
131: throw new IllegalStateException("Cannot call remove multiple times on one element.");
132: }
133: assert previousNode != null;
134: assert currentNode != null;
135: remove(previousNode, index == 0 ? hasListProperty : hasNextProperty, currentNode);
136: this.removed = true;
137: }
138:
139: abstract void replace(T replacement);
140: }