001 /*
002 * Copyright 2007 - 2009 JEuclid, http://jeuclid.sf.net
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 /* $Id: JEuclidElementFactory.java,v 550ea09de912 2010/08/05 17:05:27 max $ */
018
019 package net.sourceforge.jeuclid.elements;
020
021 import java.lang.reflect.Constructor;
022 import java.lang.reflect.Field;
023 import java.lang.reflect.InvocationTargetException;
024 import java.util.HashMap;
025 import java.util.Map;
026
027 import net.sourceforge.jeuclid.elements.content.semantic.Annotation;
028 import net.sourceforge.jeuclid.elements.content.semantic.Semantics;
029 import net.sourceforge.jeuclid.elements.generic.ForeignElement;
030 import net.sourceforge.jeuclid.elements.generic.MathImpl;
031 import net.sourceforge.jeuclid.elements.presentation.enlivening.Maction;
032 import net.sourceforge.jeuclid.elements.presentation.general.Menclose;
033 import net.sourceforge.jeuclid.elements.presentation.general.Merror;
034 import net.sourceforge.jeuclid.elements.presentation.general.Mfenced;
035 import net.sourceforge.jeuclid.elements.presentation.general.Mfrac;
036 import net.sourceforge.jeuclid.elements.presentation.general.Mpadded;
037 import net.sourceforge.jeuclid.elements.presentation.general.Mphantom;
038 import net.sourceforge.jeuclid.elements.presentation.general.Mroot;
039 import net.sourceforge.jeuclid.elements.presentation.general.Mrow;
040 import net.sourceforge.jeuclid.elements.presentation.general.Msqrt;
041 import net.sourceforge.jeuclid.elements.presentation.general.Mstyle;
042 import net.sourceforge.jeuclid.elements.presentation.script.Mmultiscripts;
043 import net.sourceforge.jeuclid.elements.presentation.script.Mover;
044 import net.sourceforge.jeuclid.elements.presentation.script.Mprescripts;
045 import net.sourceforge.jeuclid.elements.presentation.script.Msub;
046 import net.sourceforge.jeuclid.elements.presentation.script.Msubsup;
047 import net.sourceforge.jeuclid.elements.presentation.script.Msup;
048 import net.sourceforge.jeuclid.elements.presentation.script.Munder;
049 import net.sourceforge.jeuclid.elements.presentation.script.Munderover;
050 import net.sourceforge.jeuclid.elements.presentation.script.None;
051 import net.sourceforge.jeuclid.elements.presentation.table.Maligngroup;
052 import net.sourceforge.jeuclid.elements.presentation.table.Malignmark;
053 import net.sourceforge.jeuclid.elements.presentation.table.Mlabeledtr;
054 import net.sourceforge.jeuclid.elements.presentation.table.Mtable;
055 import net.sourceforge.jeuclid.elements.presentation.table.Mtd;
056 import net.sourceforge.jeuclid.elements.presentation.table.Mtr;
057 import net.sourceforge.jeuclid.elements.presentation.token.Mglyph;
058 import net.sourceforge.jeuclid.elements.presentation.token.Mi;
059 import net.sourceforge.jeuclid.elements.presentation.token.Mn;
060 import net.sourceforge.jeuclid.elements.presentation.token.Mo;
061 import net.sourceforge.jeuclid.elements.presentation.token.Ms;
062 import net.sourceforge.jeuclid.elements.presentation.token.Mspace;
063 import net.sourceforge.jeuclid.elements.presentation.token.Mtext;
064
065 import org.apache.batik.dom.AbstractDocument;
066 import org.apache.commons.logging.Log;
067 import org.apache.commons.logging.LogFactory;
068 import org.w3c.dom.Document;
069 import org.w3c.dom.Element;
070
071 /**
072 * Creates MathElements from given element strings.
073 *
074 * @version $Revision: 550ea09de912 $
075 */
076 public final class JEuclidElementFactory {
077
078 /**
079 * Logger for this class
080 */
081 private static final Log LOGGER = LogFactory
082 .getLog(JEuclidElementFactory.class);
083
084 private static final Map<String, Constructor<? extends JEuclidElement>> IMPL_CLASSES = new HashMap<String, Constructor<? extends JEuclidElement>>();;
085
086 private JEuclidElementFactory() {
087 // Empty on purpose
088 }
089
090 private static String removeNSPrefix(final String qualifiedName) {
091 final int posSeparator = qualifiedName.indexOf(':');
092 if (posSeparator >= 0) {
093 return qualifiedName.substring(posSeparator + 1);
094 }
095 return qualifiedName;
096 }
097
098 /**
099 * 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 }