View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 1999-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *      http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package com.sun.org.apache.xerces.internal.dom;
22  
23  import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
24  import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
25  import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition;
26  import org.w3c.dom.DOMException;
27  
28  /**
29   * AttrNSImpl inherits from AttrImpl and adds namespace support.
30   * <P>
31   * The qualified name is the node name, and we store localName which is also
32   * used in all queries. On the other hand we recompute the prefix when
33   * necessary.
34   *
35   * @xerces.internal
36   *
37   * @author Arnaud  Le Hors, IBM
38   * @author Andy Clark, IBM
39   * @author Ralf Pfeiffer, IBM
40   * @version $Id: AttrNSImpl.java,v 1.7 2010-11-01 04:39:37 joehw Exp $
41   */
42  public class AttrNSImpl
43      extends AttrImpl {
44  
45      //
46      // Constants
47      //
48  
49      /** Serialization version. */
50      static final long serialVersionUID = -781906615369795414L;
51  
52      static final String xmlnsURI = "http://www.w3.org/2000/xmlns/";
53      static final String xmlURI = "http://www.w3.org/XML/1998/namespace";
54  
55      //
56      // Data
57      //
58  
59      /** DOM2: Namespace URI. */
60      protected String namespaceURI;
61  
62      /** DOM2: localName. */
63      protected String localName;
64  
65      /*
66       * Default constructor
67       */
68      public AttrNSImpl(){}
69  
70     /**
71       * DOM2: Constructor for Namespace implementation.
72       */
73      protected AttrNSImpl(CoreDocumentImpl ownerDocument,
74                           String namespaceURI,
75                           String qualifiedName) {
76  
77          super(ownerDocument, qualifiedName);
78          setName(namespaceURI, qualifiedName);
79      }
80  
81      private void setName(String namespaceURI, String qname){
82          CoreDocumentImpl ownerDocument = ownerDocument();
83          String prefix;
84          // DOM Level 3: namespace URI is never empty string.
85          this.namespaceURI = namespaceURI;
86          if (namespaceURI !=null) {
87              this.namespaceURI = (namespaceURI.length() == 0)? null
88                      : namespaceURI;
89  
90          }
91          int colon1 = qname.indexOf(':');
92          int colon2 = qname.lastIndexOf(':');
93          ownerDocument.checkNamespaceWF(qname, colon1, colon2);
94          if (colon1 < 0) {
95              // there is no prefix
96              localName = qname;
97              if (ownerDocument.errorChecking) {
98                  ownerDocument.checkQName(null, localName);
99  
100                 if (qname.equals("xmlns") && (namespaceURI == null
101                     || !namespaceURI.equals(NamespaceContext.XMLNS_URI))
102                     || (namespaceURI!=null && namespaceURI.equals(NamespaceContext.XMLNS_URI)
103                     && !qname.equals("xmlns"))) {
104                     String msg =
105                         DOMMessageFormatter.formatMessage(
106                                 DOMMessageFormatter.DOM_DOMAIN,
107                                 "NAMESPACE_ERR",
108                                 null);
109                     throw new DOMException(DOMException.NAMESPACE_ERR, msg);
110                 }
111             }
112         }
113         else {
114             prefix = qname.substring(0, colon1);
115             localName = qname.substring(colon2+1);
116             ownerDocument.checkQName(prefix, localName);
117             ownerDocument.checkDOMNSErr(prefix, namespaceURI);
118         }
119     }
120 
121     // when local name is known
122     public AttrNSImpl(CoreDocumentImpl ownerDocument,
123                          String namespaceURI,
124                          String qualifiedName,
125                          String localName) {
126         super(ownerDocument, qualifiedName);
127 
128         this.localName = localName;
129         this.namespaceURI = namespaceURI;
130     }
131 
132     // for DeferredAttrImpl
133     protected AttrNSImpl(CoreDocumentImpl ownerDocument,
134                          String value) {
135         super(ownerDocument, value);
136     }
137 
138     // Support for DOM Level 3 renameNode method.
139     // Note: This only deals with part of the pb. It is expected to be
140     // called after the Attr has been detached for one thing.
141     // CoreDocumentImpl does all the work.
142     void rename(String namespaceURI, String qualifiedName) {
143         if (needsSyncData()) {
144             synchronizeData();
145         }
146                 this.name = qualifiedName;
147         setName(namespaceURI, qualifiedName);
148     }
149 
150     /**
151      * NON-DOM: resets this node and sets specified values for the node
152      *
153      * @param ownerDocument
154      * @param namespaceURI
155      * @param qualifiedName
156      * @param localName
157      */
158     public void setValues (CoreDocumentImpl ownerDocument,
159                          String namespaceURI,
160                          String qualifiedName,
161                          String localName){
162 
163         super.textNode = null;
164         super.flags = 0;
165         isSpecified(true);
166         hasStringValue(true);
167         super.setOwnerDocument(ownerDocument);
168         this.localName = localName;
169         this.namespaceURI = namespaceURI;
170         super.name = qualifiedName;
171         super.value = null;
172     }
173 
174     //
175     // DOM2: Namespace methods
176     //
177 
178     /**
179      * Introduced in DOM Level 2. <p>
180      *
181      * The namespace URI of this node, or null if it is unspecified.<p>
182      *
183      * This is not a computed value that is the result of a namespace lookup
184      * based on an examination of the namespace declarations in scope. It is
185      * merely the namespace URI given at creation time.<p>
186      *
187      * For nodes created with a DOM Level 1 method, such as createElement
188      * from the Document interface, this is null.
189      * @since WD-DOM-Level-2-19990923
190      */
191     public String getNamespaceURI()
192     {
193         if (needsSyncData()) {
194             synchronizeData();
195         }
196         // REVIST: This code could/should be done at a lower-level, such that
197         // the namespaceURI is set properly upon creation. However, there still
198         // seems to be some DOM spec interpretation grey-area.
199         return namespaceURI;
200     }
201 
202     /**
203      * Introduced in DOM Level 2. <p>
204      *
205      * The namespace prefix of this node, or null if it is unspecified. <p>
206      *
207      * For nodes created with a DOM Level 1 method, such as createElement
208      * from the Document interface, this is null. <p>
209      *
210      * @since WD-DOM-Level-2-19990923
211      */
212     public String getPrefix()
213     {
214         if (needsSyncData()) {
215             synchronizeData();
216         }
217         int index = name.indexOf(':');
218         return index < 0 ? null : name.substring(0, index);
219     }
220 
221     /**
222      * Introduced in DOM Level 2. <p>
223      *
224      * Note that setting this attribute changes the nodeName attribute, which
225      * holds the qualified name, as well as the tagName and name attributes of
226      * the Element and Attr interfaces, when applicable.<p>
227      *
228      * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified.
229      *
230      * @exception INVALID_CHARACTER_ERR
231      *                   Raised if the specified
232      *                   prefix contains an invalid character.
233      * @exception DOMException
234      * @since WD-DOM-Level-2-19990923
235      */
236     public void setPrefix(String prefix)
237         throws DOMException
238     {
239         if (needsSyncData()) {
240             synchronizeData();
241         }
242         if (ownerDocument().errorChecking) {
243             if (isReadOnly()) {
244                 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
245                 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
246             }
247             if (prefix != null && prefix.length() != 0) {
248 
249                 if (!CoreDocumentImpl.isXMLName(prefix,ownerDocument().isXML11Version())) {
250                     String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
251                     throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
252                 }
253                 if (namespaceURI == null || prefix.indexOf(':') >=0) {
254                     String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
255                     throw new DOMException(DOMException.NAMESPACE_ERR, msg);
256 
257                 }
258                if (prefix.equals("xmlns")) {
259                     if (!namespaceURI.equals(xmlnsURI)){
260                         String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
261                         throw new DOMException(DOMException.NAMESPACE_ERR, msg);
262                     }
263                 } else if (prefix.equals("xml")) {
264                     if (!namespaceURI.equals(xmlURI)) {
265                         String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
266                         throw new DOMException(DOMException.NAMESPACE_ERR, msg);
267                     }
268                 }else if (name.equals("xmlns")) {
269                     String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
270                     throw new DOMException(DOMException.NAMESPACE_ERR, msg);
271                 }
272             }
273         }
274 
275         // update node name with new qualifiedName
276         if (prefix !=null && prefix.length() != 0) {
277             name = prefix + ":" + localName;
278         }
279         else {
280             name = localName;
281         }
282     }
283 
284     /**
285      * Introduced in DOM Level 2. <p>
286      *
287      * Returns the local part of the qualified name of this node.
288      * @since WD-DOM-Level-2-19990923
289      */
290     public String getLocalName()
291     {
292         if (needsSyncData()) {
293             synchronizeData();
294         }
295         return localName;
296     }
297 
298 
299     /**
300      * @see org.w3c.dom.TypeInfo#getTypeName()
301      */
302     public String getTypeName() {
303         if (type !=null){
304             if (type instanceof XSSimpleTypeDecl){
305                 return ((XSSimpleTypeDecl)type).getName();
306             }
307             return (String)type;
308         }
309         return null;
310     }
311 
312     /**
313      * Introduced in DOM Level 3. <p>
314      * Checks if a type is derived from another by restriction. See:
315      * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
316      *
317      * @param ancestorNS
318      *        The namspace of the ancestor type declaration
319      * @param ancestorName
320      *        The name of the ancestor type declaration
321      * @param type
322      *        The reference type definition
323      *
324      * @return boolean True if the type is derived by restriciton for the
325      *         reference type
326      */
327     public boolean isDerivedFrom(String typeNamespaceArg,
328                                  String typeNameArg,
329                                  int derivationMethod) {
330         if (type != null) {
331             if (type instanceof XSSimpleTypeDecl) {
332                 return ((XSSimpleTypeDecl) type).isDOMDerivedFrom(
333                         typeNamespaceArg, typeNameArg, derivationMethod);
334             }
335         }
336         return false;
337     }
338 
339     /**
340      * @see org.w3c.dom.TypeInfo#getTypeNamespace()
341      */
342     public String getTypeNamespace() {
343         if (type !=null) {
344             if (type instanceof XSSimpleTypeDecl){
345                 return ((XSSimpleTypeDecl)type).getNamespace();
346             }
347             return DTD_URI;
348         }
349         return null;
350     }
351 
352 }