| /************************************************************************ |
| * |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER |
| * |
| * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved. |
| * |
| * Use is subject to license terms. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy |
| * of the License at http://www.apache.org/licenses/LICENSE-2.0. You can also |
| * obtain a copy of the License at http://odftoolkit.org/docs/license.txt |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ************************************************************************/ |
| |
| /* |
| * This file is automatically generated. |
| * Don't edit manually. |
| */ |
| package org.odftoolkit.odfdom.pkg; |
| |
| import java.lang.reflect.Constructor; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import org.w3c.dom.DOMException; |
| |
| /** This factory determines what elements are being used in the DOC layer |
| * (ie. the convenient layer). |
| * |
| * The mapping of ODF element to convenient class can be changed from the user |
| * during run time. |
| * |
| * For example, a user might want to create a table always with a certain style or default data and |
| * might want to overwrite the mapping for <code>{odf.element table:table}</code>, that a different |
| * class instead of <code>OdfTable</code> is being used. |
| * |
| */ |
| public class OdfXMLFactory { |
| |
| private static Map<OdfName, Class> mElementTypes = new HashMap<OdfName, Class>(); |
| private static Map<OdfName, Class> mAttributeTypes = new HashMap<OdfName, Class>(); |
| private static Map<String, String> mElementRenames = new HashMap<String, String>(); |
| //a set for the element which need to load class from incubator package. |
| private static Set<String> mIncubatorElements = new HashSet<String>(); |
| private static final String LOCAL_NAME_DELIMITER = "-"; |
| private static final String ELEMENT_NAME_DELIMITER = ":"; |
| private static final String ELEMENT_PACKAGE_NAME = "element"; |
| private static final String ATTRIBUTE_PACKAGE_NAME = "attribute"; |
| |
| static { |
| mElementRenames.put("text:h", "text:heading"); |
| mElementRenames.put("text:p", "text:paragraph"); |
| |
| mIncubatorElements.add("draw:frame"); |
| mIncubatorElements.add("draw:image"); |
| mIncubatorElements.add("number:currency-style"); |
| mIncubatorElements.add("number:date-style"); |
| mIncubatorElements.add("number:percentage-style"); |
| mIncubatorElements.add("number:number-style"); |
| mIncubatorElements.add("number:time-style"); |
| mIncubatorElements.add("office:automatic-styles"); |
| mIncubatorElements.add("office:master-styles"); |
| mIncubatorElements.add("office:styles"); |
| mIncubatorElements.add("style:default-style"); |
| mIncubatorElements.add("style:style"); |
| mIncubatorElements.add("style:page-layout"); |
| mIncubatorElements.add("text:h"); |
| mIncubatorElements.add("text:list"); |
| mIncubatorElements.add("text:list-level-style-bullet"); |
| mIncubatorElements.add("text:list-level-style-image"); |
| mIncubatorElements.add("text:list-level-style-number"); |
| mIncubatorElements.add("text:list-style"); |
| mIncubatorElements.add("text:outline-level-style"); |
| mIncubatorElements.add("text:outline-style"); |
| mIncubatorElements.add("text:p"); |
| mIncubatorElements.add("text:span"); |
| } |
| |
| /** Mapping an ODF element to a new Java DOM element class. |
| * Note: There is a default class for each element being generated from the latest ODF schema |
| */ |
| private static void setOdfElementClass(OdfName odfName, Class className) { |
| mElementTypes.put(odfName, className); |
| } |
| |
| /** Mapping an ODF attribute to a new Java DOM attribute class. |
| * Note: There is a default class for each element being generated from the latest ODF schema. */ |
| private static void setOdfAttributeClass(OdfName odfName, Class className) { |
| mAttributeTypes.put(odfName, className); |
| } |
| |
| /** |
| * @param odfName the name of the ODF attribute the desired DOM class should represent. |
| * @return the Java DOM attribute class to be mapped to a certain ODF attribute. */ |
| private static Class getOdfAttributeClass(OdfName odfName) { |
| return getOdfNodeClass(odfName, ATTRIBUTE_PACKAGE_NAME, mAttributeTypes); |
| } |
| |
| /** |
| * @param odfName the name of the ODF element the desired DOM class should represent. |
| * @return the Java DOM element class to be mapped to a certain ODF element. */ |
| private static Class getOdfElementClass(OdfName odfName) { |
| return getOdfNodeClass(odfName, ELEMENT_PACKAGE_NAME, mElementTypes); |
| } |
| |
| private static Class getOdfNodeClass(OdfName odfName, String nodeType, Map<OdfName, Class> classCache) { |
| Class c = null; |
| String className = ""; |
| c = classCache.get(odfName); |
| if (c == null) { |
| String prefix = odfName.getPrefix(); |
| if (prefix != null && !(nodeType.equals(ATTRIBUTE_PACKAGE_NAME) && prefix.equals("xmlns"))) { |
| String qName = odfName.getQName(); |
| String localName = odfName.getLocalName(); |
| //judge whether the element need to load class from incubator package. |
| if (mIncubatorElements.contains(qName)) { |
| //judge whether the element need to rename before find class name. |
| if (mElementRenames.containsKey(qName)) { |
| String renameName = mElementRenames.get(qName); |
| StringTokenizer stok = new StringTokenizer(renameName, ELEMENT_NAME_DELIMITER); |
| prefix = stok.nextToken(); |
| localName = stok.nextToken(); |
| } |
| className = getOdfIncubatorNodeClassName(prefix, localName); |
| } else if ("manifest".equals(prefix)) { |
| className = getOdfPKGNodeClassName(prefix, localName, nodeType); |
| } else { |
| className = getOdfDOMNodeClassName(prefix, localName, nodeType); |
| } |
| try { |
| c = Class.forName(className); |
| classCache.put(odfName, c); |
| } catch (ClassNotFoundException ex) { |
| // all classes are first tring to load and warning is given later |
| } catch (NoClassDefFoundError dex) { |
| Logger.getLogger(OdfXMLFactory.class.getName()).log(Level.INFO, "NoClassDefFoundError: " + className, dex.getMessage()); |
| } |
| } |
| } |
| return c; |
| } |
| |
| private static String getOdfIncubatorNodeClassName(String prefix, String localName) { |
| boolean contains = false; |
| StringBuilder className = new StringBuilder(); |
| |
| if (localName.indexOf(LOCAL_NAME_DELIMITER) != -1) { |
| StringTokenizer stok = new StringTokenizer(localName, LOCAL_NAME_DELIMITER); |
| while (stok.hasMoreElements()) { |
| String substr = stok.nextToken(); |
| if (substr.equals(prefix)) { |
| contains = true; |
| } |
| className = className.append(toUpperCaseFirstCharacter(substr)); |
| } |
| } else { |
| className = className.append(toUpperCaseFirstCharacter(localName)); |
| } |
| if (!((contains && !localName.endsWith("table")) |
| || (localName.equals(prefix)) |
| || (localName.startsWith(prefix) && prefix.equals("anim")))) { |
| className = className.insert(0, toUpperCaseFirstCharacter(prefix)); |
| } |
| className = className.insert(0, "org.odftoolkit.odfdom.incubator.doc." + prefix + "." + "Odf"); |
| |
| return className.toString(); |
| } |
| |
| private static String getOdfPKGNodeClassName(String prefix, String localName, String nodeType) { |
| StringBuilder className = new StringBuilder("org.odftoolkit.odfdom.pkg." + prefix + "."); |
| if (localName.indexOf(LOCAL_NAME_DELIMITER) != -1) { |
| StringTokenizer stok = new StringTokenizer(localName, LOCAL_NAME_DELIMITER); |
| while (stok.hasMoreElements()) { |
| className = className.append(toUpperCaseFirstCharacter(stok.nextToken())); |
| } |
| } else { |
| className = className.append(toUpperCaseFirstCharacter(localName)); |
| } |
| className.append(toUpperCaseFirstCharacter(nodeType)); |
| return className.toString(); |
| } |
| |
| private static String getOdfDOMNodeClassName(String prefix, String localName, String nodeType) { |
| StringBuilder className = new StringBuilder("org.odftoolkit.odfdom.dom." + nodeType + "." + prefix + "."); |
| className = className.append(toUpperCaseFirstCharacter(prefix)); |
| if (localName.indexOf(LOCAL_NAME_DELIMITER) != -1) { |
| StringTokenizer stok = new StringTokenizer(localName, LOCAL_NAME_DELIMITER); |
| while (stok.hasMoreElements()) { |
| className = className.append(toUpperCaseFirstCharacter(stok.nextToken())); |
| } |
| } else { |
| className = className.append(toUpperCaseFirstCharacter(localName)); |
| } |
| className.append(toUpperCaseFirstCharacter(nodeType)); |
| return className.toString(); |
| } |
| |
| private static String toUpperCaseFirstCharacter(String token) { |
| return token.substring(0, 1).toUpperCase() + token.substring(1); |
| } |
| |
| public static OdfElement newOdfElement(OdfFileDom dom, OdfName name) throws DOMException { |
| OdfElement element = null; |
| |
| // lookup registered element class for qname |
| Class elementClass = getOdfElementClass(name); |
| |
| // if a class was registered create an instance of that class |
| if (elementClass != null) { |
| element = (OdfElement) getNodeFromClass(dom, elementClass); |
| } else { |
| String oldPrefix = name.getPrefix(); |
| if (oldPrefix != null) { |
| // check if the namespace prefix is correct or add potential namespace to DOM |
| OdfName adaptedName = addNamespaceToDom(name, dom); |
| String newPrefix = adaptedName.getPrefix(); |
| // in case the prefix was changed as it existed before |
| if (oldPrefix != null && !oldPrefix.equals(newPrefix) |
| // "_1" is the suffix added by OdfFileDom to an existing Namespace |
| && newPrefix.indexOf("__") == -1) { |
| // look up again if there is a class registered for this prefix |
| element = newOdfElement(dom, adaptedName); |
| } else { |
| element = (OdfElement) new OdfAlienElement(dom, adaptedName); |
| Logger.getLogger(OdfXMLFactory.class.getName()).log(Level.FINE, "None-ODF element created for {0}", adaptedName.getQName()); |
| } |
| } else { |
| element = (OdfElement) new OdfAlienElement(dom, name); |
| Logger.getLogger(OdfXMLFactory.class.getName()).log(Level.FINE, "None-ODF element created for {0}", name.getQName()); |
| } |
| } |
| return element; |
| } |
| |
| public static OdfAttribute newOdfAttribute(OdfFileDom dom, OdfName name) throws DOMException { |
| OdfAttribute attr = null; |
| |
| // lookup registered attribute class for qname |
| Class attributeClass = getOdfAttributeClass(name); |
| |
| // if a class was registered create an instance of that class |
| if (attributeClass != null) { |
| attr = (OdfAttribute) getNodeFromClass(dom, attributeClass); |
| } else { // in case it is not a default ODF |
| // add a namespace unless it is a xmlns attribute (no attr value to set the uri) |
| String prefix = name.getPrefix(); |
| if (prefix != null && !prefix.equals("xmlns")) { |
| // check if the namespace prefix is correct or add potential namespace to DOM |
| OdfName adaptedName = addNamespaceToDom(name, dom); |
| String newPrefix = adaptedName.getPrefix(); |
| // in case the prefix was changed as it existed before |
| if (!prefix.equals(newPrefix) && newPrefix.indexOf("__") == -1) { |
| // look up again if there is a class registered for this prefix |
| attr = newOdfAttribute(dom, adaptedName); |
| } else { |
| attr = (OdfAttribute) new OdfAlienAttribute(dom, name); |
| Logger.getLogger(OdfXMLFactory.class.getName()).log(Level.FINE, "None-ODF attribute created for {0}", adaptedName.getQName()); |
| } |
| } else { |
| // create an alien attribute for namespace attribute "xmlns:*" |
| attr = (OdfAttribute) new OdfAlienAttribute(dom, name); |
| } |
| |
| } |
| return attr; |
| } |
| |
| private static OdfName addNamespaceToDom(OdfName name, OdfFileDom dom) { |
| OdfNamespace newNS = dom.setNamespace(name.getPrefix(), name.getUri()); |
| return OdfName.newName(newNS, name.getLocalName()); |
| } |
| |
| /** |
| * @param dom the XML DOM file where the node should be created on. |
| * @param nodeClass being an XMLNode the Java class of the instance to be created. |
| * @return an object instance of the XML node class being provided (usally an attribute or element). */ |
| static Object getNodeFromClass(OdfFileDom dom, Class nodeClass) { |
| Object o = null; |
| try { |
| Constructor ctor = nodeClass.getConstructor(new Class[]{OdfFileDom.class}); |
| o = ctor.newInstance(new Object[]{dom}); |
| } catch (Exception cause) { |
| // an exception at this point is a bug. Throw an Error |
| throw new Error("ODF DOM error in attribute factory", cause); |
| } |
| return o; |
| } |
| } |