initial load
[DTRules.git] / DTRules / src / main / java / com / dtrules / interpreter / RString.java
blobdebdb8e570eccb7b8c89d83a2905676519b491b0
1 /*
2 * $Id$
3 *
4 * Copyright 2004-2007 MTBJ, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
19 package com.dtrules.interpreter;
21 import com.dtrules.infrastructure.RulesException;
22 import com.dtrules.interpreter.operators.ROperator;
23 import com.dtrules.session.DTState;
24 import com.dtrules.session.RuleSet;
26 /**
27 * @author Paul Snow
30 public class RString extends ARObject {
32 RString pair;
33 String value;
34 boolean executable = false;
36 public double doubleValue() throws RulesException {
37 double d;
38 try {
39 d = Double.parseDouble(value);
40 } catch (NumberFormatException e) {
41 return super.doubleValue();
43 return d;
46 @Override
47 public int intValue() throws RulesException {
48 int i;
49 try {
50 i = Integer.parseInt(value);
51 } catch (NumberFormatException e) {
52 return super.intValue();
54 return i;
57 @Override
58 public long longValue() throws RulesException {
59 long l;
60 try {
61 l = Long.parseLong(value);
62 } catch (NumberFormatException e) {
63 return super.longValue();
65 return l;
68 @Override
69 public RDouble rDoubleValue() throws RulesException {
70 return RDouble.getRDoubleValue(doubleValue());
73 @Override
74 public RInteger rIntegerValue() throws RulesException {
75 return RInteger.getRIntegerValue(longValue());
78 @Override
79 public RName rNameValue() throws RulesException {
80 return RName.getRName(value);
83 @Override
84 public RString rStringValue() {
85 return this;
88 private RString(String v,boolean executable,RString pair){
89 value = v;
90 this.pair = pair;
91 this.executable = executable;
93 /**
94 * Return a non Executable string
95 * @param v
96 * @return
98 static public RString newRString(String v){
99 return newRString(v,false);
102 * Return an RString of the given executable nature.
103 * @param v
104 * @param executable
105 * @return
107 static public RString newRString(String v, boolean executable){
108 RString s = new RString(v,executable,null);
109 s.pair = new RString(v,!executable,s);
110 return s;
113 @Override
114 public IRObject getExecutable() {
115 if(isExecutable()){
116 return this;
117 }else{
118 return pair;
122 @Override
123 public IRObject getNonExecutable() {
124 if(isExecutable()){
125 return pair;
126 }else{
127 return this;
132 * Returns a boolean value if the String can be reasonably
133 * interpreted as a boolean.
135 * @Override
137 public boolean booleanValue() throws RulesException {
138 return RBoolean.booleanValue(value);
144 public RBoolean rBooleanValue() throws RulesException {
145 return RBoolean.getRBoolean(booleanValue());
149 * Returns String type.
150 * @see com.dtrules.interpreter.IRObject#type()
152 public int type() {
153 return iString;
157 * Here we look to see if we can do a compile time lookup of
158 * an object. If we can't, we just return the object unchanged.
159 * But if we can, then we return the value we looked up. That
160 * saves many, many runtime lookups.
162 static IRObject lookup(RuleSet ruleset, RName name){
163 IRObject v = ROperator.getPrimitives().get(name); // First check if it is an operator
164 if(v==null){ // No? Then
165 try { // look for a decision table.
166 v = ruleset.getEntityFactory(null).getDecisionTable(name);
167 } catch (RulesException e) { } // Any error just means the name isn't
168 } // a decision table. Not a problem.
169 if(v==null || v.type()== iArray) return name;
170 return v;
174 * Compiles the String and returns the executable Array Object
175 * that results. Unless the compilation fails, at which time
176 * we throw an exception.
178 * @return
179 * @throws RulesException
181 static public IRObject compile(RuleSet rs, String v, boolean executable) throws RulesException{
183 if(v==null)v=""; // Allow the compiling of null strings (we just don't do anything).
185 SimpleTokenizer tokenizer = new SimpleTokenizer(v);
187 IRObject result = compile(rs, tokenizer, v, executable, 0);
188 return result;
192 * The compiles of Strings are recursive. When we see a [ or {,
193 * we recurse. Then on a close bracket ] or } we return the
194 * non-executable or executable array. The RString checks to make
195 * sure it is the right type, and throws an error if it isn't.
196 * The recursive depth is checked by compile();
197 * @param tokenizer
198 * @return
199 * @throws RulesException
201 static private IRObject compile(RuleSet ruleset, SimpleTokenizer tokenizer, String v, boolean executable, int depth) throws RulesException {
202 try{
203 RArray result = new RArray(0,true,executable);
204 Token token;
205 while((token=tokenizer.nextToken())!=null){
206 if(token.getType()== Token.Type.STRING) {
207 IRObject rs = RString.newRString(token.strValue);
208 result.add(rs);
209 }else if(token.getType()== Token.Type.LSQUARE) {
210 IRObject o = compile(ruleset,tokenizer, v, false, depth+1);
211 result.add(o);
212 }else if(token.getType()== Token.Type.RSQUARE) {
213 if(depth==0 || executable){
214 throw new RulesException("Parsing Error",
215 "String Compile",
216 "\nError parsing <<"+v+">> \nThe token ']' was unexpected.");
219 return result;
220 }else if(token.getType()== Token.Type.LCURLY) {
221 IRObject o = compile(ruleset,tokenizer,v,true, depth+1);
222 result.add(o);
223 }else if(token.getType()== Token.Type.RCURLY) {
224 if(depth==0 || !executable){
225 throw new RulesException("Parsing Error",
226 "String Compile",
227 "\nError parsing <<"+v+">> \nThe token '}' was unexpected.");
230 return result;
231 }else if(token.getType()== Token.Type.NAME) {
232 if(token.nameValue.isExecutable()){ // All executable names are checked for compile time lookup.
233 IRObject prim = lookup(ruleset,token.nameValue);
234 if(prim == null){ // If this name is not a primitive, then
235 result.add(token.nameValue); // then add the name as it is to the array.
236 }else{
237 result.add(prim); // Otherwise, compile the reference to the operator.
239 }else{
240 result.add(token.nameValue);
243 }else if (token.getType() == Token.Type.DATE){
244 result.add(token.datevalue);
246 }else if (token.getType()== Token.Type.INT) {
247 RInteger i = RInteger.getRIntegerValue(token.longValue);
248 result.add(i);
249 }else if (token.getType()== Token.Type.REAL) {
250 RDouble d = RDouble.getRDoubleValue(token.doubleValue);
251 result.add(d);
254 if(depth!=0){
255 throw new RulesException("Parsing Error",
256 "String Compile",
257 "\nError parsing << " + v + " >>\n missing a " + (executable ? "}" : "]"));
260 return (IRObject) result;
261 } catch (RuntimeException e) {
262 throw new RulesException("Undefined","String Compile","Error compiling string: '"+v+"'\n"+e);
267 * Compiles this String and returns the object.
268 * @param executable
269 * @return
270 * @throws RulesException
272 public IRObject compile(RuleSet ruleset, boolean executable) throws RulesException{
273 return compile(ruleset, value,executable);
276 @Override
277 public boolean isExecutable() {
278 return executable;
281 public void execute(DTState state) throws RulesException {
282 if(isExecutable()){
283 IRObject o = compile(state.getSession().getRuleSet(),value,true);
284 o.execute(state);
285 }else{
286 state.datapush(this);
290 public String stringValue() {
291 return value;
293 public String toString(){
294 return "\""+value+"\"";
299 * returns 0 if both are equal. -1 if this object is less than the argument.
300 * 1 if this object is greater than the argument
302 public int compare(IRObject irObject) throws RulesException {
303 int f = this.value.compareTo(irObject.stringValue());
304 if(f<0)return -1;
305 if(f>0)return 1;
306 return f;
309 public boolean equals(IRObject o) throws RulesException {
310 return value.equals(o.stringValue());