1 /*
2 $Id: Addition.java 710 2005-03-21 16:34:22Z guest $
3 */
4
5
6 /*
7 Copyright (C) 2001-2002 Mainline Project (I3S - ESSI - CNRS -UNSA)
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 For further information on the GNU Lesser General Public License,
24 see: http://www.gnu.org/copyleft/lesser.html
25 For further information on this library, contact: mainline@essi.fr
26 */
27
28
29 package fr.ove.openmath.jome.model;
30
31 import java.util.*;
32 import fr.ove.openmath.jome.model.*;
33 import fr.ove.openmath.jome.model.events.*;
34 import fr.ove.openmath.jome.model.evaluation.*;
35
36 /***
37 * The operator "+".<BR>
38 *
39 * <CODE>Addition</CODE> represents a node in the formula tree.
40 * Its children are the operands of the operation.
41 *
42 * @author © 1999 DIRAT Laurent
43 * @version 2.0 25/06/1999
44 */
45 public class Addition extends NaryOperator {
46 /***
47 * The Constructor.
48 */
49 public Addition() {
50 setResourceIdentifier("ADDITION");
51 setValue("+");
52 setAsOperatorPriority(resourcesManager.getAsOperatorPriority("plusPriorities"));
53 setAsOperandPriority(resourcesManager.getAsOperandPriority("plusPriorities"));
54 setAreOperandsMovable(true);
55 }
56
57 /***
58 * Inserts the operator instance in the formula tree, from the current insertion position.
59 * (checks the priorities and goes up in the tree if necessary).
60 *
61 * @param current the current insertion position.
62 * @return the new insertion position.
63 */
64 public FormulaTreeStructure insert(FormulaTreeStructure current) {
65 // On cherche la position d'insertion de notre "+"
66 current = findLocation(current);
67 int currentAsOperandPriority = current.getAsOperandPriority();
68 int currentAsOperatorPriority = current.getAsOperatorPriority();
69
70 if (currentAsOperatorPriority == getAsOperandPriority()) {
71 // On a dÈj? tapÈ dans la formule un "+", on va donc insÈrer un nouveau
72 // "+" dans le prÈcÈdent ==> cas particuliers.
73 if ((currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryPlusPriorities")) ||
74 (currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryMinusPriorities"))) {
75 // Si on est en prÈcense de ce cas l?, la position d'insertion est
76 // sur un op. unaire ("+" ou "-"). Il faut rÈcupÈrer le pËre de l'op.
77 // en question, i.e. une instance d'Addition que l'on a insÈrÈ auparavant
78 // dansla FST.
79 FormulaTreeStructure father = (FormulaTreeStructure) current.getFather();
80
81 if (currentAsOperandPriority == resourcesManager.getAsOperandPriority("unaryPlusPriorities")) {
82 FormulaTreeStructure operand = (FormulaTreeStructure) current.getChild(0);
83 // si en fait, notre position d'insertion est un "+" unaire, on enlËve
84 // notre opÈrateur unaire pour ne garder que son opÈrande.
85 // Ex: on avait +a, on tape "+", on gÈnËre a+[?] o? [?] est le template.
86 int rank = current.getRank();
87
88 father.addChild(operand, rank);
89 father.removeChild(current);
90 }
91
92 // On insËre notre template.
93 VariableOrNumber template0 = new VariableOrNumber();
94 father.addChild(template0);
95
96 // On retourne la refÈrence de notre dernier point d'insertion.
97 return template0;
98 }
99
100 // On est dans le cas classique de la saisie d'une suite "+", on insËre
101 // notre template dans la FTS.
102 VariableOrNumber template = new VariableOrNumber();
103 current.addChild(template);
104
105 // On retourne la refÈrence de notre dernier point d'insertion.
106 return template;
107 }
108 else {
109 // On est dans le cas o? on commence ? saisir une addition.
110
111 // On ajoute l'opÈrateur "+" comme fils ? l'opÈrateur courant.
112 // Pour gÈrer le fait que l'on puisse taper un "+" binaire ou unaire,
113 // notre opÈrateur "+" unaire de notre FTS (UnaryPlus) sera ajoutÈ comme
114 // fils ? l'instance courante. D'o? l'ajout systÈmatique suivant ? la position
115 // d'insertion. La distinction de cas singuliers est faite au test suivant.
116 current.addChild(this);
117
118 // Ce test est nÈcessaire pour savoir si on est dans le cas du "+" binaire
119 // ou du "+" unaire.
120 if (current.getNbChildren() > 1) {
121 // Il faut que l'on fasse attention pour savoir si l'on veut entrer un "+" unaire ou pas.
122 // Donc on vient d'ajouter notre instance comme fils a current.
123 // Si on est l?, 2 solutions, le fils de current qui a pour rank, le rank de l'instance -1 :
124 // * est un template ==> on saisi un plus unaire
125 // * n'est pas un template ==> on saisi une addition
126 FormulaTreeStructure fts = (FormulaTreeStructure) current.getChild(getRank() - 1);
127
128 if(fts.getFather() instanceof Function2){
129 current.removeChild(fts);
130 fts = (FormulaTreeStructure) current.getChild(fts.getRank() - 1);
131 }
132
133 // Quelque soit le cas, on enlËve fts de current.
134 // Dans le cas du plus unaire, (fts est un template) un template sera rajoutÈ avec
135 // l'insertion du UnaryPlus
136 // Dans le cas de l'addition, fts sera ajoutÈ ? notre instance
137 current.removeChild(fts);
138
139 if ((fts.getAsOperatorPriority() == resourcesManager.getAsOperatorPriority("constantPriorities")) &&
140 fts.isTemplate()) {
141 // On ajoute un opÈrateur "+" unaire comme fils ? notre instance
142 current = this;
143 current = (new UnaryPlus()).insert(current);
144
145 // On retourne la rÈfÈrence de notre dernier point d'insertion
146 return current;
147 }
148 else {
149 addChild(fts);
150
151 // On ajoute un template ? l'addition
152 VariableOrNumber template = new VariableOrNumber();
153 addChild(template);
154
155 // On retourne la rÈfÈrence de notre dernier point d'insertion
156 return template;
157 }
158 }
159 else { // on est dans le cas du "+" unaire
160 // Comme dit prÈcÈdemment, on ajoute un opÈrateur "+" unaire comme
161 // fils ? l'instance courante.
162 current = this;
163 current = (new UnaryPlus()).insert(current);
164
165 // On retourne la rÈfÈrence de notre dernier point d'insertion
166 return current;
167 }
168 }
169 }
170
171 /***
172 * The Creation of the corresponding linear expression of the formula.
173 */
174 public String createLinear(String linear) {
175 FormulaTreeStructure child;
176
177 for (int i = 0; i < getNbChildren(); i++) {
178 child = (FormulaTreeStructure) getChild(i);
179 if (i == 0)
180 linear = child.createLinear(linear);
181 else {
182 if (!((child instanceof UnaryPlus) || (child instanceof UnaryMinus)))
183 linear += "+";
184 linear = child.createLinear(linear);
185 }
186 }
187 return linear;
188 }
189
190 /***
191 * Evaluates the instance.
192 */
193 public String evaluate() {
194 Vector evaluations = new Vector();
195
196 // On commence par Èvaluer tous les fils de l'instance
197 for (Enumeration e = getChildren().elements(); e.hasMoreElements(); )
198 evaluations.addElement(((FormulaTreeStructure) e.nextElement()).evaluate());
199
200 int nbEvaluations = evaluations.size();
201 String anEvaluation, currEvaluation;
202 // Maintenant, on parcourre toutes les Èvaluations calculÈes et on essaye de leur appliquer
203 // l'opÈrateur courant
204 for (int i = 1; i < nbEvaluations; i++) {
205 currEvaluation = (String) evaluations.elementAt(i);
206
207 for (int j = 0; j < i; j++) {
208 anEvaluation = (String) evaluations.elementAt(j);
209
210 if (Evaluator.type(currEvaluation) == Evaluator.type(anEvaluation)) {
211 evaluations.insertElementAt(Evaluator.evaluate(anEvaluation, currEvaluation, "+"), j);
212 evaluations.removeElement(anEvaluation);
213 evaluations.removeElement(currEvaluation);
214 i--;
215 nbEvaluations--;
216 break;
217 }
218 }
219 }
220
221 // On a appliquÈ l'opÈrateur courant, on retourne maintenant le rÈsultat, en prenant soin
222 // d'intercaler des opÈrateur entre les Èvaluations si nÈcessaire
223 String result = (String) evaluations.firstElement();
224 for (int i = 1; i < nbEvaluations; i++) {
225 anEvaluation = (String) evaluations.elementAt(i);
226 if (anEvaluation.charAt(0) == '-')
227 result += anEvaluation;
228 else
229 result += "+" + anEvaluation;
230 }
231 return result;
232 }
233 }