Mercurial > dive4elements > framework
comparison artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java @ 32:c2d53bd30ab8
Re-factored artifact API for better integration of background processing.
artifacts/trunk@78 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 13 Sep 2009 14:50:53 +0000 |
parents | 83a059c204f8 |
children | f7d2cd59a0d5 |
comparison
equal
deleted
inserted
replaced
31:c4d85a8532d1 | 32:c2d53bd30ab8 |
---|---|
1 package de.intevation.artifactdatabase; | 1 package de.intevation.artifactdatabase; |
2 | 2 |
3 import java.util.HashMap; | 3 import java.util.HashMap; |
4 | 4 import java.util.HashSet; |
5 import java.util.ArrayList; | |
6 import java.util.List; | |
7 | |
8 import de.intevation.artifacts.ArtifactDatabaseException; | |
5 import de.intevation.artifacts.ArtifactDatabase; | 9 import de.intevation.artifacts.ArtifactDatabase; |
6 import de.intevation.artifacts.ArtifactFactory; | 10 import de.intevation.artifacts.ArtifactFactory; |
7 import de.intevation.artifacts.Artifact; | 11 import de.intevation.artifacts.Artifact; |
12 import de.intevation.artifacts.CallContext; | |
13 | |
14 import de.intevation.artifactdatabase.Backend.PersistentArtifact; | |
15 | |
16 import org.apache.log4j.Logger; | |
17 | |
18 import org.w3c.dom.Document; | |
19 | |
20 import java.io.OutputStream; | |
21 import java.io.IOException; | |
8 | 22 |
9 /** | 23 /** |
10 * @author Sascha L. Teichmann | 24 * @author Sascha L. Teichmann |
11 */ | 25 */ |
12 public class ArtifactDatabaseImpl | 26 public class ArtifactDatabaseImpl |
13 implements ArtifactDatabase | 27 implements ArtifactDatabase, Id.Filter |
14 { | 28 { |
15 protected String [] factoryNames; | 29 private static Logger logger = |
16 protected HashMap name2factory; | 30 Logger.getLogger(ArtifactDatabaseImpl.class); |
17 | 31 |
18 protected Backend backend; | 32 public static final String NO_SUCH_FACTORY = |
19 protected Object context; | 33 "No such factory"; |
34 | |
35 public static final String NO_SUCH_ARTIFACT = | |
36 "No such artifact"; | |
37 | |
38 public static final String NOT_IN_BACKGROUND = | |
39 "Not in background"; | |
40 | |
41 public static final String INVALID_CALL_STATE = | |
42 "Invalid after call state"; | |
43 | |
44 public static final String CREATION_FAILED = | |
45 "Creation of artifact failed"; | |
46 | |
47 public static final String INTERNAL_ERROR = | |
48 "Creation of artifact failed"; | |
49 | |
50 public class CallContextImpl | |
51 implements CallContext | |
52 { | |
53 protected PersistentArtifact artifact; | |
54 protected int action; | |
55 | |
56 public CallContextImpl(PersistentArtifact artifact, int action) { | |
57 this.artifact = artifact; | |
58 this.action = action; | |
59 } | |
60 | |
61 public void afterCall(int action) { | |
62 this.action = action; | |
63 if (action == BACKGROUND) { | |
64 addIdToBackground(artifact.getId()); | |
65 } | |
66 } | |
67 | |
68 public void afterBackground(int action) { | |
69 if (this.action != BACKGROUND) { | |
70 throw new IllegalStateException(NOT_IN_BACKGROUND); | |
71 } | |
72 fromBackground(artifact, action); | |
73 } | |
74 | |
75 public Object globalContext() { | |
76 return context; | |
77 } | |
78 | |
79 public void postCall() { | |
80 switch (action) { | |
81 case NOTHING: | |
82 break; | |
83 case TOUCH: | |
84 artifact.touch(); | |
85 break; | |
86 case STORE: | |
87 artifact.store(); | |
88 break; | |
89 case BACKGROUND: | |
90 logger.warn("BACKGROUND processing is not fully implemented, yet!"); | |
91 artifact.store(); | |
92 break; | |
93 default: | |
94 logger.error(INVALID_CALL_STATE + ": " + action); | |
95 throw new IllegalStateException(INVALID_CALL_STATE); | |
96 } | |
97 } | |
98 } // class CallContextImpl | |
99 | |
100 public class DeferredOutputImpl | |
101 implements DeferredOutput | |
102 { | |
103 protected PersistentArtifact artifact; | |
104 protected Document format; | |
105 | |
106 public DeferredOutputImpl() { | |
107 } | |
108 | |
109 public DeferredOutputImpl( | |
110 PersistentArtifact artifact, | |
111 Document format | |
112 ) { | |
113 this.artifact = artifact; | |
114 this.format = format; | |
115 } | |
116 | |
117 public void write(OutputStream output) throws IOException { | |
118 | |
119 CallContextImpl cc = new CallContextImpl( | |
120 artifact, CallContext.TOUCH); | |
121 | |
122 try { | |
123 artifact.getArtifact().out(format, output, cc); | |
124 } | |
125 finally { | |
126 cc.postCall(); | |
127 } | |
128 } | |
129 } // class DeferredOutputImpl | |
130 | |
131 protected String [][] factoryNamesAndDescription; | |
132 protected HashMap name2factory; | |
133 | |
134 protected Backend backend; | |
135 protected Object context; | |
136 | |
137 protected HashSet backgroundIds; | |
20 | 138 |
21 public ArtifactDatabaseImpl() { | 139 public ArtifactDatabaseImpl() { |
22 } | 140 } |
23 | 141 |
24 public ArtifactDatabaseImpl(FactoryBootstrap bootstrap, Backend backend) { | 142 public ArtifactDatabaseImpl(FactoryBootstrap bootstrap, Backend backend) { |
25 name2factory = new HashMap(); | 143 |
144 backgroundIds = new HashSet(); | |
145 name2factory = new HashMap(); | |
26 | 146 |
27 ArtifactFactory [] factories = bootstrap.getArtifactFactories(); | 147 ArtifactFactory [] factories = bootstrap.getArtifactFactories(); |
28 factoryNames = new String[factories.length]; | 148 factoryNamesAndDescription = new String[factories.length][]; |
29 | 149 |
30 for (int i = 0; i < factories.length; ++i) { | 150 for (int i = 0; i < factories.length; ++i) { |
151 | |
31 ArtifactFactory factory = factories[i]; | 152 ArtifactFactory factory = factories[i]; |
32 name2factory.put(factoryNames[i] = factory.getName(), factory); | 153 |
154 String name = factory.getName(); | |
155 String description = factory.getDescription(); | |
156 | |
157 factoryNamesAndDescription[i] = | |
158 new String [] { name, description }; | |
159 | |
160 name2factory.put(name, factory); | |
33 } | 161 } |
34 | 162 |
35 context = bootstrap.getContext(); | 163 context = bootstrap.getContext(); |
36 | 164 |
37 this.backend = backend; | 165 this.backend = backend; |
38 } | 166 } |
39 | 167 |
40 public String [] getArtifactFactoryNames() { | 168 protected void fromBackground(PersistentArtifact artifact, int action) { |
41 return factoryNames; | 169 logger.warn("BACKGROUND processing is not fully implemented, yet!"); |
42 } | 170 switch (action) { |
43 | 171 case CallContext.NOTHING: |
44 public Artifact getArtifact(String identifier) { | 172 break; |
45 return backend.getArtifact(identifier); | 173 case CallContext.TOUCH: |
46 } | 174 artifact.touch(); |
47 | 175 break; |
48 public Artifact createArtifactWithFactory(String factoryName) { | 176 case CallContext.STORE: |
49 ArtifactFactory factory = (ArtifactFactory)name2factory.get(factoryName); | 177 artifact.store(); |
50 return factory == null | 178 break; |
51 ? null | 179 default: |
52 : backend.createArtifactWithFactory(factory, context); | 180 logger.warn("operation not allowed in fromBackground"); |
53 } | 181 } |
54 | 182 removeIdFromBackground(artifact.getId()); |
55 public Object getArtifactContext() { | 183 } |
56 return context; | 184 |
185 protected void removeIdFromBackground(int id) { | |
186 synchronized (backgroundIds) { | |
187 backgroundIds.remove(Integer.valueOf(id)); | |
188 } | |
189 } | |
190 | |
191 protected void addIdToBackground(int id) { | |
192 synchronized (backgroundIds) { | |
193 backgroundIds.add(Integer.valueOf(id)); | |
194 } | |
195 } | |
196 | |
197 public List filterIds(List ids) { | |
198 int N = ids.size(); | |
199 ArrayList out = new ArrayList(N); | |
200 synchronized (backgroundIds) { | |
201 for (int i = 0; i < N; ++i) { | |
202 Id id = (Id)ids.get(i); | |
203 if (!backgroundIds.contains(Integer.valueOf(id.getId()))) { | |
204 out.add(id); | |
205 } | |
206 } | |
207 } | |
208 return out; | |
209 } | |
210 | |
211 public String [][] artifactFactoryNamesAndDescriptions() { | |
212 return factoryNamesAndDescription; | |
213 } | |
214 | |
215 public Document createArtifactWithFactory(String factoryName) | |
216 throws ArtifactDatabaseException | |
217 { | |
218 ArtifactFactory factory = (ArtifactFactory)name2factory.get( | |
219 factoryName); | |
220 | |
221 if (factory == null) { | |
222 throw new ArtifactDatabaseException(NO_SUCH_FACTORY); | |
223 } | |
224 | |
225 Artifact artifact = factory.createArtifact( | |
226 backend.newIdentifier(), | |
227 context); | |
228 | |
229 if (artifact == null) { | |
230 throw new ArtifactDatabaseException(CREATION_FAILED); | |
231 } | |
232 | |
233 PersistentArtifact persistentArtifact; | |
234 | |
235 try { | |
236 persistentArtifact = backend.storeInitially( | |
237 artifact, | |
238 factory.timeToLiveUntouched(artifact, context)); | |
239 } | |
240 catch (Exception e) { | |
241 logger.error(e.getLocalizedMessage(), e); | |
242 throw new ArtifactDatabaseException(CREATION_FAILED); | |
243 } | |
244 | |
245 CallContextImpl cc = new CallContextImpl( | |
246 persistentArtifact, CallContext.NOTHING); | |
247 | |
248 try { | |
249 return artifact.describe(cc); | |
250 } | |
251 finally { | |
252 cc.postCall(); | |
253 } | |
254 } | |
255 | |
256 public Document describe(String identifier) | |
257 throws ArtifactDatabaseException | |
258 { | |
259 // TODO: Handle background tasks | |
260 PersistentArtifact artifact = backend.getArtifact(identifier); | |
261 | |
262 if (artifact == null) { | |
263 throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); | |
264 } | |
265 | |
266 CallContextImpl cc = new CallContextImpl( | |
267 artifact, CallContext.TOUCH); | |
268 | |
269 try { | |
270 return artifact.getArtifact().describe(cc); | |
271 } | |
272 finally { | |
273 cc.postCall(); | |
274 } | |
275 } | |
276 | |
277 public Document advance(String identifier, Document target) | |
278 throws ArtifactDatabaseException | |
279 { | |
280 // TODO: Handle background tasks | |
281 PersistentArtifact artifact = backend.getArtifact(identifier); | |
282 | |
283 if (artifact == null) { | |
284 throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); | |
285 } | |
286 | |
287 CallContextImpl cc = new CallContextImpl( | |
288 artifact, CallContext.STORE); | |
289 | |
290 try { | |
291 return artifact.getArtifact().advance(target, cc); | |
292 } | |
293 finally { | |
294 cc.postCall(); | |
295 } | |
296 } | |
297 | |
298 public Document feed(String identifier, Document data) | |
299 throws ArtifactDatabaseException | |
300 { | |
301 // TODO: Handle background tasks | |
302 PersistentArtifact artifact = backend.getArtifact(identifier); | |
303 | |
304 if (artifact == null) { | |
305 throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); | |
306 } | |
307 | |
308 CallContextImpl cc = new CallContextImpl( | |
309 artifact, CallContext.STORE); | |
310 | |
311 try { | |
312 return artifact.getArtifact().advance(data, cc); | |
313 } | |
314 finally { | |
315 cc.postCall(); | |
316 } | |
317 } | |
318 | |
319 public DeferredOutput out(String identifier, Document format) | |
320 throws ArtifactDatabaseException | |
321 { | |
322 // TODO: Handle background tasks | |
323 PersistentArtifact artifact = backend.getArtifact(identifier); | |
324 | |
325 if (artifact == null) { | |
326 throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); | |
327 } | |
328 | |
329 return new DeferredOutputImpl(artifact, format); | |
57 } | 330 } |
58 } | 331 } |
59 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: | 332 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: |