001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/datastore/sql/VirtualContentProvider.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 by:
006 Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstraße 19
030 53177 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042 ---------------------------------------------------------------------------*/
043 package org.deegree.io.datastore.sql;
044
045 import java.sql.Connection;
046 import java.util.List;
047
048 import org.deegree.datatypes.Types;
049 import org.deegree.i18n.Messages;
050 import org.deegree.io.datastore.schema.content.ConstantContent;
051 import org.deegree.io.datastore.schema.content.FieldContent;
052 import org.deegree.io.datastore.schema.content.FunctionParam;
053 import org.deegree.io.datastore.schema.content.SQLFunctionCall;
054 import org.deegree.io.datastore.schema.content.SpecialContent;
055 import org.deegree.io.datastore.schema.content.SpecialContent.VARIABLE;
056 import org.deegree.model.filterencoding.ComplexFilter;
057 import org.deegree.model.filterencoding.Filter;
058 import org.deegree.model.filterencoding.FilterTools;
059 import org.deegree.model.spatialschema.Envelope;
060 import org.deegree.model.spatialschema.Geometry;
061 import org.deegree.model.spatialschema.GeometryFactory;
062
063 /**
064 * Responsible for determining the value of properties that are mapped to {@link SQLFunctionCall}s.
065 * <p>
066 * This involves the lookup of the values of variables ({@link SpecialContent} instances).
067 *
068 * <table border="1">
069 * <tr>
070 * <th>Variable name</th>
071 * <th>Description</th>
072 * </tr>
073 * <tr>
074 * <td>$QUERY.BBOX</td>
075 * <td>Bounding box of the query (null if it is not present).</td>
076 * </tr>
077 * </table>
078 * </p>
079 *
080 * @see SQLFunctionCall
081 * @see SpecialContent
082 *
083 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
084 * @author last edited by: $Author: apoth $
085 *
086 * @version $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $
087 */
088 public class VirtualContentProvider {
089
090 // used in case that no BBOX is available
091 private static final Envelope DEFAULT_BBOX = GeometryFactory.createEnvelope( 0.0, 0.0, 0.0, 0.0, null );
092
093 private Filter filter;
094
095 private AbstractSQLDatastore ds;
096
097 private Connection conn;
098
099 /**
100 * Creates a new instance of {@link VirtualContentProvider}.
101 *
102 * @param filter
103 * @param ds
104 * @param conn
105 */
106 VirtualContentProvider( Filter filter, AbstractSQLDatastore ds, Connection conn ) {
107 this.filter = filter;
108 this.ds = ds;
109 this.conn = conn;
110 }
111
112 /**
113 * Appends a {@link SQLFunctionCall} to the given {@link StatementBuffer}.
114 * <p>
115 * This includes the correct qualification of all columns that are used as {@link FunctionParam}s.
116 *
117 * @param query
118 * @param tableAlias
119 * @param call
120 */
121 public void appendSQLFunctionCall( StatementBuffer query, String tableAlias, SQLFunctionCall call ) {
122
123 String callString = call.getCall();
124 int[] usedVars = call.getUsedVars();
125 List<FunctionParam> params = call.getParams();
126 for ( int j = 0; j < usedVars.length; j++ ) {
127 int varNo = usedVars[j];
128 String varString = "\\$" + varNo;
129 FunctionParam param = params.get( varNo - 1 );
130 if ( param instanceof FieldContent ) {
131 String replace = tableAlias + "." + ( (FieldContent) param ).getField().getField();
132 callString = callString.replaceAll( varString, replace );
133 } else if ( param instanceof ConstantContent ) {
134 String replace = ( (ConstantContent) param ).getValue();
135 callString = callString.replaceAll( varString, replace );
136 } else if ( param instanceof SpecialContent ) {
137 appendSpecialContentValue( query, (SpecialContent) param );
138 callString = callString.replaceFirst( varString, "?" );
139 } else {
140 assert false;
141 }
142 }
143 query.append( callString );
144 }
145
146 /**
147 * Appends the variable from a {@link SpecialContent} property to the given
148 * {@link StatementBuffer}.
149 *
150 * @param query
151 * @param param
152 */
153 public void appendSpecialContentValue( StatementBuffer query, SpecialContent param ) {
154
155 VARIABLE var = param.getVariable();
156
157 switch ( var ) {
158 case QUERY_BBOX: {
159
160 Object bboxDBGeometry = null;
161
162 try {
163 Envelope requestBBOX = DEFAULT_BBOX;
164
165 if ( this.filter instanceof ComplexFilter ) {
166 Object[] objects = FilterTools.extractFirstBBOX( (ComplexFilter) filter );
167 if ( objects[0] != null ) {
168 requestBBOX = (Envelope) objects[0];
169 }
170 }
171 Geometry geometry = GeometryFactory.createSurface( requestBBOX, null );
172 bboxDBGeometry = this.ds.convertDeegreeToDBGeometry( geometry, param.getSRS(), this.conn );
173 } catch ( Exception e ) {
174 String msg = Messages.getMessage( "DATASTORE_EXTRACTBBOX" );
175 throw new RuntimeException( msg, e );
176 }
177
178 // TODO: remove quick hack to make this work on Oracle
179 if (this.ds.getClass().getName().equals( "org.deegree.io.datastore.sql.oracle.OracleDatastore" )) {
180 query.addArgument( bboxDBGeometry, Types.STRUCT );
181 } else {
182 query.addArgument( bboxDBGeometry, Types.OTHER );
183 }
184
185
186 break;
187 }
188 default: {
189 assert false;
190 }
191 }
192 }
193 }