1 /*
2 * GeoVISTA Center (Penn State, Dept. of Geography)
3 * Copyright (c), 1999 - 2002, GeoVISTA Center
4 * All Rights Researved.
5 *
6 * Description:
7 * Function classes used only by edu.psu.geovista.app.spreadsheet.formula.Formula to evaluate functions.
8 * Any function needs to have a function handler that implements
9 * the "evaluate" interface of the base class functions.Function.
10 * A function can accept zero, one, or more parameters. Each parameter
11 * is a number, a relative/absolute address or an address range (e.g., A1:B3).
12
13 * The code has some reference to code written by Hua Zhong from Columbia University
14 *
15 * Apr 2, 2003
16 * Time: 10:42:12 PM
17 * @author Jin Chen
18 */
19
20 package edu.psu.geovista.app.spreadsheet.functions;
21
22
23
24 import edu.psu.geovista.app.spreadsheet.exception.ParserException;
25
26 import javax.swing.table.TableModel;
27 import java.util.*;
28 import java.io.*;
29 import java.awt.*;
30
31 import edu.psu.geovista.app.spreadsheet.formula.Node;
32 import edu.psu.geovista.app.spreadsheet.exception.NoReferenceException;
33 import edu.psu.geovista.app.spreadsheet.formula.Formula;
34 import edu.psu.geovista.app.spreadsheet.table.SSTableModel;
35 import edu.psu.geovista.app.spreadsheet.formula.Cell;
36 import edu.psu.geovista.app.spreadsheet.util.Debug;
37
38
39 public abstract class Function {
40
41 static private ParserException exception = new ParserException("#PARAM?");
42 //protected HashSet owners;//who use the function now
43 protected Formula owner;
44
45 // whether the specified parameter node is an address range
46 protected boolean isRange(Node param) {
47 LinkedList exp = param.getExp();
48 return exp.size() == 1 &&
49 ((Node)exp.getFirst()).isType(Node.COLON);
50 //((edu.psu.geovista.app.spreadsheet.formula.Node)param.getExp().getFirst()).isType(edu.psu.geovista.app.spreadsheet.formula.Node.COLON);
51 }
52
53 // return the first node of a specified parameter
54 protected Node getFirst(Node param) {
55 return (Node)param.getExp().getFirst();
56 }
57
58 // whether this function has any parameter
59 protected static void checkParamsExist(Node func) throws ParserException {
60
61 if (func.getParams().size()==0)
62 throw exception;
63 }
64
65 /***
66 * This gets the first float number of a parameter list, for functions
67 * only accepting a single parameter such as <code>ABS</code>, <code>COS
68 * </code>, etc.
69 *
70 * @param table the SharpTabelModel
71 * @param node the edu.psu.geovista.app.spreadsheet.formula unit
72 * @param col the int column coordinate
73 * @param row the int row coordinate
74 * @return the float number
75 */
76 protected float getSingleParameter( Node node)
77 throws ParserException,NoReferenceException {
78 // edu.psu.geovista.app.spreadsheet.formula.Node param = node.getNextParam();
79 LinkedList params = node.getParams();
80 Debug.showLinkedList(params,"getSingleParameter( ) show params of node "+node );
81 if (params.size() != 1)
82 throw new ParserException("#PARAM?");
83
84 LinkedList exp = ((Node)params.getFirst()).getExp(); //??? why first, what if there is multiple parameters
85 Debug.showLinkedList(exp,"getSingleParameter( ) show exp "+exp );
86 //Formula f=new Formula(this.getOwners() );
87 return this.getOwner().evaluate(exp) .floatValue();
88
89 }
90
91
92 /***
93 * This should be implemented in each function.
94 *
95 * @param table the SharpTabelModel
96 * @param node the function node starting with the funciton name
97 * with a chain of parameters
98 * @param col the int column coordinate
99 * @param row the int row coordinate
100 * @edu.psu.geovista.app.spreadsheet.exception ParserException
101 */
102 public abstract Number evaluate(Node node) throws ParserException,NoReferenceException;
103
104
105
106 /***
107 * Return the usage of the function
108 */
109 public abstract String getUsage();
110
111 /***
112 * Return the description of the function
113 */
114 public abstract String getDescription();
115
116 /***
117 * Whether this function requires parameters.
118 * By default yes.
119 * @see FunctionPI
120 * @see FunctionE
121 */
122 public boolean requireParams() { return true; }
123
124 /***
125 * Jin:
126 * Only for those function whose arguments is set of range.
127 * e.g.: SUM, AVG,MEAN...
128 * @param node the function node.
129 * @return address(x,y) in view
130 */
131 public static SelectionRange getRangeArea(Node node) throws ParserException{
132 SelectionRange range=null;
133
134 checkParamsExist(node);
135 LinkedList params = node.getParams();//only 1 element
136 Node exp=(Node)params.getFirst() ;// expresion Node(type=Node.EXP). e.g. a1:a2
137 Node colonNode=((Node)exp.getParams().getFirst());// colon Node(type=Node.COLON) e.g.: a1:a2
138 range=processColonNode(colonNode);
139
140 return range;
141 }
142 /***
143 * convert a colon node(which contain 2 ranges) into a SelectionRange
144 */
145 public static SelectionRange processColonNode(Node colonNode)throws ParserException {
146 SelectionRange range=null;
147 Point[] ps=new Point[2];//a 2 points(sp,ep)
148 Point sp=null,ep=null;//start point, end point of the range
149 //!!! following part is same as Formula's evalueExpression
150 Node start=colonNode.getNextRange() ;//start(upLeft) of the range
151 Node end=start.getNextRange() ;//end (downRight) of the range
152
153 if (start.getType() ==Node.REL_ADDR ){
154 Cell cell=start.getReference() ;
155 sp=cell.getViewAddress();
156
157 Debug.println("Cell address :"+cell.getViewAddress() );
158 }
159 else if(start.getType() ==Node.ABS_ADDR ){
160 sp=start.getAddress();
161 Debug.println("AB address:"+start.getAddress() );
162 }
163 else{
164 assert false: "Unable to handle the expression";
165 //throw edu.psu.geovista.app.spreadsheet.exception: unable to handle the expression
166 }
167 if (end.getType() ==Node.REL_ADDR ){
168 Cell cell=end.getReference() ;
169 ep=cell.getViewAddress();
170 Debug.println("Cell address :"+cell.getViewAddress() );
171 }
172 else if(end.getType() ==Node.ABS_ADDR ){
173 ep=end.getAddress() ;
174 Debug.println("AB address:"+end.getAddress() );
175 }
176 else{
177
178 assert false: "Unable to handle the expression";
179 //throw edu.psu.geovista.app.spreadsheet.exception: unable to handle the expression
180 }
181 if (sp.getX()==ep.getX()){//a single column range
182 if (sp.getY() <=ep.getY()){
183 ps[0]=sp;
184 ps[1]=ep;
185 }
186 else{
187 ps[0]=ep;
188 ps[1]=sp;
189 }
190 range=new SelectionRange(ps,SelectionRange.SINGLE_ROW );
191 }
192 else if (sp.getY()==ep.getY()){//a single row range
193 if (sp.getX() <=ep.getX()){
194 ps[0]=sp;
195 ps[1]=ep;
196 }
197 else{
198 ps[0]=ep;
199 ps[1]=sp;
200 }
201 range=new SelectionRange(ps,SelectionRange.SINGLE_COLUMN );
202
203 }
204 else{ //assume only handle a single column range or a single row range with sp above ep
205 throw new ParserException("Unable to calculate on the given range.");
206 }
207 return range;
208 }
209 /*
210 public HashSet getOwners() {
211 return owners;
212 }
213
214 public void setOwners(HashSet owners) {
215 this.owners = owners;
216 } */
217
218 protected Function getSupportFuntion(String fname, Formula owner){
219 //Function sf=Formula.getFuncHandler(fname);
220 Function sf=owner.getFunctionManager().getFuncHandler(fname);
221 sf.setOwner(owner);
222 return sf;
223 }
224
225 public void setOwner(Formula owner) {
226 this.owner = owner;
227 }
228
229 public Formula getOwner() {
230 return owner;
231 }
232 } //edu.psu.geovista.app.spreadsheet.functions.Function Class
233
234
235
236
237
238
239
240
This page was automatically generated by Maven