001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/csw/control/ISO19119RequestFactory.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    
037    package org.deegree.portal.standard.csw.control;
038    
039    import java.io.BufferedReader;
040    import java.io.InputStream;
041    import java.io.InputStreamReader;
042    import java.util.Properties;
043    
044    import org.deegree.datatypes.QualifiedName;
045    import org.deegree.enterprise.control.RPCStruct;
046    import org.deegree.framework.log.ILogger;
047    import org.deegree.framework.log.LoggerFactory;
048    import org.deegree.framework.util.StringTools;
049    import org.deegree.model.filterencoding.Literal;
050    import org.deegree.model.filterencoding.Operation;
051    import org.deegree.model.filterencoding.OperationDefines;
052    import org.deegree.model.filterencoding.PropertyIsCOMPOperation;
053    import org.deegree.model.filterencoding.PropertyName;
054    
055    /**
056     * A <code>${type_name}</code> class.<br/> TODO class description
057     *
058     * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
059     * @author last edited by: $Author: mschneider $
060     *
061     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
062     */
063    public class ISO19119RequestFactory extends CSWRequestFactory {
064    
065        private static final ILogger LOG = LoggerFactory.getLogger( ISO19119RequestFactory.class );
066    
067        // private static final char WILDCARD = '*';
068        // private static final String OUTPUTSCHEMA = "csw:profile";
069        private static final String OUTPUTSCHEMA = "http://www.isotc211.org/2005/gmd";
070    
071        private RPCStruct struct = null;
072    
073        private Properties requestElementsProps = new Properties();
074    
075        /**
076         *
077         *
078         */
079        public ISO19119RequestFactory() {
080            try {
081                InputStream is = ISO19119RequestFactory.class.getResourceAsStream( "ISO19119requestElements.properties" );
082                this.requestElementsProps.load( is );
083            } catch ( Exception e ) {
084                LOG.logError( e.getMessage(), e );
085            }
086        }
087    
088        /**
089         * creates a GetRecord request that is conform to the OGC Stateless Web Service Catalog Profil and GDI NRW catalog
090         * specifications from a RPC struct.
091         *
092         * @param struct
093         *            RPC structure containing the request parameter
094         * @param resultType
095         * @return GetFeature request as a string
096         */
097        @Override
098        public String createRequest( RPCStruct struct, String resultType ) {
099    
100            this.struct = struct;
101    
102            InputStream is = null;
103            InputStreamReader ireader = null;
104            BufferedReader br = null;
105            StringBuffer sb = null;
106            String request = null;
107    
108            is = ISO19119RequestFactory.class.getResourceAsStream( "CSWGetRecordsTemplate.xml" );
109            // is = ISO19119RequestFactory.class.getResourceAsStream( "CSWGetRecordByIdTemplate.xml" );
110    
111            try {
112                ireader = new InputStreamReader( is );
113                br = new BufferedReader( ireader );
114                sb = new StringBuffer( 50000 );
115    
116                while ( ( request = br.readLine() ) != null ) {
117                    sb.append( request );
118                }
119                request = sb.toString();
120                br.close();
121    
122            } catch ( Exception e ) {
123                LOG.logError( e.getMessage(), e );
124            }
125    
126            request = replaceVarsInSearchRequest( request, resultType );
127            // request = replaceVarsInOverviewRequest( request );
128    
129            return request;
130        }
131    
132        private String replaceVarsInSearchRequest( String request, String resultType ) {
133    
134            String filter = createFilterEncoding();
135            LOG.logDebug( "created filter: ", filter );
136            request = request.replaceFirst( "\\$FILTER", filter );
137    
138            request = request.replaceFirst( "\\$OUTPUTSCHEMA", OUTPUTSCHEMA );
139    
140            request = request.replaceFirst( "\\$RESULTTYPE", resultType );
141    
142            String startPos = "1"; // default is 1 according to OGC CSW-spec
143            if ( struct.getMember( RPC_STARTPOSITION ) != null ) {
144                startPos = (String) struct.getMember( RPC_STARTPOSITION ).getValue();
145            }
146            request = request.replaceFirst( "\\$STARTPOSITION", startPos );
147    
148            String maxRecords = Integer.toString( config.getMaxRecords() ); // default is 10 (according to spec)
149            request = request.replaceFirst( "\\$MAXRECORDS", maxRecords );
150    
151            // For 2.0.0
152            // String queryType = "csw:service"; // dataset, dataseries, application
153            // // FOR BOTH CSW2.0.0 AND CSW2.0.2 !
154            String queryType = "csw:service"; // dataset, dataseries, service, application
155            if ( struct.getMember( RPC_TYPENAME ) != null ) {
156                queryType = (String) struct.getMember( RPC_TYPENAME ).getValue();
157            }
158            /*
159             * if ( struct.getMember( RPC_TYPENAME ) != null ) { queryType = (String) struct.getMember( RPC_TYPENAME
160             * ).getValue(); if ( !"gmd:MD_Metadata".equals( queryType ) && !"csw:Record".equals( queryType )) {
161             * LOG.logError( StringTools.concat( 100, "typename ", queryType, " is not a supported type.", "Suuported types
162             * are: ", "gmd:MD_Metadata", "csw:Record" ) ); queryType = "gmd:MD_Metadata"; } }
163             */
164            request = request.replaceFirst( "\\$TYPENAME", queryType );
165    
166            String elementSet = "brief"; // brief, summary, full
167            if ( struct.getMember( RPC_ELEMENTSETNAME ) != null ) {
168                elementSet = (String) struct.getMember( RPC_ELEMENTSETNAME ).getValue();
169            }
170            request = request.replaceFirst( "\\$ELEMENTSETNAME", elementSet );
171    
172            return request;
173        }
174    
175        /**
176         * Creates a filter text according to the given parameters of the rpc request to be added to the GetRecords request
177         *
178         * @return the filter xml fragment
179         */
180        private String createFilterEncoding() {
181    
182            StringBuffer sb = new StringBuffer( 2000 );
183            int expCounter = 0;
184    
185            sb.append( "<csw:Constraint version='1.0.0'><ogc:Filter>" );
186    
187            // build filter encoding structure, handle all known fields sequentially
188            String s = null;
189    
190            s = handleServiceSearch();
191            if ( ( s != null ) && ( s.length() > 0 ) ) {
192                expCounter++;
193                sb.append( s );
194            }
195    
196            // NOTE: if some of the methods below are needed,
197            // copy them from ISO19115RequestFactory and adapt them where needed.
198    
199            // s = handleFileIdentifier();
200            // if ( ( s != null ) && ( s.length() > 0 ) ) {
201            // expCounter++;
202            // sb.append( s );
203            // }
204    
205            // s = handleParentIdentifier();
206            // if ( ( s != null ) && ( s.length() > 0 ) ) {
207            // expCounter++;
208            // sb.append( s );
209            // }
210    
211            // s = handleKeywords();
212            // if ( ( s != null ) && ( s.length() > 0 ) ) {
213            // expCounter++;
214            // sb.append( s );
215            // }
216    
217            // s = handleDate();
218            // if ( ( s != null ) && ( s.length() > 0 ) ) {
219            // expCounter++;
220            // sb.append( s );
221            // }
222    
223            // s = handleBbox();
224            // if ( ( s != null ) && ( s.length() > 0 ) ) {
225            // expCounter++;
226            // sb.append( s );
227            // }
228    
229            if ( expCounter > 1 ) {
230                sb.insert( "<csw:Constraint version='1.0.0'><ogc:Filter>".length(), "<ogc:And>" );
231                sb.append( "</ogc:And>" );
232            }
233    
234            sb.append( "</ogc:Filter></csw:Constraint>" );
235    
236            return sb.toString();
237        }
238    
239        /**
240         * @return Returns a string containing the service search part of the filter condition.
241         */
242        private String handleServiceSearch() {
243    
244            StringBuffer sb = new StringBuffer( 2000 );
245    
246            String[] t = null;
247            if ( struct.getMember( Constants.RPC_SERVICESEARCH ) != null ) {
248                String s = (String) struct.getMember( Constants.RPC_SERVICESEARCH ).getValue();
249                t = StringTools.toArray( s, "|", true );
250            }
251    
252            if ( ( t != null ) && ( t.length > 0 ) ) {
253                // sb.append( "<ogc:Or>" );
254                for ( int i = 0; i < t.length; i++ ) {
255                    if ( ( t[i] != null ) && ( t[i].length() > 0 ) ) {
256                        // replace invalid chars
257                        // t[i] = StringExtend.replace( t[i], "'", " ", true );
258                        // t[i] = StringExtend.replace( t[i], "\"", " ", true );
259    
260                        // determine the way to build FilterEncoding part
261                        String cf_props = requestElementsProps.getProperty( Constants.CONF_SERVICESEARCH );
262                        String[] cf = cf_props.split( ";" );
263    
264                        for ( int k = 0; k < cf.length; k++ ) {
265                            String strOp = t[i];
266                            if ( ( strOp != null ) && ( strOp.length() > 0 ) ) {
267                                Operation op = createOperation( OperationDefines.PROPERTYISEQUALTO, cf[k], strOp );
268                                sb.append( op.toXML() );
269                            }
270                        }
271                    }
272                }
273                // sb.append( "</ogc:Or>" );
274            }
275    
276            return sb.toString();
277        }
278    
279        /**
280         * Creates an operation in the csw GetRecords request
281         *
282         * @param opId
283         *            the operationID, ex: PROPERTYISEQUALTO, PROPERTYISELIKE
284         * @param property
285         *            what property to compare to, ex: apiso:title
286         * @param value
287         *            to compare to
288         *
289         * @return The created operation
290         */
291        private Operation createOperation( int opId, String property, Object value ) {
292    
293            Operation op = null;
294    
295            switch ( opId ) {
296            case OperationDefines.PROPERTYISEQUALTO:
297                op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISEQUALTO,
298                                                  new PropertyName( new QualifiedName( property ) ),
299                                                  new Literal( (String) value ) );
300                break;
301    
302            // case OperationDefines.PROPERTYISLIKE:
303            // char wildCard = WILDCARD;
304            // char singleChar = '?';
305            // char escapeChar = '/';
306            // String lit = wildCard + (String)value + wildCard;
307            // op = new PropertyIsLikeOperation( new PropertyName( new QualifiedName( property ) ),
308            // new Literal( lit ), wildCard, singleChar, escapeChar );
309            // break;
310            // case OperationDefines.PROPERTYISLESSTHANOREQUALTO:
311            // op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISLESSTHANOREQUALTO,
312            // new PropertyName( new QualifiedName( property ) ),
313            // new Literal( (String)value ) );
314            // break;
315            // case OperationDefines.PROPERTYISGREATERTHANOREQUALTO:
316            // op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISGREATERTHANOREQUALTO,
317            // new PropertyName( new QualifiedName( property ) ),
318            // new Literal( (String)value ) );
319            // break;
320            // case OperationDefines.BBOX:
321            // op = new SpatialOperation( OperationDefines.BBOX,
322            // new PropertyName( new QualifiedName( property ) ),
323            // (Geometry)value );
324            // break;
325            // case OperationDefines.PROPERTYISNULL:
326            // op = new PropertyIsNullOperation( new PropertyName( new QualifiedName( property ) ) );
327            // break;
328    
329            default:
330                op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISEQUALTO,
331                                                  new PropertyName( new QualifiedName( property ) ),
332                                                  new Literal( (String) value ) );
333            }
334    
335            return op;
336        }
337    
338    }