Changeset 3957 for TI01-discovery


Ignore:
Timestamp:
29/05/08 12:11:28 (11 years ago)
Author:
cbyrom
Message:

Large refactor of existing codebase to replace usage of eXist DB with
postgres:

  • adjust term search to use postgres DB
  • simplify search agents - no need to separate these since their difference

is minimal and it will simplify codestructure doing this

  • separate workflow into clearly defined methods
  • remove unnecessary field variables and properly encapsulate others
  • add logging using log4j framework
  • extend code to allow searches to be ran without term or termtype set
Location:
TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery
Files:
3 deleted
5 edited

Legend:

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

    r3950 r3957  
    88import java.util.Vector; 
    99import java.util.logging.Logger; 
     10 
     11import discoveryserviceapi.DoSearchDocument; 
    1012 
    1113/** 
     
    2123    private static final String[] LIST_NAMES = {"presentFormatList", "orderByFieldList", "scopeList", 
    2224        "termTypeList", "spatialOperatorList"}; 
     25 
     26        // Constants representing the possible, valid values for the various input list types 
     27        public static final String FULL_TEXT_TERM_TYPE = "fullText"; 
     28        public static final String AUTHOR_TERM_TYPE = "author"; 
     29        public static final String PARAMETER_TERM_TYPE = "parameter"; 
     30        public static final String OVERLAPS_OPERATOR_TYPE = "overlaps"; 
     31        public static final String WITHIN_OPERATOR_TYPE = "within"; 
     32        public static final String NO_OVERLAP_OPERATOR_TYPE = "doesNotOverlap"; 
     33         
    2334        /** 
    2435         * Performs the doFullTextSearch operation  
     
    3142        {  
    3243                logger.info("doSearch() invoked"); 
    33                 discoveryserviceapi.DoSearchReturnDocument response = discoveryserviceapi.DoSearchReturnDocument.Factory.newInstance(); 
     44                discoveryserviceapi.DoSearchReturnDocument response =  
     45                        discoveryserviceapi.DoSearchReturnDocument.Factory.newInstance(); 
    3446                discoveryserviceapi.SearchReturnType responseContent = response.addNewDoSearchReturn(); 
    3547 
    36                 // parse the request message 
    37                 discoveryserviceapi.SearchType requestContent = request.getDoSearch(); 
    38                 SearchAgent agent = null; 
    39  
    40                 if ( requestContent.getTermType().equals("fullText") ) 
    41                 { 
    42                         agent = new FullTextSearchAgent( requestContent.getTerm() ); 
    43                 } 
    44                 else if ( requestContent.getTermType().equals("author") ) 
    45                 { 
    46                         agent = new AuthorSearchAgent( requestContent.getTerm() ); 
    47                 } 
    48                 else if ( requestContent.getTermType().equals("parameter") ) 
    49                 { 
    50                         agent = new ParameterSearchAgent( requestContent.getTerm() ); 
    51                 } 
    52                 else 
    53                 { 
    54                         String errorMessage = "Invalid termType: please use getListNames to get the valid list term types"; 
    55                         logger.warning(errorMessage); 
    56                         throw new UnsupportedOperationException(errorMessage); 
    57                 } 
    58  
    59                 if ( requestContent.getTerm().length() > 0 ) 
    60                 { 
    61                         logger.info("Term set - will do term search"); 
    62                         agent.setDoTerm( true ); 
    63                 } 
    64  
    65                 if ( requestContent.isSetStart() ) 
    66                 { 
    67                         logger.info("Start position of results set set to: " + requestContent.getStart()); 
    68                         agent.setStart( requestContent.getStart() ); 
    69                 } 
    70                          
    71                 if ( requestContent.isSetHowMany() ) 
    72                 { 
    73                         logger.info("Result set size set to: " + requestContent.getHowMany()); 
    74                         agent.setHowMany( requestContent.getHowMany() ); 
    75                 } 
    76  
    77                 if ( requestContent.isSetOrderBy() ) 
    78                 { 
    79                         logger.info("Results ordered by: " + requestContent.getOrderBy()); 
    80                         agent.setOrderBy( requestContent.getOrderBy().toString() ); 
    81                         agent.setDoOrderBy( true ); 
    82                         if ( requestContent.isSetOrderByDirection() ) 
    83                         { 
    84                                 logger.info("Results ordering direction: " + requestContent.getOrderByDirection().toString()); 
    85                                 agent.setOrderByDirection( requestContent.getOrderByDirection().toString() ); 
    86                         } 
    87                 } 
    88  
    89                 if ( requestContent.sizeOfScopeArray() > 0) 
    90                 { 
    91                         for (int i=0; i<requestContent.sizeOfScopeArray(); i++) 
    92                         { 
    93                                 logger.info("Adding search scope: " + requestContent.getScopeArray(i)); 
    94                                 agent.addNewScope( requestContent.getScopeArray(i).toString() ); 
    95                         } 
    96                         agent.setDoScope( true ); 
    97                 } 
    98  
    99                 if ( requestContent.isSetBoundingBox() ) 
    100                 { 
    101                         logger.info("Adding bounding box data"); 
    102                         agent.setLimitWest( requestContent.getBoundingBox().getLimitWest() ); 
    103                         agent.setLimitSouth( requestContent.getBoundingBox().getLimitSouth() ); 
    104                         agent.setLimitEast( requestContent.getBoundingBox().getLimitEast() ); 
    105                         agent.setLimitNorth( requestContent.getBoundingBox().getLimitNorth() ); 
    106                         agent.setDoSpatio( true ); 
    107                         if ( requestContent.isSetSpatialOperator() ) 
    108                         { 
    109                                 logger.info("Adding spatial operator: " + requestContent.getSpatialOperator()); 
    110                                 agent.setSpatialOperator( requestContent.getSpatialOperator() ); 
    111                         } 
    112                 } 
    113  
    114                 if ( requestContent.isSetDateRange() ) 
    115                 { 
    116                         logger.info("Adding temporal range"); 
    117                         agent.setDateRangeStart( requestContent.getDateRange().getDateRangeStart() ); 
    118                         agent.setDateRangeEnd( requestContent.getDateRange().getDateRangeEnd() ); 
    119                         agent.setDoTemporal( true ); 
    120                 } 
    12148 
    12249                SearchSummary myResult = null; 
     
    12552                try 
    12653                { 
     54                        // firstly, parse the request message and set up the search agent 
     55                        logger.info("Preparing search agent for search"); 
     56                        SearchAgent agent = setupSearchAgent(request); 
     57 
    12758                        logger.info("Running search..."); 
    12859                        myResult = agent.doSearch(); 
     
    186117 
    187118        /** 
     119         * Prepare the search agent with all the passed in parameters from the WS request, ready to run 
     120         * a search 
     121         *  
     122         * @param request - DoSearchDocument object passed from webservice call 
     123         * @return SearchAgent object with all required initialisation done for running a search query 
     124         * @throws DiscoveryWSException if problems encountered whilst doing the set up 
     125         */ 
     126        private SearchAgent setupSearchAgent(DoSearchDocument request) throws DiscoveryWSException  
     127        { 
     128                discoveryserviceapi.SearchType requestContent = request.getDoSearch(); 
     129                SearchAgent agent = new SearchAgent(); 
     130                 
     131                // check if we're doing a term type search - if so, check there is a term to search on 
     132                if (requestContent.getTermType() != null && requestContent.getTermType().length() > 0) 
     133                { 
     134                        logger.info("Term type set - checking for term value"); 
     135 
     136                        if ( requestContent.getTerm().length() > 0 ) 
     137                        { 
     138                                logger.info("Term set - will do term search"); 
     139                                agent.setTermType(requestContent.getTermType()); 
     140                                agent.setTerm(requestContent.getTerm()); 
     141                        } 
     142                        else 
     143                        { 
     144                                logger.info("No term set - ignoring term type search specification"); 
     145                        } 
     146                } 
     147                 
     148                if ( requestContent.isSetStart() ) 
     149                { 
     150                        logger.info("Start position of results set set to: " + requestContent.getStart()); 
     151                        agent.setStart( requestContent.getStart() ); 
     152                } 
     153                         
     154                if ( requestContent.isSetHowMany() ) 
     155                { 
     156                        logger.info("Result set size set to: " + requestContent.getHowMany()); 
     157                        agent.setHowMany( requestContent.getHowMany() ); 
     158                } 
     159 
     160                if ( requestContent.isSetOrderBy() ) 
     161                { 
     162                        logger.info("Results ordered by: " + requestContent.getOrderBy()); 
     163                        agent.setOrderByField( requestContent.getOrderBy().toString() ); 
     164                        if ( requestContent.isSetOrderByDirection() ) 
     165                        { 
     166                                logger.info("Results ordering direction: " + requestContent.getOrderByDirection().toString()); 
     167                                agent.setOrderByDirection( requestContent.getOrderByDirection().toString() ); 
     168                        } 
     169                } 
     170 
     171                if ( requestContent.sizeOfScopeArray() > 0) 
     172                { 
     173                        for (int i=0; i<requestContent.sizeOfScopeArray(); i++) 
     174                        { 
     175                                logger.info("Adding search scope: " + requestContent.getScopeArray(i)); 
     176                                agent.addNewScope( requestContent.getScopeArray(i).toString() ); 
     177                        } 
     178                } 
     179 
     180                if ( requestContent.isSetBoundingBox() ) 
     181                { 
     182                        logger.info("Adding bounding box data"); 
     183                        agent.setLimitWest( requestContent.getBoundingBox().getLimitWest() ); 
     184                        agent.setLimitSouth( requestContent.getBoundingBox().getLimitSouth() ); 
     185                        agent.setLimitEast( requestContent.getBoundingBox().getLimitEast() ); 
     186                        agent.setLimitNorth( requestContent.getBoundingBox().getLimitNorth() ); 
     187                        if ( requestContent.isSetSpatialOperator() ) 
     188                        { 
     189                                logger.info("Adding spatial operator: " + requestContent.getSpatialOperator()); 
     190                                agent.setSpatialOperator( requestContent.getSpatialOperator() ); 
     191                        } 
     192                } 
     193 
     194                if ( requestContent.isSetDateRange() ) 
     195                { 
     196                        logger.info("Adding temporal range"); 
     197                        agent.setDateRangeStart( requestContent.getDateRange().getDateRangeStart() ); 
     198                        agent.setDateRangeEnd( requestContent.getDateRange().getDateRangeEnd() ); 
     199                } 
     200                return agent; 
     201        } 
     202 
     203 
     204        /** 
    188205         * Performs the doPresent operation 
    189206         * @param discoveryserviceapi.DoPresentDocument containing search request 
     
    306323                else if ( requestContent.getListName().equals("termTypeList") ) 
    307324                { 
    308                         list.addListMember("fullText"); 
    309                         list.addListMember("author"); 
    310                         list.addListMember("parameter"); 
     325                        list.addListMember(FULL_TEXT_TERM_TYPE); 
     326                        list.addListMember(AUTHOR_TERM_TYPE); 
     327                        list.addListMember(PARAMETER_TERM_TYPE); 
    311328                } 
    312329                else if ( requestContent.getListName().equals("spatialOperatorList") ) 
    313330                { 
    314                         list.addListMember("overlaps"); 
    315                         list.addListMember("doesNotOverlap"); 
    316                         list.addListMember("within"); 
     331                        list.addListMember(OVERLAPS_OPERATOR_TYPE); 
     332                        list.addListMember(NO_OVERLAP_OPERATOR_TYPE); 
     333                        list.addListMember(WITHIN_OPERATOR_TYPE); 
    317334                } 
    318335                else  
  • TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery/InterfaceDBClient.java

    r3952 r3957  
    2424         * @param sqlQuery 
    2525         * @return String[][] - array of results, if applicable, null if none returned 
     26         * NB, returned array should be populated as follows: String[rowNo][colNo] 
    2627         * @throws DiscoveryDBException 
    2728         */ 
  • TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery/PostgresDBClient.java

    r3952 r3957  
    135135                                { 
    136136                                        returnData[i][j] = results.getString(j+1); 
    137                                         System.out.println(returnData[i][j]); 
    138137                                } 
    139                                  
     138                                i++; 
    140139                            } 
    141140                    } 
     141                    logger.info("Query completed and results set retrieved"); 
    142142                    results.close(); 
    143143                } 
  • TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery/SearchAgent.java

    r3952 r3957  
    99import java.util.Calendar;  // needed because xmlbeans uses this for xsd:date 
    1010import java.util.logging.Logger; 
    11 import java.io.ByteArrayInputStream; 
     11import java.util.regex.Matcher; 
    1212import java.text.DecimalFormat; 
    1313import java.text.SimpleDateFormat; 
    14 import javax.xml.namespace.*; 
    15 import javax.xml.xpath.*; 
    16 import org.xml.sax.InputSource; 
    17 import org.w3c.dom.*; 
    18  
    19 import org.apache.xmlrpc.XmlRpcClient; 
    2014 
    2115/** 
     
    2418 *  @author     Matt Pritchard <m.j.pritchard@rl.ac.uk> 
    2519 */ 
    26 public abstract class SearchAgent  
     20public class SearchAgent  
    2721{ 
    2822 
    2923    private static Logger logger = Logger.getLogger(SearchAgent.class.getName()); 
    3024 
    31         static Properties properties = new ServiceProperties().getProperties(); 
     25    private static Properties properties = new ServiceProperties().getProperties(); 
    3226 
    3327        // Internal defaults 
     28     
     29    private String termType = null; 
     30     
    3431        static final BigInteger startDefault = new BigInteger("1"); // default value for first record to display in result set 
    3532        static final BigInteger howManyDefault = new BigInteger("30"); // default values for how many results to display in result set 
    36         boolean doSpatio = false;               // flags whether spatial search should be done 
    37         boolean doTemporal = false;             // flags whether temporal search should be done 
    38         boolean doTerm = false;                 // flags whether term search should be done 
    39         boolean doScope = false;                // flags whether search should be restricted by scope (dataCentre etc) 
    40         boolean doOrderBy = false;              // flags whether ordering should be applied to result set 
    4133         
    4234        // Initialise input parameters, setting values to internal defaults 
    43         int resultId = 0; 
    44         BigInteger start = startDefault; 
    45         BigInteger howMany = howManyDefault; 
    46         String term = ""; 
    47         String orderByField = "";       // representation used in WSDL e.g. "date", "dataCentre" 
    48         String orderByDirection = "ascending";  //default orderBy direction 
     35//      private int resultId = 0; 
     36        private BigInteger start = startDefault; 
     37        private BigInteger howMany = howManyDefault; 
     38        private String term = ""; 
     39        private String orderByField = null;     // representation used in WSDL e.g. "date", "dataCentre" 
     40        private String orderByDirection = "ASC";        //default orderBy direction 
    4941        // TODO ...add orderByDirection (and to WSDL) 
    5042 
    51         Vector scopes = new Vector(); 
    52         String spatialOperator = "overlaps"; 
    53  
    54         BigDecimal limitWest; 
    55         BigDecimal limitSouth; 
    56         BigDecimal limitEast; 
    57         BigDecimal limitNorth; 
    58         Calendar dateRangeStart; 
    59         Calendar dateRangeEnd; 
     43        Vector<String> scopes = new Vector<String>(); 
     44        private String spatialOperator = "overlaps"; 
     45 
     46        private BigDecimal limitWest; 
     47        private BigDecimal limitSouth; 
     48        private BigDecimal limitEast; 
     49        private BigDecimal limitNorth; 
     50        private Calendar dateRangeStart; 
     51        private Calendar dateRangeEnd; 
    6052 
    6153        int hits; 
    62         Hashtable result = new Hashtable(); 
    63  
     54         
     55        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
     56 
     57        // info on the DB table structure 
     58        private final String ORIGINAL_DOCUMENT_TABLE ="ORIGINAL_DOCUMENT"; 
     59        private final String SPATIAL_DATA_TABLE ="SPATIAL_DATA"; 
     60        private final String TEMPORAL_DATA_TABLE ="TEMPORAL_DATA"; 
     61        private final String SPATIAL_TEMPORAL_DATA_TABLE ="SPATIAL_TEMPORAL_DATA"; 
     62 
     63        // sql fragments to use when creating sql command 
     64        private final String WHERE_STATEMENT = " WHERE "; 
     65        private final String LIMIT_STATEMENT = " LIMIT "; 
     66        private final String OFFSET_STATEMENT = " OFFSET "; 
     67        private final String ORDERBY_STATEMENT = " ORDER BY "; 
     68         
    6469        /** 
    6570         * Default no-argument constructor. 
     
    102107        } 
    103108 
     109        public String getTerm() {               return term;    } 
    104110 
    105111        /** 
     
    107113         * @param s String, one of "date", "dataCentre", list defined in <code>orderByFieldList</code> returned by <code>getList</code> operation. 
    108114         */ 
    109         public void setOrderBy(String s) 
    110         { 
    111                 this.orderByField = s; 
     115        public void setOrderByField(String orderByField)  
     116        { 
     117                this.orderByField = orderByField; 
     118        } 
     119 
     120        public String getOrderByField()  
     121        { 
     122                return orderByField; 
    112123        } 
    113124 
     
    119130        public void setOrderByDirection(String s) 
    120131        { 
    121                 this.orderByDirection = s; 
     132                if (s != null && s.equals("descending")) 
     133                        this.orderByDirection = "DESC"; 
     134                else 
     135                        this.orderByDirection = "ASC"; 
     136        } 
     137 
     138        public String getOrderByDirection()  
     139        { 
     140                return orderByDirection; 
    122141        } 
    123142 
     
    136155         * @return scopes containing String elements like NERC-DDC etc 
    137156         */ 
    138         public Vector getScopes() 
     157        public Vector<String> getScopes() 
    139158        { 
    140159                return this.scopes; 
     
    154173        { 
    155174                String scopesStr = ""; 
    156                 Iterator it = this.scopes.iterator(); 
     175                Iterator<String> it = this.scopes.iterator(); 
    157176                while ( it.hasNext() ) 
    158177                { 
    159                         scopesStr += (String) it.next(); 
    160                 } 
     178                        scopesStr += it.next(); 
     179                } 
     180                System.out.println("got: " + scopesStr); 
     181                System.out.println("alternatively: " + this.scopes.toString()); 
    161182                return scopesStr; 
    162183        } 
     
    229250 
    230251        /** 
    231          * Sets whether spatial search should be done. 
    232          * @param b boolean flag true if spatial search is to be done 
    233          */ 
    234         public void setDoSpatio(boolean b) 
    235         { 
    236                 this.doSpatio = b; 
    237         } 
    238  
    239         /** 
    240          * Sets whether temporal search should be done. 
    241          * @param b boolean flag true if temporal search is to be done 
    242          */ 
    243         public void setDoTemporal(boolean b) 
    244         { 
    245                 this.doTemporal = b; 
    246         } 
    247  
    248         /** 
    249          * Sets whether term search should be done. 
    250          * @param b boolean flag true if term search is to be done 
    251          */ 
    252         public void setDoTerm(boolean b) 
    253         { 
    254                 this.doTerm = b; 
    255         } 
    256  
    257         /** 
    258          * Sets whether result set should be ordered. 
    259          * @param b boolean flag true if result set should be ordered 
    260          */ 
    261         public void setDoOrderBy(boolean b) 
    262         { 
    263                 this.doOrderBy = b; 
    264         } 
    265  
    266         /** 
    267          * Sets whether scope check should be done. 
    268          * @param b boolean flag true if search should be limited to scope keywords 
    269          */ 
    270         public void setDoScope(boolean b) 
    271         { 
    272                 this.doScope = b; 
    273         } 
    274  
    275         /** 
    276252         * Sets operator used for spatial search 
    277          * @param s String spatial operator to be applied, must be member of list <code>spatialOperatorsList</code> returned by <code>getList</code> operation. 
     253         * @param s String spatial operator to be applied,  
     254         *      must be member of list <code>spatialOperatorsList</code> returned by <code>getList</code> operation. 
     255         * @throws DiscoveryWSException if not correct value of getList list 
    278256        */ 
    279         public void setSpatialOperator(String s) 
    280         { 
     257        public void setSpatialOperator(String s) throws DiscoveryWSException 
     258        { 
     259                if (s.equals(DiscoveryServiceSkeleton.OVERLAPS_OPERATOR_TYPE) ||  
     260                                s.equals(DiscoveryServiceSkeleton.WITHIN_OPERATOR_TYPE) || 
     261                                s.equals(DiscoveryServiceSkeleton.NO_OVERLAP_OPERATOR_TYPE)) 
     262                { 
     263                        this.spatialOperator = s; 
     264                } 
     265                else 
     266                { 
     267                        String errorMessage = "Invalid spatial operator, " + s + 
     268                                " - please use getListNames to get the valid list of spatial operator types"; 
     269                        logger.warning(errorMessage); 
     270                        throw new DiscoveryWSException(errorMessage); 
     271                } 
    281272                this.spatialOperator = s; 
    282273        } 
     
    291282        } 
    292283 
     284        public BigDecimal getLimitWest() {              return limitWest;       } 
     285 
     286        public BigDecimal getLimitSouth() {             return limitSouth;      } 
     287 
     288        public BigDecimal getLimitEast() {              return limitEast;       } 
     289 
     290        public BigDecimal getLimitNorth() {             return limitNorth;      } 
     291 
     292        public Calendar getDateRangeStart() {           return dateRangeStart;  } 
     293 
     294        public Calendar getDateRangeEnd() {             return dateRangeEnd;    } 
     295 
     296        public BigInteger getHowMany() {                return howMany;         } 
     297 
     298        public String getTermType() {           return termType;        } 
     299 
     300        public BigInteger getStart() {          return start;   } 
     301 
     302        /** 
     303         * Set the type of the term to search on; NB, this must be either 'fullText', 'parameter' or 'author' 
     304         * - if not an exception is thrown 
     305         *  
     306         * @param termType 
     307         */ 
     308        public void setTermType(String termType) throws DiscoveryWSException 
     309        { 
     310                if (termType.equals(DiscoveryServiceSkeleton.FULL_TEXT_TERM_TYPE) ||  
     311                                termType.equals(DiscoveryServiceSkeleton.AUTHOR_TERM_TYPE) || 
     312                                termType.equals(DiscoveryServiceSkeleton.PARAMETER_TERM_TYPE)) 
     313                { 
     314                        this.termType = termType; 
     315                } 
     316                else 
     317                { 
     318                        String errorMessage = "Invalid termType, " + termType + 
     319                                " - please use getListNames to get the valid list of term types"; 
     320                        logger.warning(errorMessage); 
     321                        throw new DiscoveryWSException(errorMessage); 
     322                } 
     323        } 
     324 
     325 
    293326        /** 
    294327         * Executes the search and returns a SearchSummary object 
     
    298331        { 
    299332 
    300                 SearchSummary result = new SearchSummary(); 
     333                SearchSummary result = null; 
    301334 
    302335                try 
     
    307340                        // now run the query using the db client configured appropriately 
    308341                        InterfaceDBClient client = setupDBClient(); 
    309                         client.runQuery(sqlQuery); 
     342                        String[][] results = client.runQuery(sqlQuery); 
    310343                         
    311  
    312 //                      ByteArrayInputStream resultStream = new ByteArrayInputStream( resultByteArray ); 
    313 // 
    314 //                      // Mark the beginning of the Stream, so can reset before each xpath evaluation (!) 
    315 //                      resultStream.mark( resultStream.available() ); 
    316 //                      InputSource resultSource = new InputSource( resultStream ); 
    317 //                       
    318 //                      XPath xpath = XPathFactory.newInstance().newXPath(); 
    319 //                      String hitsExpr = "/exist:result/@hits";  
    320 //                      String documentExpr = "//exist:result/document"; 
    321 //                      xpath.setNamespaceContext( new existNamespaceContextImpl() ); 
    322 // 
    323 //                      // If there is a successful search but with no hits, exist sets hitCount=0 rather than hits=0 !! 
    324 //                      // Need to check that the thing returned by xpath will convert to an int 
    325 //                      try 
    326 //                      { 
    327 //                              int xpathHits = (new Integer( xpath.evaluate(hitsExpr, resultSource) )).intValue(); 
    328 //                              result.setHits( xpathHits ); 
    329 //                      } 
    330 //                      catch (NumberFormatException e) 
    331 //                      { 
    332 //                              result.setHits( 0 ); 
    333 //                      } 
    334 //                       
    335 //                      resultStream.reset(); 
    336 //                      NodeList nodeList = (NodeList)xpath.evaluate( documentExpr, resultSource, XPathConstants.NODESET );  
    337 //                       
    338 //                      if ( result.getHits() > 0) 
    339 //                      { 
    340 //                              Vector documents = new Vector(); 
    341 //                              for (int i=0; i<nodeList.getLength(); i++) 
    342 //                              { 
    343 //                                      Hashtable thisDoc = new Hashtable(); 
    344 //                                      thisDoc.put("name", nodeList.item(i).getFirstChild().getNodeValue() ); 
    345 //                                      thisDoc.put("matches", 1); 
    346 //                                      thisDoc.put("position", i); 
    347 //                                      documents.add( thisDoc ); 
    348 //                              } 
    349 //                              result.setStatus( true ); 
    350 //                              result.setStatusMessage( "Success" ); 
    351 //                              result.setDocuments( documents );        
    352 //                      } 
    353 //                      else 
    354 //                      { 
    355 //                              result.setStatus( false ); 
    356 //                              result.setStatusMessage("Search was successful but generated no results."); 
    357 //                      } 
    358 //                       
     344                        // now extract the results data 
     345                        result = processResults(results); 
    359346                         
    360347                } 
     
    365352                } 
    366353 
     354                return result; 
     355        } 
     356 
     357         
     358        /** 
     359         * Take the results set returned from a call to doSearch and extract the 
     360         * data into a SearchSummary object 
     361         *  
     362         * @param results - a 2D string array of results from the doSearch call  
     363         * @return SearchSummary object wrappering the results set 
     364         */ 
     365        private SearchSummary processResults(String[][] results)  
     366        { 
     367                SearchSummary result = new SearchSummary(); 
     368                result.setHits(results.length); // NB ensure this is 0 if not data returned 
     369                 
     370                if ( result.getHits() > 0) 
     371                { 
     372                        Vector<Hashtable<String, String>> documents = new Vector<Hashtable<String, String>>(); 
     373                        for (int i=0; i < results.length; i++) 
     374                        { 
     375                                Hashtable<String, String> thisDoc = new Hashtable<String, String>(); 
     376                                thisDoc.put("name", results[i][0]); 
     377                                // TODO: these next two are not used anywhere - remove or use? 
     378                                thisDoc.put("matches", String.valueOf(1)); 
     379                                thisDoc.put("position", String.valueOf(i)); 
     380                                documents.add( thisDoc ); 
     381                        } 
     382                        result.setStatus( true ); 
     383                        result.setStatusMessage( "Success" ); 
     384                        result.setDocuments( documents );        
     385                } 
     386                else 
     387                { 
     388                        result.setStatus( false ); 
     389                        result.setStatusMessage("Search was successful but generated no results."); 
     390                } 
     391                 
    367392                return result; 
    368393        } 
     
    387412        } 
    388413 
     414        /** 
     415         * Set up a SQL Select query with the input search parameters 
     416         *  
     417         * @return String - SQL command 
     418         */ 
    389419        private String constructSearchQuery()  
    390420        { 
    391                 //1. Prepare & execute the search 
    392                 Vector queryParams = new Vector(); 
    393                  
    394                 StringBuffer sqlCmd = new StringBuffer("SELECT original_document_id FROM ORIGINAL DOCUMENT WHERE "); 
     421                logger.info("Creating search query"); 
     422                 
     423                // NB, we use the postgres text search function to do term searches 
     424                StringBuffer fromSqlCmd = new StringBuffer("SELECT original_document_filename FROM " +  
     425                                ORIGINAL_DOCUMENT_TABLE + " "); 
     426                StringBuffer whereSqlCmd = new StringBuffer(); 
     427                 
     428                if (this.getTerm() != null && this.getTerm().length() > 0) 
     429                { 
     430                        logger.info("Adjusting query for " + this.getTermType() + " type search"); 
     431                         
     432                        if (this.getTermType().equals(DiscoveryServiceSkeleton.FULL_TEXT_TERM_TYPE)) 
     433                        { 
     434                                appendWhereClause(whereSqlCmd, " to_tsquery('" + this.term + "') @@ ts_vector "); 
     435                        } 
     436                        else if (this.getTermType().equals(DiscoveryServiceSkeleton.AUTHOR_TERM_TYPE)) 
     437                        { 
     438                                //TODO: IMPLEMENT datamodel side... 
     439                                appendWhereClause(whereSqlCmd, " AUTHOR LIKE %" + this.term + "% "); 
     440                        } 
     441                        else if (this.getTermType().equals(DiscoveryServiceSkeleton.PARAMETER_TERM_TYPE)) 
     442                        { 
     443                                //TODO: IMPLEMENT datamodel side... 
     444                                appendWhereClause(whereSqlCmd, " PARAMETERS LIKE %" + this.term + "% "); 
     445                        } 
     446                 
     447                } 
    395448 
    396449                // Substitute values in template xquery string 
     
    398451                xqueryStr = xqueryStr.replaceFirst("__subst_scope__", this.getScopesAsString() ); 
    399452 
    400                 // orderByField contains $ chars etc so needs special treatment to avoid "java.lang.IllegalArgumentException: Illegal group reference" when replacing 
    401                 String orderByFieldReplace = Matcher.quoteReplacement(this.orderByField); 
    402                 xqueryStr = xqueryStr.replaceAll("__subst_orderByField__", orderByFieldReplace); //NB replaceAll cos more than 1! 
    403                 xqueryStr = xqueryStr.replaceFirst("__subst_orderByDirection__", this.orderByDirection); 
    404                  
    405 */                      // Construct the search clause for spatio temporal search, if necessary 
    406                 String spatialClause = ""; 
    407                 try 
    408                 { 
    409                         SPATIO: 
    410                         if (  
    411                                 doSpatio &&  
    412                                 limitWest != null && 
    413                                 limitSouth != null && 
    414                                 limitNorth != null && 
    415                                 limitEast != null 
    416                         ) 
    417                         { 
    418                                 if (    // Ignore spatial search if search area is global 
    419                                         limitWest.intValue() == -180 && 
    420                                         limitEast.intValue() == 180 && 
    421                                         limitNorth.intValue() == 90 && 
    422                                         limitSouth.intValue() == -90 
    423                                 ) 
    424                                 { 
    425                                         doSpatio = false; 
    426                                         System.out.println("Global extent selected : spatial search ignored"); 
    427                                         break SPATIO; 
    428                                 } 
    429  
    430                                 String latFormatPattern = "#0.00"; 
    431                                 String lonFormatPattern = "##0.00"; 
    432                                 DecimalFormat latFormat = new DecimalFormat( latFormatPattern ); 
    433                                 DecimalFormat lonFormat = new DecimalFormat( lonFormatPattern ); 
    434  
    435                                 if ( spatialOperator.equals("within") ) 
    436                                 { 
    437                                         spatialClause += " sbox_contains_box("; 
    438                                 }  
    439                                 else if ( spatialOperator.equals("overlaps") ) 
    440                                 { 
    441                                         spatialClause += " sbox_overlap_box("; 
    442                                 } 
    443                                 else if ( spatialOperator.equals("doesNotOverlap") ) 
    444                                 { 
    445                                         spatialClause += " NOT sbox_overlap_box("; 
    446                                 }  
    447                                 else 
    448                                 { 
    449                                         doSpatio = false; 
    450                                         throw new Exception("Unrecognised spatial operator: " + spatialOperator + " (see spatialOperatorList for supported values)"); 
    451                                 }                                        
    452                                 spatialClause += " sbox'("+ 
    453                                 lonFormat.format( limitWest.floatValue() )+"d,"+ 
    454                                 latFormat.format( limitSouth.floatValue() )+"d),("+ 
    455                                 lonFormat.format( limitEast.floatValue() )+"d,"+ 
    456                                 latFormat.format( limitNorth.floatValue() )+"d)' "; 
    457                                 spatialClause += ", coordinates ) "; 
    458  
    459                         } 
    460                         else { 
    461                                 doSpatio = false; //just in case any components of coordinates were null 
    462                         } 
    463                 } 
    464                 catch (Exception e) 
    465                 { 
    466                         System.out.println("Error converting coordinates to SQL: " + e.toString() ); 
    467                         doSpatio = false; 
    468                 } 
    469  
    470                 String temporalClause = ""; 
    471                 try 
    472                 { 
    473                         if ( 
    474                                 doTemporal && 
    475                                 dateRangeStart != null && 
    476                                 dateRangeEnd != null && 
    477                                 dateRangeEnd.getTimeInMillis() > dateRangeStart.getTimeInMillis() 
    478                         ) 
    479                         { 
    480                                 String format = "yyyy-MM-dd"; 
    481                                 SimpleDateFormat sdf = new SimpleDateFormat(format); 
    482  
    483                                 temporalClause = " (startdate, enddate) OVERLAPS (DATE '"+sdf.format( dateRangeStart.getTime() )+"', DATE '"+ sdf.format( dateRangeEnd.getTime() ) +"') "; 
     453                 
     454*/                       
     455                // Construct the search clause for spatio temporal search, if necessary 
     456                if (isSpatialSearch()) 
     457                { 
     458                        logger.info("Adding spatial data to query"); 
     459                        // set up the bounding box geometry for the search 
     460                        String bbox = "SetSRID('BOX3D(" + this.getLimitWest().floatValue() + " " + this.getLimitSouth().floatValue() + 
     461                                ", " + this.getLimitEast().floatValue() + " " + this.getLimitNorth().floatValue() + ")’::box3d,-1)"; 
     462 
     463                        if (spatialOperator.equals(DiscoveryServiceSkeleton.OVERLAPS_OPERATOR_TYPE)) 
     464                        { 
     465                                appendWhereClause(whereSqlCmd, " geometry && " + bbox + " "); 
     466                        } 
     467                        else if ( spatialOperator.equals(DiscoveryServiceSkeleton.WITHIN_OPERATOR_TYPE) ) 
     468                        { 
     469                                appendWhereClause(whereSqlCmd, " geometry @ " + bbox + " "); 
     470                        } 
     471                        else if ( spatialOperator.equals("doesNotOverlap") ) 
     472                        { 
     473                                appendWhereClause(whereSqlCmd, "NOT geometry && " + bbox + " "); 
     474                        }  
     475                } 
     476 
     477                if (isTemporalSearch()) 
     478                { 
     479                        logger.info("Adding temporal data to query"); 
     480                        fromSqlCmd.append(", " + TEMPORAL_DATA_TABLE + ", " + SPATIAL_TEMPORAL_DATA_TABLE + ""); 
     481                        appendWhereClause(whereSqlCmd, " " + TEMPORAL_DATA_TABLE + ".start_time, " + 
     482                                        TEMPORAL_DATA_TABLE + ".end_time) OVERLAPS (DATE '" +  
     483                                this.sdf.format(this.getDateRangeStart().getTime()) +  
     484                                "', DATE '" + this.sdf.format(this.getDateRangeEnd().getTime() ) + "' AND " + 
     485                                TEMPORAL_DATA_TABLE + ".temporal_data_id == " + 
     486                                SPATIAL_TEMPORAL_DATA_TABLE + ".temporal_data_id"); 
     487                } 
     488                 
     489                // if either or both spatial and temporal data is searched on, need to join this with the main 
     490                // orig doc search query 
     491                if (isTemporalSearch() || isSpatialSearch()) 
     492                { 
     493                        whereSqlCmd.append(" AND " + SPATIAL_TEMPORAL_DATA_TABLE + ".original_document_id == " + 
     494                                        ORIGINAL_DOCUMENT_TABLE + ".original_document_id"); 
     495                } 
     496                 
     497                // add order by, and direction, if required 
     498                if (this.getOrderByField() != null) 
     499                { 
     500                        logger.info("Adding ordering info to query"); 
     501                        // orderByField contains $ chars etc so needs special treatment to  
     502                        // avoid "java.lang.IllegalArgumentException: Illegal group reference" when replacing 
     503                        // TODO: is this true now? 
     504                        String orderByFieldReplace = Matcher.quoteReplacement(this.getOrderByField()); 
     505                        whereSqlCmd.append(ORDERBY_STATEMENT + orderByFieldReplace + " " + this.getOrderByDirection()); 
     506                } 
     507                 
     508                // lastly, add the size limit and offset of the returned data set 
     509                logger.info("Adding size limit and offset of results set"); 
     510                whereSqlCmd.append(OFFSET_STATEMENT + this.getStart()); 
     511                whereSqlCmd.append(LIMIT_STATEMENT + this.getHowMany()); 
     512                 
     513                String fullCmd = fromSqlCmd.toString() + WHERE_STATEMENT + whereSqlCmd.toString() + ";"; 
     514                logger.info("SQL query generated"); 
     515                logger.fine("Value: " + fullCmd); 
     516                 
     517                return fullCmd; 
     518        } 
     519 
     520        /** 
     521         * Append to 'where' clause in sql statement, ensuring 'AND' joins are added where required 
     522         *  
     523         * @param whereSqlCmd - StringBuffer holding sql statement 
     524         * @param clause - string sql clause to add to buffer 
     525         */ 
     526        private void appendWhereClause(StringBuffer whereSqlCmd, String clause)  
     527        { 
     528                if (whereSqlCmd.length() > 0) 
     529                        whereSqlCmd.append(" AND "); 
     530                whereSqlCmd.append(clause); 
     531        } 
     532 
     533        /** 
     534         * Determine whether the search has any temporal data specified 
     535         *  
     536         * @return true if includes temporal search, false otherwise 
     537         * @throws UnsupportedOperationException if  
     538         */ 
     539        private boolean isTemporalSearch() throws UnsupportedOperationException  
     540        { 
     541                logger.info("Checking if valid temporal data specified"); 
     542                if (this.getDateRangeStart() != null && this.getDateRangeEnd() != null) 
     543                { 
     544                        if (dateRangeEnd.getTimeInMillis() > dateRangeStart.getTimeInMillis()) 
     545                        { 
     546                                logger.info("Valid temporal data specified"); 
     547                                return true; 
    484548                        } 
    485549                        else 
    486550                        { 
    487                                 doTemporal = false; // just in case any components of date range were null 
    488                         } 
    489                 } 
    490                 catch (Exception e) 
    491                 { 
    492                         System.out.println("Error converting date to SQL: " + e.toString() ); 
    493                         temporalClause = ""; 
    494                         doTemporal = false; 
    495                 }                        
    496  
    497                 String whereClause = ""; 
    498                 if ( doSpatio && doTemporal ) 
    499                 { 
    500                         whereClause = " WHERE " + spatialClause + " AND " + temporalClause + " "; 
    501                 } 
    502                 else if ( doSpatio && !doTemporal ) 
    503                 { 
    504                         whereClause = " WHERE " + spatialClause + " "; 
    505                 } 
    506                 else if ( doTemporal && !doSpatio ) 
    507                 { 
    508                         whereClause = " WHERE " + temporalClause + " "; 
    509                 } 
    510                 else 
    511                 { 
    512                         whereClause = ""; 
    513                 } 
    514 /* 
    515                 xqueryStr = xqueryStr.replaceFirst("__subst_spatioTempWhereClause__", whereClause ); 
    516  
    517                 xqueryStr = xqueryStr.replaceFirst("__subst_doTerm__", this.doTerm ? "fn:true()" : "fn:false()"); 
    518                 xqueryStr = xqueryStr.replaceFirst("__subst_doSpatioTemp__", (this.doSpatio | this.doTemporal) ? "fn:true()" : "fn:false()"); 
    519                 xqueryStr = xqueryStr.replaceFirst("__subst_doOrderBy__", this.doOrderBy ? "fn:true()" : "fn:false()"); //NB replaceAll cos more than 1!  
    520                 xqueryStr = xqueryStr.replaceFirst("__subst_doScope__", this.doScope ? "fn:true()" : "fn:false()"); 
    521                  
    522                 //System.out.println("Xquery was \n" + xqueryStr); 
    523                  
    524                 queryParams.addElement( xqueryStr.getBytes("UTF-8") );  
    525 */ 
    526                 queryParams.addElement( this.howMany.intValue() ); 
    527                 queryParams.addElement( this.start.intValue() );  
    528                 //System.out.println("start \n" + this.start.intValue()); 
    529                 //System.out.println("howMany \n" + this.howMany.intValue()); 
    530                 return null; 
    531         } 
    532  
    533         public class existNamespaceContextImpl implements NamespaceContext 
    534     { 
    535         public String getNamespaceURI(String prefix) 
    536         { 
    537                         return "http://exist.sourceforge.net/NS/exist"; 
    538         } 
    539       
    540                 // Doesn't matter what the prefix in the source doc is, override it 
    541                 // Important thing is that the namespace URI matches, and that 
    542                 // whatever prefix is set here, is used in the xpath query 
    543         public String getPrefix(String namespace) 
    544         { 
    545                         return "exist"; 
    546         } 
    547  
    548         public Iterator getPrefixes(String namespace) 
    549         { 
    550             return null; 
    551         } 
    552     }  
     551                                String errorMessage = "Invalid temporal data: End date before start date."; 
     552                                logger.warning(errorMessage); 
     553                                throw new UnsupportedOperationException(errorMessage); 
     554                        } 
     555                } 
     556                logger.info("No valid temporal data specified"); 
     557                return false; 
     558        } 
     559 
     560        /** 
     561         * Determine whether the search has any spatial data specified 
     562         * NB, checks that global limits aren't specified - if so, this is semantically 
     563         * equivalent to a non spatial search, so treat as such 
     564         *  
     565         * @return true if includes spatial search, false otherwise 
     566         */ 
     567        private boolean isSpatialSearch()  
     568        { 
     569                logger.info("Checking if valid spatial data specified"); 
     570                if (this.getLimitEast() != null && this.getLimitWest() != null && 
     571                        this.getLimitNorth() != null && this.getLimitSouth() != null) 
     572                { 
     573                        if (this.getLimitEast().intValue() != 180 && this.getLimitWest().intValue() != -180 && 
     574                                        this.getLimitNorth().intValue() != 90 && this.getLimitSouth().intValue() != -90) 
     575                        { 
     576                                logger.info("Valid spatial data specified"); 
     577                                return true; 
     578                        } 
     579                        logger.info("Spatial data is equivalent to global search - will ignore in search"); 
     580                } 
     581                logger.info("No valid spatial data specified"); 
     582                return false; 
     583        } 
    553584 
    554585 
     
    658689"return <document>{$i}</document> \n"; 
    659690 
     691 
     692 
    660693} 
  • TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery/ServiceProperties.java

    r3952 r3957  
    1212        public ServiceProperties() 
    1313        { 
    14                 properties.setProperty("jdbc.uri","jdbc:postgresql://glue.badc.rl.ac.uk/calum:51000"); 
     14                properties.setProperty("jdbc.uri","jdbc:postgresql://glue.badc.rl.ac.uk:51000/calum"); 
    1515                properties.setProperty("jdbc.username","calum"); 
    1616                properties.setProperty("jdbc.password","boybear"); 
Note: See TracChangeset for help on using the changeset viewer.