001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/sos/getobservation/GetObservationDocument.java $
002    
003    /*----------------------------------------------------------------------------
004     This file is part of deegree, http://deegree.org/
005     Copyright (C) 2001-2009 by:
006       Department of Geography, University of Bonn
007     and
008       lat/lon GmbH
009    
010     This library is free software; you can redistribute it and/or modify it under
011     the terms of the GNU Lesser General Public License as published by the Free
012     Software Foundation; either version 2.1 of the License, or (at your option)
013     any later version.
014     This library is distributed in the hope that it will be useful, but WITHOUT
015     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
016     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
017     details.
018     You should have received a copy of the GNU Lesser General Public License
019     along with this library; if not, write to the Free Software Foundation, Inc.,
020     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021    
022     Contact information:
023    
024     lat/lon GmbH
025     Aennchenstr. 19, 53177 Bonn
026     Germany
027     http://lat-lon.de/
028    
029     Department of Geography, University of Bonn
030     Prof. Dr. Klaus Greve
031     Postfach 1147, 53001 Bonn
032     Germany
033     http://www.geographie.uni-bonn.de/deegree/
034    
035     e-mail: info@deegree.org
036    ----------------------------------------------------------------------------*/
037    package org.deegree.ogcwebservices.sos.getobservation;
038    
039    import java.io.IOException;
040    import java.net.URL;
041    import java.util.ArrayList;
042    import java.util.HashMap;
043    import java.util.Iterator;
044    import java.util.List;
045    import java.util.Map;
046    
047    import javax.xml.transform.TransformerException;
048    
049    import org.deegree.datatypes.QualifiedName;
050    import org.deegree.framework.log.ILogger;
051    import org.deegree.framework.log.LoggerFactory;
052    import org.deegree.framework.xml.XMLParsingException;
053    import org.deegree.framework.xml.XMLTools;
054    import org.deegree.model.filterencoding.ComparisonOperation;
055    import org.deegree.model.filterencoding.ComplexFilter;
056    import org.deegree.model.filterencoding.Filter;
057    import org.deegree.model.filterencoding.FilterConstructionException;
058    import org.deegree.model.filterencoding.LogicalOperation;
059    import org.deegree.model.filterencoding.Operation;
060    import org.deegree.model.filterencoding.OperationDefines;
061    import org.deegree.model.filterencoding.PropertyIsBetweenOperation;
062    import org.deegree.model.filterencoding.PropertyIsCOMPOperation;
063    import org.deegree.model.filterencoding.PropertyIsLikeOperation;
064    import org.deegree.model.filterencoding.PropertyIsNullOperation;
065    import org.deegree.model.filterencoding.PropertyName;
066    import org.deegree.model.filterencoding.SpatialOperation;
067    import org.deegree.model.spatialschema.Envelope;
068    import org.deegree.ogcbase.OGCDocument;
069    import org.deegree.ogcwebservices.OGCWebService;
070    import org.deegree.ogcwebservices.OGCWebServiceException;
071    import org.deegree.ogcwebservices.sos.WFSRequestGenerator;
072    import org.deegree.ogcwebservices.sos.WFSRequester;
073    import org.deegree.ogcwebservices.sos.XMLFactory;
074    import org.deegree.ogcwebservices.sos.XSLTransformer;
075    import org.deegree.ogcwebservices.sos.configuration.MeasurementConfiguration;
076    import org.deegree.ogcwebservices.sos.configuration.PlatformConfiguration;
077    import org.deegree.ogcwebservices.sos.configuration.SOSDeegreeParams;
078    import org.deegree.ogcwebservices.sos.configuration.SensorConfiguration;
079    import org.deegree.ogcwebservices.sos.configuration.SourceServerConfiguration;
080    import org.deegree.ogcwebservices.sos.om.Observation;
081    import org.deegree.ogcwebservices.sos.om.ObservationArray;
082    import org.w3c.dom.Document;
083    import org.w3c.dom.Node;
084    import org.xml.sax.SAXException;
085    
086    /**
087     * get the observation data from the xsl transformed wfs requests
088     *
089     * @author <a href="mailto:mkulbe@lat-lon.de">Matthias Kulbe </a>
090     * @author last edited by: $Author: mschneider $
091     *
092     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $
093     */
094    public class GetObservationDocument extends OGCDocument {
095    
096        private static final long serialVersionUID = 4262217635140146058L;
097    
098        private static final ILogger LOG = LoggerFactory.getLogger( XMLFactory.class );
099    
100        private static final String XML_TEMPLATE = "GetObservationTemplate.xml";
101    
102        /**
103         * @throws IOException
104         * @throws SAXException
105         */
106        public void createEmptyDocument()
107                                throws IOException, SAXException {
108            URL url = GetObservationDocument.class.getResource( XML_TEMPLATE );
109            if ( url == null ) {
110                throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." );
111            }
112            load( url );
113        }
114    
115        /**
116         * gets the data from sensors
117         *
118         * @param deegreeParams
119         * @param request
120         * @return the data
121         * @throws OGCWebServiceException
122         * @throws XMLParsingException
123         * @throws IOException
124         * @throws SAXException
125         * @throws TransformerException
126         */
127        public ObservationArray[] getObservations( SOSDeegreeParams deegreeParams, GetObservationRequest request )
128                                throws OGCWebServiceException, XMLParsingException, TransformerException, IOException,
129                                SAXException {
130    
131            Envelope bbox = request.getBBox();
132            Object[] times = request.getTime();
133            Query query = request.getQuery();
134            String[] platforms = request.getPlatforms();
135            String[] sensors = request.getSensors();
136    
137            ArrayList<String> sensorList = null;
138    
139            if ( ( sensors.length < 1 ) && ( platforms.length < 1 ) ) {
140    
141                String[] platformsInBbox = getPlatformsInBBoxFromServers( bbox,
142                                                                          deegreeParams.getSourceServerConfigurations(),
143                                                                          deegreeParams );
144    
145                LOG.logDebug( "## found " + platformsInBbox.length + " platforms in bbox" );
146    
147                String[] sensorsFromPlatforms = getSensorIdsFromPlatforms( platformsInBbox, deegreeParams );
148    
149                LOG.logDebug( "## found " + sensorsFromPlatforms.length + " sensors in bbox" );
150    
151                sensorList = new ArrayList<String>( sensorsFromPlatforms.length );
152                for ( int i = 0; i < sensorsFromPlatforms.length; i++ ) {
153                    if ( !sensorList.contains( sensorsFromPlatforms[i] ) ) {
154                        sensorList.add( sensorsFromPlatforms[i] );
155                    }
156                }
157            } else {
158                LOG.logDebug( "info: found sensors and/or platforms" );
159                // checks the position in the bbox
160                boolean contains = areSensorsInBBox( bbox, sensors, platforms, deegreeParams );
161    
162                if ( contains ) {
163                    sensorList = new ArrayList<String>( 100 );
164                    for ( int i = 0; i < sensors.length; i++ ) {
165                        if ( !sensorList.contains( sensors[i] ) ) {
166                            sensorList.add( sensors[i] );
167                        }
168                    }
169    
170                    String[] sensorsFromPlatforms = getSensorIdsFromPlatforms( platforms, deegreeParams );
171                    for ( int i = 0; i < sensorsFromPlatforms.length; i++ ) {
172                        if ( !sensorList.contains( sensorsFromPlatforms[i] ) ) {
173                            sensorList.add( sensorsFromPlatforms[i] );
174                        }
175                    }
176                }
177            }
178    
179            ArrayList<ObservationArray> observations = new ArrayList<ObservationArray>( sensorList.size() );
180    
181            for ( int i = 0; i < sensorList.size(); i++ ) {
182                Document observationDocument = getObservationFromSensor( sensorList.get( i ), deegreeParams, times, query );
183    
184                if ( observationDocument != null ) {
185                    ObservationArray observationArray = getObservationsFromDocuments( observationDocument, bbox,
186                                                                                      sensorList.get( i ) );
187                    observations.add( observationArray );
188                }
189            }
190    
191            LOG.logDebug( "-> have " + observations.size() + " observations collected" );
192    
193            return observations.toArray( new ObservationArray[observations.size()] );
194        }
195    
196        /**
197         * returns all platforms in the given bbox, but only from the given servers
198         *
199         * @param bbox
200         * @param servers
201         * @param params
202         * @return all platforms in the given bbox, but only from the given servers
203         */
204        private String[] getPlatformsInBBoxFromServers( Envelope bbox, SourceServerConfiguration[] servers,
205                                                        SOSDeegreeParams params )
206                                throws OGCWebServiceException {
207    
208            ArrayList<Document> tPDResults = new ArrayList<Document>( servers.length );
209    
210            try {
211                for ( int i = 0; i < servers.length; i++ ) {
212    
213                    // only if server can provide platformmetadata
214                    if ( servers[i].havePlatformDescriptionData() ) {
215                        Document request = WFSRequestGenerator.createBBoxWFSRequest(
216                                                                                     bbox,
217                                                                                     servers[i].getPlatformDescriptionFeatureType(),
218                                                                                     servers[i].getPlatformDescriptionCoordPropertyName() );
219    
220                        Document result = WFSRequester.sendWFSrequest( request, servers[i].getDataService() );
221    
222                        if ( result != null ) {
223                            URL pdxs = servers[i].getPlatformDescriptionXSLTScriptSource();
224                            tPDResults.add( XSLTransformer.transformDocument( result, pdxs ) );
225                        }
226                    }
227    
228                }
229            } catch ( Exception e ) {
230                LOG.logError( "could not access platforms in BBOX from DataService ", e );
231                throw new OGCWebServiceException( this.getClass().getName(),
232                                                  "could not access platforms in BBOX from DataService " );
233            }
234    
235            Document[] docs = tPDResults.toArray( new Document[tPDResults.size()] );
236    
237            return getPlatformIdsFromPlatformDocs( docs, params );
238    
239        }
240    
241        /**
242         * returns the observationArray, with all observations, from a wfs result
243         *
244         * @param bbox
245         * @return the observationArray, with all observations, from a wfs result
246         * @throws XMLParsingException
247         */
248        private ObservationArray getObservationsFromDocuments( Document doc, Envelope bbox, String sensorId )
249                                throws XMLParsingException {
250    
251            List<Node> observations = XMLTools.getNodes( doc, "om:ObservationArray/om:observationMembers/gml:Observation",
252                                                         nsContext );
253    
254            if ( observations.size() < 1 ) {
255                LOG.logDebug( "warning: no observations found in document" );
256            }
257    
258            ArrayList<Observation> observationsList = new ArrayList<Observation>( observations.size() );
259    
260            for ( int i = 0; i < observations.size(); i++ ) {
261    
262                String timeStamp = XMLTools.getRequiredNodeAsString( observations.get( i ),
263                                                                     "./gml:timeStamp/gml:TimeInstant/gml:timePosition",
264                                                                     nsContext );
265    
266                String resultOf = XMLTools.getRequiredNodeAsString( observations.get( i ),
267                                                                    "./gml:resultOf/gml:QuantityList", nsContext );
268    
269                observationsList.add( new Observation( timeStamp, resultOf ) );
270            }
271    
272            LOG.logDebug( "-> ObservationArray created" );
273            Observation[] obs = new Observation[observationsList.size()];
274            obs = observationsList.toArray( obs );
275            return new ObservationArray( obs, bbox, sensorId );
276        }
277    
278        /**
279         * gets the observation from a sensor, by requesting the correct wfs
280         *
281         * @param sensor
282         * @param params
283         * @return the document
284         */
285        private Document getObservationFromSensor( String sensor, SOSDeegreeParams params, Object[] times, Query query )
286                                throws OGCWebServiceException {
287    
288            try {
289                // query
290                MeasurementConfiguration measureConfig = null;
291                Operation filterOperation = null;
292    
293                if ( query != null ) {
294                    String queryFeature = query.getFeature();
295                    measureConfig = params.getSensorConfiguration( sensor ).getMeasurementById( queryFeature );
296                    if ( measureConfig == null ) {
297                        throw new Exception( "warning: sensor not support the requested " + "observationFeature!" );
298                    }
299    
300                    // gets the filter operations
301                    if ( query.getFilter() != null ) {
302                        LOG.logDebug( "-> QueryFilter found" );
303                        Operation op = query.getFilter().getOperation();
304                        filterOperation = modifyOperation( op, measureConfig );
305                    }
306                } else {
307                    // TODO
308                    // I think this is a mistake and instead all measurements of a
309                    // sensor has to requested from the WFS
310                    LOG.logDebug( "warning: no query given, will use the default from sensor" );
311                    measureConfig = params.getSensorConfiguration( sensor ).getFirstMeasurementConfiguration();
312                    Filter filter = measureConfig.getConstraint();
313                    if ( filter != null ) {
314                        filterOperation = ( (ComplexFilter) filter ).getOperation();
315                    }
316                }
317    
318                Document request = WFSRequestGenerator.createObservationWFSRequest( times,
319                                                                                    measureConfig.getFeatureTypeName(),
320                                                                                    measureConfig.getTimePropertyName(),
321                                                                                    filterOperation );
322    
323                SensorConfiguration sc = params.getSensorConfiguration( sensor );
324                String ssID = sc.getFirstMeasurementConfiguration().getSourceServerId();
325                OGCWebService ows = params.getSourceServerConfiguration( ssID ).getDataService();
326    
327                Document result = WFSRequester.sendWFSrequest( request, ows );
328    
329                return XSLTransformer.transformDocument( result, measureConfig.getXSLTScriptSource() );
330            } catch ( Exception e ) {
331                LOG.logError( e.getMessage(), e );
332                throw new OGCWebServiceException( this.getClass().getName(), "could not access observations from sensor" );
333            }
334    
335        }
336    
337        /**
338         * gets all sensorIds from the given platforms
339         *
340         * @param platforms
341         * @param params
342         * @return the ids
343         */
344        private String[] getSensorIdsFromPlatforms( String[] platforms, SOSDeegreeParams params )
345                                throws OGCWebServiceException {
346    
347            // gets all servers which have to request
348            ArrayList<Document> transformedResultDocs = null;
349            try {
350                Map<String, ArrayList<String>> servers = new HashMap<String, ArrayList<String>>( platforms.length );
351    
352                for ( int t = 0; t < platforms.length; t++ ) {
353                    String sourceServerId = params.getPlatformConfiguration( platforms[t] ).getSourceServerId();
354    
355                    // server schon in liste; nur platform hinzuf�gen
356                    if ( servers.containsKey( sourceServerId ) ) {
357                        servers.get( sourceServerId ).add( platforms[t] );
358                    }
359                    // server nicht in liste; server hinzuf�gen und platform hinzuf�gen
360                    else {
361                        ArrayList<String> temp = new ArrayList<String>( 10 );
362                        temp.add( platforms[t] );
363                        servers.put( sourceServerId, temp );
364                    }
365                }
366    
367                transformedResultDocs = new ArrayList<Document>( servers.keySet().size() );
368    
369                Iterator<String> iter = servers.keySet().iterator();
370                while ( iter.hasNext() ) {
371                    String key = iter.next();
372                    List<String> list = servers.get( key );
373    
374                    String[] idProps = new String[list.size()];
375                    for ( int a = 0; a < list.size(); a++ ) {
376                        idProps[a] = params.getPlatformConfiguration( list.get( a ) ).getIdPropertyValue();
377                    }
378    
379                    QualifiedName pdft = params.getSourceServerConfiguration( key ).getPlatformDescriptionFeatureType();
380                    QualifiedName pdid = params.getSourceServerConfiguration( key ).getPlatformDescriptionIdPropertyName();
381                    Document request = WFSRequestGenerator.createIsLikeOperationWFSRequest( idProps, pdft, pdid );
382    
383                    OGCWebService ows = params.getSourceServerConfiguration( key ).getDataService();
384                    Document result = WFSRequester.sendWFSrequest( request, ows );
385    
386                    if ( result != null ) {
387                        SourceServerConfiguration ssc = params.getSourceServerConfiguration( key );
388                        URL url = ssc.getPlatformDescriptionXSLTScriptSource();
389                        transformedResultDocs.add( XSLTransformer.transformDocument( result, url ) );
390                    }
391                }
392            } catch ( Exception e ) {
393                LOG.logError( e.getMessage(), e );
394                throw new OGCWebServiceException( this.getClass().getName(), "could not access sensorsIDs from platforms " );
395            }
396    
397            Document[] docs = new Document[transformedResultDocs.size()];
398            docs = transformedResultDocs.toArray( docs );
399            return getSensorIdsFromCarriesInPlatformDoc( docs, params );
400        }
401    
402        /**
403         * returns true if all Sensor and/or Platforms inside the given BBox
404         *
405         *
406         * @param bbox
407         *            null is not allowed
408         * @param sensorIds
409         * @param platformIds
410         * @return <code>true</code> if all Sensor and/or Platforms inside the given BBox
411         * @throws IOException
412         * @throws XMLParsingException
413         * @throws TransformerException
414         * @throws IOException
415         * @throws SAXException
416         * @throws OGCWebServiceException
417         */
418        private boolean areSensorsInBBox( Envelope bbox, String[] sensorIds, String[] platformIds,
419                                          SOSDeegreeParams deegreeParams )
420                                throws OGCWebServiceException, XMLParsingException, TransformerException, IOException,
421                                SAXException {
422            if ( bbox == null ) {
423                throw new NullPointerException( "bbox must be set" );
424            }
425    
426            // sensor and platforms
427            if ( ( sensorIds != null ) && ( platformIds != null ) ) {
428                if ( ( areSensorsInBBox( sensorIds, bbox, deegreeParams ) )
429                     && ( arePlatformsInBBox( platformIds, bbox, deegreeParams ) ) ) {
430                    return true;
431                }
432            } else if ( sensorIds != null && areSensorsInBBox( sensorIds, bbox, deegreeParams ) ) {
433                // only sensors
434                return true;
435            } else if ( platformIds != null && arePlatformsInBBox( platformIds, bbox, deegreeParams ) ) {
436                // only platforms
437                return true;
438            }
439    
440            return false;
441        }
442    
443        /**
444         * returns true, if the given sensors in bbox
445         *
446         * @param sensors
447         * @param bbox
448         * @param deegreeParams
449         * @return <code>true</code>, if the given sensors in bbox
450         * @throws OGCWebServiceException
451         * @throws XMLParsingException
452         * @throws TransformerException
453         * @throws IOException
454         * @throws SAXException
455         */
456        private boolean areSensorsInBBox( String[] sensors, Envelope bbox, SOSDeegreeParams deegreeParams )
457                                throws OGCWebServiceException, XMLParsingException, TransformerException, IOException,
458                                SAXException {
459    
460            // gets all servers which have to request
461            Map<String, ArrayList<String>> servers = new HashMap<String, ArrayList<String>>( sensors.length );
462    
463            for ( int t = 0; t < sensors.length; t++ ) {
464                String sourceServerId = deegreeParams.getSensorConfiguration( sensors[t] ).getSourceServerId();
465    
466                if ( servers.containsKey( sourceServerId ) ) {
467                    servers.get( sourceServerId ).add( sensors[t] );
468                } else {
469                    ArrayList<String> temp = new ArrayList<String>();
470                    temp.add( sensors[t] );
471                    servers.put( sourceServerId, temp );
472                }
473    
474            }
475    
476            String[] keySet = servers.keySet().toArray( new String[servers.keySet().size()] );
477            ArrayList<Document> transformedWFSResults = new ArrayList<Document>( keySet.length );
478    
479            // process all servers in the hashTable
480            for ( int i = 0; i < keySet.length; i++ ) {
481    
482                Document result = getSensors( deegreeParams, servers, keySet, i );
483    
484                // if the result is not null, transform it and add it to the result
485                // document list
486                if ( result != null ) {
487                    SourceServerConfiguration ssc = deegreeParams.getSourceServerConfiguration( keySet[i] );
488                    URL url = ssc.getSensorDescriptionXSLTScriptSource();
489                    Document doc = XSLTransformer.transformDocument( result, url );
490                    transformedWFSResults.add( doc );
491                }
492    
493            }
494    
495            Document[] docs = new Document[transformedWFSResults.size()];
496            docs = transformedWFSResults.toArray( docs );
497            String[] platformList = getPlatformIdsFromAttachedToInSensorDocs( docs, deegreeParams );
498    
499            if ( arePlatformsInBBox( platformList, bbox, deegreeParams ) ) {
500                return true;
501            }
502            return false;
503        }
504    
505        private Document getSensors( SOSDeegreeParams deegreeParams, Map<String, ArrayList<String>> servers,
506                                     String[] keySet, int i )
507                                throws OGCWebServiceException {
508            Document result = null;
509            try {
510                String[] tmp = new String[servers.get( keySet[i] ).size()];
511                ArrayList<String> al = servers.get( keySet[i] );
512                String[] sensorIds = al.toArray( tmp );
513    
514                String[] sensorIdPropertyValues = new String[sensorIds.length];
515    
516                for ( int x = 0; x < sensorIds.length; x++ ) {
517                    sensorIdPropertyValues[i] = deegreeParams.getSensorConfiguration( sensorIds[x] ).getIdPropertyValue();
518                }
519    
520                SourceServerConfiguration ssc = deegreeParams.getSourceServerConfiguration( keySet[i] );
521                QualifiedName sdft = ssc.getSensorDescriptionFeatureType();
522                QualifiedName sdpn = ssc.getSensorDescriptionIdPropertyName();
523                // generates the request for the current wfs
524                Document request = WFSRequestGenerator.createIsLikeOperationWFSRequest( sensorIdPropertyValues, sdft, sdpn );
525                // sends the request to the current wfs
526                result = WFSRequester.sendWFSrequest( request, ssc.getDataService() );
527            } catch ( Exception e ) {
528                LOG.logError( e.getMessage(), e );
529                throw new OGCWebServiceException( this.getClass().getName(), "could not evaluate "
530                                                                             + "if platform is contained in BBOX" );
531            }
532            return result;
533        }
534    
535        /**
536         * checks if the platforms inside the bbox
537         *
538         * @param platformIds
539         * @param bbox
540         * @return the check result
541         * @throws OGCWebServiceException
542         */
543        private boolean arePlatformsInBBox( String[] platformIds, Envelope bbox, SOSDeegreeParams deegreeParams )
544                                throws OGCWebServiceException {
545    
546            ArrayList<SourceServerConfiguration> serverConfigsList = new ArrayList<SourceServerConfiguration>();
547    
548            // gets all platforms in bbox, only from neccessary servers
549            for ( int i = 0; i < platformIds.length; i++ ) {
550                String id = deegreeParams.getPlatformConfiguration( platformIds[i] ).getSourceServerId();
551                SourceServerConfiguration ssc = deegreeParams.getSourceServerConfiguration( id );
552                if ( !serverConfigsList.contains( ssc ) ) {
553                    serverConfigsList.add( ssc );
554                }
555            }
556    
557            SourceServerConfiguration[] ssc = new SourceServerConfiguration[serverConfigsList.size()];
558            ssc = serverConfigsList.toArray( ssc );
559            String[] platformsInBBox = getPlatformsInBBoxFromServers( bbox, ssc, deegreeParams );
560    
561            // compares platforms in bbox with the given platforms
562            for ( int i = 0; i < platformIds.length; i++ ) {
563                boolean found = false;
564    
565                for ( int a = 0; a < platformsInBBox.length; a++ ) {
566    
567                    if ( platformIds[i].equals( platformsInBBox[a] ) ) {
568    
569                        found = true;
570                    }
571                }
572                if ( !found ) {
573                    throw new OGCWebServiceException( "Sensor or Platform not in given bbox" );
574                }
575            }
576    
577            return true;
578        }
579    
580        /**
581         * gets all platformIds from attachedTo parts in SensorDescriptionDocuments
582         *
583         */
584        private String[] getPlatformIdsFromAttachedToInSensorDocs( Document[] docs, SOSDeegreeParams deegreeParams )
585                                throws XMLParsingException {
586    
587            ArrayList<String> platformIdList = new ArrayList<String>();
588    
589            for ( int a = 0; a < docs.length; a++ ) {
590    
591                List<Node> nl = XMLTools.getNodes( docs[a], "sml:Sensors/sml:Sensor", nsContext );
592    
593                for ( int i = 0; i < nl.size(); i++ ) {
594                    String platformIdPropertyValue = XMLTools.getNodeAsString( nl.get( i ),
595                                                                               "sml:attachedTo/sml:Component/text()",
596                                                                               nsContext, null );
597    
598                    PlatformConfiguration pc = deegreeParams.getPlatformConfigurationByIdPropertyValue( platformIdPropertyValue );
599    
600                    String platformId = null;
601                    if ( pc != null ) {
602                        platformId = pc.getId();
603                    }
604    
605                    if ( platformId != null ) {
606                        platformIdList.add( platformId );
607                    }
608                }
609            }
610    
611            return platformIdList.toArray( new String[platformIdList.size()] );
612        }
613    
614        /**
615         * gets the platformIds from all PlatformDescriptionDocuments
616         *
617         */
618        private String[] getPlatformIdsFromPlatformDocs( Document[] docs, SOSDeegreeParams deegreeParams )
619                                throws OGCWebServiceException {
620    
621            if ( docs == null ) {
622                throw new NullPointerException( "null not allowed" );
623            }
624    
625            ArrayList<String> platformIdList;
626            try {
627    
628                platformIdList = new ArrayList<String>( docs.length );
629                for ( int a = 0; a < docs.length; a++ ) {
630    
631                    List<Node> itemsList = XMLTools.getNodes( docs[a], "sml:Platforms/sml:Platform", nsContext );
632                    for ( int i = 0; i < itemsList.size(); i++ ) {
633                        String platformIdPropertyValue = XMLTools.getRequiredNodeAsString( itemsList.get( i ), "@id",
634                                                                                           nsContext );
635    
636                        PlatformConfiguration pc = deegreeParams.getPlatformConfigurationByIdPropertyValue( platformIdPropertyValue );
637    
638                        if ( pc != null ) {
639                            platformIdList.add( pc.getId() );
640                        }
641                    }
642    
643                }
644            } catch ( Exception e ) {
645                LOG.logError( e.getMessage(), e );
646                throw new OGCWebServiceException( this.getClass().getName(), "could not access " + "platform IDs" );
647            }
648    
649            return platformIdList.toArray( new String[platformIdList.size()] );
650    
651        }
652    
653        /**
654         * gets all sensorSCSId's from the given platformDescription Document
655         *
656         */
657        private String[] getSensorIdsFromCarriesInPlatformDoc( Document[] docs, SOSDeegreeParams deegreeParams )
658                                throws OGCWebServiceException {
659    
660            try {
661                ArrayList<String> sensorIdList = new ArrayList<String>( 100 );
662    
663                for ( int x = 0; x < docs.length; x++ ) {
664    
665                    List<Node> platformNodeList = XMLTools.getNodes( docs[x], "sml:Platforms/sml:Platform", nsContext );
666    
667                    for ( int i = 0; i < platformNodeList.size(); i++ ) {
668                        List<Node> carriesNodeList = XMLTools.getNodes( platformNodeList.get( i ), "sml:carries", nsContext );
669    
670                        for ( int a = 0; a < carriesNodeList.size(); a++ ) {
671                            String sensorIdPropertyValue = XMLTools.getRequiredNodeAsString( carriesNodeList.get( a ),
672                                                                                             "sml:Asset/text()", nsContext );
673    
674                            if ( deegreeParams.getSensorConfigurationByIdPropertyValue( sensorIdPropertyValue ) != null ) {
675                                String sensorId = deegreeParams.getSensorConfigurationByIdPropertyValue(
676                                                                                                         sensorIdPropertyValue ).getId();
677    
678                                if ( sensorId != null ) {
679                                    sensorIdList.add( sensorId );
680                                }
681                            }
682                        }
683                    }
684                }
685                return sensorIdList.toArray( new String[sensorIdList.size()] );
686            } catch ( Exception e ) {
687                LOG.logError( e.getMessage(), e );
688                throw new OGCWebServiceException( this.getClass().getName(),
689                                                  "could not access sensor IDs carres in platform " );
690            }
691        }
692    
693        /**
694         * returns the modified operation; modify the scs query to create the correct wfs querry
695         *
696         */
697        private Operation modifyOperation( Operation operation, MeasurementConfiguration measureConfig )
698                                throws FilterConstructionException {
699    
700            Operation op = null;
701            if ( operation instanceof LogicalOperation ) {
702                LOG.logDebug( "logical operation found" );
703                List<Operation> modOps = new ArrayList<Operation>();
704                List<Operation> ops = ( (LogicalOperation) operation ).getArguments();
705                for ( int i = 0; i < ops.size(); i++ ) {
706                    modOps.add( modifyOperation( ops.get( i ), measureConfig ) );
707                }
708                op = new LogicalOperation( ( (LogicalOperation) operation ).getOperatorId(), modOps );
709            } else if ( operation instanceof ComparisonOperation ) {
710                LOG.logDebug( "comparison operation found" );
711                op = ( getModifiedComparisonOperation( (ComparisonOperation) operation, measureConfig ) );
712            } else if ( operation instanceof SpatialOperation ) {
713                LOG.logDebug( "spatial operation not supported!" );
714            }
715    
716            Filter filter = measureConfig.getConstraint();
717            if ( filter != null ) {
718                // adds a predefined constraint taken from the measurements
719                // configuration
720                Operation constraint = ( (ComplexFilter) filter ).getOperation();
721                if ( op != null ) {
722                    ArrayList<Operation> ar = new ArrayList<Operation>( 2 );
723                    ar.add( constraint );
724                    ar.add( op );
725                    op = new LogicalOperation( OperationDefines.AND, ar );
726                } else {
727                    op = constraint;
728                }
729            }
730    
731            return op;
732        }
733    
734        /**
735         * returns the modified ComparisonOperation
736         *
737         */
738        private Operation getModifiedComparisonOperation( ComparisonOperation compOp,
739                                                          MeasurementConfiguration measuresConfig ) {
740    
741            if ( compOp instanceof PropertyIsBetweenOperation ) {
742                LOG.logDebug( "PropertyIsBetweenOperation found" );
743                // FIXME if function is supported by your wfs; use it! instead of
744                // this
745                ArrayList<Operation> temp = new ArrayList<Operation>();
746                // set the lower boundary
747                temp.add( new PropertyIsCOMPOperation( OperationDefines.PROPERTYISGREATERTHAN,
748                                                       new PropertyName( measuresConfig.getMeasurandPropertyName() ),
749                                                       ( (PropertyIsBetweenOperation) compOp ).getLowerBoundary() ) );
750                // set the upper boundary
751                temp.add( new PropertyIsCOMPOperation( OperationDefines.PROPERTYISLESSTHAN,
752                                                       new PropertyName( measuresConfig.getMeasurandPropertyName() ),
753                                                       ( (PropertyIsBetweenOperation) compOp ).getUpperBoundary() ) );
754                return new LogicalOperation( OperationDefines.AND, temp );
755    
756            } else if ( compOp instanceof PropertyIsCOMPOperation ) {
757                LOG.logDebug( "PropertyIsCompOperation found" );
758                // returns a PropertyIsCOMPOperation with modified PropertyName
759                return new PropertyIsCOMPOperation( compOp.getOperatorId(),
760                                                    new PropertyName( measuresConfig.getMeasurandPropertyName() ),
761                                                    ( (PropertyIsCOMPOperation) compOp ).getSecondExpression() );
762    
763            } else if ( compOp instanceof PropertyIsLikeOperation ) {
764                LOG.logDebug( "PropertyIsLike found" );
765                // returns a PropertyIsLikeOperation with modified PropertyName
766                return new PropertyIsLikeOperation( new PropertyName( measuresConfig.getMeasurandPropertyName() ),
767                                                    ( (PropertyIsLikeOperation) compOp ).getLiteral(),
768                                                    ( (PropertyIsLikeOperation) compOp ).getWildCard(),
769                                                    ( (PropertyIsLikeOperation) compOp ).getSingleChar(),
770                                                    ( (PropertyIsLikeOperation) compOp ).getEscapeChar() );
771    
772            } else if ( compOp instanceof PropertyIsNullOperation ) {
773                LOG.logDebug( "PropertyIsNull is not supported!" );
774            }
775    
776            return null;
777        }
778    }