001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.dom;
019:
020: import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
021: import org.apache.xerces.xni.NamespaceContext;
022: import org.apache.xerces.xs.XSSimpleTypeDefinition;
023: import org.w3c.dom.DOMException;
024:
025: /**
026: * AttrNSImpl inherits from AttrImpl and adds namespace support.
027: * <P>
028: * The qualified name is the node name, and we store localName which is also
029: * used in all queries. On the other hand we recompute the prefix when
030: * necessary.
031: *
032: * @xerces.internal
033: *
034: * @author Arnaud Le Hors, IBM
035: * @author Andy Clark, IBM
036: * @author Ralf Pfeiffer, IBM
037: * @version $Id: AttrNSImpl.java 449328 2006-09-23 22:58:23Z mrglavas $
038: */
039: public class AttrNSImpl extends AttrImpl {
040:
041: //
042: // Constants
043: //
044:
045: /** Serialization version. */
046: static final long serialVersionUID = -781906615369795414L;
047:
048: static final String xmlnsURI = "http://www.w3.org/2000/xmlns/";
049: static final String xmlURI = "http://www.w3.org/XML/1998/namespace";
050:
051: //
052: // Data
053: //
054:
055: /** DOM2: Namespace URI. */
056: protected String namespaceURI;
057:
058: /** DOM2: localName. */
059: protected String localName;
060:
061: /*
062: * Default constructor
063: */
064: public AttrNSImpl() {
065: }
066:
067: /**
068: * DOM2: Constructor for Namespace implementation.
069: */
070: protected AttrNSImpl(CoreDocumentImpl ownerDocument,
071: String namespaceURI, String qualifiedName) {
072:
073: super (ownerDocument, qualifiedName);
074: setName(namespaceURI, qualifiedName);
075: }
076:
077: private void setName(String namespaceURI, String qname) {
078: CoreDocumentImpl ownerDocument = ownerDocument();
079: String prefix;
080: // DOM Level 3: namespace URI is never empty string.
081: this .namespaceURI = namespaceURI;
082: if (namespaceURI != null) {
083: this .namespaceURI = (namespaceURI.length() == 0) ? null
084: : namespaceURI;
085:
086: }
087: int colon1 = qname.indexOf(':');
088: int colon2 = qname.lastIndexOf(':');
089: ownerDocument.checkNamespaceWF(qname, colon1, colon2);
090: if (colon1 < 0) {
091: // there is no prefix
092: localName = qname;
093: if (ownerDocument.errorChecking) {
094: ownerDocument.checkQName(null, localName);
095:
096: if (qname.equals("xmlns")
097: && (namespaceURI == null || !namespaceURI
098: .equals(NamespaceContext.XMLNS_URI))
099: || (namespaceURI != null
100: && namespaceURI
101: .equals(NamespaceContext.XMLNS_URI) && !qname
102: .equals("xmlns"))) {
103: String msg = DOMMessageFormatter.formatMessage(
104: DOMMessageFormatter.DOM_DOMAIN,
105: "NAMESPACE_ERR", null);
106: throw new DOMException(DOMException.NAMESPACE_ERR,
107: msg);
108: }
109: }
110: } else {
111: prefix = qname.substring(0, colon1);
112: localName = qname.substring(colon2 + 1);
113: ownerDocument.checkQName(prefix, localName);
114: ownerDocument.checkDOMNSErr(prefix, namespaceURI);
115: }
116: }
117:
118: // when local name is known
119: public AttrNSImpl(CoreDocumentImpl ownerDocument,
120: String namespaceURI, String qualifiedName, String localName) {
121: super (ownerDocument, qualifiedName);
122:
123: this .localName = localName;
124: this .namespaceURI = namespaceURI;
125: }
126:
127: // for DeferredAttrImpl
128: protected AttrNSImpl(CoreDocumentImpl ownerDocument, String value) {
129: super (ownerDocument, value);
130: }
131:
132: // Support for DOM Level 3 renameNode method.
133: // Note: This only deals with part of the pb. It is expected to be
134: // called after the Attr has been detached for one thing.
135: // CoreDocumentImpl does all the work.
136: void rename(String namespaceURI, String qualifiedName) {
137: if (needsSyncData()) {
138: synchronizeData();
139: }
140: this .name = qualifiedName;
141: setName(namespaceURI, qualifiedName);
142: }
143:
144: /**
145: * NON-DOM: resets this node and sets specified values for the node
146: *
147: * @param ownerDocument
148: * @param namespaceURI
149: * @param qualifiedName
150: * @param localName
151: */
152: public void setValues(CoreDocumentImpl ownerDocument,
153: String namespaceURI, String qualifiedName, String localName) {
154:
155: AttrImpl.textNode = null;
156: super .flags = 0;
157: isSpecified(true);
158: hasStringValue(true);
159: super .setOwnerDocument(ownerDocument);
160: this .localName = localName;
161: this .namespaceURI = namespaceURI;
162: super .name = qualifiedName;
163: super .value = null;
164: }
165:
166: //
167: // DOM2: Namespace methods
168: //
169:
170: /**
171: * Introduced in DOM Level 2. <p>
172: *
173: * The namespace URI of this node, or null if it is unspecified.<p>
174: *
175: * This is not a computed value that is the result of a namespace lookup
176: * based on an examination of the namespace declarations in scope. It is
177: * merely the namespace URI given at creation time.<p>
178: *
179: * For nodes created with a DOM Level 1 method, such as createElement
180: * from the Document interface, this is null.
181: * @since WD-DOM-Level-2-19990923
182: */
183: public String getNamespaceURI() {
184: if (needsSyncData()) {
185: synchronizeData();
186: }
187: // REVIST: This code could/should be done at a lower-level, such that
188: // the namespaceURI is set properly upon creation. However, there still
189: // seems to be some DOM spec interpretation grey-area.
190: return namespaceURI;
191: }
192:
193: /**
194: * Introduced in DOM Level 2. <p>
195: *
196: * The namespace prefix of this node, or null if it is unspecified. <p>
197: *
198: * For nodes created with a DOM Level 1 method, such as createElement
199: * from the Document interface, this is null. <p>
200: *
201: * @since WD-DOM-Level-2-19990923
202: */
203: public String getPrefix() {
204: if (needsSyncData()) {
205: synchronizeData();
206: }
207: int index = name.indexOf(':');
208: return index < 0 ? null : name.substring(0, index);
209: }
210:
211: /**
212: * Introduced in DOM Level 2. <p>
213: *
214: * Note that setting this attribute changes the nodeName attribute, which
215: * holds the qualified name, as well as the tagName and name attributes of
216: * the Element and Attr interfaces, when applicable.<p>
217: *
218: * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified.
219: *
220: * @exception INVALID_CHARACTER_ERR
221: * Raised if the specified
222: * prefix contains an invalid character.
223: * @exception DOMException
224: * @since WD-DOM-Level-2-19990923
225: */
226: public void setPrefix(String prefix) throws DOMException {
227: if (needsSyncData()) {
228: synchronizeData();
229: }
230: if (ownerDocument().errorChecking) {
231: if (isReadOnly()) {
232: String msg = DOMMessageFormatter.formatMessage(
233: DOMMessageFormatter.DOM_DOMAIN,
234: "NO_MODIFICATION_ALLOWED_ERR", null);
235: throw new DOMException(
236: DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
237: }
238: if (prefix != null && prefix.length() != 0) {
239:
240: if (!CoreDocumentImpl.isXMLName(prefix, ownerDocument()
241: .isXML11Version())) {
242: String msg = DOMMessageFormatter.formatMessage(
243: DOMMessageFormatter.DOM_DOMAIN,
244: "INVALID_CHARACTER_ERR", null);
245: throw new DOMException(
246: DOMException.INVALID_CHARACTER_ERR, msg);
247: }
248: if (namespaceURI == null || prefix.indexOf(':') >= 0) {
249: String msg = DOMMessageFormatter.formatMessage(
250: DOMMessageFormatter.DOM_DOMAIN,
251: "NAMESPACE_ERR", null);
252: throw new DOMException(DOMException.NAMESPACE_ERR,
253: msg);
254:
255: }
256: if (prefix.equals("xmlns")) {
257: if (!namespaceURI.equals(xmlnsURI)) {
258: String msg = DOMMessageFormatter.formatMessage(
259: DOMMessageFormatter.DOM_DOMAIN,
260: "NAMESPACE_ERR", null);
261: throw new DOMException(
262: DOMException.NAMESPACE_ERR, msg);
263: }
264: } else if (prefix.equals("xml")) {
265: if (!namespaceURI.equals(xmlURI)) {
266: String msg = DOMMessageFormatter.formatMessage(
267: DOMMessageFormatter.DOM_DOMAIN,
268: "NAMESPACE_ERR", null);
269: throw new DOMException(
270: DOMException.NAMESPACE_ERR, msg);
271: }
272: } else if (name.equals("xmlns")) {
273: String msg = DOMMessageFormatter.formatMessage(
274: DOMMessageFormatter.DOM_DOMAIN,
275: "NAMESPACE_ERR", null);
276: throw new DOMException(DOMException.NAMESPACE_ERR,
277: msg);
278: }
279: }
280: }
281:
282: // update node name with new qualifiedName
283: if (prefix != null && prefix.length() != 0) {
284: name = prefix + ":" + localName;
285: } else {
286: name = localName;
287: }
288: }
289:
290: /**
291: * Introduced in DOM Level 2. <p>
292: *
293: * Returns the local part of the qualified name of this node.
294: * @since WD-DOM-Level-2-19990923
295: */
296: public String getLocalName() {
297: if (needsSyncData()) {
298: synchronizeData();
299: }
300: return localName;
301: }
302:
303: /**
304: * @see org.w3c.dom.TypeInfo#getTypeName()
305: */
306: public String getTypeName() {
307: if (type != null) {
308: if (type instanceof XSSimpleTypeDecl) {
309: return ((XSSimpleTypeDecl) type).getName();
310: }
311: return (String) type;
312: }
313: return null;
314: }
315:
316: /**
317: * Introduced in DOM Level 3. <p>
318: * Checks if a type is derived from another by restriction. See:
319: * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
320: *
321: * @param typeNamespaceArg
322: * The namspace of the ancestor type declaration
323: * @param typeNameArg
324: * The name of the ancestor type declaration
325: * @param derivationMethod
326: * The derivation method
327: *
328: * @return boolean True if the type is derived by restriciton for the
329: * reference type
330: */
331: public boolean isDerivedFrom(String typeNamespaceArg,
332: String typeNameArg, int derivationMethod) {
333: if (type != null) {
334: if (type instanceof XSSimpleTypeDefinition) {
335: return ((XSSimpleTypeDecl) type)
336: .isDOMDerivedFrom(typeNamespaceArg,
337: typeNameArg, derivationMethod);
338: }
339: }
340: return false;
341: }
342:
343: /**
344: * @see org.w3c.dom.TypeInfo#getTypeNamespace()
345: */
346: public String getTypeNamespace() {
347: if (type != null) {
348: if (type instanceof XSSimpleTypeDecl) {
349: return ((XSSimpleTypeDecl) type).getNamespace();
350: }
351: return DTD_URI;
352: }
353: return null;
354: }
355:
356: }
|