001 // $HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/ogcbase/XMLFactory.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036 package org.deegree.ogcbase;
037
038 import java.io.ByteArrayInputStream;
039 import java.net.URI;
040
041 import org.deegree.datatypes.CodeList;
042 import org.deegree.datatypes.time.TimeDuration;
043 import org.deegree.datatypes.time.TimePeriod;
044 import org.deegree.datatypes.time.TimePosition;
045 import org.deegree.datatypes.time.TimeSequence;
046 import org.deegree.datatypes.values.Interval;
047 import org.deegree.datatypes.values.TypedLiteral;
048 import org.deegree.datatypes.values.Values;
049 import org.deegree.datatypes.xlink.SimpleLink;
050 import org.deegree.framework.log.ILogger;
051 import org.deegree.framework.log.LoggerFactory;
052 import org.deegree.framework.util.StringTools;
053 import org.deegree.framework.util.TimeTools;
054 import org.deegree.framework.xml.XMLFragment;
055 import org.deegree.framework.xml.XMLTools;
056 import org.deegree.model.crs.CoordinateSystem;
057 import org.deegree.model.metadata.iso19115.Keywords;
058 import org.deegree.model.metadata.iso19115.OnlineResource;
059 import org.deegree.model.spatialschema.Envelope;
060 import org.deegree.model.spatialschema.GMLGeometryAdapter;
061 import org.deegree.model.spatialschema.Geometry;
062 import org.deegree.model.spatialschema.GeometryException;
063 import org.deegree.ogcwebservices.LonLatEnvelope;
064 import org.w3c.dom.Element;
065 import org.w3c.dom.Node;
066 import org.w3c.dom.Text;
067
068 /**
069 * Factory for creating <code>DOM</code> representations from java objects used to represent OGC
070 * related schema types.
071 *
072 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
073 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
074 * @author last edited by: $Author: mschneider $
075 *
076 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
077 */
078 public class XMLFactory {
079
080 protected static final ILogger LOG = LoggerFactory.getLogger( XMLFactory.class );
081
082 protected static final URI OGCNS = CommonNamespaces.OGCNS;
083
084 protected static final URI GMLNS = CommonNamespaces.GMLNS;
085
086 protected static final URI XLNNS = CommonNamespaces.XLNNS;
087
088 /**
089 * Appends the <code>DOM</code> representation of a <code>LonLatEnvelope</code> to the
090 * passed <code>Element</code>.
091 *
092 * @param root
093 * @param lonLatEnvelope
094 * @param namespaceURI
095 */
096 protected static void appendLonLatEnvelope( Element root, LonLatEnvelope lonLatEnvelope, URI namespaceURI ) {
097 Element lonLatEnvelopeElement = XMLTools.appendElement( root, namespaceURI, "lonLatEnvelope" );
098 //lonLatEnvelopeElement.setAttribute( "srsName", "WGS84(DD)" );
099 lonLatEnvelopeElement.setAttribute( "srsName", lonLatEnvelope.getSrs() );
100 String min = lonLatEnvelope.getMin().getX() + " " + lonLatEnvelope.getMin().getY();
101 Element elem = XMLTools.appendElement( lonLatEnvelopeElement, GMLNS, "gml:pos", min );
102 elem.setAttribute( "dimension", "2" );
103 String max = lonLatEnvelope.getMax().getX() + " " + lonLatEnvelope.getMax().getY();
104 elem = XMLTools.appendElement( lonLatEnvelopeElement, GMLNS, "gml:pos", max );
105 elem.setAttribute( "dimension", "2" );
106 TimePosition[] tpos = lonLatEnvelope.getTimePositions();
107 if ( tpos != null ) {
108 for ( int i = 0; i < tpos.length; i++ ) {
109 appendTimePosition( lonLatEnvelopeElement, tpos[i] );
110 }
111 }
112 }
113
114 /**
115 * Appends an <code>XML/GML Envelope</code> -element to the passed <code>Element</code>.
116 *
117 * @param xmlNode
118 * @param envelope
119 */
120 protected static void appendEnvelope( Element xmlNode, Envelope envelope ) {
121 Element node = XMLTools.appendElement( xmlNode, GMLNS, "gml:Envelope" );
122 CoordinateSystem crs = envelope.getCoordinateSystem();
123 if ( crs != null ) {
124 try {
125 node.setAttribute( "srsName", crs.getIdentifier() );
126 } catch ( Exception e ) {
127 e.printStackTrace();
128 }
129 }
130 Element env = node;
131
132 String min = envelope.getMin().getX() + " " + envelope.getMin().getY();
133 node = XMLTools.appendElement( env, GMLNS, "gml:pos", min );
134 node.setAttribute( "dimension", "2" );
135
136 String max = envelope.getMax().getX() + " " + envelope.getMax().getY();
137 node = XMLTools.appendElement( env, GMLNS, "gml:pos", max );
138 node.setAttribute( "dimension", "2" );
139 }
140
141 /**
142 * Appends the <code>XML/GML</code> representation of a <code>TimePosition</code> to the
143 * passed <code>Element</code>.
144 *
145 * @param xmlNode
146 * @param tpos
147 */
148 protected static void appendTimePosition( Element xmlNode, TimePosition tpos ) {
149 if ( tpos != null ) {
150 String s = TimeTools.getISOFormattedTime( tpos.getTime() );
151 Element element = XMLTools.appendElement( xmlNode, GMLNS, "gml:timePosition", s );
152 element.setAttribute( "calendarEraName", tpos.getCalendarEraName() );
153 element.setAttribute( "frame", tpos.getFrame().toString() );
154 element.setAttribute( "indeterminatePosition", tpos.getIndeterminatePosition().value );
155 }
156 }
157
158 /**
159 * Appends a <code>keywords</code> -element for each <code>Keywords</code> object of the
160 * passed array to the passed <code>Element</code>.
161 *
162 * @param xmlNode
163 * @param keywords
164 * @param namespaceURI
165 */
166 protected static void appendKeywords( Element xmlNode, Keywords[] keywords, URI namespaceURI ) {
167 if ( keywords != null ) {
168 for ( int i = 0; i < keywords.length; i++ ) {
169 Element node = XMLTools.appendElement( xmlNode, namespaceURI, "keywords" );
170 appendKeywords( node, keywords[i], namespaceURI );
171 }
172 }
173 }
174
175 /**
176 * Appends a <code>keywords</code> -element to the passed <code>Element</code> and fills it
177 * with the available keywords.
178 *
179 * @param xmlNode
180 * @param keywords
181 * @param namespaceURI
182 */
183 protected static void appendKeywords( Element xmlNode, Keywords keywords, URI namespaceURI ) {
184 if ( keywords != null ) {
185 String[] kw = keywords.getKeywords();
186 for ( int i = 0; i < kw.length; i++ ) {
187 XMLTools.appendElement( xmlNode, namespaceURI, "keyword", kw[i] );
188 }
189 if ( keywords.getThesaurusName() != null ) {
190 XMLTools.appendElement( xmlNode, namespaceURI, "type", keywords.getThesaurusName() );
191 }
192 }
193 }
194
195 /**
196 * Appends an <code>XML</code> representation of the passed <code>TimeSequence</code> to the
197 * passed <code>Element</code>.
198 *
199 * @param xmlNode
200 * @param timeSeq
201 * @param namespaceURI
202 */
203 protected static void appendTemporalDomain( Element xmlNode, TimeSequence timeSeq, URI namespaceURI ) {
204 if ( timeSeq != null ) {
205 Element node = XMLTools.appendElement( xmlNode, namespaceURI, "temporalDomain", null );
206 TimePeriod[] tPer = timeSeq.getTimePeriod();
207 if ( tPer != null ) {
208 for ( int i = 0; i < tPer.length; i++ ) {
209 appendTimePeriod( node, tPer[i], namespaceURI );
210 }
211 }
212
213 TimePosition[] tPos = timeSeq.getTimePosition();
214 if ( tPos != null ) {
215 for ( int i = 0; i < tPos.length; i++ ) {
216 appendTimePosition( node, tPos[i] );
217 }
218 }
219 }
220 }
221
222 /**
223 * Appends an <code>XML</code> representation of the passed <code>TimePeriod</code> to the
224 * passed <code>Element</code>.
225 *
226 * @param xmlNode
227 * @param tPeriod
228 * @param namespaceURI
229 */
230 protected static void appendTimePeriod( Element xmlNode, TimePeriod tPeriod, URI namespaceURI ) {
231 Element node = XMLTools.appendElement( xmlNode, namespaceURI, "timePeriod" );
232 appendTimePosition( node, tPeriod.getBeginPosition() );
233 appendTimePosition( node, tPeriod.getEndPosition() );
234 appendTimeResolution( node, tPeriod.getTimeResolution() );
235 }
236
237 /**
238 * Appends an <code>XML/GML</code> representation of the passed <code>TimeDuration</code> to
239 * the passed <code>Element</code>.
240 *
241 * @param xmlNode
242 * @param duration
243 */
244 protected static void appendTimeResolution( Element xmlNode, TimeDuration duration ) {
245 XMLTools.appendElement( xmlNode, GMLNS, "gml:timeResolution", duration.getAsGMLTimeDuration() );
246 }
247
248 /**
249 * Appends an <code>XML</code> representation of the passed <code>Values</code> to the
250 * passed <code>Element</code>.
251 *
252 * @param xmlNode
253 * @param values
254 * @param namespaceURI
255 */
256 protected static void appendValues( Element xmlNode, Values values, URI namespaceURI ) {
257 Element node = XMLTools.appendElement( xmlNode, namespaceURI, "values" );
258 if ( values.getType() != null ) {
259 node.setAttribute( "type", values.getType().toString() );
260 }
261 if ( values.getSemantic() != null ) {
262 node.setAttribute( "xmlns:dgr", namespaceURI.toString() );
263 node.setAttributeNS( namespaceURI.toString(), "dgr:semantic", values.getSemantic().toString() );
264 }
265 Interval[] intervals = values.getInterval();
266 if ( intervals != null ) {
267 for ( int i = 0; i < intervals.length; i++ ) {
268 appendInterval( node, intervals[i], namespaceURI );
269 }
270 }
271 TypedLiteral[] sVal = values.getSingleValue();
272 if ( sVal != null ) {
273 for ( int i = 0; i < sVal.length; i++ ) {
274 appendTypedLiteral( node, sVal[i], "singleValue", namespaceURI );
275 }
276 }
277 }
278
279 /**
280 * Appends an <code>XML</code> representation of the passed <code>Interval</code> to the
281 * passed <code>Element</code>.
282 *
283 * @param xmlNode
284 * @param interval
285 * @param namespaceURI
286 */
287 protected static void appendInterval( Element xmlNode, Interval interval, URI namespaceURI ) {
288 Element node = XMLTools.appendElement( xmlNode, namespaceURI, "interval" );
289 Element inter = node;
290 if ( interval.getType() != null ) {
291 node.setAttribute( "type", interval.getType().toString() );
292 }
293
294 if ( interval.getSemantic() != null ) {
295 node.setAttribute( "xmlns:dgr", namespaceURI.toString() );
296 node.setAttributeNS( namespaceURI.toString(), "dgr:semantic", interval.getSemantic().toString() );
297 }
298 node.setAttribute( "atomic", "" + interval.isAtomic() );
299 if ( interval.getClosure() != null && interval.getClosure().value != "" && interval.getClosure().value != null ) {
300 node.setAttribute( "xmlns:dgr", namespaceURI.toString() );
301 node.setAttributeNS( namespaceURI.toString(), "dgr:closure", interval.getClosure().value );
302 }
303 node = XMLTools.appendElement( inter, namespaceURI, "min", interval.getMin().getValue() );
304 if ( interval.getMin().getType() != null ) {
305 node.setAttribute( "type", interval.getMin().getType().toString() );
306 }
307 node = XMLTools.appendElement( inter, namespaceURI, "max", interval.getMin().getValue() );
308 if ( interval.getMax().getType() != null ) {
309 node.setAttribute( "type", interval.getMax().getType().toString() );
310 }
311 node = XMLTools.appendElement( inter, namespaceURI, "res", interval.getRes().getValue() );
312 if ( interval.getRes().getType() != null ) {
313 node.setAttribute( "type", interval.getRes().getType().toString() );
314 }
315 }
316
317 /**
318 * Appends an <code>XML</code> representation of the passed <code>TypedLiteral</code> to the
319 * passed <code>Element</code>.
320 *
321 * @param xmlNode
322 * @param singleValue
323 * @param name
324 * @param namespaceURI
325 */
326 protected static void appendTypedLiteral( Element xmlNode, TypedLiteral singleValue, String name, URI namespaceURI ) {
327 Node node = XMLTools.appendElement( xmlNode, namespaceURI, name, singleValue.getValue() );
328 if ( singleValue.getType() != null ) {
329 ( (Element) node ).setAttribute( "type", singleValue.getType().toString() );
330 }
331 }
332
333 /**
334 * Appends an <code>XML</code> representation of the passed <code>CodeList</code> to the
335 * passed <code>Element</code>.
336 *
337 * @param xmlNode
338 * @param codeList
339 * @param namespaceURI
340 */
341 protected static void appendCodeList( Element xmlNode, CodeList codeList, URI namespaceURI ) {
342 String[] codes = codeList.getCodes();
343 String s = StringTools.arrayToString( codes, ' ' );
344 Node node = XMLTools.appendElement( xmlNode, namespaceURI, codeList.getName(), s );
345 if ( codeList.getCodeSpace() != null ) {
346 ( (Element) node ).setAttribute( "codeSpace", codeList.getCodeSpace().toString() );
347 }
348 }
349
350 /**
351 * Appends the XML attributes of the given <code>SimpleLink</code> to the also passed
352 * <code>Element</code>.
353 *
354 * @param linkElement
355 * @param simpleLink
356 */
357 protected static void appendSimpleLinkAttributes( Element linkElement, SimpleLink simpleLink ) {
358
359 linkElement.setAttributeNS( XLNNS.toString(), "xlink:type", "simple" );
360 if ( simpleLink.getHref() != null ) {
361 linkElement.setAttributeNS( XLNNS.toString(), "xlink:href", simpleLink.getHref().toString() );
362 }
363 if ( simpleLink.getRole() != null ) {
364 linkElement.setAttributeNS( XLNNS.toString(), "xlink:role", simpleLink.getRole().toString() );
365 }
366 if ( simpleLink.getArcrole() != null ) {
367 linkElement.setAttributeNS( XLNNS.toString(), "xlink:arcrole", simpleLink.getArcrole().toString() );
368 }
369 if ( simpleLink.getTitle() != null ) {
370 linkElement.setAttributeNS( XLNNS.toString(), "xlink:title", simpleLink.getTitle() );
371 }
372 if ( simpleLink.getShow() != null ) {
373 linkElement.setAttributeNS( XLNNS.toString(), "xlink:show", simpleLink.getShow() );
374 }
375 if ( simpleLink.getActuate() != null ) {
376 linkElement.setAttributeNS( XLNNS.toString(), "xlink:actuate", simpleLink.getActuate() );
377 }
378 }
379
380 /**
381 * Appends the <code>DOM</code> representation of a simple <code>XLink</code> -element to
382 * the passed <code>Element</code>.
383 *
384 * @param xmlNode
385 * @param elementName
386 * @param onlineResource
387 * @param namespaceURI
388 */
389 protected static void appendOnlineResource( Element xmlNode, String elementName, OnlineResource onlineResource,
390 URI namespaceURI ) {
391 Element linkElement = XMLTools.appendElement( xmlNode, namespaceURI, elementName );
392 linkElement.setAttributeNS( XLNNS.toString(), "xlink:type", "simple" );
393 linkElement.setAttributeNS( XLNNS.toString(), "xlink:href", onlineResource.getLinkage().getHref().toString() );
394 }
395
396 /**
397 * Appends the <code>DOM</code> representation of the given <code>PropertyPath</code> as a
398 * new text node to the given element (including necessary namespace bindings).
399 *
400 * @param element
401 * Element node where the PropertyPath is appended to
402 * @param propertyPath
403 */
404 protected static void appendPropertyPath( Element element, PropertyPath propertyPath ) {
405 StringBuffer sb = new StringBuffer();
406 sb.append( propertyPath );
407
408 Text textNode = element.getOwnerDocument().createTextNode( sb.toString() );
409 element.appendChild( textNode );
410 XMLTools.appendNSBindings( element, propertyPath.getNamespaceContext() );
411 }
412
413 /**
414 * Appends the <code>DOM</code> representation of the given feature id to the given element.
415 *
416 * @param root
417 * Element node where the "ogc:FeatureId" element is appended to
418 * @param fid
419 * feature identifier
420 */
421 protected static void appendFeatureId( Element root, String fid ) {
422 Element gmlObjectIdElement = XMLTools.appendElement( root, OGCNS, "ogc:FeatureId" );
423 gmlObjectIdElement.setAttribute( "fid", fid );
424 }
425
426 /**
427 * Appends the <code>DOM</code> representation of the given {@link Geometry} to the given
428 * element.
429 *
430 * TODO Do this a better way...
431 *
432 * @param el
433 * element node where the geometry is appended to
434 * @param geom
435 * geometry to be appended
436 * @throws GeometryException
437 */
438 protected static void appendGeometry( Element el, Geometry geom )
439 throws GeometryException {
440
441 StringBuffer sb = new StringBuffer();
442 sb.append( "<dummy xmlns:gml=\"" );
443 sb.append( CommonNamespaces.GMLNS.toString() );
444 sb.append( "\">" );
445 sb.append( GMLGeometryAdapter.export( geom ) );
446 sb.append( "</dummy>" );
447
448 ByteArrayInputStream bis = new ByteArrayInputStream( sb.toString().getBytes() );
449 try {
450 GMLDocument doc = new GMLDocument();
451 doc.load( bis, XMLFragment.DEFAULT_URL );
452 XMLTools.insertNodeInto( XMLTools.getFirstChildElement( doc.getRootElement() ), el );
453 } catch ( Exception e ) {
454 throw new GeometryException( e.getMessage() );
455 }
456 }
457 }