Ignore:
Timestamp:
04/12/06 15:02:34 (13 years ago)
Author:
mpritcha
Message:

Various updates, including moving doSearch method to SearchAgent? (since only thing different between searches is now the term).

Location:
TI01-discovery/trunk/ws-Discovery2/src/ndg/services/discovery
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • TI01-discovery/trunk/ws-Discovery2/src/ndg/services/discovery/DiscoveryServiceSkeleton.java

    r1793 r1801  
    2929                discoveryserviceapi.SearchType requestContent = request.getDoFullTextSearch(); 
    3030                FullTextSearchAgent agent = new FullTextSearchAgent( requestContent.getTerm() ); 
     31                if ( requestContent.getTerm().length() > 0 ) 
     32                { 
     33                        agent.setDoTerm( true ); 
     34                } 
    3135 
    3236                if ( requestContent.isSetStart() ) 
     
    4347                { 
    4448                        agent.setOrderBy( requestContent.getOrderBy().toString() ); 
     49                        agent.setDoOrderBy( true ); 
     50                        if ( requestContent.isSetOrderByDirection() ) 
     51                        { 
     52                                agent.setOrderByDirection( requestContent.getOrderByDirection().toString() ); 
     53                        } 
    4554                } 
    4655 
     
    5160                                agent.addNewScope( requestContent.getScopeArray(i).toString() ); 
    5261                        } 
     62                        agent.setDoScope( true ); 
     63                } 
     64 
     65                if ( requestContent.isSetBoundingBox() ) 
     66                { 
     67                        agent.setLimitWest( requestContent.getBoundingBox().getLimitWest() ); 
     68                        agent.setLimitSouth( requestContent.getBoundingBox().getLimitSouth() ); 
     69                        agent.setLimitEast( requestContent.getBoundingBox().getLimitEast() ); 
     70                        agent.setLimitNorth( requestContent.getBoundingBox().getLimitNorth() ); 
     71                        agent.setDoSpatio( true ); 
     72                } 
     73 
     74                if ( requestContent.isSetDateRange() ) 
     75                { 
     76                        agent.setDateRangeStart( requestContent.getDateRange().getDateRangeStart() ); 
     77                        agent.setDateRangeEnd( requestContent.getDateRange().getDateRangeEnd() ); 
     78                        agent.setDoTemporal( true ); 
    5379                } 
    5480 
  • TI01-discovery/trunk/ws-Discovery2/src/ndg/services/discovery/FullTextSearchAgent.java

    r1793 r1801  
    11package ndg.services.discovery; 
    2  
    3 import java.util.Hashtable; 
    4 import java.util.Iterator; 
    5 import java.util.Vector; 
    6 import java.util.Properties; 
    7 import java.math.BigInteger; 
    8  
    9 import java.io.BufferedReader; 
    10 import java.io.InputStreamReader; 
    11 import java.io.ByteArrayInputStream; 
    12 import java.io.IOException; 
    13  
    14 import javax.xml.xpath.*; 
    15 import javax.xml.*; 
    16 import javax.xml.namespace.*; 
    17 import org.xml.sax.InputSource; 
    18 import org.w3c.dom.*; 
    19  
    20 import org.apache.xmlrpc.XmlRpc; 
    21 import org.apache.xmlrpc.XmlRpcClient; 
    222 
    233/** 
     
    288public class FullTextSearchAgent extends SearchAgent implements Searchable { 
    299 
    30         // Input parameters specific to FullTextSearch 
    31         private String term; 
    32  
    3310        /** 
    34          * Default no-arg constructor, not used. 
     11         * Default no-arg constructor. 
    3512         */ 
    3613        public FullTextSearchAgent() {} 
    3714 
    3815        /** 
    39          * Another constructor 
     16         * Constructor to set term. 
    4017         */ 
    41         public FullTextSearchAgent( 
    42                 String myTerm, 
    43                 BigInteger myStart, 
    44                 int myHowMany, 
    45                 String myOrderBy, 
    46                 int myResultId ) 
     18        public FullTextSearchAgent(String term)  
    4719        { 
    48                 this.term = myTerm; 
    49                 this.start = myStart; 
    50                 this.howMany = howMany; 
    51                 this.orderBy = orderBy; 
    52                 this.resultId = myResultId; 
     20                this.setTerm( term ); 
    5321        } 
    5422 
    5523        /** 
    56          * Minimal constructor 
     24         * Sets the fullTextSearch term 
     25         * Overrides setTerm method of SearchAgent 
     26         * @param s String 
    5727         */ 
    58         public FullTextSearchAgent(String myTerm) 
     28        public void setTerm(String s) 
    5929        { 
    60                 this.term = myTerm; 
     30                this.term = "collection('/db/discovery/original')//root()[. &= '"+ s +"']"; 
    6131        } 
    62  
    63         public SearchSummary doSearch() { 
    64  
    65                 SearchSummary result = new SearchSummary(); 
    66                 XmlRpc.setEncoding("UTF-8"); 
    67                 Vector myResultDocuments = new Vector(); 
    68  
    69                 try 
    70                 { 
    71                  
    72                         // Load properties file (in root of .aar archive, i.e. from "build/classes") 
    73                         ClassLoader loader = getClass().getClassLoader(); 
    74  
    75                         // Set xmlDbURI as class variable so can reuse it in error messages 
    76                         String uri = properties.getProperty("xmlrpc.uri"); 
    77  
    78                         // Create xmlrpc client & set username, password 
    79                         XmlRpcClient xmlrpc = new XmlRpcClient( uri ); 
    80                         xmlrpc.setBasicAuthentication(properties.getProperty("xmlrpc.username"),properties.getProperty("xmlrpc.password")); 
    81  
    82  
    83                         //1. Execute the search 
    84                         Vector queryParams = new Vector(); 
    85  
    86                         // Load fullText XQuery from a file 
    87                         BufferedReader xqueryReader = new BufferedReader(  
    88                                 new InputStreamReader( loader.getResourceAsStream(  
    89                                         "DiscoveryService.fullTextSearch.xq"  
    90                                 ) ) 
    91                         ); 
    92                         String xqueryStr = ""; 
    93                         boolean eof = false; 
    94                         while (!eof) 
    95                         { 
    96                                 String line; 
    97                                 line = xqueryReader.readLine(); 
    98                                 if (line == null) 
    99                                 { 
    100                                         eof = true; 
    101                                 } 
    102                                 else 
    103                                 { 
    104                                         xqueryStr += line + "\n"; 
    105                                 } 
    106                         } 
    107                         xqueryReader.close(); 
    108  
    109                         // Substitute components of Xquery depending on input options 
    110                         //subst_spatial1 = let $connection := sql:get-connection("org.postgresql.Driver", "jdbc:postgresql://glue.badc.rl.ac.uk/ndg_spatial", "postgres", "postgresDB") 
    111                         //subst_spatial2 = let $sql_result := sql:execute($connection, "select id from spatio where id like '/db%' limit 10;", fn:true()) 
    112                         //subst_sortfield = $i/ndgDoc/moles/dgMetadata/dgMetadataRecord/dgDataEntity/dgDataSummary/dgDataCoverage/dgSpatioTemporalCoverage/dgSpatioTemporalRange/dgTemporalCoverage/DateRange/DateRangeStart 
    113                         //subst_result = fn:distinct-values($x_result/text()[.=$sql_result/sql:row/id/text()]) 
    114                         //or subst_result = $x_result 
    115  
    116                         // Substitute __term__ in the xquery for value from request message 
    117                         xqueryStr = xqueryStr.replaceAll("__term__", term); 
    118                         //xqueryStr = xqueryStr.replaceAll("__orderBy__", orderBy); 
    119  
    120                         // Construct clause to add scope restriction if requested 
    121                         String scopeClause = ""; 
    122                         if ( this.scopes.size() > 0) 
    123                         { 
    124                                 Iterator it = scopes.iterator(); 
    125                                 scopeClause += " and ( ./ndgDoc/keywords/keyword |= \'"; 
    126                                 if ( it.hasNext() ) 
    127                                 { 
    128                                         scopeClause += (String)it.next() + " "; 
    129                                 } 
    130                                 scopeClause += "\' ) "; 
    131                         } 
    132                         xqueryStr = xqueryStr.replaceAll("__scope__", scopeClause); 
    133                         System.out.println("Xquery was \n" + xqueryStr); 
    134  
    135                         queryParams.addElement( xqueryStr.getBytes("UTF-8") );  
    136  
    137                         queryParams.addElement( this.howMany ); 
    138                         queryParams.addElement( this.start );  
    139  
    140                         Hashtable options = new Hashtable(); 
    141                         options.put("indent", "yes"); 
    142                         options.put("encoding", "UTF-8"); 
    143                         options.put("process-xsl-pi", "no"); 
    144                         queryParams.addElement( options ); 
    145                         byte[] resultByteArray = (byte[])xmlrpc.execute( "query", queryParams ); 
    146                         ByteArrayInputStream resultStream = new ByteArrayInputStream( resultByteArray ); 
    147  
    148                         // Mark the beginning of the Stream, so can reset before each xpath evaluation (!) 
    149                         resultStream.mark( resultStream.available() ); 
    150                         InputSource resultSource = new InputSource( resultStream ); 
    151                          
    152                         XPath xpath = XPathFactory.newInstance().newXPath(); 
    153                         String hitsExpr = "/exist:result/@hits";  
    154                         String documentExpr = "//exist:result/document"; 
    155                         xpath.setNamespaceContext( new existNamespaceContextImpl() ); 
    156  
    157                         // If there is a successful search but with no hits, exist sets hitCount=0 rather than hits=0 !! 
    158                         // Need to check that the thing returned by xpath will convert to an int 
    159                         try 
    160                         { 
    161                                 int xpathHits = (new Integer( xpath.evaluate(hitsExpr, resultSource) )).intValue(); 
    162                                 result.setHits( xpathHits ); 
    163                         } 
    164                         catch (NumberFormatException e) 
    165                         { 
    166                                 result.setHits( 0 ); 
    167                         } 
    168                          
    169                         resultStream.reset(); 
    170                         NodeList nodeList = (NodeList)xpath.evaluate( documentExpr, resultSource, XPathConstants.NODESET );  
    171                          
    172                         if ( result.getHits() > 0) 
    173                         { 
    174                                 Vector documents = new Vector(); 
    175                                 for (int i=0; i<nodeList.getLength(); i++) 
    176                                 { 
    177                                         Hashtable thisDoc = new Hashtable(); 
    178                                         thisDoc.put("name", nodeList.item(i).getFirstChild().getNodeValue() ); 
    179                                         thisDoc.put("matches", 1); 
    180                                         thisDoc.put("position", i); 
    181                                         documents.add( thisDoc ); 
    182                                 } 
    183                                 result.setStatus( true ); 
    184                                 result.setStatusMessage( "Success" ); 
    185                                 result.setDocuments( documents );        
    186                         } 
    187                         else 
    188                         { 
    189                                 result.setStatus( false ); 
    190                                 result.setStatusMessage("Search was successful but generated no results."); 
    191                         } 
    192                          
    193                          
    194  
    195                 } 
    196                 catch (org.apache.xmlrpc.XmlRpcException e) 
    197                 { 
    198                         status = false; 
    199                         statusMessage = "Search failed - reason : " + e.toString(); 
    200                         result.setStatus(false); 
    201                         result.setStatusMessage( statusMessage ); 
    202                 } 
    203                 catch (Exception e) 
    204                 { 
    205                         status = false; 
    206                         statusMessage = "An error ocurred - details : " + e.toString(); 
    207                         result.setStatus( status ); 
    208                         result.setStatusMessage( statusMessage ); 
    209                 } 
    210  
    211                 return result; 
    212         } 
    213  
    214         public class existNamespaceContextImpl implements NamespaceContext 
    215     { 
    216         public String getNamespaceURI(String prefix) 
    217         { 
    218                         return "http://exist.sourceforge.net/NS/exist"; 
    219         } 
    220       
    221                 // Doesn't matter what the prefix in the source doc is, override it 
    222                 // Important thing is that the namespace URI matches, and that 
    223                 // whatever prefix is set here, is used in the xpath query 
    224         public String getPrefix(String namespace) 
    225         { 
    226                         return "exist"; 
    227         } 
    228  
    229         public Iterator getPrefixes(String namespace) 
    230         { 
    231             return null; 
    232         } 
    233     }  
    234  
    235         // setter methods for start, howMany, OrderBy already defined in superclass SearchAgent 
    23632 
    23733} 
  • TI01-discovery/trunk/ws-Discovery2/src/ndg/services/discovery/SearchAgent.java

    r1793 r1801  
    77import java.util.Date; 
    88import java.math.BigInteger; // needed because xmlbeans uses this for xsd:positiveInteger 
     9import java.math.BigDecimal; // needed because xmlbeans uses this for xsd:decimal 
     10import java.util.Calendar;  // needed because xmlbeans uses this for xsd:date 
    911import java.io.BufferedReader; 
    1012import java.io.InputStreamReader; 
     13import java.io.ByteArrayInputStream; 
    1114import java.io.IOException; 
     15import java.text.DecimalFormat; 
     16import java.text.SimpleDateFormat; 
     17 
     18import javax.xml.namespace.*; 
     19import javax.xml.xpath.*; 
     20import javax.xml.*; 
     21import org.xml.sax.InputSource; 
     22import org.w3c.dom.*; 
    1223 
    1324import org.apache.xmlrpc.XmlRpc; 
     
    2637        public static final BigInteger startDefault = new BigInteger("1"); 
    2738        public static final BigInteger howManyDefault = new BigInteger("30"); 
     39        boolean doSpatio = false; // flags whether spatio search should be included in search 
     40        boolean doTemporal = false;             // flags whether temporal search should be included in search 
     41        boolean doTerm = false;         // flags whether term should be included in search 
     42        boolean doScope = false; 
     43        boolean doOrderBy = false; 
     44        String xqueryStr = ""; // set intial value from template 
    2845 
    2946        // Input parameters 
     
    3148        BigInteger start = startDefault; 
    3249        BigInteger howMany = howManyDefault; 
    33         String orderBy; 
     50        String term = ""; 
     51        String orderBy;                                                 // representation used in WSDL e.g. "date", "dataCentre" 
     52        String orderByField = "";                               // xquery / xpath expression representing orderBy field 
     53        String orderByDirection = "ascending";  //default orderBy direction 
     54        // TODO ...add orderByDirection (and to WSDL) 
    3455        Vector scopes = new Vector(); 
    3556 
    36         float limitNorth; 
    37         float limitSouth; 
    38         float limitWest; 
    39         float limitEast; 
    40         Date dateRangeStart; 
    41         Date dateRangeEnd; 
     57        BigDecimal limitWest; 
     58        BigDecimal limitSouth; 
     59        BigDecimal limitEast; 
     60        BigDecimal limitNorth; 
     61        Calendar dateRangeStart; 
     62        Calendar dateRangeEnd; 
    4263 
    4364        // Output parameters 
     
    79100 
    80101        /** 
     102         * Sets the search term. 
     103         * Overridden by FullTextSearchAgent 
     104         * @param s String 
     105         */ 
     106        public void setTerm(String s) 
     107        { 
     108                this.term = s; 
     109        } 
     110 
     111 
     112        /** 
    81113         * Sets the field by which to sort the result set 
    82114         * @param s String, one of "date", "dataCentre" 
     
    84116        public void setOrderBy(String s) 
    85117        { 
     118                this.orderBy = s; 
     119                 
    86120                if ( s.equals("date") ) 
    87121                { 
    88                         this.orderBy = " order by $i//DIF_Creation_Date"; 
    89                 } 
    90                 else if ( s.equals("dataCentre") ) 
    91                 { 
    92                         this.orderBy = "order by $i//Data_Center/Data_Center_Name/Short_Name"; 
    93                 } 
    94                 else 
    95                 { 
    96                         this.orderBy = "order by document-uri($i)"; 
    97                 } 
     122                        this.orderByField = "{document($name)/dgMetadata/dgMetadataRecord/dgDataEntity/dgDataSummary/dgDataCoverage/dgTemporalCoverage/DateRange/DateRangeStart}"; 
     123                } 
     124 
     125                if ( s.equals("dataCentre") ) 
     126                { 
     127                        // TODO ...not correct yet (should look up Organisation moles record) 
     128                        this.orderByField = "{document($name)/dgMetadata/dgMetadataRecord/dgDataEntity/dgDataRoles/dgDataCurator/dgRoleHolder/dgOrganisationID/repositoryIdentifier}"; 
     129                } 
     130        } 
     131 
     132        /** 
     133         * Sets the direction in which to sort the result set 
     134         * @param s String, one of "ascending", "descending" 
     135         */ 
     136        public void setOrderByDirection(String s) 
     137        { 
     138                this.orderByDirection = s; 
    98139        } 
    99140 
     
    118159        /** 
    119160         * Sets north bound of BoundingBox. 
    120          * <p>Value should be float. 
     161         * <p>Value should be BigDecimal. 
    121162         * @param f value of north bound of search box 
    122163         */ 
    123         public void setLimitNorth(float f) 
    124         { 
    125                 if ( f <= 90.0 && f >= -90.0 ) 
     164 
     165        /** 
     166         * Returns scopes as space-separated String 
     167         * @return String containing scope keywords separated by spaces 
     168         */ 
     169        public String getScopesAsString() 
     170        { 
     171                String scopesStr = ""; 
     172                Iterator it = this.scopes.iterator(); 
     173                while ( it.hasNext() ) 
     174                { 
     175                        scopesStr += (String) it.next(); 
     176                } 
     177                return scopesStr; 
     178        } 
     179 
     180        /** 
     181         * Sets north bound of BoundingBox. 
     182         * <p>Value should be BigDecimal. 
     183         * @param f value of north bound of search box 
     184         */ 
     185 
     186 
     187        public void setLimitNorth(BigDecimal f) 
     188        { 
     189                if ( f.floatValue() <= 90.0 && f.floatValue() >= -90.0 ) 
    126190                { 
    127191                        this.limitNorth = f; 
     
    131195        /** 
    132196         * Sets south bound of BoundingBox. 
    133          * <p>Value should be float. 
    134          * @param f value of north bound of search box 
    135          */ 
    136         public void setLimitSouth(float f) 
    137         { 
    138                 if ( f <= 90.0 && f >= -90.0 ) 
     197         * <p>Value should be BigDecimal. 
     198         * @param f value of south bound of search box 
     199         */ 
     200        public void setLimitSouth(BigDecimal f) 
     201        { 
     202                if ( f.floatValue() <= 90.0 && f.floatValue() >= -90.0 ) 
    139203                { 
    140204                        this.limitSouth = f; 
     
    144208        /** 
    145209         * Sets south bound of BoundingBox. 
    146          * <p>Value should be float. 
    147          * @param f value of north bound of search box 
    148          */ 
    149         public void setLimitWest(float f) 
    150         { 
    151                 if ( f <= 180.0 && f >= -180.0 ) 
     210         * <p>Value should be BigDecimal. 
     211         * @param f value of west bound of search box 
     212         */ 
     213        public void setLimitWest(BigDecimal f) 
     214        { 
     215                if ( f.floatValue() <= 180.0 && f.floatValue() >= -180.0 ) 
    152216                { 
    153217                        this.limitWest = f; 
     
    157221        /** 
    158222         * Sets south bound of BoundingBox. 
    159          * <p>Value should be float. 
    160          * @param f value of north bound of search box 
    161          */ 
    162         public void setLimitEast(float f) 
    163         { 
    164                 if ( f <= 180.0 && f >= -180.0 ) 
     223         * <p>Value should be BigDecimal. 
     224         * @param f value of west bound of search box 
     225         */ 
     226        public void setLimitEast(BigDecimal f) 
     227        { 
     228                if ( f.floatValue() <= 180.0 && f.floatValue() >= -180.0 ) 
    165229                { 
    166230                        this.limitEast = f; 
     
    173237         * @param f value of north bound of search box 
    174238         */ 
    175         public void setDateRangeStart(String s) 
    176         { 
    177  
     239        public void setDateRangeStart(Calendar c) 
     240        { 
     241                this.dateRangeStart = c; 
    178242        } 
    179243 
     
    183247         * @param f value of north bound of search box 
    184248         */ 
    185         public void setDateRangeEnd(String s) 
    186         { 
    187  
    188         } 
     249        public void setDateRangeEnd(Calendar c) 
     250        { 
     251                this.dateRangeEnd = c; 
     252        } 
     253 
     254        /** 
     255         * Sets whether spatio search should be done. 
     256         * <p>Value should be boolean. 
     257         * @param b 
     258         */ 
     259        public void setDoSpatio(boolean b) 
     260        { 
     261                this.doSpatio = b; 
     262        } 
     263 
     264        /** 
     265         * Sets whether temporal search should be done. 
     266         * <p>Value should be boolean. 
     267         * @param b 
     268         */ 
     269        public void setDoTemporal(boolean b) 
     270        { 
     271                this.doTemporal = b; 
     272        } 
     273 
     274        /** 
     275         * Sets whether term search should be done. 
     276         * <p>Value should be boolean. 
     277         * @param b 
     278         */ 
     279        public void setDoTerm(boolean b) 
     280        { 
     281                this.doTerm = b; 
     282        } 
     283 
     284        /** 
     285         * Sets whether orderby should be done. 
     286         * <p>Value should be boolean. 
     287         * @param b 
     288         */ 
     289        public void setDoOrderBy(boolean b) 
     290        { 
     291                this.doOrderBy = b; 
     292        } 
     293 
     294        /** 
     295         * Sets whether scope check should be done. 
     296         * <p>Value should be boolean. 
     297         * @param b 
     298         */ 
     299        public void setDoScope(boolean b) 
     300        { 
     301                this.doScope = b; 
     302        } 
     303 
     304        /** 
     305         * Executes the search and returns a SearchSummary object 
     306         */ 
     307        public SearchSummary doSearch() { 
     308 
     309                SearchSummary result = new SearchSummary(); 
     310                XmlRpc.setEncoding("UTF-8"); 
     311                Vector myResultDocuments = new Vector(); 
     312                xqueryStr = xqueryStrTemplate; //set initial value from template 
     313 
     314                try 
     315                { 
     316                 
     317                        // Load properties file (in root of .aar archive, i.e. from "build/classes") 
     318                        //ClassLoader loader = getClass().getClassLoader(); 
     319 
     320                        // Set xmlDbURI as class variable so can reuse it in error messages 
     321                        String uri = properties.getProperty("xmlrpc.uri"); 
     322 
     323                        // Create xmlrpc client & set username, password 
     324                        XmlRpcClient xmlrpc = new XmlRpcClient( uri ); 
     325                        xmlrpc.setBasicAuthentication(properties.getProperty("xmlrpc.username"),properties.getProperty("xmlrpc.password")); 
     326 
     327 
     328                        //1. Prepare & execute the search 
     329                        Vector queryParams = new Vector(); 
     330 
     331                        // Substitute values in template xquery string 
     332                        xqueryStr = xqueryStr.replaceFirst("__subst_term__", this.term); 
     333                        xqueryStr = xqueryStr.replaceFirst("__subst_scope__", this.getScopesAsString() ); 
     334                        //"/dgMetadata/dgMetadataRecord/dgDataEntity/dgDataSummary/dgDataCoverage/dgTemporalCoverage/DateRange/DateRangeStart" 
     335                        xqueryStr = xqueryStr.replaceFirst("__subst_orderByField__", this.orderByField); 
     336                         
     337                        // Construct the search clause for spatio temporal search, if necessary 
     338                        String spatialClause = ""; 
     339                        try 
     340                        { 
     341                                if (  
     342                                        doSpatio &&  
     343                                        limitWest != null && 
     344                                        limitSouth != null && 
     345                                        limitNorth != null && 
     346                                        limitEast != null 
     347                                ) 
     348                                { 
     349                                        String latFormatPattern = "#0.00"; 
     350                                        String lonFormatPattern = "##0.00"; 
     351                                        DecimalFormat latFormat = new DecimalFormat( latFormatPattern ); 
     352                                        DecimalFormat lonFormat = new DecimalFormat( lonFormatPattern ); 
     353 
     354                                        spatialClause = " sbox_overlap_box( coordinates, sbox'("+ 
     355                                                lonFormat.format( limitWest.floatValue() )+"d,"+ 
     356                                                latFormat.format( limitSouth.floatValue() )+"d),("+ 
     357                                                lonFormat.format( limitEast.floatValue() )+"d,"+ 
     358                                                latFormat.format( limitNorth.floatValue() )+"d)') "; 
     359                                         
     360                                } 
     361                                else { 
     362                                        doSpatio = false; //just in case any components of coordinates were null 
     363                                } 
     364                        } 
     365                        catch (Exception e) 
     366                        { 
     367                                System.out.println("Error converting coordinates to SQL: " + e.toString() ); 
     368                                doSpatio = false; 
     369                        } 
     370 
     371                        String temporalClause = ""; 
     372                        try 
     373                        { 
     374                                if ( 
     375                                        doTemporal && 
     376                                        dateRangeStart != null && 
     377                                        dateRangeEnd != null && 
     378                                        dateRangeEnd.getTimeInMillis() > dateRangeStart.getTimeInMillis() 
     379                                ) 
     380                                { 
     381                                        String format = "yyyy-MM-dd"; 
     382                                        SimpleDateFormat sdf = new SimpleDateFormat(format); 
     383 
     384                                        temporalClause = " (startdate, enddate) OVERLAPS (DATE '"+sdf.format( dateRangeStart.getTime() )+"', DATE '"+ sdf.format( dateRangeEnd.getTime() ) +"') "; 
     385                                } 
     386                                else 
     387                                { 
     388                                        doTemporal = false; // just in case any components of date range were null 
     389                                } 
     390                        } 
     391                        catch (Exception e) 
     392                        { 
     393                                System.out.println("Error converting date to SQL: " + e.toString() ); 
     394                                temporalClause = ""; 
     395                                doTemporal = false; 
     396                        }                        
     397 
     398                        String whereClause = ""; 
     399                        if ( doSpatio && doTemporal ) 
     400                        { 
     401                                whereClause = " WHERE " + spatialClause + " AND " + temporalClause + " "; 
     402                        } 
     403                        else if ( doSpatio && !doTemporal ) 
     404                        { 
     405                                whereClause = " WHERE " + spatialClause + " "; 
     406                        } 
     407                        else if ( doTemporal && !doSpatio ) 
     408                        { 
     409                                whereClause = " WHERE " + temporalClause + " "; 
     410                        } 
     411                        else 
     412                        { 
     413                                whereClause = ""; 
     414                        } 
     415 
     416                        xqueryStr = xqueryStr.replaceFirst("__subst_spatioTempWhereClause__", whereClause ); 
     417                        xqueryStr = xqueryStr.replaceFirst("__subst_orderByDirection__", this.orderByDirection); 
     418 
     419                        xqueryStr = xqueryStr.replaceFirst("__subst_doTerm__", this.doTerm ? "fn:true()" : "fn:false()"); 
     420                        xqueryStr = xqueryStr.replaceFirst("__subst_doSpatioTemp__", (this.doSpatio | this.doTemporal) ? "fn:true()" : "fn:false()"); 
     421                        xqueryStr = xqueryStr.replaceFirst("__subst_doOrderBy__", this.doOrderBy ? "fn:true()" : "fn:false()"); 
     422                        xqueryStr = xqueryStr.replaceFirst("__subst_doScope__", this.doScope ? "fn:true()" : "fn:false()"); 
     423 
     424                        System.out.println("Xquery was \n" + xqueryStr); 
     425 
     426                        queryParams.addElement( xqueryStr.getBytes("UTF-8") );  
     427 
     428                        queryParams.addElement( this.howMany.intValue() ); 
     429                        queryParams.addElement( this.start.intValue() );  
     430 
     431                        Hashtable options = new Hashtable(); 
     432                        options.put("indent", "yes"); 
     433                        options.put("encoding", "UTF-8"); 
     434                        options.put("process-xsl-pi", "no"); 
     435                        queryParams.addElement( options ); 
     436                        byte[] resultByteArray = (byte[])xmlrpc.execute( "query", queryParams ); 
     437                        ByteArrayInputStream resultStream = new ByteArrayInputStream( resultByteArray ); 
     438 
     439                        // Mark the beginning of the Stream, so can reset before each xpath evaluation (!) 
     440                        resultStream.mark( resultStream.available() ); 
     441                        InputSource resultSource = new InputSource( resultStream ); 
     442                         
     443                        XPath xpath = XPathFactory.newInstance().newXPath(); 
     444                        String hitsExpr = "/exist:result/@hits";  
     445                        String documentExpr = "//exist:result/document"; 
     446                        xpath.setNamespaceContext( new existNamespaceContextImpl() ); 
     447 
     448                        // If there is a successful search but with no hits, exist sets hitCount=0 rather than hits=0 !! 
     449                        // Need to check that the thing returned by xpath will convert to an int 
     450                        try 
     451                        { 
     452                                int xpathHits = (new Integer( xpath.evaluate(hitsExpr, resultSource) )).intValue(); 
     453                                result.setHits( xpathHits ); 
     454                        } 
     455                        catch (NumberFormatException e) 
     456                        { 
     457                                result.setHits( 0 ); 
     458                        } 
     459                         
     460                        resultStream.reset(); 
     461                        NodeList nodeList = (NodeList)xpath.evaluate( documentExpr, resultSource, XPathConstants.NODESET );  
     462                         
     463                        if ( result.getHits() > 0) 
     464                        { 
     465                                Vector documents = new Vector(); 
     466                                for (int i=0; i<nodeList.getLength(); i++) 
     467                                { 
     468                                        Hashtable thisDoc = new Hashtable(); 
     469                                        thisDoc.put("name", nodeList.item(i).getFirstChild().getNodeValue() ); 
     470                                        thisDoc.put("matches", 1); 
     471                                        thisDoc.put("position", i); 
     472                                        documents.add( thisDoc ); 
     473                                } 
     474                                result.setStatus( true ); 
     475                                result.setStatusMessage( "Success" ); 
     476                                result.setDocuments( documents );        
     477                        } 
     478                        else 
     479                        { 
     480                                result.setStatus( false ); 
     481                                result.setStatusMessage("Search was successful but generated no results."); 
     482                        } 
     483                         
     484                         
     485 
     486                } 
     487                catch (org.apache.xmlrpc.XmlRpcException e) 
     488                { 
     489                        status = false; 
     490                        statusMessage = "Search failed - reason : " + e.toString(); 
     491                        result.setStatus(false); 
     492                        result.setStatusMessage( statusMessage ); 
     493                } 
     494                catch (Exception e) 
     495                { 
     496                        status = false; 
     497                        statusMessage = "An error ocurred - details : " + e.toString(); 
     498                        result.setStatus( status ); 
     499                        result.setStatusMessage( statusMessage ); 
     500                } 
     501 
     502                return result; 
     503        } 
     504 
     505        public class existNamespaceContextImpl implements NamespaceContext 
     506    { 
     507        public String getNamespaceURI(String prefix) 
     508        { 
     509                        return "http://exist.sourceforge.net/NS/exist"; 
     510        } 
     511      
     512                // Doesn't matter what the prefix in the source doc is, override it 
     513                // Important thing is that the namespace URI matches, and that 
     514                // whatever prefix is set here, is used in the xpath query 
     515        public String getPrefix(String namespace) 
     516        { 
     517                        return "exist"; 
     518        } 
     519 
     520        public Iterator getPrefixes(String namespace) 
     521        { 
     522            return null; 
     523        } 
     524    }  
     525 
     526 
     527        public static String xqueryStrTemplate =  
     528"xquery version \"1.0\"; \n"+ 
     529"declare namespace sql=\"http://exist-db.org/xquery/sql\"; \n"+ 
     530"declare function local:getScope() as xs:string { \n"+ 
     531"   \"__subst_scope__\" \n"+ 
     532"}; \n"+ 
     533"declare function local:getOrderByField() as xs:string { \n"+ 
     534"   \"__subst_orderByField__\" \n"+ 
     535"}; \n"+ 
     536"declare function local:getSpatioTempWhereClause() as xs:string { \n"+ 
     537"   \"__subst_spatioTempWhereClause__\" \n"+ 
     538"}; \n"+ 
     539"declare function local:getOrderByDirection() as xs:string { \n"+ 
     540"   \"__subst_orderByDirection__\" \n"+ 
     541"}; \n"+ 
     542"declare function local:doSpatioTemp() as xs:boolean { \n"+ 
     543"   __subst_doSpatioTemp__ \n"+ 
     544"}; \n"+ 
     545"declare function local:doTerm() as xs:boolean { \n"+ 
     546"   __subst_doTerm__ \n"+ 
     547"}; \n"+ 
     548"declare function local:doOrderBy() as xs:boolean { \n"+ 
     549"   __subst_doOrderBy__ \n"+ 
     550"}; \n"+ 
     551"declare function local:doScope() as xs:boolean { \n"+ 
     552"   __subst_doScope__ \n"+ 
     553"}; \n"+ 
     554"declare function local:doSpatioTempQuery() as item()* { \n"+ 
     555"   let $connection := sql:get-connection(\"org.postgresql.Driver\", \""+properties.getProperty("jdbc.uri")+"\", \""+properties.getProperty("jdbc.username")+"\", \""+properties.getProperty("jdbc.password")+"\") \n"+ 
     556"   let $result := sql:execute($connection, fn:string-join( (\"select * from spatiotemp \", local:getSpatioTempWhereClause(),\";\"), \"\"), fn:true()) \n"+ 
     557"   let $s_result := ( \n"+ 
     558"       for $j in $result/sql:row/id/text() \n"+ 
     559"       return <document>{$j}</document> \n"+ 
     560"   ) \n"+ 
     561"   return $s_result \n"+ 
     562"}; \n"+ 
     563"declare function local:doTermQuery() as item()* { \n"+ 
     564"   (: Get result of full-text search :) \n"+ 
     565"   let $result := __subst_term__ \n"+ 
     566"   for $i in $result \n"+ 
     567"      return <document>{util:document-name($i)}</document> \n"+ 
     568"}; \n"+ 
     569"declare function local:mergeResults($arg1 as item()*, $arg2 as item()*) as item()* { \n"+ 
     570"   for $i in $arg1[./text()=$arg2/text()] \n"+ 
     571"   return <document>{$i/text()}</document> \n"+ 
     572"}; \n"+ 
     573"declare function local:filterByScope($arg1 as item()*) as item()* { \n"+ 
     574"   if ( local:doScope() ) then ( \n"+ 
     575"      for $i in $arg1 \n"+ 
     576"       let $coll := '/db/discovery/moles' \n"+ 
     577"       let $thisdoc := util:document-name($i) \n"+ 
     578"       let $name := string-join( ($coll , $thisdoc), '/' ) \n"+ 
     579"       let $molesdoc := document( $name ) \n"+ 
     580"        where document($name)//dgStructuredKeyword/dgValidTerm[. &= local:getScope()] \n"+ 
     581"      return $i \n"+ 
     582"   ) \n"+ 
     583"   else $arg1 \n"+ 
     584"}; \n"+ 
     585"declare function local:orderBy($arg1 as item()* )as item()* { \n"+ 
     586"   if ( local:doOrderBy() ) then ( \n"+ 
     587"      if ( local:getOrderByDirection() = \"descending\" ) then ( \n"+ 
     588"         for $i in $arg1 \n"+ 
     589"         order by local:getOrderByField() descending \n"+ 
     590"         return $i \n"+ 
     591"      ) \n"+ 
     592"      else ( \n"+ 
     593"         for $i in $arg1 \n"+ 
     594"         order by local:getOrderByField() ascending \n"+ 
     595"         return $i \n"+ 
     596"      ) \n"+ 
     597"   ) \n"+ 
     598"   else $arg1 \n"+ 
     599"}; \n"+ 
     600 
     601"declare function local:buildResult() as item()* { \n"+ 
     602" \n"+ 
     603"   let $termResult := ( \n"+ 
     604"      if ( local:doTerm() ) then local:doTermQuery() \n"+ 
     605"      else () \n"+ 
     606"   ) \n"+ 
     607"   let $spatioResult := ( \n"+ 
     608"      if ( local:doSpatioTemp() ) then local:doSpatioTempQuery() \n"+ 
     609"      else () \n"+ 
     610"   ) \n"+ 
     611"   (: populate $seq with appropriate combination of result, depending on search options :) \n"+ 
     612"   let $seq := ( \n"+ 
     613    
     614"      if ( local:doTerm() ) then ( \n"+ 
     615"         if ( local:doSpatioTemp() ) then ( \n"+ 
     616"            local:mergeResults($termResult, $spatioResult) \n"+ 
     617"         ) \n"+ 
     618"         else ( \n"+ 
     619"            $termResult \n"+ 
     620"         ) \n"+ 
     621"      ) \n"+ 
     622"      else ( \n"+ 
     623"         if ( local:doSpatioTemp() ) then ( \n"+ 
     624"            $spatioResult \n"+ 
     625"         ) \n"+ 
     626"         else ( \n"+ 
     627"            () \n"+ 
     628"         ) \n"+ 
     629"      ) \n"+ 
     630"   ) \n"+ 
     631"   for $i in local:orderBy( local:filterByScope( $seq ) ) \n"+ 
     632"   return $i \n"+ 
     633"}; \n"+ 
     634"for $i in local:buildResult() \n"+ 
     635"return $i \n"; 
     636 
    189637} 
    190  
Note: See TracChangeset for help on using the changeset viewer.