1 /***
2 *
3 */
4 package org.astrogrid.desktop.modules.votech;
5
6 import java.net.URI;
7 import java.util.Collection;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12
13 import junit.framework.Test;
14 import junit.framework.TestCase;
15 import junit.framework.TestSuite;
16 import net.sf.ehcache.Ehcache;
17 import net.sf.ehcache.Element;
18 import net.sf.ehcache.Status;
19
20 import org.apache.commons.collections.IteratorUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.astrogrid.acr.ivoa.resource.Resource;
24 import org.astrogrid.desktop.modules.system.ui.UIContext;
25 import org.astrogrid.desktop.modules.ui.BackgroundWorker;
26
27 /*** Implemnentation of {@link AnnotationService}.
28 * @author Noel.Winstanley@manchester.ac.uk
29 * @since Jun 18, 20077:12:26 PM
30 */
31 public class AnnotationServiceImpl implements AnnotationService{
32 /***
33 * Logger for this class
34 */
35 private static final Log logger = LogFactory
36 .getLog(AnnotationServiceImpl.class);
37
38
39 private final List<AnnotationSource> annotationSources;
40 private final AnnotationIO io;
41 private final Ehcache cache;
42 protected final UIContext ui;
43 public AnnotationServiceImpl(final Ehcache cache, final UIContext ui, final AnnotationIO io) {
44 super();
45 this.io = io;
46 this.cache = cache;
47 this.ui = ui;
48
49
50 this.annotationSources = io.getSourcesList();
51
52 run();
53 }
54
55
56 public void addSource(final AnnotationSource nu) {
57 if (annotationSources.contains(nu)) {
58 logger.warn("Ignoring attempt to add duplicate source " + nu);
59 return;
60 }
61 annotationSources.add(nu);
62 saveSourceList();
63 if (! (nu instanceof DynamicAnnotationSource)) {
64 loadStaticSource(nu);
65 }
66 }
67
68 private void saveSourceList() {
69 (new BackgroundWorker(ui,"Saving annotation source list") {
70
71 @Override
72 protected Object construct() throws Exception {
73 io.saveAnnotationSourceList(listSources());
74 return null;
75 }
76 }).start();
77 }
78
79 public AnnotationSource[] listSources() {
80 return annotationSources.toArray(new AnnotationSource[annotationSources.size()]);
81 }
82
83 public void removeSource(final AnnotationSource remove) {
84 if (io.getUserSource().equals(remove)) {
85 logger.warn("Ignoring attempt to remove user source");
86 return;
87 }
88 annotationSources.remove(remove);
89 saveSourceList();
90
91 cache.removeAll();
92 run();
93 }
94
95 /*** load and process the annotation sources - or at least those that are static. */
96 public final void run() {
97 for (final Iterator<AnnotationSource> i = annotationSources.iterator(); i.hasNext();) {
98 final AnnotationSource s = i.next();
99 if (! (s instanceof DynamicAnnotationSource)) {
100
101 loadStaticSource(s);
102 }
103 }
104 }
105
106 /*** process a single static source */
107 public void loadStaticSource(final AnnotationSource source) {
108
109 (new BackgroundWorker(ui,"Loading annotations from " + source.getName(),BackgroundWorker.LONG_TIMEOUT,Thread.MIN_PRIORITY) {
110
111 @Override
112 protected Object construct() throws Exception {
113 final Collection anns = io.load(source);
114 for (final Iterator i = anns.iterator(); i.hasNext();) {
115 final Annotation a = (Annotation) i.next();
116 a.setSource(source);
117 final URI resourceId = a.getResourceId();
118 Element el = cache.get(resourceId);
119 if (el == null) {
120 final Map<AnnotationSource, Annotation> m = new HashMap<AnnotationSource, Annotation>(annotationSources.size());
121 m.put(a.getSource(),a);
122 el = new Element(resourceId,m);
123 } else {
124 final Map<AnnotationSource, Annotation> m = (Map<AnnotationSource, Annotation>)el.getValue();
125 m.put(a.getSource(),a);
126 }
127 cache.put(el);
128 }
129 return null;
130 }
131 @Override
132 protected void doError(final Throwable ex) {
133
134
135 logger.warn("Failed to load annotations from " + source.getName());
136 logger.debug("Cause",ex);
137
138 }
139 }).start();
140 }
141
142
143
144 public AnnotationSource getUserAnnotationSource() {
145 return io.getUserSource();
146 }
147 public UserAnnotation getUserAnnotation(final Resource r) {
148 if (r == null) {
149 return null;
150 }
151 return getUserAnnotation(r.getId());
152 }
153 public UserAnnotation getUserAnnotation(final URI resourceId) {
154 if (resourceId == null) {
155 return null;
156 }
157 final Element el = cache.get(resourceId);
158 if (el == null) {
159 return null;
160 }
161 final Map m = (Map)el.getValue();
162 final UserAnnotation ua = (UserAnnotation)m.get(io.getUserSource());
163 return ua;
164 }
165
166
167
168 public void setUserAnnotation(final Resource r, final UserAnnotation ann) {
169 if (ann == null || r == null) {
170 return;
171 }
172 final AnnotationSource userSource = io.getUserSource();
173
174 ann.setResourceId(r.getId());
175 ann.setSource(userSource);
176
177
178 Element el = cache.get(r.getId());
179 if (el == null) {
180 final Map<AnnotationSource, UserAnnotation> m = new HashMap<AnnotationSource, UserAnnotation>();
181 m.put(userSource,ann);
182 el = new Element(r.getId(),m);
183 } else {
184 final Map<AnnotationSource, UserAnnotation> m = (Map<AnnotationSource, UserAnnotation>)el.getValue();
185 m.put(userSource,ann);
186 }
187 cache.put(el);
188 io.updateUserAnnotation(ann);
189
190 }
191
192
193 public void removeUserAnnotation(final Resource r) {
194 if (r == null) {
195 return;
196 }
197 final Element el = cache.get(r.getId());
198 if (el != null) {
199 final Map m = (Map)el.getValue();
200 if (m.remove(io.getUserSource()) != null) {
201 cache.put(el);
202 io.removeUserAnnotation(r);
203 }
204 }
205 }
206
207
208 public void processLocalAnnotations(final Resource r, final AnnotationProcessor procesor) {
209 if (r == null || procesor == null) {
210 return;
211 }
212 final Element el = cache.get(r.getId());
213 if (el == null) {
214 return;
215 }
216 final Map m = (Map)el.getValue();
217 for (final Iterator i = m.values().iterator(); i.hasNext(); ) {
218 final Annotation a = (Annotation)i.next();
219 if (a instanceof UserAnnotation) {
220 procesor.process((UserAnnotation)a);
221 } else {
222 procesor.process(a);
223 }
224 }
225 }
226
227 public Iterator getLocalAnnotations(final Resource r) {
228 if (r == null) {
229 return IteratorUtils.emptyIterator();
230 }
231 final Element el = cache.get(r.getId());
232 if (el == null) {
233 return IteratorUtils.emptyIterator();
234 }
235 final Map m = (Map)el.getValue();
236 return m.values().iterator();
237 }
238
239 public void processRemainingAnnotations(final Resource r, final AnnotationProcessor processor) {
240 Element el = cache.get(r.getId());
241 final Map<AnnotationSource, Annotation> m;
242 if (el == null) {
243 m = new HashMap<AnnotationSource, Annotation>();
244 el = new Element(r.getId(),m);
245 } else {
246 m = (Map<AnnotationSource, Annotation>)el.getValue();
247 }
248 final Element toCache = el;
249 for (final Iterator<AnnotationSource> i = annotationSources.iterator(); i.hasNext();) {
250 final AnnotationSource source = i.next();
251 if (source instanceof DynamicAnnotationSource &&
252 ! m.containsKey(source)) {
253 (new BackgroundWorker(ui,"Loading annotations from " + source.getName(),BackgroundWorker.SHORT_TIMEOUT,Thread.MIN_PRIORITY) {
254 @Override
255 protected Object construct() throws Exception {
256 final DynamicAnnotationSource dynSource = (DynamicAnnotationSource)source;
257 final Annotation ann = (dynSource).getAnnotationFor(r);
258 if (ann != null && dynSource.shouldCache()) {
259 m.put(source,ann);
260 cache.put(toCache);
261
262 }
263 return ann;
264 }
265 @Override
266 protected void doFinished(final Object result) {
267 final Annotation ann = (Annotation)result;
268 if (ann != null) {
269 if (ann instanceof UserAnnotation) {
270 processor.process((UserAnnotation)ann);
271 } else {
272 processor.process(ann);
273 }
274 }
275 }
276 @Override
277 protected void doError(final Throwable ex) {
278
279
280 logger.warn("Failed to load annotations from " + source.getName());
281 logger.debug("Cause",ex);
282
283 }
284 }).start();
285 }
286 }
287 }
288
289 public Test getSelftest() {
290 final TestSuite ts = new TestSuite("Annotations");
291 ts.addTest(new TestCase("Annotations") {
292 @Override
293 protected void runTest() {
294 assertEquals("Problem with cache",Status.STATUS_ALIVE,cache.getStatus());
295 }
296 });
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 return ts;
318 }
319
320
321 }