org.apache.xmlbeans.QNameSetBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-xmlbeans Show documentation
Show all versions of commons-xmlbeans Show documentation
The Apache Commons Codec package contains simple encoder and decoders for
various formats such as Base64 and Hexadecimal. In addition to these
widely used encoders and decoders, the codec package also maintains a
collection of phonetic encoding utilities.
The newest version!
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 org.apache.xmlbeans;
import javax.xml.namespace.QName;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
/**
* Used to build {@link QNameSet QNameSets}.
*/
public class QNameSetBuilder implements QNameSetSpecification, java.io.Serializable
{
private static final long serialVersionUID = 1L;
private boolean _inverted;
private Set _includedURIs;
private Set _excludedQNames;
private Set _includedQNames;
/**
* Constructs an empty QNameSetBuilder.
*/
public QNameSetBuilder()
{
_inverted = false;
_includedURIs = new HashSet();
_excludedQNames = new HashSet();
_includedQNames = new HashSet();
}
/**
* Constructs a QNameSetBuilder whose initial contents are given by
* another QNameSetSpecification.
* @param set the QNameSetSpecificaiton to copy
*/
public QNameSetBuilder(QNameSetSpecification set)
{
Set includedURIs = set.includedURIs();
if (includedURIs != null)
{
_inverted = false;
_includedURIs = new HashSet(includedURIs);
_excludedQNames = new HashSet(set.excludedQNamesInIncludedURIs());
_includedQNames = new HashSet(set.includedQNamesInExcludedURIs());
}
else
{
_inverted = true;
_includedURIs = new HashSet(set.excludedURIs());
_excludedQNames = new HashSet(set.includedQNamesInExcludedURIs());
_includedQNames = new HashSet(set.excludedQNamesInIncludedURIs());
}
}
/**
* Constructs a QNameSetBuilder whose inital contents are given by
* the four sets. Exactly one of either excludedURIs or includedURIs must
* be non-null.
*
* @param excludedURIs the finite set of namespace URI strings to exclude from the set, or null if this set is infinite
* @param includedURIs the finite set of namespace URI strings to include in the set, or null if this set is infinite
* @param excludedQNamesInIncludedURIs the finite set of exceptional QNames to exclude from the included namespaces
* @param excludedQNamesInIncludedURIs the finite set of exceptional QNames to include that are in the excluded namespaces
*/
public QNameSetBuilder(Set excludedURIs, Set includedURIs, Set excludedQNamesInIncludedURIs, Set includedQNamesInExcludedURIs)
{
if (includedURIs != null && excludedURIs == null)
{
_inverted = false;
_includedURIs = new HashSet(includedURIs);
_excludedQNames = new HashSet(excludedQNamesInIncludedURIs);
_includedQNames = new HashSet(includedQNamesInExcludedURIs);
}
else if (excludedURIs != null && includedURIs == null)
{
_inverted = true;
_includedURIs = new HashSet(excludedURIs);
_excludedQNames = new HashSet(includedQNamesInExcludedURIs);
_includedQNames = new HashSet(excludedQNamesInIncludedURIs);
}
else
throw new IllegalArgumentException("Exactly one of excludedURIs and includedURIs must be null");
}
/**
* Constructs a QNameSetBuilder whose initial contents are given
* as a list of namespace URIs, using the same format used by wildcards
* in XSD files.
*
* @param str a wildcard namespace specification string such as "##any",
* "##other", "##local", "##targetNamespace", or a space-separated
* list of URIs.
* @param targetURI the current targetNamespace
*/
public QNameSetBuilder(String str, String targetURI)
{
this();
if (str == null)
str = "##any";
String[] uri = splitList(str);
for (int i = 0; i < uri.length; i++)
{
String adduri = uri[i];
if (adduri.startsWith("##"))
{
if (adduri.equals("##other"))
{
if (targetURI == null)
throw new IllegalArgumentException();
QNameSetBuilder temp = new QNameSetBuilder();
temp.addNamespace(targetURI);
temp.addNamespace("");
temp.invert();
addAll(temp);
continue;
}
else if (adduri.equals("##any"))
{
clear();
invert();
continue;
}
else if (uri[i].equals("##targetNamespace"))
{
if (targetURI == null)
throw new IllegalArgumentException();
adduri = targetURI;
}
else if (uri[i].equals("##local"))
{
adduri = "";
}
}
addNamespace(adduri);
}
}
/**
* Local xml names are hased using "" as the namespace.
*/
private static String nsFromName(QName QName)
{
String ns = QName.getNamespaceURI();
return ns == null ? "" : ns;
}
private static final String[] EMPTY_STRINGARRAY = new String[0];
private static boolean isSpace(char ch)
{
switch (ch)
{
case ' ':
case '\t':
case '\r':
case '\n':
return true;
default:
return false;
}
}
private static String[] splitList(String s)
{
if (s.length() == 0)
return EMPTY_STRINGARRAY;
List result = new ArrayList();
int i = 0;
int start = 0;
for (;;)
{
while (i < s.length() && isSpace(s.charAt(i)))
i += 1;
if (i >= s.length())
return (String[])result.toArray(EMPTY_STRINGARRAY);
start = i;
while (i < s.length() && !isSpace(s.charAt(i)))
i += 1;
result.add(s.substring(start, i));
}
}
/**
* Remove all xml names from qnameset whose namespace matches the uri.
*/
private static void removeAllMatchingNs(String uri, Set qnameset)
{
for (Iterator i = qnameset.iterator(); i.hasNext(); )
{
if (uri.equals(nsFromName((QName)i.next())))
i.remove();
}
}
/**
* Remove all xml names from qnameset whose namespace is in the
* first set of uris but not the second.
*/
private static void removeAllMatchingFirstOnly(Set setFirst, Set setSecond, Set qnameset)
{
for (Iterator i = qnameset.iterator(); i.hasNext(); )
{
String ns = nsFromName((QName)i.next());
if (setFirst.contains(ns) && !setSecond.contains(ns))
i.remove();
}
}
/**
* Remove all xml names from qnameset whose namespace is in both
* sets of uris.
*/
private static void removeAllMatchingBoth(Set setFirst, Set setSecond, Set qnameset)
{
for (Iterator i = qnameset.iterator(); i.hasNext(); )
{
String ns = nsFromName((QName)i.next());
if (setFirst.contains(ns) && setSecond.contains(ns))
i.remove();
}
}
/**
* Remove all xml names from qnameset whose namespace is in neither
* set of uris.
*/
private static void removeAllMatchingNeither(Set setFirst, Set setSecond, Set qnameset)
{
for (Iterator i = qnameset.iterator(); i.hasNext(); )
{
String ns = nsFromName((QName)i.next());
if (!setFirst.contains(ns) && !setSecond.contains(ns))
i.remove();
}
}
/**
* True if this ModelTransitionSet contains the given qname.
*/
public boolean contains(QName name)
{
boolean in = _includedURIs.contains(nsFromName(name)) ?
!_excludedQNames.contains(name) :
_includedQNames.contains(name);
return _inverted ^ in;
}
/**
* True if this ModelTransitionSet contains all QNames.
*/
public boolean isAll()
{
return _inverted && _includedURIs.size() == 0 && _includedQNames.size() == 0;
}
/**
* True if this ModelTransitionSet contains no QNames.
*/
public boolean isEmpty()
{
return !_inverted && _includedURIs.size() == 0 && _includedQNames.size() == 0;
}
/**
* Returns a new QNameSet that is the intersection of this one and another.
*/
public QNameSet intersect(QNameSetSpecification set)
{
QNameSetBuilder result = new QNameSetBuilder(this);
result.restrict(set);
return result.toQNameSet();
}
/**
* Returns a new QNameSet that is the union of this one and another.
*/
public QNameSet union(QNameSetSpecification set)
{
QNameSetBuilder result = new QNameSetBuilder(this);
result.addAll(set);
return result.toQNameSet();
}
/**
* Returns a new QNameSet that is the inverse of this one.
*/
public QNameSet inverse()
{
return QNameSet.forSets(includedURIs(), excludedURIs(), includedQNamesInExcludedURIs(), excludedQNamesInIncludedURIs());
}
/**
* True if the parameter is a subset of this set.
*/
public boolean containsAll(QNameSetSpecification set)
{
if (!_inverted && set.excludedURIs() != null)
return false;
return inverse().isDisjoint(set);
}
/**
* True if the given set is disjoint from this one.
*/
public boolean isDisjoint(QNameSetSpecification set)
{
if (_inverted && set.excludedURIs() != null)
return false;
if (_inverted)
return isDisjointImpl(set, this);
else
return isDisjointImpl(this, set);
}
private boolean isDisjointImpl(QNameSetSpecification set1, QNameSetSpecification set2)
{
Set includeURIs = set1.includedURIs();
Set otherIncludeURIs = set2.includedURIs();
if (otherIncludeURIs != null)
{
for (Iterator i = includeURIs.iterator(); i.hasNext(); )
{
if (otherIncludeURIs.contains(i.next()))
return false;
}
}
else
{
Set otherExcludeURIs = set2.excludedURIs();
for (Iterator i = includeURIs.iterator(); i.hasNext(); )
{
if (!otherExcludeURIs.contains(i.next()))
return false;
}
}
for (Iterator i = set1.includedQNamesInExcludedURIs().iterator(); i.hasNext(); )
{
if (set2.contains((QName)i.next()))
return false;
}
if (includeURIs.size() > 0)
for (Iterator i = set2.includedQNamesInExcludedURIs().iterator(); i.hasNext(); )
{
if (set1.contains((QName)i.next()))
return false;
}
return true;
}
/**
* Clears this QNameSetBuilder
*/
public void clear()
{
_inverted = false;
_includedURIs.clear();
_excludedQNames.clear();
_includedQNames.clear();
}
/**
* Inverts this QNameSetBuilder.
*/
public void invert()
{
_inverted = !_inverted;
}
/**
* Adds a single QName to this QNameSetBuilder.
*/
public void add(QName qname)
{
if (!_inverted)
addImpl(qname);
else
removeImpl(qname);
}
/**
* Adds an entire namespace URI of QNames to this QNameSetBuilder.
* The empty string is used to signifiy the (local) no-namespace.
*/
public void addNamespace(String uri)
{
if (!_inverted)
addNamespaceImpl(uri);
else
removeNamespaceImpl(uri);
}
/**
* Adds the contents of another QNameSet to this QNameSetBuilder.
*/
public void addAll(QNameSetSpecification set)
{
if (_inverted)
removeAllImpl(set.includedURIs(), set.excludedURIs(), set.includedQNamesInExcludedURIs(), set.excludedQNamesInIncludedURIs());
else
addAllImpl(set.includedURIs(), set.excludedURIs(), set.includedQNamesInExcludedURIs(), set.excludedQNamesInIncludedURIs());
}
/**
* Removes the given qname from this QNameSetBuilder.
*/
public void remove(QName qname)
{
if (_inverted)
addImpl(qname);
else
removeImpl(qname);
}
/**
* Removes an entire namespace URI from this QNameSetBuilder.
*/
public void removeNamespace(String uri)
{
if (_inverted)
addNamespaceImpl(uri);
else
removeNamespaceImpl(uri);
}
/**
* Removes all contents of a given QNameSet from this QNameSetBuilder.
*/
public void removeAll(QNameSetSpecification set)
{
if (_inverted)
addAllImpl(set.includedURIs(), set.excludedURIs(), set.includedQNamesInExcludedURIs(), set.excludedQNamesInIncludedURIs());
else
removeAllImpl(set.includedURIs(), set.excludedURIs(), set.includedQNamesInExcludedURIs(), set.excludedQNamesInIncludedURIs());
}
/**
* Restricts the contents of this QNameSetBuilder to be a subset of the
* given QNameSet. In other words, computes an intersection.
*/
public void restrict(QNameSetSpecification set)
{
if (_inverted)
addAllImpl(set.excludedURIs(), set.includedURIs(), set.excludedQNamesInIncludedURIs(), set.includedQNamesInExcludedURIs());
else
removeAllImpl(set.excludedURIs(), set.includedURIs(), set.excludedQNamesInIncludedURIs(), set.includedQNamesInExcludedURIs());
}
/**
* Implementation of add(qname) that ignores inversion.
*/
private void addImpl(QName qname)
{
if (_includedURIs.contains(nsFromName(qname)))
_excludedQNames.remove(qname);
else
_includedQNames.add(qname);
}
/**
* Implementation of add(ns) that ignores inversion.
*/
private void addNamespaceImpl(String uri)
{
if (_includedURIs.contains(uri))
{
removeAllMatchingNs(uri, _excludedQNames);
}
else
{
removeAllMatchingNs(uri, _includedQNames);
_includedURIs.add(uri);
}
}
/**
* Implementation of add(set) that ignores inversion.
*/
private void addAllImpl(Set includedURIs, Set excludedURIs, Set includedQNames, Set excludedQNames)
{
boolean exclude = (excludedURIs != null);
Set specialURIs = exclude ? excludedURIs : includedURIs;
for (Iterator i = _excludedQNames.iterator(); i.hasNext(); )
{
QName name = (QName)i.next();
String uri = nsFromName(name);
if ((exclude ^ specialURIs.contains(uri)) && !excludedQNames.contains(name))
i.remove();
}
for (Iterator i = excludedQNames.iterator(); i.hasNext(); )
{
QName name = (QName)i.next();
String uri = nsFromName(name);
if (!_includedURIs.contains(uri) && !_includedQNames.contains(name))
_excludedQNames.add(name);
}
for (Iterator i = includedQNames.iterator(); i.hasNext(); )
{
QName name = (QName)i.next();
String uri = nsFromName(name);
if (!_includedURIs.contains(uri))
_includedQNames.add(name);
else
_excludedQNames.remove(name);
}
if (!exclude)
{
removeAllMatchingFirstOnly(includedURIs, _includedURIs, _includedQNames);
_includedURIs.addAll(includedURIs);
}
else
{
removeAllMatchingNeither(excludedURIs, _includedURIs, _includedQNames);
for (Iterator i = _includedURIs.iterator(); i.hasNext(); )
{
String uri = (String)i.next();
if (!excludedURIs.contains(uri))
i.remove();
}
for (Iterator i = excludedURIs.iterator(); i.hasNext(); )
{
String uri = (String)i.next();
if (!_includedURIs.contains(uri))
_includedURIs.add(uri);
else
_includedURIs.remove(uri);
}
Set temp = _excludedQNames;
_excludedQNames = _includedQNames;
_includedQNames = temp;
_inverted = !_inverted;
}
}
/**
* Implementation of remove(qname) that ignores inversion.
*/
private void removeImpl(QName qname)
{
if (_includedURIs.contains(nsFromName(qname)))
_excludedQNames.add(qname);
else
_includedQNames.remove(qname);
}
/**
* Implementation of remove(ns) that ignores inversion.
*/
private void removeNamespaceImpl(String uri)
{
if (_includedURIs.contains(uri))
{
removeAllMatchingNs(uri, _excludedQNames);
_includedURIs.remove(uri);
}
else
{
removeAllMatchingNs(uri, _includedQNames);
}
}
/**
* Implementation of remove(set) that ignores inversion.
*/
private void removeAllImpl(Set includedURIs, Set excludedURIs, Set includedQNames, Set excludedQNames)
{
boolean exclude = (excludedURIs != null);
Set specialURIs = exclude ? excludedURIs : includedURIs;
for (Iterator i = _includedQNames.iterator(); i.hasNext(); )
{
QName name = (QName)i.next();
String uri = nsFromName(name);
if (exclude ^ specialURIs.contains(uri))
{
if (!excludedQNames.contains(name))
i.remove();
}
else
{
if (includedQNames.contains(name))
i.remove();
}
}
for (Iterator i = includedQNames.iterator(); i.hasNext(); )
{
QName name = (QName)i.next();
String uri = nsFromName(name);
if (_includedURIs.contains(uri))
_excludedQNames.add(name);
}
for (Iterator i = excludedQNames.iterator(); i.hasNext(); )
{
QName name = (QName)i.next();
String uri = nsFromName(name);
if (_includedURIs.contains(uri) && !_excludedQNames.contains(name))
_includedQNames.add(name);
}
if (exclude)
{
removeAllMatchingFirstOnly(_includedURIs, excludedURIs, _excludedQNames);
}
else
{
removeAllMatchingBoth(_includedURIs, includedURIs, _excludedQNames);
}
for (Iterator i = _includedURIs.iterator(); i.hasNext(); )
{
if (exclude ^ specialURIs.contains(i.next()))
i.remove();
}
}
public Set excludedURIs()
{
if (_inverted) return Collections.unmodifiableSet(_includedURIs);
return null;
}
public Set includedURIs()
{
if (!_inverted) return _includedURIs;
return null;
}
public Set excludedQNamesInIncludedURIs()
{
return Collections.unmodifiableSet(_inverted ? _includedQNames : _excludedQNames);
}
public Set includedQNamesInExcludedURIs()
{
return Collections.unmodifiableSet(_inverted ? _excludedQNames : _includedQNames);
}
private String prettyQName(QName name)
{
if (name.getNamespaceURI() == null)
return name.getLocalPart();
return name.getLocalPart() + "@" + name.getNamespaceURI();
}
/**
* Returns a string representation useful for debugging, subject to change.
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("QNameSetBuilder");
sb.append(_inverted ? "-(" : "+(");
for (Iterator i = _includedURIs.iterator(); i.hasNext(); )
{
sb.append("+*@");
sb.append(i.next());
sb.append(", ");
}
for (Iterator i = _excludedQNames.iterator(); i.hasNext(); )
{
sb.append("-");
sb.append(prettyQName((QName)i.next()));
sb.append(", ");
}
for (Iterator i = _includedQNames.iterator(); i.hasNext(); )
{
sb.append("+");
sb.append(prettyQName((QName)i.next()));
sb.append(", ");
}
int index = sb.lastIndexOf(", ");
if (index > 0)
sb.setLength(index);
sb.append(')');
return sb.toString();
}
/**
* Returns a {@link QNameSet} equivalent to the current state of this
* QNameSetBuilder.
*/
public QNameSet toQNameSet()
{
return QNameSet.forSpecification(this);
}
}