All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.odftoolkit.odfdom.pkg.OdfXMLFactory Maven / Gradle / Ivy

Go to download

ODFDOM is an OpenDocument Format (ODF) framework. Its purpose is to provide an easy common way to create, access and manipulate ODF files, without requiring detailed knowledge of the ODF specification. It is designed to provide the ODF developer community with an easy lightwork programming API portable to any object-oriented language. The current reference implementation is written in Java.

There is a newer version: 0.8.11-incubating
Show newest version
/************************************************************************
 *
 * 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 {odf.element table:table}, that a different
 *  class instead of OdfTable is being used.
 * 
 */
public class OdfXMLFactory {

	private static Map mElementTypes = new HashMap();
	private static Map mAttributeTypes = new HashMap();
	private static Map mElementRenames = new HashMap();
	//a set for the element which need to load class from incubator package.
	private static Set mIncubatorElements = new HashSet();
	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 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;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy