View Javadoc

1   /*
2   $Id: Formula.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 java.awt.*;
33  
34  import fr.ove.openmath.jome.model.processor.*;
35  import fr.ove.openmath.jome.model.events.ModelEvent;
36  import fr.ove.openmath.jome.model.evaluation.*;
37  import fr.ove.openmath.jome.behaviour.Modifiable;
38  import fr.ove.openmath.jome.ctrl.linear.events.*;
39  import fr.ove.utils.Factory;
40  import fr.ove.openmath.jome.formaters.om.*;
41  import fr.ove.openmath.jome.formaters.pmml.PMathMLFormater;
42  import fr.ove.openmath.jome.formaters.mml.*;
43  
44  /***
45  * The formula.<BR>
46  * The root of the formula tree structure.
47  *
48  * @author © 2000 DIRAT Laurent
49  * @version 2.0  28/06/99
50  */
51  public class Formula extends FormulaTreeStructure implements LinearParserListener {
52      /***
53      * The current insertion position in the formula (tree structure).
54      */
55      public FormulaTreeStructure current;
56      
57      /***
58      * The OpenMath formater for exportation of the formula as an OpenMath object
59      */
60      OpenMathFormater omFormater = new OpenMathFormater();
61      
62      /***
63      * The MathML formater for exportation of the formula as a MathML object
64      */
65      MathMLFormater mmlFormater = new MathMLFormater();
66      
67      PMathMLFormater pmmlFormater = new PMathMLFormater();
68      
69      // On maintient une pile qui va contenir les instances qui ont besoin d'Ítre "fermÈes".
70      // Par exemple les parenthËses, les listes, ...
71      // NÈcessaire de faire Áa ? cause des inclusions mutuelles d'opÈrateurs du mÍme type.
72      private Stack openingStack = new Stack();
73      
74      /***
75      * Flag to deal with a possible processing of the model of the formula before rendering.<BR>
76      * The default is <CODE>false</CODE>, i.e. we want the formula to be displayed
77      * normally (no processing).
78      */
79      private boolean doProcessing = false;
80      
81      /***
82      * The processor which will process the model of the formula before rendering if wanted.<BR>
83      * By default, no processor is set. One processor has to added when desired.
84      */
85      private Processor processor = null;
86  
87      /***
88      * The Constructor.
89      */
90      public Formula () {
91          setResourceIdentifier("FORMULA");
92          setAsOperatorPriority(resourcesManager.getAsOperatorPriority("formulaPriorities"));
93          setAsOperandPriority(resourcesManager.getAsOperandPriority("formulaPriorities"));
94          current = this;
95      }
96      
97      /***
98      * To check is the instance is an operator.
99      * @return <CODE>true</CODE> if it is an operator. <CODE>false</CODE> otherwise.
100     */
101     public boolean isOperator() {
102         return false;
103     }
104     
105     /***
106     * Inserts the operator instance in the formula tree, from the current insertion position.
107     * (checks the priorities and goes up in the tree if necessary).<BR>
108     * At the moment, we can't insert a formula in an another formula.
109     * @param current the current insertion position.
110     */
111     public FormulaTreeStructure insert(FormulaTreeStructure current) {
112         // On ne devrait pas insÈrer de formule !!
113         // A voir, peut Ítre utile pour le drag'n drop d'une nouvelle formule;
114         return null;
115     }
116 
117     /***
118     * The Creation of the corresponding linear expression of the formula.
119     */
120     public String createLinear(String linear) {
121         if (getNbChildren() > 0)
122             linear = ((FormulaTreeStructure) getChild(0)).createLinear(linear);
123             
124         return linear;
125     }
126     
127     /***
128     * clears the formula.
129     */
130     public void clear() {
131         // On enlËve tous les enfants de la FTS.
132         removeAll();
133         // On remet la position courante d'insertion sur la racine de la FTS
134         current = this;
135     }
136     
137     /***
138     * Returns the linear expression of the formula.
139     */
140     public String getLinear() {
141         return createLinear("");
142     }
143 
144     /***
145     * Returns the OpenMath representation of the formula.
146     */
147     public String getOpenMath() {
148         return omFormater.getOpenMath(this);
149     }
150     
151     /***
152     * Returns the MathML representation of the formula.
153     */
154     public String getMathML() {
155         return mmlFormater.getMathML(this);
156     }
157     
158     public String getPMML(){
159     	return pmmlFormater.getPMML(this);
160     }
161     
162     /***
163     * Evaluates the instance.
164     */
165     public String evaluate() {
166         if (getNbChildren() > 0)
167             return ((FormulaTreeStructure) getChild(0)).evaluate();
168         else
169             return "";
170     }
171     
172     /***
173     * Treats the event received.
174     * @param linearParserEvent the event received.
175     */
176     public void consumeLinearParserEvent(LinearParserEvent linearParserEvent) {
177         int identifier = linearParserEvent.getIdentifier();
178         String value = linearParserEvent.getValue();
179         ModelEvent modelEvent;
180         
181         switch (identifier) {
182             case LinearParserEvent.START_EXPRESSION :
183                 clear();
184                 openingStack.setSize(0);
185                 modelEvent = new ModelEvent(this);
186                 modelEvent.setAction(ModelEvent.CLEAR, null);
187                 fireModelEvent(modelEvent);
188                 break;
189                 
190             case LinearParserEvent.END_EXPRESSION :
191                 // Le modËle de la formule est entiËrement construit.
192                 // On regarde d'abord les Èventuels traitements ? effectuer sur le modËle
193                 // avant la construction des displays.
194                 if (doProcessing && (processor != null)) {
195         		    // Initialisation du processeur si besoin est.
196         		    processor.init();
197                     processor.doProcess();
198                 }
199                 
200                 modelEvent = new ModelEvent(this);
201                 modelEvent.setAction(ModelEvent.CREATE, null);
202                 fireModelEvent(modelEvent);
203                 break;
204                 
205             default :
206                 String strIdentifier = linearParserEvent.getIdentifierAsString();
207                 String className = resourcesManager.getClassName(strIdentifier);
208                 FormulaTreeStructure newFts = null;
209 
210 				/*if( value == null && identifier == linearParserEvent.CLOSE_CURLY && current !=null && current.getFather() instanceof Function2){
211 					current.getFather().removeChild(current);
212 				}
213                 else*/ if (className.equals("null")) {
214 					/*if (identifier == linearParserEvent.SEPARATOR && current != null && current.getFather() instanceof Function2) {
215 						Variable var = new Variable();
216 						var.setValue(value);
217 						var.setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
218 						var.setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
219 						current.getFather().addChild(var);
220 						
221 						current.getFather().removeChild(current);
222 						
223 						
224 						VariableOrNumber template = new VariableOrNumber();
225 						current.getFather().addChild(template);
226 						current = template;
227 
228 					}else */if (identifier == linearParserEvent.SEPARATOR) {
229                         //current = current.goTo(FormulaTreeStructure.SLOT_AS_OPERATOR_PRIORITY);
230 						current = current.goTo(resourcesManager.getAsOperatorPriority("slotPriorities"));
231                         
232                         
233                         // current est maintenant une instance de Slot, on rÈcupËre son pËre pour lui
234                         // ajouter un nouvel ÈlÈment.
235                         //NaryOperator2 currentFather = (NaryOperator2) current.getFather();
236 						FormulaTreeStructure currentFather = (FormulaTreeStructure) current.getFather();
237 						if(currentFather instanceof NaryOperator2)
238 							current = ((NaryOperator2)currentFather).addElement();
239 						else{
240 							current = ((Function2)currentFather).addElement();
241 							Variable var = new Variable();
242 							var.setResourceIdentifier(strIdentifier);
243 							var.setValue(value);
244 							var.setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
245 							var.setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
246 							current = var.insert(current);
247 							current = ((Function2)currentFather).addElement();
248 						}
249                         
250                     }
251                     else {
252                         // Alors c'est forcÈment un linearParserEvent.CLOSE_*
253                         if (!openingStack.isEmpty()) {
254 							current = current.goTo(resourcesManager.getAsOperatorPriority("slotPriorities"));
255 							FormulaTreeStructure currentFather = (FormulaTreeStructure) current.getFather();							
256 							if(currentFather instanceof Function2 && value != null){
257 								current = ((Function2)currentFather).addElement();
258 								Variable var = new Variable();
259 								var.setValue(value);
260 								var.setResourceIdentifier(strIdentifier);								
261 								var.setAsOperatorPriority(resourcesManager.getAsOperatorPriority("constantPriorities"));
262 								var.setAsOperandPriority(resourcesManager.getAsOperandPriority("constantPriorities"));
263 								current = var.insert(current);								
264 							}
265                         	
266                             current = (FormulaTreeStructure) openingStack.pop();
267                             // Et remonte encore d'un cran ? cause des prioritÈs des opÈrateurs
268                             // (surtout en ce qui concerne les parenthËses)
269                             current = (FormulaTreeStructure) current.getFather();
270                         }
271                     }
272                 }
273                 else {
274                     if (className.equals("refine")) {
275                         String[] properties = resourcesManager.getResourceStrings(value);
276                         if (properties.length != 0)
277                             strIdentifier = value; // On a trouvÈ qque chose correspondant ? value
278                         else {
279                             if (identifier == linearParserEvent.RESERVED) 
280                                 // Il n'existe pas de mot rÈservÈ dÈfini dans le modËle correspondant ? value.
281                                 // On considËre donc value comme une variable.
282                                 strIdentifier = "VARIABLE";
283                             else
284                                 // Si ce n'est pas un mot rÈservÈ, c'est une fonction.
285                                 // Il n'existe pas de fonction spÈciale dÈfinie correspondant ? value.
286                                 // On considËre donc value comme une fonction par dÈfaut ayant pour nom value.
287                                 strIdentifier = "defaultFunction";
288                         }
289                     }
290                     
291                     newFts = (FormulaTreeStructure) Factory.getClassInstance(resourcesManager.getClassName(strIdentifier));
292                     newFts.setResourceIdentifier(strIdentifier);
293                     String prioritiesId = resourcesManager.getPrioritiesIdentifier(strIdentifier);
294                     newFts.setAsOperatorPriority(resourcesManager.getAsOperatorPriority(prioritiesId));
295                     newFts.setAsOperandPriority(resourcesManager.getAsOperandPriority(prioritiesId));
296                     
297                     if (value != null)
298                         newFts.setValue(value);
299                         
300                     Integer arity = resourcesManager.getArity(strIdentifier);
301                     if (arity != null)
302                         ((KaryOperator) newFts).setOperatorArity(arity.intValue());
303                     
304                     switch (identifier) {
305                         case LinearParserEvent.FUNCTION :
306 						case LinearParserEvent.FUNCTION2 :
307                      //   case LinearParserEvent.OPEN_PAREN :
308                        // case LinearParserEvent.OPEN_BRACKET :
309                        // case LinearParserEvent.OPEN_CURLY :
310                        // case LinearParserEvent.GROUP_START :
311                             openingStack.push(newFts);
312                     }
313                     
314                     current = newFts.insert(current);
315                 }
316         }
317     }
318     
319     /***
320     * Sets if we had to process the instance before rendering.
321     * @param doProcessing <CODE>true</CODE> if the instance needs a processing.
322     * <CODE>false</CODE> otherwise.
323     */
324     public void setDoProcessing(boolean doProcessing) {
325         this.doProcessing = doProcessing;
326     }
327     
328     /***
329     * Returns <CODE>true</CODE> if the instance needs a processing.
330     * <CODE>false</CODE> otherwise.
331     */
332     public boolean getDoProcessing() {
333         return doProcessing;
334     }
335     
336     /***
337     * Sets the processor of the instance.
338     * @param processor the processor.
339     */
340     public void setProcessor(Processor processor) {
341         this.processor = processor;
342     }
343     
344     /***
345     * Returns the processor of the instance.
346     */
347     public Processor getProcessor() {
348         return processor;
349     }
350     
351     /***
352     * Processes the instance
353     */
354     public void doProcess() {
355         if (doProcessing && (processor != null))
356             processor.doProcess();
357     }
358     
359     public static void main(String args[]) {
360         String exp = "sum(i^n,0,sum(i^n,0,5))t";
361         Formula formula = new Formula();
362         fr.ove.openmath.jome.ctrl.linear.LinearParser linearParser = new fr.ove.openmath.jome.ctrl.linear.LinearParser();
363         linearParser.addLinearParserListener(formula);
364         linearParser.parse(exp);
365         System.out.println("la formule saisie est : \t\t" + exp);
366         System.out.println("la formule construite est : \t\t" + formula.getLinear());
367         
368         try {
369             Thread.sleep(5000);
370         }
371         catch (Exception e) {
372             e.printStackTrace();
373         }
374     }
375 
376 }