View Javadoc

1   /*
2    * Copyright 2007 - 2009 JEuclid, http://jeuclid.sf.net
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* $Id: JEuclidElementFactory.java,v 550ea09de912 2010/08/05 17:05:27 max $ */
18  
19  package net.sourceforge.jeuclid.elements;
20  
21  import java.lang.reflect.Constructor;
22  import java.lang.reflect.Field;
23  import java.lang.reflect.InvocationTargetException;
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  import net.sourceforge.jeuclid.elements.content.semantic.Annotation;
28  import net.sourceforge.jeuclid.elements.content.semantic.Semantics;
29  import net.sourceforge.jeuclid.elements.generic.ForeignElement;
30  import net.sourceforge.jeuclid.elements.generic.MathImpl;
31  import net.sourceforge.jeuclid.elements.presentation.enlivening.Maction;
32  import net.sourceforge.jeuclid.elements.presentation.general.Menclose;
33  import net.sourceforge.jeuclid.elements.presentation.general.Merror;
34  import net.sourceforge.jeuclid.elements.presentation.general.Mfenced;
35  import net.sourceforge.jeuclid.elements.presentation.general.Mfrac;
36  import net.sourceforge.jeuclid.elements.presentation.general.Mpadded;
37  import net.sourceforge.jeuclid.elements.presentation.general.Mphantom;
38  import net.sourceforge.jeuclid.elements.presentation.general.Mroot;
39  import net.sourceforge.jeuclid.elements.presentation.general.Mrow;
40  import net.sourceforge.jeuclid.elements.presentation.general.Msqrt;
41  import net.sourceforge.jeuclid.elements.presentation.general.Mstyle;
42  import net.sourceforge.jeuclid.elements.presentation.script.Mmultiscripts;
43  import net.sourceforge.jeuclid.elements.presentation.script.Mover;
44  import net.sourceforge.jeuclid.elements.presentation.script.Mprescripts;
45  import net.sourceforge.jeuclid.elements.presentation.script.Msub;
46  import net.sourceforge.jeuclid.elements.presentation.script.Msubsup;
47  import net.sourceforge.jeuclid.elements.presentation.script.Msup;
48  import net.sourceforge.jeuclid.elements.presentation.script.Munder;
49  import net.sourceforge.jeuclid.elements.presentation.script.Munderover;
50  import net.sourceforge.jeuclid.elements.presentation.script.None;
51  import net.sourceforge.jeuclid.elements.presentation.table.Maligngroup;
52  import net.sourceforge.jeuclid.elements.presentation.table.Malignmark;
53  import net.sourceforge.jeuclid.elements.presentation.table.Mlabeledtr;
54  import net.sourceforge.jeuclid.elements.presentation.table.Mtable;
55  import net.sourceforge.jeuclid.elements.presentation.table.Mtd;
56  import net.sourceforge.jeuclid.elements.presentation.table.Mtr;
57  import net.sourceforge.jeuclid.elements.presentation.token.Mglyph;
58  import net.sourceforge.jeuclid.elements.presentation.token.Mi;
59  import net.sourceforge.jeuclid.elements.presentation.token.Mn;
60  import net.sourceforge.jeuclid.elements.presentation.token.Mo;
61  import net.sourceforge.jeuclid.elements.presentation.token.Ms;
62  import net.sourceforge.jeuclid.elements.presentation.token.Mspace;
63  import net.sourceforge.jeuclid.elements.presentation.token.Mtext;
64  
65  import org.apache.batik.dom.AbstractDocument;
66  import org.apache.commons.logging.Log;
67  import org.apache.commons.logging.LogFactory;
68  import org.w3c.dom.Document;
69  import org.w3c.dom.Element;
70  
71  /**
72   * Creates MathElements from given element strings.
73   * 
74   * @version $Revision: 550ea09de912 $
75   */
76  public final class JEuclidElementFactory {
77  
78      /**
79       * Logger for this class
80       */
81      private static final Log LOGGER = LogFactory
82              .getLog(JEuclidElementFactory.class);
83  
84      private static final Map<String, Constructor<? extends JEuclidElement>> IMPL_CLASSES = new HashMap<String, Constructor<? extends JEuclidElement>>();;
85  
86      private JEuclidElementFactory() {
87          // Empty on purpose
88      }
89  
90      private static String removeNSPrefix(final String qualifiedName) {
91          final int posSeparator = qualifiedName.indexOf(':');
92          if (posSeparator >= 0) {
93              return qualifiedName.substring(posSeparator + 1);
94          }
95          return qualifiedName;
96      }
97  
98      /**
99       * Retrieve the constructor for an JEuclidElement, if available.
100      * 
101      * @param nsUri
102      *            namespace of the element
103      * @param qualifiedName
104      *            qualified name
105      * @return A constructor to create the element, or null if no such
106      *         constructor is available.
107      */
108     public static Constructor<? extends JEuclidElement> getJEuclidElementConstructor(
109             final String nsUri, final String qualifiedName) {
110         final String localName = JEuclidElementFactory
111                 .removeNSPrefix(qualifiedName);
112         if ((nsUri == null) || (nsUri.length() == 0)
113                 || (AbstractJEuclidElement.URI.equals(nsUri))) {
114             return JEuclidElementFactory.IMPL_CLASSES.get(localName);
115         } else {
116             return null;
117         }
118     }
119 
120     /**
121      * Factory for MathML Elements.
122      * 
123      * @param nsUri
124      *            namespace URI. May be null. May be ignored in the case of
125      *            MathML.
126      * @param qualifiedName
127      *            name of the element with optional namespace prefix.
128      * @param ownerDocument
129      *            Document this element belongs to.
130      * @return A new MathElement for this tag name.
131      */
132     public static Element elementFromName(final String nsUri,
133             final String qualifiedName, final Document ownerDocument) {
134 
135 
136         JEuclidElement element = null;
137 
138             final Constructor<? extends JEuclidElement> con = JEuclidElementFactory.
139             getJEuclidElementConstructor(nsUri, qualifiedName);
140 
141             if (con != null) {
142                 try {
143                     element = con.newInstance(qualifiedName,
144                             ownerDocument);
145                 } catch (final InstantiationException e) {
146                     element = null;
147                 } catch (final IllegalAccessException e) {
148                     element = null;
149                 } catch (final InvocationTargetException e) {
150                     element = null;
151                 }
152             }
153         
154         if (element == null) {
155             element = new ForeignElement(nsUri, qualifiedName,
156                     (AbstractDocument) ownerDocument);
157         }
158         return element;
159     }
160 
161     private static void addClass(final Class<? extends JEuclidElement> c) {
162         try {
163             final Field f = c.getField("ELEMENT");
164             final String tag = (String) f.get(null);
165             JEuclidElementFactory.IMPL_CLASSES.put(tag, c.getConstructor(
166                     String.class, AbstractDocument.class));
167         } catch (final NoSuchFieldException e) {
168             JEuclidElementFactory.LOGGER.warn(c.toString(), e);
169         } catch (final NoSuchMethodException e) {
170             JEuclidElementFactory.LOGGER.warn(c.toString(), e);
171         } catch (final IllegalAccessException e) {
172             JEuclidElementFactory.LOGGER.warn(c.toString(), e);
173         }
174     }
175 
176     // CHECKSTYLE:OFF
177     static {
178         // CHECKSTYLE:ON
179         JEuclidElementFactory.addClass(MathImpl.class);
180         JEuclidElementFactory.addClass(Mfenced.class);
181         JEuclidElementFactory.addClass(Mfrac.class);
182         JEuclidElementFactory.addClass(Menclose.class);
183         JEuclidElementFactory.addClass(Mphantom.class);
184         JEuclidElementFactory.addClass(Msup.class);
185         JEuclidElementFactory.addClass(Msub.class);
186         JEuclidElementFactory.addClass(Mmultiscripts.class);
187         JEuclidElementFactory.addClass(Mprescripts.class);
188         JEuclidElementFactory.addClass(None.class);
189         JEuclidElementFactory.addClass(Msubsup.class);
190         JEuclidElementFactory.addClass(Munder.class);
191         JEuclidElementFactory.addClass(Mover.class);
192         JEuclidElementFactory.addClass(Munderover.class);
193         JEuclidElementFactory.addClass(Mspace.class);
194         JEuclidElementFactory.addClass(Ms.class);
195         JEuclidElementFactory.addClass(Mstyle.class);
196         JEuclidElementFactory.addClass(Msqrt.class);
197         JEuclidElementFactory.addClass(Mroot.class);
198         JEuclidElementFactory.addClass(Mtable.class);
199         JEuclidElementFactory.addClass(Mtr.class);
200         JEuclidElementFactory.addClass(Mlabeledtr.class);
201         JEuclidElementFactory.addClass(Mtd.class);
202         JEuclidElementFactory.addClass(Mo.class);
203         JEuclidElementFactory.addClass(Mi.class);
204         JEuclidElementFactory.addClass(Mn.class);
205         JEuclidElementFactory.addClass(Mtext.class);
206         JEuclidElementFactory.addClass(Mrow.class);
207         JEuclidElementFactory.addClass(Maligngroup.class);
208         JEuclidElementFactory.addClass(Malignmark.class);
209         JEuclidElementFactory.addClass(Semantics.class);
210         JEuclidElementFactory.addClass(Annotation.class);
211         JEuclidElementFactory.addClass(Mpadded.class);
212         JEuclidElementFactory.addClass(Merror.class);
213         JEuclidElementFactory.addClass(Maction.class);
214         JEuclidElementFactory.addClass(Mglyph.class);
215     }
216 
217 }