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 }