org.n52.sos.ds.pgsql.PGSQLDescribeSensorDAO.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.sos.ds.pgsql.PGSQLDescribeSensorDAO.java

Source

/***************************************************************
 Copyright (C) 2008
 by 52 North Initiative for Geospatial Open Source Software GmbH
    
 Contact: Andreas Wytzisk
 52 North Initiative for Geospatial Open Source Software GmbH
 Martin-Luther-King-Weg 24
 48155 Muenster, Germany
 info@52north.org
    
 This program is free software; you can redistribute and/or modify it under 
 the terms of the GNU General Public License version 2 as published by the 
 Free Software Foundation.
    
 This program is distributed WITHOUT ANY WARRANTY; even without the implied
 WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 General Public License for more details.
    
 You should have received a copy of the GNU General Public License along with
 this program (see gnu-gpl v2.txt). If not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or
 visit the Free Software Foundation web page, http://www.fsf.org.
    
 Author: <LIST OF AUTHORS/EDITORS>
 Created: <CREATION DATE>
 Modified: <DATE OF LAST MODIFICATION (optional line)>
***************************************************************/

package org.n52.sos.ds.pgsql;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.apache.xmlbeans.XmlException;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.n52.sos.SosConfigurator;
import org.n52.sos.SosConstants;
import org.n52.sos.SosDateTimeUtilities;
import org.n52.sos.SosConstants.DescribeSensorParams;
import org.n52.sos.ds.IDescribeSensorDAO;
import org.n52.sos.ogc.filter.FilterConstants;
import org.n52.sos.ogc.filter.TemporalFilter;
import org.n52.sos.ogc.filter.FilterConstants.TimeOperator;
import org.n52.sos.ogc.gml.GMLConstants;
import org.n52.sos.ogc.gml.time.ISosTime;
import org.n52.sos.ogc.gml.time.TimeInstant;
import org.n52.sos.ogc.gml.time.TimePeriod;
import org.n52.sos.ogc.ows.OwsExceptionReport;
import org.n52.sos.ogc.ows.OwsExceptionReport.ExceptionCode;
import org.n52.sos.ogc.ows.OwsExceptionReport.ExceptionLevel;
import org.n52.sos.ogc.sensorML.ProcedureHistory;
import org.n52.sos.ogc.sensorML.ProcedureHistoryEvent;
import org.n52.sos.request.SosDescribeSensorRequest;
import org.n52.sos.resp.SensorDocument;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.WKTReader;

/**
 * DAO of PostgreSQL DB for GetCapabilities Operation
 * 
 * @author Christoph Stasch
 * 
 */
public class PGSQLDescribeSensorDAO implements IDescribeSensorDAO {

    /** the logger, used to log exceptions and additonaly information */
    private static Logger log = Logger.getLogger(PGSQLDescribeSensorDAO.class);

    /** connection pool for getting connections to DB */
    private PGConnectionPool cpool;

    /**
     * standard constructor sets up the logger
     */
    public PGSQLDescribeSensorDAO(PGConnectionPool cpool) {
        this.cpool = cpool;
    }

    /**
     * @return Returns the sensor description as result of the describeSensor operation
     */
    public SensorDocument getSensorDocument(SosDescribeSensorRequest request) throws OwsExceptionReport {

        // sensorDocument which should be returned
        SensorDocument result = null;

        String filename = null;
        String descriptionType = null;
        String smlFile = null;

        String query = "SELECT " + PGDAOConstants.descUrlCn + " , " + PGDAOConstants.descTypeCn + " , "
                + PGDAOConstants.smlFileCn + " FROM " + PGDAOConstants.procTn + " WHERE " + PGDAOConstants.procIDCn
                + " = '" + request.getProcedure() + "'";

        Connection con = null;
        try {
            con = cpool.getConnection();

            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {
                filename = rs.getString(PGDAOConstants.descUrlCn);
                descriptionType = rs.getString(PGDAOConstants.descTypeCn);
                smlFile = rs.getString(PGDAOConstants.smlFileCn);

                log.debug("FILENAME: " + filename);
                log.debug("DESCTYPE: " + descriptionType);
                log.debug("SMLFILE: " + smlFile);
            }
        } catch (SQLException sqle) {
            OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
            log.error("An error occured while query the procedure from the SOS database!", sqle);
            se.addCodedException(ExceptionCode.NoApplicableCode, null, sqle);
            throw se;
        } finally {
            if (con != null) {
                cpool.returnConnection(con);
            }
        }

        // check whether SMLFile or Url is set
        if (filename == null && smlFile == null) {

            // throw ex
            OwsExceptionReport se = new OwsExceptionReport();
            se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                    SosConstants.DescribeSensorParams.procedure.toString(),
                    "No sensorML file was found for the requested procedure " + request.getProcedure());
            log.error("No sensorML file was found for the requested procedure " + request.getProcedure());
            throw se;

        } else {

            if (filename != null && descriptionType != null && smlFile == null) {
                // return sensorML from folder

                if (!descriptionType.equalsIgnoreCase(request.getOutputFormat())) {
                    OwsExceptionReport se = new OwsExceptionReport();
                    se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                            SosConstants.DescribeSensorParams.outputFormat.toString(),
                            "The value of the output format is wrong and has to be " + descriptionType
                                    + " for procedure " + request.getProcedure());
                    log.error("The value of the output format is wrong and has to be " + descriptionType
                            + " for procedure " + request.getProcedure());
                    throw se;
                }

                try {

                    File sensorFile = null;
                    log.info(filename);

                    // read in the description file
                    if (filename.startsWith("standard/")) {
                        filename = filename.replace("standard/", "");
                        sensorFile = new File(SosConfigurator.getInstance().getSensorDir(), filename);
                    } else {
                        sensorFile = new File(filename);
                    }

                    FileInputStream fis = new FileInputStream(sensorFile);

                    // parse the file into an org.w3c.dom.Document
                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = factory.newDocumentBuilder();
                    Document doc = builder.parse(fis);

                    // close inpuStream of description file
                    fis.close();

                    // set result
                    result = new SensorDocument(doc);

                } catch (FileNotFoundException fnfe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", fnfe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, fnfe);
                    throw se;
                } catch (IOException ioe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", ioe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, ioe);
                    throw se;
                } catch (ParserConfigurationException pce) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", pce);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, pce);
                    throw se;
                } catch (SAXException saxe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", saxe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, saxe);
                    throw se;
                }
            } else {
                // return sensorML from DB

                try {

                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = factory.newDocumentBuilder();
                    org.w3c.dom.Document doc = builder.parse(new InputSource(new StringReader(smlFile)));

                    result = new SensorDocument(doc);

                } catch (SAXException saxe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", saxe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, saxe);
                    throw se;
                } catch (IOException ioe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", ioe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, ioe);
                    throw se;
                } catch (ParserConfigurationException pce) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", pce);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, pce);
                    throw se;
                }
            }
        }

        return result;
    }

    /**
     * @return Returns the sensor description as result of the describeSensor operation
     */
    public String getSensorDescription(SosDescribeSensorRequest request) throws OwsExceptionReport {

        // sensorDocument which should be returned
        String result = null;

        String filename = null;
        String descriptionType = null;
        String smlFile = null;

        String query = "SELECT " + PGDAOConstants.descUrlCn + " , " + PGDAOConstants.descTypeCn + " , "
                + PGDAOConstants.smlFileCn + " FROM " + PGDAOConstants.procTn + " WHERE " + PGDAOConstants.procIDCn
                + " = '" + request.getProcedure() + "'";

        Connection con = null;
        try {
            con = cpool.getConnection();

            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {
                filename = rs.getString(PGDAOConstants.descUrlCn);
                descriptionType = rs.getString(PGDAOConstants.descTypeCn);
                smlFile = rs.getString(PGDAOConstants.smlFileCn);

                log.debug("FILENAME: " + filename);
                log.debug("DESCTYPE: " + descriptionType);
                log.debug("SMLFILE: " + smlFile);
            }
        } catch (SQLException sqle) {
            OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
            log.error("An error occured while query the procedure from the SOS database!", sqle);
            se.addCodedException(ExceptionCode.NoApplicableCode, null, sqle);
            throw se;
        } finally {
            if (con != null) {
                cpool.returnConnection(con);
            }
        }

        // check whether SMLFile or Url is set
        if (filename == null && smlFile == null) {

            // throw ex
            OwsExceptionReport se = new OwsExceptionReport();
            se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                    SosConstants.DescribeSensorParams.procedure.toString(),
                    "No sensorML file was found for the requested procedure " + request.getProcedure());
            log.error("No sensorML file was found for the requested procedure " + request.getProcedure());
            throw se;

        } else {

            if (filename != null && descriptionType != null && smlFile == null) {
                // return sensorML from folder

                if (descriptionType.equalsIgnoreCase(request.getOutputFormat())) {
                    OwsExceptionReport se = new OwsExceptionReport();
                    se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                            SosConstants.DescribeSensorParams.outputFormat.toString(),
                            "The value of the output format is wrong and has to be " + descriptionType
                                    + " for procedure " + request.getProcedure());
                    log.error("The value of the output format is wrong and has to be " + descriptionType
                            + " for procedure " + request.getProcedure());
                    throw se;
                }

                try {

                    File sensorFile = null;
                    log.info(filename);

                    // read in the description file
                    if (filename.startsWith("standard/")) {
                        filename = filename.replace("standard/", "");
                        sensorFile = new File(SosConfigurator.getInstance().getSensorDir(), filename);
                    } else {
                        sensorFile = new File(filename);
                    }

                    FileInputStream fis = new FileInputStream(sensorFile);

                    byte[] b = new byte[fis.available()];
                    fis.read(b);
                    fis.close();

                    // set result
                    result = new String(b);

                } catch (FileNotFoundException fnfe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", fnfe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, fnfe);
                    throw se;
                } catch (IOException ioe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    log.error("An error occured while parsing the sensor description document!", ioe);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null, ioe);
                    throw se;
                }
            } else {
                // return sensorML from DB
                result = smlFile;
            }
        }

        return result;

    }

    /**
     * @return Returns the actual position of a sensor
     */
    public Point getActualPosition(SosDescribeSensorRequest request) throws OwsExceptionReport {

        // actualPosition which should be returned
        Point actualPosition = null;

        String query = "SELECT AsText(" + PGDAOConstants.actualPositionCn + ") AS geomText , SRID("
                + PGDAOConstants.actualPositionCn + ") AS srid " + " FROM " + PGDAOConstants.procTn + " WHERE "
                + PGDAOConstants.procIDCn + " = '" + request.getProcedure() + "'";

        WKTReader wktReader = new WKTReader();
        Connection con = null;
        try {
            con = cpool.getConnection();

            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {

                // read position
                String geomWKT = rs.getString("geomText");
                int srid = Integer.MIN_VALUE;
                try {
                    Geometry geom = wktReader.read(geomWKT);
                    srid = rs.getInt("srid");
                    geom.setSRID(srid);
                    actualPosition = (Point) geom;
                } catch (Exception pe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null,
                            "Error while parsing geometry of procedure from SOS DB: " + pe.getMessage());
                    log.warn(se.getMessage());
                    throw se;
                }

            }
        } catch (SQLException sqle) {
            OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
            log.error("An error occured while query the procedure from the SOS database!", sqle);
            se.addCodedException(ExceptionCode.NoApplicableCode, null, sqle);
            throw se;
        } finally {
            if (con != null) {
                cpool.returnConnection(con);
            }
        }

        return actualPosition;

    }

    /**
     * 
     * queries dynamic sensor parameters from SOSmobile DB and returns history containing the dynamic
     * parameters
     * 
     * @param request
     *        describeSensor request
     * @return Returns history of dynamic sensor parameters
     */
    public ProcedureHistory getProcedureHistory(SosDescribeSensorRequest request) throws OwsExceptionReport {

        ProcedureHistory history = null;

        // build query
        StringBuilder query = new StringBuilder();

        query.append("SELECT " + PGDAOConstants.procHistProcedureIdCn + " , " + PGDAOConstants.procHistActiveCn
                + " , " + PGDAOConstants.mobileCn + " , AsText(" + PGDAOConstants.procHistPositionCn
                + ") AS geomText " + " , SRID(" + PGDAOConstants.procHistPositionCn + ") AS srid , "
                + "iso_timestamp(" + PGDAOConstants.procHistTimeStampCn + ") AS "
                + PGDAOConstants.procHistTimeStampCn + " FROM " + PGDAOConstants.procHistTn);

        if (request.getTime() != null && request.getTime().length > 0) {
            query.append(getWhereClause4Time(request.getTime(), request.getProcedure()));
        }

        Connection con = null;
        WKTReader wktReader = new WKTReader();
        Collection<ProcedureHistoryEvent> events = new ArrayList<ProcedureHistoryEvent>();
        try {
            con = cpool.getConnection();

            Statement stmt = con.createStatement();
            log.debug("PROCEDURE HISTORY QUERY[DescribeSensor Operation]: " + query);
            ResultSet rs = stmt.executeQuery(query.toString());
            while (rs.next()) {
                String procID = rs.getString(PGDAOConstants.procIDCn);

                // read position
                String geomWKT = rs.getString("geomText");
                int srid = Integer.MIN_VALUE;
                Point position = null;
                try {
                    Geometry geom = wktReader.read(geomWKT);
                    srid = rs.getInt("srid");
                    geom.setSRID(srid);
                    position = (Point) geom;
                } catch (Exception pe) {
                    OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                    se.addCodedException(ExceptionCode.NoApplicableCode, null,
                            "Error while parsing geometry of procedure history from SOSmobile DB: "
                                    + pe.getMessage());
                    log.warn(se.getMessage());
                    throw se;
                }

                // read time stamp
                String dateString = rs.getString(PGDAOConstants.timestampCn);
                DateTime timeStamp = null;
                timeStamp = SosDateTimeUtilities.parseIsoString2DateTime(dateString);

                // read active and mobile
                boolean mobile = rs.getBoolean(PGDAOConstants.mobileCn);
                boolean active = rs.getBoolean(PGDAOConstants.activeCn);

                ProcedureHistoryEvent event = new ProcedureHistoryEvent(procID, position, active, mobile,
                        timeStamp);
                events.add(event);

            }
        } catch (SQLException sqle) {
            OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
            log.error("An error occured while query the procedure from the SOS database!", sqle);
            se.addCodedException(ExceptionCode.NoApplicableCode, null, sqle);
            throw se;
        } finally {
            if (con != null) {
                cpool.returnConnection(con);
            }
        }
        history = new ProcedureHistory(events);
        return history;
    }

    /**
     * returns the where clause for the Time parameters of the describeSensor request
     * 
     * @param times
     *        Time[] which contains the TimeInstants or TimePeriods for which the where clause should be
     *        constructed
     * @return String containing the where clause for this Time[]
     * @throws XmlException
     *         if construction of the where clause failed
     * @throws OwsExceptionReport
     *         if construction of the where clause failed
     */
    private String getWhereClause4Time(TemporalFilter[] times, String procedure_id) throws OwsExceptionReport {

        // string which contains the where clause
        StringBuffer query = new StringBuffer();

        query.append(" WHERE " + PGDAOConstants.procHistProcedureIdCn + " = '" + procedure_id + "' ");

        TemporalFilter temporalFilter = times[0];

        ISosTime time = temporalFilter.getTime();
        if (time instanceof TimeInstant) {
            query.append(
                    createWhereClause4timeInstant((TimeInstant) time, temporalFilter.getOperator(), procedure_id));
        }

        if (time instanceof TimePeriod) {
            query.append(
                    createWhereClause4timePeriod((TimePeriod) time, temporalFilter.getOperator(), procedure_id));
        }

        // get TimeNodes
        for (int j = 1; j < times.length; j++) {

            temporalFilter = times[j];

            time = temporalFilter.getTime();
            if (time instanceof TimeInstant) {
                query.append(createWhereClause4timeInstant((TimeInstant) time, temporalFilter.getOperator(),
                        procedure_id));
            }

            if (time instanceof TimePeriod) {
                query.append(createWhereClause4timePeriod((TimePeriod) time, temporalFilter.getOperator(),
                        procedure_id));
            }

        }

        return query.toString();
    } // end getWhereClause4Time

    /**
     * creates and returns the where clause for time period parameter
     * 
     * @param timePeriod
     *        TimePeriod object for which the where clause should be created
     * @param operator
     *        name of timeObs element (e.g. ogc:after or ogc:TEquals)
     * @return String containing the where clause for time period parameter
     * @throws ParseException
     *         if parsing begin or end date failed
     * @throws OwsExceptionReport
     *         if one parameter is incorrect or a required paramter is missing
     */
    private String createWhereClause4timePeriod(TimePeriod timePeriod, TimeOperator operator, String procedure_id)
            throws OwsExceptionReport {

        DateTime start = timePeriod.getStart();
        String indetStartTime = timePeriod.getStartIndet();
        DateTime end = timePeriod.getEnd();
        String indetEndTime = timePeriod.getEndIndet();
        Period duration = timePeriod.getDuration();

        String result = "";

        switch (operator) {

        // before
        case TM_Before:
            // //if indetPosition of endPosition = After throw exception!
            if (indetEndTime != null) {
                if (indetEndTime.equals(GMLConstants.IndetTimeValues.after.name())) {
                    OwsExceptionReport se = new OwsExceptionReport();
                    se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                            DescribeSensorParams.time.toString(),
                            "The value of indeterminatePosition = '" + indetEndTime
                                    + "'  of EndPosition in TimePeriod"
                                    + " is in conflict with the temporal operator of time = '" + operator);
                    throw se;
                }
            }

            result += " AND (" + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " < " + "'"
                    + SosDateTimeUtilities.formatDateTime2IsoString(end) + "'" + ")";
            break; // end before

        // after
        case TM_After:
            // if indetPosition of beginPosition = Before throw exception!
            if (indetEndTime != null) {
                if (indetEndTime.equals(GMLConstants.IndetTimeValues.before.name())) {
                    OwsExceptionReport se = new OwsExceptionReport();
                    se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                            DescribeSensorParams.time.toString(),
                            "The value of indeterminatePosition = '" + indetStartTime
                                    + "'  of StartPosition in TimePeriod"
                                    + " is in conflict with the temporal operator of time = '" + operator);
                    throw se;
                }
            }

            result += " AND (" + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " > " + "'"
                    + SosDateTimeUtilities.formatDateTime2IsoString(start) + "'" + ")";
            break; // end after

        // during
        case TM_During:

            /*
             * if duration not null, values between a duration should be returned. Only the endPosition
             * PGConfigurator.timestampCn or indeterminateTime of endPosition is read in. The begin Position
             * is not received attention. A timePeriod element which works may look like: 
             * <ogc:During>
             * <gml:TimePeriod> 
             * <gml:beginPosition indeterminatePosition="unknown"></gml:beginPosition>
             * <gml:endPosition indeterminatePosition="now">2005-10-05T10:17:00</gml:endPosition>
             * <gml:duration>P5M</gml:duration>
             * </gml:TimePeriod> 
             * </ogc:During>
             */
            if (duration != null) {

                if (indetEndTime != null && indetEndTime.equals(GMLConstants.IndetTimeValues.now.name())) {
                    end = new DateTime();
                }

                else if (end == null) {
                    OwsExceptionReport se = new OwsExceptionReport();
                    se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                            DescribeSensorParams.time.toString(),
                            "If duration is set, either timePosition of endPosition in timePeriod"
                                    + " must be set or indeterminatePosition of endPosition must be 'now' or 'unknown', where"
                                    + "'unknown' accords to 'now'.");
                    throw se;
                }
                DateTime begin = end.minus(duration);

                result += " AND (" + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " > "
                        + "'" + SosDateTimeUtilities.formatDateTime2IsoString(begin) + "'" + " AND "
                        + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " < " + "'"
                        + SosDateTimeUtilities.formatDateTime2IsoString(end) + "'" + ")";

            }

            else {
                if ((indetStartTime != null && indetStartTime.equals(GMLConstants.IndetTimeValues.before.name()))
                        && (indetEndTime != null
                                && indetEndTime.equals(GMLConstants.IndetTimeValues.after.name()))) {
                    OwsExceptionReport se = new OwsExceptionReport();
                    se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                            DescribeSensorParams.time.toString(),
                            "The value of indeterminatePosition of StartPosition ='" + indetStartTime
                                    + "'  and of indeterminatePosition of EndPosition ='" + indetEndTime
                                    + "' in TimePeriod" + " is in conflict with the temporal operator of time = '"
                                    + operator);
                    throw se;
                }

                result += " AND (" + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " > "
                        + "'" + SosDateTimeUtilities.formatDateTime2IsoString(start) + "'" + " AND "
                        + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " < " + "'"
                        + SosDateTimeUtilities.formatDateTime2IsoString(end) + "'" + ")";

            }
            break; // end during

        // after
        case TM_Equals:

            if (indetStartTime != null && indetEndTime != null
                    && indetStartTime.equals(FilterConstants.TimeOperator.TM_Before)
                    && indetEndTime.equals(FilterConstants.TimeOperator.TM_After)) {
                OwsExceptionReport se = new OwsExceptionReport();
                se.addCodedException(OwsExceptionReport.ExceptionCode.InvalidParameterValue,
                        DescribeSensorParams.time.toString(),
                        "The value of indeterminatePosition of StartPosition ='" + indetStartTime
                                + "'  and of indeterminatePosition of EndPosition ='" + indetEndTime
                                + "' in TimePeriod" + " is in conflict with the temporal operator of time = '"
                                + operator);
                throw se;
            }
            result += " AND (" + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " >= " + "'"
                    + SosDateTimeUtilities.formatDateTime2IsoString(start) + "'" + "AND "
                    + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " <= " + "'"
                    + SosDateTimeUtilities.formatDateTime2IsoString(end) + "'" + ")";
            break; // end after
        }

        return result.toString();
    } // end getWhereClause4timeInstant

    /**
     * creates the where clause for timeInstant parameter
     * 
     * @param timeInstant
     *        the timeInstant for which the where clause should be created
     * @param operator
     *        String containing the timeObs value (e.g. "after" or "before"...)
     * @return String representing the where clause for time instant
     * 
     * @throws ParseException
     *         if parsing the time parameter failed
     * @throws OwsExceptionReport
     *         if value for operator is incorrect
     */
    private String createWhereClause4timeInstant(TimeInstant timeInstant, TimeOperator operator,
            String procedure_id) throws OwsExceptionReport {

        DateTime timeValue = timeInstant.getValue();
        String result = "";

        // now build strings thru switching between operators
        switch (operator) {

        // before
        case TM_Before:
            result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " < '"
                    + SosDateTimeUtilities.formatDateTime2IsoString(timeValue) + "' ";
            break; // end before

        // after
        case TM_After:
            result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " > '"
                    + SosDateTimeUtilities.formatDateTime2IsoString(timeValue) + "' ";
            break; // end after

        // during
        case TM_During:
            result += createTimeInstantString4Tequals(timeInstant);
            break;// end during

        // equals
        case TM_Equals:
            result += createTimeInstantString4Tequals(timeInstant);
            break; // end equals

        default:
            OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
            se.addCodedException(ExceptionCode.InvalidParameterValue, DescribeSensorParams.time.toString(),
                    operator.name());
            throw se;
        }

        return result;
    } // end createWhereClause4TimeInstant

    /**
     * creates condition string for time instant with operator T_Equals or T_During
     * 
     * @param time
     *        time instant for which the condition string should be created
     * @return Returns condition string created from passed time instant
     */
    private String createTimeInstantString4Tequals(TimeInstant time) {
        String result = "";
        String indeterminateValue = time.getIndeterminateValue();
        DateTime timeValue = time.getValue();
        if (indeterminateValue != null) {
            // indeterminateTime = "after"
            if (indeterminateValue.equals(GMLConstants.IndetTimeValues.after.name())) {
                result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " > '"
                        + SosDateTimeUtilities.formatDateTime2IsoString(timeValue) + "' ";
            }

            // indeterminateTime = "before"
            else if (indeterminateValue.equals(GMLConstants.IndetTimeValues.before.name())) {
                result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " < '"
                        + SosDateTimeUtilities.formatDateTime2IsoString(timeValue) + "' ";
            }

            // indeterminateTime = "now"
            else if (indeterminateValue.equals(GMLConstants.IndetTimeValues.now.name())) {
                result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " = '"
                        + SosDateTimeUtilities.formatDateTime2IsoString(new DateTime()) + "' ";
            }

            // indeterminateTime = "unknown"
            else if (indeterminateValue.equals(GMLConstants.IndetTimeValues.unknown.name())) {
                result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " = '"
                        + SosDateTimeUtilities.formatDateTime2IsoString(timeValue) + "' ";
            }
        }

        // indeterminateTime is incorrect or not set, the during clause
        // without indeterminatTime param is created!!
        else {
            result += " AND " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn + " = '"
                    + SosDateTimeUtilities.formatDateTime2IsoString(timeValue) + "' ";
        }
        return result;
    } // end createTimeInstantString4Tequals

    /**
     * creates where clause for time period parameter
     * 
     * @param period
     *        time period, for which where clause should be created
     * @param procID
     *        id of procedure
     * @return Returns where clause for query
     */
    @SuppressWarnings("unused")
    private String createWhereClause4TimePeriod(TimePeriod period, String procID) {
        DateTime begin = period.getStart();
        DateTime end = period.getEnd();
        if (begin == null || end == null) {
            // TODO throw exception
        }
        String query = " WHERE (" + PGDAOConstants.procHistTimeStampCn + " <= '"
                + SosDateTimeUtilities.formatDateTime2IsoString(end) + "' AND " + PGDAOConstants.procHistTimeStampCn
                + ">= '" + SosDateTimeUtilities.formatDateTime2IsoString(begin) + "') AND "
                + PGDAOConstants.procHistProcedureIdCn + " ='" + procID + "';";
        return query;
    }

    /**
     * creates the where clause for getProcedureHistory operation, if time parameter of describeSensor request
     * is TimeInstant; if it is timeInstant, last actual parameters are returned
     * 
     * @param instant
     *        time instant of describeSensor request
     * @param procID
     *        id of procedure
     * @return Returns where clause
     * @throws OwsExceptionReport
     *         if time instant is incorrect
     */
    @SuppressWarnings("unused")
    private String createWhereClause4TimeInstant(TimeInstant instant, String procID) throws OwsExceptionReport {

        String query = " INNER JOIN (SELECT MAX(" + PGDAOConstants.procHistTimeStampCn + ") as time  FROM "
                + PGDAOConstants.procHistTn + " WHERE " + PGDAOConstants.procHistTimeStampCn + " < '";

        if (instant.getIndeterminateValue() != null) {

            if (instant.getIndeterminateValue().equals(GMLConstants.IndetTimeValues.now.name())) {
                query += SosDateTimeUtilities.formatDateTime2IsoString(new DateTime());
            } else {
                OwsExceptionReport se = new OwsExceptionReport(ExceptionLevel.DetailedExceptions);
                log.error(
                        "Only 'now' is supported as indeterminate time value in timeInstant parameter of DescribeSensor request!");
                se.addCodedException(ExceptionCode.InvalidParameterValue,
                        SosConstants.DescribeSensorParams.time.name(),
                        "Only 'now' is supported as indeterminate time value in timeInstant parameter of DescribeSensor request!");
                throw se;
            }
        }

        else if (instant.getValue() != null) {
            query += SosDateTimeUtilities.formatDateTime2IsoString(instant.getValue());
        }

        query += "' AND " + PGDAOConstants.procHistProcedureIdCn + " = '" + procID + "'";
        query += ") AS temp ON " + PGDAOConstants.procHistTn + "." + PGDAOConstants.procHistTimeStampCn
                + " = temp.time ";
        query += " WHERE " + PGDAOConstants.procHistProcedureIdCn + " = '" + procID + "';";

        return query;
    }

}