001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/sos/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.ogcwebservices.sos;
037    
038    import java.net.URI;
039    import java.util.ArrayList;
040    
041    import org.deegree.framework.log.ILogger;
042    import org.deegree.framework.log.LoggerFactory;
043    import org.deegree.framework.xml.XMLFragment;
044    import org.deegree.framework.xml.XMLTools;
045    import org.deegree.model.metadata.iso19115.Address;
046    import org.deegree.model.metadata.iso19115.CitedResponsibleParty;
047    import org.deegree.model.metadata.iso19115.ContactInfo;
048    import org.deegree.model.metadata.iso19115.OnlineResource;
049    import org.deegree.model.metadata.iso19115.Phone;
050    import org.deegree.model.metadata.iso19115.RoleCode;
051    import org.deegree.ogcbase.CommonNamespaces;
052    import org.deegree.ogcwebservices.OGCWebServiceException;
053    import org.deegree.ogcwebservices.getcapabilities.OperationsMetadata;
054    import org.deegree.ogcwebservices.getcapabilities.ServiceIdentification;
055    import org.deegree.ogcwebservices.getcapabilities.ServiceProvider;
056    import org.deegree.ogcwebservices.sos.capabilities.CapabilitiesDocument;
057    import org.deegree.ogcwebservices.sos.capabilities.Platform;
058    import org.deegree.ogcwebservices.sos.capabilities.SOSCapabilities;
059    import org.deegree.ogcwebservices.sos.capabilities.Sensor;
060    import org.deegree.ogcwebservices.sos.describeplatform.DescribePlatformResult;
061    import org.deegree.ogcwebservices.sos.describeplatform.PlatformDescriptionDocument;
062    import org.deegree.ogcwebservices.sos.describeplatform.PlatformMetadata;
063    import org.deegree.ogcwebservices.sos.describesensor.DescribeSensorResult;
064    import org.deegree.ogcwebservices.sos.describesensor.SensorDescriptionDocument;
065    import org.deegree.ogcwebservices.sos.describesensor.SensorMetadata;
066    import org.deegree.ogcwebservices.sos.getobservation.GetObservationDocument;
067    import org.deegree.ogcwebservices.sos.getobservation.GetObservationResult;
068    import org.deegree.ogcwebservices.sos.om.Observation;
069    import org.deegree.ogcwebservices.sos.om.ObservationArray;
070    import org.deegree.ogcwebservices.sos.sensorml.BasicResponse;
071    import org.deegree.ogcwebservices.sos.sensorml.Classifier;
072    import org.deegree.ogcwebservices.sos.sensorml.CoordinateReferenceSystem;
073    import org.deegree.ogcwebservices.sos.sensorml.Discussion;
074    import org.deegree.ogcwebservices.sos.sensorml.EngineeringCRS;
075    import org.deegree.ogcwebservices.sos.sensorml.GeoLocation;
076    import org.deegree.ogcwebservices.sos.sensorml.GeoPositionModel;
077    import org.deegree.ogcwebservices.sos.sensorml.GeographicCRS;
078    import org.deegree.ogcwebservices.sos.sensorml.Identifier;
079    import org.deegree.ogcwebservices.sos.sensorml.LocationModel;
080    import org.deegree.ogcwebservices.sos.sensorml.Product;
081    import org.deegree.ogcwebservices.sos.sensorml.ProjectedCRS;
082    import org.deegree.ogcwebservices.sos.sensorml.Quantity;
083    import org.deegree.ogcwebservices.sos.sensorml.Reference;
084    import org.deegree.ogcwebservices.sos.sensorml.ResponseModel;
085    import org.w3c.dom.Document;
086    import org.w3c.dom.Element;
087    
088    /**
089     * export data to XML Files
090     *
091     * @author <a href="mailto:mkulbe@lat-lon.de">Matthias Kulbe </a>
092     * @author last edited by: $Author: mschneider $
093     *
094     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $
095     */
096    public class XMLFactory extends org.deegree.owscommon.XMLFactory {
097    
098        private static final ILogger LOG = LoggerFactory.getLogger( XMLFactory.class );
099    
100        protected static final URI SOSNS = CommonNamespaces.SOSNS;
101    
102        protected static final URI DEEGREESOS = CommonNamespaces.DEEGREESOS;
103    
104        /**
105         * exports the SCS Capabilities
106         *
107         * @param scsCapabilities
108         * @return the document
109         * @throws OGCWebServiceException
110         */
111        public static XMLFragment export( SOSCapabilities scsCapabilities )
112                                throws OGCWebServiceException {
113    
114            try {
115    
116                CapabilitiesDocument doc = new CapabilitiesDocument();
117    
118                doc.createEmptyDocument();
119    
120                Element root = doc.getRootElement();
121                XMLTools.appendNSBinding( root, CommonNamespaces.SOS_PREFIX.toLowerCase(), CommonNamespaces.SOSNS );
122    
123                // sets the version
124                root.setAttribute( "version", scsCapabilities.getVersion() );
125    
126                // sets the updateSsequence
127                root.setAttribute( "updateSequence", scsCapabilities.getUpdateSequence() );
128    
129                // appends the ServiceIdentification
130                ServiceIdentification serviceIdentification = scsCapabilities.getServiceIdentification();
131                if ( serviceIdentification != null ) {
132                    appendServiceIdentification( root, serviceIdentification );
133                }
134    
135                // appends the ServiceProvider
136                ServiceProvider serviceProvider = scsCapabilities.getServiceProvider();
137                if ( serviceProvider != null ) {
138                    appendServiceProvider( root, serviceProvider );
139                }
140    
141                // appends the OpertionsMetadata
142                OperationsMetadata operationsMetadata = scsCapabilities.getOperationsMetadata();
143                if ( operationsMetadata != null ) {
144                    appendOperationsMetadata( root, operationsMetadata );
145                }
146    
147                // appends the PlatformList
148                ArrayList<Platform> platformList = scsCapabilities.getPlatformList();
149                if ( platformList != null ) {
150                    appendPlatformList( root, platformList );
151                }
152    
153                // appends the SensorList
154                ArrayList<Sensor> sensorList = scsCapabilities.getSensorList();
155                if ( sensorList != null ) {
156                    appendSensorList( root, sensorList );
157                }
158    
159                return doc;
160    
161            } catch ( Exception e ) {
162                LOG.logError( e.getMessage(), e );
163                throw new OGCWebServiceException( "scs webservice failure" );
164            }
165    
166        }
167    
168        /**
169         *
170         * @param describePlatformResult
171         * @return the document
172         * @throws OGCWebServiceException
173         */
174        public static XMLFragment export( DescribePlatformResult describePlatformResult )
175                                throws OGCWebServiceException {
176    
177            PlatformDescriptionDocument scsDocument = new PlatformDescriptionDocument();
178    
179            // erstellt ein leeres Dokument wie in dem Template angegeben
180            try {
181                scsDocument.createEmptyDocument();
182    
183                Element root = scsDocument.getRootElement();
184                XMLTools.appendNSBinding( root, CommonNamespaces.GML_PREFIX.toLowerCase(), CommonNamespaces.GMLNS );
185                Document doc = root.getOwnerDocument();
186    
187                PlatformMetadata[] platformMetadata = describePlatformResult.getPlatforms();
188    
189                for ( int i = 0; i < platformMetadata.length; i++ ) {
190    
191                    root.appendChild( appendPlatform( platformMetadata[i], doc ) );
192                }
193    
194                return scsDocument;
195    
196            } catch ( Exception e ) {
197                LOG.logError( e.getMessage(), e );
198                throw new OGCWebServiceException( "sos webservice failure" );
199            }
200        }
201    
202        /**
203         *
204         * @param describeSensorResult
205         * @return the XML
206         * @throws OGCWebServiceException
207         */
208        public static XMLFragment export( DescribeSensorResult describeSensorResult )
209                                throws OGCWebServiceException {
210    
211            try {
212    
213                SensorDescriptionDocument scsDocument = new SensorDescriptionDocument();
214    
215                scsDocument.createEmptyDocument();
216    
217                Element root = scsDocument.getRootElement();
218                XMLTools.appendNSBinding( root, CommonNamespaces.GML_PREFIX.toLowerCase(), CommonNamespaces.GMLNS );
219    
220                Document doc = root.getOwnerDocument();
221    
222                SensorMetadata[] sensorMetadata = describeSensorResult.getSensors();
223    
224                for ( int i = 0; i < sensorMetadata.length; i++ ) {
225                    root.appendChild( appendSensor( sensorMetadata[i], doc ) );
226                }
227    
228                return scsDocument;
229    
230            } catch ( Exception e ) {
231                e.printStackTrace();
232                throw new OGCWebServiceException( "sos webservice failure" );
233            }
234        }
235    
236        /**
237         *
238         * @param getObservationResult
239         * @return the XML document
240         * @throws OGCWebServiceException
241         */
242        public static XMLFragment export( GetObservationResult getObservationResult )
243                                throws OGCWebServiceException {
244    
245            GetObservationDocument scsDocument = new GetObservationDocument();
246    
247            try {
248                scsDocument.createEmptyDocument();
249    
250                Element root = scsDocument.getRootElement();
251                Document doc = root.getOwnerDocument();
252    
253                // TODO add boundedBy
254                Element boundedBy = doc.createElement( "gml:boundedBy" );
255                root.appendChild( boundedBy );
256    
257                Element leer = doc.createElement( "gml:Null" );
258                boundedBy.appendChild( leer );
259    
260                leer.appendChild( doc.createTextNode( "unknown" ) );
261    
262                Element observationMembers = doc.createElement( "om:observationMembers" );
263                root.appendChild( observationMembers );
264    
265                // add observation
266                appendObservationArrays( getObservationResult.getObservations(), observationMembers, doc );
267    
268                return scsDocument;
269    
270            } catch ( Exception e ) {
271                LOG.logError( e.getMessage(), e );
272                throw new OGCWebServiceException( "sos webservice failure" );
273            }
274        }
275    
276        /**
277         * appends ObservationArrays
278         *
279         * @param observationArrays
280         * @param element
281         * @param doc
282         */
283        private static void appendObservationArrays( ObservationArray[] observationArrays, Element element, Document doc ) {
284            if ( observationArrays == null ) {
285                return;
286            }
287            if ( element == null ) {
288                return;
289            }
290            if ( doc == null ) {
291                return;
292            }
293    
294            for ( int i = 0; i < observationArrays.length; i++ ) {
295    
296                Element observationArray = doc.createElement( "om:ObservationArray" );
297                element.appendChild( observationArray );
298    
299                // TODO add boundedBy
300                Element boundedBy = doc.createElement( "gml:boundedBy" );
301                observationArray.appendChild( boundedBy );
302    
303                Element boundingBox = doc.createElement( "gml:boundingBox" );
304                boundedBy.appendChild( boundingBox );
305    
306                Element coordMin = doc.createElement( "gml:coord" );
307                boundingBox.appendChild( coordMin );
308    
309                Element minX = doc.createElement( "gml:X" );
310                coordMin.appendChild( minX );
311    
312                minX.appendChild( doc.createTextNode( "" + observationArrays[i].getBoundedBy().getMin().getX() ) );
313    
314                Element minY = doc.createElement( "gml:Y" );
315                coordMin.appendChild( minY );
316    
317                minY.appendChild( doc.createTextNode( "" + observationArrays[i].getBoundedBy().getMin().getY() ) );
318    
319                Element coordMax = doc.createElement( "gml:coord" );
320                boundingBox.appendChild( coordMax );
321    
322                Element maxX = doc.createElement( "gml:X" );
323                coordMax.appendChild( maxX );
324    
325                maxX.appendChild( doc.createTextNode( "" + observationArrays[i].getBoundedBy().getMax().getX() ) );
326    
327                Element maxY = doc.createElement( "gml:Y" );
328                coordMax.appendChild( maxY );
329    
330                maxY.appendChild( doc.createTextNode( "" + observationArrays[i].getBoundedBy().getMax().getY() ) );
331    
332                // TODO add using
333                Element using = doc.createElement( "om:using" );
334                observationArray.appendChild( using );
335    
336                Element observationMembers = doc.createElement( "om:observationMembers" );
337                observationArray.appendChild( observationMembers );
338    
339                appendObservations( observationArrays[i].getObservations(), observationMembers, doc );
340    
341            }
342    
343        }
344    
345        /**
346         * appends Observations
347         *
348         * @param observations
349         * @param element
350         * @param doc
351         */
352        private static void appendObservations( Observation[] observations, Element element, Document doc ) {
353            if ( observations == null ) {
354                return;
355            }
356            if ( element == null ) {
357                return;
358            }
359            if ( doc == null ) {
360                return;
361            }
362    
363            for ( int i = 0; i < observations.length; i++ ) {
364    
365                Element observation = doc.createElement( "gml:Observation" );
366                element.appendChild( observation );
367    
368                // add timeStamp
369                Element timeStamp = doc.createElement( "gml:timeStamp" );
370                observation.appendChild( timeStamp );
371    
372                Element timeInstant = doc.createElement( "gml:TimeInstant" );
373                timeStamp.appendChild( timeInstant );
374    
375                Element timePosition = doc.createElement( "gml:timePosition" );
376                timeInstant.appendChild( timePosition );
377    
378                timePosition.appendChild( doc.createTextNode( observations[i].getTimeStamp() ) );
379    
380                // add resultOf
381                Element resultOf = doc.createElement( "gml:resultOf" );
382                observation.appendChild( resultOf );
383    
384                Element quantityList = doc.createElement( "gml:QuantityList" );
385                resultOf.appendChild( quantityList );
386    
387                String ro = observations[i].getResultOf();
388                if ( ro != null ) {
389                    quantityList.appendChild( doc.createTextNode( ro ) );
390                }
391    
392            }
393    
394        }
395    
396        /**
397         * appends a PlatformList used by getCapabilities
398         *
399         * @param root
400         * @param pl
401         *
402         */
403        private static void appendPlatformList( Element root, ArrayList<Platform> pl ) {
404    
405            if ( pl == null ) {
406                return;
407            }
408    
409            // XmlNode nn = new XmlNode(root);
410            // nn.appendDomChild(XmlNode.Element, SCSNS, "sos:PlatformList", null);
411    
412            Element element = XMLTools.appendElement( root, SOSNS, "sos:PlatformList" );
413    
414            // XmlNode platformListNode = new XmlNode( nn );
415    
416            for ( int i = 0; i < pl.size(); i++ ) {
417    
418                // XmlNode n = new XmlNode(platformListNode);
419                // n.appendDomChild(XmlNode.Element, SCSNS, "sos:Platform",null);
420                // XmlNode platformNode =new XmlNode( n );
421    
422                Element elem = XMLTools.appendElement( element, SOSNS, "sos:Platform" );
423                elem.setAttribute( "Id", pl.get( i ).getId() );
424    
425                // platformNode.appendDomChild( XmlNode.Attribute, null, "Id", ""
426                // + ((Platform) pl.get(i)).getId());
427    
428                // platformNode.appendDomChild( XmlNode.Attribute, null, "Description",
429                // "" + ((Platform) pl.get(i)).getDescription());
430    
431                elem.setAttribute( "Description", pl.get( i ).getDescription() );
432            }
433        }
434    
435        /**
436         * appends a sensor list used by getCapabilities
437         *
438         * @param root
439         * @param sl
440         *
441         */
442        private static void appendSensorList( Element root, ArrayList<Sensor> sl ) {
443            if ( sl == null ) {
444                return;
445            }
446    
447            Element element = XMLTools.appendElement( root, SOSNS, "sos:SensorList" );
448    
449            for ( int i = 0; i < sl.size(); i++ ) {
450                Element elem = XMLTools.appendElement( element, SOSNS, "sos:Sensor" );
451                elem.setAttribute( "Id", sl.get( i ).getId() );
452                elem.setAttribute( "Description", sl.get( i ).getDescription() );
453    
454            }
455        }
456    
457        /**
458         * returns a platform element
459         *
460         * @param actPlatform
461         * @param doc
462         * @return a platform element
463         */
464        private static Element appendPlatform( PlatformMetadata actPlatform, Document doc ) {
465    
466            if ( actPlatform == null ) {
467                return null;
468            }
469    
470            Element platform = doc.createElement( "sml:Platform" );
471    
472            appendIdentifiedAs( actPlatform.getIdentifiedAs(), platform, doc );
473    
474            appendClassifiedAs( actPlatform.getClassifiedAs(), platform, doc );
475    
476            appendAttachedTo( actPlatform, platform, doc );
477    
478            appendHasCRS( actPlatform.getHasCRS(), platform, doc );
479    
480            appendDescribedBy( actPlatform, platform, doc );
481    
482            appendLocatedUsing( actPlatform.getLocatedUsing(), platform, doc );
483    
484            appendCarries( actPlatform.getCarries(), platform, doc );
485    
486            return platform;
487        }
488    
489        /**
490         *
491         * @param actSensor
492         * @param doc
493         * @return the new element
494         */
495        private static Element appendSensor( SensorMetadata actSensor, Document doc ) {
496            if ( actSensor == null ) {
497                return null;
498            }
499    
500            Element sensor = doc.createElement( "sml:Sensor" );
501    
502            appendIdentifiedAs( actSensor.getIdentifiedAs(), sensor, doc );
503    
504            appendClassifiedAs( actSensor.getClassifiedAs(), sensor, doc );
505    
506            appendAttachedTo( actSensor, sensor, doc );
507    
508            appendHasCRS( actSensor.getHasCRS(), sensor, doc );
509    
510            appendDescribedBy( actSensor, sensor, doc );
511    
512            appendLocatedUsing( actSensor.getLocatedUsing(), sensor, doc );
513    
514            appendMeasures( actSensor.getMeasures(), sensor, doc );
515    
516            return sensor;
517        }
518    
519        /**
520         * appends a IdentifiedAs Node
521         *
522         * @param actidentifier
523         *            blah blah. Cannot be null.
524         * @param element
525         * @param doc
526         */
527        private static void appendIdentifiedAs( Identifier[] actidentifier, Element element, Document doc ) {
528            if ( actidentifier == null ) {
529                return;
530            }
531    
532            for ( int i = 0; i < actidentifier.length; i++ ) {
533                int type = actidentifier[i].getIdentifierType();
534    
535                Element identifiedAs = doc.createElement( "sml:identifiedAs" );
536                Element identifier = doc.createElement( "sml:Identifier" );
537    
538                // is required; no check
539                identifier.appendChild( doc.createTextNode( actidentifier[i].getIdentifierValue() ) );
540    
541                // is optional; but type must be checked
542                if ( type == 1 )
543                    identifier.setAttribute( "type", "shortName" );
544                if ( type == 2 )
545                    identifier.setAttribute( "type", "longName" );
546                if ( type == 3 )
547                    identifier.setAttribute( "type", "serialNumber" );
548                if ( type == 4 )
549                    identifier.setAttribute( "type", "modelNumber" );
550                if ( type == 5 )
551                    identifier.setAttribute( "type", "missionNumber" );
552                if ( type == 6 )
553                    identifier.setAttribute( "type", "partNumber" );
554    
555                // is optional; check
556                if ( actidentifier[i].getIdentifierCodeSpace() != null )
557                    identifier.setAttribute( "codeSpace", actidentifier[i].getIdentifierCodeSpace() );
558    
559                identifiedAs.appendChild( identifier );
560                element.appendChild( identifiedAs );
561            }
562    
563        }
564    
565        private static void appendAttachedTo( Object object, Element element, Document doc ) {
566    
567            // optional; check
568            if ( ( (ComponentMetadata) object ).getAttachedTo() != null ) {
569                Element attachedTo = doc.createElement( "sml:attachedTo" );
570    
571                Element component = doc.createElement( "sml:Component" );
572                attachedTo.appendChild( component );
573    
574                component.appendChild( doc.createTextNode( ( (ComponentMetadata) object ).getAttachedTo() ) );
575                element.appendChild( attachedTo );
576            }
577        }
578    
579        private static void appendClassifiedAs( Classifier[] actClassifier, Element element, Document doc ) {
580            if ( actClassifier == null ) {
581                return;
582            }
583    
584            for ( int i = 0; i < actClassifier.length; i++ ) {
585    
586                Element classifiedAs = doc.createElement( "sml:classifiedAs" );
587                Element classifier = doc.createElement( "sml:Classifier" );
588                classifiedAs.appendChild( classifier );
589    
590                // required; no check
591                classifier.setAttribute( "type", actClassifier[i].getType() );
592    
593                // required; no check
594                classifier.appendChild( doc.createTextNode( actClassifier[i].getValue() ) );
595                // optional; check
596                if ( actClassifier[i].getCodeSpace() != null ) {
597                    classifier.setAttribute( "codeSpace", actClassifier[i].getCodeSpace() );
598                }
599    
600                element.appendChild( classifiedAs );
601            }
602    
603        }
604    
605        private static void appendDerivedFrom( ResponseModel[] responseModels, Element element, Document doc ) {
606            if ( responseModels == null ) {
607                return;
608            }
609    
610            for ( int i = 0; i < responseModels.length; i++ ) {
611    
612                Element derivedFrom = doc.createElement( "sml:derivedFrom" );
613                element.appendChild( derivedFrom );
614    
615                Element responseModel = doc.createElement( "sml:ResponseModel" );
616                derivedFrom.appendChild( responseModel );
617    
618                // appends identifiedAs
619                appendIdentifiedAs( responseModels[i].getIdentifiedAs(), responseModel, doc );
620    
621                // appends classifiedAs
622                appendClassifiedAs( responseModels[i].getClassifiedAs(), responseModel, doc );
623    
624                // appends description
625                appendDescription( responseModels[i].getDescription(), responseModel, doc );
626    
627                appendUsesParametersFromDerivedFrom( responseModels[i].getUsesParameters(), responseModel, doc );
628    
629            }
630    
631        }
632    
633        private static void appendHasCRS( EngineeringCRS engineeringCRS, Element element, Document doc ) {
634            if ( engineeringCRS == null ) {
635                return;
636            }
637    
638            Element hasCRS = doc.createElement( "sml:hasCRS" );
639            element.appendChild( hasCRS );
640            appendEngineeringCRS( engineeringCRS, hasCRS, doc );
641    
642        }
643    
644        private static void appendEngineeringCRS( EngineeringCRS engineeringCRS, Element element, Document doc ) {
645    
646            if ( engineeringCRS == null ) {
647                return;
648            }
649    
650            Element engineeringCRSEle = doc.createElement( "gml:EngineeringCRS" );
651            element.appendChild( engineeringCRSEle );
652            Element srsName = doc.createElement( "gml:srsName" );
653    
654            srsName.appendChild( doc.createTextNode( engineeringCRS.getSrsName() ) );
655    
656            engineeringCRSEle.appendChild( srsName );
657    
658        }
659    
660        private static void appendCoordinateReferenceSystem( CoordinateReferenceSystem crs, Element element, Document doc ) {
661    
662            if ( crs == null ) {
663                return;
664            }
665    
666            if ( crs instanceof GeographicCRS ) {
667                Element geographicCRS = doc.createElement( "gml:GeographicCRS" );
668                element.appendChild( geographicCRS );
669                Element srsName = doc.createElement( "gml:srsName" );
670    
671                srsName.appendChild( doc.createTextNode( crs.getSrsName() ) );
672    
673                geographicCRS.appendChild( srsName );
674            }
675            if ( crs instanceof ProjectedCRS ) {
676                Element projectedCRS = doc.createElement( "gml:ProjectedCRS" );
677                element.appendChild( projectedCRS );
678                Element srsName = doc.createElement( "gml:srsName" );
679    
680                srsName.appendChild( doc.createTextNode( crs.getSrsName() ) );
681    
682                projectedCRS.appendChild( srsName );
683            }
684    
685        }
686    
687        private static void appendDescribedBy( Object object, Element element, Document doc ) {
688    
689            if ( ( (ComponentMetadata) object ).getDescribedBy() != null ) {
690                Element describedBy = doc.createElement( "sml:describedBy" );
691    
692                Element componentDescription = doc.createElement( "sml:ComponentDescription" );
693                describedBy.appendChild( componentDescription );
694    
695                if ( ( ( (ComponentMetadata) object ).getDescribedBy() ).getId() != null ) {
696                    componentDescription.setAttribute( "id", ( ( (ComponentMetadata) object ).getDescribedBy() ).getId() );
697                }
698    
699                // append description
700                appendDescription( ( ( (ComponentMetadata) object ).getDescribedBy() ).getDescription(),
701                                   componentDescription, doc );
702    
703                // append operatedBy
704                CitedResponsibleParty[] operatedBy = ( ( (ComponentMetadata) object ).getDescribedBy() ).getOperatedBy();
705                for ( int i = 0; i < operatedBy.length; i++ ) {
706                    appendOperatedBy( operatedBy[i], componentDescription, doc );
707                }
708    
709                // append operatedBy
710                CitedResponsibleParty[] manufactedBy = ( ( (ComponentMetadata) object ).getDescribedBy() ).getManufacturedBy();
711                for ( int i = 0; i < manufactedBy.length; i++ ) {
712                    appendManufactedBy( manufactedBy[i], componentDescription, doc );
713                }
714    
715                // append operatedBy
716                CitedResponsibleParty[] deployedBy = ( ( (ComponentMetadata) object ).getDescribedBy() ).getDeployedBy();
717                for ( int i = 0; i < deployedBy.length; i++ ) {
718                    appendDeployedBy( deployedBy[i], componentDescription, doc );
719                }
720    
721                // append reference
722                Reference[] reference = ( ( (ComponentMetadata) object ).getDescribedBy() ).getReference();
723                if ( ( reference != null ) && ( reference.length > 0 ) ) {
724                    Element ref = doc.createElement( "sml:reference" );
725                    componentDescription.appendChild( ref );
726    
727                    for ( int i = 0; i < reference.length; i++ ) {
728                        if ( reference[i].isOnLineResource() ) {
729    
730                            appendOnlineResource( reference[i].getOnLineResource(), ref, doc );
731                        }
732                        if ( reference[i].isCitation() ) {
733                            // why is this here?
734                        }
735                    }
736                }
737                element.appendChild( describedBy );
738            }
739    
740        }
741    
742        private static void appendLocatedUsing( LocationModel[] locatedUsingList, Element element, Document doc ) {
743    
744            if ( locatedUsingList == null ) {
745                return;
746            }
747    
748            Element locatedUsing = doc.createElement( "sml:locatedUsing" );
749            element.appendChild( locatedUsing );
750    
751            // process all locatedUsing objects
752            for ( int i = 0; i < locatedUsingList.length; i++ ) {
753    
754                // is GeoPositionModel
755                if ( locatedUsingList[i] instanceof GeoPositionModel ) {
756                    Element geoPositionModel = doc.createElement( "sml:GeoPositionModel" );
757                    locatedUsing.appendChild( geoPositionModel );
758    
759                    if ( ( (GeoPositionModel) locatedUsingList[i] ).getId() != null ) {
760                        geoPositionModel.setAttribute( "id", ( (GeoPositionModel) locatedUsingList[i] ).getId() );
761                    }
762    
763                    appendIdentifiedAs( ( (GeoPositionModel) locatedUsingList[i] ).getIdentifiedAs(), geoPositionModel, doc );
764    
765                    appendClassifiedAs( ( (GeoPositionModel) locatedUsingList[i] ).getClassifiedAs(), geoPositionModel, doc );
766    
767                    appendDescription( ( (GeoPositionModel) locatedUsingList[i] ).getDescription(), geoPositionModel, doc );
768    
769                    // append sourceCRS
770                    Element sourceCRS = doc.createElement( "sml:sourceCRS" );
771                    geoPositionModel.appendChild( sourceCRS );
772                    appendEngineeringCRS( ( (GeoPositionModel) locatedUsingList[i] ).getSourceCRS(), sourceCRS, doc );
773    
774                    // append referenceCRS
775                    Element referenceCRS = doc.createElement( "sml:referenceCRS" );
776                    geoPositionModel.appendChild( referenceCRS );
777                    appendCoordinateReferenceSystem( ( (GeoPositionModel) locatedUsingList[i] ).getReferenceCRS(),
778                                                     referenceCRS, doc );
779    
780                    // append usesParameters
781                    appendUsesParametersFromGeoLocation(
782                                                         ( (GeoPositionModel) locatedUsingList[i] ).getUsesParametersObjects(),
783                                                         geoPositionModel, doc );
784    
785                }
786            }
787    
788        }
789    
790        private static void appendUsesParametersFromGeoLocation( Object[] objects, Element element, Document doc ) {
791    
792            if ( objects == null ) {
793                return;
794            }
795    
796            for ( int i = 0; i < objects.length; i++ ) {
797                // is GeoLocation
798                if ( objects[i] instanceof GeoLocation ) {
799                    Element usesParameters = doc.createElement( "sml:usesParameters" );
800                    element.appendChild( usesParameters );
801    
802                    Element geoLocation = doc.createElement( "sml:GeoLocation" );
803                    usesParameters.appendChild( geoLocation );
804    
805                    geoLocation.setAttribute( "id", ( (GeoLocation) objects[i] ).getId() );
806    
807                    // appends latitude
808                    Element latitude = doc.createElement( "sml:latitude" );
809                    geoLocation.appendChild( latitude );
810                    appendQuantity( ( (GeoLocation) objects[i] ).getLatitude(), latitude, doc );
811    
812                    // appends longitude
813                    Element longitude = doc.createElement( "sml:longitude" );
814                    geoLocation.appendChild( longitude );
815                    appendQuantity( ( (GeoLocation) objects[i] ).getLongitude(), longitude, doc );
816    
817                    // appends altitude
818                    if ( ( (GeoLocation) objects[i] ).getAltitude() != null ) {
819                        Element altitude = doc.createElement( "sml:altitude" );
820                        geoLocation.appendChild( altitude );
821                        appendQuantity( ( (GeoLocation) objects[i] ).getAltitude(), altitude, doc );
822                    }
823    
824                    // appends trueHeading
825                    if ( ( (GeoLocation) objects[i] ).getTrueHeading() != null ) {
826                        Element trueHeading = doc.createElement( "sml:trueHeading" );
827                        geoLocation.appendChild( trueHeading );
828                        appendQuantity( ( (GeoLocation) objects[i] ).getTrueHeading(), trueHeading, doc );
829                    }
830    
831                    // appends speed
832                    if ( ( (GeoLocation) objects[i] ).getSpeed() != null ) {
833                        Element speed = doc.createElement( "sml:speed" );
834                        geoLocation.appendChild( speed );
835                        appendQuantity( ( (GeoLocation) objects[i] ).getSpeed(), speed, doc );
836                    }
837    
838                }
839    
840            }
841        }
842    
843        private static void appendUsesParametersFromDerivedFrom( Object[] objects, Element element, Document doc ) {
844            if ( objects != null ) {
845                for ( int i = 0; i < objects.length; i++ ) {
846                    // is GeoLocation
847                    if ( objects[i] instanceof BasicResponse ) {
848                        Element usesParameters = doc.createElement( "sml:usesParameters" );
849                        element.appendChild( usesParameters );
850    
851                        Element basicResponse = doc.createElement( "sml:BasicResponse" );
852                        usesParameters.appendChild( basicResponse );
853    
854                        Element resolution = doc.createElement( "sml:resolution" );
855                        basicResponse.appendChild( resolution );
856    
857                        Element typedQuantity = doc.createElement( "sml:TypedQuantity" );
858                        resolution.appendChild( typedQuantity );
859    
860                        typedQuantity.appendChild( doc.createTextNode( ""
861                                                                       + ( (BasicResponse) objects[i] ).getResolution().getValue() ) );
862    
863                        // sets required attrib type
864                        typedQuantity.setAttribute( "type",
865                                                    ( (BasicResponse) objects[i] ).getResolution().getType().toString() );
866    
867                        // sets optional attrib codeSpace
868                        if ( ( (BasicResponse) objects[i] ).getResolution().getCodeSpace() != null ) {
869                            typedQuantity.setAttribute(
870                                                        "codeSpace",
871                                                        ( (BasicResponse) objects[i] ).getResolution().getCodeSpace().toString() );
872                        }
873    
874                        // sets optional attrib fixed
875                        if ( !( (BasicResponse) objects[i] ).getResolution().isFixed() ) {
876                            typedQuantity.setAttribute( "fixed", "false" );
877                        }
878    
879                        // sets optional attrib uom
880                        if ( ( (BasicResponse) objects[i] ).getResolution().getUom() != null ) {
881                            typedQuantity.setAttribute( "uom",
882                                                        ( (BasicResponse) objects[i] ).getResolution().getUom().toString() );
883                        }
884    
885                        // sets optional attrib min
886                        if ( !Double.isNaN( ( (BasicResponse) objects[i] ).getResolution().getMin() ) ) {
887                            typedQuantity.setAttribute( "min", "" + ( (BasicResponse) objects[i] ).getResolution().getMin() );
888                        }
889    
890                        // sets optional attrib max
891                        if ( !Double.isNaN( ( (BasicResponse) objects[i] ).getResolution().getMax() ) ) {
892                            typedQuantity.setAttribute( "max", "" + ( (BasicResponse) objects[i] ).getResolution().getMax() );
893                        }
894    
895                        // sets optional attrib id
896                        if ( ( (BasicResponse) objects[i] ).getResolution().getId() != null ) {
897                            typedQuantity.setAttribute( "id", ( (BasicResponse) objects[i] ).getResolution().getId() );
898                        }
899    
900                    }
901    
902                }
903    
904            }
905        }
906    
907        private static void appendQuantity( Quantity quantity, Element element, Document doc ) {
908    
909            if ( quantity == null ) {
910                return;
911            }
912    
913            Element quantityEle = doc.createElement( "sml:Quantity" );
914            element.appendChild( quantityEle );
915            quantityEle.appendChild( doc.createTextNode( "" + quantity.getValue() ) );
916    
917            // appends uom
918            if ( quantity.getUom() != null ) {
919                quantityEle.setAttribute( "uom", quantity.getUom().toString() );
920            }
921    
922            // appends fixed
923            if ( quantity.isFixed() ) {
924                quantityEle.setAttribute( "fixed", "true" );
925            }
926            if ( !quantity.isFixed() ) {
927                quantityEle.setAttribute( "fixed", "false" );
928            }
929    
930            // appends min
931            if ( !Double.isNaN( quantity.getMin() ) ) {
932                quantityEle.setAttribute( "min", "" + quantity.getMin() );
933            }
934    
935            // appends max
936            if ( !Double.isNaN( quantity.getMax() ) ) {
937                quantityEle.setAttribute( "max", "" + quantity.getMax() );
938            }
939    
940        }
941    
942        /**
943         *
944         * @param description
945         * @param element
946         * @param doc
947         */
948        private static void appendDescription( Discussion[] description, Element element, Document doc ) {
949    
950            if ( description == null ) {
951                return;
952            }
953    
954            for ( int i = 0; i < description.length; i++ ) {
955    
956                Element desc = doc.createElement( "sml:description" );
957    
958                desc.appendChild( doc.createTextNode( description[i].getValue() ) );
959    
960                if ( description[i].getId() != null ) {
961                    desc.setAttribute( "id", description[i].getId() );
962                }
963                if ( description[i].getTopic() != null ) {
964                    desc.setAttribute( "topic", description[i].getTopic().toString() );
965                }
966                if ( description[i].getCodeSpace() != null ) {
967                    desc.setAttribute( "codeSpace", description[i].getCodeSpace().toString() );
968    
969                }
970    
971                element.appendChild( desc );
972            }
973    
974        }
975    
976        /**
977         *
978         * @param onlineResource
979         * @param element
980         * @param doc
981         */
982        private static void appendOnlineResource( OnlineResource onlineResource, Element element, Document doc ) {
983    
984            if ( onlineResource == null ) {
985                return;
986            }
987    
988            Element onlineRes = doc.createElement( "iso19115:CI_OnlineResource" );
989    
990            // append linkage
991            Element linkage = doc.createElement( "iso19115:linkage" );
992            linkage.appendChild( doc.createTextNode( onlineResource.getLinkage().getHref().toString() ) );
993            onlineRes.appendChild( linkage );
994    
995            // append function
996            if ( onlineResource.getFunctionCode().getValue() != null ) {
997                Element function = doc.createElement( "iso19115:function" );
998                function.appendChild( doc.createTextNode( onlineResource.getFunctionCode().getValue() ) );
999                onlineRes.appendChild( function );
1000            }
1001    
1002            // append protocol
1003            if ( onlineResource.getProtocol() != null ) {
1004                Element protocol = doc.createElement( "iso19115:protocol" );
1005                protocol.appendChild( doc.createTextNode( onlineResource.getProtocol() ) );
1006                onlineRes.appendChild( protocol );
1007            }
1008    
1009            // append applicationProfile
1010            if ( onlineResource.getApplicationProfile() != null ) {
1011                Element applicationProfile = doc.createElement( "iso19115:applicationProfile" );
1012                applicationProfile.appendChild( doc.createTextNode( onlineResource.getApplicationProfile() ) );
1013                onlineRes.appendChild( applicationProfile );
1014            }
1015    
1016            // append name
1017            if ( onlineResource.getOnlineResourceName() != null ) {
1018                Element name = doc.createElement( "iso19115:name" );
1019                name.appendChild( doc.createTextNode( onlineResource.getOnlineResourceName() ) );
1020                onlineRes.appendChild( name );
1021            }
1022    
1023            // append description
1024            if ( onlineResource.getOnlineResourceDescription() != null ) {
1025                Element description = doc.createElement( "iso19115:description" );
1026                description.appendChild( doc.createTextNode( onlineResource.getOnlineResourceDescription() ) );
1027                onlineRes.appendChild( description );
1028            }
1029    
1030            element.appendChild( onlineRes );
1031    
1032        }
1033    
1034        private static void appendOperatedBy( CitedResponsibleParty responsibleParty, Element element, Document doc ) {
1035    
1036            if ( responsibleParty == null ) {
1037                return;
1038            }
1039    
1040            Element operatedBy = doc.createElement( "sml:operatedBy" );
1041            element.appendChild( operatedBy );
1042            appendResponsibleParty( responsibleParty, operatedBy, doc );
1043    
1044        }
1045    
1046        private static void appendManufactedBy( CitedResponsibleParty responsibleParty, Element element, Document doc ) {
1047    
1048            if ( responsibleParty == null ) {
1049                return;
1050            }
1051    
1052            Element manufactedBy = doc.createElement( "sml:manufactedBy" );
1053            element.appendChild( manufactedBy );
1054            appendResponsibleParty( responsibleParty, manufactedBy, doc );
1055    
1056        }
1057    
1058        private static void appendDeployedBy( CitedResponsibleParty responsibleParty, Element element, Document doc ) {
1059    
1060            if ( responsibleParty == null ) {
1061                return;
1062            }
1063    
1064            Element deployedBy = doc.createElement( "sml:deployedBy" );
1065            element.appendChild( deployedBy );
1066            appendResponsibleParty( responsibleParty, deployedBy, doc );
1067    
1068        }
1069    
1070        private static void appendContactInfo( ContactInfo contact, Element element, Document doc ) {
1071    
1072            if ( contact == null ) {
1073                return;
1074            }
1075    
1076            Element cont = doc.createElement( "iso19115:contactInfo" );
1077            element.appendChild( cont );
1078    
1079            if ( contact.getPhone() != null ) {
1080                appendPhone( contact.getPhone(), cont, doc );
1081            }
1082    
1083            if ( contact.getAddress() != null ) {
1084                appendAddress( contact.getAddress(), cont, doc );
1085            }
1086    
1087            if ( contact.getOnLineResource() != null ) {
1088                appendOnlineResource( contact.getOnLineResource(), cont, doc );
1089            }
1090    
1091            if ( contact.getHoursOfService() != null ) {
1092                Element hours = doc.createElement( "iso19115:hoursOfService" );
1093                cont.appendChild( hours );
1094                hours.appendChild( doc.createTextNode( contact.getHoursOfService() ) );
1095            }
1096    
1097            if ( contact.getContactInstructions() != null ) {
1098                Element instr = doc.createElement( "iso19115:contactInstructions" );
1099                cont.appendChild( instr );
1100                instr.appendChild( doc.createTextNode( contact.getContactInstructions() ) );
1101            }
1102    
1103        }
1104    
1105        private static void appendPhone( Phone phone, Element element, Document doc ) {
1106    
1107            if ( phone == null ) {
1108                return;
1109            }
1110    
1111            Element phoneEle = doc.createElement( "iso19115:phone" );
1112            element.appendChild( phoneEle );
1113    
1114            String[] voice = phone.getVoice();
1115            if ( ( voice != null ) && ( voice.length > 0 ) ) {
1116                for ( int i = 0; i < voice.length; i++ ) {
1117                    Element actVoice = doc.createElement( "iso19115:voice" );
1118                    phoneEle.appendChild( actVoice );
1119                    actVoice.appendChild( doc.createTextNode( voice[i] ) );
1120                }
1121            }
1122    
1123            String[] fac = phone.getFacsimile();
1124            if ( ( fac != null ) && ( fac.length > 0 ) ) {
1125                for ( int i = 0; i < fac.length; i++ ) {
1126                    Element actFac = doc.createElement( "iso19115:facsimile" );
1127                    phoneEle.appendChild( actFac );
1128                    actFac.appendChild( doc.createTextNode( fac[i] ) );
1129                }
1130            }
1131    
1132        }
1133    
1134        private static void appendAddress( Address address, Element element, Document doc ) {
1135    
1136            if ( address == null ) {
1137                return;
1138            }
1139    
1140            Element addr = doc.createElement( "iso19115:address" );
1141            element.appendChild( addr );
1142    
1143            if ( address.getCity() != null ) {
1144                Element city = doc.createElement( "iso19115:city" );
1145                addr.appendChild( city );
1146                city.appendChild( doc.createTextNode( address.getCity() ) );
1147            }
1148    
1149            if ( address.getAdministrativeArea() != null ) {
1150                Element administrativeArea = doc.createElement( "iso19115:administrativeArea" );
1151                addr.appendChild( administrativeArea );
1152                administrativeArea.appendChild( doc.createTextNode( address.getAdministrativeArea() ) );
1153            }
1154    
1155            if ( address.getPostalCode() != null ) {
1156                Element postalCode = doc.createElement( "iso19115:postalCode" );
1157                addr.appendChild( postalCode );
1158                postalCode.appendChild( doc.createTextNode( address.getPostalCode() ) );
1159            }
1160    
1161            if ( address.getCountry() != null ) {
1162                Element country = doc.createElement( "iso19115:country" );
1163                addr.appendChild( country );
1164                country.appendChild( doc.createTextNode( address.getCountry() ) );
1165            }
1166    
1167            String[] deliveryPoints = address.getDeliveryPoint();
1168            for ( int i = 0; i < deliveryPoints.length; i++ ) {
1169                Element deliveryPoint = doc.createElement( "iso19115:deliveryPoint" );
1170                addr.appendChild( deliveryPoint );
1171                deliveryPoint.appendChild( doc.createTextNode( deliveryPoints[i] ) );
1172            }
1173    
1174            String[] electronicMailAddresses = address.getElectronicMailAddress();
1175            for ( int i = 0; i < electronicMailAddresses.length; i++ ) {
1176                Element electronicMailAddress = doc.createElement( "iso19115:electronicMailAddress" );
1177                addr.appendChild( electronicMailAddress );
1178                electronicMailAddress.appendChild( doc.createTextNode( electronicMailAddresses[i] ) );
1179            }
1180    
1181        }
1182    
1183        private static void appendResponsibleParty( CitedResponsibleParty responsibleParty, Element element, Document doc ) {
1184    
1185            if ( responsibleParty == null ) {
1186                return;
1187            }
1188    
1189            Element respParty = doc.createElement( "iso19115:CI_ResponsibleParty" );
1190            element.appendChild( respParty );
1191    
1192            // append IndividualName
1193            if ( responsibleParty.getIndividualName() != null ) {
1194                String[] individualNameList = responsibleParty.getIndividualName();
1195                for ( int i = 0; i < individualNameList.length; i++ ) {
1196                    Element individualName = doc.createElement( "iso19115:individualName" );
1197                    individualName.appendChild( doc.createTextNode( individualNameList[i] ) );
1198                    respParty.appendChild( individualName );
1199                }
1200            }
1201    
1202            // append OrganisationName
1203            if ( responsibleParty.getOrganisationName() != null ) {
1204                String[] organisationNameList = responsibleParty.getOrganisationName();
1205                for ( int i = 0; i < organisationNameList.length; i++ ) {
1206                    Element organisationName = doc.createElement( "iso19115:organisationName" );
1207                    organisationName.appendChild( doc.createTextNode( organisationNameList[i] ) );
1208                    respParty.appendChild( organisationName );
1209                }
1210            }
1211    
1212            // append PositionName
1213            if ( responsibleParty.getPositionName() != null ) {
1214                String[] positionNameList = responsibleParty.getPositionName();
1215                for ( int i = 0; i < positionNameList.length; i++ ) {
1216                    Element positionName = doc.createElement( "iso19115:positionName" );
1217                    positionName.appendChild( doc.createTextNode( positionNameList[i] ) );
1218                    respParty.appendChild( positionName );
1219                }
1220            }
1221    
1222            // append Role as codelist
1223    
1224            RoleCode[] roleList = responsibleParty.getRoleCode();
1225    
1226            for ( int i = 0; i < roleList.length; i++ ) {
1227                if ( roleList[i].getValue() != null ) {
1228                    Element role = doc.createElement( "iso19115:role" );
1229                    respParty.appendChild( role );
1230                    Element codeList = doc.createElement( "iso19115:CI_RoleCode_CodeList" );
1231                    role.appendChild( codeList );
1232                    codeList.appendChild( doc.createTextNode( roleList[i].getValue() ) );
1233                }
1234            }
1235    
1236            // append contact
1237            if ( responsibleParty.getContactInfo() != null ) {
1238                ContactInfo[] contactInfoList = responsibleParty.getContactInfo();
1239                for ( int i = 0; i < contactInfoList.length; i++ ) {
1240                    appendContactInfo( contactInfoList[i], respParty, doc );
1241                }
1242    
1243            }
1244    
1245        }
1246    
1247        private static void appendMeasures( Product[] products, Element element, Document doc ) {
1248    
1249            if ( products == null ) {
1250                return;
1251            }
1252    
1253            for ( int i = 0; i < products.length; i++ ) {
1254    
1255                Element measures = doc.createElement( "sml:measures" );
1256                Element product = doc.createElement( "sml:Product" );
1257                if ( products[i].getId() != null ) {
1258                    product.setAttribute( "id", products[i].getId() );
1259                }
1260                measures.appendChild( product );
1261    
1262                // appends identifiedAs
1263                appendIdentifiedAs( products[i].getIdentifiedAs(), product, doc );
1264    
1265                // appends classifiedAs
1266                appendClassifiedAs( products[i].getClassifiedAs(), product, doc );
1267    
1268                // appends description
1269                appendDescription( products[i].getDescription(), product, doc );
1270    
1271                // appends observable
1272                if ( products[i].getObservable() != null ) {
1273                    Element observable = doc.createElement( "sml:observable" );
1274                    product.appendChild( observable );
1275                    Element phenomenon = doc.createElement( "sml:Phenomenon" );
1276                    observable.appendChild( phenomenon );
1277    
1278                    if ( products[i].getObservable().getId() != null ) {
1279                        phenomenon.setAttribute( "id", products[i].getObservable().getId() );
1280                    }
1281    
1282                    if ( products[i].getObservable().getName() != null ) {
1283                        Element name = doc.createElement( "sml:name" );
1284                        phenomenon.appendChild( name );
1285                        name.appendChild( doc.createTextNode( products[i].getObservable().getName() ) );
1286                    }
1287    
1288                    if ( products[i].getObservable().getDefinition() != null ) {
1289                        Element description = doc.createElement( "sml:description" );
1290                        phenomenon.appendChild( description );
1291                        description.appendChild( doc.createTextNode( products[i].getObservable().getDefinition() ) );
1292                    }
1293                }
1294    
1295                // appends hasCRS
1296                if ( products[i].getHasCRS() != null ) {
1297                    appendHasCRS( products[i].getHasCRS(), product, doc );
1298                }
1299    
1300                // appends locatedUsing
1301                if ( products[i].getLocatedUsing() != null ) {
1302                    appendLocatedUsing( products[i].getLocatedUsing(), product, doc );
1303                }
1304    
1305                appendDerivedFrom( products[i].getDerivedFrom(), product, doc );
1306    
1307                element.appendChild( measures );
1308            }
1309    
1310        }
1311    
1312        private static void appendCarries( String[] asset, Element element, Document doc ) {
1313            if ( asset == null ) {
1314                return;
1315            }
1316    
1317            for ( int i = 0; i < asset.length; i++ ) {
1318                Element carries = doc.createElement( "sml:carries" );
1319                element.appendChild( carries );
1320                Element assetEle = doc.createElement( "sml:Asset" );
1321                carries.appendChild( assetEle );
1322                assetEle.appendChild( doc.createTextNode( asset[i] ) );
1323    
1324            }
1325    
1326        }
1327    }