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.dynabean;
30
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.WeakHashMap;
37
38 import org.apache.commons.beanutils.DynaBean;
39 import org.apache.commons.beanutils.DynaClass;
40 import org.openrdf.elmo.Entity;
41 import org.openrdf.elmo.dynabean.helpers.DynaClassInfo;
42 import org.openrdf.elmo.dynabean.helpers.DynaClassInfoFactory;
43 import org.openrdf.elmo.exceptions.ElmoIOException;
44 import org.openrdf.elmo.exceptions.ElmoPersistException;
45 import org.openrdf.elmo.sesame.SesameManager;
46 import org.openrdf.elmo.sesame.SesameProperty;
47 import org.openrdf.elmo.sesame.helpers.PropertyChanger;
48 import org.openrdf.elmo.sesame.roles.SesameEntity;
49 import org.openrdf.model.BNode;
50 import org.openrdf.model.Resource;
51 import org.openrdf.model.URI;
52 import org.openrdf.model.ValueFactory;
53 import org.openrdf.model.vocabulary.RDF;
54 import org.openrdf.repository.Repository;
55 import org.openrdf.repository.RepositoryException;
56 import org.openrdf.repository.contextaware.ContextAwareConnection;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 @SuppressWarnings("unchecked")
76 public class DynaBeanSupport implements DynaBean {
77
78 private static WeakHashMap<Repository, DynaClassInfoFactory> factories = new WeakHashMap();
79
80 private SesameManager manager;
81
82 private SesameEntity bean;
83
84 private DynaClassInfo dynaClassInfo;
85
86 private Map<String, SesameProperty> properties = new HashMap<String, SesameProperty>();
87
88 public DynaBeanSupport(Entity elmo) {
89 this.bean = (SesameEntity) elmo;
90 this.manager = bean.getSesameManager();
91 DynaClassInfoFactory factory;
92 Repository repository;
93 repository = manager.getConnection().getRepository();
94 synchronized (factories) {
95 factory = factories.get(repository);
96 if (factory == null) {
97 factory = new DynaClassInfoFactory();
98 factories.put(repository, factory);
99 }
100 }
101 Resource resource = bean.getSesameResource();
102 this.dynaClassInfo = factory.findDyanClass(manager, resource);
103 }
104
105 public DynaClass getDynaClass() {
106 DynaClassSupport c = new DynaClassSupport(bean);
107 c.setDynaClassInfo(dynaClassInfo);
108 return c;
109 }
110
111 @SuppressWarnings("unchecked")
112 private SesameProperty getSesameProperty(String property) {
113 if (properties.containsKey(property))
114 return properties.get(property);
115 URI pred = getPredicate(property);
116 assert pred != null;
117 PropertyChanger pc = new PropertyChanger(pred);
118 SesameProperty sp = new SesameProperty(bean, pc);
119 properties.put(property, sp);
120 return sp;
121 }
122
123 private URI getPredicate(String property) {
124 int colon = property.indexOf(':');
125 if (colon < 0)
126 return dynaClassInfo.getPredicate(property);
127 ContextAwareConnection conn = manager.getConnection();
128 ValueFactory vf = conn.getRepository().getValueFactory();
129 for (int i = colon + 1, n = property.length(); i < n; i++) {
130 switch (property.charAt(i)) {
131 case ':':
132 case '/':
133 case '#':
134 return vf.createURI(property);
135 }
136 }
137 try {
138 String ns = conn.getNamespace(property.substring(0, colon));
139 if (ns == null) {
140 String msg = "Unknown prefix in property: " + property;
141 throw new IllegalArgumentException(msg);
142 }
143 return vf.createURI(ns, property.substring(colon + 1));
144 } catch (RepositoryException e) {
145 throw new ElmoIOException(e);
146 }
147 }
148
149 public Object get(String property) {
150 if (dynaClassInfo.isFunctional(property))
151 return getSesameProperty(property).getSingle();
152 return getSesameProperty(property);
153 }
154
155 public void set(String property, Object value) {
156 boolean func = dynaClassInfo.isFunctional(property);
157 if (value == null) {
158 getSesameProperty(property).clear();
159 } else if (!func && value instanceof Set) {
160 getSesameProperty(property).setAll((Set<?>) value);
161 } else {
162 getSesameProperty(property).setSingle(value);
163 }
164 }
165
166 public Object get(String property, int index) {
167 assert dynaClassInfo.isFunctional(property) : dynaClassInfo
168 .getDynaProperty(property);
169 SesameProperty sp = getSesameProperty(property);
170 List list = (List) sp.getSingle();
171 if (list == null)
172 return null;
173 return list.get(index);
174 }
175
176 @SuppressWarnings("unchecked")
177 public void set(String property, int index, Object value) {
178 assert dynaClassInfo.isFunctional(property) : dynaClassInfo
179 .getDynaProperty(property);
180 SesameProperty sp = getSesameProperty(property);
181 List<Object> list = (List) sp.getSingle();
182 if (list == null && value == null) {
183 return;
184 } else if (list == null) {
185 Collection<URI> types = dynaClassInfo.getRdfTypes(property);
186 ContextAwareConnection conn = manager.getConnection();
187 ValueFactory vf = conn.getRepository().getValueFactory();
188 BNode bNode = vf.createBNode();
189 try {
190 for (URI rdfType : types) {
191 conn.add(bNode, RDF.TYPE, rdfType);
192 }
193 } catch (RepositoryException e) {
194 throw new ElmoPersistException(e);
195 }
196 list = (List<Object>) manager.find(bNode);
197 list.add(value);
198 getSesameProperty(property).setSingle(list);
199 } else if (index == list.size()) {
200 if (value != null)
201 list.add(value);
202 } else if (value == null) {
203 list.remove(index);
204 } else {
205 list.set(index, value);
206 }
207 }
208
209 public Object get(String property, String key) {
210 if (!getDynaClass().getDynaProperty(property).isMapped())
211 throw new UnsupportedOperationException();
212 assert dynaClassInfo.isFunctional(property) : dynaClassInfo
213 .getDynaProperty(property);
214 SesameProperty sp = getSesameProperty(property);
215 Map map = (Map) sp.getSingle();
216 if (map == null)
217 return null;
218 return map.get(key);
219 }
220
221 @SuppressWarnings("unchecked")
222 public void set(String property, String key, Object value) {
223 if (!getDynaClass().getDynaProperty(property).isIndexed())
224 throw new UnsupportedOperationException();
225 assert dynaClassInfo.isFunctional(property) : dynaClassInfo
226 .getDynaProperty(property);
227 SesameProperty sp = getSesameProperty(property);
228 Map<String, Object> map = (Map) sp.getSingle();
229 if (map == null) {
230 Collection<URI> types = dynaClassInfo.getRdfTypes(property);
231 ContextAwareConnection conn = manager.getConnection();
232 ValueFactory vf = conn.getRepository().getValueFactory();
233 BNode bNode = vf.createBNode();
234 try {
235 for (URI rdfType : types) {
236 conn.add(bNode, RDF.TYPE, rdfType);
237 }
238 } catch (RepositoryException e) {
239 throw new ElmoPersistException(e);
240 }
241 map = (Map<String, Object>) manager.find(bNode);
242 map.put(key, value);
243 getSesameProperty(property).setSingle(map);
244 } else if (value == null) {
245 map.remove(key);
246 } else {
247 map.put(key, value);
248 }
249 }
250
251 public boolean contains(String property, String key) {
252 if (!getDynaClass().getDynaProperty(property).isMapped())
253 throw new UnsupportedOperationException();
254 assert dynaClassInfo.isFunctional(property);
255 SesameProperty sp = getSesameProperty(property);
256 Map map = (Map) sp.getSingle();
257 if (map == null)
258 return false;
259 return map.containsKey(key);
260 }
261
262 public void remove(String property, String key) {
263 if (!getDynaClass().getDynaProperty(property).isMapped())
264 throw new UnsupportedOperationException();
265 assert dynaClassInfo.isFunctional(property);
266 SesameProperty sp = getSesameProperty(property);
267 Map map = (Map) sp.getSingle();
268 if (map != null)
269 map.remove(key);
270 }
271
272 }