001 /* 002 003 ============================================================================ 004 The Apache Software License, Version 1.1 005 ============================================================================ 006 007 Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. 008 009 Redistribution and use in source and binary forms, with or without modifica- 010 tion, are permitted provided that the following conditions are met: 011 012 1. Redistributions of source code must retain the above copyright notice, 013 this list of conditions and the following disclaimer. 014 015 2. Redistributions in binary form must reproduce the above copyright notice, 016 this list of conditions and the following disclaimer in the documentation 017 and/or other materials provided with the distribution. 018 019 3. The end-user documentation included with the redistribution, if any, must 020 include the following acknowledgment: "This product includes software 021 developed by the Apache Software Foundation (http://www.apache.org/)." 022 Alternately, this acknowledgment may appear in the software itself, if 023 and wherever such third-party acknowledgments normally appear. 024 025 4. The names "Batik" and "Apache Software Foundation" must not be 026 used to endorse or promote products derived from this software without 027 prior written permission. For written permission, please contact 028 apache@apache.org. 029 030 5. Products derived from this software may not be called "Apache", nor may 031 "Apache" appear in their name, without prior written permission of the 032 Apache Software Foundation. 033 034 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 035 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 036 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 037 APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 038 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- 039 DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 040 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 041 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 042 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 043 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 044 045 This software consists of voluntary contributions made by many individuals 046 on behalf of the Apache Software Foundation. For more information on the 047 Apache Software Foundation, please see <http://www.apache.org/>. 048 049 */ 050 051 package org.apache.batik.dom.svg; 052 053 import org.apache.batik.css.engine.CSSEngine; 054 import org.apache.batik.dom.AbstractAttr; 055 import org.apache.batik.dom.AbstractDocument; 056 import org.apache.batik.dom.events.NodeEventTarget; 057 import org.apache.batik.util.SoftDoublyIndexedTable; 058 import org.w3c.dom.Attr; 059 import org.w3c.dom.DOMException; 060 import org.w3c.dom.NamedNodeMap; 061 import org.w3c.dom.Node; 062 import org.w3c.dom.events.MutationEvent; 063 064 /** 065 * This class provides a superclass to implement an SVG element, or 066 * an element interoperable with the SVG elements. 067 * 068 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> 069 * @version $Id: AbstractElement.java,v 1.10 2003/08/08 11:38:59 vhardy Exp $ 070 */ 071 public abstract class AbstractElement 072 extends org.apache.batik.dom.AbstractElement 073 implements NodeEventTarget { 074 075 /** 076 * The live attribute values. 077 */ 078 protected transient SoftDoublyIndexedTable liveAttributeValues; 079 080 /** 081 * Creates a new Element object. 082 */ 083 protected AbstractElement() { 084 } 085 086 /** 087 * Creates a new Element object. 088 * @param prefix The namespace prefix. 089 * @param owner The owner document. 090 */ 091 protected AbstractElement(String prefix, AbstractDocument owner) { 092 ownerDocument = owner; 093 setPrefix(prefix); 094 initializeAttributes(); 095 } 096 097 // NodeEventTarget //////////////////////////////////////////////////// 098 099 /** 100 * Implements {@link NodeEventTarget#getParentNodeEventTarget()}. 101 */ 102 public NodeEventTarget getParentNodeEventTarget() { 103 return (NodeEventTarget) 104 CSSEngine.getLogicalParentNode(getParentNode()); 105 } 106 107 // Attributes ///////////////////////////////////////////////////////// 108 109 /** 110 * Returns the live attribute value associated with given 111 * attribute, if any. 112 * @param ns The attribute's namespace. 113 * @param ln The attribute's local name. 114 */ 115 public LiveAttributeValue getLiveAttributeValue(String ns, String ln) { 116 if (liveAttributeValues == null) { 117 return null; 118 } 119 return (LiveAttributeValue)liveAttributeValues.get(ns, ln); 120 } 121 122 /** 123 * Associates a live attribute value to this element. 124 * @param ns The attribute's namespace. 125 * @param ln The attribute's local name. 126 * @param val The live value. 127 */ 128 public void putLiveAttributeValue(String ns, String ln, 129 LiveAttributeValue val) { 130 if (liveAttributeValues == null) { 131 liveAttributeValues = new SoftDoublyIndexedTable(); 132 } 133 liveAttributeValues.put(ns, ln, val); 134 } 135 136 /** 137 * Returns the AttributeInitializer for this element type. 138 * @return null if this element has no attribute with a default value. 139 */ 140 protected AttributeInitializer getAttributeInitializer() { 141 return null; 142 } 143 144 /** 145 * Initializes the attributes of this element to their default value. 146 */ 147 protected void initializeAttributes() { 148 AttributeInitializer ai = getAttributeInitializer(); 149 if (ai != null) { 150 ai.initializeAttributes(this); 151 } 152 } 153 154 /** 155 * Resets an attribute to the default value. 156 * @return true if a default value is known for the given attribute. 157 */ 158 protected boolean resetAttribute(String ns, String prefix, String ln) { 159 AttributeInitializer ai = getAttributeInitializer(); 160 if (ai == null) { 161 return false; 162 } 163 return ai.resetAttribute(this, ns, prefix, ln); 164 } 165 166 /** 167 * Creates the attribute list. 168 */ 169 protected NamedNodeMap createAttributes() { 170 return new ExtendedNamedNodeHashMap(); 171 } 172 173 /** 174 * Sets an unspecified attribute. 175 * @param nsURI The attribute namespace URI. 176 * @param name The attribute's qualified name. 177 * @param value The attribute's default value. 178 */ 179 public void setUnspecifiedAttribute(String nsURI, String name, 180 String value) { 181 if (attributes == null) { 182 attributes = createAttributes(); 183 } 184 ((ExtendedNamedNodeHashMap)attributes). 185 setUnspecifiedAttribute(nsURI, name, value); 186 } 187 188 /** 189 * Called when an attribute has been added. 190 */ 191 protected void attrAdded(Attr node, String newv) { 192 LiveAttributeValue lav = getLiveAttributeValue(node); 193 if (lav != null) { 194 lav.attrAdded(node, newv); 195 } 196 } 197 198 /** 199 * Called when an attribute has been modified. 200 */ 201 protected void attrModified(Attr node, String oldv, String newv) { 202 LiveAttributeValue lav = getLiveAttributeValue(node); 203 if (lav != null) { 204 lav.attrModified(node, oldv, newv); 205 } 206 } 207 208 /** 209 * Called when an attribute has been removed. 210 */ 211 protected void attrRemoved(Attr node, String oldv) { 212 LiveAttributeValue lav = getLiveAttributeValue(node); 213 if (lav != null) { 214 lav.attrRemoved(node, oldv); 215 } 216 } 217 218 /** 219 * Gets Returns the live attribute value associated with given 220 * attribute, if any. 221 */ 222 private LiveAttributeValue getLiveAttributeValue(Attr node) { 223 String ns = node.getNamespaceURI(); 224 return getLiveAttributeValue(ns, (ns == null) 225 ? node.getNodeName() 226 : node.getLocalName()); 227 } 228 229 // Importation //////////////////////////////////////////////////// 230 231 /** 232 * Exports this node to the given document. 233 */ 234 protected Node export(Node n, AbstractDocument d) { 235 super.export(n, d); 236 ((AbstractElement)n).initializeAttributes(); 237 238 super.export(n, d); 239 return n; 240 } 241 242 /** 243 * Deeply exports this node to the given document. 244 */ 245 protected Node deepExport(Node n, AbstractDocument d) { 246 super.export(n, d); 247 ((AbstractElement)n).initializeAttributes(); 248 249 super.deepExport(n, d); 250 return n; 251 } 252 253 /** 254 * An implementation of the {@link NamedNodeMap}. 255 */ 256 protected class ExtendedNamedNodeHashMap extends NamedNodeHashMap { 257 258 /** 259 * Creates a new ExtendedNamedNodeHashMap object. 260 */ 261 public ExtendedNamedNodeHashMap() { 262 } 263 264 /** 265 * Adds an unspecified attribute to the map. 266 * @param nsURI The attribute namespace URI. 267 * @param name The attribute's qualified name. 268 * @param value The attribute's default value. 269 */ 270 public void setUnspecifiedAttribute(String nsURI, String name, 271 String value) { 272 Attr attr = getOwnerDocument().createAttributeNS(nsURI, name); 273 attr.setValue(value); 274 ((AbstractAttr)attr).setSpecified(false); 275 setNamedItemNS(attr); 276 } 277 278 /** 279 * <b>DOM</b>: Implements {@link 280 * NamedNodeMap#removeNamedItemNS(String,String)}. 281 */ 282 public Node removeNamedItemNS(String namespaceURI, String localName) 283 throws DOMException { 284 if (isReadonly()) { 285 throw createDOMException 286 (DOMException.NO_MODIFICATION_ALLOWED_ERR, 287 "readonly.node.map", 288 new Object[] {}); 289 } 290 if (localName == null) { 291 throw createDOMException(DOMException.NOT_FOUND_ERR, 292 "attribute.missing", 293 new Object[] { "" }); 294 } 295 AbstractAttr n = (AbstractAttr)remove(namespaceURI, localName); 296 if (n == null) { 297 throw createDOMException(DOMException.NOT_FOUND_ERR, 298 "attribute.missing", 299 new Object[] { localName }); 300 } 301 n.setOwnerElement(null); 302 String prefix = n.getPrefix(); 303 304 // Reset the attribute to its default value Rate305 if (!resetAttribute(namespaceURI, prefix, localName)) { 306 // Mutation event 307 fireDOMAttrModifiedEvent(n.getNodeName(), n, 308 n.getNodeValue(), "", 309 MutationEvent.REMOVAL); 310 } 311 return n; 312 } 313 } 314 }