KleeneOperator.java
001 /*
002  *  Copyright (c) 1995-2012, 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 
034   private static final long serialVersionUID = 5590283708947918804L;
035 
036   protected static final Logger log = Logger.getLogger(KleeneOperator.class);
037 
038   /**
039    * Enum containing the defined types of operators.
040    *
041    @version $Revision$
042    @author esword
043    */
044   public enum Type
045   {
046       SINGLE(""),
047       OPTIONAL("?"),
048       STAR("*"),
049       PLUS("+"),
050       RANGE("[x,y]");
051 
052       private String symbol;
053 
054       Type( )
055       {
056       }
057 
058       TypeString symbol )
059       {
060           this.symbol = symbol;
061       }
062 
063       public String getSymbol()
064       {
065           returnsymbol );
066       }
067 
068       /**
069        * Conversion routine from the old JapeConstants values to
070        * the type class.
071        */
072       public static KleeneOperator.Type getFromJapeConstant(int op) {
073         switch(op) {
074           case JapeConstants.NO_KLEENE_OP:
075             return KleeneOperator.Type.SINGLE;
076           case JapeConstants.KLEENE_PLUS:
077             return KleeneOperator.Type.PLUS;
078           case JapeConstants.KLEENE_STAR:
079             return KleeneOperator.Type.PLUS;
080           case JapeConstants.KLEENE_QUERY:
081             return KleeneOperator.Type.OPTIONAL;
082           default:
083             throw new IllegalArgumentException("Unknown op code: " + op);
084         }
085       }
086 
087       /**
088        * Conversion routine from the string symbol for a type to the type
089        * Enum.
090        */
091       public static KleeneOperator.Type getFromSymbol(String symbol) {
092         for(Type t : Type.values()) {
093           if (t.getSymbol().equals(symbol))
094             return t;
095         }
096 
097         return null;
098       }
099   }
100 
101   private Type type;
102   private Integer min;
103   private Integer max;
104   private String displayString;
105 
106   /**
107    * Create an operator with the given type, setting the
108    * appropriate min for each (and max when defined).  This constructor
109    * should not be used for {@link Type#RANGE} operators.  Use one of
110    * the other range-defining constructors in that case.
111    @param type
112    */
113   public KleeneOperator(Type type) {
114     this.type = type;
115 
116     //setup min and max in case needed
117     if (type == Type.SINGLE) {
118       min = 1;
119       max = 1;
120     }
121     else if (type == Type.OPTIONAL) {
122       min = 0;
123       max = 1;
124     }
125     else if (type == Type.STAR) {
126       min = 0;
127       //no set max
128     }
129     else if (type == Type.PLUS) {
130       min = 1;
131       //no set max
132     }
133     else if (type == Type.RANGE) {
134       //default to 1 and 1.  Really, the other constructor should be used.
135       min = 1;
136       max = 1;
137     }
138   }
139 
140   /**
141    * Create an operator with type RANGE and min and max both set to val.
142    @param val
143    */
144   public KleeneOperator(Integer val) {
145     this(val, val);
146   }
147 
148   /**
149    * Create an operator with type RANGE and the given min and max.
150    @param min
151    @param max
152    */
153   public KleeneOperator(Integer min, Integer max) {
154     this.type = Type.RANGE;
155 
156     if (min != null && max != null && min > max)
157       throw new IllegalArgumentException("min cannot be greater than max: " + min + ", " + max);
158 
159     this.min = min;
160     this.max = max;
161   }
162 
163   /**
164    * The string representation for most operators is the operator symbol itself.  For ranges, the
165    * min and max are shown.  If min == max, only one is shown.
166    */
167   @Override
168   public String toString() {
169     if (type != Type.RANGEreturn type.getSymbol();
170         
171     if(displayString != nullreturn displayString;
172 
173     StringBuilder sb = new StringBuilder("[");
174     sb.append(getMin());
175     if(!min.equals(max)) {
176       sb.append(",");
177       if(max != nullsb.append(max);
178     }
179     sb.append("]");
180 
181     displayString = sb.toString();
182     
183     return displayString;
184   }
185 
186   /*
187    * =================================================================================================
188    * Getters and Setters
189    * =================================================================================================
190    */
191   public Type getType() {
192     return type;
193   }
194 
195   public void setType(Type type) {
196     this.type = type;
197   }
198 
199   public Integer getMin() {
200     return min;
201   }
202 
203   public Integer getMax() {
204     return max;
205   }
206 }