001/* 002 * Copyright (c) 2004-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.ecoinformatics.seek.ecogrid.quicksearch; 031 032import java.util.Hashtable; 033import java.util.List; 034import java.util.Vector; 035 036import org.kepler.configuration.ConfigurationProperty; 037 038/** 039 * A class to implement a query object that looks like this: 040 041 <query> 042 <queryId>eml210-quick-search-query</queryId> 043 <system>http://knb.ecoinformatics.org</system> 044 <namespace> 045 <prefix>eml</prefix> 046 <value>eml://ecoinformatics.org/eml-2.1.0</value> 047 </namespace> 048 <returnField>dataset/title</returnField> 049 <returnField>entityName</returnField> 050 <title>eml210-quick-search-query</title> 051 <AND> 052 <OR> 053 <condition> 054 <concept>dataset/title</concept> 055 <operator>LIKE</operator> 056 <value>#value#</value> 057 </condition> 058 <condition> 059 <concept>keyword</concept> 060 <operator>LIKE</operator> 061 <value>#value#</value> 062 </condition> 063 <condition> 064 <concept>creator/individualName/surName</concept> 065 <operator>LIKE</operator> 066 <value>#value#</value> 067 </condition> 068 <condition> 069 <concept>taxonRankValue</concept> 070 <operator>LIKE</operator> 071 <value>#value#</value> 072 </condition> 073 <condition> 074 <concept>abstract/para</concept> 075 <operator>LIKE</operator> 076 <value>#value#</value> 077 </condition> 078 </OR> 079 <OR> 080 <condition> 081 <concept>dataset/dataTable/physical/distribution/online/url</concept> 082 <operator>LIKE</operator> 083 <value>http://%</value> 084 </condition> 085 <condition> 086 <concept>dataset/dataTable/physical/distribution/online/url</concept> 087 <operator>LIKE</operator> 088 <value>ecogrid://%</value> 089 </condition> 090 <condition> 091 <concept>dataset/spatialRaster/physical/distribution/online/url</concept> 092 <operator>LIKE</operator> 093 <value>ecogrid://%</value> 094 </condition> 095 </OR> 096 <OR> 097 <condition> 098 <concept>dataset/dataTable/physical/distribution/online/url/@function</concept> 099 <operator>EQUALS</operator> 100 <value>download</value> 101 </condition> 102 <condition> 103 <concept>dataset/spatialRaster/physical/distribution/online/url/@function</concept> 104 <operator>EQUALS</operator> 105 <value>download</value> 106 </condition> 107 </OR> 108 </AND> 109 </query> 110 111*/ 112public class SearchQuery 113{ 114 public String queryId; 115 public String system; 116 public Namespace namespace; 117 public Vector<String> returnField; 118 public String title; 119 public Condition condition; 120 public BooleanLogic andOrConditions; 121 122 /** 123 * constructor 124 */ 125 public SearchQuery(ConfigurationProperty queryProp) 126 { 127 parseProp(queryProp); 128 } 129 130 /** 131 * replace the values in the conditions with the values in the hash 132 */ 133 public void replaceValues(Hashtable valueMap) 134 { 135 if(andOrConditions != null) 136 { 137 andOrConditions.replaceValues(valueMap); 138 } 139 140 if(condition != null) 141 { 142 condition.replaceValue(valueMap); 143 } 144 } 145 146 /** 147 * toString 148 */ 149 public String toString() 150 { 151 String s = new String(); 152 s += "<query queryId=\"" + queryId + "\" system=\"" + system + "\">\n"; 153 s += namespace.toString(); 154 155 for(int i=0; i<returnField.size(); i++) 156 { 157 String rf = (String)returnField.get(i); 158 s += "<returnField>" + rf + "</returnField>\n"; 159 } 160 161 s += "<title>" + title + "</title>\n"; 162 163 if(condition != null) 164 { 165 s += condition.toString(); 166 } 167 if(andOrConditions != null) 168 { 169 s += andOrConditions.toString(); 170 } 171 s += "</query>\n"; 172 return s; 173 } 174 175 /** 176 * parse the property 177 */ 178 private void parseProp(ConfigurationProperty queryProp) 179 { 180 //get the basic fields 181 queryId = getValueIfNotNull(queryProp.getProperty("queryId")); 182 system = getValueIfNotNull(queryProp.getProperty("system")); 183 title = getValueIfNotNull(queryProp.getProperty("title")); 184 185 //get the returnfields 186 List returnfields = queryProp.getProperties("returnField"); 187 returnField = new Vector(); 188 for(int i=0; i<returnfields.size(); i++) 189 { 190 String returnfield = ((ConfigurationProperty)returnfields.get(i)).getValue(); 191 returnField.add(returnfield); 192 } 193 194 //namespace 195 ConfigurationProperty namespaceProp = queryProp.getProperty("namespace"); 196 if(namespaceProp != null) 197 { 198 namespace = new Namespace(); 199 namespace.prefix = getValueIfNotNull(namespaceProp.getProperty("prefix")); 200 namespace.value = getValueIfNotNull(namespaceProp.getProperty("value")); 201 } 202 203 //conditions 204 ConfigurationProperty conditionProp = queryProp.getProperty("condition"); 205 if(conditionProp != null) 206 { 207 condition = new Condition(conditionProp); 208 } 209 210 //AND/OR/Conditions 211 andOrConditions = parseAndOrProp(queryProp); 212 213 } 214 215 /** 216 * parse the conditions 217 */ 218 private BooleanLogic parseAndOrProp(ConfigurationProperty queryProp) 219 { 220 List l = queryProp.getProperties(); 221 BooleanLogic bl = new BooleanLogic(); 222 223 for(int i=0; i<l.size(); i++) 224 { 225 ConfigurationProperty cp = (ConfigurationProperty)l.get(i); 226 if(cp.getName().equals("AND")) 227 { 228 bl.isAnd = true; 229 bl.logic.add(parseAndOrProp(cp)); 230 } 231 else if(cp.getName().equals("OR")) 232 { 233 bl.isOr = true; 234 bl.logic.add(parseAndOrProp(cp)); 235 } 236 else if(cp.getName().equals("condition")) 237 { 238 bl.addCondition(new Condition(cp)); 239 } 240 else 241 { 242 continue; 243 } 244 } 245 return bl; 246 } 247 248 /** 249 * get the value or null if there isn't one 250 */ 251 private String getValueIfNotNull(ConfigurationProperty cp) 252 { 253 if(cp != null) 254 { 255 return cp.getValue(); 256 } 257 else 258 { 259 return null; 260 } 261 } 262 263 /** 264 * class to hold a namespace 265 */ 266 private class Namespace 267 { 268 public String prefix; 269 public String value; 270 271 public Namespace() 272 { 273 274 } 275 276 public String toString() 277 { 278 String s = ""; 279 s += "<namespace prefix=\"" + prefix + "\">" + value + "</namespace>\n"; 280 return s; 281 } 282 } 283 284 /** 285 * class to hold a condition 286 */ 287 private class Condition 288 { 289 public String concept; 290 public String operator; 291 public String value; 292 293 public Condition(ConfigurationProperty conditionProp) 294 { 295 concept = getValueIfNotNull(conditionProp.getProperty("concept")); 296 operator = getValueIfNotNull(conditionProp.getProperty("operator")); 297 value = getValueIfNotNull(conditionProp.getProperty("value")); 298 } 299 300 /** 301 * replace the value of this condition with the value in the valueMap 302 */ 303 public void replaceValue(Hashtable valueMap) 304 { 305 String v = (String)valueMap.get(value); 306 if(v != null) 307 { 308 value = v; 309 } 310 } 311 312 public String toString() 313 { 314 String s = ""; 315 s += "<condition concept=\"" + concept + "\" operator=\"" + operator + "\">" + value + "</condition>\n"; 316 return s; 317 } 318 } 319 320 /** 321 * class to contain the boolean logic 322 */ 323 private class BooleanLogic 324 { 325 public Vector<Condition> conditions; 326 public Vector<BooleanLogic> logic; 327 public boolean isOr = false; 328 public boolean isAnd = false; 329 330 public BooleanLogic() 331 { 332 logic = new Vector(); 333 conditions = new Vector(); 334 } 335 336 public void addCondition(Condition c) 337 { 338 conditions.add(c); 339 } 340 341 public void addBooleanLogic(BooleanLogic b) 342 { 343 logic.add(b); 344 } 345 346 public String toString() 347 { 348 return toString(this); 349 } 350 351 /** 352 * replace the values in the conditions with the values in the valueMap 353 */ 354 public void replaceValues(Hashtable valueMap) 355 { 356 replaceValues(valueMap, this); 357 } 358 359 private void replaceValues(Hashtable valueMap, BooleanLogic bl) 360 { 361 if(bl.conditions != null && bl.conditions.size() > 0) 362 { 363 for(int i=0; i<bl.conditions.size(); i++) 364 { 365 Condition c = (Condition)bl.conditions.get(i); 366 c.replaceValue(valueMap); 367 } 368 } 369 370 if(bl.logic != null && bl.logic.size() > 0) 371 { 372 for(int i=0; i<bl.logic.size(); i++) 373 { 374 BooleanLogic newbl = (BooleanLogic)bl.logic.get(i); 375 replaceValues(valueMap, newbl); 376 } 377 } 378 } 379 380 private String toString(BooleanLogic bl) 381 { 382 String s = ""; 383 384 if(bl.conditions != null && bl.conditions.size() > 0) 385 { 386 for(int i=0; i<bl.conditions.size(); i++) 387 { 388 Condition c = (Condition)bl.conditions.get(i); 389 s += c.toString(); 390 } 391 } 392 393 if(bl.logic != null && bl.logic.size() > 0) 394 { 395 for(int i=0; i<bl.logic.size(); i++) 396 { 397 BooleanLogic newbl = (BooleanLogic)bl.logic.get(i); 398 if(bl.isAnd) 399 { 400 s += "<AND>\n"; 401 s += toString(newbl); 402 s += "</AND>\n"; 403 } 404 else if(bl.isOr) 405 { 406 s += "<OR>\n"; 407 s += toString(newbl); 408 s += "</OR>\n"; 409 } 410 } 411 } 412 413 return s; 414 } 415 } 416}