KleeneOperator.java
001 /*
002  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
003  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004  *
005  *  This file is part of GATE (see http://gate.ac.uk/), and is free
006  *  software, licenced under the GNU Library General Public License,
007  *  Version 2, June 1991 (in the distribution as file licence.html,
008  *  and also available at http://gate.ac.uk/gate/licence.html).
009  *
010  *  Eric Sword, 09/19/08
011  *
012  *  $Id$
013  */
014 package gate.jape;
015 
016 import org.apache.log4j.Logger;
017 import gate.jape.JapeConstants;
018 
019 import java.io.Serializable;
020 
021 /**
022  * Representation of Kleene operators on expressions. Kleene operators
023  * indicate the number of repetitions over an expression that are legal.
024  * The most common are star (0 or more), plus (1 or more), and optional
025  * (0 or 1, also referred to as "kleene query"). The class can also
026  * represent a range with a fixed minimum, maximum, or both. Finally, a
027  * default type of single (exactly 1) is also defined.
028  *
029  @version $Revision$
030  @author esword
031  */
032 public class KleeneOperator implements Serializable {
033   protected static final Logger log = Logger.getLogger(KleeneOperator.class);
034 
035   /**
036    * Enum containing the defined types of operators.
037    *
038    @version $Revision$
039    @author esword
040    */
041   public enum Type
042   {
043       SINGLE(""),
044       OPTIONAL("?"),
045       STAR("*"),
046       PLUS("+"),
047       RANGE("[x,y]");
048 
049       private String symbol;
050 
051       Type( )
052       {
053       }
054 
055       TypeString symbol )
056       {
057           this.symbol = symbol;
058       }
059 
060       public String getSymbol()
061       {
062           returnsymbol );
063       }
064 
065       /**
066        * Conversion routine from the old JapeConstants values to
067        * the type class.
068        @param op
069        @return
070        */
071       public static KleeneOperator.Type getFromJapeConstant(int op) {
072         switch(op) {
073           case JapeConstants.NO_KLEENE_OP:
074             return KleeneOperator.Type.SINGLE;
075           case JapeConstants.KLEENE_PLUS:
076             return KleeneOperator.Type.PLUS;
077           case JapeConstants.KLEENE_STAR:
078             return KleeneOperator.Type.PLUS;
079           case JapeConstants.KLEENE_QUERY:
080             return KleeneOperator.Type.OPTIONAL;
081           default:
082             throw new IllegalArgumentException("Unknown op code: " + op);
083         }
084       }
085 
086       /**
087        * Conversion routine from the string symbol for a type to the type
088        * Enum.
089        *
090        @param symbol
091        @return
092        */
093       public static KleeneOperator.Type getFromSymbol(String symbol) {
094         for(Type t : Type.values()) {
095           if (t.getSymbol().equals(symbol))
096             return t;
097         }
098 
099         return null;
100       }
101   }
102 
103   private Type type;
104   private Integer min;
105   private Integer max;
106   private String displayString;
107 
108   /**
109    * Create an operator with the given type, setting the
110    * appropriate min for each (and max when defined).  This constructor
111    * should not be used for {@link Type#RANGE} operators.  Use one of
112    * the other range-defining constructors in that case.
113    @param type
114    */
115   public KleeneOperator(Type type) {
116     this.type = type;
117 
118     //setup min and max in case needed
119     if (type == Type.SINGLE) {
120       min = 1;
121       max = 1;
122     }
123     else if (type == Type.OPTIONAL) {
124       min = 0;
125       max = 1;
126     }
127     else if (type == Type.STAR) {
128       min = 0;
129       //no set max
130     }
131     else if (type == Type.PLUS) {
132       min = 1;
133       //no set max
134     }
135     else if (type == Type.RANGE) {
136       //default to 1 and 1.  Really, the other constructor should be used.
137       min = 1;
138       max = 1;
139     }
140   }
141 
142   /**
143    * Create an operator with type RANGE and min and max both set to val.
144    @param val
145    */
146   public KleeneOperator(Integer val) {
147     this(val, val);
148   }
149 
150   /**
151    * Create an operator with type RANGE and the given min and max.
152    @param min
153    @param max
154    */
155   public KleeneOperator(Integer min, Integer max) {
156     this.type = Type.RANGE;
157 
158     if (min != null && max != null && min > max)
159       throw new IllegalArgumentException("min cannot be greater than max: " + min + ", " + max);
160 
161     this.min = min;
162     this.max = max;
163   }
164 
165   /**
166    * The string representation for most operators is the operator symbol itself.  For ranges, the
167    * min and max are shown.  If min == max, only one is shown.
168    */
169   @Override
170   public String toString() {
171     if (type != Type.RANGEreturn type.getSymbol();
172         
173     if(displayString != nullreturn displayString;
174 
175     StringBuilder sb = new StringBuilder("[");
176     sb.append(getMin());
177     if(!min.equals(max)) {
178       sb.append(",");
179       if(max != nullsb.append(max);
180     }
181     sb.append("]");
182 
183     displayString = sb.toString();
184     
185     return displayString;
186   }
187 
188   /*
189    * =================================================================================================
190    * Getters and Setters
191    * =================================================================================================
192    */
193   public Type getType() {
194     return type;
195   }
196 
197   public void setType(Type type) {
198     this.type = type;
199   }
200 
201   public Integer getMin() {
202     return min;
203   }
204 
205   public Integer getMax() {
206     return max;
207   }
208 }