KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > io > MathMLParser


1 package JSci.io;
2
3 import java.util.Set JavaDoc;
4 import java.util.HashSet JavaDoc;
5 import JSci.maths.*;
6 import JSci.maths.matrices.*;
7 import JSci.maths.vectors.*;
8 import JSci.maths.fields.*;
9 import org.w3c.dom.*;
10 import org.w3c.dom.mathml.*;
11 import org.xml.sax.SAXNotRecognizedException JavaDoc;
12 import org.xml.sax.SAXNotSupportedException JavaDoc;
13 import org.apache.xerces.parsers.DOMParser;
14
15 /**
16 * The MathMLParser class will parse a MathML document into JSci objects.
17 * @version 0.9
18 * @author Mark Hale
19 */

20 public final class MathMLParser extends DOMParser {
21         /**
22         * Constructs a MathMLParser.
23         */

24         public MathMLParser() {
25                 try {
26                         setProperty("http://apache.org/xml/properties/dom/document-class-name", "JSci.mathml.MathMLDocumentImpl");
27                 } catch(SAXNotRecognizedException JavaDoc e) {
28                         e.printStackTrace();
29                 } catch(SAXNotSupportedException JavaDoc e) {
30                         e.printStackTrace();
31                 }
32         }
33         /**
34         * Translates the document into JSci objects.
35         */

36         public Object JavaDoc[] translateToJSciObjects() {
37                 return translateToJSciObjects(getDocument().getDocumentElement());
38         }
39     public static Object JavaDoc[] translateToJSciObjects(Node root) {
40                 Translator translator=new JSciObjectTranslator();
41                 return translator.translate(root);
42     }
43         /**
44         * Translates the document into JSci code.
45         */

46         public Object JavaDoc[] translateToJSciCode() {
47                 return translateToJSciCode(getDocument().getDocumentElement());
48         }
49     public static Object JavaDoc[] translateToJSciCode(Node root) {
50                 Translator translator=new JSciCodeTranslator();
51                 return translator.translate(root);
52     }
53         /**
54         * Translator.
55         */

56         static abstract class Translator extends Object JavaDoc {
57                 public Translator() {}
58                 public Object JavaDoc[] translate(Node root) {
59                         return parseMATH(root);
60                 }
61                 /**
62                 * Parses the <math> node.
63                 */

64                 private Object JavaDoc[] parseMATH(Node n) {
65                         int len=0;
66                         final NodeList nl=n.getChildNodes();
67                         final Object JavaDoc objList[]=new Object JavaDoc[nl.getLength()];
68                         Object JavaDoc obj;
69                         for(int i=0;i<objList.length;i++) {
70                                 obj=processNode(nl.item(i));
71                                 if(obj!=null) {
72                                         objList[len]=obj;
73                                         len++;
74                                 }
75                         }
76                         final Object JavaDoc parseList[]=new Object JavaDoc[len];
77                         System.arraycopy(objList,0,parseList,0,len);
78                         return parseList;
79                 }
80                 /**
81                 * Processes a node.
82                 */

83                 protected Object JavaDoc processNode(Node n) {
84                         final String JavaDoc nodeName=n.getNodeName();
85                         if(n instanceof MathMLApplyElement || nodeName.equals("reln"))
86                                 return parseAPPLY((MathMLContentContainer)n);
87                         else if(n instanceof MathMLCnElement)
88                                 return parseCN((MathMLCnElement)n);
89                         else if(n instanceof MathMLCiElement)
90                                 return parseCI((MathMLCiElement)n);
91                         else if(n instanceof MathMLVectorElement)
92                                 return parseVECTOR((MathMLVectorElement)n);
93                         else if(n instanceof MathMLMatrixElement)
94                                 return parseMATRIX((MathMLMatrixElement)n);
95                         else if(n instanceof MathMLSetElement)
96                                 return parseSET((MathMLSetElement)n);
97                         else if(n instanceof MathMLStringLitElement)
98                                 return parseMS((MathMLStringLitElement)n);
99                         else if(nodeName.equals("mtext"))
100                                 return parseMTEXT((MathMLPresentationToken)n);
101                         else
102                                 return null;
103                 }
104                 protected abstract Object JavaDoc parseAPPLY(MathMLContentContainer n);
105                 protected abstract Object JavaDoc parseCN(MathMLCnElement n);
106                 protected abstract Object JavaDoc parseCI(MathMLCiElement n);
107                 protected abstract Object JavaDoc parseVECTOR(MathMLVectorElement n);
108                 protected abstract Object JavaDoc parseMATRIX(MathMLMatrixElement n);
109                 protected abstract Object JavaDoc parseSET(MathMLSetElement n);
110                 protected abstract Object JavaDoc parseMS(MathMLStringLitElement n);
111                 protected abstract Object JavaDoc parseMTEXT(MathMLPresentationToken n);
112         }
113         /**
114         * JSci object translator.
115         */

116         static class JSciObjectTranslator extends Translator {
117                 private final int INTEGER=0;
118                 private final int DOUBLE=1;
119                 private final int COMPLEX=2;
120                 private int setID=1;
121
122                 public JSciObjectTranslator() {}
123                 /**
124                 * Parses &lt;apply&gt; tags.
125                 * @return MathMLExpression.
126                 */

127                 protected Object JavaDoc parseAPPLY(MathMLContentContainer n) {
128                         final MathMLExpression expr=new MathMLExpression();
129                         final NodeList nl=n.getChildNodes();
130                         Object JavaDoc obj;
131                         int i;
132                         for(i=0;nl.item(i).getNodeType()==Node.TEXT_NODE;i++)
133                                 ;
134                         expr.setOperation(nl.item(i).getNodeName());
135                         for(;i<nl.getLength();i++) {
136                                 obj=processNode(nl.item(i));
137                                 if(obj!=null)
138                                         expr.addArgument(obj);
139                         }
140                         return expr;
141                 }
142                 /**
143                 * Parses &lt;cn&gt; tags.
144                 * @return Ring.Member.
145                 */

146                 protected Object JavaDoc parseCN(MathMLCnElement n) {
147                         return parseNumber(n);
148                 }
149                 private Ring.Member parseNumber(MathMLCnElement n) {
150                 // support only base 10
151
if(!n.getBase().equals("10"))
152                                 return null;
153                         final String JavaDoc attrType = n.getType();
154                         if(attrType.equals("real")) {
155                                 return new MathDouble(n.getFirstChild().getNodeValue());
156                         } else if(attrType.equals("integer")) {
157                                 return new MathInteger(n.getFirstChild().getNodeValue());
158                         } else if(attrType.equals("rational")) {
159                                 final Node num=n.getArgument(1);
160                                 final Node denom=n.getArgument(2);
161                                 return new MathDouble(num.getNodeValue()).divide(new MathDouble(denom.getNodeValue()));
162                         } else if(attrType.equals("complex-cartesian")) {
163                                 final Node re=n.getArgument(1);
164                                 final Node im=n.getArgument(2);
165                                 return new Complex(
166                                         new Double JavaDoc(re.getNodeValue()).doubleValue(),
167                                         new Double JavaDoc(im.getNodeValue()).doubleValue()
168                                 );
169                         } else if(attrType.equals("complex-polar")) {
170                                 final Node mod=n.getArgument(1);
171                                 final Node arg=n.getArgument(2);
172                                 return Complex.polar(
173                                         new Double JavaDoc(mod.getNodeValue()).doubleValue(),
174                                         new Double JavaDoc(arg.getNodeValue()).doubleValue()
175                                 );
176                         } else if(attrType.equals("constant")) {
177                                 final String JavaDoc value=n.getFirstChild().getNodeValue();
178                                 if(value.equals("&pi;"))
179                                         return RealField.PI;
180                                 else if(value.equals("&ee;") || value.equals("&ExponentialE;"))
181                                         return RealField.E;
182                                 else if(value.equals("&ii;") || value.equals("&ImaginaryI;"))
183                                         return ComplexField.I;
184                                 else if(value.equals("&gamma;"))
185                                         return RealField.GAMMA;
186                                 else if(value.equals("&infty;") || value.equals("&infin;"))
187                                         return RealField.INFINITY;
188                                 else if(value.equals("&NaN;") || value.equals("&NotANumber;"))
189                                         return RealField.NaN;
190                                 else
191                                         return null;
192                         } else
193                                 return null;
194                 }
195                 /**
196                 * Parses &lt;ci&gt; tags.
197                 * @return String.
198                 */

199                 protected Object JavaDoc parseCI(MathMLCiElement n) {
200                         return n.getFirstChild().getNodeValue();
201                 }
202                 /**
203                 * Parses &lt;vector&gt; tags.
204                 * @return MathVector.
205                 */

206                 protected Object JavaDoc parseVECTOR(MathMLVectorElement n) {
207                         int len=0,type=INTEGER;
208                         final Ring.Member num[]=new Ring.Member[n.getNcomponents()];
209                         for(int i=0;i<num.length;i++) {
210                                 MathMLContentElement elem = n.getComponent(i+1);
211                                 if(elem instanceof MathMLCnElement) {
212                                         num[len]=parseNumber((MathMLCnElement)elem);
213                                         if(num[len]!=null) {
214                                         // work out number format needed
215
if(num[len] instanceof MathDouble && type<DOUBLE)
216                                                         type=DOUBLE;
217                                                 else if(num[len] instanceof Complex && type<COMPLEX)
218                                                         type=COMPLEX;
219                                                 len++;
220                                         }
221                                 }
222                         }
223                 // output to JSci objects
224
if(type==INTEGER) {
225                                 final int array[]=new int[len];
226                                 for(int i=0;i<array.length;i++)
227                                         array[i]=((MathInteger)num[i]).value();
228                                 return new IntegerVector(array);
229                         } else if(type==DOUBLE) {
230                                 final double array[]=new double[len];
231                                 for(int i=0;i<array.length;i++) {
232                                         if(num[i] instanceof MathInteger)
233                                                 array[i]=((MathInteger)num[i]).value();
234                                         else
235                                                 array[i]=((MathDouble)num[i]).value();
236                                 }
237                                 return new DoubleVector(array);
238                         } else {
239                                 final Complex array[]=new Complex[len];
240                                 for(int i=0;i<array.length;i++) {
241                                         if(num[i] instanceof MathInteger)
242                                                 array[i]=new Complex(((MathInteger)num[i]).value(),0.0);
243                                         else if(num[i] instanceof MathDouble)
244                                                 array[i]=new Complex(((MathDouble)num[i]).value(),0.0);
245                                         else
246                                                 array[i]=(Complex)num[i];
247                                 }
248                                 return new ComplexVector(array);
249                         }
250                 }
251                 /**
252                 * Parses &lt;matrix&gt; tags.
253                 * @return Matrix.
254                 */

255                 protected Object JavaDoc parseMATRIX(MathMLMatrixElement n) {
256                         int rows=0,cols=Integer.MAX_VALUE;
257                         final Ring.Member num[][]=new Ring.Member[n.getNrows()][];
258                         for(int i=0;i<num.length;i++) {
259                                 num[rows]=parseMatrixRow(n.getRow(i+1));
260                                 if(num[rows].length<cols)
261                                         cols=num[rows].length;
262                                 rows++;
263                         }
264                 // work out number format needed
265
int type=INTEGER;
266                         for(int j,i=0;i<rows;i++) {
267                                 for(j=0;j<cols;j++) {
268                                         if(num[i][j] instanceof MathDouble && type<DOUBLE)
269                                                 type=DOUBLE;
270                                         else if(num[i][j] instanceof Complex && type<COMPLEX)
271                                                 type=COMPLEX;
272                                 }
273                         }
274                 // output to JSci objects
275
if(type==INTEGER) {
276                                 final int array[][]=new int[rows][cols];
277                                 for(int j,i=0;i<rows;i++) {
278                                         for(j=0;j<cols;j++)
279                                                 array[i][j]=((MathInteger)num[i][j]).value();
280                                 }
281                                 if(rows==cols)
282                                         return new IntegerSquareMatrix(array);
283                                 else
284                                         return new IntegerMatrix(array);
285                         } else if(type==DOUBLE) {
286                                 final double array[][]=new double[rows][cols];
287                                 for(int j,i=0;i<rows;i++) {
288                                         for(j=0;j<cols;j++) {
289                                                 if(num[i][j] instanceof MathInteger)
290                                                         array[i][j]=((MathInteger)num[i][j]).value();
291                                                 else
292                                                         array[i][j]=((MathDouble)num[i][j]).value();
293                                         }
294                                 }
295                                 if(rows==cols)
296                                         return new DoubleSquareMatrix(array);
297                                 else
298                                         return new DoubleMatrix(array);
299                         } else {
300                                 final Complex array[][]=new Complex[rows][cols];
301                                 for(int j,i=0;i<rows;i++) {
302                                         for(j=0;j<cols;j++) {
303                                                 if(num[i][j] instanceof MathInteger)
304                                                         array[i][j]=new Complex(((MathInteger)num[i][j]).value(),0.0);
305                                                 else if(num[i][j] instanceof MathDouble)
306                                                         array[i][j]=new Complex(((MathDouble)num[i][j]).value(),0.0);
307                                                 else
308                                                         array[i][j]=(Complex)num[i][j];
309                                         }
310                                 }
311                                 if(rows==cols)
312                                         return new ComplexSquareMatrix(array);
313                                 else
314                                         return new ComplexMatrix(array);
315                         }
316                 }
317                 /**
318                 * Parses &lt;matrixrow&gt; tags.
319                 */

320                 private Ring.Member[] parseMatrixRow(MathMLMatrixrowElement n) {
321                         int len=0;
322                         final Ring.Member num[]=new Ring.Member[n.getNEntries()];
323                         for(int i=0;i<num.length;i++) {
324                                 MathMLContentElement elem = n.getEntry(i+1);
325                                 if(elem instanceof MathMLCnElement) {
326                                         num[len]=parseNumber((MathMLCnElement)elem);
327                                         if(num[len]!=null)
328                                                 len++;
329                                 }
330                         }
331                         final Ring.Member row[]=new Ring.Member[len];
332                         System.arraycopy(num,0,row,0,len);
333                         return row;
334                 }
335                 /**
336                 * Parses &lt;set&gt; tags.
337                 * @return FiniteSet.
338                 */

339                 protected Object JavaDoc parseSET(MathMLSetElement n) {
340                         final NodeList nl = n.getChildNodes();
341                         final Set JavaDoc elements = new HashSet JavaDoc(nl.getLength());
342                         for(int i=0;i<nl.getLength();i++) {
343                                 Node child = nl.item(i);
344                                 if(child instanceof MathMLCiElement)
345                                         elements.add(parseCI((MathMLCiElement)child));
346                         }
347                 // output to JSci objects
348
return new FiniteSet(elements);
349                 }
350                 /**
351                 * Parses &lt;ms&gt; tags.
352                 * @return String.
353                 */

354                 protected Object JavaDoc parseMS(MathMLStringLitElement n) {
355                         return n.getFirstChild().getNodeValue();
356                 }
357                 /**
358                 * Parses &lt;mtext&gt; tags.
359                 * @return String.
360                 */

361                 protected Object JavaDoc parseMTEXT(MathMLPresentationToken n) {
362                         return n.getFirstChild().getNodeValue();
363                 }
364         }
365         /**
366         * JSci code translator.
367         */

368         static class JSciCodeTranslator extends Translator {
369                 public JSciCodeTranslator() {}
370                 /**
371                 * Parses &lt;apply&gt; tags.
372                 * @return String.
373                 */

374                 protected Object JavaDoc parseAPPLY(MathMLContentContainer n) {
375                         final StringBuffer JavaDoc buf=new StringBuffer JavaDoc();
376                         final NodeList nl=n.getChildNodes();
377                         Object JavaDoc obj;
378                         int i;
379                         for(i=0;nl.item(i).getNodeType()==Node.TEXT_NODE;i++)
380                                 ;
381                         String JavaDoc op=nl.item(i).getNodeName();
382                         if(op.equals("plus"))
383                                 op="add";
384                         else if(op.equals("minus"))
385                                 op="subtract";
386                         else if(op.equals("times"))
387                                 op="multiply";
388                         boolean isFirst=true;
389                         for(;i<nl.getLength();i++) {
390                                 obj=processNode(nl.item(i));
391                                 if(obj!=null) {
392                                         if(isFirst) {
393                                                 buf.append(obj);
394                                                 isFirst=false;
395                                         } else
396                                                 buf.append('.').append(op).append('(').append(obj).append(')');
397                                 }
398                         }
399                         return buf;
400                 }
401                 /**
402                 * Parses &lt;cn&gt; tags.
403                 * @return String.
404                 */

405                 protected Object JavaDoc parseCN(MathMLCnElement n) {
406                 // support only base 10
407
if(!n.getBase().equals("10"))
408                                 return null;
409                         final String JavaDoc attrType = n.getType();
410                         if(attrType.equals("real")) {
411                                 return "new MathDouble("+n.getFirstChild().getNodeValue()+')';
412                         } else if(attrType.equals("integer")) {
413                                 return "new MathInteger("+n.getFirstChild().getNodeValue()+')';
414                         } else if(attrType.equals("rational")) {
415                                 final Node num=n.getArgument(1);
416                                 final Node denom=n.getArgument(2);
417                                 return "new MathDouble("+num.getNodeValue()+'/'+denom.getNodeValue()+')';
418                         } else if(attrType.equals("complex-cartesian")) {
419                                 final Node re=n.getArgument(1);
420                                 final Node im=n.getArgument(2);
421                                 return "new Complex("+re.getNodeValue()+','+im.getNodeValue()+')';
422                         } else if(attrType.equals("complex-polar")) {
423                                 final Node mod=n.getArgument(1);
424                                 final Node arg=n.getArgument(2);
425                                 return "Complex.polar("+mod.getNodeValue()+','+arg.getNodeValue()+')';
426                         } else if(attrType.equals("constant")) {
427                                 final String JavaDoc value=n.getFirstChild().getNodeValue();
428                                 if(value.equals("&pi;"))
429                                         return "RealField.PI";
430                                 else if(value.equals("&ee;") || value.equals("&ExponentialE;"))
431                                         return "RealField.E";
432                                 else if(value.equals("&ii;") || value.equals("&ImaginaryI;"))
433                                         return "ComplexField.I";
434                                 else if(value.equals("&gamma;"))
435                                         return "RealField.GAMMA";
436                                 else if(value.equals("&infty;") || value.equals("&infin;"))
437                                         return "RealField.INFINITY";
438                                 else if(value.equals("&NaN;") || value.equals("&NotANumber;"))
439                                         return "RealField.NaN";
440                                 else
441                                         return null;
442                         } else
443                                 return null;
444                 }
445                 /**
446                 * Parses &lt;ci&gt; tags.
447                 * @return String.
448                 */

449                 protected Object JavaDoc parseCI(MathMLCiElement n) {
450                         return n.getFirstChild().getNodeValue();
451                 }
452                 /**
453                 * Parses &lt;vector&gt; tags.
454                 * @return String.
455                 */

456                 protected Object JavaDoc parseVECTOR(MathMLVectorElement n) {
457                         return null;
458                 }
459                 /**
460                 * Parses &lt;matrix&gt; tags.
461                 * @return String.
462                 */

463                 protected Object JavaDoc parseMATRIX(MathMLMatrixElement n) {
464                         return null;
465                 }
466                 /**
467                 * Parses &lt;set&gt; tags.
468                 * @return String.
469                 */

470                 protected Object JavaDoc parseSET(MathMLSetElement n) {
471                         return null;
472                 }
473                 /**
474                 * Parses &lt;ms&gt; tags.
475                 * @return String.
476                 */

477                 protected Object JavaDoc parseMS(MathMLStringLitElement n) {
478                         return n.getFirstChild().getNodeValue();
479                 }
480                 /**
481                 * Parses &lt;mtext&gt; tags.
482                 * @return String.
483                 */

484                 protected Object JavaDoc parseMTEXT(MathMLPresentationToken n) {
485                         return "/*\n"+n.getFirstChild().getNodeValue()+"\n*/";
486                 }
487         }
488 }
489
Popular Tags