blob: b536dc08c955de34b19fd6e248cc2374a939e8a0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.oodt.cas.pushpull.expressions;
//OODT imports
import org.apache.oodt.cas.pushpull.exceptions.MethodException;
//JDK imports
import java.util.LinkedList;
import java.util.Stack;
/**
*
* @author bfoster
* @version $Revision$
*
* <p>
* Describe your class here
* </p>.
*/
public class Method {
private String name;
private String infix;
private LinkedList<Variable> args;
private LinkedList<String> argNames;
private LinkedList<Integer> argTypes;
public final int INT = 0;
public final int STRING = 1;
public Method(String name) {
this.name = name;
args = new LinkedList<Variable>();
argNames = new LinkedList<String>();
argTypes = new LinkedList<Integer>();
}
public void addArgSignature(String name, int type) {
argNames.add(name);
argTypes.add(new Integer(type));
}
public boolean addArg(String name, String value) {
int nextLoc = args.size();
if (nextLoc >= 0) {
switch (argTypes.get(nextLoc).intValue()) {
case INT:
addArg(new Variable(null, new Integer(value)));
break;
case STRING:
addArg(new Variable(null, value));
break;
default:
return false;
}
return true;
} else
return false;
}
public void addArg(Variable v) {
args.addLast(v);
}
public void setBehavoir(String infix) {
this.infix = infix;
}
private LinkedList<ValidInput> convert(String infix) throws MethodException {
try {
LinkedList<ValidInput> output = new LinkedList<ValidInput>();
Stack<ValidInput> stack = new Stack<ValidInput>();
char[] infixArray = infix.toCharArray();
for (int i = 0; i < infixArray.length; i++) {
char c = infixArray[i];
// System.out.println("Next C = " + c);
switch (c) {
case '$':
StringBuffer variable = new StringBuffer("");
boolean globalVar = false;
// skip $ by incr i and if true then variable is a global
// variable and skip '{' by incr i again
if (infixArray[++i] == '{') {
globalVar = true;
i++;
}
for (; i < infixArray.length; i++) {
char ch = infixArray[i];
// System.out.println("ch = " + ch);
if ((ch <= 'Z' && ch >= 'A')
|| (ch <= 'z' && ch >= 'a')
|| (ch <= '9' && ch >= '0') || ch == '_')
variable.append(ch);
else
break;
}
if (globalVar) {
try {
output.addLast(GlobalVariables.hashMap.get(variable
.toString()));
} catch (Exception e) {
e.printStackTrace();
}
} else {
i--;
output.addLast(args.get(argNames.indexOf(variable
.toString())));
}
// System.out.println(output);
break;
case '#':
StringBuffer variableIntString = new StringBuffer("");
int k = i + 1;
for (; k < infixArray.length; k++) {
char ch = infixArray[k];
if (ch <= '9' && ch >= '0')
variableIntString.append(ch);
else
break;
}
output.addLast(new Variable(null, new Integer(
variableIntString.toString())));
i = k - 1;
break;
case '"':
StringBuffer variableString = new StringBuffer("");
int l = i + 1;
for (; l < infixArray.length; l++) {
char ch = infixArray[l];
if (ch != '"')
variableString.append(ch);
else
break;
}
output
.addLast(new Variable(null, variableString
.toString()));
i = l;
break;
case '+':
case '-':
case '/':
case '*':
// System.out.println("operators");
while (!stack.empty()
&& hasHigherPrecedence(stack.peek().toString()
.charAt(0), c)) {
output.addLast(stack.pop());
}
stack.push(new Operator(c + ""));
// System.out.println("Stack: " + stack);
break;
case ')':
while (!stack.empty()) {
ValidInput vi = stack.pop();
if (vi.toString().charAt(0) == '(')
break;
output.addLast(vi);
}
break;
case '(':
stack.push(new Punctuation(c + ""));
break;
}
}
while (!stack.empty())
output.addLast(stack.pop());
return output;
} catch (Exception e) {
throw new MethodException("Failed to convert infix to postfix : "
+ e.getMessage());
}
}
public Object execute() throws MethodException {
try {
Stack<ValidInput> stack = new Stack<ValidInput>();
LinkedList<ValidInput> postfix = convert(infix);
for (ValidInput vi : postfix) {
if (vi instanceof Variable) {
stack.push(vi);
} else if (vi instanceof Operator) {
ValidInput first = stack.pop();
ValidInput second = stack.pop();
switch (vi.toString().charAt(0)) {
case '+':
if (((Variable) first).isString()
|| ((Variable) second).isString()) {
String value = second.toString() + first.toString();
stack.push(new Variable(null, value));
} else if (((Variable) first).isInteger()
&& ((Variable) second).isInteger()) {
Integer value = new Integer(((Integer) second
.getValue()).intValue()
+ ((Integer) first.getValue()).intValue());
stack.push(new Variable(null, value));
} else {
throw new MethodException(
"Invalid Concatination/Addition types. . .must be String or Integer");
}
break;
case '-':
if (((Variable) first).isInteger()
&& ((Variable) second).isInteger()) {
Integer value = new Integer(((Integer) second
.getValue()).intValue()
- ((Integer) first.getValue()).intValue());
stack.push(new Variable(null, value));
} else {
throw new MethodException(
"Invalid Subtraction types. . .must be Integer");
}
break;
case '*':
if (((Variable) first).isInteger()
&& ((Variable) second).isInteger()) {
Integer value = new Integer(((Integer) second
.getValue()).intValue()
* ((Integer) first.getValue()).intValue());
stack.push(new Variable(null, value));
} else {
throw new MethodException(
"Invalid Multiplication types. . .must be Integer");
}
break;
case '/':
if (((Variable) first).isInteger()
&& ((Variable) second).isInteger()
&& ((Integer) ((Variable) first).getValue())
.intValue() > 0) {
Integer value = new Integer(((Integer) second
.getValue()).intValue()
/ ((Integer) first.getValue()).intValue());
stack.push(new Variable(null, value));
} else {
throw new MethodException(
"Invalid Division types. . .must be Integer and denominator must be greater than 0");
}
break;
}
}
}
return stack.pop().getValue();
} catch (Exception e) {
throw new MethodException("Failed to execute method " + name
+ " : " + e.getMessage());
}
}
// does first have higher precedence than second
private boolean hasHigherPrecedence(char first, char second) {
switch (first) {
case '+':
case '-':
switch (second) {
case '+':
case '-':
return true;
}
return false;
case '*':
case '/':
return true;
}
return false;
}
public String getName() {
return name;
}
}