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.behaviours;
30
31 import info.aduna.iteration.CloseableIteration;
32
33 import java.util.AbstractList;
34 import java.util.HashSet;
35
36 import org.openrdf.elmo.Entity;
37 import org.openrdf.elmo.Mergeable;
38 import org.openrdf.elmo.Refreshable;
39 import org.openrdf.elmo.annotations.intercepts;
40 import org.openrdf.elmo.annotations.rdf;
41 import org.openrdf.elmo.exceptions.ElmoIOException;
42 import org.openrdf.elmo.exceptions.ElmoPersistException;
43 import org.openrdf.elmo.sesame.SesameManager;
44 import org.openrdf.elmo.sesame.iterators.ElmoIteration;
45 import org.openrdf.elmo.sesame.roles.SesameEntity;
46 import org.openrdf.model.Resource;
47 import org.openrdf.model.Statement;
48 import org.openrdf.model.URI;
49 import org.openrdf.model.Value;
50 import org.openrdf.model.vocabulary.RDF;
51 import org.openrdf.repository.Repository;
52 import org.openrdf.repository.RepositoryConnection;
53 import org.openrdf.repository.RepositoryException;
54 import org.openrdf.repository.contextaware.ContextAwareConnection;
55
56
57
58
59
60
61 @rdf("http://www.w3.org/2000/01/rdf-schema#Container")
62 public class SesameContainer extends AbstractList<Object> implements
63 java.util.List<Object>, Refreshable, Mergeable {
64
65 private static final int UNKNOWN = -1;
66
67 private SesameManager manager;
68
69 private Resource resource;
70
71 private int _size = UNKNOWN;
72
73 public SesameContainer(Entity bean) {
74 SesameEntity sbean = (SesameEntity) bean;
75 this.manager = sbean.getSesameManager();
76 this.resource = sbean.getSesameResource();
77 }
78
79 public void refresh() {
80 _size = UNKNOWN;
81 }
82
83 public void merge(Object source) {
84 if (source instanceof java.util.List) {
85 RepositoryConnection conn = manager.getConnection();
86 try {
87 boolean autoCommit = conn.isAutoCommit();
88 if (autoCommit)
89 conn.setAutoCommit(false);
90 java.util.List list = (java.util.List) source;
91 int size = list.size();
92 for (int i=0,n=size; i<n; i++) {
93 internalSet(i, list.get(i));
94 }
95 if (_size > UNKNOWN && _size < size)
96 _size = size;
97 if (autoCommit)
98 conn.setAutoCommit(true);
99 } catch (RepositoryException e) {
100 throw new ElmoPersistException(e);
101 }
102 }
103 }
104
105 private URI getMemberPredicate(int index) {
106 RepositoryConnection conn = manager.getConnection();
107 Repository repository;
108 repository = conn.getRepository();
109 String uri = RDF.NAMESPACE + '_' + (index + 1);
110 return repository.getValueFactory().createURI(uri);
111 }
112
113 @Override
114 public Object set(int index, Object obj) {
115 RepositoryConnection conn = manager.getConnection();
116 try {
117 boolean autoCommit = conn.isAutoCommit();
118 if (autoCommit)
119 conn.setAutoCommit(false);
120 Value value = internalSet(index, obj);
121 Object old = createInstance(value);
122 if (autoCommit)
123 conn.setAutoCommit(true);
124 return old;
125 } catch (RepositoryException e) {
126 throw new ElmoPersistException(e);
127 }
128 }
129
130 private Value internalSet(int index, Object o) {
131 URI pred = getMemberPredicate(index);
132 ElmoIteration<Statement, Value> stmts = getStatements(pred);
133 try {
134 Value newValue = o == null ? null : manager.getValue(o);
135 Value oldValue = null;
136 while (stmts.hasNext()) {
137 oldValue = stmts.next();
138 if (newValue == null || !newValue.equals(oldValue))
139 stmts.remove();
140 }
141 if (newValue != null && !newValue.equals(oldValue)) {
142 ContextAwareConnection conn = manager.getConnection();
143 conn.add(resource, pred, newValue);
144 }
145 return oldValue;
146 } catch (RepositoryException e) {
147 throw new ElmoPersistException(e);
148 } finally {
149 stmts.close();
150 }
151 }
152
153 private ElmoIteration<Statement, Value> getStatements(URI pred) {
154 try {
155 CloseableIteration<? extends Statement, RepositoryException> stmts;
156 final ContextAwareConnection conn = manager.getConnection();
157 stmts = conn.getStatements(resource, pred, null);
158 return new ElmoIteration<Statement, Value>(stmts) {
159 @Override
160 protected Value convert(Statement stmt) throws Exception {
161 return stmt.getObject();
162 }
163
164 @Override
165 protected void remove(Statement stmt) throws Exception {
166 conn.remove(stmt);
167 }
168 };
169 } catch (RepositoryException e) {
170 throw new ElmoIOException(e);
171 }
172 }
173
174 @Override
175 public void add(int index, Object obj) {
176 RepositoryConnection conn = manager.getConnection();
177 try {
178 boolean autoCommit = conn.isAutoCommit();
179 if (autoCommit)
180 conn.setAutoCommit(false);
181 for (int i = size() - 1; i >= index; i--) {
182 internalSet(i + 1, get(i));
183 }
184 internalSet(index, obj);
185 if (_size > UNKNOWN)
186 _size++;
187 if (autoCommit)
188 conn.setAutoCommit(true);
189 } catch (RepositoryException e) {
190 throw new ElmoPersistException(e);
191 }
192 }
193
194 @Override
195 public Object remove(int index) {
196 RepositoryConnection conn = manager.getConnection();
197 try {
198 boolean autoCommit = conn.isAutoCommit();
199 conn.setAutoCommit(false);
200 Object obj = get(index);
201 int size = size();
202 for (int i = index; i < size - 1; i++) {
203 internalSet(i, get(i + 1));
204 }
205 URI pred = getMemberPredicate(size - 1);
206 ElmoIteration<Statement, Value> stmts = getStatements(pred);
207 try {
208 while (stmts.hasNext()) {
209 stmts.next();
210 stmts.remove();
211 }
212 } finally {
213 stmts.close();
214 }
215 if (_size > UNKNOWN)
216 _size--;
217 conn.setAutoCommit(autoCommit);
218 return obj;
219 } catch (RepositoryException e) {
220 throw new ElmoPersistException(e);
221 }
222 }
223
224 @Override
225 public Object get(int index) {
226 URI pred = getMemberPredicate(index);
227 ElmoIteration<Statement, Value> stmts = getStatements(pred);
228 try {
229 if (stmts.hasNext()) {
230 Value next = stmts.next();
231 return createInstance(next);
232 }
233 return null;
234 } finally {
235 stmts.close();
236 }
237 }
238
239 @Override
240 public int size() {
241 if (_size < 0) {
242 synchronized (this) {
243 if (_size < 0) {
244 int index = getSize();
245 _size = index;
246 }
247 }
248 }
249 return _size;
250 }
251
252 @Override
253 @intercepts(method="toString",argc=0)
254 public String toString() {
255 return super.toString();
256 }
257
258 private Object createInstance(Value next) {
259 return manager.getInstance(next);
260 }
261
262 private int getSize() {
263 try {
264 CloseableIteration<? extends Statement, RepositoryException> iter;
265 HashSet<URI> set = new HashSet<URI>();
266 ContextAwareConnection conn = manager.getConnection();
267 iter = conn.getStatements(resource, null, null);
268 try {
269 while (iter.hasNext()) {
270 set.add(iter.next().getPredicate());
271 }
272 } finally {
273 iter.close();
274 }
275 int index = 0;
276 while (set.contains(getMemberPredicate(index)))
277 index++;
278 return index;
279 } catch (RuntimeException e) {
280 throw e;
281 } catch (Exception e) {
282 throw new ElmoIOException(e);
283 }
284 }
285 }