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:

http://dive4elements.wald.intevation.org