comparison flys-artifacts/src/main/java/org/dive4elements/river/artifacts/context/FLYSContextFactory.java @ 5831:bd047b71ab37

Repaired internal references
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:06:39 +0200
parents flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java@b26465581abf
children
comparison
equal deleted inserted replaced
5830:160f53ee0870 5831:bd047b71ab37
1 package org.dive4elements.river.artifacts.context;
2
3 import org.dive4elements.artifactdatabase.state.State;
4 import org.dive4elements.artifactdatabase.state.StateEngine;
5 import org.dive4elements.artifactdatabase.transition.Transition;
6 import org.dive4elements.artifactdatabase.transition.TransitionEngine;
7 import org.dive4elements.artifacts.ArtifactContextFactory;
8 import org.dive4elements.artifacts.GlobalContext;
9 import org.dive4elements.artifacts.common.utils.Config;
10 import org.dive4elements.artifacts.common.utils.XMLUtils;
11 import org.dive4elements.river.artifacts.model.Module;
12 import org.dive4elements.river.artifacts.model.ZoomScale;
13 import org.dive4elements.river.artifacts.states.StateFactory;
14 import org.dive4elements.river.artifacts.transitions.TransitionFactory;
15 import org.dive4elements.river.themes.Theme;
16 import org.dive4elements.river.themes.ThemeFactory;
17 import org.dive4elements.river.themes.ThemeGroup;
18 import org.dive4elements.river.themes.ThemeMapping;
19
20 import java.io.File;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.xml.xpath.XPathConstants;
27
28 import org.apache.log4j.Logger;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.Node;
32 import org.w3c.dom.NodeList;
33
34
35 /**
36 * The ArtifactContextFactory is used to initialize basic components and put
37 * them into the global context of the application.
38 *
39 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
40 */
41 public class FLYSContextFactory implements ArtifactContextFactory {
42
43 /** The logger that is used in this class. */
44 private static Logger logger = Logger.getLogger(FLYSContextFactory.class);
45
46 /** The XPath to the artifacts configured in the configuration. */
47 public static final String XPATH_ARTIFACTS =
48 "/artifact-database/artifacts/artifact";
49
50 /** The XPath to the name of the artifact. */
51 public static final String XPATH_ARTIFACT_NAME = "/artifact/@name";
52
53 /** The XPath to the xlink ref in an artifact configuration. */
54 public static final String XPATH_XLINK = "xlink:href";
55
56 /** The XPath to the transitions configured in the artifact config. */
57 public static final String XPATH_TRANSITIONS =
58 "/artifact/states/transition";
59
60 /** The XPath to the states configured in the artifact config. */
61 public static final String XPATH_STATES =
62 "/artifact/states/state";
63
64 public static final String XPATH_OUTPUT_GENERATORS =
65 "/artifact-database/output-generators/output-generator";
66
67 public static final String XPATH_THEME_CONFIG =
68 "/artifact-database/flys/themes/configuration/text()";
69
70 public static final String XPATH_THEMES =
71 "theme";
72
73 public static final String XPATH_THEME_GROUPS =
74 "/themes/themegroup";
75
76 public static final String XPATH_THEME_MAPPINGS =
77 "/themes/mappings/mapping";
78
79 public static final String XPATH_RIVER_WMS =
80 "/artifact-database/floodmap/river";
81
82 public static final String XPATH_MODULES = "/artifact-database/modules/module";
83
84 private static final String XPATH_ZOOM_SCALES = "/artifact-database/options/zoom-scales/zoom-scale";
85
86 private static final String XPATH_DGM_PATH = "/artifact-database/options/dgm-path/text()";
87
88
89 /**
90 * Creates a new FLYSArtifactContext object and initialize all
91 * components required by the application.
92 *
93 * @param config The artifact server configuration.
94 * @return a FLYSArtifactContext.
95 */
96 @Override
97 public GlobalContext createArtifactContext(Document config) {
98 FLYSContext context = new FLYSContext(config);
99
100 configureTransitions(config, context);
101 configureStates(config, context);
102 configureOutGenerators(config, context);
103 configureThemes(config, context);
104 configureThemesMappings(config, context);
105 configureFloodmapWMS(config, context);
106 configureModules(config, context);
107 configureZoomScales(config, context);
108 configureDGMPath(config, context);
109
110 return context;
111 }
112
113
114 private void configureDGMPath(Document config, FLYSContext context) {
115 String dgmPath = (String) XMLUtils.xpath(
116 config,
117 XPATH_DGM_PATH,
118 XPathConstants.STRING);
119
120 context.put("dgm-path", dgmPath);
121 }
122
123
124 protected void configureZoomScales(Document config, FLYSContext context) {
125 NodeList list = (NodeList)XMLUtils.xpath(
126 config,
127 XPATH_ZOOM_SCALES,
128 XPathConstants.NODESET);
129 ZoomScale scale = new ZoomScale();
130 for (int i = 0; i < list.getLength(); i++) {
131 Element element = (Element)list.item(i);
132 String river = "default";
133 double range = 0d;
134 double radius = 10d;
135 if (element.hasAttribute("river")) {
136 river = element.getAttribute("river");
137 }
138 if (!element.hasAttribute("range")) {
139 continue;
140 }
141 else {
142 String r = element.getAttribute("range");
143 try {
144 range = Double.parseDouble(r);
145 }
146 catch (NumberFormatException nfe) {
147 continue;
148 }
149 }
150 if (!element.hasAttribute("radius")) {
151 continue;
152 }
153 else {
154 String r = element.getAttribute("radius");
155 try {
156 radius = Double.parseDouble(r);
157 }
158 catch (NumberFormatException nfe) {
159 continue;
160 }
161 }
162 scale.addRange(river, range, radius);
163 }
164 context.put("zoomscale", scale);
165 }
166
167
168 /**
169 * This method initializes the transition configuration.
170 *
171 * @param config the config document.
172 * @param context the FLYSContext.
173 */
174 protected void configureTransitions(Document config, FLYSContext context) {
175 TransitionEngine engine = new TransitionEngine();
176
177 Document[] artifacts = getArtifactConfigurations(config);
178 logger.info("Found " + artifacts.length + " artifacts in the config.");
179
180 for (Document doc: artifacts) {
181
182 String artName = (String) XMLUtils.xpath(
183 doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING);
184
185 NodeList list = (NodeList) XMLUtils.xpath(
186 doc, XPATH_TRANSITIONS, XPathConstants.NODESET);
187
188 if (list == null) {
189 logger.warn("The artifact " + artName +
190 " has no transitions configured.");
191 continue;
192 }
193
194 int trans = list.getLength();
195
196 logger.info(
197 "Artifact '" + artName + "' has " + trans + " transitions.");
198
199 for (int i = 0; i < trans; i++) {
200 Transition t = TransitionFactory.createTransition(list.item(i));
201 String s = t.getFrom();
202 engine.addTransition(s, t);
203 }
204 }
205
206 context.put(FLYSContext.TRANSITION_ENGINE_KEY, engine);
207 }
208
209
210 /**
211 * This method returns all artifact documents defined in
212 * <code>config</code>. <br>NOTE: The artifact configurations need to be
213 * stored in own files referenced by an xlink.
214 *
215 * @param config The global configuration.
216 *
217 * @return an array of Artifact configurations.
218 */
219 protected Document[] getArtifactConfigurations(Document config) {
220 NodeList artifacts = (NodeList) XMLUtils.xpath(
221 config, XPATH_ARTIFACTS, XPathConstants.NODESET);
222
223 int count = artifacts.getLength();
224
225 Document[] artifactDocs = new Document[count];
226
227 for (int i = 0; i < count; i++) {
228 Element tmp = (Element) artifacts.item(i);
229
230 String xlink = tmp.getAttribute(XPATH_XLINK);
231 xlink = Config.replaceConfigDir(xlink);
232
233 File artifactFile = new File(xlink);
234 artifactDocs[i] = XMLUtils.parseDocument(artifactFile);
235 }
236
237 return artifactDocs;
238 }
239
240
241 /**
242 * This method initializes the transition configuration.
243 *
244 * @param config the config document.
245 * @param context the FLYSContext.
246 */
247 protected void configureStates(Document config, FLYSContext context) {
248 StateEngine engine = new StateEngine();
249
250 Document[] artifacts = getArtifactConfigurations(config);
251 logger.info("Found " + artifacts.length + " artifacts in the config.");
252
253 for (Document doc: artifacts) {
254 List<State> states = new ArrayList<State>();
255
256 String artName = (String) XMLUtils.xpath(
257 doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING);
258
259 NodeList stateList = (NodeList) XMLUtils.xpath(
260 doc, XPATH_STATES, XPathConstants.NODESET);
261
262 if (stateList == null) {
263 logger.warn("The artifact " + artName +
264 " has no states configured.");
265 continue;
266 }
267
268 int count = stateList.getLength();
269
270 logger.info(
271 "Artifact '" + artName + "' has " + count + " states.");
272
273 for (int i = 0; i < count; i++) {
274 states.add(StateFactory.createState(
275 stateList.item(i)));
276 }
277
278 engine.addStates(artName, states);
279 }
280
281 context.put(FLYSContext.STATE_ENGINE_KEY, engine);
282 }
283
284
285 /**
286 * This method intializes the provided output generators.
287 *
288 * @param config the config document.
289 * @param context the FLYSContext.
290 */
291 protected void configureOutGenerators(Document config, FLYSContext context){
292 Map<String, Class<?>> generators = new HashMap<String, Class<?>>();
293
294 NodeList outGenerators = (NodeList) XMLUtils.xpath(
295 config,
296 XPATH_OUTPUT_GENERATORS,
297 XPathConstants.NODESET);
298
299 int num = outGenerators == null ? 0 : outGenerators.getLength();
300
301 if (num == 0) {
302 logger.warn("No output generators configured in this application.");
303 return;
304 }
305
306 logger.info("Found " + num + " configured output generators.");
307
308 int idx = 0;
309
310 for (int i = 0; i < num; i++) {
311 Node item = outGenerators.item(i);
312
313 String name = (String) XMLUtils.xpath(
314 item, "@name", XPathConstants.STRING);
315
316 String clazz = (String) XMLUtils.xpath(
317 item, "text()", XPathConstants.STRING);
318
319 if (name == null || clazz == null) {
320 continue;
321 }
322
323 try {
324 generators.put(name, Class.forName(clazz));
325
326 idx++;
327 }
328 catch (ClassNotFoundException cnfe) {
329 logger.warn(cnfe, cnfe);
330 }
331 }
332
333 logger.info("Successfully loaded " + idx + " output generators.");
334 context.put(FLYSContext.OUTGENERATORS_KEY, generators);
335 }
336
337
338 /**
339 * This methods reads the configured themes and puts them into the
340 * FLYSContext.
341 *
342 * @param config The global configuration.
343 * @param context The FLYSContext.
344 */
345 protected void configureThemes(Document config, FLYSContext context) {
346 logger.debug("FLYSContextFactory.configureThemes");
347
348 Document cfg = getThemeConfig(config);
349
350 NodeList themeGroups = (NodeList) XMLUtils.xpath(
351 cfg, XPATH_THEME_GROUPS, XPathConstants.NODESET);
352
353 int groupNum = themeGroups != null ? themeGroups.getLength() : 0;
354
355 if (groupNum == 0) {
356 logger.warn("There are no theme groups configured!");
357 }
358
359 logger.info("Found " + groupNum + " theme groups in configuration");
360
361 List<ThemeGroup> groups = new ArrayList<ThemeGroup>();
362
363 for (int g = 0; g < groupNum; g++) {
364 Element themeGroup = (Element) themeGroups.item(g);
365 NodeList themes = (NodeList) XMLUtils.xpath(
366 themeGroup, XPATH_THEMES, XPathConstants.NODESET);
367
368 int num = themes != null ? themes.getLength() : 0;
369
370 if (num == 0) {
371 logger.warn("There are no themes configured!");
372 return;
373 }
374
375 logger.info("Theme group has " + num + " themes.");
376
377 Map<String, Theme> theThemes = new HashMap<String, Theme>();
378
379 for (int i = 0; i < num; i++) {
380 Node theme = themes.item(i);
381
382 Theme theTheme = ThemeFactory.createTheme(cfg, theme);
383
384 if (theme != null) {
385 theThemes.put(theTheme.getName(), theTheme);
386 }
387 }
388 String gName = themeGroup.getAttribute("name");
389 groups.add(new ThemeGroup(gName, theThemes));
390
391 logger.info(
392 "Initialized " + theThemes.size() + "/" + num + " themes " +
393 "of theme-group '" + gName + "'");
394 }
395 context.put(FLYSContext.THEMES, groups);
396 }
397
398 /**
399 * This method is used to retrieve the theme configuration document.
400 *
401 * @param config The global configuration.
402 *
403 * @return the theme configuration.
404 */
405 protected Document getThemeConfig(Document config) {
406 String themeConfig = (String) XMLUtils.xpath(
407 config,
408 XPATH_THEME_CONFIG,
409 XPathConstants.STRING);
410
411 themeConfig = Config.replaceConfigDir(themeConfig);
412
413 logger.debug("Parse theme cfg: " + themeConfig);
414
415 return XMLUtils.parseDocument(new File(themeConfig));
416 }
417
418
419 protected void configureThemesMappings(Document cfg, FLYSContext context) {
420 logger.debug("FLYSContextFactory.configureThemesMappings");
421
422 Document config = getThemeConfig(cfg);
423
424 NodeList mappings = (NodeList) XMLUtils.xpath(
425 config, XPATH_THEME_MAPPINGS, XPathConstants.NODESET);
426
427 int num = mappings != null ? mappings.getLength() : 0;
428
429 if (num == 0) {
430 logger.warn("No theme <--> facet mappins found!");
431 return;
432 }
433
434 Map<String, List<ThemeMapping>> mapping =
435 new HashMap<String, List<ThemeMapping>>();
436
437 for (int i = 0; i < num; i++) {
438 Element node = (Element)mappings.item(i);
439
440 String from = node.getAttribute("from");
441 String to = node.getAttribute("to");
442 String pattern = node.getAttribute("pattern");
443 String masterAttrPattern = node.getAttribute("masterAttr");
444 String outputPattern = node.getAttribute("output");
445
446 if (from.length() > 0 && to.length() > 0) {
447 List<ThemeMapping> tm = mapping.get(from);
448
449 if (tm == null) {
450 tm = new ArrayList<ThemeMapping>();
451 mapping.put(from, tm);
452 }
453
454 tm.add(new ThemeMapping(
455 from, to, pattern, masterAttrPattern, outputPattern));
456 }
457 }
458
459 logger.debug("Found " + mapping.size() + " theme mappings.");
460
461 context.put(FLYSContext.THEME_MAPPING, mapping);
462 }
463
464
465 /**
466 * Reads configured floodmap river WMSs from floodmap.xml and
467 * loads them into the given FLYSContext.
468 * @param cfg
469 * @param context
470 */
471 protected void configureFloodmapWMS(Document cfg, FLYSContext context) {
472 Map<String, String> riverWMS = new HashMap<String, String>();
473
474 NodeList rivers = (NodeList) XMLUtils.xpath(
475 cfg, XPATH_RIVER_WMS, XPathConstants.NODESET);
476
477 int num = rivers != null ? rivers.getLength() : 0;
478
479 for (int i = 0; i < num; i++) {
480 Element e = (Element) rivers.item(i);
481
482 String river = e.getAttribute("name");
483 String url = XMLUtils.xpathString(e, "river-wms/@url", null);
484
485 if (river != null && url != null) {
486 riverWMS.put(river, url);
487 }
488 }
489
490 logger.debug("Found " + riverWMS.size() + " river WMS.");
491
492 context.put(FLYSContext.RIVER_WMS, riverWMS);
493 }
494
495
496 /**
497 * This method initializes the modules configuration.
498 *
499 * @param config the config document.
500 * @param context the FLYSContext.
501 */
502 protected void configureModules(Document cfg, FLYSContext context) {
503 NodeList modulenodes = (NodeList) XMLUtils.xpath(
504 cfg, XPATH_MODULES, XPathConstants.NODESET);
505
506 int num = modulenodes != null ? modulenodes.getLength() : 0;
507 ArrayList<Module> modules = new ArrayList<Module>(num);
508
509 for (int i = 0; i < num; i++) {
510 Element e = (Element) modulenodes.item(i);
511 String modulename = e.getAttribute("name");
512 String attrselected = e.getAttribute("selected");
513 boolean selected = attrselected == null ? false :
514 attrselected.equalsIgnoreCase("true");
515 logger.debug("Loaded module " + modulename);
516 modules.add(new Module(modulename, selected));
517 }
518 context.put(FLYSContext.MODULES, modules);
519 }
520 }
521 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org