001 /* 002 * Copyright 2007, 2012 Stephen Fisher and Junhyong Kim, University of 003 * Pennsylvania. 004 * 005 * This file is part of Glo-DB. 006 * 007 * Glo-DB is free software: you can redistribute it and/or modify it 008 * under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Glo-DB is distributed in the hope that it will be useful, but 013 * WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Glo-DB. If not, see <http://www.gnu.org/licenses/>. 019 * 020 * @(#)QueryElement.java 021 */ 022 023 package edu.upenn.gloDB.gui; 024 025 import edu.upenn.gloDB.GloDBUtils; 026 import java.util.ArrayList; 027 import java.util.Iterator; 028 029 /** 030 * Contains query info for either a single Track or a group of 031 * QueryElements (ie Tracks). 032 * 033 * @author Stephen Fisher 034 * @version $Id: QueryElement.java,v 1.1.2.19 2007/03/01 21:17:33 fisher Exp $ 035 */ 036 037 public class QueryElement implements Cloneable { 038 // public static final String[] OPERATORS = { "AND", "sAND", "&&", "OR", "||", "MINUS", "sMINUS", "-", "POS", "." }; 039 public static final String[] OPERATORS = { "AND", "sAND", "&&", "OR", "||", "MINUS", "sMINUS", "-", "POS" }; 040 041 /** Group of QueryElements (ie Tracks). */ 042 private ArrayList group = new ArrayList(); 043 044 /** Track ID. */ 045 public String track = ""; 046 047 /** 048 * Index for type of operation to be performed. The string values 049 * are stored in OPERATORS. 050 */ 051 public int operator = -1; 052 053 /** Negate? */ 054 public boolean negate = false; 055 056 /** Sequence ID. */ 057 public String sequence = ""; 058 059 /** Minimum acceptible Feature width. */ 060 private int minLength = -1; 061 062 /** Maximum acceptible Feature width. */ 063 private int maxLength = -1; 064 065 /** Minimum acceptible position within 'sequence'. */ 066 private int minSeqPos = -1; 067 068 /** 069 * Maximum acceptible position within 'sequence'. If -1, then 070 * goes to maximum Sequence length. 071 */ 072 private int maxSeqPos = -1; 073 074 /** Minimum ordered position ('POS'). */ 075 private int minPos = -1; 076 077 /** Maximum ordered position ('POS'). */ 078 private int maxPos = -1; 079 080 /** 081 * Minimum number of repeating features. 082 * @XXX Default = '1' 083 */ 084 private int minRepeat = 1; 085 086 /** 087 * Maximum number of repeating features. 088 * @XXX Default = '1' 089 */ 090 private int maxRepeat = 1; 091 092 /** 093 * Minimum number of positions between repeating features. If '0', 094 * then any overlap between features will be valid. 095 * @XXX Default = '0' 096 */ 097 private int minWithin = 0; 098 099 /** 100 * Maximum number of positions between repeating features. 101 * @XXX Default = '0' 102 */ 103 private int maxWithin = 0; 104 105 /** Create a new QueryElement object. */ 106 public QueryElement() { 107 } 108 109 /** Create a new QueryElement object. */ 110 public QueryElement(String track) { 111 this.track = track; 112 } 113 114 //-------------------------------------------------------------------------- 115 // Setters and Getters 116 117 public ArrayList getGroup() { return group; } 118 119 /** If null value, then will set group to a new ArrayList(). */ 120 public void setGroup(ArrayList group) { 121 if (group == null) this.group = new ArrayList(); 122 else this.group = group; 123 } 124 125 public void setMinLength(String val) { 126 if (val.trim().length() == 0) { 127 this.minLength = -1; 128 } else { 129 try { 130 this.minLength = Integer.parseInt(val.trim()); 131 } catch (NumberFormatException e) { 132 GloDBUtils.printError("Illegal value for width lower bound, using default (\"-1\")."); 133 this.minLength = -1; 134 } 135 } 136 } 137 public void setMaxLength(String val) { 138 if (val.trim().length() == 0) { 139 this.maxLength = -1; 140 } else { 141 try { 142 this.maxLength = Integer.parseInt(val.trim()); 143 } catch (NumberFormatException e) { 144 GloDBUtils.printError("Illegal value for width upper bound, using default (\"-1\")."); 145 this.maxLength = -1; 146 } 147 } 148 } 149 150 public void setMinSeqPos(String val) { 151 if (val.trim().length() == 0) { 152 this.minSeqPos = -1; 153 } else { 154 try { 155 this.minSeqPos = Integer.parseInt(val.trim()); 156 } catch (NumberFormatException e) { 157 GloDBUtils.printError("Illegal value for location lower bound, using default (\"-1\")."); 158 this.minSeqPos = -1; 159 } 160 } 161 } 162 public void setMaxSeqPos(String val) { 163 if (val.trim().length() == 0) { 164 this.maxSeqPos = -1; 165 } else { 166 try { 167 this.maxSeqPos = Integer.parseInt(val.trim()); 168 } catch (NumberFormatException e) { 169 GloDBUtils.printError("Illegal value for location upper bound, using default (\"-1\")."); 170 this.maxSeqPos = -1; 171 } 172 } 173 } 174 175 public void setMinRepeat(String val) { 176 if (val.trim().length() == 0) { 177 this.minRepeat = 1; 178 } else { 179 try { 180 this.minRepeat = Integer.parseInt(val.trim()); 181 } catch (NumberFormatException e) { 182 GloDBUtils.printError("Illegal value for repeat lower bound, using default (\"1\")."); 183 this.minRepeat = 1; 184 } 185 } 186 } 187 public void setMaxRepeat(String val) { 188 if (val.trim().length() == 0) { 189 this.maxRepeat = 1; 190 } else { 191 try { 192 this.maxRepeat = Integer.parseInt(val.trim()); 193 } catch (NumberFormatException e) { 194 GloDBUtils.printError("Illegal value for repeat upper bound, using default (\"1\")."); 195 this.maxRepeat = 1; 196 } 197 } 198 } 199 200 public void setMinWithin(String val) { 201 if (val.trim().length() == 0) { 202 this.minWithin = 0; 203 } else { 204 try { 205 this.minWithin = Integer.parseInt(val.trim()); 206 } catch (NumberFormatException e) { 207 GloDBUtils.printError("Illegal value for within lower bound, using default (\"0\")."); 208 this.minWithin = 0; 209 } 210 } 211 } 212 public void setMaxWithin(String val) { 213 if (val.trim().length() == 0) { 214 this.maxWithin = 0; 215 } else { 216 try { 217 this.maxWithin = Integer.parseInt(val.trim()); 218 } catch (NumberFormatException e) { 219 GloDBUtils.printError("Illegal value for within upper bound, using default (\"0\")."); 220 this.maxWithin = 0; 221 } 222 } 223 } 224 225 public void setMinPos(String val) { 226 if (val.trim().length() == 0) { 227 this.minPos = -1; 228 } else { 229 try { 230 this.minPos = Integer.parseInt(val.trim()); 231 } catch (NumberFormatException e) { 232 GloDBUtils.printError("Illegal value for width lower bound, using default (\"-1\")."); 233 this.minPos = -1; 234 } 235 } 236 } 237 public void setMaxPos(String val) { 238 if (val.trim().length() == 0) { 239 this.maxPos = -1; 240 } else { 241 try { 242 this.maxPos = Integer.parseInt(val.trim()); 243 } catch (NumberFormatException e) { 244 GloDBUtils.printError("Illegal value for width upper bound, using default (\"-1\")."); 245 this.maxPos = -1; 246 } 247 } 248 } 249 250 /** Most often need these as Strings */ 251 public String getMinLength() { 252 if (minLength == -1) return ""; 253 else return Integer.toString(minLength); 254 } 255 public String getMaxLength() { 256 if (maxLength == -1) return ""; 257 return Integer.toString(maxLength); 258 } 259 public String getMinSeqPos() { 260 if (minSeqPos == -1) return ""; 261 return Integer.toString(minSeqPos); 262 } 263 public String getMaxSeqPos() { 264 if (maxSeqPos == -1) return ""; 265 return Integer.toString(maxSeqPos); 266 } 267 public String getMinRepeat() { 268 if (minRepeat == 1) return ""; 269 return Integer.toString(minRepeat); 270 } 271 public String getMaxRepeat() { 272 if (maxRepeat == 1) return ""; 273 return Integer.toString(maxRepeat); 274 } 275 public String getMinWithin() { 276 if (minWithin == 0) return ""; 277 return Integer.toString(minWithin); 278 } 279 public String getMaxWithin() { 280 if (maxWithin == 0) return ""; 281 return Integer.toString(maxWithin); 282 } 283 public String getMinPos() { 284 if (minPos == -1) return ""; 285 else return Integer.toString(minPos); 286 } 287 public String getMaxPos() { 288 if (maxPos == -1) return ""; 289 return Integer.toString(maxPos); 290 } 291 292 293 //-------------------------------------------------------------------------- 294 // Miscellaneous Methods 295 296 /** Returns the string equivalent to the operator index value. */ 297 public static String getOperatorVal(int index) { 298 if (index < 0) return ""; 299 else return OPERATORS[index]; 300 } 301 302 /** Returns the string equivalent to the operator index value. */ 303 public static boolean isOrderOperator(int index) { 304 if (index < 0) return false; 305 306 String operator = OPERATORS[index]; 307 // if ((operator.compareToIgnoreCase("POS") == 0) 308 // || (operator.compareToIgnoreCase(".") == 0)) { 309 if (operator.compareToIgnoreCase("POS") == 0) { 310 return true; 311 } else { 312 return false; 313 } 314 } 315 316 /** Returns the string equivalent to the operator index value. */ 317 public static boolean isOrderOperator(String operator) { 318 // if ((operator.compareToIgnoreCase("POS") == 0) 319 // || (operator.compareToIgnoreCase(".") == 0)) { 320 if (operator.compareToIgnoreCase("POS") == 0) { 321 return true; 322 } else { 323 return false; 324 } 325 } 326 327 /** Returns the string equivalent to the operator index value. */ 328 public String getOperatorVal() { 329 if (operator < 0) { 330 return ""; 331 } else { 332 String op = OPERATORS[operator]; 333 if (isOrderOperator(op)) { 334 if (maxPos == -1) op += "{" + getMinPos() + "}"; 335 else op += "{" + getMinPos() + ", " + getMaxPos() + "}"; 336 } 337 return op; 338 } 339 } 340 341 /** 'element' is assumed to be a QueryElement. */ 342 public void addToGroup(Object element) { 343 group.add(element); 344 } 345 346 public boolean isGrouped() { 347 if (group.size() > 0) return true; 348 else return false; 349 } 350 351 public int groupSize() { return group.size(); } 352 353 public Iterator groupIterator() { return group.iterator(); } 354 355 /** 356 * Create a shallow clone (just clone the structure, not the 357 * Objects) of the existing object. 358 */ 359 public Object clone() { 360 QueryElement queryElement = new QueryElement(); 361 queryElement.group = this.group; 362 queryElement.track = this.track; 363 queryElement.operator = this.operator; 364 queryElement.negate = this.negate; 365 queryElement.sequence = this.sequence; 366 queryElement.minLength = this.minLength; 367 queryElement.maxLength = this.maxLength; 368 queryElement.minSeqPos = this.minSeqPos; 369 queryElement.maxSeqPos = this.maxSeqPos; 370 queryElement.minRepeat = this.minRepeat; 371 queryElement.maxRepeat = this.maxRepeat; 372 queryElement.minWithin = this.minWithin; 373 queryElement.maxWithin = this.maxWithin; 374 queryElement.minPos = this.minPos; 375 queryElement.maxPos = this.maxPos; 376 return queryElement; 377 } 378 379 /** 380 * Creates an array with the fields in the following order: 381 * "operator, negate, group, track, sequence, min/max length, 382 * min/max pos". 383 */ 384 public Object[] toArray() { 385 Object[] out = new Object[10]; 386 out[0] = getOperatorVal(); 387 out[1] = new Boolean(negate); 388 if (isGrouped()) { 389 out[2] = new Boolean(true); 390 out[3] = ""; 391 } else { 392 out[2] = new Boolean(false); 393 out[3] = track; 394 } 395 out[4] = sequence; 396 out[5] = getMinLength(); 397 out[6] = getMaxLength(); 398 out[7] = getMinSeqPos(); 399 out[8] = getMaxSeqPos(); 400 out[9] = getMinRepeat(); 401 out[10] = getMaxRepeat(); 402 out[11] = getMinWithin(); 403 out[12] = getMaxWithin(); 404 out[13] = this.toString(); 405 return out; 406 } 407 408 /** 409 * Returns a String that contains the qualifiers (Sequence, 410 * Length, and SeqPos) formatted for a query. 411 */ 412 public String toStringQualifiers() { 413 String out = ""; 414 415 // add sequence 416 if (sequence != "") out += " S:" + sequence; 417 418 // add length and seqPos 419 String tmp = ""; 420 if (minLength > -1) { 421 if (maxLength == -1) { // <min> 422 tmp = " <" + Integer.toString(minLength); 423 } else { // <min, max> 424 tmp = " <" + Integer.toString(minLength) + ", " + Integer.toString(maxLength); 425 } 426 } 427 if (minSeqPos > -1) { 428 if (tmp == "") tmp = " <"; 429 if (maxSeqPos == -1) { // ;min> 430 tmp += "; " + Integer.toString(minSeqPos) + ">"; 431 } else { // ;min, max> 432 tmp += "; " + Integer.toString(minSeqPos) + ", " + Integer.toString(maxSeqPos) + ">"; 433 } 434 } else { 435 if (tmp != "") tmp += ">"; 436 } 437 out += tmp; 438 439 // add repeat 440 tmp = ""; 441 if (minRepeat > 1) { 442 if (maxRepeat == 1) { // {min} 443 tmp = " {" + Integer.toString(minRepeat); 444 } else { // {min, max} 445 tmp = " {" + Integer.toString(minRepeat) + ", " + Integer.toString(maxRepeat); 446 } 447 448 if (minWithin > 0) { 449 if (maxWithin == 0) { // ; min} 450 tmp += "; " + Integer.toString(minWithin); 451 } else { // ;min, max} 452 tmp += "; " + Integer.toString(minWithin) + ", " + Integer.toString(maxWithin); 453 } 454 } 455 456 tmp += "}"; 457 } 458 out += tmp; 459 460 return out; 461 } 462 463 /** Returns QueryElement information for debugging purposes. */ 464 public String toString() { 465 if ((! isGrouped()) && (track == "")) return ""; 466 467 // add operator 468 String out = ""; 469 // if (operator.length() > 0) out += " " + operator + " "; 470 if (operator > -1) out += " " + getOperatorVal() + " "; 471 472 if (isGrouped()) { 473 // add negate and group 474 if (negate) out += "! ( "; 475 else out += "( "; 476 for (Iterator i = group.iterator(); i.hasNext();) { 477 out += i.next(); 478 } 479 out += " )"; 480 } else { 481 // add negate and track 482 if (negate) out += "! " + track; 483 else out += track; 484 } 485 486 out += toStringQualifiers(); 487 488 return out; 489 } 490 } // QueryElement.java