001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/tools/wms/WFS2WMS.java $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstr. 19
030: 53177 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042: ---------------------------------------------------------------------------*/
043: package org.deegree.tools.wms;
044:
045: import static org.deegree.i18n.Messages.getMessage;
046:
047: import java.io.File;
048: import java.io.FileOutputStream;
049: import java.net.URL;
050: import java.util.ArrayList;
051: import java.util.HashMap;
052: import java.util.List;
053: import java.util.Map;
054: import java.util.Properties;
055:
056: import org.deegree.datatypes.QualifiedName;
057: import org.deegree.framework.log.ILogger;
058: import org.deegree.framework.log.LoggerFactory;
059: import org.deegree.framework.util.ColorUtils;
060: import org.deegree.framework.xml.NamespaceContext;
061: import org.deegree.framework.xml.XMLFragment;
062: import org.deegree.framework.xml.XMLParsingException;
063: import org.deegree.framework.xml.XMLTools;
064: import org.deegree.framework.xml.XSLTDocument;
065: import org.deegree.graphics.sld.AbstractLayer;
066: import org.deegree.graphics.sld.NamedLayer;
067: import org.deegree.graphics.sld.StyleFactory;
068: import org.deegree.graphics.sld.StyledLayerDescriptor;
069: import org.deegree.graphics.sld.UserStyle;
070: import org.deegree.ogcbase.CommonNamespaces;
071: import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
072: import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
073: import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
074: import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType;
075: import org.w3c.dom.Node;
076:
077: /**
078: * Creates a deegree WMS configuration document or a Layer section from a WFS capabilities document.
079: * The datasource type for each layer will be LOCALWFS. Also a style with random color(s) will be
080: * created, assigned to the layers and stored in a xml document named $OUTFILE_BASE$_styles.xml.
081: * TODO support for usage of an already existing WMS configuration document TODO determine geometry
082: * types of the feature types registered within the wfs capabilities document
083: *
084: *
085: * @version $Revision: 10424 $
086: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
087: * @author last edited by: $Author: rbezema $
088: *
089: * @version $Revision: 10424 $, $Date: 2008-03-05 00:36:30 -0800 (Wed, 05 Mar 2008) $
090: *
091: */
092: public class WFS2WMS {
093:
094: private static NamespaceContext nsc = CommonNamespaces
095: .getNamespaceContext();
096:
097: private ILogger LOG = LoggerFactory.getLogger(WFS2WMS.class);
098:
099: private URL xsl = WFS2WMS.class.getResource("wfs2wms.xsl");
100:
101: private Properties prop = null;
102:
103: /**
104: * Create an instance with given properties
105: * @param prop to use
106: */
107: public WFS2WMS(Properties prop) {
108: this .prop = prop;
109: }
110:
111: /**
112: * @param node to retrieve the minimum x value from.
113: * @return the minimum y value or -180 if not found
114: */
115: public static double getMinX(Node node) {
116: double v = -180;
117: try {
118: String s = XMLTools.getNodeAsString(node, ".", nsc,
119: "-180 -90");
120: String[] t = s.split(" ");
121: v = Double.parseDouble(t[0]);
122: } catch (XMLParsingException e) {
123: e.printStackTrace();
124: }
125: return v;
126: }
127:
128: /**
129: * @param node to retrieve the minimum y value from.
130: * @return the maximum y value or -90 if not found
131: */
132: public static double getMinY(Node node) {
133: double v = -90;
134: try {
135: String s = XMLTools.getNodeAsString(node, ".", nsc,
136: "-180 -90");
137: String[] t = s.split(" ");
138: v = Double.parseDouble(t[1]);
139: } catch (XMLParsingException e) {
140: e.printStackTrace();
141: }
142: return v;
143: }
144:
145: /**
146: * @param node to retrieve the maximum x value from.
147: * @return the maximum x value or 180 if not found
148: */
149: public static double getMaxX(Node node) {
150: double v = 180;
151: try {
152: String s = XMLTools.getNodeAsString(node, ".", nsc,
153: "180 90");
154: String[] t = s.split(" ");
155: v = Double.parseDouble(t[0]);
156: } catch (XMLParsingException e) {
157: e.printStackTrace();
158: }
159: return v;
160: }
161:
162: /**
163: * @param node to retrieve the maximum y value from.
164: * @return the maximum y value or 90 if not found
165: */
166: public static double getMaxY(Node node) {
167: double v = 90;
168: try {
169: String s = XMLTools.getNodeAsString(node, ".", nsc,
170: "180 90");
171: String[] t = s.split(" ");
172: v = Double.parseDouble(t[1]);
173: } catch (XMLParsingException e) {
174: e.printStackTrace();
175: }
176: return v;
177: }
178:
179: /**
180: * append all required namespace definition to the root element
181: *
182: * @param xml
183: * @return
184: * @throws InvalidCapabilitiesException
185: */
186: private XMLFragment addNamespaces(XMLFragment wms,
187: WFSCapabilities capa) {
188: WFSFeatureType[] fts = capa.getFeatureTypeList()
189: .getFeatureTypes();
190: for (int i = 0; i < fts.length; i++) {
191: QualifiedName qn = fts[i].getName();
192: XMLTools.appendNSBinding(wms.getRootElement(), qn
193: .getPrefix(), qn.getNamespace());
194: }
195: return wms;
196: }
197:
198: /**
199: * creates a style for each feature type registered in a WFS capabilities document
200: *
201: * @param wfs
202: * @return
203: */
204: private List<UserStyle> createStyles(WFSCapabilities capa) {
205: List<UserStyle> styles = new ArrayList<UserStyle>();
206: Map<QualifiedName, Integer> types = determineGeometryType(capa);
207:
208: WFSFeatureType[] fts = capa.getFeatureTypeList()
209: .getFeatureTypes();
210:
211: UserStyle st = null;
212: for (int i = 0; i < fts.length; i++) {
213: QualifiedName qn = fts[i].getName();
214: int type = types.get(qn);
215: switch (type) {
216: case 1: {
217: st = (UserStyle) StyleFactory.createPointStyle(
218: "square", ColorUtils.getRandomColor(false),
219: ColorUtils.getRandomColor(false), 1, 1, 10, 10,
220: 0, Double.MAX_VALUE);
221: break;
222: }
223: case 2: {
224: st = (UserStyle) StyleFactory.createLineStyle(
225: ColorUtils.getRandomColor(false), 4, 1, 0,
226: Double.MAX_VALUE);
227: break;
228: }
229:
230: case 3: {
231: st = (UserStyle) StyleFactory.createPolygonStyle(
232: ColorUtils.getRandomColor(false), 1, ColorUtils
233: .getRandomColor(false), 1, 1, 0,
234: Double.MAX_VALUE);
235: break;
236: }
237: }
238: st.setName("default:" + qn.getPrefixedName());
239: styles.add(st);
240: }
241:
242: return styles;
243: }
244:
245: /**
246: *
247: * @param styles
248: * @return
249: */
250: private StyledLayerDescriptor createSLD(List<UserStyle> styles) {
251:
252: UserStyle[] us = styles.toArray(new UserStyle[styles.size()]);
253: NamedLayer nl = new NamedLayer("defaultstyle", null, us);
254: return new StyledLayerDescriptor(new AbstractLayer[] { nl },
255: "1.0.0");
256:
257: }
258:
259: /**
260: * returns the geometry type of each feature type registered within the passed WFS capabilities
261: * document<br>
262: * <ul>
263: * <li>1 = point or multi point
264: * <li>2 = curve or multi curve
265: * <li>3 = surface or multi surface
266: * </ul>
267: *
268: * @param capa
269: * @return
270: */
271: private Map<QualifiedName, Integer> determineGeometryType(
272: WFSCapabilities capa) {
273:
274: Map<QualifiedName, Integer> types = new HashMap<QualifiedName, Integer>();
275:
276: WFSFeatureType[] fts = capa.getFeatureTypeList()
277: .getFeatureTypes();
278: for (int i = 0; i < fts.length; i++) {
279: QualifiedName qn = fts[i].getName();
280: // TODO
281: // get real geometry type
282: types.put(qn, 3);
283: }
284:
285: return types;
286: }
287:
288: /**
289: * Run the conversion
290: *
291: * @throws Exception
292: */
293: public void run() throws Exception {
294:
295: String out = prop.getProperty("-outFile");
296: File file = new File(out);
297: int pos = file.getName().lastIndexOf('.');
298: String styleDoc = file.getName().substring(0, pos)
299: + "_styles.xml";
300:
301: HashMap<String, String> param = new HashMap<String, String>();
302: param.put("PARENTLAYER", prop.getProperty("-parentLayer"));
303: param.put("MINX", prop.getProperty("-minx"));
304: param.put("MINY", prop.getProperty("-miny"));
305: param.put("MAXX", prop.getProperty("-maxx"));
306: param.put("MAXY", prop.getProperty("-maxy"));
307: param.put("SRS", prop.getProperty("-srs"));
308: if ("true".equals(prop.getProperty("-full"))) {
309: param.put("WMSCAPS", "1");
310: }
311: param.put("STYLEDOC", styleDoc);
312:
313: LOG.logInfo("XSLT-parameter: ", param);
314:
315: XSLTDocument outXSLSheet = new XSLTDocument();
316: outXSLSheet.load(xsl);
317:
318: file = new File(prop.getProperty("-wfsCaps"));
319: param.put("WFSCAPS", file.toURL().toExternalForm());
320: XMLFragment doc = new XMLFragment();
321: doc.load(file.toURL());
322:
323: XMLFragment resultDocument = outXSLSheet.transform(doc, null,
324: null, param);
325:
326: WFSCapabilitiesDocument wfsdoc = new WFSCapabilitiesDocument();
327: wfsdoc.setRootElement(doc.getRootElement());
328: WFSCapabilities capa = (WFSCapabilities) wfsdoc
329: .parseCapabilities();
330:
331: resultDocument = addNamespaces(resultDocument, capa);
332:
333: List<UserStyle> styles = createStyles(capa);
334: StyledLayerDescriptor sld = createSLD(styles);
335:
336: String s = prop.getProperty("-outFile").replace(".xml",
337: "_styles.xml");
338: file = new File(s);
339: FileOutputStream fos = new FileOutputStream(file);
340: fos.write(sld.exportAsXML().getBytes());
341: fos.close();
342:
343: file = new File(prop.getProperty("-outFile"));
344: fos = new FileOutputStream(file);
345: resultDocument.write(fos);
346: fos.close();
347: }
348:
349: private static void validate(Properties map) throws Exception {
350: if (map.get("-parentLayer") == null) {
351: throw new Exception(getMessage("WFS2WMS.validate_2"));
352: }
353: if (map.get("-minx") != null) {
354: Double.parseDouble(map.getProperty("-minx"));
355: } else {
356: map.put("-minx", "-180");
357: }
358: if (map.get("-miny") != null) {
359: Double.parseDouble(map.getProperty("-miny"));
360: } else {
361: map.put("-miny", "-90");
362: }
363: if (map.get("-maxx") != null) {
364: Double.parseDouble(map.getProperty("-maxx"));
365: } else {
366: map.put("-maxx", "180");
367: }
368: if (map.get("-maxy") != null) {
369: Double.parseDouble(map.getProperty("-maxy"));
370: } else {
371: map.put("-maxy", "90");
372: }
373: if (map.get("-srs") == null) {
374: map.put("-srs", "EPSG:4326");
375: }
376: if (map.get("-wfsCaps") == null) {
377: throw new Exception(getMessage("WFS2WMS.validate_0"));
378: }
379: if (map.get("-outFile") == null) {
380: throw new Exception(getMessage("WFS2WMS.validate_1"));
381: }
382: }
383:
384: /**
385: * @param args
386: * @throws Exception if the conversion could not be fulfilled
387: */
388: public static void main(String[] args) throws Exception {
389:
390: Properties map = new Properties();
391: for (int i = 0; i < args.length; i += 2) {
392: System.out.println(args[i + 1]);
393: map.put(args[i], args[i + 1]);
394: }
395:
396: try {
397: validate(map);
398: } catch (Exception e) {
399: System.out.println("!!! E R R O R !!!");
400: System.out.println(e.getMessage());
401: System.out
402: .println("----------------------------------------------------");
403: System.out.println(getMessage("WFS2WMS.parentLayer"));
404: System.out.println(getMessage("WFS2WMS.wfsCaps"));
405: System.out.println(getMessage("WFS2WMS.outFile"));
406: return;
407: }
408:
409: WFS2WMS wfs2wms = new WFS2WMS(map);
410: wfs2wms.run();
411:
412: }
413:
414: }
|