001: //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/ogcwebservices/wfs/XMLFactory.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: 53115 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.ogcwebservices.wfs;
044:
045: import java.io.IOException;
046: import java.net.URI;
047: import java.net.URL;
048:
049: import org.deegree.datatypes.xlink.SimpleLink;
050: import org.deegree.enterprise.DeegreeParams;
051: import org.deegree.framework.log.ILogger;
052: import org.deegree.framework.log.LoggerFactory;
053: import org.deegree.framework.xml.XMLTools;
054: import org.deegree.i18n.Messages;
055: import org.deegree.model.filterencoding.capabilities.FilterCapabilities;
056: import org.deegree.model.metadata.iso19115.Keywords;
057: import org.deegree.model.metadata.iso19115.Linkage;
058: import org.deegree.model.metadata.iso19115.OnlineResource;
059: import org.deegree.model.spatialschema.Envelope;
060: import org.deegree.model.spatialschema.Position;
061: import org.deegree.ogcbase.CommonNamespaces;
062: import org.deegree.ogcwebservices.getcapabilities.DCPType;
063: import org.deegree.ogcwebservices.getcapabilities.HTTP;
064: import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
065: import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
066: import org.deegree.ogcwebservices.getcapabilities.Protocol;
067: import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
068: import org.deegree.ogcwebservices.getcapabilities.ServiceProvider;
069: import org.deegree.ogcwebservices.wfs.capabilities.FeatureTypeList;
070: import org.deegree.ogcwebservices.wfs.capabilities.Operation;
071: import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
072: import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType;
073: import org.deegree.ogcwebservices.wfs.capabilities.WFSOperationsMetadata;
074: import org.deegree.ogcwebservices.wfs.configuration.WFSConfiguration;
075: import org.w3c.dom.Element;
076:
077: /**
078: * Responsible for the generation of XML representations of objects from the WFS context.
079: *
080: * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
081: *
082: * @author last edited by: $Author:$
083: *
084: * @version $Revision:$, $Date:$
085: *
086: */
087:
088: public class XMLFactory_1_0_0 {
089:
090: private static final URI WFSNS = CommonNamespaces.WFSNS;
091:
092: private static final String PRE_WFS = CommonNamespaces.WFS_PREFIX
093: + ":";
094:
095: private static final ILogger LOG = LoggerFactory
096: .getLogger(XMLFactory_1_0_0.class);
097:
098: private static XMLFactory_1_0_0 factory = null;
099:
100: /**
101: * @return a cached instance of this XMLFactory.
102: */
103: public static synchronized XMLFactory_1_0_0 getInstance() {
104: if (factory == null) {
105: factory = new XMLFactory_1_0_0();
106: }
107: return factory;
108: }
109:
110: /**
111: * Exports a <code>WFSCapabilities</code> instance to a <code>WFSCapabilitiesDocument</code>
112: * with version 1_0.
113: *
114: * @param config
115: * @return DOM representation of the <code>WFSCapabilities</code>
116: * @throws IOException
117: * if XML template could not be loaded
118: */
119: public WFSCapabilitiesDocument export(WFSConfiguration config) {
120:
121: WFSCapabilitiesDocument capabilitiesDocument = new WFSCapabilitiesDocument();
122:
123: capabilitiesDocument.createEmptyDocument("1.0.0");
124: Element root = capabilitiesDocument.getRootElement();
125:
126: // Find the default online resource
127: DeegreeParams deegreeParams = config.getDeegreeParams();
128: String defaultOnlineResource = "http://localhost:8080/deegree/services";
129: if (deegreeParams != null) {
130: OnlineResource or = deegreeParams
131: .getDefaultOnlineResource();
132: if (or != null) {
133: Linkage link = or.getLinkage();
134: if (link != null) {
135: URL uri = link.getHref();
136: if (uri != null) {
137: String tmp = uri.toExternalForm();
138: if (!"".equals(tmp.toString())) {
139: defaultOnlineResource = tmp;
140: }
141: }
142: }
143: }
144: }
145:
146: ServiceIdentification serviceIdentification = config
147: .getServiceIdentification();
148: ServiceProvider serviceProvider = config.getServiceProvider();
149: OperationsMetadata operationsMetadata = config
150: .getOperationsMetadata();
151: FeatureTypeList featureTypeList = config.getFeatureTypeList();
152:
153: if (serviceIdentification != null) {
154: String onlineResource = null;
155: if (serviceProvider != null) {
156: SimpleLink resource = serviceProvider.getProviderSite();
157: URI online = resource.getHref();
158: onlineResource = online.toASCIIString();
159: } else {
160: onlineResource = defaultOnlineResource;
161: }
162: appendService(root, serviceIdentification, onlineResource);
163: }
164:
165: // Add the capabilities element
166: if (operationsMetadata != null) {
167: appendCapability(root,
168: (WFSOperationsMetadata) operationsMetadata,
169: defaultOnlineResource);
170: }
171:
172: if (featureTypeList != null) {
173: appendFeatureTypeList(root, featureTypeList);
174: }
175:
176: FilterCapabilities filterCapabilities = config
177: .getFilterCapabilities();
178: if (filterCapabilities != null) {
179: org.deegree.model.filterencoding.XMLFactory
180: .appendFilterCapabilities100(root,
181: filterCapabilities);
182: }
183: return capabilitiesDocument;
184: }
185:
186: /**
187: * Appends the DOM representation of the {@link ServiceIdentification} section to the passed
188: * {@link Element}.
189: *
190: * @param root
191: * to which to append the service section.
192: * @param serviceIdentification
193: * bean of the service identification element.
194: * @param onlineResource
195: * to be used as a default onlineResource.
196: */
197: private void appendService(Element root,
198: ServiceIdentification serviceIdentification,
199: String onlineResource) {
200:
201: // 'Service'-element
202: Element service = XMLTools.appendElement(root, WFSNS, PRE_WFS
203: + "Service");
204:
205: // 'Name'-element
206: String tmpValue = serviceIdentification.getName();
207: tmpValue = checkForEmptyValue(tmpValue, PRE_WFS + "Name", "WFS");
208: XMLTools.appendElement(service, WFSNS, PRE_WFS + "Name",
209: tmpValue);
210:
211: tmpValue = serviceIdentification.getTitle();
212: tmpValue = checkForEmptyValue(tmpValue, PRE_WFS + "Title",
213: "A Web Feature Service");
214: XMLTools.appendElement(service, WFSNS, PRE_WFS + "Title",
215: tmpValue);
216:
217: tmpValue = serviceIdentification.getAbstract();
218: if (tmpValue != null && "".equals(tmpValue.trim())) {
219: XMLTools.appendElement(service, WFSNS,
220: PRE_WFS + "Abstract", tmpValue);
221: }
222:
223: Keywords[] keywords = serviceIdentification.getKeywords();
224: appendKeyWords(service, keywords);
225:
226: XMLTools.appendElement(service, WFSNS, PRE_WFS
227: + "OnlineResource", onlineResource);
228:
229: tmpValue = serviceIdentification.getFees();
230: if (tmpValue == null || "".equals(tmpValue.trim())) {
231: tmpValue = "NONE";
232: }
233: XMLTools.appendElement(service, WFSNS, PRE_WFS + "Fees",
234: tmpValue);
235:
236: String[] constraints = serviceIdentification
237: .getAccessConstraints();
238: StringBuffer sb = new StringBuffer();
239: if (constraints == null || constraints.length > 0) {
240: sb.append("NONE");
241: } else {
242: for (int i = 0; i < constraints.length; ++i) {
243: String constraint = constraints[i];
244: if (constraint != null && "".equals(constraint.trim())) {
245: sb.append(constraint);
246: if ((i + 1) < constraints.length) {
247: sb.append(" ");
248: }
249: }
250: }
251: if (sb.length() == 0) {
252: sb.append("NONE");
253: }
254: }
255: XMLTools.appendElement(service, WFSNS, PRE_WFS
256: + "AccessConstraints", sb.toString());
257:
258: }
259:
260: /**
261: * Appends the wfs:Capability element to the root element
262: *
263: * @param root
264: * @param operationsMetadata
265: */
266: private void appendCapability(Element root,
267: WFSOperationsMetadata operationsMetadata,
268: String defaultOnlineResource) {
269: Element capability = XMLTools.appendElement(root, WFSNS,
270: PRE_WFS + "Capability");
271: Element request = XMLTools.appendElement(capability, WFSNS,
272: PRE_WFS + "Request");
273: org.deegree.ogcwebservices.getcapabilities.Operation[] ops = operationsMetadata
274: .getOperations();
275: if (ops != null && ops.length > 0) {
276: for (org.deegree.ogcwebservices.getcapabilities.Operation op : ops) {
277: String name = op.getName();
278: if (!(name == null || "".equals(name.trim()) || "GetGMLObject"
279: .equals(name.trim()))) {
280: name = name.trim();
281:
282: Element operation = XMLTools.appendElement(request,
283: WFSNS, PRE_WFS + name);
284: if ("DescribeFeatureType".equalsIgnoreCase(name)) {
285: Element sdl = XMLTools.appendElement(operation,
286: WFSNS, PRE_WFS
287: + "SchemaDescriptionLanguage");
288: XMLTools.appendElement(sdl, WFSNS, PRE_WFS
289: + "XMLSCHEMA");
290: } else if ("GetFeature".equalsIgnoreCase(name)
291: || "GetFeatureWithLock"
292: .equalsIgnoreCase(name)) {
293: Element resultFormat = XMLTools.appendElement(
294: operation, WFSNS, PRE_WFS
295: + "ResultFormat");
296: XMLTools.appendElement(resultFormat, WFSNS,
297: PRE_WFS + "GML2");
298: }
299: DCPType[] dcpTypes = op.getDCPs();
300: if (dcpTypes != null && dcpTypes.length > 0) {
301: for (DCPType dcpType : dcpTypes) {
302: appendDCPType(operation, dcpType,
303: defaultOnlineResource);
304: }
305: } else {
306: appendDCPType(operation, null,
307: defaultOnlineResource);
308: }
309: }
310: }
311: }
312:
313: }
314:
315: /**
316: * Appends the XML representation of the <code>wfs:FeatureTypeList</code>- section to the
317: * passed <code>Element</code>.
318: *
319: * @param root
320: * @param featureTypeList
321: */
322: private void appendFeatureTypeList(Element root,
323: FeatureTypeList featureTypeList) {
324: Element featureTypeListNode = XMLTools.appendElement(root,
325: WFSNS, PRE_WFS + "FeatureTypeList");
326: Operation[] operations = featureTypeList.getGlobalOperations();
327: if (operations != null) {
328: Element operationsNode = XMLTools.appendElement(
329: featureTypeListNode, WFSNS, PRE_WFS + "Operations");
330: for (int i = 0; i < operations.length; i++) {
331: XMLTools.appendElement(operationsNode, WFSNS, PRE_WFS
332: + operations[i].getOperation());
333: }
334: }
335: WFSFeatureType[] featureTypes = featureTypeList
336: .getFeatureTypes();
337: if (featureTypes != null) {
338: for (int i = 0; i < featureTypes.length; i++) {
339: appendWFSFeatureType(featureTypeListNode,
340: featureTypes[i]);
341: }
342: }
343: }
344:
345: /**
346: * Appends the DCPType in the WFS namespace... pre-ows stuff.
347: *
348: * @param operation
349: * to add the dcptype to.
350: * @param type
351: * a bean containing necessary information if <code>null</code> a http-get/post dcp
352: * with the defaultonline resource will be inserted.
353: * @param defaultOnlineResource
354: * if no dcpType is given or no URL were inserted in the config, this will be
355: * inserted.
356: */
357: private void appendDCPType(Element operation, DCPType type,
358: String defaultOnlineResource) {
359: Element dcpType = XMLTools.appendElement(operation, WFSNS,
360: PRE_WFS + "DCPType");
361: Element http = XMLTools.appendElement(dcpType, WFSNS, PRE_WFS
362: + "HTTP");
363: boolean appendDefaultProtocol = true;
364: if (type != null) {
365: Protocol pr = type.getProtocol();
366: if (pr != null) {
367: if (pr instanceof HTTP) {
368: HTTP prot = (HTTP) pr;
369: URL[] getters = prot.getGetOnlineResources();
370: URL[] posters = prot.getPostOnlineResources();
371: if ((getters != null && getters.length > 0)) {
372: for (URL get : getters) {
373: appendGetURL(http, get.toExternalForm());
374: }
375: } else {
376: appendGetURL(http, defaultOnlineResource);
377: }
378: if (posters != null && posters.length > 0) {
379: for (URL post : posters) {
380: appendPostURL(http, post.toExternalForm());
381: }
382: } else {
383: appendPostURL(http, defaultOnlineResource);
384: }
385: appendDefaultProtocol = false;
386: }
387: }
388: }
389: if (appendDefaultProtocol) {
390: appendGetURL(http, defaultOnlineResource);
391: appendPostURL(http, defaultOnlineResource);
392: }
393: }
394:
395: private void appendGetURL(Element http, String resourceURL) {
396: Element get = XMLTools.appendElement(http, WFSNS, PRE_WFS
397: + "Get");
398: get.setAttribute("onlineResource", resourceURL);
399: }
400:
401: private void appendPostURL(Element http, String resourceURL) {
402: Element post = XMLTools.appendElement(http, WFSNS, PRE_WFS
403: + "Post");
404: post.setAttribute("onlineResource", resourceURL);
405: }
406:
407: private void appendKeyWords(Element root, Keywords[] keywords) {
408: if (keywords != null && keywords.length > 0) {
409: StringBuffer sb = new StringBuffer();
410: for (int k = 0; k < keywords.length; ++k) {
411: String[] words = keywords[k].getKeywords();
412: if (words != null && words.length > 0) {
413: for (int i = 0; i < words.length; ++i) {
414: sb.append(words[i]);
415: if ((i + 1) < words.length) {
416: sb.append(" ");
417: }
418: }
419: }
420: if ((k + 1) < keywords.length) {
421: sb.append(" ");
422: }
423: }
424: XMLTools.appendElement(root, WFSNS, PRE_WFS + "Keywords",
425: sb.toString());
426: }
427: }
428:
429: /**
430: * Appends the XML representation of the <code>WFSFeatureType</code> instance to the passed
431: * <code>Element</code>.
432: *
433: * @param root
434: * @param featureType
435: */
436: private void appendWFSFeatureType(Element root,
437: WFSFeatureType featureType) {
438:
439: Element featureTypeNode = XMLTools.appendElement(root, WFSNS,
440: PRE_WFS + "FeatureType");
441:
442: if (featureType.getName().getPrefix() != null) {
443: XMLTools.appendNSBinding(featureTypeNode, featureType
444: .getName().getPrefix(), featureType.getName()
445: .getNamespace());
446: }
447: XMLTools.appendElement(featureTypeNode, WFSNS,
448: PRE_WFS + "Name", featureType.getName()
449: .getPrefixedName());
450: XMLTools.appendElement(featureTypeNode, WFSNS, PRE_WFS
451: + "Title", featureType.getTitle());
452: String tmpValue = featureType.getAbstract();
453: if (tmpValue != null && !"".equals(tmpValue.trim())) {
454: XMLTools.appendElement(featureTypeNode, WFSNS, PRE_WFS
455: + "Abstract", tmpValue);
456: }
457: Keywords[] keywords = featureType.getKeywords();
458: appendKeyWords(featureTypeNode, keywords);
459:
460: URI defaultSrs = featureType.getDefaultSRS();
461: if (defaultSrs != null) {
462: XMLTools.appendElement(featureTypeNode, WFSNS, PRE_WFS
463: + "SRS", defaultSrs.toASCIIString());
464: } else if (featureType.getOtherSrs() != null
465: && featureType.getOtherSrs().length > 0) {
466: for (URI srs : featureType.getOtherSrs()) {
467: if (srs != null) {
468: XMLTools.appendElement(featureTypeNode, WFSNS,
469: PRE_WFS + "SRS", srs.toASCIIString());
470: break;
471: }
472: }
473: } else {
474: // defaulting to EPSG:4326 is this correct????
475: LOG
476: .logDebug("Found no default- or other-SRS, setting to EPGS:4326, is this correct?");
477: XMLTools.appendElement(featureTypeNode, WFSNS, PRE_WFS
478: + "SRS", "EPSG:4326");
479: }
480: Operation[] operations = featureType.getOperations();
481: if (operations != null && operations.length > 0) {
482: for (Operation op : operations) {
483: if (op != null
484: && !"".equals(op.getOperation().trim())
485: && !"GetGMLObject".equalsIgnoreCase(op
486: .getOperation().trim())) {
487: Element opEl = XMLTools.appendElement(
488: featureTypeNode, WFSNS, PRE_WFS
489: + "Operations");
490: XMLTools.appendElement(opEl, WFSNS, PRE_WFS
491: + op.getOperation().trim());
492:
493: }
494: }
495: }
496:
497: Envelope[] wgs84BoundingBoxes = featureType
498: .getWgs84BoundingBoxes();
499: for (Envelope bbox : wgs84BoundingBoxes) {
500: if (bbox != null
501: && bbox.getMin().getCoordinateDimension() == 2) {
502: Element latlon = XMLTools.appendElement(
503: featureTypeNode, WFSNS, PRE_WFS
504: + "LatLongBoundingBox");
505: Position min = bbox.getMin();
506: Position max = bbox.getMax();
507: latlon
508: .setAttribute("minx", Double.toString(min
509: .getX()));
510: latlon
511: .setAttribute("miny", Double.toString(min
512: .getY()));
513: latlon
514: .setAttribute("maxx", Double.toString(max
515: .getX()));
516: latlon
517: .setAttribute("maxy", Double.toString(max
518: .getY()));
519: }
520: }
521: MetadataURL[] mdURLs = featureType.getMetadataUrls();
522: if (mdURLs != null) {
523: for (MetadataURL mdURL : mdURLs) {
524: if (mdURL != null && mdURL.getOnlineResource() != null) {
525: // first check if the format and type are acceptable.
526: String format = mdURL.getFormat();
527: boolean formatOK = false;
528: if (format != null && !"".equals(format.trim())) {
529: format = format.trim();
530: if ("XML".equals(format)
531: || "SGML".equals(format)
532: || "TXT".equals(format)) {
533: formatOK = true;
534: }
535: }
536:
537: String type = mdURL.getType();
538: boolean typeOK = false;
539: if (formatOK && type != null
540: && !"".equals(type.trim())) {
541: type = type.trim();
542: if ("TC211".equals(type) || "FGDC".equals(type)) {
543: typeOK = true;
544: }
545: }
546: if (formatOK && typeOK) {
547: Element metadata = XMLTools.appendElement(
548: featureTypeNode, WFSNS, PRE_WFS
549: + "MetadataURL", mdURL
550: .getOnlineResource()
551: .toExternalForm());
552: metadata.setAttribute("type", type);
553: metadata.setAttribute("format", format);
554: }
555: }
556: }
557: }
558: }
559:
560: private String checkForEmptyValue(String value, String elementName,
561: String defaultValue) {
562: if (value == null || "".equals(value.trim())) {
563: LOG.logError(Messages.getMessage(
564: "WFS_MISSING_REQUIRED_ELEMENT", elementName));
565: value = defaultValue;
566: }
567: return value;
568: }
569: }
|