/* Woodstox Lite ("wool") XML processor
*
* Copyright (c) 2006- Tatu Saloranta, tatu.saloranta@iki.fi
*
* Licensed under the License specified in the file LICENSE which is
* included with the source code.
* You may not use this file except in compliance with the License.
*
* 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 com.fasterxml.aalto.in;
import javax.xml.namespace.QName;
Prefixed Name is similar to QName
(qualified name), but only contains information about local name optionally prefixed by a prefix and colon, without namespace binding information. /**
* Prefixed Name is similar to {@link javax.xml.namespace.QName} (qualified name),
* but only contains information about local name optionally prefixed by
* a prefix and colon, without namespace binding information.
*/
public abstract class PName
{
protected final String _prefixedName;
protected final String _prefix;
protected final String _localName;
Binding of this qualified/prefixed name. Null if there is no
prefix; in which case name is either bound to the default namespace
(when element name), or no namespace (when other name, like attribute)
/**
* Binding of this qualified/prefixed name. Null if there is no
* prefix; in which case name is either bound to the default namespace
* (when element name), or no namespace (when other name, like attribute)
*/
protected NsBinding _namespaceBinding = null;
/*
/**********************************************************************
/* Life-cycle
/**********************************************************************
*/
protected PName(String pname, String prefix, String ln)
{
_prefixedName = pname;
_prefix = prefix;
_localName = ln;
}
public abstract PName createBoundName(NsBinding nsb);
/*
// 26-Jun-2006, TSa: Doesn't seem to be needed any more...
protected void bind(NsBinding nsb)
{
if (mNsBinding != null) { // !!! Temporary assertion
throw new RuntimeException("Trying to re-set binding (for '"+getPrefixedName()+"'), was: "+mNsBinding+", new: "+nsb);
}
mNsBinding = nsb;
}
*/
/*
/**********************************************************************
/* Accessors
/**********************************************************************
*/
public final String getPrefixedName() { return _prefixedName; }
Returns: Prefix of this name, if it has one; null if not.
/**
* @return Prefix of this name, if it has one; null if not.
*/
public final String getPrefix() { return _prefix; }
public final String getLocalName() { return _localName; }
public boolean hasPrefix() { return _prefix != null; }
public boolean hasPrefixedName(String n) { return _prefixedName.equals(n); }
public final NsBinding getNsBinding() { return _namespaceBinding; }
public final String getNsUri() {
return (_namespaceBinding == null) ? null : _namespaceBinding.mURI;
}
public final QName constructQName()
{
String pr = _prefix;
String uri = (_namespaceBinding == null) ? null : _namespaceBinding.mURI;
// Stupid QName: some impls barf on nulls...
return new QName((uri == null) ? "" : uri,
_localName,
(pr == null) ? "" : pr);
}
Method called to construct a QName representation of elemented
represented by this PName. Because of namespace defaulting,
current default namespace binding also needs to be passed
(since only explicit ones get bound to PName instances).
/**
* Method called to construct a QName representation of elemented
* represented by this PName. Because of namespace defaulting,
* current default namespace binding also needs to be passed
* (since only explicit ones get bound to PName instances).
*/
public final QName constructQName(NsBinding defaultNs)
{
String pr = _prefix;
if (pr == null) { // QName barfs on nulls
pr = "";
}
// Do we have a local binding?
if (_namespaceBinding != null) {
String uri = _namespaceBinding.mURI;
if (uri != null) { // yup
return new QName(uri, _localName, pr);
}
}
// Nope. Default ns?
String uri = defaultNs.mURI;
return new QName((uri == null) ? "" : uri, _localName, pr);
}
/*
/**********************************************************************
/* Namespace binding
/**********************************************************************
*/
Returns: True if the name has no binding object, but will need
one (has prefix)
/**
* @return True if the name has no binding object, but will need
* one (has prefix)
*/
public final boolean needsBinding() {
return (_prefix != null) && (_namespaceBinding == null);
}
Returns: True if the name as described either has no prefix (either
belongs to the default ns [elems], or to 'no namespace' [attrs]),
or has a prefix that is bound currently. False if name has a prefix
that is unbound.
/**
* @return True if the name as described either has no prefix (either
* belongs to the default ns [elems], or to 'no namespace' [attrs]),
* or has a prefix that is bound currently. False if name has a prefix
* that is unbound.
*/
public final boolean isBound()
{
return (_namespaceBinding == null) || (_namespaceBinding.mURI != null);
}
Method that compares two bound PNames for semantic equality. This
means that the local name, as well as bound URI are compared.
/**
* Method that compares two bound PNames for semantic equality. This
* means that the local name, as well as bound URI are compared.
*/
public final boolean boundEquals(PName other)
{
if (other == null || other._localName != _localName) {
return false;
}
// Let's assume URIs are canonicalized at least on per-doc basis?
return other.getNsUri() == getNsUri();
}
public final boolean unboundEquals(PName other)
{
return (other._prefixedName == _prefixedName);
}
public final boolean boundEquals(String nsUri, String ln)
{
if (!_localName.equals(ln)) {
return false;
}
String thisUri = getNsUri();
if (nsUri == null || nsUri.length() == 0) {
return (thisUri == null);
}
return nsUri.equals(thisUri);
}
public final int unboundHashCode()
{
return _prefixedName.hashCode();
}
public final int boundHashCode()
{
/* How often do we have same local name, but differing URI?
* Probably not often... thus, let's only use local name's hash.
*/
return _localName.hashCode();
}
public static int boundHashCode(String nsURI, String localName)
{
return localName.hashCode();
}
/*
/**********************************************************************
/* Redefined standard methods
/**********************************************************************
*/
@Override
public final String toString() { return _prefixedName; }
@Override
public int hashCode() {
return _prefixedName.hashCode();
}
@Override
public final boolean equals(Object o)
{
if (o == this) {
return true;
}
if (!(o instanceof PName)) {
return false;
}
PName other = (PName) o;
/* Only prefix and ln are interned, not the full prefixed name...
* so let's compare separately. Can use identity comparison with
* those though:
*/
return (other._prefix == _prefix) && (other._localName == _localName);
}
/*
/**********************************************************************
/* Methods for package/core parser
/**********************************************************************
*/
/* Note: These 3 methods really should be in the byte-based sub-class...
* but there are performance reasons to keep there, to remove
* some otherwise necessary casts.
*/
public abstract int sizeInQuads();
public abstract int getFirstQuad();
public abstract int getQuad(int index);
public abstract int getLastQuad();
}