comparison artifacts/src/main/java/org/dive4elements/river/artifacts/context/RiverContextFactory.java @ 5866:9a6741ccf6d4

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

http://dive4elements.wald.intevation.org