1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.openrdf.elmo.sesame;
30
31 import info.aduna.iteration.CloseableIteration;
32
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Set;
40
41 import org.openrdf.elmo.ElmoProperty;
42 import org.openrdf.elmo.exceptions.ElmoPersistException;
43 import org.openrdf.elmo.exceptions.ElmoIOException;
44 import org.openrdf.elmo.sesame.helpers.PropertyChanger;
45 import org.openrdf.elmo.sesame.iterators.ElmoIteration;
46 import org.openrdf.elmo.sesame.roles.SesameEntity;
47 import org.openrdf.model.Resource;
48 import org.openrdf.model.Statement;
49 import org.openrdf.model.URI;
50 import org.openrdf.model.Value;
51 import org.openrdf.repository.RepositoryConnection;
52 import org.openrdf.repository.RepositoryException;
53 import org.openrdf.repository.contextaware.ContextAwareConnection;
54
55
56
57
58
59
60
61
62 public class SesameProperty<E> implements ElmoProperty<E>, Set<E> {
63
64 private final SesameEntity bean;
65
66 protected PropertyChanger property;
67
68 private boolean singleCached;
69
70 private E single;
71
72 public SesameProperty(SesameEntity bean, PropertyChanger property) {
73 assert bean != null;
74 assert property != null;
75 this.bean = bean;
76 this.property = property;
77 }
78
79 public void refresh() {
80 singleCached = false;
81 single = null;
82 }
83
84 public boolean add(E o) {
85 Value val = getValue(o);
86 if (contains(val))
87 return false;
88 ContextAwareConnection conn = getConnection();
89 try {
90 add(conn, getResource(), val);
91 } catch (RepositoryException e) {
92 throw new ElmoPersistException(e);
93 }
94 return true;
95 }
96
97 public boolean addAll(Collection<? extends E> c) {
98 RepositoryConnection conn = getConnection();
99 boolean modified = false;
100 try {
101 boolean autoCommit = conn.isAutoCommit();
102 if (autoCommit)
103 conn.setAutoCommit(false);
104 for (E o : c)
105 if (add(o))
106 modified = true;
107 if (autoCommit)
108 conn.setAutoCommit(true);
109 } catch (RepositoryException e) {
110 throw new ElmoPersistException(e);
111 }
112 return modified;
113 }
114
115 public void clear() {
116 ContextAwareConnection conn = getConnection();
117 try {
118 boolean autoCommit = conn.isAutoCommit();
119 conn.setAutoCommit(false);
120 CloseableIteration<? extends Statement, RepositoryException> stmts;
121 stmts = getStatements();
122 try {
123 while (stmts.hasNext()) {
124 remove(conn, stmts.next());
125 }
126 } finally {
127 stmts.close();
128 }
129 conn.setAutoCommit(autoCommit);
130 } catch (RepositoryException e) {
131 throw new ElmoPersistException(e);
132 }
133 }
134
135 public boolean contains(Object o) {
136 Value val = getValue(o);
137 ContextAwareConnection conn = getConnection();
138 try {
139 return conn.hasStatement(getResource(), getURI(), val);
140 } catch (RepositoryException e) {
141 throw new ElmoPersistException(e);
142 }
143 }
144
145 public boolean containsAll(Collection<?> c) {
146 Iterator<?> e = c.iterator();
147 while (e.hasNext())
148 if (!contains(e.next()))
149 return false;
150 return true;
151 }
152
153 @Override
154 public boolean equals(Object o) {
155 if (o == this)
156 return true;
157 if (!o.getClass().equals(this.getClass()))
158 return false;
159 SesameProperty<?> p = (SesameProperty<?>) o;
160 if (!getManager().equals(p.getManager()))
161 return false;
162 if (!getResource().equals(p.getResource()))
163 return false;
164 if (!property.equals(p.property))
165 return false;
166 return true;
167 }
168
169 public Set<E> getAll() {
170 return this;
171 }
172
173 public E getSingle() {
174 if (singleCached)
175 return single;
176 ElmoIteration<Statement, E> iter = getElmoIteration();
177 try {
178 if (iter.hasNext()) {
179 single = iter.next();
180 } else {
181 single = null;
182 }
183 singleCached = true;
184 return single;
185 } finally {
186 iter.close();
187 }
188 }
189
190 @Override
191 public int hashCode() {
192 int hashCode = bean.hashCode();
193 hashCode ^= property.hashCode();
194 return hashCode;
195 }
196
197 public boolean isEmpty() {
198 ElmoIteration<Statement, E> iter = getElmoIteration();
199 try {
200 return !iter.hasNext();
201 } finally {
202 iter.close();
203 }
204 }
205
206 public Iterator<E> iterator() {
207 ElmoIteration<Statement, E> iter = getElmoIteration();
208 if (iter.hasNext()) {
209 bean.opened(iter);
210 }
211 return iter;
212 }
213
214 public boolean remove(Object o) {
215 Value val = getValue(o);
216 if (!contains(val))
217 return false;
218 ContextAwareConnection conn = getConnection();
219 try {
220 remove(conn, getResource(), val);
221 } catch (RepositoryException e) {
222 throw new ElmoPersistException(e);
223 }
224 return true;
225 }
226
227 public boolean removeAll(Collection<?> c) {
228 RepositoryConnection conn = getConnection();
229 boolean modified = false;
230 try {
231 boolean autoCommit = conn.isAutoCommit();
232 if (autoCommit)
233 conn.setAutoCommit(false);
234 for (Object o : c)
235 if (remove(o))
236 modified = true;
237 if (autoCommit)
238 conn.setAutoCommit(true);
239 } catch (RepositoryException e) {
240 throw new ElmoPersistException(e);
241 }
242 return modified;
243 }
244
245 public boolean retainAll(Collection<?> c) {
246 RepositoryConnection conn = getConnection();
247 boolean modified = false;
248 try {
249 boolean autoCommit = conn.isAutoCommit();
250 if (autoCommit)
251 conn.setAutoCommit(false);
252 Iterator<E> e = iterator();
253 while (e.hasNext()) {
254 if (!c.contains(e.next())) {
255 e.remove();
256 modified = true;
257 }
258 }
259 if (autoCommit)
260 conn.setAutoCommit(true);
261 } catch (RepositoryException e) {
262 throw new ElmoPersistException(e);
263 }
264 return modified;
265 }
266
267 public void setAll(Set<E> set) {
268 if (this == set)
269 return;
270 if (set == null) {
271 clear();
272 return;
273 }
274 Set<E> c = new HashSet<E>(set);
275 RepositoryConnection conn = getConnection();
276 try {
277 boolean autoCommit = conn.isAutoCommit();
278 if (autoCommit)
279 conn.setAutoCommit(false);
280 Iterator<E> e = iterator();
281 while (e.hasNext()) {
282 Object next = e.next();
283 if (c.contains(next)) {
284 c.remove(next);
285 } else {
286 e.remove();
287 }
288 }
289 if (c.size() > 0)
290 addAll(c);
291 if (autoCommit)
292 conn.setAutoCommit(true);
293 } catch (RepositoryException e) {
294 throw new ElmoPersistException(e);
295 }
296 }
297
298 public void setSingle(E o) {
299 if (o == null) {
300 clear();
301 } else {
302 setAll(Collections.singleton(o));
303 }
304 single = null;
305 singleCached = false;
306 }
307
308 public int size() {
309 CloseableIteration<? extends Statement, RepositoryException> iter;
310 try {
311 iter = getStatements();
312 try {
313 int size;
314 for (size = 0; iter.hasNext(); size++)
315 iter.next();
316 return size;
317 } finally {
318 iter.close();
319 }
320 } catch (RepositoryException e) {
321 throw new ElmoIOException(e);
322 }
323 }
324
325 public Object[] toArray() {
326 List<E> list = new ArrayList<E>();
327 ElmoIteration<Statement, E> iter = getElmoIteration();
328 try {
329 while (iter.hasNext()) {
330 list.add(iter.next());
331 }
332 } finally {
333 iter.close();
334 }
335 return list.toArray();
336 }
337
338 public <T> T[] toArray(T[] a) {
339 List<E> list = new ArrayList<E>();
340 ElmoIteration<Statement, E> iter = getElmoIteration();
341 try {
342 while (iter.hasNext()) {
343 list.add(iter.next());
344 }
345 } finally {
346 iter.close();
347 }
348 return list.toArray(a);
349 }
350
351 @Override
352 public String toString() {
353 StringBuilder sb = new StringBuilder();
354 ElmoIteration<Statement, E> iter = getElmoIteration();
355 try {
356 if (iter.hasNext()) {
357 sb.append(iter.next().toString());
358 }
359 while (iter.hasNext()) {
360 sb.append(", ");
361 sb.append(iter.next());
362 }
363 } finally {
364 iter.close();
365 }
366 return sb.toString();
367 }
368
369 final SesameManager getManager() {
370 return bean.getSesameManager();
371 }
372
373 final ContextAwareConnection getConnection() {
374 return getManager().getConnection();
375 }
376
377 final Resource getResource() {
378 return bean.getSesameResource();
379 }
380
381 final URI getURI() {
382 return property.getPredicate();
383 }
384
385 void add(ContextAwareConnection conn, Resource subj, Value obj)
386 throws RepositoryException {
387 property.add(conn, subj, obj);
388 }
389
390 void remove(ContextAwareConnection conn, Resource subj, Value obj)
391 throws RepositoryException {
392 property.remove(conn, subj, obj);
393 }
394
395 void remove(ContextAwareConnection conn, Statement stmt)
396 throws RepositoryException {
397 assert stmt.getPredicate().equals(getURI());
398 remove(conn, stmt.getSubject(), stmt.getObject());
399 }
400
401 @SuppressWarnings("unchecked")
402 E createInstance(Statement stmt) {
403 Value value = stmt.getObject();
404 return (E) getManager().getInstance(value);
405 }
406
407 CloseableIteration<? extends Statement, RepositoryException> getStatements()
408 throws RepositoryException {
409 ContextAwareConnection conn = getConnection();
410 return conn.getStatements(getResource(), getURI(), null);
411 }
412
413 Value getValue(Object instance) {
414 if (instance instanceof Value)
415 return (Value) instance;
416 return getManager().getValue(instance);
417 }
418
419 private ElmoIteration<Statement, E> getElmoIteration() {
420 try {
421 return new ElmoIteration<Statement, E>(getStatements()) {
422
423 @Override
424 protected E convert(Statement stmt) {
425 return createInstance(stmt);
426 }
427
428 @Override
429 protected void remove(Statement stmt) {
430 try {
431 ContextAwareConnection conn = getConnection();
432 SesameProperty.this.remove(conn, stmt);
433 } catch (RepositoryException e) {
434 throw new ElmoPersistException(e);
435 }
436 }
437
438 };
439 } catch (RepositoryException e) {
440 throw new ElmoPersistException(e);
441 }
442 }
443
444 }