teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.context; ingo@106: teichmann@7099: import java.io.File; ingo@106: import java.util.ArrayList; gernotbelger@9555: import java.util.Collections; ingo@295: import java.util.HashMap; ingo@106: import java.util.List; ingo@295: import java.util.Map; ingo@106: ingo@106: import javax.xml.xpath.XPathConstants; ingo@106: ingo@106: import org.apache.log4j.Logger; teichmann@7099: import org.dive4elements.artifactdatabase.state.State; teichmann@7099: import org.dive4elements.artifactdatabase.state.StateEngine; teichmann@7099: import org.dive4elements.artifactdatabase.transition.Transition; teichmann@7099: import org.dive4elements.artifactdatabase.transition.TransitionEngine; teichmann@7099: import org.dive4elements.artifacts.ArtifactContextFactory; gernotbelger@9555: import org.dive4elements.artifacts.ContextInjector; teichmann@7099: import org.dive4elements.artifacts.GlobalContext; teichmann@7099: import org.dive4elements.artifacts.common.utils.Config; teichmann@7099: import org.dive4elements.artifacts.common.utils.ElementConverter; teichmann@7099: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@7099: import org.dive4elements.river.artifacts.model.Module; rrenkert@7756: import org.dive4elements.river.artifacts.model.RiverFactory; teichmann@7099: import org.dive4elements.river.artifacts.model.ZoomScale; teichmann@7099: import org.dive4elements.river.artifacts.states.StateFactory; teichmann@7099: import org.dive4elements.river.artifacts.transitions.TransitionFactory; teichmann@7226: import org.dive4elements.river.exports.GeneratorLookup; teichmann@7099: import org.dive4elements.river.exports.OutGenerator; rrenkert@7756: import org.dive4elements.river.model.River; teichmann@7099: import org.dive4elements.river.themes.Theme; teichmann@7099: import org.dive4elements.river.themes.ThemeFactory; teichmann@7099: import org.dive4elements.river.themes.ThemeGroup; teichmann@7099: import org.dive4elements.river.themes.ThemeMapping; ingo@106: import org.w3c.dom.Document; ingo@106: import org.w3c.dom.Element; ingo@295: import org.w3c.dom.Node; ingo@106: import org.w3c.dom.NodeList; ingo@106: ingo@106: /** ingo@106: * The ArtifactContextFactory is used to initialize basic components and put ingo@106: * them into the global context of the application. ingo@106: * ingo@106: * @author Ingo Weinzierl ingo@106: */ teichmann@5866: public class RiverContextFactory implements ArtifactContextFactory { ingo@106: teichmann@8202: /** The log that is used in this class. */ teichmann@8202: private static Logger log = Logger.getLogger(RiverContextFactory.class); ingo@106: ingo@106: /** The XPath to the artifacts configured in the configuration. */ gernotbelger@9555: private static final String XPATH_ARTIFACTS = "/artifact-database/artifacts/artifact"; ingo@106: ingo@106: /** The XPath to the name of the artifact. */ gernotbelger@9555: private static final String XPATH_ARTIFACT_NAME = "/artifact/@name"; ingo@106: ingo@106: /** The XPath to the xlink ref in an artifact configuration. */ gernotbelger@9555: private static final String XPATH_XLINK = "xlink:href"; ingo@106: ingo@106: /** The XPath to the transitions configured in the artifact config. */ gernotbelger@9555: private static final String XPATH_TRANSITIONS = "/artifact/states/transition"; ingo@106: ingo@107: /** The XPath to the states configured in the artifact config. */ gernotbelger@9555: private static final String XPATH_STATES = "/artifact/states/state"; raimund@2737: gernotbelger@9555: private static final String XPATH_OUTPUT_GENERATORS = "/artifact-database/output-generators//output-generator"; ingo@345: gernotbelger@9555: private static final String XPATH_THEME_CONFIG = "/artifact-database/flys/themes/configuration/text()"; ingo@958: gernotbelger@9555: private static final String XPATH_THEMES = "theme"; bjoern@3630: gernotbelger@9555: private static final String XPATH_LEGEND_GROUP = "/themes/legendgroup"; rrenkert@4619: gernotbelger@9555: private static final String XPATH_THEME_GROUPS = "/themes/themegroup"; gernotbelger@9555: gernotbelger@9555: private static final String XPATH_THEME_MAPPINGS = "/themes/mappings/mapping"; gernotbelger@9555: gernotbelger@9555: private static final String XPATH_RIVER_WMS = "/artifact-database/floodmap/river"; gernotbelger@9555: gernotbelger@9555: private static final String XPATH_MODULES = "/artifact-database/modules/module"; gernotbelger@9555: gernotbelger@9555: private static final String XPATH_ZOOM_SCALES = "/artifact-database/options/zoom-scales/zoom-scale"; gernotbelger@9555: gernotbelger@9555: private static final String XPATH_DGM_PATH = "/artifact-database/options/dgm-path/text()"; rrenkert@5152: teichmann@6933: private static GlobalContext GLOBAL_CONTEXT_INSTANCE; teichmann@6933: ingo@106: /** teichmann@5867: * Creates a new D4EArtifactContext object and initialize all ingo@106: * components required by the application. ingo@106: * gernotbelger@9555: * @param config gernotbelger@9555: * The artifact server configuration. teichmann@5867: * @return a D4EArtifactContext. ingo@106: */ christian@4656: @Override gernotbelger@9555: public GlobalContext createArtifactContext(final Document config) { gernotbelger@9555: final RiverContext context = new RiverContext(config); ingo@106: ingo@106: configureTransitions(config, context); ingo@107: configureStates(config, context); ingo@295: configureOutGenerators(config, context); ingo@341: configureThemes(config, context); ingo@345: configureThemesMappings(config, context); gernotbelger@9555: configureLegend(config, context); christian@4656: configureFloodmapWMS(config, context); bjoern@3630: configureModules(config, context); rrenkert@4619: configureZoomScales(config, context); rrenkert@5152: configureDGMPath(config, context); ingo@106: teichmann@6933: synchronized (RiverContextFactory.class) { teichmann@6933: GLOBAL_CONTEXT_INSTANCE = context; teichmann@6933: } teichmann@6933: ingo@106: return context; ingo@106: } ingo@106: teichmann@6933: public static synchronized GlobalContext getGlobalContext() { teichmann@6933: return GLOBAL_CONTEXT_INSTANCE; teichmann@6933: } teichmann@6933: gernotbelger@9555: private void configureDGMPath(final Document config, final RiverContext context) { gernotbelger@9555: final String dgmPath = (String) XMLUtils.xpath(config, XPATH_DGM_PATH, XPathConstants.STRING); rrenkert@5152: rrenkert@5152: context.put("dgm-path", dgmPath); rrenkert@5152: } rrenkert@5152: gernotbelger@9555: private void configureZoomScales(final Document config, final RiverContext context) { gernotbelger@9555: final NodeList list = (NodeList) XMLUtils.xpath(config, XPATH_ZOOM_SCALES, XPathConstants.NODESET); gernotbelger@9555: final ZoomScale scale = new ZoomScale(); rrenkert@4619: for (int i = 0; i < list.getLength(); i++) { gernotbelger@9555: final Element element = (Element) list.item(i); rrenkert@4619: String river = "default"; rrenkert@4619: double range = 0d; rrenkert@4619: double radius = 10d; rrenkert@4619: if (element.hasAttribute("river")) { rrenkert@4619: river = element.getAttribute("river"); rrenkert@4619: } rrenkert@4619: if (!element.hasAttribute("range")) { rrenkert@4619: continue; gernotbelger@9555: } else { gernotbelger@9555: final String r = element.getAttribute("range"); rrenkert@4619: try { rrenkert@4619: range = Double.parseDouble(r); rrenkert@4619: } gernotbelger@9555: catch (final NumberFormatException nfe) { rrenkert@4619: continue; rrenkert@4619: } rrenkert@4619: } rrenkert@4619: if (!element.hasAttribute("radius")) { rrenkert@4619: continue; gernotbelger@9555: } else { gernotbelger@9555: final String r = element.getAttribute("radius"); rrenkert@4619: try { rrenkert@4619: radius = Double.parseDouble(r); rrenkert@4619: } gernotbelger@9555: catch (final NumberFormatException nfe) { rrenkert@4619: continue; rrenkert@4619: } rrenkert@4619: } rrenkert@4619: scale.addRange(river, range, radius); gernotbelger@9555: } gernotbelger@9555: context.put("zoomscale", scale); rrenkert@4619: } rrenkert@4619: ingo@106: /** ingo@106: * This method initializes the transition configuration. ingo@106: * gernotbelger@9555: * @param config gernotbelger@9555: * the config document. gernotbelger@9555: * @param context gernotbelger@9555: * the RiverContext. ingo@106: */ gernotbelger@9555: private void configureTransitions(final Document config, final RiverContext context) { gernotbelger@9555: final TransitionEngine engine = new TransitionEngine(); ingo@106: gernotbelger@9555: final List artifacts = getArtifactConfigurations(config); teichmann@8202: log.info("Found " + artifacts.size() + " artifacts in the config."); ingo@106: gernotbelger@9555: for (final Document doc : artifacts) { ingo@106: gernotbelger@9555: final String artName = (String) XMLUtils.xpath(doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); ingo@106: gernotbelger@9555: final NodeList list = (NodeList) XMLUtils.xpath(doc, XPATH_TRANSITIONS, XPathConstants.NODESET); ingo@106: ingo@111: if (list == null) { gernotbelger@9555: log.warn("The artifact " + artName + " has no transitions configured."); ingo@107: continue; ingo@106: } ingo@106: gernotbelger@9555: final int trans = list.getLength(); ingo@106: gernotbelger@9555: log.info("Artifact '" + artName + "' has " + trans + " transitions."); ingo@106: ingo@106: for (int i = 0; i < trans; i++) { gernotbelger@9555: final Transition t = TransitionFactory.createTransition(list.item(i)); gernotbelger@9555: final String s = t.getFrom(); ingo@111: engine.addTransition(s, t); ingo@106: } ingo@106: } ingo@106: teichmann@5866: context.put(RiverContext.TRANSITION_ENGINE_KEY, engine); ingo@106: } ingo@106: ingo@106: /** ingo@106: * This method returns all artifact documents defined in gernotbelger@9555: * config.
gernotbelger@9555: * NOTE: The artifact configurations need to be ingo@106: * stored in own files referenced by an xlink. ingo@106: * gernotbelger@9555: * @param config gernotbelger@9555: * The global configuration. ingo@106: * ingo@106: * @return an array of Artifact configurations. ingo@106: */ gernotbelger@9555: private List getArtifactConfigurations(final Document config) { gernotbelger@9555: final NodeList artifacts = (NodeList) XMLUtils.xpath(config, XPATH_ARTIFACTS, XPathConstants.NODESET); ingo@106: gernotbelger@9555: final int count = artifacts.getLength(); ingo@106: gernotbelger@9555: final ArrayList docs = new ArrayList<>(count); ingo@106: ingo@106: for (int i = 0; i < count; i++) { gernotbelger@9555: final Element tmp = (Element) artifacts.item(i); ingo@106: ingo@106: String xlink = tmp.getAttribute(XPATH_XLINK); gernotbelger@9555: xlink = Config.replaceConfigDir(xlink); ingo@106: teichmann@8272: if (!xlink.isEmpty()) { gernotbelger@9555: final File file = new File(xlink); teichmann@8272: if (!file.isFile() || !file.canRead()) { gernotbelger@9555: log.warn("Artifact configuration '" + file + "' not found."); teichmann@8272: } else { gernotbelger@9555: final Document doc = XMLUtils.parseDocument(file); teichmann@8272: if (doc != null) { teichmann@8272: docs.add(doc); teichmann@8272: } teichmann@8272: } teichmann@8086: continue; teichmann@8086: } gernotbelger@9555: final Document doc = XMLUtils.newDocument(); gernotbelger@9555: final Node copy = doc.adoptNode(tmp.cloneNode(true)); teichmann@8272: doc.appendChild(copy); teichmann@8272: docs.add(doc); ingo@106: } teichmann@8086: return docs; ingo@106: } ingo@107: ingo@107: /** ingo@107: * This method initializes the transition configuration. ingo@107: * gernotbelger@9555: * @param config gernotbelger@9555: * the config document. gernotbelger@9555: * @param context gernotbelger@9555: * the RiverContext. ingo@107: */ gernotbelger@9555: private void configureStates(final Document config, final RiverContext context) { gernotbelger@9555: final StateEngine engine = new StateEngine(); ingo@107: gernotbelger@9555: final List artifacts = getArtifactConfigurations(config); teichmann@8202: log.info("Found " + artifacts.size() + " artifacts in the config."); ingo@107: gernotbelger@9555: for (final Document doc : artifacts) { gernotbelger@9555: final List states = new ArrayList<>(); ingo@107: gernotbelger@9555: final String artName = (String) XMLUtils.xpath(doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); ingo@107: gernotbelger@9555: final NodeList stateList = (NodeList) XMLUtils.xpath(doc, XPATH_STATES, XPathConstants.NODESET); ingo@107: ingo@107: if (stateList == null) { gernotbelger@9555: log.warn("The artifact " + artName + " has no states configured."); ingo@107: continue; ingo@107: } ingo@107: gernotbelger@9555: final int count = stateList.getLength(); ingo@107: gernotbelger@9555: log.info("Artifact '" + artName + "' has " + count + " states."); ingo@107: ingo@107: for (int i = 0; i < count; i++) { gernotbelger@9555: states.add(StateFactory.createState(stateList.item(i))); ingo@107: } ingo@107: ingo@107: engine.addStates(artName, states); ingo@107: } ingo@107: teichmann@5866: context.put(RiverContext.STATE_ENGINE_KEY, engine); ingo@107: } ingo@295: ingo@295: /** ingo@295: * This method intializes the provided output generators. ingo@295: * gernotbelger@9555: * @param config gernotbelger@9555: * the config document. gernotbelger@9555: * @param context gernotbelger@9555: * the RiverContext. ingo@295: */ gernotbelger@9555: private void configureOutGenerators(final Document config, final RiverContext context) { gernotbelger@9555: final NodeList outGenerators = (NodeList) XMLUtils.xpath(config, XPATH_OUTPUT_GENERATORS, XPathConstants.NODESET); ingo@295: gernotbelger@9555: final int num = outGenerators == null ? 0 : outGenerators.getLength(); ingo@295: ingo@295: if (num == 0) { teichmann@8202: log.warn("No output generators configured in this application."); ingo@295: return; ingo@295: } ingo@295: teichmann@8202: log.info("Found " + num + " configured output generators."); ingo@295: gernotbelger@9555: final GeneratorLookup generators = new GeneratorLookup(); teichmann@7037: ingo@295: int idx = 0; ingo@295: ingo@295: for (int i = 0; i < num; i++) { gernotbelger@9555: final Element item = (Element) outGenerators.item(i); ingo@295: gernotbelger@9555: final String names = item.getAttribute("names").trim(); gernotbelger@9555: final String clazz = item.getAttribute("class").trim(); gernotbelger@9555: final String converter = item.getAttribute("converter").trim(); gernotbelger@9555: final String injectors = item.getAttribute("injectors").trim(); ingo@295: teichmann@7074: if (names.isEmpty() || clazz.isEmpty()) { ingo@295: continue; ingo@295: } ingo@295: teichmann@7073: Class generatorClass = null; teichmann@7073: ingo@295: try { gernotbelger@9555: generatorClass = (Class) Class.forName(clazz); ingo@295: } gernotbelger@9555: catch (final ClassNotFoundException cnfe) { teichmann@8202: log.error(cnfe, cnfe); teichmann@7073: continue; teichmann@7073: } teichmann@7073: teichmann@7099: Object cfg = null; teichmann@7099: teichmann@7099: if (!converter.isEmpty()) { teichmann@7099: try { gernotbelger@9555: final ElementConverter ec = (ElementConverter) Class.forName(converter).newInstance(); teichmann@7099: cfg = ec.convert(item); teichmann@7099: } gernotbelger@9555: catch (final ClassNotFoundException cnfe) { teichmann@8202: log.error(cnfe, cnfe); teichmann@7099: } gernotbelger@9555: catch (final InstantiationException ie) { teichmann@8202: log.error(ie); teichmann@7099: } gernotbelger@9555: catch (final IllegalAccessException iae) { teichmann@8202: log.error(iae); teichmann@7099: } teichmann@7099: } teichmann@7099: teichmann@8254: List cis = null; teichmann@8219: teichmann@8254: if (!injectors.isEmpty()) { gernotbelger@9555: cis = new ArrayList<>(); gernotbelger@9555: for (final String injector : injectors.split("[\\s,]+")) { teichmann@8254: try { gernotbelger@9555: final ContextInjector ci = (ContextInjector) Class.forName(injector).newInstance(); teichmann@8254: ci.setup(item); teichmann@8254: cis.add(ci); teichmann@8254: } gernotbelger@9555: catch (final ClassNotFoundException cnfe) { teichmann@8254: log.error(cnfe, cnfe); teichmann@8254: } gernotbelger@9555: catch (final InstantiationException ie) { teichmann@8254: log.error(ie); teichmann@8254: } gernotbelger@9555: catch (final IllegalAccessException iae) { teichmann@8254: log.error(iae); teichmann@8254: } teichmann@8219: } teichmann@8219: } teichmann@8219: gernotbelger@9555: for (String key : names.split("[\\s,]+")) { teichmann@7073: if (!(key = key.trim()).isEmpty()) { teichmann@8254: generators.putGenerator(key, generatorClass, cfg, cis); teichmann@7073: idx++; teichmann@7073: } ingo@295: } ingo@295: } ingo@295: teichmann@8202: log.info("Successfully loaded " + idx + " output generators."); teichmann@5866: context.put(RiverContext.OUTGENERATORS_KEY, generators); teichmann@7227: context.put(RiverContext.FACETFILTER_KEY, generators); ingo@295: } ingo@341: ingo@341: /** ingo@341: * This methods reads the configured themes and puts them into the teichmann@5866: * RiverContext. ingo@341: * gernotbelger@9555: * @param config gernotbelger@9555: * The global configuration. gernotbelger@9555: * @param context gernotbelger@9555: * The RiverContext. ingo@341: */ gernotbelger@9555: private void configureThemes(final Document config, final RiverContext context) { teichmann@8202: log.debug("RiverContextFactory.configureThemes"); ingo@341: gernotbelger@9555: final Document cfg = getThemeConfig(config); ingo@341: gernotbelger@9555: final NodeList themeGroups = (NodeList) XMLUtils.xpath(cfg, XPATH_THEME_GROUPS, XPathConstants.NODESET); ingo@341: gernotbelger@9555: final int groupNum = themeGroups != null ? themeGroups.getLength() : 0; ingo@341: raimund@2737: if (groupNum == 0) { teichmann@8202: log.warn("There are no theme groups configured!"); ingo@341: } sascha@3256: teichmann@8202: log.info("Found " + groupNum + " theme groups in configuration"); ingo@341: gernotbelger@9555: final List groups = new ArrayList<>(); ingo@341: raimund@2737: for (int g = 0; g < groupNum; g++) { gernotbelger@9555: final Element themeGroup = (Element) themeGroups.item(g); ingo@341: gernotbelger@9555: final Map theThemes = readThemes(cfg, themeGroup); ingo@341: gernotbelger@9555: if (theThemes.size() == 0) { teichmann@8202: log.warn("There are no themes configured!"); raimund@2737: return; raimund@2737: } raimund@2737: gernotbelger@9555: final String gName = themeGroup.getAttribute("name"); raimund@2737: groups.add(new ThemeGroup(gName, theThemes)); sascha@3256: gernotbelger@9555: log.info("Initialized " + theThemes.size() + "/" + theThemes.size() + " themes " + "of theme-group '" + gName + "'"); raimund@2737: } teichmann@5866: context.put(RiverContext.THEMES, groups); ingo@341: } ingo@341: ingo@341: /** gernotbelger@9555: * This methods reads the configured themes and puts them into the gernotbelger@9555: * RiverContext. gernotbelger@9555: * gernotbelger@9555: * @param config gernotbelger@9555: * The global configuration. gernotbelger@9555: * @param context gernotbelger@9555: * The RiverContext. gernotbelger@9555: */ gernotbelger@9555: private void configureLegend(final Document config, final RiverContext context) { gernotbelger@9555: log.debug("RiverContextFactory.configureLegend"); gernotbelger@9555: gernotbelger@9555: final Map legendGroup = readLegend(config); gernotbelger@9555: context.put(RiverContext.LEGEND, legendGroup); gernotbelger@9555: } gernotbelger@9555: gernotbelger@9555: private Map readLegend(final Document config) { gernotbelger@9555: gernotbelger@9555: final Document cfg = getThemeConfig(config); gernotbelger@9555: gernotbelger@9555: final Node legendGroup = (Node) XMLUtils.xpath(cfg, XPATH_LEGEND_GROUP, XPathConstants.NODE); gernotbelger@9555: if (legendGroup == null) { gernotbelger@9555: log.warn("There is no legend group configured"); gernotbelger@9555: return Collections.emptyMap(); gernotbelger@9555: } gernotbelger@9555: gernotbelger@9555: return readThemes(cfg, legendGroup); gernotbelger@9555: } gernotbelger@9555: gernotbelger@9555: private Map readThemes(final Document cfg, final Node themeGroup) { gernotbelger@9555: final NodeList themes = (NodeList) XMLUtils.xpath(themeGroup, XPATH_THEMES, XPathConstants.NODESET); gernotbelger@9555: if (themes == null) gernotbelger@9555: return Collections.emptyMap(); gernotbelger@9555: gernotbelger@9555: final int num = themes.getLength(); gernotbelger@9555: log.info("Theme group has " + num + " themes."); gernotbelger@9555: final Map theThemes = new HashMap<>(); gernotbelger@9555: gernotbelger@9555: for (int i = 0; i < num; i++) { gernotbelger@9555: final Node theme = themes.item(i); gernotbelger@9555: gernotbelger@9555: final Theme theTheme = ThemeFactory.createTheme(cfg, theme); gernotbelger@9555: theThemes.put(theTheme.getName(), theTheme); gernotbelger@9555: } gernotbelger@9555: gernotbelger@9555: return theThemes; gernotbelger@9555: } gernotbelger@9555: gernotbelger@9555: /** ingo@341: * This method is used to retrieve the theme configuration document. ingo@341: * gernotbelger@9555: * @param config gernotbelger@9555: * The global configuration. ingo@341: * ingo@341: * @return the theme configuration. ingo@341: */ gernotbelger@9555: private Document getThemeConfig(final Document config) { gernotbelger@9555: String themeConfig = (String) XMLUtils.xpath(config, XPATH_THEME_CONFIG, XPathConstants.STRING); ingo@341: ingo@341: themeConfig = Config.replaceConfigDir(themeConfig); ingo@341: teichmann@8202: log.debug("Parse theme cfg: " + themeConfig); ingo@341: gernotbelger@9555: return XMLUtils.parseDocument(new File(themeConfig), true, XMLUtils.CONF_RESOLVER); ingo@341: } ingo@345: gernotbelger@9555: private void configureThemesMappings(final Document cfg, final RiverContext context) { teichmann@8202: log.debug("RiverContextFactory.configureThemesMappings"); ingo@345: gernotbelger@9555: final Document config = getThemeConfig(cfg); ingo@345: gernotbelger@9555: final NodeList mappings = (NodeList) XMLUtils.xpath(config, XPATH_THEME_MAPPINGS, XPathConstants.NODESET); ingo@345: gernotbelger@9555: final int num = mappings != null ? mappings.getLength() : 0; ingo@345: ingo@345: if (num == 0) { teichmann@8202: log.warn("No theme <--> facet mappins found!"); ingo@345: return; ingo@345: } ingo@345: gernotbelger@9555: final Map> mapping = new HashMap<>(); ingo@345: ingo@345: for (int i = 0; i < num; i++) { gernotbelger@9555: final Element node = (Element) mappings.item(i); ingo@345: gernotbelger@9555: final String from = node.getAttribute("from"); gernotbelger@9555: final String to = node.getAttribute("to"); gernotbelger@9555: final String pattern = node.getAttribute("pattern"); gernotbelger@9555: final String masterAttrPattern = node.getAttribute("masterAttr"); gernotbelger@9555: final String outputPattern = node.getAttribute("output"); ingo@1747: raimund@2742: if (from.length() > 0 && to.length() > 0) { ingo@1747: List tm = mapping.get(from); ingo@1747: ingo@1747: if (tm == null) { gernotbelger@9555: tm = new ArrayList<>(); ingo@1747: mapping.put(from, tm); ingo@1747: } ingo@1747: gernotbelger@9555: tm.add(new ThemeMapping(from, to, pattern, masterAttrPattern, outputPattern)); ingo@345: } ingo@345: } ingo@345: teichmann@8202: log.debug("Found " + mapping.size() + " theme mappings."); ingo@345: teichmann@5866: context.put(RiverContext.THEME_MAPPING, mapping); ingo@345: } ingo@958: christian@4656: /** christian@4656: * Reads configured floodmap river WMSs from floodmap.xml and teichmann@5866: * loads them into the given RiverContext. gernotbelger@9555: * christian@4656: * @param cfg christian@4656: * @param context christian@4656: */ gernotbelger@9555: private void configureFloodmapWMS(final Document cfg, final RiverContext context) { gernotbelger@9555: final Map riverWMS = new HashMap<>(); ingo@958: gernotbelger@9555: final NodeList rivers = (NodeList) XMLUtils.xpath(cfg, XPATH_RIVER_WMS, XPathConstants.NODESET); ingo@958: gernotbelger@9555: final int num = rivers != null ? rivers.getLength() : 0; ingo@958: ingo@958: for (int i = 0; i < num; i++) { gernotbelger@9555: final Element e = (Element) rivers.item(i); ingo@958: gernotbelger@9555: final String river = e.getAttribute("name"); gernotbelger@9555: final String url = XMLUtils.xpathString(e, "river-wms/@url", null); ingo@958: ingo@958: if (river != null && url != null) { ingo@958: riverWMS.put(river, url); ingo@958: } ingo@958: } ingo@958: teichmann@8202: log.debug("Found " + riverWMS.size() + " river WMS."); ingo@958: teichmann@5866: context.put(RiverContext.RIVER_WMS, riverWMS); ingo@958: } bjoern@3630: bjoern@3630: /** bjoern@3630: * This method initializes the modules configuration. bjoern@3630: * gernotbelger@9555: * @param config gernotbelger@9555: * the config document. gernotbelger@9555: * @param context gernotbelger@9555: * the RiverContext. bjoern@3630: */ gernotbelger@9555: private void configureModules(final Document cfg, final RiverContext context) { gernotbelger@9555: final NodeList modulenodes = (NodeList) XMLUtils.xpath(cfg, XPATH_MODULES, XPathConstants.NODESET); bjoern@3630: gernotbelger@8870: final int num = modulenodes != null ? modulenodes.getLength() : 0; gernotbelger@8870: gernotbelger@8870: final List modules = new ArrayList<>(num); bjoern@3630: bjoern@3630: for (int i = 0; i < num; i++) { gernotbelger@8870: final Element e = (Element) modulenodes.item(i); gernotbelger@8870: final String modulename = e.getAttribute("name"); gernotbelger@8870: final String attrselected = e.getAttribute("selected"); gernotbelger@8870: final boolean selected = Boolean.parseBoolean(attrselected); gernotbelger@8870: final String group = e.getAttribute("group"); gernotbelger@9555: teichmann@8202: log.debug("Loaded module " + modulename); gernotbelger@9555: gernotbelger@8870: final NodeList children = e.getChildNodes(); gernotbelger@8870: final List rivers = new ArrayList<>(children.getLength()); rrenkert@7756: for (int j = 0; j < children.getLength(); j++) { rrenkert@7756: if (children.item(j).getNodeType() != Node.ELEMENT_NODE) { rrenkert@7756: continue; rrenkert@7756: } gernotbelger@9555: gernotbelger@9555: final Element ce = (Element) children.item(j); rrenkert@7756: if (ce.hasAttribute("uuid")) { rrenkert@7756: rivers.add(ce.getAttribute("uuid")); gernotbelger@9555: } else if (ce.hasAttribute("name")) { gernotbelger@8870: final List allRivers = RiverFactory.getRivers(); gernotbelger@8870: final String name = ce.getAttribute("name"); gernotbelger@9555: for (final River r : allRivers) { rrenkert@7756: if (name.equals(r.getName())) { rrenkert@7756: rivers.add(r.getModelUuid()); rrenkert@7756: break; rrenkert@7756: } rrenkert@7756: } rrenkert@7756: } rrenkert@7756: } gernotbelger@8870: modules.add(new Module(modulename, selected, group, rivers)); bjoern@3630: } teichmann@5866: context.put(RiverContext.MODULES, modules); bjoern@3630: } gernotbelger@9555: }