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