001 //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/resources/eclipse/files_template.xml $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 - Department of Geography, University of Bonn - 006 and 007 - lat/lon GmbH - 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.portal.cataloguemanager.control; 037 038 import java.io.IOException; 039 import java.nio.charset.Charset; 040 import java.util.ArrayList; 041 import java.util.HashMap; 042 import java.util.List; 043 import java.util.Map; 044 import java.util.UUID; 045 046 import org.deegree.datatypes.QualifiedName; 047 import org.deegree.enterprise.control.ajax.ResponseHandler; 048 import org.deegree.enterprise.control.ajax.WebEvent; 049 import org.deegree.framework.log.ILogger; 050 import org.deegree.framework.log.LoggerFactory; 051 import org.deegree.framework.util.Pair; 052 import org.deegree.framework.xml.XMLFragment; 053 import org.deegree.model.crs.CRSFactory; 054 import org.deegree.model.crs.CoordinateSystem; 055 import org.deegree.model.filterencoding.ComplexFilter; 056 import org.deegree.model.filterencoding.Filter; 057 import org.deegree.model.filterencoding.Literal; 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.PropertyIsLikeOperation; 063 import org.deegree.model.filterencoding.PropertyIsNullOperation; 064 import org.deegree.model.filterencoding.PropertyName; 065 import org.deegree.model.filterencoding.SpatialOperation; 066 import org.deegree.model.spatialschema.Geometry; 067 import org.deegree.model.spatialschema.GeometryFactory; 068 import org.deegree.ogcbase.CommonNamespaces; 069 import org.deegree.ogcbase.PropertyPath; 070 import org.deegree.ogcbase.SortProperty; 071 import org.deegree.ogcwebservices.csw.discovery.GetRecords; 072 import org.deegree.ogcwebservices.csw.discovery.Query; 073 import org.deegree.ogcwebservices.csw.discovery.GetRecords.RESULT_TYPE; 074 import org.deegree.portal.cataloguemanager.model.ExceptionBean; 075 076 /** 077 * TODO add class documentation here 078 * 079 * @author <a href="mailto:name@deegree.org">Andreas Poth</a> 080 * @author last edited by: $Author: admin $ 081 * 082 * @version $Revision: $, $Date: $ 083 */ 084 public class MetadataSearchListener extends AbstractSearchListener { 085 086 private static final ILogger LOG = LoggerFactory.getLogger( MetadataSearchListener.class ); 087 088 // private String[] ignoredChars = new String[] { ",", ";", "\\.", "\\+", "\\(", "\\)" }; 089 090 // private String[] cqp = new String[] { "{http://www.opengis.net/cat/csw/apiso/1.0}:Title" }; 091 092 // private String[] timecqp = new String[] { "{http://www.opengis.net/cat/csw/apiso/1.0}:date" }; 093 094 /* 095 * (non-Javadoc) 096 * 097 * @see 098 * org.deegree.enterprise.control.ajax.AbstractListener#actionPerformed(org.deegree.enterprise.control.ajax.WebEvent 099 * , org.deegree.enterprise.control.ajax.ResponseHandler) 100 */ 101 @SuppressWarnings("unchecked") 102 public void actionPerformed( WebEvent event, ResponseHandler resp ) 103 throws IOException { 104 105 config = getCatalogueManagerConfiguration( event ); 106 Map<String, String> param = event.getParameter(); 107 String query = param.get( "freeText" ); 108 String startDate = param.get( "from" ); 109 String endDate = param.get( "to" ); 110 String geographicIdentifier = param.get( "geogrID" ); 111 List<String> queryStrings = parseQuery( config, query ); 112 String bbox = getBBOX( geographicIdentifier ); 113 GetRecords getRecords; 114 try { 115 getRecords = createGetRecords( queryStrings, startDate, endDate, bbox ); 116 } catch ( Exception e ) { 117 LOG.logError( e ); 118 ExceptionBean bean = new ExceptionBean( this.getClass().getName(), e.getMessage() ); 119 resp.writeAndClose( true, bean ); 120 return; 121 } 122 List<Pair<String, XMLFragment>> result; 123 try { 124 result = performQuery( getRecords ); 125 } catch ( Throwable e ) { 126 LOG.logError( e ); 127 ExceptionBean bean = new ExceptionBean( this.getClass().getName(), e.getMessage() ); 128 resp.writeAndClose( true, bean ); 129 return; 130 } 131 List<SearchResultBean> formattedResult = null; 132 try { 133 formattedResult = formatResult( result ); 134 } catch ( Exception e ) { 135 LOG.logError( e ); 136 ExceptionBean bean = new ExceptionBean( this.getClass().getName(), e.getMessage() ); 137 resp.writeAndClose( true, bean ); 138 return; 139 } 140 141 // store search meta informations to be used for pageing 142 event.getSession().setAttribute( SEARCHRESULTINFO, searchResultInfos ); 143 144 int c = 0; 145 for ( SearchResultInfo sri : searchResultInfos ) { 146 c += sri.getNumberOfRecordsMatched(); 147 } 148 149 event.getSession().setAttribute( CURRENTSEARCH, getRecords ); 150 event.getSession().setAttribute( COUNTER, 0 ); 151 152 String charEnc = Charset.defaultCharset().displayName(); 153 resp.setContentType( "application/json; charset=" + charEnc ); 154 resp.writeAndClose( false, new Object[] { formattedResult, new Integer( c ), new Integer( 0 ) } ); 155 156 } 157 158 /** 159 * @param queryStrings 160 * @param startDate 161 * @param endDate 162 * @param bbox 163 * @return GetRecord request 164 * @throws Exception 165 */ 166 private GetRecords createGetRecords( List<String> queryStrings, String startDate, String endDate, String bbox ) 167 throws Exception { 168 List<Operation> opList = new ArrayList<Operation>( queryStrings.size() + 3 ); 169 List<Operation> notOpList = new ArrayList<Operation>( queryStrings.size() + 3 ); 170 for ( String searchString : queryStrings ) { 171 for ( String property : config.getSearchableProperties() ) { 172 PropertyName propertyName = new PropertyName( new QualifiedName( property ) ); 173 Operation operation = null; 174 if ( searchString.startsWith( "-" ) ) { 175 Literal literal = new Literal( '*' + searchString.substring( 1 ) + '*' ); 176 operation = new PropertyIsLikeOperation( propertyName, literal, '*', '?', '/', false ); 177 List<Operation> tmp = new ArrayList<Operation>(); 178 tmp.add( operation ); 179 operation = new LogicalOperation( OperationDefines.NOT, tmp ); 180 Operation notNull = new PropertyIsNullOperation( propertyName ); 181 tmp = new ArrayList<Operation>(); 182 tmp.add( operation ); 183 tmp.add( notNull ); 184 notOpList.add( new LogicalOperation( OperationDefines.OR, tmp ) ); 185 } else { 186 Literal literal = new Literal( '*' + searchString + '*' ); 187 operation = new PropertyIsLikeOperation( propertyName, literal, '*', '?', '/', false ); 188 opList.add( operation ); 189 } 190 191 } 192 } 193 LogicalOperation compare = null; 194 if ( opList.size() > 1 && notOpList.size() > 0 ) { 195 compare = new LogicalOperation( OperationDefines.OR, opList ); 196 notOpList.add( compare ); 197 compare = new LogicalOperation( OperationDefines.AND, notOpList ); 198 } else if ( opList.size() > 1 && notOpList.size() == 0 ) { 199 compare = new LogicalOperation( OperationDefines.OR, opList ); 200 } else if ( opList.size() == 0 && notOpList.size() > 1 ) { 201 compare = new LogicalOperation( OperationDefines.AND, notOpList ); 202 } else if ( opList.size() == 0 && notOpList.size() == 0 ) { 203 compare = new LogicalOperation( OperationDefines.AND, notOpList ); 204 } 205 206 List<Operation> opTimeList = new ArrayList<Operation>( queryStrings.size() + 3 ); 207 for ( String property : config.getDateProperties() ) { 208 PropertyName propertyName = new PropertyName( new QualifiedName( property ) ); 209 Literal start = new Literal( startDate ); 210 Literal end = new Literal( endDate ); 211 Operation operation = new PropertyIsBetweenOperation( propertyName, start, end ); 212 opTimeList.add( operation ); 213 } 214 215 List<Operation> allOps = new ArrayList<Operation>(); 216 if ( opList.size() > 1 || notOpList.size() > 1 ) { 217 allOps.add( compare ); 218 } else if ( opList.size() == 1 && notOpList.size() == 1 ) { 219 allOps.add( opList.get( 0 ) ); 220 allOps.add( notOpList.get( 0 ) ); 221 } else if ( opList.size() == 0 && notOpList.size() == 1 ) { 222 allOps.add( notOpList.get( 0 ) ); 223 } else if ( opList.size() == 1 && notOpList.size() == 0 ) { 224 allOps.add( opList.get( 0 ) ); 225 } 226 227 LogicalOperation time = new LogicalOperation( OperationDefines.OR, opTimeList ); 228 allOps.add( time ); 229 230 if ( bbox != null ) { 231 QualifiedName qn = new QualifiedName( "{http://www.opengis.net/cat/csw/apiso/1.0}:BoundingBox" ); 232 PropertyName propertyName = new PropertyName( qn ); 233 CoordinateSystem crs = CRSFactory.create( "EPSG:4326" ); 234 Geometry geom = GeometryFactory.createSurface( GeometryFactory.createEnvelope( bbox, crs ), crs ); 235 SpatialOperation sp = new SpatialOperation( OperationDefines.BBOX, propertyName, geom ); 236 allOps.add( sp ); 237 } 238 239 Filter filter = null; 240 if ( allOps.size() > 1 ) { 241 filter = new ComplexFilter( new LogicalOperation( OperationDefines.AND, allOps ) ); 242 } else { 243 filter = new ComplexFilter( allOps.get( 0 ) ); 244 } 245 List<QualifiedName> typeNames = new ArrayList<QualifiedName>(); 246 typeNames.add( new QualifiedName( "{http://www.isotc211.org/2005/gmd}:MD_Metadata" ) ); 247 SortProperty[] sortProperties = SortProperty.create( "apiso:Title", 248 CommonNamespaces.getNamespaceContext().getNamespaceMap() ); 249 Query query = new Query( "brief", new ArrayList<QualifiedName>(), new HashMap<String, QualifiedName>(), 250 new ArrayList<PropertyPath>(), filter, sortProperties, typeNames, 251 new HashMap<String, QualifiedName>() ); 252 return new GetRecords( UUID.randomUUID().toString(), "2.0.2", null, null, RESULT_TYPE.RESULTS, 253 "application/xml", "http://www.isotc211.org/2005/gmd", 1, config.getStepSize(), -1, 254 null, query ); 255 } 256 257 /** 258 * @param geographicIdentifier 259 * @return 260 */ 261 private String getBBOX( String geographicIdentifier ) { 262 if ( geographicIdentifier != null ) { 263 List<SpatialExtent> extents = config.getSpatialExtents(); 264 for ( SpatialExtent spatialExtent : extents ) { 265 if ( spatialExtent.getId().equalsIgnoreCase( geographicIdentifier ) ) { 266 return spatialExtent.getBbox(); 267 } 268 } 269 } 270 return null; 271 } 272 273 /** 274 * 275 * @param config 276 * @param query 277 * @return 278 */ 279 private List<String> parseQuery( CatalogueManagerConfiguration config, String query ) { 280 char[] ignoredChars = config.getIgnoreCharacters(); 281 for ( int i = 0; i < ignoredChars.length; i++ ) { 282 query = query.replace( ignoredChars[i], ' ' ).trim(); 283 } 284 List<String> list = new ArrayList<String>(); 285 StringBuilder sb = new StringBuilder(); 286 boolean open = false; 287 for ( int i = 0; i < query.length(); i++ ) { 288 if ( query.charAt( i ) == ' ' && !open && sb.length() > 0 ) { 289 list.add( sb.toString() ); 290 sb.delete( 0, sb.length() ); 291 } else if ( ( query.charAt( i ) == '"' || query.charAt( i ) == '\'' ) && !open ) { 292 open = true; 293 } else if ( ( query.charAt( i ) == '"' || query.charAt( i ) == '\'' ) && open ) { 294 open = false; 295 } else if ( query.charAt( i ) != ' ' || open ) { 296 sb.append( query.charAt( i ) ); 297 } 298 } 299 if ( sb.length() > 0 && sb.charAt( sb.length() - 1 ) != '"' && sb.charAt( sb.length() - 1 ) != '\'' ) { 300 list.add( sb.toString() ); 301 } 302 return list; 303 } 304 305 }