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

org.odftoolkit.odfdom.dom.element.OdfStyleBase 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: 1.0.0-BETA1
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. * *

********************************************************************** */ package org.odftoolkit.odfdom.dom.element; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.odftoolkit.odfdom.dom.OdfDocumentNamespace; import org.odftoolkit.odfdom.dom.element.style.StyleChartPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleDrawingPagePropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleGraphicPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleHeaderFooterPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleListLevelPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StylePageLayoutPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleParagraphPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleRubyPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleSectionPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleTableCellPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleTableColumnPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleTablePropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleTableRowPropertiesElement; import org.odftoolkit.odfdom.dom.element.style.StyleTextPropertiesElement; import org.odftoolkit.odfdom.dom.style.OdfStyleFamily; import org.odftoolkit.odfdom.dom.style.OdfStylePropertySet; import org.odftoolkit.odfdom.dom.style.props.OdfStylePropertiesSet; import org.odftoolkit.odfdom.dom.style.props.OdfStyleProperty; import org.odftoolkit.odfdom.pkg.OdfAttribute; import org.odftoolkit.odfdom.pkg.OdfContainerElementBase; import org.odftoolkit.odfdom.pkg.OdfElement; import org.odftoolkit.odfdom.pkg.OdfFileDom; import org.odftoolkit.odfdom.pkg.OdfName; import org.w3c.dom.Attr; import org.w3c.dom.DOMException; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * A placeholder for multiple style incarnation, for instance from either the * automatic or the template styles parent, e.g. StyleStyleElement is inheriting from it */ public abstract class OdfStyleBase extends OdfContainerElementBase implements OdfStylePropertySet, Comparable { /** */ private static final long serialVersionUID = 8271282184913774000L; private HashMap mPropertySetElementMap; private ArrayList mStyleUser; static HashMap mStylePropertiesElementToSetMap; static { mStylePropertiesElementToSetMap = new HashMap(); mStylePropertiesElementToSetMap.put( StyleChartPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.ChartProperties); mStylePropertiesElementToSetMap.put( StyleDrawingPagePropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.DrawingPageProperties); mStylePropertiesElementToSetMap.put( StyleGraphicPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.GraphicProperties); mStylePropertiesElementToSetMap.put( StyleHeaderFooterPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.HeaderFooterProperties); mStylePropertiesElementToSetMap.put( StyleListLevelPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.ListLevelProperties); mStylePropertiesElementToSetMap.put( StylePageLayoutPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.PageLayoutProperties); mStylePropertiesElementToSetMap.put( StyleParagraphPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.ParagraphProperties); mStylePropertiesElementToSetMap.put( StyleRubyPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.RubyProperties); mStylePropertiesElementToSetMap.put( StyleSectionPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.SectionProperties); mStylePropertiesElementToSetMap.put( StyleTableCellPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableCellProperties); mStylePropertiesElementToSetMap.put( StyleTableColumnPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableColumnProperties); mStylePropertiesElementToSetMap.put( StyleTablePropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableProperties); mStylePropertiesElementToSetMap.put( StyleTableRowPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableRowProperties); mStylePropertiesElementToSetMap.put( StyleTextPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TextProperties); } /** Creates a new instance of OdfElement */ public OdfStyleBase(OdfFileDom ownerDocument, String namespaceURI, String qualifiedName) throws DOMException { super(ownerDocument, namespaceURI, qualifiedName); } /** Creates a new instance of OdfElement */ public OdfStyleBase(OdfFileDom ownerDocument, OdfName aName) throws DOMException { super(ownerDocument, aName.getUri(), aName.getQName()); } public void addStyleUser(OdfStylableElement user) { if (mStyleUser == null) { mStyleUser = new ArrayList(); } mStyleUser.add(user); } /** * get a map containing all properties of this style and their values. * * @return map of properties. @Deprecated Broken by design as the same OdfStlyeProperty can occur * multiple times and would be overwritten (e.g. background color exist 3times in cells). */ public Map getStyleProperties() { TreeMap result = new TreeMap(); OdfStyleFamily family = getFamily(); if (family != null) { for (OdfStyleProperty property : family.getProperties()) { if (hasProperty(property)) { result.put(property, getProperty(property)); } } } return result; } /** * get a map containing all properties of this style and their values. The map will also include * any properties set by parent styles * * @return a map of all the properties. @Deprecated Broken by design as the same OdfStlyeProperty * can occur multiple times and would be overwritten (e.g. background color exist 3times in * cells). */ public Map getStylePropertiesDeep() { TreeMap result = new TreeMap(); OdfStyleBase style = this; while (style != null) { OdfStyleFamily family = style.getFamily(); if (family != null) { for (OdfStyleProperty property : family.getProperties()) { if (!result.containsKey(property) && style.hasProperty(property)) { result.put(property, style.getProperty(property)); } } } style = style.getParentStyle(); } return result; } public void removeStyleUser(OdfStylableElement user) { if (mStyleUser != null) { mStyleUser.remove(user); } } public int getStyleUserCount() { return mStyleUser == null ? 0 : mStyleUser.size(); } /** * Returns an iterator for all OdfStylableElement elements using this style. * * @return an iterator for all OdfStylableElement elements using this style */ public Iterable getStyleUsers() { if (mStyleUser != null) { return mStyleUser; } return new ArrayList(); } public String getFamilyName() { return getFamily().getName(); } /** * @param set * @return the style:*-properties element for the given set. Returns null if such element does not * exist yet. */ public OdfStylePropertiesBase getPropertiesElement(OdfStylePropertiesSet set) { if (mPropertySetElementMap != null) { return mPropertySetElementMap.get(set); } return null; } /** * @param set * @return the style:*-properties element for the given set. If such element does not yet exist, * it is created. */ public OdfStylePropertiesBase getOrCreatePropertiesElement(OdfStylePropertiesSet set) { OdfStylePropertiesBase properties = null; if (mPropertySetElementMap != null) { properties = mPropertySetElementMap.get(set); } if (properties == null) { for (Entry entry : mStylePropertiesElementToSetMap.entrySet()) { if (entry.getValue().equals(set)) { properties = (OdfStylePropertiesBase) ((OdfFileDom) this.ownerDocument).createElementNS(entry.getKey()); if (getFirstChild() == null) { appendChild(properties); } else { // make sure the properties elements are in the correct order Node beforeNode = null; if (set.equals(OdfStylePropertiesSet.GraphicProperties)) { beforeNode = OdfElement.findFirstChildNode(StyleParagraphPropertiesElement.class, this); if (beforeNode == null) { beforeNode = OdfElement.findFirstChildNode(StyleTextPropertiesElement.class, this); } } else if (set.equals(OdfStylePropertiesSet.ParagraphProperties)) { beforeNode = OdfElement.findFirstChildNode(StyleTextPropertiesElement.class, this); } else if (!set.equals(OdfStylePropertiesSet.TextProperties)) { beforeNode = getFirstChild(); } if (beforeNode == null) { beforeNode = getFirstChild(); // find first non properties node while (beforeNode != null) { if (beforeNode.getNodeType() == Node.ELEMENT_NODE) { if (!(beforeNode instanceof OdfStylePropertiesBase)) { break; } } beforeNode = beforeNode.getNextSibling(); } } insertBefore(properties, beforeNode); } break; } } } return properties; } /** @return a property value. */ public String getProperty(OdfStyleProperty prop) { String value = null; OdfStylePropertiesBase properties = getPropertiesElement(prop.getPropertySet()); if (properties != null) { if (properties.hasAttributeNS(prop.getName().getUri(), prop.getName().getLocalName())) { return properties.getOdfAttribute(prop.getName()).getValue(); } } OdfStyleBase parent = getParentStyle(); if (parent != null) { return parent.getProperty(prop); } return value; } public boolean hasProperty(OdfStyleProperty prop) { if (mPropertySetElementMap != null) { OdfStylePropertiesBase properties = mPropertySetElementMap.get(prop.getPropertySet()); if (properties != null) { return properties.hasAttributeNS(prop.getName().getUri(), prop.getName().getLocalName()); } } return false; } @Override protected void onOdfNodeInserted(OdfElement node, Node refChild) { if (node instanceof OdfStylePropertiesBase) { OdfStylePropertiesSet set = mStylePropertiesElementToSetMap.get(node.getOdfName()); if (set != null) { if (mPropertySetElementMap == null) { mPropertySetElementMap = new HashMap(); } mPropertySetElementMap.put(set, (OdfStylePropertiesBase) node); } } } @Override protected void onOdfNodeRemoved(OdfElement node) { if (mPropertySetElementMap != null) { if (node instanceof OdfStylePropertiesBase) { OdfStylePropertiesSet set = mStylePropertiesElementToSetMap.get(node.getOdfName()); if (set != null) { mPropertySetElementMap.remove(set); } } } } public Map getProperties(Set properties) { HashMap map = new HashMap(); for (OdfStyleProperty property : properties) { map.put(property, getProperty(property)); } return map; } public Set getStrictProperties() { return getFamily().getProperties(); } public void removeProperty(OdfStyleProperty property) { if (mPropertySetElementMap != null) { OdfStylePropertiesBase properties = mPropertySetElementMap.get(property.getPropertySet()); if (properties != null) { properties.removeAttributeNS( property.getName().getUri(), property.getName().getLocalName()); } } } public void setProperties(Map properties) { for (Map.Entry entry : properties.entrySet()) { setProperty(entry.getKey(), entry.getValue()); } } public void setProperty(OdfStyleProperty property, String value) { OdfStylePropertiesBase properties = getOrCreatePropertiesElement(property.getPropertySet()); if (properties != null) { OdfAttribute propertyAttr = ((OdfFileDom) this.ownerDocument).createAttributeNS(property.getName()); properties.setOdfAttribute(propertyAttr); propertyAttr.setValue(value); } } /** * compare one style to another one. This implements a total order on style objects. * * @param obj - the reference object with which to compare2. * @return 0 if this object is the same as the obj argument; -1 if this object is less than the * obj argument; 1 if this object is greater than the obj argument */ public int compareTo(Object obj) { if (this == obj) { return 0; } if (!(obj instanceof OdfStyleBase)) { if (obj == null) { throw new ClassCastException("The object to be compared is null!"); } else { throw new ClassCastException("The object to be compared is not a style!"); } } OdfStyleBase compare = (OdfStyleBase) obj; int c = compareNodes(this, compare); return c; } // Currently this function does not consider the order of child nodes, e.g., // // // // // // // // // // // and // // // // // // // // // // // are regarded non-equal // private static int compareNodes(Node compare1, Node compare2) { // Only styles can be equal, that are from the same element // (e.g. style:style and text:list-level-style-bullet are never equal) int c = 0; // if the local name is unequal (e.g. style vs. list-level-style-bullet) // the String compareTo will give me the order if ((c = compare1.getLocalName().compareTo(compare2.getLocalName())) != 0) { return c; } // if the namespaceURI is unequal (e.g. style vs. text) // the String compareTo will give me the order if ((c = compare1.getNamespaceURI().compareTo(compare2.getNamespaceURI())) != 0) { return c; } // compare number of attributes int attr_count1 = compare1.getAttributes() != null ? compare1.getAttributes().getLength() : 0; int attr_count2 = compare2.getAttributes() != null ? compare2.getAttributes().getLength() : 0; // attributes with default values do not exist in the ODFDOM XML model if (attr_count1 != attr_count2) { return attr_count1 < attr_count2 ? -1 : 1; } // sort attributes by namespace:localname, omit style name SortedMap attr1 = getSortedAttributes(compare1); SortedMap attr2 = getSortedAttributes(compare2); // compare2 attribute names and values Iterator keySet1Iter = attr1.keySet().iterator(); Iterator keySet2Iter = attr2.keySet().iterator(); while (keySet1Iter.hasNext()) { String key1 = keySet1Iter.next(); String key2 = keySet2Iter.next(); if ((c = key1.compareTo(key2)) != 0) { return c; } String attrValue1 = attr1.get(key1); String attrValue2 = attr2.get(key1); if ((c = attrValue1.compareTo(attrValue2)) != 0) { return c; } } // now number of child elements ArrayList nodes1 = getNonEmptyChildNodes(compare1); ArrayList nodes2 = getNonEmptyChildNodes(compare2); if (nodes1.size() != nodes2.size()) { return nodes1.size() < nodes2.size() ? -1 : 1; } // now compare child elements Iterator iter1 = nodes1.iterator(); Iterator iter2 = nodes2.iterator(); while (iter1.hasNext()) { Node child1 = iter1.next(); Node child2 = iter2.next(); if ((c = compareNodes(child1, child2)) != 0) { return c; } } return 0; } // helper function for compareTo. // sorts attributes by namespace:localname private static SortedMap getSortedAttributes(Node node) { SortedMap ret = new TreeMap(); NamedNodeMap attrs = node.getAttributes(); for (int i = 0; i < attrs.getLength(); i++) { Node cur = attrs.item(i); String namespace = cur.getNamespaceURI(); String local = cur.getLocalName(); // styles can be still the same, even if they have different names if (local.equals("name") && namespace.equals(OdfDocumentNamespace.STYLE.getUri())) { continue; } ret.put(namespace + ":" + local, ((Attr) cur).getValue()); } return ret; } // helper function for compareTo. // all except "empty" text nodes will be returned private static ArrayList getNonEmptyChildNodes(Node node) { ArrayList ret = new ArrayList(); NodeList childs = node.getChildNodes(); for (int i = 0; i < childs.getLength(); i++) { Node cur = childs.item(i); if (cur.getNodeType() == Node.TEXT_NODE) { if (cur.getNodeValue().trim().length() == 0) { continue; // skip whitespace text nodes } } ret.add(cur); } return ret; } /** * Indicates if some other object is equal to this one. The attribute style:name is ignored during * compare2. * * @param obj - the reference object with which to compare2. * @return true if this object is the same as the obj argument; false otherwise. */ @Override public boolean equals(Object obj) { return obj != null ? compareTo(obj) == 0 : false; } @Override public int hashCode() { return 59 * 7 + (this.mPropertySetElementMap != null ? this.mPropertySetElementMap.hashCode() : 0); } /** @return the style family of the style or null if none existent */ public OdfStyleFamily getFamily() { return null; } /** @return the style parent of the style or null if none existent */ public OdfStyleBase getParentStyle() { return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy