1
2
3
4
5
6
7
8
9
10
11
12
13
14 package eu.fbk.rdfpro.util;
15
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.Objects;
19 import java.util.Set;
20
21 import javax.annotation.Nullable;
22
23 import org.openrdf.model.Namespace;
24 import org.openrdf.model.Resource;
25 import org.openrdf.model.Statement;
26 import org.openrdf.model.URI;
27 import org.openrdf.model.Value;
28 import org.openrdf.model.impl.NamespaceImpl;
29 import org.openrdf.model.util.ModelException;
30 import org.openrdf.query.Binding;
31 import org.openrdf.query.BindingSet;
32 import org.openrdf.query.Dataset;
33 import org.openrdf.query.MalformedQueryException;
34 import org.openrdf.query.QueryEvaluationException;
35 import org.openrdf.query.QueryLanguage;
36 import org.openrdf.query.TupleQuery;
37 import org.openrdf.query.algebra.TupleExpr;
38 import org.openrdf.repository.RepositoryConnection;
39 import org.openrdf.repository.RepositoryException;
40 import org.openrdf.repository.RepositoryResult;
41
42 final class QuadModelRepositoryAdapter extends QuadModel implements AutoCloseable {
43
44 private static final long serialVersionUID = 1L;
45
46 private final RepositoryConnection connection;
47
48 private final boolean trackChanges;
49
50 QuadModelRepositoryAdapter(final RepositoryConnection connection, final boolean trackChanges) {
51 this.connection = Objects.requireNonNull(connection);
52 this.trackChanges = trackChanges;
53 }
54
55 @Override
56 public void close() {
57 IO.closeQuietly(this.connection);
58 }
59
60 @Override
61 protected Set<Namespace> doGetNamespaces() {
62 try {
63 final Set<Namespace> namespaces = new HashSet<>();
64 RepositoryResult<? extends Namespace> iteration;
65 iteration = this.connection.getNamespaces();
66 try {
67 while (iteration.hasNext()) {
68 namespaces.add(iteration.next());
69 }
70 } finally {
71 iteration.close();
72 }
73 return namespaces;
74 } catch (final RepositoryException ex) {
75 throw new ModelException(ex);
76 }
77 }
78
79 @Override
80 @Nullable
81 protected Namespace doGetNamespace(final String prefix) {
82 try {
83 final String name = this.connection.getNamespace(prefix);
84 return name == null ? null : new NamespaceImpl(prefix, name);
85 } catch (final RepositoryException ex) {
86 throw new ModelException(ex);
87 }
88 }
89
90 @Override
91 protected Namespace doSetNamespace(final String prefix, @Nullable final String name) {
92 try {
93 final String oldName = this.connection.getNamespace(prefix);
94 final Namespace oldNamespace = oldName == null ? null : new NamespaceImpl(prefix,
95 oldName);
96 if (name == null) {
97 this.connection.removeNamespace(prefix);
98 } else {
99 this.connection.setNamespace(prefix, name);
100 }
101 return oldNamespace;
102 } catch (final RepositoryException ex) {
103 throw new ModelException(ex);
104 }
105 }
106
107 @Override
108 protected int doSize(@Nullable final Resource subj, @Nullable final URI pred,
109 @Nullable final Value obj, final Resource[] ctxs) {
110 try {
111 if (subj == null && pred == null && obj == null) {
112 return (int) this.connection.size(ctxs);
113 } else {
114 int size = 0;
115 RepositoryResult<? extends Statement> iteration;
116 iteration = this.connection.getStatements(subj, pred, obj, false, ctxs);
117 try {
118 while (iteration.hasNext()) {
119 iteration.next();
120 ++size;
121 }
122 } finally {
123 iteration.close();
124 }
125 return size;
126 }
127 } catch (final RepositoryException ex) {
128 throw new ModelException(ex);
129 }
130 }
131
132 @Override
133 protected int doSizeEstimate(@Nullable final Resource subj, @Nullable final URI pred,
134 @Nullable final Value obj, @Nullable final Resource ctx) {
135 return Integer.MAX_VALUE;
136 }
137
138 @Override
139 protected Iterator<Statement> doIterator(@Nullable final Resource subj,
140 @Nullable final URI pred, @Nullable final Value obj, final Resource[] ctxs) {
141 try {
142 return Iterators.forIteration(this.connection.getStatements(subj, pred, obj, false,
143 ctxs));
144 } catch (final RepositoryException ex) {
145 throw new ModelException(ex);
146 }
147 }
148
149 @Override
150 protected boolean doAdd(@Nullable final Resource subj, @Nullable final URI pred,
151 @Nullable final Value obj, final Resource[] ctxs) {
152 try {
153 if (!this.trackChanges) {
154 this.connection.add(subj, pred, obj, ctxs);
155 return true;
156 } else if (ctxs.length == 0) {
157 if (this.connection.hasStatement(subj, pred, obj, false, new Resource[] { null })) {
158 return false;
159 }
160 this.connection.add(subj, pred, obj, ctxs);
161 return true;
162 } else if (ctxs.length == 1) {
163 if (this.connection.hasStatement(subj, pred, obj, false, ctxs)) {
164 return false;
165 }
166 this.connection.add(subj, pred, obj, ctxs);
167 return true;
168 } else {
169 boolean modified = false;
170 for (final Resource ctx : ctxs) {
171 final Resource[] singletonCtxs = new Resource[] { ctx };
172 if (!this.connection.hasStatement(subj, pred, obj, false, singletonCtxs)) {
173 this.connection.add(subj, pred, obj, singletonCtxs);
174 modified = true;
175 }
176 }
177 return modified;
178 }
179 } catch (final RepositoryException ex) {
180 throw new ModelException(ex);
181 }
182 }
183
184 @Override
185 protected boolean doRemove(@Nullable final Resource subj, @Nullable final URI pred,
186 @Nullable final Value obj, final Resource[] ctxs) {
187 try {
188 if (!this.trackChanges) {
189 this.connection.remove(subj, pred, obj, ctxs);
190 return true;
191 } else {
192 if (!this.connection.hasStatement(subj, pred, obj, false, ctxs)) {
193 return false;
194 }
195 this.connection.remove(subj, pred, obj, ctxs);
196 return true;
197 }
198 } catch (final RepositoryException ex) {
199 throw new ModelException(ex);
200 }
201 }
202
203 @Override
204 protected Iterator<BindingSet> doEvaluate(final TupleExpr expr, final Dataset dataset,
205 final BindingSet bindings) {
206
207 final String queryString = Algebra.renderQuery(expr, null, null, true);
208 try {
209 final TupleQuery query = this.connection.prepareTupleQuery(QueryLanguage.SPARQL,
210 queryString);
211 query.setDataset(dataset);
212 for (final Binding binding : bindings) {
213 query.setBinding(binding.getName(), binding.getValue());
214 }
215 return Iterators.forIteration(query.evaluate());
216 } catch (final QueryEvaluationException | MalformedQueryException | RepositoryException ex) {
217 throw new ModelException(ex);
218 }
219 }
220
221 }