/************************************************************************ | |
* | |
* 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, true); | |
} | |
/** | |
* @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, false); | |
} | |
private static Class getOdfNodeClass(OdfName odfName, String nodeType, Map<OdfName, Class> classCache, boolean isAttribute) { | |
Class c = null; | |
String className = ""; | |
c = classCache.get(odfName); | |
if (c == null) { | |
// Ignore looking for XML namespace attributes or ODF elements without prefix, | |
// as there are no typed ODF classes | |
// (NOTE: For any ODF node from the schema the ODF prefix would ALWAYS exist | |
// as there is a prefix normalization during the previous loading) | |
String prefix = odfName.getPrefix(); | |
if (prefix != null && !(isAttribute && 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) && !isAttribute) { | |
//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; | |
} | |
} |