001    /*
002     **
003     ** Licensed to the Apache Software Foundation (ASF) under one
004     ** or more contributor license agreements.  See the NOTICE file
005     ** distributed with this work for additional information
006     ** regarding copyright ownership.  The ASF licenses this file
007     ** to you under the Apache License, Version 2.0 (the
008     ** "License"); you may not use this file except in compliance
009     ** with the License.  You may obtain a copy of the License at
010     **
011     **  http://www.apache.org/licenses/LICENSE-2.0
012     **
013     ** Unless required by applicable law or agreed to in writing,
014     ** software distributed under the License is distributed on an
015     ** "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016     ** KIND, either express or implied.  See the License for the
017     ** specific language governing permissions and limitations
018     ** under the License.
019     */
020    package javax.xml.namespace;
021    
022    import java.io.Serializable;
023    import javax.xml.XMLConstants;
024    
025    public class QName implements Serializable {
026        // not specified in the javadoc, but this is what appears to be used.
027        private static final long serialVersionUID = -9120448754896609940L;
028        // the namespace URI of this qualified name
029        private final String namespaceURI;
030        // the local part of the name
031        private final String localPart;
032        // the name prefix string
033        private final String prefix;
034    
035        public QName(String localPart) {
036            // default both the URI and the prefix
037            this("", localPart, XMLConstants.DEFAULT_NS_PREFIX);
038        }
039    
040        public QName(String namespaceURI, String localPart) {
041            // the default prefix is defined in XMLConstants
042            this(namespaceURI, localPart, XMLConstants.DEFAULT_NS_PREFIX);
043        }
044    
045        public QName(String namespaceURI, String localPart, String prefix) {
046            // there is a default in constants as well
047            this.namespaceURI = namespaceURI == null ? "" : namespaceURI;
048    
049            // both the local part and the prefix are required
050            if (localPart == null) {
051                throw new IllegalArgumentException("local part is required when creating a QName");
052            }
053            this.localPart = localPart;
054    
055            if (prefix == null) {
056                throw new IllegalArgumentException("prefix is required when creating a QName");
057            }
058            this.prefix = prefix;
059        }
060    
061        public final boolean equals(Object other) {
062            if (other == null || !(other instanceof QName)) {
063                return false;
064            }
065    
066            QName qName = (QName)other;
067    
068            // only the namespace and localPart are considered.  the prefix is not used.
069            return namespaceURI.equals(qName.namespaceURI) && localPart.equals(qName.localPart);
070        }
071    
072        public final int hashCode() {
073            // uses both the namespace and localpart as a combined hash.
074            return namespaceURI.hashCode() ^ localPart.hashCode();
075        }
076    
077        public String getNamespaceURI() {
078            return namespaceURI;
079        }
080    
081        public String getLocalPart() {
082            return localPart;
083        }
084    
085        public String getPrefix() {
086            return prefix;
087        }
088    
089        public String toString() {
090            // if no real URI, this is just the local part, otherwise
091            // use the braces syntax.
092            if (namespaceURI.length() == 0) {
093                return localPart;
094            }
095            else {
096                return "{" + namespaceURI + "}" + localPart;
097            }
098        }
099    
100        public static QName valueOf(String source) {
101            // a name is required
102            if (source == null) {
103                throw new IllegalArgumentException("source QName string is required");
104            }
105    
106            // if this is a null string or it does not start with '{', treat this
107            // as a local part alone.
108            if (source.length() == 0 || source.charAt(0) != '{') {
109                return new QName(source);
110            }
111    
112            // Namespace URI and local part specified
113            int uriEnd  = source.indexOf('}');
114            if (uriEnd == -1) {
115                throw new IllegalArgumentException("Incorrect QName syntax: " + source);
116            }
117    
118            String uri = source.substring(1, uriEnd);
119            if (uri.length() == 0) {
120                throw new IllegalArgumentException("Null namespace URI in QName value: " + source);
121            }
122            // no prefix possible here, just the URI and the local part
123            return new QName(uri, source.substring(uriEnd + 1));
124        }
125    }