maxCch)
n = maxCch;
if (n <= 0)
return 0;
s.getChars(0, n, chars, off);
return n;
}
static String applyWhiteSpaceRule(String s, int wsr)
{
int l = s == null ? 0 : s.length();
if (l == 0 || wsr == WS_PRESERVE)
return s;
char ch;
if (wsr == WS_REPLACE)
{
for (int i = 0; i < l; i++)
if ((ch = s.charAt(i)) == '\n' || ch == '\r' || ch == '\t')
return processWhiteSpaceRule(s, wsr);
}
else if (wsr == Locale.WS_COLLAPSE)
{
if (CharUtil.isWhiteSpace(s.charAt(0)) ||
CharUtil.isWhiteSpace(s.charAt(l - 1)))
return processWhiteSpaceRule(s, wsr);
boolean lastWasWhite = false;
for (int i = 1; i < l; i++)
{
boolean isWhite = CharUtil.isWhiteSpace(s.charAt(i));
if (isWhite && lastWasWhite)
return processWhiteSpaceRule(s, wsr);
lastWasWhite = isWhite;
}
}
return s;
}
static String processWhiteSpaceRule(String s, int wsr)
{
ScrubBuffer sb = getScrubBuffer(wsr);
sb.scrub(s, 0, s.length());
return sb.getResultAsString();
}
static final class ScrubBuffer
{
ScrubBuffer()
{
_sb = new StringBuffer();
}
void init(int wsr)
{
_sb.delete(0, _sb.length());
_wsr = wsr;
_state = START_STATE;
}
void scrub(Object src, int off, int cch)
{
if (cch == 0)
return;
if (_wsr == Locale.WS_PRESERVE)
{
CharUtil.getString(_sb, src, off, cch);
return;
}
char[] chars;
if (src instanceof char[])
chars = (char[]) src;
else
{
if (cch <= _srcBuf.length)
chars = _srcBuf;
else if (cch <= 16384)
chars = _srcBuf = new char[16384];
else
chars = new char[cch];
CharUtil.getChars(chars, 0, src, off, cch);
off = 0;
}
int start = 0;
for (int i = 0; i < cch; i++)
{
char ch = chars[off + i];
if (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')
{
_sb.append(chars, off + start, i - start);
start = i + 1;
if (_wsr == Locale.WS_REPLACE)
_sb.append(' ');
else if (_state == NOSPACE_STATE)
_state = SPACE_SEEN_STATE;
}
else
{
if (_state == SPACE_SEEN_STATE)
_sb.append(' ');
_state = NOSPACE_STATE;
}
}
_sb.append(chars, off + start, cch - start);
}
String getResultAsString()
{
return _sb.toString();
}
private static final int START_STATE = 0;
private static final int SPACE_SEEN_STATE = 1;
private static final int NOSPACE_STATE = 2;
private int _state;
private int _wsr;
private char[] _srcBuf = new char[1024];
private StringBuffer _sb;
}
private static ThreadLocal tl_scrubBuffer =
new ThreadLocal()
{
protected Object initialValue()
{
return new SoftReference(new ScrubBuffer());
}
};
static ScrubBuffer getScrubBuffer(int wsr)
{
SoftReference softRef = (SoftReference) tl_scrubBuffer.get();
ScrubBuffer scrubBuffer = (ScrubBuffer) (softRef).get();
if (scrubBuffer == null)
{
scrubBuffer = new ScrubBuffer();
tl_scrubBuffer.set(new SoftReference(scrubBuffer));
}
scrubBuffer.init(wsr);
return scrubBuffer;
}
static boolean pushToContainer(Cur c)
{
c.push();
for (; ;)
{
switch (c.kind())
{
case ROOT:
case ELEM:
return true;
case -ROOT:
case -ELEM:
c.pop();
return false;
case COMMENT:
case PROCINST:
c.skip();
break;
default :
c.nextWithAttrs();
break;
}
}
}
static boolean toFirstNormalAttr(Cur c)
{
c.push();
if (c.toFirstAttr())
{
do
{
if (!c.isXmlns())
{
c.popButStay();
return true;
}
}
while (c.toNextAttr());
}
c.pop();
return false;
}
static boolean toPrevNormalAttr(Cur c)
{
if (c.isAttr())
{
c.push();
for (; ;)
{
assert c.isAttr();
// See if I can move backward. If I'm at the first attr, prev must return
// false and not move.
if (!c.prev())
break;
// Skip past the text value or attr begin
c.prev();
// I might have skipped over text above
if (!c.isAttr())
c.prev();
if (c.isNormalAttr())
{
c.popButStay();
return true;
}
}
c.pop();
}
return false;
}
static boolean toNextNormalAttr(Cur c)
{
c.push();
while (c.toNextAttr())
{
if (!c.isXmlns())
{
c.popButStay();
return true;
}
}
c.pop();
return false;
}
Xobj findNthChildElem(Xobj parent, QName name, QNameSet set, int n)
{
// only one of (set or name) is not null
// or both are null for a wildcard
assert (name == null || set == null);
assert n >= 0;
if (parent == null)
return null;
int da = _nthCache_A.distance(parent, name, set, n);
int db = _nthCache_B.distance(parent, name, set, n);
Xobj x =
da <= db
? _nthCache_A.fetch(parent, name, set, n)
: _nthCache_B.fetch(parent, name, set, n);
if (da == db)
{
nthCache temp = _nthCache_A;
_nthCache_A = _nthCache_B;
_nthCache_B = temp;
}
return x;
}
int count(Xobj parent, QName name, QNameSet set)
{
int n = 0;
for (Xobj x = findNthChildElem(parent, name, set, 0);
x != null; x = x._nextSibling)
{
if (x.isElem())
{
if (set == null)
{
if (x._name.equals(name))
n++;
}
else if (set.contains(x._name))
n++;
}
}
return n;
}
static boolean toChild(Cur c, QName name, int n)
{
if (n >= 0 && pushToContainer(c))
{
Xobj x = c._locale.findNthChildElem(c._xobj, name, null, n);
c.pop();
if (x != null)
{
c.moveTo(x);
return true;
}
}
return false;
}
static boolean toFirstChildElement(Cur c)
{
// if (!pushToContainer(c))
// return false;
//
// if (!c.toFirstChild() || (!c.isElem() && !toNextSiblingElement(c)))
// {
// c.pop();
// return false;
// }
//
// c.popButStay();
//
// return true;
Xobj originalXobj = c._xobj;
int originalPos = c._pos;
loop:
for (; ;)
{
switch (c.kind())
{
case ROOT:
case ELEM:
break loop;
case -ROOT:
case -ELEM:
c.moveTo(originalXobj, originalPos);
return false;
case COMMENT:
case PROCINST:
c.skip();
break;
default:
c.nextWithAttrs();
break;
}
}
if (!c.toFirstChild() || (!c.isElem() && !toNextSiblingElement(c)))
{
c.moveTo(originalXobj, originalPos);
return false;
}
return true;
}
static boolean toLastChildElement(Cur c)
{
if (!pushToContainer(c))
return false;
if (!c.toLastChild() || (!c.isElem() && !toPrevSiblingElement(c)))
{
c.pop();
return false;
}
c.popButStay();
return true;
}
static boolean toPrevSiblingElement(Cur cur)
{
if (!cur.hasParent())
return false;
Cur c = cur.tempCur();
boolean moved = false;
int k = c.kind();
if (k != ATTR)
{
for (; ;)
{
if (!c.prev())
break;
k = c.kind();
if (k == ROOT || k == ELEM)
break;
if (c.kind() == -ELEM)
{
c.toParent();
cur.moveToCur(c);
moved = true;
break;
}
}
}
c.release();
return moved;
}
static boolean toNextSiblingElement(Cur c)
{
if (!c.hasParent())
return false;
c.push();
int k = c.kind();
if (k == ATTR)
{
c.toParent();
c.next();
}
else if (k == ELEM)
c.skip();
while ((k = c.kind()) >= 0)
{
if (k == ELEM)
{
c.popButStay();
return true;
}
if (k > 0)
c.toEnd();
c.next();
}
c.pop();
return false;
}
static boolean toNextSiblingElement(Cur c, Xobj parent)
{
Xobj originalXobj = c._xobj;
int originalPos = c._pos;
int k = c.kind();
if (k == ATTR)
{
c.moveTo(parent);
c.next();
}
else if (k == ELEM)
c.skip();
while ((k = c.kind()) >= 0)
{
if (k == ELEM)
{
return true;
}
if (k > 0)
c.toEnd();
c.next();
}
c.moveTo(originalXobj, originalPos);
return false;
}
static void applyNamespaces(Cur c, Map namespaces)
{
assert c.isContainer();
java.util.Iterator i = namespaces.keySet().iterator();
while (i.hasNext())
{
String prefix = (String) i.next();
// Usually, this is the predefined xml namespace
if (!prefix.toLowerCase().startsWith("xml"))
{
if (c.namespaceForPrefix(prefix, false) == null)
{
c.push();
c.next();
c.createAttr(c._locale.createXmlns(prefix));
c.next();
c.insertString((String) namespaces.get(prefix));
c.pop();
}
}
}
}
static Map getAllNamespaces(Cur c, Map filleMe)
{
assert c.isNode();
c.push();
if (!c.isContainer())
c.toParent();
assert c.isContainer();
do
{
QName cName = c.getName();
while (c.toNextAttr())
{
if (c.isXmlns())
{
String prefix = c.getXmlnsPrefix();
String uri = c.getXmlnsUri();
// Here I check to see if there is a default namespace
// mapping which is not empty on a non root container which
// is in a namespace. This this case, I do not want to add
// this mapping because it could not be persisted out this
// way.
if (prefix.length() == 0 && uri.length() > 0 &&
cName != null &&
cName.getNamespaceURI().length() > 0)
{
continue;
}
if (filleMe == null)
filleMe = new HashMap();
if (!filleMe.containsKey(prefix))
filleMe.put(prefix, uri);
}
}
if (!c.isContainer())
c.toParentRaw();
}
while (c.toParentRaw());
c.pop();
return filleMe;
}
class nthCache
{
private boolean namesSame(QName pattern, QName name)
{
return pattern == null || pattern.equals(name);
}
private boolean setsSame(QNameSet patternSet, QNameSet set)
{
// value equality is probably too expensive. Since the use case
// involves QNameSets that are generated by the compiler, we
// can use identity comparison.
return patternSet != null && patternSet == set;
}
private boolean nameHit(QName namePattern, QNameSet setPattern,
QName name)
{
return
setPattern == null
? namesSame(namePattern, name)
: setPattern.contains(name);
}
private boolean cacheSame(QName namePattern, QNameSet setPattern)
{
return
setPattern == null
? namesSame(namePattern, _name)
: setsSame(setPattern, _set);
}
int distance(Xobj parent, QName name, QNameSet set, int n)
{
assert n >= 0;
if (_version != Locale.this.version())
return Integer.MAX_VALUE - 1;
if (parent != _parent || !cacheSame(name, set))
return Integer.MAX_VALUE;
return n > _n ? n - _n : _n - n;
}
Xobj fetch(Xobj parent, QName name, QNameSet set, int n)
{
assert n >= 0;
if (_version != Locale.this.version() || _parent != parent ||
!cacheSame(name, set) || n == 0)
{
_version = Locale.this.version();
_parent = parent;
_name = name;
_child = null;
_n = -1;
loop:
for (Xobj x = parent._firstChild;
x != null; x = x._nextSibling)
{
if (x.isElem() && nameHit(name, set, x._name))
{
_child = x;
_n = 0;
break loop;
}
}
}
if (_n < 0)
return null;
if (n > _n)
{
while (n > _n)
{
for (Xobj x = _child._nextSibling; ; x = x._nextSibling)
{
if (x == null)
return null;
if (x.isElem() && nameHit(name, set, x._name))
{
_child = x;
_n++;
break;
}
}
}
}
else if (n < _n)
{
while (n < _n)
{
for (Xobj x = _child._prevSibling; ; x = x._prevSibling)
{
if (x == null)
return null;
if (x.isElem() && nameHit(name, set, x._name))
{
_child = x;
_n--;
break;
}
}
}
}
return _child;
}
private long _version;
private Xobj _parent;
private QName _name;
private QNameSet _set;
private Xobj _child;
private int _n;
}
//
//
//
Dom findDomNthChild ( Dom parent, int n )
{
assert n >= 0;
if (parent == null)
return null;
int da = _domNthCache_A.distance(parent, n);
int db = _domNthCache_B.distance(parent, n);
// the "better" cache should never walk more than 1/2 len
Dom x = null;
boolean bInvalidate = (db - _domNthCache_B._len / 2 > 0) &&
(db - _domNthCache_B._len / 2 - domNthCache.BLITZ_BOUNDARY > 0);
boolean aInvalidate = (da - _domNthCache_A._len / 2 > 0) &&
(da - _domNthCache_A._len / 2 - domNthCache.BLITZ_BOUNDARY > 0);
if (da <= db)
if (!aInvalidate)
x = _domNthCache_A.fetch(parent, n);
else
{
_domNthCache_B._version = -1;//blitz the cache
x = _domNthCache_B.fetch(parent, n);
}
else if (!bInvalidate)
x = _domNthCache_B.fetch(parent, n);
else
{
_domNthCache_A._version = -1;//blitz the cache
x = _domNthCache_A.fetch(parent, n);
}
if (da == db)
{
domNthCache temp = _domNthCache_A;
_domNthCache_A = _domNthCache_B;
_domNthCache_B = temp;
}
return x;
}
int domLength ( Dom parent )
{
if (parent == null)
return 0;
int da = _domNthCache_A.distance( parent, 0 );
int db = _domNthCache_B.distance( parent, 0 );
int len =
da <= db
? _domNthCache_A.length( parent )
: _domNthCache_B.length( parent );
if (da == db)
{
domNthCache temp = _domNthCache_A;
_domNthCache_A = _domNthCache_B;
_domNthCache_B = temp;
}
return len;
}
void invalidateDomCaches ( Dom d )
{
if (_domNthCache_A._parent == d)
_domNthCache_A._version = -1;
if (_domNthCache_B._parent == d)
_domNthCache_B._version = -1;
}
boolean isDomCached ( Dom d )
{
return _domNthCache_A._parent == d || _domNthCache_B._parent == d;
}
class domNthCache
{
int distance ( Dom parent, int n )
{
assert n >= 0;
if (_version != Locale.this.version())
return Integer.MAX_VALUE - 1;
if (parent != _parent)
return Integer.MAX_VALUE;
return n > _n ? n - _n : _n - n;
}
int length ( Dom parent )
{
if (_version != Locale.this.version() || _parent != parent)
{
_parent = parent;
_version = Locale.this.version();
_child = null;
_n = -1;
_len = -1;
}
if (_len == -1)
{
Dom x = null;
if (_child != null && _n != -1)
{
x = _child;
_len = _n;
}
else
{
x = DomImpl.firstChild(_parent);
_len = 0;
// cache the 0th child
_child = x;
_n = 0;
}
for (; x != null; x = DomImpl.nextSibling(x) )
{
_len++;
}
}
return _len;
}
Dom fetch ( Dom parent, int n )
{
assert n >= 0;
if (_version != Locale.this.version() || _parent != parent)
{
_parent = parent;
_version = Locale.this.version();
_child = null;
_n = -1;
_len = -1;
for (Dom x = DomImpl.firstChild(_parent); x != null; x = DomImpl.nextSibling(x) )
{
_n++;
if (_child == null && n == _n )
{
_child = x;
break;
}
}
return _child;
}
if (_n < 0)
return null;
if (n > _n)
{
while ( n > _n )
{
for (Dom x = DomImpl.nextSibling(_child); ; x = DomImpl.nextSibling(x) )
{
if (x == null)
return null;
_child = x;
_n++;
break;
}
}
}
else if (n < _n)
{
while ( n < _n )
{
for (Dom x = DomImpl.prevSibling(_child); ; x = DomImpl.prevSibling(x) )
{
if (x == null)
return null;
_child = x;
_n--;
break;
}
}
}
return _child;
}
public static final int BLITZ_BOUNDARY = 40; //walk small lists
private long _version;
private Dom _parent;
private Dom _child;
private int _n;
private int _len;
}
//
//
//
CharUtil getCharUtil()
{
if (_charUtil == null)
_charUtil = new CharUtil(1024);
return _charUtil;
}
long version()
{
return _versionAll;
}
Cur weakCur(Object o)
{
assert o != null && !(o instanceof Ref);
Cur c = getCur();
assert c._tempFrame == -1;
assert c._ref == null;
c._ref = new Ref(c, o);
return c;
}
final ReferenceQueue refQueue()
{
if (_refQueue == null)
_refQueue = new ReferenceQueue();
return _refQueue;
}
final static class Ref
extends PhantomReference
{
Ref(Cur c, Object obj)
{
super(obj, c._locale.refQueue());
_cur = c;
}
Cur _cur;
}
Cur tempCur()
{
return tempCur(null);
}
Cur tempCur(String id)
{
Cur c = getCur();
assert c._tempFrame == -1;
assert _numTempFramesLeft < _tempFrames.length : "Temp frame not pushed";
int frame = _tempFrames.length - _numTempFramesLeft - 1;
assert frame >= 0 && frame < _tempFrames.length;
Cur next = _tempFrames[frame];
c._nextTemp = next;
assert c._prevTemp == null;
if (next != null)
{
assert next._prevTemp == null;
next._prevTemp = c;
}
_tempFrames[frame] = c;
c._tempFrame = frame;
c._id = id;
return c;
}
Cur getCur()
{
assert _curPool == null || _curPoolCount > 0;
Cur c;
if (_curPool == null)
c = new Cur(this);
else
{
_curPool = _curPool.listRemove(c = _curPool);
_curPoolCount--;
}
assert c._state == Cur.POOLED;
assert c._prev == null && c._next == null;
assert c._xobj == null && c._pos == Cur.NO_POS;
assert c._ref == null;
_registered = c.listInsert(_registered);
c._state = Cur.REGISTERED;
return c;
}
void embedCurs()
{
for (Cur c; (c = _registered) != null;)
{
assert c._xobj != null;
_registered = c.listRemove(_registered);
c._xobj._embedded = c.listInsert(c._xobj._embedded);
c._state = Cur.EMBEDDED;
}
}
TextNode createTextNode()
{
return _saaj == null ? new TextNode(this) : new SaajTextNode(this);
}
CdataNode createCdataNode()
{
return _saaj == null ?
new CdataNode(this) : new SaajCdataNode(this);
}
boolean entered()
{
return _tempFrames.length - _numTempFramesLeft > 0;
}
public void enter(Locale otherLocale)
{
enter();
if (otherLocale != this)
otherLocale.enter();
}
public void enter()
{
assert _numTempFramesLeft >= 0;
if (--_numTempFramesLeft <= 0)
{
Cur[] newTempFrames = new Cur[(_numTempFramesLeft =
_tempFrames.length) *
2];
System.arraycopy(_tempFrames, 0, newTempFrames, 0,
_tempFrames.length);
_tempFrames = newTempFrames;
}
if (++_entryCount > 1000)
{
pollQueue();
_entryCount = 0;
}
}
private void pollQueue()
{
if (_refQueue != null)
{
for (; ;)
{
Ref ref = (Ref) _refQueue.poll();
if (ref == null)
break;
if (ref._cur != null)
ref._cur.release();
}
}
}
public void exit(Locale otherLocale)
{
exit();
if (otherLocale != this)
otherLocale.exit();
}
public void exit()
{
// assert _numTempFramesLeft >= 0;
//asserts computed frame fits between 0 and _tempFrames.length
assert _numTempFramesLeft >= 0 &&
(_numTempFramesLeft <= _tempFrames.length - 1):
" Temp frames mismanaged. Impossible stack frame. Unsynchronized: " +
noSync();
int frame = _tempFrames.length - ++_numTempFramesLeft;
while (_tempFrames[frame] != null)
_tempFrames[frame].release();
}
//
//
//
public boolean noSync()
{
return _noSync;
}
public boolean sync()
{
return !_noSync;
}
static final boolean isWhiteSpace(String s)
{
int l = s.length();
while (l-- > 0)
if (!CharUtil.isWhiteSpace(s.charAt(l)))
return false;
return true;
}
static final boolean isWhiteSpace(StringBuffer sb)
{
int l = sb.length();
while (l-- > 0)
if (!CharUtil.isWhiteSpace(sb.charAt(l)))
return false;
return true;
}
static boolean beginsWithXml(String name)
{
if (name.length() < 3)
return false;
char ch;
if (((ch = name.charAt(0)) == 'x' || ch == 'X') &&
((ch = name.charAt(1)) == 'm' || ch == 'M') &&
((ch = name.charAt(2)) == 'l' || ch == 'L'))
{
return true;
}
return false;
}
static boolean isXmlns(QName name)
{
String prefix = name.getPrefix();
if (prefix.equals("xmlns"))
return true;
return prefix.length() == 0 && name.getLocalPart().equals("xmlns");
}
QName createXmlns(String prefix)
{
if (prefix == null)
prefix = "";
return
prefix.length() == 0
? makeQName(_xmlnsUri, "xmlns", "")
: makeQName(_xmlnsUri, prefix, "xmlns");
}
static String xmlnsPrefix(QName name)
{
return name.getPrefix().equals("xmlns") ? name.getLocalPart() : "";
}
//
// Loading/parsing
//
static abstract class LoadContext
{
protected abstract void startDTD(String name, String publicId,
String systemId);
protected abstract void endDTD();
protected abstract void startElement(QName name);
protected abstract void endElement();
protected abstract void attr(QName name, String value);
protected abstract void attr(String local, String uri, String prefix,
String value);
protected abstract void xmlns(String prefix, String uri);
protected abstract void comment(char[] buff, int off, int cch);
protected abstract void comment(String comment);
protected abstract void procInst(String target, String value);
protected abstract void text(char[] buff, int off, int cch);
protected abstract void text(String s);
protected abstract Cur finish();
protected abstract void abort();
protected abstract void bookmark(XmlBookmark bm);
protected abstract void bookmarkLastNonAttr(XmlBookmark bm);
protected abstract void bookmarkLastAttr(QName attrName,
XmlBookmark bm);
protected abstract void lineNumber(int line, int column, int offset);
protected void addIdAttr(String eName, String aName){
if ( _idAttrs == null )
_idAttrs = new java.util.Hashtable();
_idAttrs.put(aName,eName);
}
protected boolean isAttrOfTypeId(QName aqn, QName eqn){
if (_idAttrs == null)
return false;
String pre = aqn.getPrefix();
String lName = aqn.getLocalPart();
String urnName = "".equals(pre)?lName:pre + ":" + lName;
String eName = (String) _idAttrs.get(urnName);
if (eName == null ) return false;
//get the name of the parent elt
pre = eqn.getPrefix();
lName = eqn.getLocalPart();
lName = eqn.getLocalPart();
urnName = "".equals(pre)?lName:pre + ":" + lName;
return eName.equals(urnName);
}
private java.util.Hashtable _idAttrs;
}
private static class DefaultEntityResolver
implements EntityResolver
{
public InputSource resolveEntity(String publicId, String systemId)
{
return new InputSource(new StringReader(""));
}
}
private static SaxLoader getPiccoloSaxLoader()
{
SaxLoader piccoloLoader = (SaxLoader) SystemCache.get().getSaxLoader();
if (piccoloLoader == null)
{
piccoloLoader = PiccoloSaxLoader.newInstance();
SystemCache.get().setSaxLoader(piccoloLoader);
}
return piccoloLoader;
}
private static SaxLoader getSaxLoader(XmlOptions options)
{
options = XmlOptions.maskNull(options);
EntityResolver er = null;
if (!options.hasOption(XmlOptions.LOAD_USE_DEFAULT_RESOLVER))
{
er = (EntityResolver) options.get(XmlOptions.ENTITY_RESOLVER);
if (er == null)
er = ResolverUtil.getGlobalEntityResolver();
if (er == null)
er = new DefaultEntityResolver();
}
SaxLoader sl;
if (options.hasOption(XmlOptions.LOAD_USE_XMLREADER))
{
XMLReader xr = (XMLReader) options.get(
XmlOptions.LOAD_USE_XMLREADER);
if (xr == null)
throw new IllegalArgumentException("XMLReader is null");
sl = new XmlReaderSaxLoader(xr);
// I've noticed that most XMLReaders don't like a null EntityResolver...
if (er != null)
xr.setEntityResolver(er);
}
else
{
sl = getPiccoloSaxLoader();
// Piccolo doesnot mind a null entity resolver ...
sl.setEntityResolver(er);
}
return sl;
}
private static class XmlReaderSaxLoader
extends SaxLoader
{
XmlReaderSaxLoader(XMLReader xr)
{
super(xr, null);
}
}
private static class PiccoloSaxLoader
extends SaxLoader
{
private PiccoloSaxLoader(Piccolo p)
{
super(p, p.getStartLocator());
_piccolo = p;
}
static PiccoloSaxLoader newInstance()
{
return new PiccoloSaxLoader(new Piccolo());
}
void postLoad(Cur c)
{
XmlDocumentProperties props = getDocProps(c, true);
props.setEncoding(_piccolo.getEncoding());
props.setVersion(_piccolo.getVersion());
super.postLoad(c);
}
private Piccolo _piccolo;
}
private static abstract class SaxHandler
implements ContentHandler, LexicalHandler , DeclHandler, DTDHandler
{
SaxHandler(Locator startLocator)
{
_startLocator = startLocator;
}
SaxHandler()
{
this(null);
}
void initSaxHandler(Locale l, XmlOptions options)
{
_locale = l;
options = XmlOptions.maskNull(options);
_context = new Cur.CurLoadContext(_locale, options);
_wantLineNumbers =
_startLocator != null &&
options.hasOption(XmlOptions.LOAD_LINE_NUMBERS);
_wantLineNumbersAtEndElt =
_startLocator != null &&
options.hasOption(XmlOptions.LOAD_LINE_NUMBERS_END_ELEMENT);
_wantCdataBookmarks =
_startLocator != null &&
options.hasOption(XmlOptions.LOAD_SAVE_CDATA_BOOKMARKS);
if (options.hasOption(XmlOptions.LOAD_ENTITY_BYTES_LIMIT))
_entityBytesLimit = ((Integer)(options.get(XmlOptions.LOAD_ENTITY_BYTES_LIMIT))).intValue();
}
public void startDocument()
throws SAXException
{
// Do nothing ... start of document is implicit
}
public void endDocument()
throws SAXException
{
// Do nothing ... end of document is implicit
}
public void startElement(String uri, String local, String qName,
Attributes atts)
throws SAXException
{
if (local.length() == 0)
local = qName;
// Out current parser (Piccolo) does not error when a
// namespace is used and not defined. Check for these here
if (qName.indexOf(':') >= 0 && uri.length() == 0)
{
XmlError err =
XmlError.forMessage("Use of undefined namespace prefix: " +
qName.substring(0, qName.indexOf(':')));
throw new XmlRuntimeException(err.toString(), null, err);
}
_context.startElement(_locale.makeQualifiedQName(uri, qName));
if (_wantLineNumbers)
{
_context.bookmark(
new XmlLineNumber(_startLocator.getLineNumber(),
_startLocator.getColumnNumber() - 1, -1));
}
for (int i = 0, len = atts.getLength(); i < len; i++)
{
String aqn = atts.getQName(i);
if (aqn.equals("xmlns"))
{
_context.xmlns("", atts.getValue(i));
}
else if (aqn.startsWith("xmlns:"))
{
String prefix = aqn.substring(6);
if (prefix.length() == 0)
{
XmlError err =
XmlError.forMessage("Prefix not specified",
XmlError.SEVERITY_ERROR);
throw new XmlRuntimeException(err.toString(), null,
err);
}
String attrUri = atts.getValue(i);
if (attrUri.length() == 0)
{
XmlError err =
XmlError.forMessage(
"Prefix can't be mapped to no namespace: " +
prefix,
XmlError.SEVERITY_ERROR);
throw new XmlRuntimeException(err.toString(), null,
err);
}
_context.xmlns(prefix, attrUri);
}
else
{
int colon = aqn.indexOf(':');
if (colon < 0)
_context.attr(aqn, atts.getURI(i), null,
atts.getValue(i));
else
{
_context.attr(aqn.substring(colon + 1), atts.getURI(i), aqn.substring(
0, colon),
atts.getValue(i));
}
}
}
}
public void endElement(String namespaceURI, String localName,
String qName)
throws SAXException
{
_context.endElement();
if (_wantLineNumbersAtEndElt)
{
_context.bookmark(
new XmlLineNumber(_startLocator.getLineNumber(),
_startLocator.getColumnNumber() - 1, -1));
}
}
public void characters(char ch[], int start, int length)
throws SAXException
{
_context.text(ch, start, length);
if (_wantCdataBookmarks && _insideCDATA)
_context.bookmarkLastNonAttr(CDataBookmark.CDATA_BOOKMARK);
if (_insideEntity!=0)
{
if ((_entityBytes += length) > _entityBytesLimit)
{
XmlError err = XmlError.forMessage(XmlErrorCodes.EXCEPTION_EXCEEDED_ENTITY_BYTES,
new Integer[]{ new Integer(_entityBytesLimit) });
throw new SAXException(err.getMessage());
}
}
}
public void ignorableWhitespace(char ch[], int start, int length)
throws SAXException
{
}
public void comment(char ch[], int start, int length)
throws SAXException
{
_context.comment(ch, start, length);
}
public void processingInstruction(String target, String data)
throws SAXException
{
_context.procInst(target, data);
}
public void startDTD(String name, String publicId, String systemId)
throws SAXException
{
_context.startDTD(name, publicId, systemId);
}
public void endDTD()
throws SAXException
{
_context.endDTD();
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException
{
if (beginsWithXml(prefix) &&
!("xml".equals(prefix) && _xml1998Uri.equals(uri)))
{
XmlError err =
XmlError.forMessage(
"Prefix can't begin with XML: " + prefix,
XmlError.SEVERITY_ERROR);
throw new XmlRuntimeException(err.toString(), null, err);
}
}
public void endPrefixMapping(String prefix)
throws SAXException
{
}
public void skippedEntity(String name)
throws SAXException
{
// throw new RuntimeException( "Not impl: skippedEntity" );
}
public void startCDATA()
throws SAXException
{
_insideCDATA = true;
}
public void endCDATA()
throws SAXException
{
_insideCDATA = false;
}
public void startEntity(String name)
throws SAXException
{
_insideEntity++;
}
public void endEntity(String name)
throws SAXException
{
_insideEntity--;
assert _insideEntity>=0;
if (_insideEntity==0)
{
_entityBytes=0;
}
}
public void setDocumentLocator(Locator locator)
{
// TODO - for non-Piccolo use cases, use a locator to get line numbers
}
//DeclHandler
public void attributeDecl(String eName, String aName, String type, String valueDefault, String value){
if (type.equals("ID")){
_context.addIdAttr(eName,aName);
}
}
public void elementDecl(String name, String model){
}
public void externalEntityDecl(String name, String publicId, String systemId){
}
public void internalEntityDecl(String name, String value){
}
//DTDHandler
public void notationDecl(String name, String publicId, String systemId){
}
public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName){
}
protected Locale _locale;
protected LoadContext _context;
private boolean _wantLineNumbers;
private boolean _wantLineNumbersAtEndElt;
private boolean _wantCdataBookmarks;
private Locator _startLocator;
private boolean _insideCDATA = false;
private int _entityBytesLimit = 10240;
private int _entityBytes = 0;
private int _insideEntity = 0;
}
private static abstract class SaxLoader
extends SaxHandler
implements ErrorHandler
{
SaxLoader(XMLReader xr, Locator startLocator)
{
super(startLocator);
_xr = xr;
try
{
_xr.setFeature(
"http://xml.org/sax/features/namespace-prefixes", true);
_xr.setFeature("http://xml.org/sax/features/namespaces", true);
_xr.setFeature("http://xml.org/sax/features/validation", false);
_xr.setProperty(
"http://xml.org/sax/properties/lexical-handler", this);
_xr.setContentHandler(this);
_xr.setProperty("http://xml.org/sax/properties/declaration-handler", this);
_xr.setDTDHandler(this);
_xr.setErrorHandler(this);
}
catch (Throwable e)
{
throw new RuntimeException(e.getMessage(), e);
}
}
void setEntityResolver(EntityResolver er)
{
_xr.setEntityResolver(er);
}
void postLoad(Cur c)
{
// fix garbage collection of Locale -> Xobj -> STL
_locale = null;
_context = null;
}
public Cur load(Locale l, InputSource is, XmlOptions options)
throws XmlException, IOException
{
is.setSystemId("file://");
initSaxHandler(l, options);
try
{
_xr.parse(is);
Cur c = _context.finish();
associateSourceName(c, options);
postLoad(c);
return c;
}
catch (FileFormatException e)
{
_context.abort();
throw new XmlException(e.getMessage(), e);
}
catch (XmlRuntimeException e)
{
_context.abort();
throw new XmlException(e);
}
catch (SAXParseException e)
{
_context.abort();
XmlError err =
XmlError.forLocation(e.getMessage(),
(String) XmlOptions.safeGet(options,
XmlOptions.DOCUMENT_SOURCE_NAME),
e.getLineNumber(), e.getColumnNumber(), -1);
throw new XmlException(err.toString(), e, err);
}
catch (SAXException e)
{
_context.abort();
XmlError err = XmlError.forMessage(e.getMessage());
throw new XmlException(err.toString(), e, err);
}
catch (RuntimeException e)
{
_context.abort();
throw e;
}
}
public void fatalError(SAXParseException e)
throws SAXException
{
throw e;
}
public void error(SAXParseException e)
throws SAXException
{
throw e;
}
public void warning(SAXParseException e)
throws SAXException
{
throw e;
}
private XMLReader _xr;
}
private Dom load(InputSource is, XmlOptions options)
throws XmlException, IOException
{
return getSaxLoader(options).load(this, is, options).getDom();
}
public Dom load(Reader r)
throws XmlException, IOException
{
return load(r, null);
}
public Dom load(Reader r, XmlOptions options)
throws XmlException, IOException
{
return load(new InputSource(r), options);
}
public Dom load(InputStream in)
throws XmlException, IOException
{
return load(in, null);
}
public Dom load(InputStream in, XmlOptions options)
throws XmlException, IOException
{
return load(new InputSource(in), options);
}
public Dom load(String s)
throws XmlException
{
return load(s, null);
}
public Dom load(String s, XmlOptions options)
throws XmlException
{
Reader r = new StringReader(s);
try
{
return load(r, options);
}
catch (IOException e)
{
assert false: "StringReader should not throw IOException";
throw new XmlException(e.getMessage(), e);
}
finally
{
try
{
r.close();
}
catch (IOException e)
{
}
}
}
//
// DOMImplementation methods
//
public Document createDocument(String uri, String qname,
DocumentType doctype)
{
return DomImpl._domImplementation_createDocument(this, uri, qname,
doctype);
}
public DocumentType createDocumentType(String qname, String publicId,
String systemId)
{
throw new RuntimeException("Not implemented");
// return DomImpl._domImplementation_createDocumentType( this, qname, publicId, systemId );
}
public boolean hasFeature(String feature, String version)
{
return DomImpl._domImplementation_hasFeature(this, feature, version);
}
public Object getFeature(String feature, String version)
{
throw new RuntimeException("DOM Level 3 Not implemented");
}
//
// Dom methods
//
private static Dom checkNode(Node n)
{
if (n == null)
throw new IllegalArgumentException("Node is null");
if (!(n instanceof Dom))
throw new IllegalArgumentException("Node is not an XmlBeans node");
return (Dom) n;
}
public static XmlCursor nodeToCursor(Node n)
{
return DomImpl._getXmlCursor(checkNode(n));
}
public static XmlObject nodeToXmlObject(Node n)
{
return DomImpl._getXmlObject(checkNode(n));
}
public static XMLStreamReader nodeToXmlStream(Node n)
{
return DomImpl._getXmlStreamReader(checkNode(n));
}
public static Node streamToNode(XMLStreamReader xs)
{
return Jsr173.nodeFromStream(xs);
}
//
// SaajCallback methods
//
public void setSaajData(Node n, Object o)
{
assert n instanceof Dom;
DomImpl.saajCallback_setSaajData((Dom) n, o);
}
public Object getSaajData(Node n)
{
assert n instanceof Dom;
return DomImpl.saajCallback_getSaajData((Dom) n);
}
public Element createSoapElement(QName name, QName parentName)
{
assert _ownerDoc != null;
return DomImpl.saajCallback_createSoapElement(_ownerDoc, name,
parentName);
}
public Element importSoapElement(Document doc, Element elem, boolean deep,
QName parentName)
{
assert doc instanceof Dom;
return DomImpl.saajCallback_importSoapElement((Dom) doc, elem, deep,
parentName);
}
private static final class DefaultQNameFactory
implements QNameFactory
{
private QNameCache _cache = XmlBeans.getQNameCache();
public QName getQName(String uri, String local)
{
return _cache.getName(uri, local, "");
}
public QName getQName(String uri, String local, String prefix)
{
return _cache.getName(uri, local, prefix);
}
public QName getQName(char[] uriSrc, int uriPos, int uriCch,
char[] localSrc, int localPos, int localCch)
{
return
_cache.getName(new String(uriSrc, uriPos, uriCch),
new String(localSrc, localPos, localCch),
"");
}
public QName getQName(char[] uriSrc, int uriPos, int uriCch,
char[] localSrc, int localPos, int localCch,
char[] prefixSrc, int prefixPos, int prefixCch)
{
return
_cache.getName(new String(uriSrc, uriPos, uriCch),
new String(localSrc, localPos, localCch),
new String(prefixSrc, prefixPos, prefixCch));
}
}
private static final class LocalDocumentQNameFactory
implements QNameFactory
{
private QNameCache _cache = new QNameCache( 32 );
public QName getQName(String uri, String local)
{
return _cache.getName(uri, local, "");
}
public QName getQName(String uri, String local, String prefix)
{
return _cache.getName(uri, local, prefix);
}
public QName getQName(char[] uriSrc, int uriPos, int uriCch,
char[] localSrc, int localPos, int localCch)
{
return
_cache.getName(new String(uriSrc, uriPos, uriCch),
new String(localSrc, localPos, localCch),
"");
}
public QName getQName(char[] uriSrc, int uriPos, int uriCch,
char[] localSrc, int localPos, int localCch,
char[] prefixSrc, int prefixPos, int prefixCch)
{
return
_cache.getName(new String(uriSrc, uriPos, uriCch),
new String(localSrc, localPos, localCch),
new String(prefixSrc, prefixPos, prefixCch));
}
}
//
//
//
boolean _noSync;
SchemaTypeLoader _schemaTypeLoader;
private ReferenceQueue _refQueue;
private int _entryCount;
int _numTempFramesLeft;
Cur[] _tempFrames;
Cur _curPool;
int _curPoolCount;
Cur _registered;
ChangeListener _changeListeners;
long _versionAll;
long _versionSansText;
Locations _locations;
private CharUtil _charUtil;
int _offSrc;
int _cchSrc;
Saaj _saaj;
Dom _ownerDoc;
QNameFactory _qnameFactory;
boolean _validateOnSet;
int _posTemp;
nthCache _nthCache_A = new nthCache();
nthCache _nthCache_B = new nthCache();
domNthCache _domNthCache_A = new domNthCache();
domNthCache _domNthCache_B = new domNthCache();
}
xmlbeans-2.6.0/src/store/org/apache/xmlbeans/impl/store/Xobj.java 0000644 0001750 0001750 00000323723 11476266350 023102 0 ustar apo apo /* 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.impl.store;
import org.apache.xmlbeans.CDataBookmark;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.DOMImplementation;
// DOM Level 3
import org.w3c.dom.UserDataHandler;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.TypeInfo;
import javax.xml.transform.Source;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.apache.xmlbeans.impl.soap.Detail;
import org.apache.xmlbeans.impl.soap.DetailEntry;
import org.apache.xmlbeans.impl.soap.MimeHeaders;
import org.apache.xmlbeans.impl.soap.Name;
import org.apache.xmlbeans.impl.soap.SOAPBody;
import org.apache.xmlbeans.impl.soap.SOAPBodyElement;
import org.apache.xmlbeans.impl.soap.SOAPElement;
import org.apache.xmlbeans.impl.soap.SOAPEnvelope;
import org.apache.xmlbeans.impl.soap.SOAPException;
import org.apache.xmlbeans.impl.soap.SOAPFactory;
import org.apache.xmlbeans.impl.soap.SOAPFault;
import org.apache.xmlbeans.impl.soap.SOAPFaultElement;
import org.apache.xmlbeans.impl.soap.SOAPHeader;
import org.apache.xmlbeans.impl.soap.SOAPHeaderElement;
import org.apache.xmlbeans.impl.soap.SOAPPart;
import org.apache.xmlbeans.impl.store.Locale.LoadContext;
import org.apache.xmlbeans.impl.store.DomImpl.Dom;
import org.apache.xmlbeans.impl.store.DomImpl.CharNode;
import org.apache.xmlbeans.impl.store.DomImpl.TextNode;
import org.apache.xmlbeans.impl.store.DomImpl.CdataNode;
import org.apache.xmlbeans.impl.store.DomImpl.SaajTextNode;
import org.apache.xmlbeans.impl.store.DomImpl.SaajCdataNode;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.SchemaField;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlCursor.XmlMark;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.apache.xmlbeans.impl.values.TypeStoreVisitor;
import org.apache.xmlbeans.impl.values.TypeStoreUserFactory;
import javax.xml.namespace.QName;
import org.apache.xmlbeans.impl.common.ValidatorListener;
import org.apache.xmlbeans.impl.common.XmlLocale;
import org.apache.xmlbeans.impl.common.QNameHelper;
abstract class Xobj implements TypeStore
{
static final int TEXT = Cur.TEXT;
static final int ROOT = Cur.ROOT;
static final int ELEM = Cur.ELEM;
static final int ATTR = Cur.ATTR;
static final int COMMENT = Cur.COMMENT;
static final int PROCINST = Cur.PROCINST;
static final int END_POS = Cur.END_POS;
static final int NO_POS = Cur.NO_POS;
Xobj ( Locale l, int kind, int domType )
{
assert kind == ROOT || kind == ELEM || kind == ATTR || kind == COMMENT || kind == PROCINST;
_locale = l;
_bits = (domType << 4) + kind;
}
final boolean entered ( ) { return _locale.entered(); }
final int kind ( ) { return _bits & 0xF; }
final int domType ( ) { return (_bits & 0xF0) >> 4; }
final boolean isRoot ( ) { return kind() == ROOT; }
final boolean isAttr ( ) { return kind() == ATTR; }
final boolean isElem ( ) { return kind() == ELEM; }
final boolean isProcinst ( ) { return kind() == PROCINST; }
final boolean isComment ( ) { return kind() == COMMENT; }
final boolean isContainer ( ) { return Cur.kindIsContainer( kind() ); }
final boolean isUserNode ( ) { int k = kind(); return k == ELEM || k == ROOT || (k == ATTR && !isXmlns()); }
final boolean isNormalAttr ( ) { return isAttr() && !Locale.isXmlns( _name ); }
final boolean isXmlns ( ) { return isAttr() && Locale.isXmlns( _name ); }
final int cchValue ( ) { return _cchValue; }
final int cchAfter ( ) { return _cchAfter; }
final int posAfter ( ) { return 2 + _cchValue; }
final int posMax ( ) { return 2 + _cchValue + _cchAfter; }
final String getXmlnsPrefix ( ) { return Locale.xmlnsPrefix( _name ); }
final String getXmlnsUri ( ) { return getValueAsString(); }
final boolean hasTextEnsureOccupancy ( )
{
ensureOccupancy();
return hasTextNoEnsureOccupancy();
}
final boolean hasTextNoEnsureOccupancy ( )
{
if (_cchValue > 0)
return true;
Xobj lastAttr = lastAttr();
return lastAttr != null && lastAttr._cchAfter > 0;
}
final boolean hasAttrs ( ) { return _firstChild != null && _firstChild.isAttr(); }
final boolean hasChildren ( ) { return _lastChild != null && !_lastChild .isAttr(); }
/**
* this method is to speed up DomImpl
* when underlying obj is an Xobj
*
* @return 0 or 1 dom children; val 2 indicates that DomImpl needs to
* compute the result itself
*/
final protected int getDomZeroOneChildren()
{
if (_firstChild == null &&
_srcValue == null &&
_charNodesValue == null)
return 0;
if (_lastChild != null &&
_lastChild.isAttr() &&
_lastChild._charNodesAfter == null &&
_lastChild._srcAfter == null &&
_srcValue == null &&
_charNodesValue == null
)
return 0;
if (_firstChild == _lastChild &&
_firstChild != null &&
!_firstChild.isAttr() &&
_srcValue == null &&
_charNodesValue == null &&
_firstChild._srcAfter == null
)
return 1;
if (_firstChild == null &&
_srcValue != null &&
( _charNodesValue == null ||
(_charNodesValue._next == null &&
_charNodesValue._cch == _cchValue))
)
return 1;
//single elem after an attr
Xobj lastAttr = lastAttr();
Xobj node = lastAttr == null ?
null : lastAttr._nextSibling;
if (lastAttr != null &&
lastAttr._srcAfter == null &&
node != null &&
node._srcAfter == null &&
node._nextSibling == null)
return 1;
return 2;
}
/**
* can one use the _firstChild pointer to retrieve
* the first DOM child
*
* @return
*/
final protected boolean isFirstChildPtrDomUsable()
{
if (_firstChild == null &&
_srcValue == null &&
_charNodesValue == null)
return true;
if (_firstChild != null &&
!_firstChild.isAttr() &&
_srcValue == null &&
_charNodesValue == null)
{
assert (_firstChild instanceof Xobj.NodeXobj):
"wrong node type";
return true;
}
return false;
}
/**
* can one use the _nextSibling pointer to retrieve
* the next DOM sibling
* @return
*/
final protected boolean isNextSiblingPtrDomUsable()
{
if (_charNodesAfter == null &&
_srcAfter == null)
{
assert (_nextSibling == null ||
_nextSibling instanceof Xobj.NodeXobj):
"wrong node type";
return true;
}
return false;
}
/**
* can one use the _charNodesValue pointer to retrieve
* the next DOM sibling
*
* @return
*/
final protected boolean isExistingCharNodesValueUsable()
{
if (_srcValue == null) return false;
if (_charNodesValue != null && _charNodesValue._next == null
&& _charNodesValue._cch == _cchValue)
return true;
return false;
}
final protected boolean isCharNodesValueUsable()
{
return isExistingCharNodesValueUsable() ||
(_charNodesValue =
Cur.updateCharNodes(_locale, this,
_charNodesValue, _cchValue)) != null;
}
/**
* can one use the _charNodesAfter pointer to retrieve
* the next DOM sibling
*
* @return
*/
final protected boolean isCharNodesAfterUsable()
{
if (_srcAfter == null) return false;
if (_charNodesAfter != null && _charNodesAfter._next == null
&& _charNodesAfter._cch == this._cchAfter)
return true;
return (_charNodesAfter =
Cur.updateCharNodes(_locale, this,
_charNodesAfter, _cchAfter)) != null;
}
final Xobj lastAttr ( )
{
if (_firstChild == null || !_firstChild.isAttr())
return null;
Xobj lastAttr = _firstChild;
while ( lastAttr._nextSibling != null && lastAttr._nextSibling.isAttr() )
lastAttr = lastAttr._nextSibling;
return lastAttr;
}
abstract Dom getDom ( );
abstract Xobj newNode ( Locale l );
final int cchLeft ( int p )
{
if (isRoot() && p == 0)
return 0;
Xobj x = getDenormal( p );
p = posTemp();
int pa = x.posAfter();
return p - (p < pa ? 1 : pa);
}
final int cchRight ( int p )
{
assert p < posMax();
if (p <= 0)
return 0;
int pa = posAfter();
return p < pa ? pa - p - 1 : posMax() - p;
}
//
// Dom interface
//
public final Locale locale ( ) { return _locale; }
public final int nodeType ( ) { return domType(); }
public final QName getQName ( ) { return _name; }
public final Cur tempCur ( ) { Cur c = _locale.tempCur(); c.moveTo( this ); return c; }
public void dump ( PrintStream o, Object ref ) { Cur.dump( o, (Xobj) this, ref ); }
public void dump ( PrintStream o ) { Cur.dump( o, this, this ); }
public void dump ( ) { dump( System.out ); }
//
//
//
final Cur getEmbedded ( )
{
_locale.embedCurs();
return _embedded;
}
// Incoming p must be at text (implicitly denormalized)
final boolean inChars ( int p, Xobj xIn, int pIn, int cch, boolean includeEnd )
{
assert p > 0 && p < posMax() && p != posAfter() - 1 && cch > 0;
assert xIn.isNormal( pIn );
// No need to denormalize "in" if the right hand side is excluded. Denormalizing deals
// with the case where p is END_POS.
int offset;
if (includeEnd)
{
// Can't denormalize at the beginning of the document
if (xIn.isRoot() && pIn == 0)
return false;
xIn = xIn.getDenormal( pIn );
pIn = xIn.posTemp();
offset = 1;
}
else
offset = 0;
return xIn == this && pIn >= p && pIn < p + (cch < 0 ? cchRight( p ) : cch) + offset;
}
// Is x/p just after the end of this
final boolean isJustAfterEnd ( Xobj x, int p )
{
assert x.isNormal( p );
// Get denormalize at the beginning of the doc
if (x.isRoot() && p == 0)
return false;
return
x == this
? p == posAfter()
: x.getDenormal( p ) == this && x.posTemp() == posAfter();
}
final boolean isInSameTree ( Xobj x )
{
if (_locale != x._locale)
return false;
for ( Xobj y = this ; ; y = y._parent )
{
if (y == x)
return true;
if (y._parent == null)
{
for ( ; ; x = x._parent )
{
if (x == this)
return true;
if (x._parent == null)
return x == y;
}
}
}
}
final boolean contains ( Cur c )
{
assert c.isNormal();
return contains( c._xobj, c._pos );
}
final boolean contains ( Xobj x, int p )
{
assert x.isNormal( p );
if (this == x)
return p == END_POS || (p > 0 && p < posAfter());
if (_firstChild == null)
return false;
for ( ; x != null ; x = x._parent )
if (x == this)
return true;
return false;
}
final Bookmark setBookmark ( int p, Object key, Object value )
{
assert isNormal( p );
for ( Bookmark b = _bookmarks ; b != null ; b = b._next )
{
if (p == b._pos && key == b._key)
{
if (value == null)
{
_bookmarks = b.listRemove( _bookmarks );
return null;
}
b._value = value;
return b;
}
}
if (value == null)
return null;
Bookmark b = new Bookmark();
b._xobj = this;
b._pos = p;
b._key = key;
b._value = value;
_bookmarks = b.listInsert( _bookmarks );
return b;
}
final boolean hasBookmark(Object key, int pos)
{
for ( Bookmark b = _bookmarks ; b != null ; b = b._next )
if ( b._pos == pos && key == b._key )
{
//System.out.println("hasCDataBookmark pos: " + pos + " xobj: " + getQName() + " b._pos: " + _bookmarks._pos);
return true;
}
return false;
}
final Xobj findXmlnsForPrefix ( String prefix )
{
assert isContainer() && prefix != null;
for ( Xobj c = this ; c != null ; c = c._parent )
for ( Xobj a = c.firstAttr() ; a != null ; a = a.nextAttr() )
if (a.isXmlns() && a.getXmlnsPrefix().equals( prefix ))
return a;
return null;
}
final boolean removeAttr ( QName name )
{
assert isContainer();
Xobj a = getAttr( name );
if (a == null)
return false;
Cur c = a.tempCur();
for ( ; ; )
{
c.moveNode( null );
a = getAttr( name );
if (a == null)
break;
c.moveTo( a );
}
c.release();
return true;
}
final Xobj setAttr ( QName name, String value )
{
assert isContainer();
Cur c = tempCur();
if (c.toAttr( name ))
c.removeFollowingAttrs();
else
{
c.next();
c.createAttr( name );
}
c.setValue( value );
Xobj a = c._xobj;
c.release();
return a;
}
final void setName ( QName newName )
{
assert isAttr() || isElem() || isProcinst();
assert newName != null;
if (!_name.equals( newName ) || !_name.getPrefix().equals( newName.getPrefix() ))
{
// TODO - this is not a structural change .... perhaps should not issue a change here?
_locale.notifyChange();
QName oldName = _name;
_name = newName;
if (this instanceof Xobj.NamedNodeXobj)
{
NamedNodeXobj me = (NamedNodeXobj)this;
me._canHavePrefixUri = true;
}
if (!isProcinst())
{
Xobj disconnectFromHere = this;
if (isAttr() && _parent != null)
{
if (oldName.equals( Locale._xsiType ) || newName.equals( Locale._xsiType ))
disconnectFromHere = _parent;
if (oldName.equals( Locale._xsiNil ) || newName.equals( Locale._xsiNil ))
_parent.invalidateNil();
}
disconnectFromHere.disconnectNonRootUsers();
}
_locale._versionAll++;
_locale._versionSansText++;
}
}
final Xobj ensureParent ( )
{
assert _parent != null || (!isRoot() && cchAfter() == 0);
return _parent == null ? new DocumentFragXobj( _locale ).appendXobj( this ) : _parent;
}
final Xobj firstAttr ( )
{
return _firstChild == null || !_firstChild.isAttr() ? null : _firstChild;
}
final Xobj nextAttr ( )
{
if (_firstChild != null && _firstChild.isAttr())
return _firstChild;
if (_nextSibling != null && _nextSibling.isAttr())
return _nextSibling;
return null;
}
final boolean isValid ( )
{
if (isVacant() && (_cchValue != 0 || _user == null))
return false;
return true;
}
final int posTemp ( )
{
return _locale._posTemp;
}
final Xobj getNormal ( int p )
{
assert p == END_POS || (p >= 0 && p <= posMax());
Xobj x = this;
if (p == x.posMax())
{
if (x._nextSibling != null)
{
x = x._nextSibling;
p = 0;
}
else
{
x = x.ensureParent();
p = END_POS;
}
}
else if (p == x.posAfter() - 1)
p = END_POS;
_locale._posTemp = p;
return x;
}
// Can't denormalize a position at the very beginning of the document. No where to go to the
// left!
final Xobj getDenormal ( int p )
{
assert END_POS == -1;
assert !isRoot() || p == END_POS || p > 0;
Xobj x = this;
if (p == 0)
{
if (x._prevSibling == null)
{
x = x.ensureParent();
p = x.posAfter() - 1;
}
else
{
x = x._prevSibling;
p = x.posMax();
}
}
else if (p == END_POS)
{
if (x._lastChild == null)
p = x.posAfter() - 1;
else
{
x = x._lastChild;
p = x.posMax();
}
}
_locale._posTemp = p;
return x;
}
final boolean isNormal ( int p )
{
if (!isValid())
return false;
if (p == END_POS || p == 0)
return true;
if (p < 0 || p >= posMax())
return false;
if (p >= posAfter())
{
if (isRoot())
return false;
if (_nextSibling != null && _nextSibling.isAttr())
return false;
if (_parent == null || !_parent.isContainer())
return false;
}
if (p == posAfter() - 1)
return false;
return true;
}
final Xobj walk ( Xobj root, boolean walkChildren )
{
if (_firstChild != null && walkChildren)
return _firstChild;
for ( Xobj x = this ; x != root ; x = x._parent )
if (x._nextSibling != null)
return x._nextSibling;
return null;
}
final Xobj removeXobj ( )
{
if (_parent != null)
{
if (_parent._firstChild == this)
_parent._firstChild = _nextSibling;
if (_parent._lastChild == this)
_parent._lastChild = _prevSibling;
if (_prevSibling != null)
_prevSibling._nextSibling = _nextSibling;
if (_nextSibling != null)
_nextSibling._prevSibling = _prevSibling;
_parent = null;
_prevSibling = null;
_nextSibling = null;
}
return this;
}
final Xobj insertXobj ( Xobj s )
{
assert _locale == s._locale;
assert !s.isRoot() && !isRoot();
assert s._parent == null;
assert s._prevSibling == null;
assert s._nextSibling == null;
ensureParent();
s._parent = _parent;
s._prevSibling = _prevSibling;
s._nextSibling = this;
if (_prevSibling != null)
_prevSibling._nextSibling = s;
else
_parent._firstChild = s;
_prevSibling = s;
return this;
}
final Xobj appendXobj ( Xobj c )
{
assert _locale == c._locale;
assert !c.isRoot();
assert c._parent == null;
assert c._prevSibling == null;
assert c._nextSibling == null;
assert _lastChild == null || _firstChild != null;
c._parent = this;
c._prevSibling = _lastChild;
if (_lastChild == null)
_firstChild = c;
else
_lastChild._nextSibling = c;
_lastChild = c;
return this;
}
final void removeXobjs ( Xobj first, Xobj last )
{
assert last._locale == first._locale;
assert first._parent == this;
assert last._parent == this;
if (_firstChild == first)
_firstChild = last._nextSibling;
if (_lastChild == last)
_lastChild = first._prevSibling;
if (first._prevSibling != null)
first._prevSibling._nextSibling = last._nextSibling;
if (last._nextSibling != null)
last._nextSibling._prevSibling = first._prevSibling;
// Leave the children linked together
first._prevSibling = null;
last._nextSibling = null;
for ( ; first != null ; first = first._nextSibling )
first._parent = null;
}
final void insertXobjs ( Xobj first, Xobj last )
{
assert _locale == first._locale;
assert last._locale == first._locale;
assert first._parent == null && last._parent == null;
assert first._prevSibling == null;
assert last._nextSibling == null;
first._prevSibling = _prevSibling;
last._nextSibling = this;
if (_prevSibling != null)
_prevSibling._nextSibling = first;
else
_parent._firstChild = first;
_prevSibling = last;
for ( ; first != this ; first = first._nextSibling )
first._parent = _parent;
}
final void appendXobjs ( Xobj first, Xobj last )
{
assert _locale == first._locale;
assert last._locale == first._locale;
assert first._parent == null && last._parent == null;
assert first._prevSibling == null;
assert last._nextSibling == null;
assert !first.isRoot();
first._prevSibling = _lastChild;
if (_lastChild == null)
_firstChild = first;
else
_lastChild._nextSibling = first;
_lastChild = last;
for ( ; first != null ; first = first._nextSibling )
first._parent = this;
}
static final void disbandXobjs ( Xobj first, Xobj last )
{
assert last._locale == first._locale;
assert first._parent == null && last._parent == null;
assert first._prevSibling == null;
assert last._nextSibling == null;
assert !first.isRoot();
while ( first != null )
{
Xobj next = first._nextSibling;
first._nextSibling = first._prevSibling = null;
first = next;
}
}
// Potential attr is going to be moved/removed, invalidate parent if it is a special attr
final void invalidateSpecialAttr ( Xobj newParent )
{
if (isAttr())
{
if (_name.equals( Locale._xsiType ))
{
if (_parent != null)
_parent.disconnectNonRootUsers();
if (newParent != null)
newParent.disconnectNonRootUsers();
}
if (_name.equals( Locale._xsiNil ))
{
if (_parent != null)
_parent.invalidateNil();
if (newParent != null)
newParent.invalidateNil();
}
}
}
// Move or remove chars. Incoming p is denormalized. Incoming xTo and pTo are denormalized.
// Option to move curs with text. Option to perform invalidations.
//
// Important note: this fcn must operate under the assumption that the tree may be in an
// invalid state. Most likely, there may be text on two different nodes which should belong
// on the same node. Assertion of cursor normalization usually detects this problem. Any of
// the fcns it calls must also deal with these invalid conditions. Try not to call so many
// fcns from here.
final void removeCharsHelper (
int p, int cchRemove, Xobj xTo, int pTo, boolean moveCurs, boolean invalidate )
{
assert p > 0 && p < posMax() && p != posAfter() - 1;
assert cchRemove > 0;
assert cchRight( p ) >= cchRemove;
assert !moveCurs || xTo != null;
// Here I check the span of text to be removed for cursors. If xTo/pTo is not specified,
// then the caller wants these cursors to collapse to be after the text being removed. If
// the caller specifies moveCurs, then the caller has arranged for the text being removed
// to have been copied to xTp/pTo and wants the cursors to be moved there as well.
// Note that I call nextChars here. I do this because trying to shift the cursor to the
// end of the text to be removed with a moveTo could cause the improper placement of the
// cursor just before an end tag, instead of placing it just before the first child. Also,
// I adjust all positions of curs after the text to be removed to account for the removal.
for ( Cur c = getEmbedded() ; c != null ; )
{
Cur next = c._next;
// Here I test to see if the Cur c is in the range of chars to be removed. Normally
// I would call inChars, but it can't handle the invalidity of the tree, so I heve
// inlined the inChars logic here (includeEnd is false, makes it much simpler).
// Note that I also call moveToNoCheck because the destination may have afterText
// and no parent which will cause normaliztion checks in MoveTo to fail. I don't think
// that nextChars will be called under such circumstnaces.
assert c._xobj == this;
if (c._pos >= p && c._pos < p + cchRemove)
{
if (moveCurs)
c.moveToNoCheck( xTo, pTo + c._pos - p );
else
c.nextChars( cchRemove - c._pos + p );
}
// If c is still on this Xobj and it's to the right of the chars to remove, adjust
// it to adapt to the removal of the cars. I don't have to worry about END_POS
// here, just curs in text.
if (c._xobj == this && c._pos >= p + cchRemove)
c._pos -= cchRemove;
c = next;
}
// Here I move bookmarks in this text to the span of text at xTo/pTo. The text at this/p
// is going away, but a caller of this fcn who specifies xTo/pTo has copied the text to
// xTo/pTo. The caller has to make sure that if xTo/pTo is not specified, then there are
// no bookmarks in the span of text to be removed.
for ( Bookmark b = _bookmarks ; b != null ; )
{
Bookmark next = b._next;
// Similarly, as above, I can't call inChars here
assert b._xobj == this;
if (b._pos >= p && b._pos < p + cchRemove)
{
assert xTo != null;
b.moveTo( xTo, pTo + b._pos - p );
}
if (b._xobj == this && b._pos >= p + cchRemove)
b._pos -= cchRemove;
b = b._next;
}
// Now, remove the actual chars
int pa = posAfter();
CharUtil cu = _locale.getCharUtil();
if (p < pa)
{
_srcValue = cu.removeChars( p - 1, cchRemove, _srcValue, _offValue, _cchValue );
_offValue = cu._offSrc;
_cchValue = cu._cchSrc;
if (invalidate)
{
invalidateUser();
invalidateSpecialAttr( null );
}
}
else
{
_srcAfter = cu.removeChars( p - pa, cchRemove, _srcAfter, _offAfter, _cchAfter );
_offAfter = cu._offSrc;
_cchAfter = cu._cchSrc;
if (invalidate && _parent != null)
_parent.invalidateUser();
}
}
// Insert chars into this xobj. Incoming p is denormalized. Update bookmarks and cursors.
// This fcn does not deal with occupation of the value, this needs to be handled by the
// caller.
final void insertCharsHelper ( int p, Object src, int off, int cch, boolean invalidate )
{
assert p > 0;
assert p >= posAfter() || isOccupied();
int pa = posAfter();
// Here I shuffle bookmarks and cursors affected by the insertion of the new text. Because
// getting the embedded cursors is non-trivial, I avoid getting them if I don't need to.
// Basically, I need to know if p is before any text in the node as a whole. If it is,
// then there may be cursors/marks I need to shift right.
if (p - (p < pa ? 1 : 2) < _cchValue + _cchAfter)
{
for ( Cur c = getEmbedded() ; c != null ; c = c._next )
if (c._pos >= p)
c._pos += cch;
for ( Bookmark b = _bookmarks ; b != null ; b = b._next )
if (b._pos >= p)
b._pos += cch;
}
// Now, stuff the new characters in! Also invalidate the proper container and if the
// value of an attribute is changing, check for special attr invalidation. Note that
// I do not assume that inserting after text will have a parent. There are use cases
// from moveNodesContents which excersize this.
CharUtil cu = _locale.getCharUtil();
if (p < pa)
{
_srcValue = cu.insertChars( p - 1, _srcValue, _offValue, _cchValue, src, off, cch );
_offValue = cu._offSrc;
_cchValue = cu._cchSrc;
if (invalidate)
{
invalidateUser();
invalidateSpecialAttr( null );
}
}
else
{
_srcAfter = cu.insertChars( p - pa, _srcAfter, _offAfter, _cchAfter, src, off, cch );
_offAfter = cu._offSrc;
_cchAfter = cu._cchSrc;
if (invalidate && _parent != null)
_parent.invalidateUser();
}
}
Xobj copyNode ( Locale toLocale )
{
Xobj newParent = null;
Xobj copy = null;
for ( Xobj x = this ; ; )
{
x.ensureOccupancy();
Xobj newX = x.newNode( toLocale );
newX._srcValue = x._srcValue;
newX._offValue = x._offValue;
newX._cchValue = x._cchValue;
newX._srcAfter = x._srcAfter;
newX._offAfter = x._offAfter;
newX._cchAfter = x._cchAfter;
for ( Bookmark b = x._bookmarks; b != null ; b = b._next )
{
if ( x.hasBookmark( CDataBookmark.CDATA_BOOKMARK.getKey(), b._pos) )
newX.setBookmark(b._pos, CDataBookmark.CDATA_BOOKMARK.getKey(), CDataBookmark.CDATA_BOOKMARK);
}
// TODO - strange to have charNode stuff inside here .....
// newX._charNodesValue = CharNode.copyNodes( x._charNodesValue, newX._srcValue );
// newX._charNodesAfter = CharNode.copyNodes( x._charNodesAfter, newX._srcAfter );
if (newParent == null)
copy = newX;
else
newParent.appendXobj( newX );
// Walk to the next in-order xobj. Record the current (y) to compute newParent
Xobj y = x;
if ((x = x.walk( this, true )) == null)
break;
if (y == x._parent)
newParent = newX;
else
for ( ; y._parent != x._parent ; y = y._parent )
newParent = newParent._parent;
}
copy._srcAfter = null;
copy._offAfter = 0;
copy._cchAfter = 0;
return copy;
}
// Rturns all the chars, even if there is text intermixed with children
String getCharsAsString ( int p, int cch, int wsr )
{
if (cchRight( p ) == 0)
return "";
Object src = getChars( p, cch );
if (wsr == Locale.WS_PRESERVE)
return CharUtil.getString( src, _locale._offSrc, _locale._cchSrc );
Locale.ScrubBuffer scrub = Locale.getScrubBuffer( wsr );
scrub.scrub( src, _locale._offSrc, _locale._cchSrc );
return scrub.getResultAsString();
}
String getCharsAfterAsString ( int off, int cch )
{
int offset = off + _cchValue + 2;
if (offset == posMax())
offset = -1;
return getCharsAsString(offset, cch,
Locale.WS_PRESERVE);
}
String getCharsValueAsString ( int off, int cch )
{
return getCharsAsString(off + 1, cch,
Locale.WS_PRESERVE);
}
String getValueAsString ( int wsr )
{
if (!hasChildren())
{
Object src = getFirstChars();
if (wsr == Locale.WS_PRESERVE)
{
String s = CharUtil.getString( src, _locale._offSrc, _locale._cchSrc );
// Cache string to be able to use it later again
int cch = s.length();
if (cch > 0)
{
Xobj lastAttr = lastAttr();
assert (lastAttr == null ? _cchValue : lastAttr._cchAfter) == cch;
if (lastAttr != null)
{
lastAttr._srcAfter = s;
lastAttr._offAfter = 0;
}
else
{
_srcValue = s;
_offValue = 0;
}
}
return s;
}
Locale.ScrubBuffer scrub = Locale.getScrubBuffer( wsr );
scrub.scrub( src, _locale._offSrc, _locale._cchSrc );
return scrub.getResultAsString();
}
Locale.ScrubBuffer scrub = Locale.getScrubBuffer( wsr );
Cur c = tempCur();
c.push();
for ( c.next() ; !c.isAtEndOfLastPush() ; )
{
if (c.isText())
scrub.scrub( c.getChars( -1 ), c._offSrc, c._cchSrc );
if (c.isComment() || c.isProcinst())
c.skip();
else
c.next();
}
String s = scrub.getResultAsString();
c.release();
return s;
}
String getValueAsString ( )
{
return getValueAsString( Locale.WS_PRESERVE );
}
String getString ( int p, int cch )
{
int cchRight = cchRight( p );
if (cchRight == 0)
return "";
if (cch < 0 || cch > cchRight)
cch = cchRight;
int pa = posAfter();
assert p > 0;
String s;
if (p >= pa)
{
s = CharUtil.getString( _srcAfter, _offAfter + p - pa, cch );
if (p == pa && cch == _cchAfter)
{
_srcAfter = s;
_offAfter = 0;
}
}
else
{
s = CharUtil.getString( _srcValue, _offValue + p - 1, cch );
if (p == 1 && cch == _cchValue)
{
_srcValue = s;
_offValue = 0;
}
}
return s;
}
// Returns just chars just after the begin tag ... does not get all the text if there are
// children
Object getFirstChars ( )
{
ensureOccupancy();
if (_cchValue > 0)
return getChars( 1, -1 );
Xobj lastAttr = lastAttr();
if (lastAttr == null || lastAttr._cchAfter <= 0)
{
_locale._offSrc = 0;
_locale._cchSrc = 0;
return null;
}
return lastAttr.getChars( lastAttr.posAfter(), -1 );
}
Object getChars ( int pos, int cch, Cur c )
{
Object src = getChars( pos, cch );
c._offSrc = _locale._offSrc;
c._cchSrc = _locale._cchSrc;
return src;
}
// These return the remainder of the char triple that getChars starts
Object getChars ( int pos, int cch )
{
assert isNormal( pos );
int cchRight = cchRight( pos );
if (cch < 0 || cch > cchRight)
cch = cchRight;
if (cch == 0)
{
_locale._offSrc = 0;
_locale._cchSrc = 0;
return null;
}
return getCharsHelper( pos, cch );
}
// Assumes that there are chars to return, does not assume normal x/p
Object getCharsHelper ( int pos, int cch )
{
assert cch > 0 && cchRight( pos ) >= cch;
int pa = posAfter();
Object src;
if (pos >= pa)
{
src = _srcAfter;
_locale._offSrc = _offAfter + pos - pa;
}
else
{
src = _srcValue;
_locale._offSrc = _offValue + pos - 1;
}
_locale._cchSrc = cch;
return src;
}
//
//
//
final void setBit ( int mask ) { _bits |= mask; }
final void clearBit ( int mask ) { _bits &= ~mask; }
final boolean bitIsSet ( int mask ) { return (_bits & mask) != 0; }
final boolean bitIsClear ( int mask ) { return (_bits & mask) == 0; }
static final int VACANT = 0x100;
static final int STABLE_USER = 0x200;
static final int INHIBIT_DISCONNECT = 0x400;
final boolean isVacant ( ) { return bitIsSet ( VACANT ); }
final boolean isOccupied ( ) { return bitIsClear ( VACANT ); }
final boolean inhibitDisconnect ( ) { return bitIsSet ( INHIBIT_DISCONNECT ); }
final boolean isStableUser ( ) { return bitIsSet( STABLE_USER ); }
void invalidateNil ( )
{
if (_user != null)
_user.invalidate_nilvalue();
}
void setStableType ( SchemaType type )
{
setStableUser( ((TypeStoreUserFactory) type).createTypeStoreUser() );
}
void setStableUser ( TypeStoreUser user )
{
disconnectNonRootUsers();
disconnectUser();
assert _user == null;
_user = user;
_user.attach_store( this );
setBit( STABLE_USER );
}
void disconnectUser ( )
{
if (_user != null && !inhibitDisconnect())
{
ensureOccupancy();
_user.disconnect_store();
_user = null;
}
}
// If a node does not have a user, then I don't need to walk its descendents. NOte that
// the doconnect happens in document order. This may be a problem ... not sure ... May want
// to disconnect in a bottom up manner.
void disconnectNonRootUsers ( )
{
Xobj next;
for ( Xobj x = this ; x != null ; x = next )
{
next = x.walk( this, x._user != null );
if (!x.isRoot())
x.disconnectUser();
}
}
void disconnectChildrenUsers ( )
{
Xobj next;
for ( Xobj x = walk( this, _user == null ) ; x != null ; x = next )
{
next = x.walk( this, x._user != null );
x.disconnectUser();
}
}
/**
* Given a prefix, returns the namespace corresponding to
* the prefix at this location, or null if there is no mapping
* for this prefix.
*
* prefix="" indicates the absence of a prefix. A return value
* of "" indicates the no-namespace, and should not be confused
* with a return value of null, which indicates an illegal
* state, where there is no mapping for the given prefix.
*
* If the the default namespace is not explicitly mapped in the xml,
* the xml spec says that it should be mapped to the no-namespace.
* When the 'defaultAlwaysMapped' parameter is true, the default namepsace
* will return the no-namespace even if it is not explicity
* mapped, otherwise the default namespace will return null.
*
* This function intercepts the built-in prefixes "xml" and
* "xmlns" and returns their well-known namespace URIs.
*
* @param prefix The prefix to look up.
* @param defaultAlwaysMapped If true, return the no-namespace for the default namespace if not set.
* @return The mapped namespace URI ("" if no-namespace), or null if no mapping.
*/
final String namespaceForPrefix ( String prefix, boolean defaultAlwaysMapped )
{
if (prefix == null)
prefix = "";
// handle built-in prefixes
if (prefix.equals( "xml" ))
return Locale._xml1998Uri;
if (prefix.equals( "xmlns" ))
return Locale._xmlnsUri;
for ( Xobj x = this ; x != null ; x = x._parent )
for ( Xobj a = x._firstChild ; a != null && a.isAttr() ; a = a._nextSibling )
if (a.isXmlns() && a.getXmlnsPrefix().equals( prefix ))
return a.getXmlnsUri();
return defaultAlwaysMapped && prefix.length() == 0 ? "" : null;
}
final String prefixForNamespace ( String ns, String suggestion, boolean createIfMissing )
{
if (ns == null)
ns = "";
// special cases
if (ns.equals( Locale._xml1998Uri ))
return "xml";
if (ns.equals( Locale._xmlnsUri ))
return "xmlns";
// Get the closest container for the spot we're on
Xobj base = this;
while ( !base.isContainer() )
base = base.ensureParent();
// Special handling for the no-namespace case
if (ns.length() == 0)
{
// Search for a namespace decl which defines the default namespace
Xobj a = base.findXmlnsForPrefix( "" );
// If I did not find a default decl or the decl maps to the no namespace, then
// the default namespace is mapped to ""
if (a == null || a.getXmlnsUri().length() == 0)
return "";
// At this point, I've found a default namespace which is *not* the no-namespace.
// If I can't modify the document to mape the desired no-namespace, I must fail.
if (!createIfMissing)
return null;
// Ok, I need to make the default namespace on the nearest container map to ""
base.setAttr( _locale.createXmlns( null ), "" );
return "";
}
// Look for an exisiting mapping for the desired uri which has a visible prefix
for ( Xobj c = base ; c != null ; c = c._parent )
for ( Xobj a = c.firstAttr() ; a != null ; a = a.nextAttr() )
if (a.isXmlns() && a.getXmlnsUri().equals( ns ))
if (base.findXmlnsForPrefix( a.getXmlnsPrefix() ) == a)
return a.getXmlnsPrefix();
// No exisiting xmlns I can use, need to create one. See if I can first
if (!createIfMissing)
return null;
// Sanitize the suggestion.
if (suggestion != null &&
(suggestion.length() == 0 || suggestion.toLowerCase().startsWith( "xml" ) ||
base.findXmlnsForPrefix( suggestion ) != null))
{
suggestion = null;
}
// If no suggestion, make one up
if (suggestion == null)
{
String prefixBase = QNameHelper.suggestPrefix( ns );
suggestion = prefixBase;
for ( int i = 1 ; ; suggestion = prefixBase + i++ )
if (base.findXmlnsForPrefix( suggestion ) == null)
break;
}
// Add a new namespace decl at the top elem if one exists, otherwise at root
Xobj c = base;
while ( !c.isRoot() && !c.ensureParent().isRoot() )
c = c._parent;
base.setAttr( _locale.createXmlns( suggestion ), ns );
return suggestion;
}
final QName getValueAsQName ( )
{
assert !hasChildren();
// TODO -
// caching the QName value in this object would prevent one from having
// to repeat all this string arithmatic over and over again. Perhaps
// when I make the store capable of handling strong simple types this
// can be done ...
String value = getValueAsString( Locale.WS_COLLAPSE );
String prefix, localname;
int firstcolon = value.indexOf( ':' );
if (firstcolon >= 0)
{
prefix = value.substring( 0, firstcolon );
localname = value.substring( firstcolon + 1 );
}
else
{
prefix = "";
localname = value;
}
String uri = namespaceForPrefix( prefix, true );
if (uri == null)
return null; // no prefix definition found - that's illegal
return new QName( uri, localname );
}
final Xobj getAttr ( QName name )
{
for ( Xobj x = _firstChild ; x != null && x.isAttr() ; x = x._nextSibling )
if (x._name.equals( name ))
return x;
return null;
}
final QName getXsiTypeName ( )
{
assert isContainer();
Xobj a = getAttr( Locale._xsiType );
return a == null ? null : a.getValueAsQName();
}
final XmlObject getObject ( )
{
return isUserNode() ? (XmlObject) getUser() : null;
}
final TypeStoreUser getUser ( )
{
assert isUserNode();
assert _user != null || (!isRoot() && !isStableUser());
if (_user == null)
{
// BUGBUG - this is recursive
TypeStoreUser parentUser =
_parent == null
? ((TypeStoreUserFactory) XmlBeans.NO_TYPE).createTypeStoreUser()
: _parent.getUser();
_user =
isElem()
? parentUser.create_element_user( _name, getXsiTypeName() )
: parentUser.create_attribute_user( _name );
_user.attach_store( this );
}
return _user;
}
final void invalidateUser ( )
{
assert isValid();
assert _user == null || isUserNode();
if (_user != null)
_user.invalidate_value();
}
final void ensureOccupancy ( )
{
assert isValid();
if (isVacant())
{
assert isUserNode();
// In order to use Cur to set the value, I mark the
// value as occupied and remove the user to prohibit
// further user invalidations
clearBit( VACANT );
TypeStoreUser user = _user;
_user = null;
String value = user.build_text( this );
long saveVersion = _locale._versionAll;
long saveVersionSansText = _locale._versionSansText;
setValue( value );
assert saveVersionSansText == _locale._versionSansText;
_locale._versionAll = saveVersion;
assert _user == null;
_user = user;
}
}
private void setValue(String val)
{
assert CharUtil.isValid(val, 0, val.length());
// Check for nothing to insert
if (val.length() <= 0)
return;
_locale.notifyChange();
Xobj lastAttr = lastAttr();
int startPos = 1;
Xobj charOwner = this;
if (lastAttr != null)
{
charOwner = lastAttr;
startPos = charOwner.posAfter();
}
charOwner.insertCharsHelper(startPos, val, 0, val.length(), true);
}
//
// TypeStore
//
public SchemaTypeLoader get_schematypeloader ( )
{
return _locale._schemaTypeLoader;
}
public XmlLocale get_locale ( )
{
return _locale;
}
// TODO - remove this when I've replaced the old store
public Object get_root_object ( )
{
return _locale;
}
public boolean is_attribute ( ) { assert isValid(); return isAttr(); }
public boolean validate_on_set ( ) { assert isValid(); return _locale._validateOnSet; }
public void invalidate_text ( )
{
_locale.enter();
try
{
assert isValid();
if (isOccupied())
{
if (hasTextNoEnsureOccupancy() || hasChildren())
{
TypeStoreUser user = _user;
_user = null;
Cur c = tempCur();
c.moveNodeContents( null, false );
c.release();
assert _user == null;
_user = user;
}
setBit( VACANT );
}
assert isValid();
}
finally
{
_locale.exit();
}
}
public String fetch_text ( int wsr )
{
_locale.enter();
try
{
assert isValid() && isOccupied();
return getValueAsString( wsr );
}
finally
{
_locale.exit();
}
}
public XmlCursor new_cursor ( )
{
_locale.enter();
try
{
Cur c = tempCur();
XmlCursor xc = new Cursor( c );
c.release();
return xc;
}
finally
{
_locale.exit();
}
}
public SchemaField get_schema_field ( )
{
assert isValid();
if (isRoot())
return null;
TypeStoreUser parentUser = ensureParent().getUser();
if (isAttr())
return parentUser.get_attribute_field( _name );
assert isElem();
TypeStoreVisitor visitor = parentUser.new_visitor();
if (visitor == null)
return null;
for ( Xobj x = _parent._firstChild ; ; x = x._nextSibling )
{
if (x.isElem())
{
visitor.visit( x._name );
if (x == this)
return visitor.get_schema_field();
}
}
}
public void validate ( ValidatorListener eventSink )
{
_locale.enter();
try
{
Cur c = tempCur();
Validate validate = new Validate( c, eventSink );
c.release();
}
finally
{
_locale.exit();
}
}
public TypeStoreUser change_type ( SchemaType type )
{
_locale.enter();
try
{
Cur c = tempCur();
c.setType( type, false );
c.release();
}
finally
{
_locale.exit();
}
return getUser();
}
public TypeStoreUser substitute ( QName name, SchemaType type )
{
_locale.enter();
try
{
Cur c = tempCur();
c.setSubstitution( name, type, false );
c.release();
}
finally
{
_locale.exit();
}
return getUser();
}
public QName get_xsi_type ( )
{
return getXsiTypeName();
}
public void store_text ( String text )
{
_locale.enter();
TypeStoreUser user = _user;
_user = null;
try
{
Cur c = tempCur();
c.moveNodeContents( null, false );
if (text != null && text.length() > 0)
{
c.next();
c.insertString( text );
}
c.release();
}
finally
{
assert _user == null;
_user = user;
_locale.exit();
}
}
public int compute_flags ( )
{
if (isRoot())
return 0;
TypeStoreUser parentUser = ensureParent().getUser();
if (isAttr())
return parentUser.get_attributeflags( _name );
int f = parentUser.get_elementflags( _name );
if (f != -1)
return f;
TypeStoreVisitor visitor = parentUser.new_visitor();
if (visitor == null)
return 0;
for ( Xobj x = _parent._firstChild ; ; x = x._nextSibling )
{
if (x.isElem())
{
visitor.visit( x._name );
if (x == this)
return visitor.get_elementflags();
}
}
}
public String compute_default_text ( )
{
if (isRoot())
return null;
TypeStoreUser parentUser = ensureParent().getUser();
if (isAttr())
return parentUser.get_default_attribute_text( _name );
String result = parentUser.get_default_element_text( _name );
if (result != null)
return result;
TypeStoreVisitor visitor = parentUser.new_visitor();
if (visitor == null)
return null;
for ( Xobj x = _parent._firstChild ; ; x = x._nextSibling )
{
if (x.isElem())
{
visitor.visit( x._name );
if (x == this)
return visitor.get_default_text();
}
}
}
public boolean find_nil ( )
{
if (isAttr())
return false;
_locale.enter();
try
{
Xobj a = getAttr( Locale._xsiNil );
if (a == null)
return false;
String value = a.getValueAsString( Locale.WS_COLLAPSE );
return value.equals( "true" ) || value.equals( "1" );
}
finally
{
_locale.exit();
}
}
public void invalidate_nil ( )
{
if (isAttr())
return;
_locale.enter();
try
{
if (!_user.build_nil())
removeAttr( Locale._xsiNil );
else
setAttr( Locale._xsiNil, "true" );
}
finally
{
_locale.exit();
}
}
public int count_elements ( QName name )
{
return _locale.count( this, name, null );
}
public int count_elements ( QNameSet names )
{
return _locale.count( this, null, names );
}
public TypeStoreUser find_element_user ( QName name, int i )
{
for ( Xobj x = _firstChild ; x != null ; x = x._nextSibling )
if (x.isElem() && x._name.equals( name ) && --i < 0)
return x.getUser();
return null;
}
public TypeStoreUser find_element_user ( QNameSet names, int i )
{
for ( Xobj x = _firstChild ; x != null ; x = x._nextSibling )
if (x.isElem() && names.contains( x._name ) && --i < 0)
return x.getUser();
return null;
}
public void find_all_element_users ( QName name, List fillMeUp )
{
for ( Xobj x = _firstChild ; x != null ; x = x._nextSibling )
if (x.isElem() && x._name.equals( name ))
fillMeUp.add( x.getUser() );
}
public void find_all_element_users ( QNameSet names, List fillMeUp )
{
for ( Xobj x = _firstChild ; x != null ; x = x._nextSibling )
if (x.isElem() && names.contains( x._name ))
fillMeUp.add( x.getUser() );
}
private static TypeStoreUser insertElement ( QName name, Xobj x, int pos )
{
x._locale.enter();
try
{
Cur c = x._locale.tempCur();
c.moveTo( x, pos );
c.createElement( name );
TypeStoreUser user = c.getUser();
c.release();
return user;
}
finally
{
x._locale.exit();
}
}
public TypeStoreUser insert_element_user ( QName name, int i )
{
if (i < 0)
throw new IndexOutOfBoundsException();
if (!isContainer())
throw new IllegalStateException();
Xobj x = _locale.findNthChildElem( this, name, null, i );
if (x == null)
{
if (i > _locale.count( this, name, null ) + 1)
throw new IndexOutOfBoundsException();
return add_element_user( name );
}
return insertElement( name, x, 0 );
}
public TypeStoreUser insert_element_user ( QNameSet names, QName name, int i )
{
if (i < 0)
throw new IndexOutOfBoundsException();
if (!isContainer())
throw new IllegalStateException();
Xobj x = _locale.findNthChildElem( this, null, names, i );
if (x == null)
{
if (i > _locale.count( this, null, names ) + 1)
throw new IndexOutOfBoundsException();
return add_element_user( name );
}
return insertElement( name, x, 0 );
}
public TypeStoreUser add_element_user ( QName name )
{
if (!isContainer())
throw new IllegalStateException();
QNameSet endSet = null;
boolean gotEndSet = false;
Xobj candidate = null;
for ( Xobj x = _lastChild ; x != null ; x = x._prevSibling )
{
if (x.isContainer())
{
if (x._name.equals( name ))
break;
if (!gotEndSet)
{
endSet = _user.get_element_ending_delimiters( name );
gotEndSet = true;
}
if (endSet == null || endSet.contains( x._name ))
candidate = x;
}
}
return
candidate == null
? insertElement( name, this, END_POS )
: insertElement( name, candidate, 0 );
}
private static void removeElement ( Xobj x )
{
if (x == null)
throw new IndexOutOfBoundsException();
x._locale.enter();
try
{
Cur c = x.tempCur();
c.moveNode( null );
c.release();
}
finally
{
x._locale.exit();
}
}
public void remove_element ( QName name, int i )
{
if (i < 0)
throw new IndexOutOfBoundsException();
if (!isContainer())
throw new IllegalStateException();
Xobj x;
for ( x = _firstChild ; x != null ; x = x._nextSibling )
if (x.isElem() && x._name.equals( name ) && --i < 0)
break;
removeElement( x );
}
public void remove_element ( QNameSet names, int i )
{
if (i < 0)
throw new IndexOutOfBoundsException();
if (!isContainer())
throw new IllegalStateException();
Xobj x;
for ( x = _firstChild ; x != null ; x = x._nextSibling )
if (x.isElem() && names.contains( x._name ) && --i < 0)
break;
removeElement( x );
}
public TypeStoreUser find_attribute_user ( QName name )
{
Xobj a = getAttr( name );
return a == null ? null : a.getUser();
}
public TypeStoreUser add_attribute_user ( QName name )
{
if (getAttr( name ) != null)
throw new IndexOutOfBoundsException();
_locale.enter();
try
{
return setAttr( name, "" ).getUser();
}
finally
{
_locale.exit();
}
}
public void remove_attribute ( QName name )
{
_locale.enter();
try
{
if (!removeAttr( name ))
throw new IndexOutOfBoundsException();
}
finally
{
_locale.exit();
}
}
public TypeStoreUser copy_contents_from ( TypeStore source )
{
Xobj xSrc = (Xobj) source;
if (xSrc == this)
return getUser();
_locale.enter();
try
{
xSrc._locale.enter();
Cur c = tempCur();
try
{
Cur cSrc1 = xSrc.tempCur();
Map sourceNamespaces = Locale.getAllNamespaces( cSrc1, null );
cSrc1.release();
if (isAttr())
{
Cur cSrc = xSrc.tempCur();
String value = Locale.getTextValue( cSrc );
cSrc.release();
c.setValue( value );
}
else
{
// Here I save away the user of this node so that it does not get whacked
// in the following operations.
disconnectChildrenUsers();
assert !inhibitDisconnect();
setBit( INHIBIT_DISCONNECT );
QName xsiType = isContainer() ? getXsiTypeName() : null;
Xobj copy = xSrc.copyNode( _locale );
Cur.moveNodeContents( this, null, true );
c.next();
Cur.moveNodeContents( copy, c, true );
c.moveTo( this );
if (xsiType != null)
c.setXsiType( xsiType );
assert inhibitDisconnect();
clearBit( INHIBIT_DISCONNECT );
}
if (sourceNamespaces != null)
{
if (!c.isContainer())
c.toParent();
Locale.applyNamespaces( c, sourceNamespaces );
}
}
finally
{
c.release();
xSrc._locale.exit();
}
}
finally
{
_locale.exit();
}
return getUser();
}
public TypeStoreUser copy(SchemaTypeLoader stl, SchemaType type, XmlOptions options)
{
//do not use a user's Factory method for copying.
//XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
Xobj destination = null;
options = XmlOptions.maskNull(options);
SchemaType sType = (SchemaType) options.get(XmlOptions.DOCUMENT_TYPE);
if (sType == null)
sType = type == null ? XmlObject.type : type;
Locale locale = this.locale();
if ( Boolean.TRUE.equals(options.get(XmlOptions.COPY_USE_NEW_SYNC_DOMAIN)) )
locale = Locale.getLocale(stl, options);
if (sType.isDocumentType() || (sType.isNoType() && (this instanceof Xobj.DocumentXobj)))
destination = Cur.createDomDocumentRootXobj(locale, false);
else
destination = Cur.createDomDocumentRootXobj(locale, true);
locale.enter();
try
{
Cur c = destination.tempCur();
c.setType(type);
c.release();
}
finally
{
locale.exit();
}
TypeStoreUser tsu = destination.copy_contents_from(this);
return tsu;
}
public void array_setter ( XmlObject[] sources, QName elementName )
{
_locale.enter();
try
{
// TODO - this is the quick and dirty implementation, make this faster
int m = sources.length;
ArrayList copies = new ArrayList();
ArrayList types = new ArrayList();
for ( int i = 0 ; i < m ; i++ )
{
// TODO - deal with null sources[ i ] here -- what to do?
if (sources[ i ] == null)
throw new IllegalArgumentException( "Array element null" );
else if (sources[ i ].isImmutable())
{
copies.add( null );
types.add( null );
}
else
{
Xobj x = ((Xobj) ((TypeStoreUser) sources[ i ]).get_store());
if (x._locale == _locale)
copies.add( x.copyNode( _locale ) );
else
{
x._locale.enter();
try
{
copies.add( x.copyNode( _locale ) );
}
finally
{
x._locale.exit();
}
}
types.add( sources[ i ].schemaType() );
}
}
int n = count_elements( elementName );
for ( ; n > m ; n-- )
remove_element( elementName, m );
for ( ; m > n ; n++ )
add_element_user( elementName );
assert m == n;
ArrayList elements = new ArrayList();
find_all_element_users( elementName, elements );
for ( int i = 0 ; i < elements.size() ; i++ )
elements.set( i, (Xobj) ((TypeStoreUser) elements.get( i )).get_store() );
assert elements.size() == n;
Cur c = tempCur();
for ( int i = 0 ; i < n ; i++ )
{
Xobj x = (Xobj) elements.get( i );
if (sources[ i ].isImmutable())
x.getObject().set( sources[ i ] );
else
{
Cur.moveNodeContents( x, null, true );
c.moveTo( x );
c.next();
Cur.moveNodeContents( (Xobj) copies.get( i ), c, true );
x.change_type( (SchemaType) types.get( i ) );
}
}
c.release();
}
finally
{
_locale.exit();
}
}
public void visit_elements ( TypeStoreVisitor visitor )
{
throw new RuntimeException( "Not implemeneted" );
}
public XmlObject[] exec_query ( String queryExpr, XmlOptions options ) throws XmlException
{
_locale.enter();
try
{
Cur c = tempCur();
XmlObject[] result = Query.objectExecQuery( c, queryExpr, options );
c.release();
return result;
}
finally
{
_locale.exit();
}
}
public String find_prefix_for_nsuri ( String nsuri, String suggested_prefix )
{
_locale.enter();
try
{
return prefixForNamespace( nsuri, suggested_prefix, true );
}
finally
{
_locale.exit();
}
}
public String getNamespaceForPrefix ( String prefix )
{
return namespaceForPrefix( prefix, true );
}
//
//
//
abstract static class NodeXobj extends Xobj implements Dom, Node, NodeList
{
NodeXobj ( Locale l, int kind, int domType )
{
super( l, kind, domType );
}
Dom getDom ( ) { return this; }
//
//
//
public int getLength ( ) { return DomImpl._childNodes_getLength( this ); }
public Node item ( int i ) { return DomImpl._childNodes_item( this, i ); }
public Node appendChild ( Node newChild ) { return DomImpl._node_appendChild( this, newChild ); }
public Node cloneNode ( boolean deep ) { return DomImpl._node_cloneNode( this, deep ); }
public NamedNodeMap getAttributes ( ) { return null; }
public NodeList getChildNodes ( ) { return this; }
public Node getParentNode ( ) { return DomImpl._node_getParentNode( this ); }
public Node removeChild ( Node oldChild ) { return DomImpl._node_removeChild( this, oldChild ); }
public Node getFirstChild ( ) { return DomImpl._node_getFirstChild( this ); }
public Node getLastChild ( ) { return DomImpl._node_getLastChild( this ); }
public String getLocalName ( ) { return DomImpl._node_getLocalName( this ); }
public String getNamespaceURI ( ) { return DomImpl._node_getNamespaceURI( this ); }
public Node getNextSibling ( ) { return DomImpl._node_getNextSibling( this ); }
public String getNodeName ( ) { return DomImpl._node_getNodeName( this ); }
public short getNodeType ( ) { return DomImpl._node_getNodeType( this ); }
public String getNodeValue ( ) { return DomImpl._node_getNodeValue( this ); }
public Document getOwnerDocument ( ) { return DomImpl._node_getOwnerDocument( this ); }
public String getPrefix ( ) { return DomImpl._node_getPrefix( this ); }
public Node getPreviousSibling ( ) { return DomImpl._node_getPreviousSibling( this ); }
public boolean hasAttributes ( ) { return DomImpl._node_hasAttributes( this ); }
public boolean hasChildNodes ( ) { return DomImpl._node_hasChildNodes( this ); }
public Node insertBefore ( Node newChild, Node refChild ) { return DomImpl._node_insertBefore( this, newChild, refChild ); }
public boolean isSupported ( String feature, String version ) { return DomImpl._node_isSupported( this, feature, version ); }
public void normalize ( ) { DomImpl._node_normalize( this ); }
public Node replaceChild ( Node newChild, Node oldChild ) { return DomImpl._node_replaceChild( this, newChild, oldChild ); }
public void setNodeValue ( String nodeValue ) { DomImpl._node_setNodeValue( this, nodeValue ); }
public void setPrefix ( String prefix ) { DomImpl._node_setPrefix( this, prefix ); }
public boolean nodeCanHavePrefixUri( ){ return false; }
// DOM Level 3
public Object getUserData ( String key ) { return DomImpl._node_getUserData( this, key ); }
public Object setUserData ( String key, Object data, UserDataHandler handler ) { return DomImpl._node_setUserData( this, key, data, handler ); }
public Object getFeature ( String feature, String version ) { return DomImpl._node_getFeature( this, feature, version ); }
public boolean isEqualNode ( Node arg ) { return DomImpl._node_isEqualNode( this, arg ); }
public boolean isSameNode ( Node arg ) { return DomImpl._node_isSameNode( this, arg ); }
public String lookupNamespaceURI ( String prefix ) { return DomImpl._node_lookupNamespaceURI( this, prefix ); }
public String lookupPrefix ( String namespaceURI ) { return DomImpl._node_lookupPrefix( this, namespaceURI ); }
public boolean isDefaultNamespace ( String namespaceURI ) { return DomImpl._node_isDefaultNamespace( this, namespaceURI ); }
public void setTextContent ( String textContent ) { DomImpl._node_setTextContent( this, textContent ); }
public String getTextContent ( ) { return DomImpl._node_getTextContent( this ); }
public short compareDocumentPosition ( Node other ) { return DomImpl._node_compareDocumentPosition( this, other ); }
public String getBaseURI ( ) { return DomImpl._node_getBaseURI( this ); }
}
static class DocumentXobj extends NodeXobj implements Document
{
DocumentXobj ( Locale l )
{
super( l, ROOT, DomImpl.DOCUMENT );
}
Xobj newNode ( Locale l ) { return new DocumentXobj( l ); }
//
//
//
public Attr createAttribute ( String name ) { return DomImpl._document_createAttribute( this, name ); }
public Attr createAttributeNS ( String namespaceURI, String qualifiedName ) { return DomImpl._document_createAttributeNS( this, namespaceURI, qualifiedName ); }
public CDATASection createCDATASection ( String data ) { return DomImpl._document_createCDATASection( this, data ); }
public Comment createComment ( String data ) { return DomImpl._document_createComment( this, data ); }
public DocumentFragment createDocumentFragment ( ) { return DomImpl._document_createDocumentFragment( this ); }
public Element createElement ( String tagName ) { return DomImpl._document_createElement( this, tagName ); }
public Element createElementNS ( String namespaceURI, String qualifiedName ) { return DomImpl._document_createElementNS( this, namespaceURI, qualifiedName ); }
public EntityReference createEntityReference ( String name ) { return DomImpl._document_createEntityReference( this, name ); }
public ProcessingInstruction createProcessingInstruction ( String target, String data ) { return DomImpl._document_createProcessingInstruction( this, target, data ); }
public Text createTextNode ( String data ) { return DomImpl._document_createTextNode( this, data ); }
public DocumentType getDoctype ( ) { return DomImpl._document_getDoctype( this ); }
public Element getDocumentElement ( ) { return DomImpl._document_getDocumentElement( this ); }
public Element getElementById ( String elementId ) {
if ( _idToElement == null )return null;
Xobj o = (Xobj) _idToElement.get(elementId);
if (o == null) return null;
if (!isInSameTree(o))
{
_idToElement.remove(elementId);
}
return (Element)o;
}
public NodeList getElementsByTagName ( String tagname ) { return DomImpl._document_getElementsByTagName( this, tagname ); }
public NodeList getElementsByTagNameNS ( String namespaceURI, String localName ) { return DomImpl._document_getElementsByTagNameNS( this, namespaceURI, localName ); }
public DOMImplementation getImplementation ( ) { return DomImpl._document_getImplementation( this ); }
public Node importNode ( Node importedNode, boolean deep ) { return DomImpl._document_importNode( this, importedNode, deep ); }
// DOM Level 3
public Node adoptNode ( Node source ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getDocumentURI ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public DOMConfiguration getDomConfig ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getInputEncoding ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public boolean getStrictErrorChecking ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getXmlEncoding ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public boolean getXmlStandalone ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getXmlVersion ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void normalizeDocument ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public Node renameNode ( Node n, String namespaceURI, String qualifiedName ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setDocumentURI ( String documentURI ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setStrictErrorChecking ( boolean strictErrorChecking ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setXmlStandalone ( boolean xmlStandalone ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setXmlVersion ( String xmlVersion ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
protected void addIdElement( String idVal, Dom e){
if ( _idToElement == null)
_idToElement = new java.util.Hashtable();
_idToElement.put(idVal,e);
}
void removeIdElement( String idVal ){
if (_idToElement != null)
_idToElement.remove(idVal);
}
private java.util.Hashtable _idToElement;
}
static class DocumentFragXobj extends NodeXobj implements DocumentFragment
{
DocumentFragXobj ( Locale l ) { super( l, ROOT, DomImpl.DOCFRAG ); }
Xobj newNode ( Locale l ) { return new DocumentFragXobj( l ); }
}
final static class ElementAttributes implements NamedNodeMap
{
ElementAttributes ( ElementXobj elementXobj )
{
_elementXobj = elementXobj;
}
public int getLength ( ) { return DomImpl._attributes_getLength( _elementXobj ); }
public Node getNamedItem ( String name ) { return DomImpl._attributes_getNamedItem ( _elementXobj, name ); }
public Node getNamedItemNS ( String namespaceURI, String localName ) { return DomImpl._attributes_getNamedItemNS ( _elementXobj, namespaceURI, localName ); }
public Node item ( int index ) { return DomImpl._attributes_item ( _elementXobj, index ); }
public Node removeNamedItem ( String name ) { return DomImpl._attributes_removeNamedItem ( _elementXobj, name ); }
public Node removeNamedItemNS ( String namespaceURI, String localName ) { return DomImpl._attributes_removeNamedItemNS ( _elementXobj, namespaceURI, localName ); }
public Node setNamedItem ( Node arg ) { return DomImpl._attributes_setNamedItem ( _elementXobj, arg ); }
public Node setNamedItemNS ( Node arg ) { return DomImpl._attributes_setNamedItemNS ( _elementXobj, arg ); }
private ElementXobj _elementXobj;
}
static abstract class NamedNodeXobj extends NodeXobj
{
NamedNodeXobj ( Locale l, int kind, int domType )
{
super( l, kind, domType );
_canHavePrefixUri = true;
}
public boolean nodeCanHavePrefixUri( ){ return _canHavePrefixUri; }
boolean _canHavePrefixUri;
}
static class ElementXobj extends NamedNodeXobj implements Element
{
ElementXobj ( Locale l, QName name )
{
super( l, ELEM, DomImpl.ELEMENT );
_name = name;
}
Xobj newNode ( Locale l ) { return new ElementXobj( l, _name ); }
//
//
//
public NamedNodeMap getAttributes ( )
{
if (_attributes == null)
_attributes = new ElementAttributes( this );
return _attributes;
}
public String getAttribute ( String name ) { return DomImpl._element_getAttribute( this, name ); }
public Attr getAttributeNode ( String name ) { return DomImpl._element_getAttributeNode( this, name ); }
public Attr getAttributeNodeNS ( String namespaceURI, String localName ) { return DomImpl._element_getAttributeNodeNS( this, namespaceURI, localName ); }
public String getAttributeNS ( String namespaceURI, String localName ) { return DomImpl._element_getAttributeNS( this, namespaceURI, localName ); }
public NodeList getElementsByTagName ( String name ) { return DomImpl._element_getElementsByTagName( this, name ); }
public NodeList getElementsByTagNameNS ( String namespaceURI, String localName ) { return DomImpl._element_getElementsByTagNameNS( this, namespaceURI, localName ); }
public String getTagName ( ) { return DomImpl._element_getTagName( this ); }
public boolean hasAttribute ( String name ) { return DomImpl._element_hasAttribute( this, name ); }
public boolean hasAttributeNS ( String namespaceURI, String localName ) { return DomImpl._element_hasAttributeNS( this, namespaceURI, localName ); }
public void removeAttribute ( String name ) { DomImpl._element_removeAttribute( this, name ); }
public Attr removeAttributeNode ( Attr oldAttr ) { return DomImpl._element_removeAttributeNode( this, oldAttr ); }
public void removeAttributeNS ( String namespaceURI, String localName ) { DomImpl._element_removeAttributeNS( this, namespaceURI, localName ); }
public void setAttribute ( String name, String value ) { DomImpl._element_setAttribute( this, name, value ); }
public Attr setAttributeNode ( Attr newAttr ) { return DomImpl._element_setAttributeNode( this, newAttr ); }
public Attr setAttributeNodeNS ( Attr newAttr ) { return DomImpl._element_setAttributeNodeNS( this, newAttr ); }
public void setAttributeNS ( String namespaceURI, String qualifiedName, String value ) { DomImpl._element_setAttributeNS( this, namespaceURI, qualifiedName, value ); }
// DOM Level 3
public TypeInfo getSchemaTypeInfo ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setIdAttribute ( String name, boolean isId ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setIdAttributeNS ( String namespaceURI, String localName, boolean isId ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setIdAttributeNode ( Attr idAttr, boolean isId ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
private ElementAttributes _attributes;
}
static class AttrXobj extends NamedNodeXobj implements Attr
{
AttrXobj ( Locale l, QName name )
{
super( l, ATTR, DomImpl.ATTR );
_name = name;
}
Xobj newNode ( Locale l ) { return new AttrXobj( l, _name ); }
//
public Node getNextSibling ( ) { return null; }
//
public String getName ( ) { return DomImpl._node_getNodeName( this ); }
public Element getOwnerElement ( ) { return DomImpl._attr_getOwnerElement( this ); }
public boolean getSpecified ( ) { return DomImpl._attr_getSpecified( this ); }
public String getValue ( ) { return DomImpl._node_getNodeValue( this ); }
public void setValue ( String value ) { DomImpl._node_setNodeValue( this, value ); }
// DOM Level 3
public TypeInfo getSchemaTypeInfo ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public boolean isId ( ) { return false; }
}
static class AttrIdXobj
extends AttrXobj
{
AttrIdXobj ( Locale l, QName name )
{
super( l, name );
}
public boolean isId()
{
return true;
}
}
static class CommentXobj extends NodeXobj implements Comment
{
CommentXobj ( Locale l ) { super( l, COMMENT, DomImpl.COMMENT ); }
Xobj newNode ( Locale l ) { return new CommentXobj( l ); }
public NodeList getChildNodes ( ) { return DomImpl._emptyNodeList; }
public void appendData ( String arg ) { DomImpl._characterData_appendData( this, arg ); }
public void deleteData ( int offset, int count ) { DomImpl._characterData_deleteData( this, offset, count ); }
public String getData ( ) { return DomImpl._characterData_getData( this ); }
public int getLength ( ) { return DomImpl._characterData_getLength( this ); }
public Node getFirstChild ( ) { return null; }
public void insertData ( int offset, String arg ) { DomImpl._characterData_insertData( this, offset, arg ); }
public void replaceData ( int offset, int count, String arg ) { DomImpl._characterData_replaceData( this, offset, count, arg ); }
public void setData ( String data ) { DomImpl._characterData_setData( this, data ); }
public String substringData ( int offset, int count ) { return DomImpl._characterData_substringData( this, offset, count ); }
}
static class ProcInstXobj extends NodeXobj implements ProcessingInstruction
{
ProcInstXobj ( Locale l, String target )
{
super( l, PROCINST, DomImpl.PROCINST );
_name = _locale.makeQName( null, target );
}
Xobj newNode ( Locale l ) { return new ProcInstXobj( l, _name.getLocalPart() ); }
public int getLength ( ) { return 0; }
public Node getFirstChild ( ) { return null; }
public String getData ( ) { return DomImpl._processingInstruction_getData( this ); }
public String getTarget ( ) { return DomImpl._processingInstruction_getTarget( this ); }
public void setData ( String data ) { DomImpl._processingInstruction_setData( this, data ); }
}
//
// SAAJ objects
//
static class SoapPartDocXobj extends DocumentXobj
{
SoapPartDocXobj ( Locale l )
{
super(l);
//super( l, ROOT, DomImpl.DOCUMENT );
_soapPartDom = new SoapPartDom( this );
}
Dom getDom ( ) { return _soapPartDom; }
Xobj newNode ( Locale l ) { return new SoapPartDocXobj( l ); }
SoapPartDom _soapPartDom;
}
static class SoapPartDom extends SOAPPart implements Dom, Document, NodeList
{
SoapPartDom ( SoapPartDocXobj docXobj )
{
_docXobj = docXobj;
}
public int nodeType ( ) { return DomImpl.DOCUMENT; }
public Locale locale ( ) { return _docXobj._locale; }
public Cur tempCur ( ) { return _docXobj.tempCur(); }
public QName getQName ( ) { return _docXobj._name; }
public void dump ( ) { dump( System.out ); }
public void dump ( PrintStream o ) { _docXobj.dump( o ); }
public void dump ( PrintStream o, Object ref ) { _docXobj.dump( o, ref ); }
public String name ( ) { return "#document"; }
public Node appendChild ( Node newChild ) { return DomImpl._node_appendChild( this, newChild ); }
public Node cloneNode ( boolean deep ) { return DomImpl._node_cloneNode( this, deep ); }
public NamedNodeMap getAttributes ( ) { return null; }
public NodeList getChildNodes ( ) { return this; }
public Node getParentNode ( ) { return DomImpl._node_getParentNode( this ); }
public Node removeChild ( Node oldChild ) { return DomImpl._node_removeChild( this, oldChild ); }
public Node getFirstChild ( ) { return DomImpl._node_getFirstChild( this ); }
public Node getLastChild ( ) { return DomImpl._node_getLastChild( this ); }
public String getLocalName ( ) { return DomImpl._node_getLocalName( this ); }
public String getNamespaceURI ( ) { return DomImpl._node_getNamespaceURI( this ); }
public Node getNextSibling ( ) { return DomImpl._node_getNextSibling( this ); }
public String getNodeName ( ) { return DomImpl._node_getNodeName( this ); }
public short getNodeType ( ) { return DomImpl._node_getNodeType( this ); }
public String getNodeValue ( ) { return DomImpl._node_getNodeValue( this ); }
public Document getOwnerDocument ( ) { return DomImpl._node_getOwnerDocument( this ); }
public String getPrefix ( ) { return DomImpl._node_getPrefix( this ); }
public Node getPreviousSibling ( ) { return DomImpl._node_getPreviousSibling( this ); }
public boolean hasAttributes ( ) { return DomImpl._node_hasAttributes( this ); }
public boolean hasChildNodes ( ) { return DomImpl._node_hasChildNodes( this ); }
public Node insertBefore ( Node newChild, Node refChild ) { return DomImpl._node_insertBefore( this, newChild, refChild ); }
public boolean isSupported ( String feature, String version ) { return DomImpl._node_isSupported( this, feature, version ); }
public void normalize ( ) { DomImpl._node_normalize( this ); }
public Node replaceChild ( Node newChild, Node oldChild ) { return DomImpl._node_replaceChild( this, newChild, oldChild ); }
public void setNodeValue ( String nodeValue ) { DomImpl._node_setNodeValue( this, nodeValue ); }
public void setPrefix ( String prefix ) { DomImpl._node_setPrefix( this, prefix ); }
// DOM Level 3
public Object getUserData ( String key ) { return DomImpl._node_getUserData( this, key ); }
public Object setUserData ( String key, Object data, UserDataHandler handler ) { return DomImpl._node_setUserData( this, key, data, handler ); }
public Object getFeature ( String feature, String version ) { return DomImpl._node_getFeature( this, feature, version ); }
public boolean isEqualNode ( Node arg ) { return DomImpl._node_isEqualNode( this, arg ); }
public boolean isSameNode ( Node arg ) { return DomImpl._node_isSameNode( this, arg ); }
public String lookupNamespaceURI ( String prefix ) { return DomImpl._node_lookupNamespaceURI( this, prefix ); }
public String lookupPrefix ( String namespaceURI ) { return DomImpl._node_lookupPrefix( this, namespaceURI ); }
public boolean isDefaultNamespace ( String namespaceURI ) { return DomImpl._node_isDefaultNamespace( this, namespaceURI ); }
public void setTextContent ( String textContent ) { DomImpl._node_setTextContent( this, textContent ); }
public String getTextContent ( ) { return DomImpl._node_getTextContent( this ); }
public short compareDocumentPosition ( Node other ) { return DomImpl._node_compareDocumentPosition( this, other ); }
public String getBaseURI ( ) { return DomImpl._node_getBaseURI( this ); }
public Node adoptNode ( Node source ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getDocumentURI ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public DOMConfiguration getDomConfig ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getInputEncoding ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public boolean getStrictErrorChecking ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getXmlEncoding ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public boolean getXmlStandalone ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public String getXmlVersion ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void normalizeDocument ( ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public Node renameNode ( Node n, String namespaceURI, String qualifiedName ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setDocumentURI ( String documentURI ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setStrictErrorChecking ( boolean strictErrorChecking ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setXmlStandalone ( boolean xmlStandalone ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public void setXmlVersion ( String xmlVersion ) { throw new RuntimeException( "DOM Level 3 Not implemented" ); }
public Attr createAttribute ( String name ) { return DomImpl._document_createAttribute( this, name ); }
public Attr createAttributeNS ( String namespaceURI, String qualifiedName ) { return DomImpl._document_createAttributeNS( this, namespaceURI, qualifiedName ); }
public CDATASection createCDATASection ( String data ) { return DomImpl._document_createCDATASection( this, data ); }
public Comment createComment ( String data ) { return DomImpl._document_createComment( this, data ); }
public DocumentFragment createDocumentFragment ( ) { return DomImpl._document_createDocumentFragment( this ); }
public Element createElement ( String tagName ) { return DomImpl._document_createElement( this, tagName ); }
public Element createElementNS ( String namespaceURI, String qualifiedName ) { return DomImpl._document_createElementNS( this, namespaceURI, qualifiedName ); }
public EntityReference createEntityReference ( String name ) { return DomImpl._document_createEntityReference( this, name ); }
public ProcessingInstruction createProcessingInstruction ( String target, String data ) { return DomImpl._document_createProcessingInstruction( this, target, data ); }
public Text createTextNode ( String data ) { return DomImpl._document_createTextNode( this, data ); }
public DocumentType getDoctype ( ) { return DomImpl._document_getDoctype( this ); }
public Element getDocumentElement ( ) { return DomImpl._document_getDocumentElement( this ); }
public Element getElementById ( String elementId ) { return DomImpl._document_getElementById( this, elementId ); }
public NodeList getElementsByTagName ( String tagname ) { return DomImpl._document_getElementsByTagName( this, tagname ); }
public NodeList getElementsByTagNameNS ( String namespaceURI, String localName ) { return DomImpl._document_getElementsByTagNameNS( this, namespaceURI, localName ); }
public DOMImplementation getImplementation ( ) { return DomImpl._document_getImplementation( this ); }
public Node importNode ( Node importedNode, boolean deep ) { return DomImpl._document_importNode( this, importedNode, deep ); }
public int getLength ( ) { return DomImpl._childNodes_getLength( this ); }
public Node item ( int i ) { return DomImpl._childNodes_item( this, i ); }
public void removeAllMimeHeaders ( ) { DomImpl._soapPart_removeAllMimeHeaders( this ); }
public void removeMimeHeader ( String name ) { DomImpl._soapPart_removeMimeHeader( this, name ); }
public Iterator getAllMimeHeaders ( ) { return DomImpl._soapPart_getAllMimeHeaders( this ); }
public SOAPEnvelope getEnvelope ( ) { return DomImpl._soapPart_getEnvelope( this ); }
public Source getContent ( ) { return DomImpl._soapPart_getContent( this ); }
public void setContent ( Source source ) { DomImpl._soapPart_setContent( this, source ); }
public String[] getMimeHeader ( String name ) { return DomImpl._soapPart_getMimeHeader( this, name ); }
public void addMimeHeader ( String name, String value ) { DomImpl._soapPart_addMimeHeader( this, name,value ); }
public void setMimeHeader ( String name, String value ) { DomImpl._soapPart_setMimeHeader( this, name, value ); }
public Iterator getMatchingMimeHeaders ( String[] names ) { return DomImpl._soapPart_getMatchingMimeHeaders( this, names ); }
public Iterator getNonMatchingMimeHeaders ( String[] names ) { return DomImpl._soapPart_getNonMatchingMimeHeaders( this, names ); }
public boolean nodeCanHavePrefixUri( ){ return true; }
SoapPartDocXobj _docXobj;
}
static class SoapElementXobj
extends ElementXobj implements SOAPElement, org.apache.xmlbeans.impl.soap.Node
{
SoapElementXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapElementXobj( l, _name ); }
public void detachNode ( ) { DomImpl._soapNode_detachNode( this ); }
public void recycleNode ( ) { DomImpl._soapNode_recycleNode( this ); }
public String getValue ( ) { return DomImpl._soapNode_getValue( this ); }
public void setValue ( String value ) { DomImpl._soapNode_setValue( this, value ); }
public SOAPElement getParentElement ( ) { return DomImpl._soapNode_getParentElement( this ); }
public void setParentElement ( SOAPElement p ) { DomImpl._soapNode_setParentElement( this, p ); }
public void removeContents ( ) { DomImpl._soapElement_removeContents( this ); }
public String getEncodingStyle ( ) { return DomImpl._soapElement_getEncodingStyle( this ); }
public void setEncodingStyle ( String encodingStyle ) { DomImpl._soapElement_setEncodingStyle( this, encodingStyle ); }
public boolean removeNamespaceDeclaration ( String prefix ) { return DomImpl._soapElement_removeNamespaceDeclaration( this, prefix ); }
public Iterator getAllAttributes ( ) { return DomImpl._soapElement_getAllAttributes( this ); }
public Iterator getChildElements ( ) { return DomImpl._soapElement_getChildElements( this ); }
public Iterator getNamespacePrefixes ( ) { return DomImpl._soapElement_getNamespacePrefixes( this ); }
public SOAPElement addAttribute ( Name name, String value ) throws SOAPException { return DomImpl._soapElement_addAttribute( this, name, value ); }
public SOAPElement addChildElement ( SOAPElement oldChild ) throws SOAPException { return DomImpl._soapElement_addChildElement( this, oldChild ); }
public SOAPElement addChildElement ( Name name ) throws SOAPException { return DomImpl._soapElement_addChildElement( this, name ); }
public SOAPElement addChildElement ( String localName ) throws SOAPException { return DomImpl._soapElement_addChildElement( this, localName ); }
public SOAPElement addChildElement ( String localName, String prefix ) throws SOAPException { return DomImpl._soapElement_addChildElement( this, localName, prefix ); }
public SOAPElement addChildElement ( String localName, String prefix, String uri ) throws SOAPException { return DomImpl._soapElement_addChildElement( this, localName, prefix, uri ); }
public SOAPElement addNamespaceDeclaration ( String prefix, String uri ) { return DomImpl._soapElement_addNamespaceDeclaration( this, prefix, uri ); }
public SOAPElement addTextNode ( String data ) { return DomImpl._soapElement_addTextNode( this, data ); }
public String getAttributeValue ( Name name ) { return DomImpl._soapElement_getAttributeValue( this, name ); }
public Iterator getChildElements ( Name name ) { return DomImpl._soapElement_getChildElements( this, name ); }
public Name getElementName ( ) { return DomImpl._soapElement_getElementName( this ); }
public String getNamespaceURI ( String prefix ) { return DomImpl._soapElement_getNamespaceURI( this, prefix ); }
public Iterator getVisibleNamespacePrefixes ( ) { return DomImpl._soapElement_getVisibleNamespacePrefixes( this ); }
public boolean removeAttribute ( Name name ) { return DomImpl._soapElement_removeAttribute( this, name ); }
}
static class SoapBodyXobj extends SoapElementXobj implements SOAPBody
{
SoapBodyXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapBodyXobj( l, _name ); }
public boolean hasFault ( ) { return DomImpl.soapBody_hasFault( this ); }
public SOAPFault addFault ( ) throws SOAPException { return DomImpl.soapBody_addFault( this ); }
public SOAPFault getFault ( ) { return DomImpl.soapBody_getFault( this ); }
public SOAPBodyElement addBodyElement ( Name name ) { return DomImpl.soapBody_addBodyElement( this, name ); }
public SOAPBodyElement addDocument ( Document document ) { return DomImpl.soapBody_addDocument( this, document ); }
public SOAPFault addFault ( Name name, String s ) throws SOAPException { return DomImpl.soapBody_addFault( this, name, s ); }
public SOAPFault addFault ( Name faultCode, String faultString, java.util.Locale locale ) throws SOAPException { return DomImpl.soapBody_addFault( this, faultCode, faultString, locale ); }
}
static class SoapBodyElementXobj extends SoapElementXobj implements SOAPBodyElement
{
SoapBodyElementXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapBodyElementXobj( l, _name ); }
}
static class SoapEnvelopeXobj extends SoapElementXobj implements SOAPEnvelope
{
SoapEnvelopeXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapEnvelopeXobj( l, _name ); }
public SOAPBody addBody ( ) throws SOAPException { return DomImpl._soapEnvelope_addBody( this ); }
public SOAPBody getBody ( ) throws SOAPException { return DomImpl._soapEnvelope_getBody( this ); }
public SOAPHeader getHeader ( ) throws SOAPException { return DomImpl._soapEnvelope_getHeader( this ); }
public SOAPHeader addHeader ( ) throws SOAPException { return DomImpl._soapEnvelope_addHeader( this ); }
public Name createName ( String localName ) { return DomImpl._soapEnvelope_createName( this, localName ); }
public Name createName ( String localName, String prefix, String namespaceURI ) { return DomImpl._soapEnvelope_createName( this, localName, prefix, namespaceURI ); }
}
static class SoapHeaderXobj extends SoapElementXobj implements SOAPHeader
{
SoapHeaderXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapHeaderXobj( l, _name ); }
public Iterator examineAllHeaderElements ( ) { return DomImpl.soapHeader_examineAllHeaderElements( this ); }
public Iterator extractAllHeaderElements ( ) { return DomImpl.soapHeader_extractAllHeaderElements( this ); }
public Iterator examineHeaderElements ( String actor ) { return DomImpl.soapHeader_examineHeaderElements( this, actor ); }
public Iterator examineMustUnderstandHeaderElements ( String mustUnderstandString ) { return DomImpl.soapHeader_examineMustUnderstandHeaderElements( this, mustUnderstandString ); }
public Iterator extractHeaderElements ( String actor ) { return DomImpl.soapHeader_extractHeaderElements( this, actor ); }
public SOAPHeaderElement addHeaderElement ( Name name ) { return DomImpl.soapHeader_addHeaderElement( this, name ); }
}
static class SoapHeaderElementXobj extends SoapElementXobj implements SOAPHeaderElement
{
SoapHeaderElementXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapHeaderElementXobj( l, _name ); }
public void setMustUnderstand ( boolean mustUnderstand ) { DomImpl.soapHeaderElement_setMustUnderstand( this, mustUnderstand ); }
public boolean getMustUnderstand ( ) { return DomImpl.soapHeaderElement_getMustUnderstand( this ); }
public void setActor ( String actor ) { DomImpl.soapHeaderElement_setActor( this, actor ); }
public String getActor ( ) { return DomImpl.soapHeaderElement_getActor( this ); }
}
static class SoapFaultXobj extends SoapBodyElementXobj implements SOAPFault
{
SoapFaultXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapFaultXobj( l, _name ); }
public void setFaultString ( String faultString ) { DomImpl.soapFault_setFaultString( this, faultString ); }
public void setFaultString ( String faultString, java.util.Locale locale ) { DomImpl.soapFault_setFaultString( this, faultString, locale ); }
public void setFaultCode ( Name faultCodeName ) throws SOAPException { DomImpl.soapFault_setFaultCode( this, faultCodeName ); }
public void setFaultActor ( String faultActorString ) { DomImpl.soapFault_setFaultActor( this, faultActorString ); }
public String getFaultActor ( ) { return DomImpl.soapFault_getFaultActor( this ); }
public String getFaultCode ( ) { return DomImpl.soapFault_getFaultCode( this ); }
public void setFaultCode ( String faultCode ) throws SOAPException { DomImpl.soapFault_setFaultCode( this, faultCode ); }
public java.util.Locale getFaultStringLocale ( ) { return DomImpl.soapFault_getFaultStringLocale( this ); }
public Name getFaultCodeAsName ( ) { return DomImpl.soapFault_getFaultCodeAsName( this ); }
public String getFaultString ( ) { return DomImpl.soapFault_getFaultString( this ); }
public Detail addDetail ( ) throws SOAPException { return DomImpl.soapFault_addDetail( this ); }
public Detail getDetail ( ) { return DomImpl.soapFault_getDetail( this ); }
}
static class SoapFaultElementXobj extends SoapElementXobj implements SOAPFaultElement
{
SoapFaultElementXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new SoapFaultElementXobj( l, _name ); }
}
static class DetailXobj extends SoapFaultElementXobj implements Detail
{
DetailXobj ( Locale l, QName name ) { super( l, name ); }
Xobj newNode ( Locale l ) { return new DetailXobj( l, _name ); }
public DetailEntry addDetailEntry ( Name name ) { return DomImpl.detail_addDetailEntry( this, name ); }
public Iterator getDetailEntries ( ) { return DomImpl.detail_getDetailEntries( this ); }
}
static class DetailEntryXobj extends SoapElementXobj implements DetailEntry
{
Xobj newNode ( Locale l ) { return new DetailEntryXobj( l, _name ); }
DetailEntryXobj ( Locale l, QName name ) { super( l, name ); }
}
//
//
//
static class Bookmark implements XmlMark
{
boolean isOnList ( Bookmark head )
{
for ( ; head != null ; head = head._next )
if (head == this)
return true;
return false;
}
Bookmark listInsert ( Bookmark head )
{
assert _next == null && _prev == null;
if (head == null)
head = _prev = this;
else
{
_prev = head._prev;
head._prev = head._prev._next = this;
}
return head;
}
Bookmark listRemove ( Bookmark head )
{
assert _prev != null && isOnList( head );
if (_prev == this)
head = null;
else
{
if (head == this)
head = _next;
else
_prev._next = _next;
if (_next == null)
head._prev = _prev;
else
{
_next._prev = _prev;
_next = null;
}
}
_prev = null;
assert _next == null;
return head;
}
void moveTo ( Xobj x, int p )
{
assert isOnList( _xobj._bookmarks );
if (_xobj != x)
{
_xobj._bookmarks = listRemove( _xobj._bookmarks );
x._bookmarks = listInsert( x._bookmarks );
_xobj = x;
}
_pos = p;
}
//
// XmlCursor.XmlMark method
//
public XmlCursor createCursor ( )
{
if (_xobj == null)
{
throw new IllegalStateException(
"Attempting to create a cursor on a bookmark that " +
"has been cleared or replaced.");
}
return Cursor.newCursor( _xobj, _pos );
}
//
//
//
Xobj _xobj;
int _pos;
Bookmark _next;
Bookmark _prev;
Object _key;
Object _value;
}
//
//
//
Locale _locale;
QName _name;
Cur _embedded;
Bookmark _bookmarks;
int _bits;
Xobj _parent;
Xobj _nextSibling;
Xobj _prevSibling;
Xobj _firstChild;
Xobj _lastChild;
Object _srcValue, _srcAfter;
int _offValue, _offAfter;
int _cchValue, _cchAfter;
// TODO - put this in a ptr off this node
CharNode _charNodesValue;
CharNode _charNodesAfter;
// TODO - put this in a ptr off this node
TypeStoreUser _user;
}
xmlbeans-2.6.0/src/store/org/apache/xmlbeans/impl/store/CharUtil.java 0000644 0001750 0001750 00000065124 11361341572 023702 0 ustar apo apo /* 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.impl.store;
import java.io.PrintStream;
import java.lang.ref.SoftReference;
public final class CharUtil
{
public CharUtil ( int charBufSize )
{
_charBufSize = charBufSize;
}
public CharIterator getCharIterator ( Object src, int off, int cch )
{
_charIter.init( src, off, cch );
return _charIter;
}
public CharIterator getCharIterator ( Object src, int off, int cch, int start )
{
_charIter.init( src, off, cch, start );
return _charIter;
}
public static CharUtil getThreadLocalCharUtil ( )
{
SoftReference softRef = (SoftReference)tl_charUtil.get();
CharUtil charUtil = (CharUtil) softRef.get();
if (charUtil==null)
{
charUtil = new CharUtil( CHARUTIL_INITIAL_BUFSIZE );
tl_charUtil.set(new SoftReference(charUtil));
}
return charUtil;
}
public static void getString ( StringBuffer sb, Object src, int off, int cch )
{
assert isValid( src, off, cch );
if (cch == 0)
return;
if (src instanceof char[])
sb.append( (char[]) src, off, cch );
else if (src instanceof String)
{
String s = (String) src;
if (off == 0 && cch == s.length())
sb.append( (String) src );
else
sb.append( s.substring( off, off + cch ) );
}
else
((CharJoin) src).getString( sb, off, cch );
}
public static void getChars ( char[] chars, int start, Object src, int off, int cch )
{
assert isValid( src, off, cch );
assert chars != null && start >= 0 && start <= chars.length;
if (cch == 0)
return;
if (src instanceof char[])
System.arraycopy( (char[]) src, off, chars, start, cch );
else if (src instanceof String)
((String) src).getChars( off, off + cch, chars, start );
else
((CharJoin) src).getChars( chars, start, off, cch );
}
public static String getString ( Object src, int off, int cch )
{
assert isValid( src, off, cch );
if (cch == 0)
return "";
if (src instanceof char[])
return new String( (char[]) src, off, cch );
if (src instanceof String)
{
String s = (String) src;
if (off == 0 && cch == s.length())
return s;
return s.substring( off, off + cch );
}
StringBuffer sb = new StringBuffer();
((CharJoin) src).getString( sb, off, cch );
return sb.toString();
}
public static final boolean isWhiteSpace ( char ch )
{
switch ( ch )
{
case ' ': case '\t': case '\n': case '\r': return true;
default : return false;
}
}
public final boolean isWhiteSpace ( Object src, int off, int cch )
{
assert isValid( src, off, cch );
if (cch <= 0)
return true;
if (src instanceof char[])
{
for ( char[] chars = (char[]) src ; cch > 0 ; cch-- )
if (!isWhiteSpace( chars[ off++ ] ))
return false;
return true;
}
if (src instanceof String)
{
for ( String s = (String) src ; cch > 0 ; cch-- )
if (!isWhiteSpace( s.charAt( off++ ) ))
return false;
return true;
}
boolean isWhite = true;
for ( _charIter.init( src, off, cch ) ; _charIter.hasNext() ; )
{
if (!isWhiteSpace( _charIter.next() ))
{
isWhite = false;
break;
}
}
_charIter.release();
return isWhite;
}
public Object stripLeft ( Object src, int off, int cch )
{
assert isValid( src, off, cch );
if (cch > 0)
{
if (src instanceof char[])
{
char[] chars = (char[]) src;
while ( cch > 0 && isWhiteSpace( chars[ off ] ) )
{ cch--; off++; }
}
else if (src instanceof String)
{
String s = (String) src;
while ( cch > 0 && isWhiteSpace( s.charAt( off ) ) )
{ cch--; off++; }
}
else
{
int count = 0;
for ( _charIter.init( src, off, cch ) ; _charIter.hasNext() ; count++ )
if (!isWhiteSpace( _charIter.next() ))
break;
_charIter.release();
off += count;
}
}
if (cch == 0)
{
_offSrc = 0;
_cchSrc = 0;
return null;
}
_offSrc = off;
_cchSrc = cch;
return src;
}
public Object stripRight ( Object src, int off, int cch )
{
assert isValid( src, off, cch );
if (cch > 0)
{
for ( _charIter.init( src, off, cch, cch ) ; _charIter.hasPrev() ; cch-- )
if (!isWhiteSpace( _charIter.prev() ))
break;
_charIter.release();
}
if (cch == 0)
{
_offSrc = 0;
_cchSrc = 0;
return null;
}
_offSrc = off;
_cchSrc = cch;
return src;
}
public Object insertChars (
int posInsert,
Object src, int off, int cch,
Object srcInsert, int offInsert, int cchInsert )
{
assert isValid( src, off, cch );
assert isValid( srcInsert, offInsert, cchInsert );
assert posInsert >= 0 && posInsert <= cch;
// TODO - at some point, instead of creating joins, I should
// normalize all the text into a single buffer to stop large
// tree's from being built when many modifications happen...
// TODO - actually, I should see if the size of the new char
// sequence is small enough to simply allocate a new contigous
// sequence, either in a common char[] managed by the master,
// or just create a new string ... this goes for remove chars
// as well.
if (cchInsert == 0)
{
_cchSrc = cch;
_offSrc = off;
return src;
}
if (cch == 0)
{
_cchSrc = cchInsert;
_offSrc = offInsert;
return srcInsert;
}
_cchSrc = cch + cchInsert;
Object newSrc;
if (_cchSrc <= MAX_COPY && canAllocate( _cchSrc ))
{
char[] c = allocate( _cchSrc );
getChars( c, _offSrc, src, off, posInsert );
getChars( c, _offSrc + posInsert, srcInsert, offInsert, cchInsert );
getChars( c, _offSrc + posInsert + cchInsert, src, off + posInsert, cch - posInsert );
newSrc = c;
}
else
{
_offSrc = 0;
CharJoin newJoin;
if (posInsert == 0)
newJoin = new CharJoin( srcInsert, offInsert, cchInsert, src, off );
else if (posInsert == cch)
newJoin = new CharJoin( src, off, cch, srcInsert, offInsert );
else
{
CharJoin j = new CharJoin( src, off, posInsert, srcInsert, offInsert );
newJoin = new CharJoin( j, 0, posInsert + cchInsert, src, off + posInsert );
}
if (newJoin._depth > CharJoin.MAX_DEPTH)
newSrc = saveChars( newJoin, _offSrc, _cchSrc );
else
newSrc = newJoin;
}
assert isValid( newSrc, _offSrc, _cchSrc );
return newSrc;
}
public Object removeChars ( int posRemove, int cchRemove, Object src, int off, int cch )
{
assert isValid( src, off, cch );
assert posRemove >= 0 && posRemove <= cch;
assert cchRemove >= 0 && posRemove + cchRemove <= cch;
Object newSrc;
_cchSrc = cch - cchRemove;
if (_cchSrc == 0)
{
newSrc = null;
_offSrc = 0;
}
else if (posRemove == 0)
{
newSrc = src;
_offSrc = off + cchRemove;
}
else if (posRemove + cchRemove == cch)
{
newSrc = src;
_offSrc = off;
}
else
{
int cchAfter = cch - cchRemove;
if (cchAfter <= MAX_COPY && canAllocate( cchAfter ))
{
char[] chars = allocate( cchAfter );
getChars( chars, _offSrc, src, off, posRemove );
getChars(
chars, _offSrc + posRemove,
src, off + posRemove + cchRemove, cch - posRemove - cchRemove );
newSrc = chars;
_offSrc = _offSrc;
}
else
{
CharJoin j = new CharJoin( src, off, posRemove, src, off + posRemove + cchRemove );
if (j._depth > CharJoin.MAX_DEPTH)
newSrc = saveChars( j, 0, _cchSrc );
else
{
newSrc = j;
_offSrc = 0;
}
}
}
assert isValid( newSrc, _offSrc, _cchSrc );
return newSrc;
}
private static int sizeof ( Object src )
{
assert src == null || src instanceof String || src instanceof char[];
if (src instanceof char[])
return ((char[]) src).length;
return src == null ? 0 : ((String) src).length();
}
private boolean canAllocate ( int cch )
{
return _currentBuffer == null || _currentBuffer.length - _currentOffset >= cch;
}
private char[] allocate ( int cch )
{
assert _currentBuffer == null || _currentBuffer.length - _currentOffset > 0;
if (_currentBuffer == null)
{
_currentBuffer = new char [ Math.max( cch, _charBufSize ) ];
_currentOffset = 0;
}
_offSrc = _currentOffset;
_cchSrc = Math.min( _currentBuffer.length - _currentOffset, cch );
char[] retBuf = _currentBuffer;
assert _currentOffset + _cchSrc <= _currentBuffer.length;
if ((_currentOffset += _cchSrc) == _currentBuffer.length)
{
_currentBuffer = null;
_currentOffset = 0;
}
return retBuf;
}
public Object saveChars ( Object srcSave, int offSave, int cchSave )
{
return saveChars( srcSave, offSave, cchSave, null, 0, 0 );
}
public Object saveChars (
Object srcSave, int offSave, int cchSave,
Object srcPrev, int offPrev, int cchPrev )
{
// BUGBUG (ericvas)
//
// There is a severe degenerate situation which can deveol here. The cases is where
// there is a long strings of calls to saveChars, where the caller passes in prev text
// to be prepended. In this cases, the buffer breaks and a join is made, but because the
// join is created, subsequent calls willproduce additional joins. I need to figure
// out a way that a whole bunch of joins are not created. I really only want to create
// joins in situations where large amount of text is manipulated.
assert isValid( srcSave, offSave, cchSave );
assert isValid( srcPrev, offPrev, cchPrev );
// Allocate some space to save the text and copy it there. This may not allocate all
// the space I need. This happens when I run out of buffer space. Deal with this later.
char[] srcAlloc = allocate( cchSave );
int offAlloc = _offSrc;
int cchAlloc = _cchSrc;
assert cchAlloc <= cchSave;
getChars( srcAlloc, offAlloc, srcSave, offSave, cchAlloc );
Object srcNew;
int offNew;
int cchNew = cchAlloc + cchPrev;
// The prev arguments specify a chunk of text which the caller wants prepended to the
// text to be saved. The optimization here is to detect the case where the prev text
// and the newly allcoated and saved text are adjacent, so that I can avoid copying
// or joining the two pieces. The situation where this happens most is when a parser
// reports a big piece of text in chunks, perhaps because there are entities in the
// big chunk of text.
CharJoin j;
if (cchPrev == 0)
{
srcNew = srcAlloc;
offNew = offAlloc;
}
else if (srcPrev == srcAlloc && offPrev + cchPrev == offAlloc)
{
assert srcPrev instanceof char[];
srcNew = srcPrev;
offNew = offPrev;
}
else if (srcPrev instanceof CharJoin && (j = (CharJoin) srcPrev)._srcRight == srcAlloc &&
offPrev + cchPrev - j._cchLeft + j._offRight == offAlloc)
{
assert j._srcRight instanceof char[];
srcNew = srcPrev;
offNew = offPrev;
}
else
{
j = new CharJoin( srcPrev, offPrev, cchPrev, srcAlloc, offAlloc );
srcNew = j;
offNew = 0;
srcNew = j._depth > CharJoin.MAX_DEPTH ? saveChars( j, 0, cchNew ) : j;
}
// Now, srcNew and offNew specify the two parts of the triple which has the prev text and
// part of the text to save (if not all of it). Here I compute cchMore which is any
// remaining text which was not allocated for earlier. Effectively, this code deals with
// the case where the text to save was greater than the remaining space in the buffer and
// I need to allocate another buffer to save away the second part and then join the two.
int cchMore = cchSave - cchAlloc;
if (cchMore > 0)
{
// If we're here the the buffer got consumed. So, this time it must allocate a new
// buffer capable of containing all of the remaining text (no matter how large) and
// return the beginning part of it.
srcAlloc = allocate( cchMore );
offAlloc = _offSrc;
cchAlloc = _cchSrc;
assert cchAlloc == cchMore;
assert offAlloc == 0;
getChars( srcAlloc, offAlloc, srcSave, offSave + (cchSave - cchMore), cchMore );
j = new CharJoin( srcNew, offNew, cchNew, srcAlloc, offAlloc );
offNew = 0;
cchNew += cchMore;
srcNew = j._depth > CharJoin.MAX_DEPTH ? saveChars( j, 0, cchNew ) : j;
}
_offSrc = offNew;
_cchSrc = cchNew;
assert isValid( srcNew, _offSrc, _cchSrc );
return srcNew;
}
private static void dumpText ( PrintStream o, String s )
{
o.print( "\"" );
for ( int i = 0 ; i < s.length() ; i++ )
{
char ch = s.charAt( i );
if (i == 36)
{
o.print( "..." );
break;
}
if (ch == '\n') o.print( "\\n" );
else if (ch == '\r') o.print( "\\r" );
else if (ch == '\t') o.print( "\\t" );
else if (ch == '\f') o.print( "\\f" );
else if (ch == '\f') o.print( "\\f" );
else if (ch == '"' ) o.print( "\\\"" );
else o.print( ch );
}
o.print( "\"" );
}
public static void dump ( Object src, int off, int cch )
{
dumpChars( System.out, src, off, cch );
System.out.println();
}
public static void dumpChars ( PrintStream p, Object src, int off, int cch )
{
p.print( "off=" + off + ", cch=" + cch + ", " );
if (src == null)
p.print( "" );
else if (src instanceof String)
{
String s = (String) src;
p.print( "String" );
if (off != 0 || cch != s.length())
{
if (off < 0 || off > s.length() || off + cch < 0 || off + cch > s.length())
{
p.print( " (Error)" );
return;
}
}
//p.print( ": " );
dumpText( p, s.substring( off, off + cch ) );
}
else if (src instanceof char[])
{
char[] chars = (char[]) src;
p.print( "char[]" );
if (off != 0 || cch != chars.length)
{
if (off < 0 || off > chars.length || off + cch < 0 || off + cch > chars.length)
{
p.print( " (Error)" );
return;
}
}
//p.print( ": " );
dumpText( p, new String( chars, off, cch ) );
}
else if (src instanceof CharJoin)
{
p.print( "CharJoin" );
((CharJoin) src).dumpChars( p, off, cch );
}
else
{
p.print( "Unknown text source" );
}
}
public static boolean isValid ( Object src, int off, int cch )
{
if (cch < 0 || off < 0)
return false;
if (src == null)
return off == 0 && cch == 0;
if (src instanceof char[])
{
char[] c = (char[]) src;
return off <= c.length && off + cch <= c.length;
}
if (src instanceof String)
{
String s = (String) src;
return off <= s.length() && off + cch <= s.length();
}
if (src instanceof CharJoin)
return ((CharJoin) src).isValid( off, cch );
return false;
}
//
// Private stuff
//
public static final class CharJoin
{
public CharJoin (
Object srcLeft, int offLeft, int cchLeft, Object srcRight, int offRight )
{
_srcLeft = srcLeft; _offLeft = offLeft; _cchLeft = cchLeft;
_srcRight = srcRight; _offRight = offRight;
int depth = 0;
if (srcLeft instanceof CharJoin)
depth = ((CharJoin) srcLeft)._depth;
if (srcRight instanceof CharJoin)
{
int rightDepth = ((CharJoin) srcRight)._depth;
if (rightDepth > depth)
depth = rightDepth;
}
_depth = depth + 1;
assert _depth <= MAX_DEPTH + 2;
}
private int cchRight ( int off, int cch )
{
return Math.max( 0, cch - _cchLeft - off );
}
public int depth ( )
{
int depth = 0;
if (_srcLeft instanceof CharJoin)
depth = ((CharJoin) _srcLeft).depth();
if (_srcRight instanceof CharJoin)
depth = Math.max( ((CharJoin)_srcRight).depth(), depth );
return depth + 1;
}
public boolean isValid ( int off, int cch )
{
// Deep trees cause this to take forever
if (_depth > 2)
return true;
assert _depth == depth();
if (off < 0 || cch < 0)
return false;
if (!CharUtil.isValid( _srcLeft, _offLeft, _cchLeft ))
return false;
if (!CharUtil.isValid( _srcRight, _offRight, cchRight( off, cch ) ))
return false;
return true;
}
private void getString ( StringBuffer sb, int off, int cch )
{
assert cch > 0;
if (off < _cchLeft)
{
int cchL = Math.min( _cchLeft - off, cch );
CharUtil.getString( sb, _srcLeft, _offLeft + off, cchL );
if (cch > cchL)
CharUtil.getString( sb, _srcRight, _offRight, cch - cchL );
}
else
CharUtil.getString( sb, _srcRight, _offRight + off - _cchLeft, cch );
}
private void getChars ( char[] chars, int start, int off, int cch )
{
assert cch > 0;
if (off < _cchLeft)
{
int cchL = Math.min( _cchLeft - off, cch );
CharUtil.getChars( chars, start, _srcLeft, _offLeft + off, cchL );
if (cch > cchL)
CharUtil.getChars( chars, start + cchL, _srcRight, _offRight, cch - cchL );
}
else
CharUtil.getChars( chars, start, _srcRight, _offRight + off - _cchLeft, cch );
}
private void dumpChars( int off, int cch )
{
dumpChars( System.out, off, cch );
}
private void dumpChars( PrintStream p, int off, int cch )
{
p.print( "( " );
CharUtil.dumpChars( p, _srcLeft, _offLeft, _cchLeft );
p.print( ", " );
CharUtil.dumpChars( p, _srcRight, _offRight, cchRight( off, cch ) );
p.print( " )" );
}
//
//
//
public final Object _srcLeft;
public final int _offLeft;
public final int _cchLeft;
public final Object _srcRight;
public final int _offRight;
public final int _depth;
static final int MAX_DEPTH = 64;
}
//
//
//
public final static class CharIterator
{
public void init ( Object src, int off, int cch )
{
init( src, off, cch, 0 );
}
public void init ( Object src, int off, int cch, int startPos )
{
assert isValid( src, off, cch );
release();
_srcRoot = src;
_offRoot = off;
_cchRoot = cch;
_minPos = _maxPos = -1;
movePos( startPos );
}
public void release ( )
{
_srcRoot = null;
_srcLeafString = null;
_srcLeafChars = null;
}
public boolean hasNext ( ) { return _pos < _cchRoot; }
public boolean hasPrev ( ) { return _pos > 0; }
public char next ( )
{
assert hasNext() ;
char ch = currentChar();
movePos( _pos + 1 );
return ch;
}
public char prev ( )
{
assert hasPrev() ;
movePos( _pos - 1 );
return currentChar();
}
public void movePos ( int newPos )
{
assert newPos >= 0 && newPos <= _cchRoot;
if (newPos < _minPos || newPos > _maxPos)
{
// if newPos out of cached leaf, recache new leaf
Object src = _srcRoot;
int off = _offRoot + newPos;
int cch = _cchRoot;
for ( _offLeaf = _offRoot ; src instanceof CharJoin ; )
{
CharJoin j = (CharJoin) src;
if (off < j._cchLeft)
{
src = j._srcLeft;
_offLeaf = j._offLeft;
off = off + j._offLeft;
cch = j._cchLeft;
}
else
{
src = j._srcRight;
_offLeaf = j._offRight;
off = off - (j._cchLeft - j._offRight);
cch = cch - j._cchLeft;
}
}
// _offLeaf = off - Math.min( off - _offLeaf, newPos );
_minPos = newPos - (off - _offLeaf);
// _maxPos = newPos + Math.min( _cchRoot - newPos, sizeof( src ) - off );
_maxPos = _minPos + cch;
if (newPos < _cchRoot)
_maxPos--;
// Cache the leaf src to avoid instanceof for every char
_srcLeafChars = null;
_srcLeafString = null;
if (src instanceof char[])
_srcLeafChars = (char[]) src;
else
_srcLeafString = (String) src;
assert newPos >= _minPos && newPos <= _maxPos;
}
_pos = newPos;
}
private char currentChar ( )
{
int i = _offLeaf + _pos - _minPos;
return _srcLeafChars == null ? _srcLeafString.charAt( i ) : _srcLeafChars[ i ];
}
private Object _srcRoot; // Original triple
private int _offRoot;
private int _cchRoot;
private int _pos; // Current position
private int _minPos; // Min/max poses for current cached leaf
private int _maxPos;
private int _offLeaf;
private String _srcLeafString; // Cached leaf - either a char[] or a string
private char[] _srcLeafChars;
}
private static int CHARUTIL_INITIAL_BUFSIZE = 1024 * 32;
private static ThreadLocal tl_charUtil =
new ThreadLocal() { protected Object initialValue() { return new SoftReference(new CharUtil( CHARUTIL_INITIAL_BUFSIZE )); } };
private CharIterator _charIter = new CharIterator();
// TODO - 64 is kinda arbitrary. Perhaps it should be configurable.
private static final int MAX_COPY = 64;
// Current char buffer we're allcoating new chars to
private int _charBufSize;
private int _currentOffset;
private char[] _currentBuffer;
// These members are used to communicate offset and character count
// information back to a caller of various methods on CharUtil.
// Usually, the methods returns the src Object, and these two hold
// the offset and the char count.
public int _offSrc;
public int _cchSrc;
} xmlbeans-2.6.0/src/store/org/apache/xmlbeans/impl/store/Cur.java 0000644 0001750 0001750 00000300040 11361341572 022705 0 ustar apo apo /* 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.impl.store;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.DOMImplementation;
// DOM Level 3
import org.w3c.dom.UserDataHandler;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.TypeInfo;
import javax.xml.transform.Source;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import org.apache.xmlbeans.impl.soap.Detail;
import org.apache.xmlbeans.impl.soap.DetailEntry;
import org.apache.xmlbeans.impl.soap.MimeHeaders;
import org.apache.xmlbeans.impl.soap.Name;
import org.apache.xmlbeans.impl.soap.SOAPBody;
import org.apache.xmlbeans.impl.soap.SOAPBodyElement;
import org.apache.xmlbeans.impl.soap.SOAPElement;
import org.apache.xmlbeans.impl.soap.SOAPEnvelope;
import org.apache.xmlbeans.impl.soap.SOAPException;
import org.apache.xmlbeans.impl.soap.SOAPFactory;
import org.apache.xmlbeans.impl.soap.SOAPFault;
import org.apache.xmlbeans.impl.soap.SOAPFaultElement;
import org.apache.xmlbeans.impl.soap.SOAPHeader;
import org.apache.xmlbeans.impl.soap.SOAPHeaderElement;
import org.apache.xmlbeans.impl.soap.SOAPPart;
import org.apache.xmlbeans.impl.store.Xobj.Bookmark;
import org.apache.xmlbeans.impl.store.Locale.LoadContext;
import org.apache.xmlbeans.impl.store.DomImpl.Dom;
import org.apache.xmlbeans.impl.store.DomImpl.CharNode;
import org.apache.xmlbeans.impl.store.DomImpl.TextNode;
import org.apache.xmlbeans.impl.store.DomImpl.CdataNode;
import org.apache.xmlbeans.impl.store.DomImpl.SaajTextNode;
import org.apache.xmlbeans.impl.store.DomImpl.SaajCdataNode;
import org.apache.xmlbeans.CDataBookmark;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlLineNumber;
import org.apache.xmlbeans.SchemaField;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.XmlDocumentProperties;
import org.apache.xmlbeans.XmlCursor.XmlBookmark;
import org.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.apache.xmlbeans.impl.values.TypeStoreVisitor;
import org.apache.xmlbeans.impl.values.TypeStoreUserFactory;
import javax.xml.namespace.QName;
import org.apache.xmlbeans.impl.common.ValidatorListener;
import org.apache.xmlbeans.impl.common.XmlLocale;
import org.apache.xmlbeans.impl.common.QNameHelper;
final class Cur
{
static final int TEXT = 0; // Must be 0
static final int ROOT = 1;
static final int ELEM = 2;
static final int ATTR = 3;
static final int COMMENT = 4;
static final int PROCINST = 5;
static final int POOLED = 0;
static final int REGISTERED = 1;
static final int EMBEDDED = 2;
static final int DISPOSED = 3;
static final int END_POS = -1;
static final int NO_POS = -2;
Cur ( Locale l )
{
_locale = l;
_pos = NO_POS;
_tempFrame = -1;
_state = POOLED;
_stackTop = Locations.NULL;
_selectionFirst = -1;
_selectionN = -1;
_selectionLoc = Locations.NULL;
_selectionCount = 0;
}
boolean isPositioned ( ) { assert isNormal(); return _xobj != null; }
static boolean kindIsContainer ( int k ) { return k == ELEM || k == ROOT; }
static boolean kindIsFinish ( int k ) { return k == -ELEM || k == -ROOT; }
int kind ( )
{
assert isPositioned();
int kind = _xobj.kind();
return _pos == 0 ? kind : (_pos == END_POS ? - kind : TEXT);
}
boolean isRoot ( ) { assert isPositioned(); return _pos == 0 && _xobj.kind() == ROOT; }
boolean isElem ( ) { assert isPositioned(); return _pos == 0 && _xobj.kind() == ELEM; }
boolean isAttr ( ) { assert isPositioned(); return _pos == 0 && _xobj.kind() == ATTR; }
boolean isComment ( ) { assert isPositioned(); return _pos == 0 && _xobj.kind() == COMMENT; }
boolean isProcinst ( ) { assert isPositioned(); return _pos == 0 && _xobj.kind() == PROCINST; }
boolean isText ( ) { assert isPositioned(); return _pos > 0; }
boolean isEnd ( ) { assert isPositioned(); return _pos == END_POS && _xobj.kind() ==ELEM;}
boolean isEndRoot ( ) { assert isPositioned(); return _pos == END_POS && _xobj.kind() ==ROOT;}
boolean isNode ( ) { assert isPositioned(); return _pos == 0; }
boolean isContainer ( ) { assert isPositioned(); return _pos == 0 && kindIsContainer( _xobj.kind() ); }
boolean isFinish ( ) { assert isPositioned(); return _pos == END_POS && kindIsContainer( _xobj.kind() ); }
boolean isUserNode ( ) { assert isPositioned(); int k = kind(); return k == ELEM || k == ROOT || (k == ATTR && !isXmlns()); }
boolean isContainerOrFinish ( )
{
assert isPositioned();
if (_pos!=0 && _pos!= END_POS)
return false;
int kind = _xobj.kind();
return kind == ELEM || kind == -ELEM || kind == ROOT || kind == -ROOT;
}
boolean isNormalAttr ( ) { return isNode() && _xobj.isNormalAttr(); }
boolean isXmlns ( ) { return isNode() && _xobj.isXmlns(); }
boolean isTextCData ( ) { return _xobj.hasBookmark(CDataBookmark.class, _pos); }
QName getName ( ) { assert isNode() || isEnd(); return _xobj._name; }
String getLocal ( ) { return getName().getLocalPart(); }
String getUri ( ) { return getName().getNamespaceURI(); }
String getXmlnsPrefix ( ) { assert isXmlns(); return _xobj.getXmlnsPrefix(); }
String getXmlnsUri ( ) { assert isXmlns(); return _xobj.getXmlnsUri(); }
boolean isDomDocRoot ( ) { return isRoot() && _xobj.getDom() instanceof Document; }
boolean isDomFragRoot ( ) { return isRoot() && _xobj.getDom() instanceof DocumentFragment; }
int cchRight ( ) { assert isPositioned(); return _xobj.cchRight( _pos ); }
int cchLeft ( ) { assert isPositioned(); return _xobj.cchLeft ( _pos ); }
//
// Creation methods
//
void createRoot ( )
{
createDomDocFragRoot();
}
void createDomDocFragRoot ( )
{
moveTo( new Xobj.DocumentFragXobj( _locale ) );
}
void createDomDocumentRoot ( )
{
moveTo( createDomDocumentRootXobj( _locale ) );
}
void createAttr ( QName name )
{
createHelper( new Xobj.AttrXobj( _locale, name ) );
}
void createComment ( )
{
createHelper( new Xobj.CommentXobj( _locale ) );
}
void createProcinst ( String target )
{
createHelper( new Xobj.ProcInstXobj( _locale, target ) );
}
void createElement ( QName name )
{
createElement( name, null );
}
void createElement ( QName name, QName parentName )
{
createHelper( createElementXobj( _locale, name, parentName ) );
}
static Xobj createDomDocumentRootXobj ( Locale l )
{
return createDomDocumentRootXobj(l, false);
}
static Xobj createDomDocumentRootXobj ( Locale l , boolean fragment)
{
Xobj xo;
if (l._saaj == null)
if (fragment)
xo = new Xobj.DocumentFragXobj( l );
else
xo = new Xobj.DocumentXobj( l );
else
xo = new Xobj.SoapPartDocXobj( l );
if (l._ownerDoc == null)
l._ownerDoc = xo.getDom();
return xo;
}
static Xobj createElementXobj ( Locale l, QName name, QName parentName )
{
if (l._saaj == null)
return new Xobj.ElementXobj( l, name );
Class c = l._saaj.identifyElement( name, parentName );
if (c == SOAPElement.class) return new Xobj.SoapElementXobj ( l, name );
if (c == SOAPBody.class) return new Xobj.SoapBodyXobj ( l, name );
if (c == SOAPBodyElement.class) return new Xobj.SoapBodyElementXobj ( l, name );
if (c == SOAPEnvelope.class) return new Xobj.SoapEnvelopeXobj ( l, name );
if (c == SOAPHeader.class) return new Xobj.SoapHeaderXobj ( l, name );
if (c == SOAPHeaderElement.class) return new Xobj.SoapHeaderElementXobj ( l, name );
if (c == SOAPFaultElement.class) return new Xobj.SoapFaultElementXobj ( l, name );
if (c == Detail.class) return new Xobj.DetailXobj ( l, name );
if (c == DetailEntry.class) return new Xobj.DetailEntryXobj ( l, name );
if (c == SOAPFault.class) return new Xobj.SoapFaultXobj ( l, name );
throw new IllegalStateException( "Unknown SAAJ element class: " + c );
}
private void createHelper ( Xobj x )
{
assert x._locale == _locale;
// insert the new Xobj into an exisiting tree.
if (isPositioned())
{
Cur from = tempCur( x, 0 );
from.moveNode( this );
from.release();
}
moveTo( x );
}
//
// General operations
//
boolean isSamePos ( Cur that )
{
assert isNormal() && (that == null || that.isNormal());
return _xobj == that._xobj && _pos == that._pos;
}
// is this just after the end of that (that must be the start of a node)
boolean isJustAfterEnd ( Cur that )
{
assert isNormal() && that != null && that.isNormal() && that.isNode();
return that._xobj.isJustAfterEnd( _xobj, _pos );
}
boolean isJustAfterEnd ( Xobj x )
{
return x.isJustAfterEnd( _xobj, _pos );
}
boolean isAtEndOf ( Cur that )
{
assert that != null && that.isNormal() && that.isNode();
return _xobj == that._xobj && _pos == END_POS;
}
boolean isInSameTree ( Cur that )
{
assert isPositioned() && that.isPositioned();
return _xobj.isInSameTree( that._xobj );
}
// Retunr -1, 0 or 1 for relative cursor positions. Return 2 is not in sames trees.
int comparePosition ( Cur that )
{
assert isPositioned() && that.isPositioned();
// If in differnet locales, then can't comapre
if (_locale != that._locale)
return 2;
// No need to denormalize, but I want positions which I can compare (no END_POS)
Xobj xThis = _xobj;
int pThis = _pos == END_POS ? xThis.posAfter() - 1 : _pos;
Xobj xThat = that._xobj;
int pThat = that._pos == END_POS ? xThat.posAfter() - 1 : that._pos;
// There are several cases:
//
// 1. Cursors are on the same xobj
// 2. One cursor is a child of the other
// 3. Cursors share a common parent
// 4. Cursors are not in the same trees
//
// Check for the first, trivial, case. Then, compute the depths of the nodes the
// cursors are on, checkin for case 2
//
if (xThis == xThat)
return pThis < pThat ? -1 : pThis == pThat ? 0 : 1;
// Compute the depth of xThis. See if I hit xThat (case 2)
int dThis = 0;
for ( Xobj x = xThis._parent ; x != null ; x = x._parent )
{
dThis++;
if (x == xThat)
return pThat < xThat.posAfter() - 1 ? 1 : -1;
}
// Compute the depth of xThat. See if I hit xThis (case 2)
int dThat = 0;
for ( Xobj x = xThat._parent ; x != null ; x = x._parent )
{
dThat++;
if (x == xThis)
return pThis < xThis.posAfter() - 1 ? -1 : 1;
}
// Must be case 3 or 4 now. Find a common parent. If none, then it's case 4
while ( dThis > dThat ) { dThis--; xThis = xThis._parent; }
while ( dThat > dThis ) { dThat--; xThat = xThat._parent; }
assert dThat == dThis;
if (dThat == 0)
return 2;
assert xThis._parent != null && xThat._parent != null;
while ( xThis._parent != xThat._parent )
{
if ((xThis = xThis._parent) == null)
return 2;
xThat = xThat._parent;
}
// Now, see where xThis and XThat are relative to eachother in the childlist. Apply
// some quick common checks before iterating.
if (xThis._prevSibling == null || xThat._nextSibling == null)
return -1;
if (xThis._nextSibling == null || xThat._prevSibling == null)
return 1;
while ( xThis != null )
if ((xThis = xThis._prevSibling) == xThat)
return 1;
return -1;
}
void setName ( QName newName )
{
assert isNode() && newName != null;
_xobj.setName( newName );
}
void moveTo ( Xobj x )
{
moveTo( x, 0 );
}
void moveTo ( Xobj x, int p )
{
// This cursor may not be normalized upon entry, don't assert isNormal() here
assert x == null || _locale == x._locale;
assert x != null || p == NO_POS;
assert x == null || x.isNormal( p ) || ( x.isVacant() && x._cchValue==0 && x._user == null );
assert _state == REGISTERED || _state == EMBEDDED;
assert _state == EMBEDDED || (_xobj == null || !isOnList( _xobj._embedded ));
assert _state == REGISTERED || (_xobj != null && isOnList( _xobj._embedded ));
moveToNoCheck( x, p );
assert isNormal() || ( _xobj.isVacant() && _xobj._cchValue==0 && _xobj._user == null );
}
void moveToNoCheck ( Xobj x, int p )
{
if (_state == EMBEDDED && x != _xobj)
{
_xobj._embedded = listRemove( _xobj._embedded );
_locale._registered = listInsert( _locale._registered );
_state = REGISTERED;
}
_xobj = x;
_pos = p;
}
void moveToCur ( Cur to )
{
assert isNormal() && (to == null || to.isNormal());
if (to == null)
moveTo( null, NO_POS );
else
moveTo( to._xobj, to._pos );
}
void moveToDom ( Dom d )
{
assert _locale == d.locale();
assert d instanceof Xobj || d instanceof Xobj.SoapPartDom;
moveTo( d instanceof Xobj ? (Xobj) d : ((Xobj.SoapPartDom) d)._docXobj );
}
static final class Locations
{
private static final int NULL = -1;
Locations ( Locale l )
{
_locale = l;
_xobjs = new Xobj [ _initialSize ];
_poses = new int [ _initialSize ];
_curs = new Cur [ _initialSize ];
_next = new int [ _initialSize ];
_prev = new int [ _initialSize ];
_nextN = new int [ _initialSize ];
_prevN = new int [ _initialSize ];
for ( int i = _initialSize - 1 ; i >= 0 ; i-- )
{
assert _xobjs[ i ] == null;
_poses [ i ] = NO_POS;
_next [ i ] = i + 1;
_prev [ i ] = NULL;
_nextN [ i ] = NULL;
_prevN [ i ] = NULL;
}
_next [ _initialSize - 1 ] = NULL;
_free = 0;
_naked = NULL;
}
boolean isSamePos ( int i, Cur c )
{
if (_curs[ i ] == null)
return c._xobj == _xobjs[ i ] && c._pos == _poses[ i ];
else
return c.isSamePos( _curs[ i ] );
}
boolean isAtEndOf ( int i, Cur c )
{
assert _curs[ i ] != null || _poses[ i ] == 0;
assert _curs[ i ] == null || _curs[ i ].isNode();
if (_curs[ i ] == null)
return c._xobj == _xobjs[ i ] && c._pos == END_POS;
else
return c.isAtEndOf( _curs[ i ] );
}
void moveTo ( int i, Cur c )
{
if (_curs[ i ] == null)
c.moveTo( _xobjs[ i ], _poses[ i ] );
else
c.moveToCur( _curs[ i ] );
}
int insert ( int head, int before, int i )
{
return insert( head, before, i, _next, _prev );
}
int remove ( int head, int i )
{
Cur c = _curs[ i ];
assert c != null || _xobjs[ i ] != null;
assert c != null || _xobjs[ i ] != null;
if (c != null)
{
_curs[ i ].release();
_curs[ i ] = null;
assert _xobjs[ i ] == null;
assert _poses [ i ] == NO_POS;
}
else
{
assert _xobjs[ i ] != null && _poses[ i ] != NO_POS;
_xobjs[ i ] = null;
_poses[ i ] = NO_POS;
_naked = remove( _naked, i, _nextN, _prevN );
}
head = remove( head, i, _next, _prev );
_next[ i ] = _free;
_free = i;
return head;
}
int allocate ( Cur addThis )
{
assert addThis.isPositioned();
if (_free == NULL)
makeRoom();
int i = _free;
_free = _next [ i ];
_next [ i ] = NULL;
assert _prev [ i ] == NULL;
assert _curs [ i ] == null;
assert _xobjs[ i ] == null;
assert _poses[ i ] == NO_POS;
_xobjs [ i ] = addThis._xobj;
_poses [ i ] = addThis._pos;
_naked = insert( _naked, NULL, i, _nextN, _prevN );
return i;
}
private static int insert ( int head, int before, int i, int[] next, int[] prev )
{
if (head == NULL)
{
assert before == NULL;
prev[ i ] = i;
head = i;
}
else if (before != NULL)
{
prev[ i ] = prev[ before ];
next[ i ] = before;
prev[ before ] = i;
if (head == before)
head = i;
}
else
{
prev[ i ] = prev[ head ];
assert next[ i ] == NULL;
next[ prev[ head ] ] = i;
prev[ head ] = i;
}
return head;
}
private static int remove ( int head, int i, int[] next, int[] prev )
{
if (prev[ i ] == i)
{
assert head == i;
head = NULL;
}
else
{
if (head == i)
head = next[ i ];
else
next[ prev [ i ] ] = next[ i ];
if (next[ i ] == NULL)
prev[ head ] = prev[ i ];
else
{
prev[ next[ i ] ] = prev[ i ];
next[ i ] = NULL;
}
}
prev[ i ] = NULL;
assert next[ i ] == NULL;
return head;
}
void notifyChange ( )
{
for ( int i ; (i = _naked) != NULL ; )
{
assert _curs[ i ] == null && _xobjs[ i ] != null && _poses[ i ] != NO_POS;
_naked = remove( _naked, i, _nextN, _prevN );
_curs[ i ] = _locale.getCur();
_curs[ i ].moveTo( _xobjs[ i ], _poses[ i ] );
_xobjs[ i ] = null;
_poses[ i ] = NO_POS;
}
}
int next ( int i ) { return _next[ i ]; }
int prev ( int i ) { return _prev[ i ]; }
private void makeRoom ( )
{
assert _free == NULL;
int l = _xobjs.length;
Xobj [] oldXobjs = _xobjs;
int [] oldPoses = _poses;
Cur [] oldCurs = _curs;
int [] oldNext = _next;
int [] oldPrev = _prev;
int [] oldNextN = _nextN;
int [] oldPrevN = _prevN;
_xobjs = new Xobj [ l * 2 ];
_poses = new int [ l * 2 ];
_curs = new Cur [ l * 2 ];
_next = new int [ l * 2 ];
_prev = new int [ l * 2 ];
_nextN = new int [ l * 2 ];
_prevN = new int [ l * 2 ];
System.arraycopy( oldXobjs, 0, _xobjs, 0, l );
System.arraycopy( oldPoses, 0, _poses, 0, l );
System.arraycopy( oldCurs, 0, _curs, 0, l );
System.arraycopy( oldNext, 0, _next, 0, l );
System.arraycopy( oldPrev, 0, _prev, 0, l );
System.arraycopy( oldNextN, 0, _nextN, 0, l );
System.arraycopy( oldPrevN, 0, _prevN, 0, l );
for ( int i = l * 2 - 1 ; i >= l ; i-- )
{
_next [ i ] = i + 1;
_prev [ i ] = NULL;
_nextN [ i ] = NULL;
_prevN [ i ] = NULL;
_poses [ i ] = NO_POS;
}
_next [ l * 2 - 1 ] = NULL;
_free = l;
}
private static final int _initialSize = 32;
private Locale _locale;
private Xobj [] _xobjs;
private int [] _poses;
private Cur [] _curs;
private int [] _next;
private int [] _prev;
private int [] _nextN;
private int [] _prevN;
private int _free; // Unused entries
private int _naked; // Entries without Curs
}
void push ( )
{
assert isPositioned();
int i = _locale._locations.allocate( this );
_stackTop = _locale._locations.insert( _stackTop, _stackTop, i );
}
void pop ( boolean stay )
{
if (stay)
popButStay();
else
pop();
}
void popButStay ( )
{
if (_stackTop != Locations.NULL)
_stackTop = _locale._locations.remove( _stackTop, _stackTop );
}
boolean pop ( )
{
if (_stackTop == Locations.NULL)
return false;
_locale._locations.moveTo( _stackTop, this );
_stackTop = _locale._locations.remove( _stackTop, _stackTop );
return true;
}
boolean isAtLastPush ( )
{
assert _stackTop != Locations.NULL;
return _locale._locations.isSamePos( _stackTop, this );
}
boolean isAtEndOfLastPush ( )
{
assert _stackTop != Locations.NULL;
return _locale._locations.isAtEndOf( _stackTop, this );
}
void addToSelection ( Cur that )
{
assert that != null && that.isNormal();
assert isPositioned() && that.isPositioned();
int i = _locale._locations.allocate( that );
_selectionFirst = _locale._locations.insert( _selectionFirst, Locations.NULL, i );
_selectionCount++;
}
void addToSelection ( )
{
assert isPositioned();
int i = _locale._locations.allocate( this );
_selectionFirst = _locale._locations.insert( _selectionFirst, Locations.NULL, i );
_selectionCount++;
}
private int selectionIndex ( int i )
{
assert _selectionN >= -1 && i >= 0 && i < _selectionCount;
if (_selectionN == -1)
{
_selectionN = 0;
_selectionLoc = _selectionFirst;
}
while ( _selectionN < i )
{
_selectionLoc = _locale._locations.next( _selectionLoc );
_selectionN++;
}
while ( _selectionN > i )
{
_selectionLoc = _locale._locations.prev( _selectionLoc );
_selectionN--;
}
return _selectionLoc;
}
void removeSelection ( int i )
{
assert i >= 0 && i < _selectionCount;
int j = selectionIndex( i );
// Update the nth selection indices to accomodate the deletion
if (i < _selectionN)
_selectionN--;
else if (i == _selectionN)
{
_selectionN--;
if (i == 0)
_selectionLoc = Locations.NULL;
else
_selectionLoc = _locale._locations.prev( _selectionLoc );
}
_selectionFirst = _locale._locations.remove( _selectionFirst, j );
_selectionCount--;
}
int selectionCount ( )
{
return _selectionCount;
}
void moveToSelection ( int i )
{
assert i >= 0 && i < _selectionCount;
_locale._locations.moveTo( selectionIndex( i ), this );
}
void clearSelection ( )
{
assert _selectionCount >= 0;
while ( _selectionCount > 0 )
removeSelection( 0 );
}
boolean toParent ( ) { return toParent( false ); }
boolean toParentRaw ( ) { return toParent( true ); }
Xobj getParent ( ) { return getParent( false ); }
Xobj getParentRaw ( ) { return getParent( true ); }
boolean hasParent ( )
{
assert isPositioned();
if (_pos == END_POS || (_pos >= 1 && _pos < _xobj.posAfter()))
return true;
assert _pos == 0 || _xobj._parent != null;
return _xobj._parent != null;
}
Xobj getParentNoRoot()
{
assert isPositioned();
if (_pos == END_POS || (_pos >= 1 && _pos < _xobj.posAfter()))
return _xobj;
assert _pos == 0 || _xobj._parent != null;
if (_xobj._parent != null)
return _xobj._parent;
return null;
}
Xobj getParent ( boolean raw )
{
assert isPositioned();
if (_pos == END_POS || (_pos >= 1 && _pos < _xobj.posAfter()))
return _xobj;
assert _pos == 0 || _xobj._parent != null;
if (_xobj._parent != null)
return _xobj._parent;
if (raw || _xobj.isRoot())
return null;
Cur r = _locale.tempCur();
r.createRoot();
Xobj root = r._xobj;
r.next();
moveNode( r );
r.release();
return root;
}
boolean toParent ( boolean raw )
{
Xobj parent = getParent( raw );
if (parent == null)
return false;
moveTo( parent );
return true;
}
void toRoot ()
{
Xobj xobj = _xobj;
while (!xobj.isRoot())
{
if (xobj._parent==null)
{
Cur r = _locale.tempCur();
r.createRoot();
Xobj root = r._xobj;
r.next();
moveNode( r );
r.release();
xobj = root;
break;
}
xobj = xobj._parent;
}
moveTo(xobj);
}
boolean hasText ( )
{
assert isNode();
return _xobj.hasTextEnsureOccupancy();
}
boolean hasAttrs ( )
{
assert isNode();
return _xobj.hasAttrs();
}
boolean hasChildren ( )
{
assert isNode();
return _xobj.hasChildren();
}
boolean toFirstChild ( )
{
assert isNode();
if (!_xobj.hasChildren())
return false;
for ( Xobj x = _xobj._firstChild ; ; x = x._nextSibling )
{
if (!x.isAttr())
{
moveTo( x );
return true;
}
}
}
protected boolean toLastChild ( )
{
assert isNode();
if (!_xobj.hasChildren())
return false;
moveTo( _xobj._lastChild );
return true;
}
boolean toNextSibling ( )
{
assert isNode();
if (_xobj.isAttr())
{
if (_xobj._nextSibling != null && _xobj._nextSibling.isAttr())
{
moveTo( _xobj._nextSibling );
return true;
}
}
else if (_xobj._nextSibling != null)
{
moveTo( _xobj._nextSibling );
return true;
}
return false;
}
void setValueAsQName ( QName qname )
{
assert isNode();
String value = qname.getLocalPart();
String ns = qname.getNamespaceURI();
String prefix =
prefixForNamespace(
ns, qname.getPrefix().length() > 0 ? qname.getPrefix() : null, true );
if (prefix.length() > 0)
value = prefix + ":" + value;
setValue( value );
}
void setValue ( String value )
{
assert isNode();
moveNodeContents( null, false );
next();
insertString( value );
toParent();
}
void removeFollowingAttrs ( )
{
assert isAttr();
QName attrName = getName();
push();
if (toNextAttr())
{
while ( isAttr() )
{
if (getName().equals( attrName ))
moveNode( null );
else if (!toNextAttr())
break;
}
}
pop();
}
String getAttrValue ( QName name )
{
String s = null;
push();
if (toAttr( name ))
s = getValueAsString();
pop();
return s;
}
void setAttrValueAsQName ( QName name, QName value )
{
assert isContainer();
if (value == null)
{
_xobj.removeAttr( name );
}
else
{
if (toAttr( name ))
{
removeFollowingAttrs();
}
else
{
next();
createAttr( name );
}
setValueAsQName( value );
toParent();
}
}
boolean removeAttr ( QName name )
{
assert isContainer();
return _xobj.removeAttr( name );
}
void setAttrValue ( QName name, String value )
{
assert isContainer();
_xobj.setAttr( name, value );
}
boolean toAttr ( QName name )
{
assert isNode();
Xobj a = _xobj.getAttr( name );
if (a == null)
return false;
moveTo( a );
return true;
}
boolean toFirstAttr ( )
{
assert isNode();
Xobj firstAttr = _xobj.firstAttr();
if (firstAttr == null)
return false;
moveTo( firstAttr );
return true;
}
boolean toLastAttr ( )
{
assert isNode();
if (!toFirstAttr())
return false;
while ( toNextAttr() )
;
return true;
}
boolean toNextAttr ( )
{
assert isAttr() || isContainer();
Xobj nextAttr = _xobj.nextAttr();
if (nextAttr == null)
return false;
moveTo( nextAttr );
return true;
}
boolean toPrevAttr ( )
{
if (isAttr())
{
if (_xobj._prevSibling == null)
moveTo( _xobj.ensureParent() );
else
moveTo( _xobj._prevSibling );
return true;
}
prev();
if (!isContainer())
{
next();
return false;
}
return toLastAttr();
}
boolean skipWithAttrs ( )
{
assert isNode();
if (skip())
return true;
if (_xobj.isRoot())
return false;
assert _xobj.isAttr();
toParent();
next();
return true;
}
boolean skip ( )
{
assert isNode();
if (_xobj.isRoot())
return false;
if (_xobj.isAttr())
{
if (_xobj._nextSibling == null || !_xobj._nextSibling.isAttr())
return false;
moveTo( _xobj._nextSibling, 0 );
}
else
moveTo( getNormal( _xobj, _xobj.posAfter() ), _posTemp );
return true;
}
void toEnd ( )
{
assert isNode();
moveTo( _xobj, END_POS );
}
void moveToCharNode ( CharNode node )
{
assert node.getDom() != null && node.getDom().locale() == _locale;
moveToDom( node.getDom() );
CharNode n;
_xobj.ensureOccupancy();
n = _xobj._charNodesValue =
updateCharNodes( _locale, _xobj, _xobj._charNodesValue, _xobj._cchValue );
for ( ; n != null ; n = n._next )
{
if (node == n)
{
moveTo( getNormal( _xobj, n._off + 1 ), _posTemp );
return;
}
}
n = _xobj._charNodesAfter =
updateCharNodes( _locale, _xobj, _xobj._charNodesAfter, _xobj._cchAfter );
for ( ; n != null ; n = n._next )
{
if (node == n)
{
moveTo( getNormal( _xobj, n._off + _xobj._cchValue + 2 ), _posTemp );
return;
}
}
assert false;
}
boolean prevWithAttrs ( )
{
if (prev())
return true;
if (!isAttr())
return false;
toParent();
return true;
}
boolean prev ( )
{
assert isPositioned();
if (_xobj.isRoot() && _pos == 0)
return false;
if (_xobj.isAttr() && _pos == 0 && _xobj._prevSibling == null)
return false;
Xobj x = getDenormal();
int p = _posTemp;
assert p > 0 && p != END_POS;
int pa = x.posAfter();
if (p > pa)
p = pa;
else if (p == pa)
{
// Text after an attr is allowed only on the last attr,
// and that text belongs to the parent container..
//
// If we're a thte end of the last attr, then we were just
// inside the container, and we need to skip the attrs.
if (x.isAttr() &&
(x._cchAfter > 0 || x._nextSibling == null || !x._nextSibling.isAttr()))
{
x = x.ensureParent();
p = 0;
}
else
p = END_POS;
}
else if (p == pa - 1)
{
x.ensureOccupancy();
p = x._cchValue > 0 ? 1 : 0;
}
else if (p > 1)
p = 1;
else
{
assert p == 1;
p = 0;
}
moveTo( getNormal( x, p ), _posTemp );
return true;
}
boolean next ( boolean withAttrs )
{
return withAttrs ? nextWithAttrs() : next();
}
boolean nextWithAttrs ( )
{
int k = kind();
if (kindIsContainer( k ))
{
if (toFirstAttr())
return true;
}
else if (k == -ATTR)
{
if (next())
return true;
toParent();
if (!toParentRaw())
return false;
}
return next();
}
boolean next ( )
{
assert isNormal();
Xobj x = _xobj;
int p = _pos;
int pa = x.posAfter();
if (p >= pa)
p = _xobj.posMax();
else if (p == END_POS)
{
if (x.isRoot() || (x.isAttr() && (x._nextSibling == null || !x._nextSibling.isAttr())))
return false;
p = pa;
}
else if (p > 0)
{
assert x._firstChild == null || !x._firstChild.isAttr();
if (x._firstChild != null)
{
x = x._firstChild;
p = 0;
}
else
p = END_POS;
}
else
{
assert p == 0;
x.ensureOccupancy();
p = 1;
if (x._cchValue == 0)
{
if (x._firstChild != null)
{
if (x._firstChild.isAttr())
{
Xobj a = x._firstChild;
while ( a._nextSibling != null && a._nextSibling.isAttr() )
a = a._nextSibling;
if (a._cchAfter > 0)
{
x = a;
p = a.posAfter();
}
else if (a._nextSibling != null)
{
x = a._nextSibling;
p = 0;
}
}
else
{
x = x._firstChild;
p = 0;
}
}
}
}
moveTo( getNormal( x, p ), _posTemp );
return true;
}
int prevChars ( int cch )
{
assert isPositioned();
int cchLeft = cchLeft();
if (cch < 0 || cch > cchLeft)
cch = cchLeft;
// Dang, I love this stmt :-)
if (cch != 0)
moveTo( getNormal( getDenormal(), _posTemp - cch ), _posTemp );
return cch;
}
int nextChars ( int cch )
{
assert isPositioned();
int cchRight = cchRight();
if (cchRight == 0)
return 0;
if (cch < 0 || cch >= cchRight)
{
// Use next to not skip over children
next();
return cchRight;
}
moveTo( getNormal( _xobj, _pos + cch ), _posTemp );
return cch;
}
void setCharNodes ( CharNode nodes )
{
assert nodes == null || _locale == nodes.locale();
assert isPositioned();
Xobj x = getDenormal();
int p = _posTemp;
assert !x.isRoot() || (p > 0 && p < x.posAfter());
if (p >= x.posAfter())
x._charNodesAfter = nodes;
else
x._charNodesValue = nodes;
for ( ; nodes != null ; nodes = nodes._next )
nodes.setDom( (Dom) x );
// No Need to notify text change or alter version, text nodes are
// not part of the infoset
}
CharNode getCharNodes ( )
{
assert isPositioned();
assert !isRoot();
Xobj x = getDenormal();
CharNode nodes;
if (_posTemp >= x.posAfter())
{
nodes = x._charNodesAfter =
updateCharNodes( _locale, x, x._charNodesAfter, x._cchAfter );
}
else
{
x.ensureOccupancy();
nodes = x._charNodesValue =
updateCharNodes( _locale, x, x._charNodesValue, x._cchValue );
}
return nodes;
}
// private
static CharNode updateCharNodes ( Locale l, Xobj x, CharNode nodes, int cch )
{
assert nodes == null || nodes.locale() == l;
CharNode node = nodes;
int i = 0;
while ( node != null && cch > 0 )
{
assert node.getDom() == x;
if (node._cch > cch)
node._cch = cch;
node._off = i;
i += node._cch;
cch -= node._cch;
node = node._next;
}
if (cch <= 0)
{
for ( ; node != null ; node = node._next )
{
assert node.getDom() == x;
if (node._cch != 0)
node._cch = 0;
node._off = i;
}
}
else
{
node = l.createTextNode();
node.setDom( (Dom) x );
node._cch = cch;
node._off = i;
nodes = CharNode.appendNode( nodes, node );
}
return nodes;
}
final QName getXsiTypeName ( )
{
assert isNode();
return _xobj.getXsiTypeName();
}
final void setXsiType ( QName value )
{
assert isContainer();
setAttrValueAsQName( Locale._xsiType, value );
}
final QName valueAsQName ( )
{
throw new RuntimeException( "Not implemented" );
}
final String namespaceForPrefix ( String prefix, boolean defaultAlwaysMapped )
{
return _xobj.namespaceForPrefix( prefix, defaultAlwaysMapped );
}
final String prefixForNamespace ( String ns, String suggestion, boolean createIfMissing )
{
return
(isContainer() ? _xobj : getParent()).
prefixForNamespace( ns, suggestion, createIfMissing );
}
// Does the node at this cursor properly contain the position specified by the argument
boolean contains ( Cur that )
{
assert isNode();
assert that != null && that.isPositioned();
return _xobj.contains( that );
}
void insertString ( String s )
{
if (s != null)
insertChars( s, 0, s.length() );
}
void insertChars ( Object src, int off, int cch )
{
assert isPositioned() && !isRoot();
assert CharUtil.isValid( src, off, cch );
// Check for nothing to insert
if (cch <= 0)
return;
_locale.notifyChange();
// The only situation where I need to ensure occupancy is when I'm at the end of a node.
// All other positions will require occupancy. For example, if I'm at the beginning of a
// node, then I will either insert in the after text of the previous sibling, or I will
// insert in the value of the parent. In the latter case, because the parent has a child,
// it cannot be vacant.
if (_pos == END_POS)
_xobj.ensureOccupancy();
// Get the denormailized Xobj and pos. This is the Xobj which will actually receive
// the new chars. Note that a denormalized position can never be <= 0.
Xobj x = getDenormal();
int p = _posTemp;
assert p > 0;
// This will move "this" cursor to be after the inserted text. No worries, I'll update its
// position after. This insertChars takes care of all the appropriate invalidations
// (passing true as last arg).
x.insertCharsHelper( p, src, off, cch, true );
// Reposition the cursor to be just before the newly inserted text. It's current
// position could have been shifted, or it may have been just before the end tag, or
// normalized on another Xobj.
moveTo( x, p );
_locale._versionAll++;
}
// Move the chars just after this Cur to the "to" Cur. If no "to" Cur is specified,
// then remove the chars.
Object moveChars ( Cur to, int cchMove )
{
assert isPositioned();
assert cchMove <= 0 || cchMove <= cchRight();
assert to == null || (to.isPositioned() && !to.isRoot());
if (cchMove < 0)
cchMove = cchRight();
// If we're instructed to move 0 characters, then return the null triple.
if (cchMove == 0)
{
_offSrc = 0;
_cchSrc = 0;
return null;
}
// Here I record the triple of the chars to move. I will return this. No need to save
// cch 'cause cchMove will be that value.
Object srcMoved = getChars( cchMove );
int offMoved = _offSrc;
// Either I'm moving text from the value or the after text. If after, then the container
// must be occupied. If in the value, because we're just before text, it must be occupied.
assert isText() && (_pos >= _xobj.posAfter() ? _xobj._parent : _xobj).isOccupied();
if (to == null)
{
// In this case, I'm removing chars vs moving them. Normally I would like to blow
// them away entirely, but if there are any references to those chars via a bookmark
// I need to keep them alive. I do this by moving these chars to a new root. Note
// that because Curs will stay behind, I don't have to check for them.
for ( Bookmark b = _xobj._bookmarks ; b != null ; b = b._next )
{
if (inChars( b, cchMove, false ))
{
Cur c = _locale.tempCur();
c.createRoot();
c.next();
Object chars = moveChars( c, cchMove );
c.release();
return chars;
}
}
}
else
{
// If the target, "to", is inside or on the edge of the text to be moved, then this
// is a no-op. In this case, I still want to return the text "moved".
//
// Note how I move "to" and this cur around. I move "to" to be at the beginning of the
// chars moved and "this" to be at the end. If the text were really moving to a
// different location, then "to" would be at the beginning of the newly moved chars,
// and "this" would be at the gap left by the newly removed chars.
if (inChars( to, cchMove, true ))
{
// BUGBUG - may want to consider shuffling the interior cursors to the right just
// like I move "this" to the right...
to.moveToCur( this );
nextChars( cchMove );
_offSrc = offMoved;
_cchSrc = cchMove;
return srcMoved;
}
// Copy the chars here, I'll remove the originals next
to.insertChars( srcMoved, offMoved, cchMove );
}
// Notice that I can delay the general change notification to this point because any
// modifications up to this point are made by calling other high level operations which
// generate this notification themselves. Also, no need to notify of general change in
// the "to" locale because the insertion of chars above handles that.
_locale.notifyChange();
//
//if ( _xobj != null )
{
if (to == null)
_xobj.removeCharsHelper( _pos, cchMove, null, NO_POS, false, true );
else
_xobj.removeCharsHelper( _pos, cchMove, to._xobj, to._pos, false, true );
}
// Need to update the position of this cursor even though it did not move anywhere. This
// needs to happen because it may not be properly normalized anymore. Note that because
// of the removal of the text, this cur may not be normal any more, thus I call moveTo
// which does not assume this.
_locale._versionAll++;
_offSrc = offMoved;
_cchSrc = cchMove;
return srcMoved;
}
void moveNode ( Cur to )
{
assert isNode() && !isRoot();
assert to == null || to.isPositioned();
assert to == null || !contains( to );
assert to == null || !to.isRoot();
// TODO - should assert that is an attr is being moved, it is ok there
// Record the node to move and skip this cur past it. This moves this cur to be after
// the move to move/remove -- it's final resting place. The only piece of information
// about the source of the move is the node itself.
Xobj x = _xobj;
skip();
// I call another function here to move the node. I do this because I don't have to
// worry about messing with "this" here given that it not should be treated like any other
// cursor after this point.
moveNode( x, to );
}
// Moves text from one place to another in a low-level way, used as a helper for the higher
// level functions. Takes care of moving bookmarks and cursors. In the high level content
// manipulation functions, cursors do not follow content, but this helper moves them. The
// arguments are denormalized. The Xobj's must be different from eachother but from the same
// locale. The destination must not be not be vacant.
private static void transferChars ( Xobj xFrom, int pFrom, Xobj xTo, int pTo, int cch )
{
assert xFrom != xTo;
assert xFrom._locale == xTo._locale;
assert pFrom > 0 && pFrom < xFrom.posMax();
assert pTo > 0 && pTo <= xTo .posMax();
assert cch > 0 && cch <= xFrom.cchRight( pFrom );
assert pTo >= xTo.posAfter() || xTo.isOccupied();
// Copy the chars from -> to without performing any invalidations. This will scoot curs
// and marks around appropriately. Note that I get the cars with getCharsHelper which
// does not check for normalization because the state of the tree at this moment may not
// exactly be "correct" here.
xTo.insertCharsHelper(
pTo, xFrom.getCharsHelper( pFrom, cch ),
xFrom._locale._offSrc, xFrom._locale._cchSrc, false );
xFrom.removeCharsHelper( pFrom, cch, xTo, pTo, true, false );
}
// Moves the node x to "to", or removes it if to is null.
static void moveNode ( Xobj x, Cur to )
{
assert x != null && !x.isRoot();
assert to == null || to.isPositioned();
assert to == null || !x.contains( to );
assert to == null || !to.isRoot();
if (to != null)
{
// Before I go much further, I want to make sure that if "to" is in the container of
// a vacant node, I get it occupied. I do not need to worry about the source being
// vacant.
if (to._pos == END_POS)
to._xobj.ensureOccupancy();
// See if the destination is on the edge of the node to be moved (a no-op). It is
// illegal to call this fcn when to is contained within the node to be moved. Note
// that I make sure that to gets oved to the beginning of the node. The position of
// to in all operations should leave to just before the content moved/inserted.
if ((to._pos == 0 && to._xobj == x) || to.isJustAfterEnd( x ))
{
// TODO - should shuffle contained curs to the right???
to.moveTo( x );
return;
}
}
// Notify the locale(s) about the change I am about to make.
x._locale.notifyChange();
x._locale._versionAll++;
x._locale._versionSansText++;
if (to != null && to._locale != x._locale)
{
to._locale.notifyChange();
to._locale._versionAll++;
to._locale._versionSansText++;
}
// Node is going away. Invalidate the parent (the text around the node is merging).
// Also, this node may be an attribute -- invalidate special attrs ...
if (x.isAttr())
x.invalidateSpecialAttr( to == null ? null : to.getParentRaw() );
else
{
if (x._parent != null)
x._parent.invalidateUser();
if (to != null && to.hasParent())
to.getParent().invalidateUser();
}
// If there is any text after x, I move it to be before x. This frees me to extract x
// and it's contents with out this text coming along for the ride. Note that if this
// node is the last attr and there is text after it, transferText will move the text
// to a potential previous attr. This is an invalid state for a short period of time.
// I need to move this text away here so that when I walk the tree next, *all* curs
// embedded in this node or deeper will be moved off this node.
if (x._cchAfter > 0)
transferChars( x, x.posAfter(), x.getDenormal( 0 ), x.posTemp(), x._cchAfter );
assert x._cchAfter == 0;
// Walk the node tree, moving curs out, disconnecting users and relocating to a, possibly,
// new locale. I embed the cursors in this locale before itersting to just cause the
// embed to happen once.
x._locale.embedCurs();
for ( Xobj y = x ; y != null ; y = y.walk( x, true ) )
{
while ( y._embedded != null )
y._embedded.moveTo( x.getNormal( x.posAfter() ) );
y.disconnectUser();
if (to != null)
y._locale = to._locale;
}
// Now, actually remove the node
x.removeXobj();
// Now, if there is a destination, insert the node there and shuffle the text in the
// vicinity of the destination appropriately.
if (to != null)
{
// To know where I should insert/append the node to move, I need to see where "to"
// would be if there were no text after it. However, I need to keep "to" where it
// is when I move the text after it later.
Xobj here = to._xobj;
boolean append = to._pos != 0;
int cchRight = to.cchRight();
if (cchRight > 0)
{
to.push();
to.next();
here = to._xobj;
append = to._pos != 0;
to.pop();
}
if (append)
here.appendXobj( x );
else
here.insertXobj( x );
// The only text I need to move is that to the right of "to". Even considering all
// the cases where an attribute is involed!
if (cchRight > 0)
transferChars( to._xobj, to._pos, x, x.posAfter(), cchRight );
to.moveTo( x );
}
}
void moveNodeContents ( Cur to, boolean moveAttrs )
{
assert _pos==0;
assert to == null || !to.isRoot();
// By calling this helper, I do not have to deal with this Cur any longer. Basically,
// this Cur is out of the picture, it behaves like any other cur at this point.
moveNodeContents( _xobj, to, moveAttrs );
}
static void moveNodeContents ( Xobj x, Cur to, boolean moveAttrs )
{
// TODO - should assert that is an attr is being moved, it is ok there
assert to == null || !to.isRoot();
// Collect a bit of information about the contents to move first. Note that the collection
// of this info must not cause a vacant value to become occupied.
boolean hasAttrs = x.hasAttrs();
boolean noSubNodesToMove = !x.hasChildren() && (!moveAttrs || !hasAttrs);
// Deal with the cases where only text is involved in the move
if (noSubNodesToMove)
{
// If we're vacant and there is no place to move a potential value, then I can avoid
// acquiring the text from the TypeStoreUser. Otherwise, there may be text here I
// need to move somewhere else.
if (x.isVacant() && to == null)
{
x.clearBit( Xobj.VACANT );
x.invalidateUser();
x.invalidateSpecialAttr( null );
x._locale._versionAll++;
}
else if (x.hasTextEnsureOccupancy())
{
Cur c = x.tempCur();
c.next();
c.moveChars( to, -1 );
c.release();
}
return;
}
// Here I check to see if "to" is just inside x. In this case this is a no-op. Note that
// the value of x may still be vacant.
if (to != null)
{
// Quick check of the right edge. If it is there, I need to move "to" to the left edge
// so that it is positioned at the beginning of the "moved" content.
if (x == to._xobj && to._pos == END_POS)
{
// TODO - shuffle interior curs?
to.moveTo( x );
to.next( moveAttrs && hasAttrs );
return;
}
// Here I need to see if to is at the left edge. I push to's current position and
// then navigate it to the left edge then compare it to the pushed position...
// Note: gotta be careful to make sure to and x are not in different locales, curs
// may not go to a different locale.
boolean isAtLeftEdge = false;
if (to._locale == x._locale)
{
to.push();
to.moveTo( x );
to.next( moveAttrs && hasAttrs );
isAtLeftEdge = to.isAtLastPush();
to.pop();
}
// TODO - shuffle interior curs?
if (isAtLeftEdge)
return;
// Now, after dealing with the edge condition, I can assert that to is not inside x
assert !x.contains( to );
// So, at this point, I've taken case of the no-op cases and the movement of just text.
// Also, to must be occupied because I took care of the text only and nothing to move
// cases.
assert to.getParent().isOccupied();
}
// TODO - did I forget to put a changeNotification here? Look more closely ...
// Deal with the value text of x which is either on x or the last attribute of x.
// I need to get it out of the way to properly deal with the walk of the contents.
// In order to reposition "to" properly later, I need to record how many chars were moved.
int valueMovedCch = 0;
if (x.hasTextNoEnsureOccupancy())
{
Cur c = x.tempCur();
c.next();
c.moveChars( to, -1 );
c.release();
if (to != null)
to.nextChars( valueMovedCch = c._cchSrc );
}
// Now, walk all the contents, invalidating special attrs, reportioning cursors,
// disconnecting users and relocating to a potentially different locale. Because I moved
// the value text above, no top level attrs should have any text.
x._locale.embedCurs();
Xobj firstToMove = x.walk( x, true );
boolean sawBookmark = false;
for ( Xobj y = firstToMove ; y != null ; y = y.walk( x, true ) )
{
if (y._parent == x && y.isAttr())
{
assert y._cchAfter == 0;
if (!moveAttrs)
{
firstToMove = y._nextSibling;
continue;
}
y.invalidateSpecialAttr( to == null ? null : to.getParent() );
}
for ( Cur c ; (c = y._embedded) != null ; )
c.moveTo( x, END_POS );
y.disconnectUser();
if (to != null)
y._locale = to._locale;
sawBookmark = sawBookmark || y._bookmarks != null;
}
Xobj lastToMove = x._lastChild;
// If there were any bookmarks in the tree to remove, to preserve the content that these
// bookmarks reference, move the contents to a new root. Note that I already moved the
// first piece of text above elsewhere. Note: this has the effect of keeping all of the
// contents alive even if there is one bookmark deep into the tree. I should really
// disband all the content, except for the pieces which are bookmarked.
Cur surragateTo = null;
if (sawBookmark && to == null)
{
surragateTo = to = x._locale.tempCur();
to.createRoot();
to.next();
}
// Perform the rest of the invalidations. If only attrs are moving, then no user
// invalidation needed. If I've move text to "to" already, no need to invalidate
// again.
if (!lastToMove.isAttr())
x.invalidateUser();
x._locale._versionAll++;
x._locale._versionSansText++;
if (to != null && valueMovedCch == 0)
{
to.getParent().invalidateUser();
to._locale._versionAll++;
to._locale._versionSansText++;
}
// Remove the children and, if needed, move them
x.removeXobjs( firstToMove, lastToMove );
if (to != null)
{
// To know where I should insert/append the contents to move, I need to see where "to"
// would be if there were no text after it.
Xobj here = to._xobj;
boolean append = to._pos != 0;
int cchRight = to.cchRight();
if (cchRight > 0)
{
to.push();
to.next();
here = to._xobj;
append = to._pos != 0;
to.pop();
}
// Now, I have to shuffle the text around "to" in special ways. A complication is
// the insertion of attributes. First, if I'm inserting attrs here then, logically,
// there can be no text to the left because attrs can only live after another attr
// or just inside a container. So, If attrs are being inserted and there is value
// text on the target container, I will need to move this value text to be after
// the lew last attribute. Note that this value text may already live on a current
// last attr (before the inserting). Also, I need to figure this all out before I
// move the text after "to" because this text may end up being sent to the same place
// as the containers value text when the last new node being inserted is an attr!
// Whew!
if (firstToMove.isAttr())
{
Xobj lastNewAttr = firstToMove;
while ( lastNewAttr._nextSibling != null && lastNewAttr._nextSibling.isAttr() )
lastNewAttr = lastNewAttr._nextSibling;
// Get to's parnet now before I potentially move him with the next transfer
Xobj y = to.getParent();
if (cchRight > 0)
transferChars( to._xobj, to._pos, lastNewAttr, lastNewAttr.posMax(), cchRight );
if (y.hasTextNoEnsureOccupancy())
{
int p, cch;
if (y._cchValue > 0)
{
p = 1;
cch = y._cchValue;
}
else
{
y = y.lastAttr();
p = y.posAfter();
cch = y._cchAfter;
}
transferChars( y, p, lastNewAttr, lastNewAttr.posAfter(), cch );
}
}
else if (cchRight > 0)
transferChars( to._xobj, to._pos, lastToMove, lastToMove.posMax(), cchRight );
// After mucking with the text, splice the new tree in
if (append)
here.appendXobjs( firstToMove, lastToMove );
else
here.insertXobjs( firstToMove, lastToMove );
// Position "to" to be at the beginning of the newly inserted contents
to.moveTo( firstToMove );
to.prevChars( valueMovedCch );
}
// If I consed up a to, release it here
if (surragateTo != null)
surragateTo.release();
}
protected final Bookmark setBookmark ( Object key, Object value )
{
assert isNormal();
assert key != null;
return _xobj.setBookmark( _pos, key, value );
}
Object getBookmark ( Object key )
{
assert isNormal();
assert key != null;
for ( Bookmark b = _xobj._bookmarks ; b != null ; b = b._next )
if (b._pos == _pos && b._key == key)
return b._value;
return null;
}
int firstBookmarkInChars ( Object key, int cch )
{
assert isNormal();
assert key != null;
assert cch > 0;
assert cch <= cchRight();
int d = -1;
if (isText())
{
for ( Bookmark b = _xobj._bookmarks ; b != null ; b = b._next )
if (b._key == key && inChars( b, cch, false ))
d = (d == -1 || b._pos - _pos < d) ? b._pos - _pos : d;
}
return d;
}
int firstBookmarkInCharsLeft ( Object key, int cch )
{
assert isNormal();
assert key != null;
assert cch > 0;
assert cch <= cchLeft();
int d = -1;
if (cchLeft() > 0)
{
Xobj x = getDenormal();
int p = _posTemp - cch;
for ( Bookmark b = x._bookmarks ; b != null ; b = b._next )
if (b._key == key && x.inChars( p, b._xobj, b._pos, cch, false ))
d = (d == -1 || b._pos - p < d) ? b._pos - p : d;
}
return d;
}
String getCharsAsString ( int cch )
{
assert isNormal() && _xobj != null;
return getCharsAsString( cch, Locale.WS_PRESERVE );
}
String getCharsAsString ( int cch, int wsr )
{
return _xobj.getCharsAsString( _pos, cch, wsr );
}
String getValueAsString ( int wsr )
{
assert isNode();
return _xobj.getValueAsString( wsr );
}
String getValueAsString ( )
{
assert isNode();
assert ! hasChildren();
return _xobj.getValueAsString();
}
Object getChars ( int cch )
{
assert isPositioned();
return _xobj.getChars( _pos, cch, this );
}
Object getFirstChars ( )
{
assert isNode();
Object src = _xobj.getFirstChars();
_offSrc = _locale._offSrc;
_cchSrc = _locale._cchSrc;
return src;
}
void copyNode ( Cur to )
{
assert to != null;
assert isNode();
Xobj copy = _xobj.copyNode( to._locale );
// TODO - in the moveNode case, I would not have to walk the tree for cursors ... optimize
if (to.isPositioned())
Cur.moveNode( copy, to );
else
to.moveTo( copy );
}
Cur weakCur ( Object o )
{
Cur c = _locale.weakCur( o );
c.moveToCur( this );
return c;
}
Cur tempCur ( )
{
return tempCur( null );
}
Cur tempCur ( String id )
{
Cur c = _locale.tempCur( id );
c.moveToCur( this );
return c;
}
private Cur tempCur ( Xobj x, int p )
{
assert _locale == x._locale;
assert x != null || p == NO_POS;
Cur c = _locale.tempCur();
if (x != null)
c.moveTo( getNormal( x, p ), _posTemp );
return c;
}
// Is a cursor (c) in the chars defined by cch chars after where this Cur is positioned.
// Is inclusive on the left, and inclusive/exclusive on the right depending on the value
// of includeEnd.
boolean inChars ( Cur c, int cch, boolean includeEnd )
{
assert isPositioned() && isText() && cchRight() >= cch;
assert c.isNormal();
return _xobj.inChars( _pos, c._xobj, c._pos, cch, includeEnd );
}
boolean inChars ( Bookmark b, int cch, boolean includeEnd )
{
assert isPositioned() && isText() && cchRight() >= cch;
assert b._xobj.isNormal( b._pos );
return _xobj.inChars( _pos, b._xobj, b._pos, cch, includeEnd );
}
// Can't be static because I need to communicate pos in _posTemp :-(
// I wish I had multiple return vars ...
private Xobj getNormal ( Xobj x, int p )
{
Xobj nx = x.getNormal( p );
_posTemp = x._locale._posTemp;
return nx;
}
private Xobj getDenormal ( )
{
assert isPositioned();
return getDenormal( _xobj, _pos );
}
private Xobj getDenormal ( Xobj x, int p )
{
Xobj dx = x.getDenormal( p );
_posTemp = x._locale._posTemp;
return dx;
}
// May throw IllegalArgumentException if can't change the type
void setType ( SchemaType type )
{
setType( type, true );
}
void setType ( SchemaType type, boolean complain )
{
assert type != null;
assert isUserNode();
TypeStoreUser user = peekUser();
if (user != null && user.get_schema_type() == type)
return;
if (isRoot())
{
_xobj.setStableType( type );
return;
}
// Gotta get the parent user to make sure this type is ok here
TypeStoreUser parentUser = _xobj.ensureParent().getUser();
// One may only set the type of an attribute to its 'natural' type because
// attributes cannot take advantage of the xsiType attribute.
if (isAttr())
{
if (complain && parentUser.get_attribute_type( getName() ) != type)
{
throw
new IllegalArgumentException(
"Can't set type of attribute to " + type.toString() );
}
return;
}
assert isElem();
// First check to see if this type can be here sans xsi:type.
// If so, make sure there is no xsi:type
if (parentUser.get_element_type( getName(), null ) == type)
{
removeAttr( Locale._xsiType );
return;
}
// If the desired type has no name, then it cannot be
// referenced via xsi:type
QName typeName = type.getName();
if (typeName == null)
{
if (complain)
throw new IllegalArgumentException( "Can't set type of element, type is un-named" );
else
return;
}
// See if setting xsiType would result in the target type
if (parentUser.get_element_type( getName(), typeName ) != type)
{
if (complain)
throw new IllegalArgumentException( "Can't set type of element, invalid type" );
else
return;
}
setAttrValueAsQName( Locale._xsiType, typeName );
}
void setSubstitution ( QName name, SchemaType type )
{
setSubstitution( name, type, true );
}
void setSubstitution ( QName name, SchemaType type, boolean complain )
{
assert name != null;
assert type != null;
assert isUserNode();
TypeStoreUser user = peekUser();
if (user != null && user.get_schema_type() == type && name.equals(getName()))
return;
if (isRoot())
{
// If this is the root node, we can't set its name, so the whole
// operation is aborted
return;
}
// Gotta get the parent user to make sure this type is ok here
TypeStoreUser parentUser = _xobj.ensureParent().getUser();
// One may only set the type of an attribute to its 'natural' type because
// attributes cannot take advantage of the xsiType attribute.
if (isAttr())
{
if (complain)
{
throw
new IllegalArgumentException(
"Can't use substitution with attributes");
}
return;
}
assert isElem();
// First check to see if this type can be here sans xsi:type.
// If so, make sure there is no xsi:type
if (parentUser.get_element_type( name, null ) == type)
{
setName( name );
removeAttr( Locale._xsiType );
return;
}
// If the desired type has no name, then it cannot be
// referenced via xsi:type
QName typeName = type.getName();
if (typeName == null)
{
if (complain)
throw new IllegalArgumentException( "Can't set xsi:type on element, type is un-named" );
else
return;
}
// See if setting xsiType would result in the target type
if (parentUser.get_element_type( name, typeName ) != type)
{
if (complain)
throw new IllegalArgumentException( "Can't set xsi:type on element, invalid type" );
else
return;
}
setName( name );
setAttrValueAsQName( Locale._xsiType, typeName );
}
TypeStoreUser peekUser ( )
{
assert isUserNode();
return _xobj._user;
}
XmlObject getObject ( )
{
return isUserNode() ? (XmlObject) getUser() : null;
}
TypeStoreUser getUser ( )
{
assert isUserNode();
return _xobj.getUser();
}
Dom getDom ( )
{
assert isNormal();
assert isPositioned();
if (isText())
{
int cch = cchLeft();
for ( CharNode cn = getCharNodes() ; ; cn = cn._next )
if ((cch -= cn._cch) < 0)
return cn;
}
return _xobj.getDom();
}
static void release ( Cur c )
{
if (c != null)
c.release();
}
void release ( )
{
if (_tempFrame >= 0)
{
if (_nextTemp != null)
_nextTemp._prevTemp = _prevTemp;
if (_prevTemp == null)
_locale._tempFrames[ _tempFrame ] = _nextTemp;
else
_prevTemp._nextTemp = _nextTemp;
_prevTemp = _nextTemp = null;
_tempFrame = -1;
}
if (_state != POOLED && _state != DISPOSED)
{
// Clean up any state
while ( _stackTop != -1 )
popButStay();
clearSelection();
_id = null;
// Unposition
moveToCur( null );
assert isNormal();
assert _xobj == null;
assert _pos == NO_POS;
// Release weak reference and attacked value
if (_ref != null)
{
_ref.clear();
_ref._cur = null;
}
_ref = null;
// Unregister and either diapose of cursor or add it back to pool
assert _state == REGISTERED;
_locale._registered = listRemove( _locale._registered );
if (_locale._curPoolCount < 16)
{
_locale._curPool = listInsert( _locale._curPool );
_state = POOLED;
_locale._curPoolCount++;
}
else
{
_locale = null;
_state = DISPOSED;
}
}
}
boolean isOnList ( Cur head )
{
for ( ; head != null ; head = head._next )
if (head == this)
return true;
return false;
}
Cur listInsert ( Cur head )
{
assert _next == null && _prev == null;
if (head == null)
head = _prev = this;
else
{
_prev = head._prev;
head._prev = head._prev._next = this;
}
return head;
}
Cur listRemove ( Cur head )
{
assert _prev != null && isOnList( head );
if (_prev == this)
head = null;
else
{
if (head == this)
head = _next;
else
_prev._next = _next;
if (_next == null)
head._prev = _prev;
else
{
_next._prev = _prev;
_next = null;
}
}
_prev = null;
assert _next == null;
return head;
}
// boolean isNormal ( Cur that )
// {
// return isNormal() && (that == null || (_locale == that._locale && that.isNormal()));
// }
boolean isNormal ( )
{
if (_state == POOLED || _state == DISPOSED)
return false;
if (_xobj == null)
return _pos == NO_POS;
if (!_xobj.isNormal( _pos ))
return false;
if (_state == EMBEDDED)
return isOnList( _xobj._embedded );
assert _state == REGISTERED;
return isOnList( _locale._registered );
}
static final String LOAD_USE_LOCALE_CHAR_UTIL = "LOAD_USE_LOCALE_CHAR_UTIL";
static final class CurLoadContext extends LoadContext
{
CurLoadContext ( Locale l, XmlOptions options )
{
options = XmlOptions.maskNull( options );
_locale = l;
_charUtil =
options.hasOption( LOAD_USE_LOCALE_CHAR_UTIL )
? _locale.getCharUtil()
: CharUtil.getThreadLocalCharUtil();
_frontier = createDomDocumentRootXobj( _locale );
_after = false;
_lastXobj = _frontier;
_lastPos = 0;
if (options.hasOption( XmlOptions.LOAD_REPLACE_DOCUMENT_ELEMENT ))
{
_replaceDocElem = (QName) options.get( XmlOptions.LOAD_REPLACE_DOCUMENT_ELEMENT );
_discardDocElem = true;
}
_stripWhitespace = options.hasOption( XmlOptions.LOAD_STRIP_WHITESPACE );
_stripComments = options.hasOption( XmlOptions.LOAD_STRIP_COMMENTS );
_stripProcinsts = options.hasOption( XmlOptions.LOAD_STRIP_PROCINSTS );
_substituteNamespaces = (Map) options.get( XmlOptions.LOAD_SUBSTITUTE_NAMESPACES );
_additionalNamespaces = (Map) options.get( XmlOptions.LOAD_ADDITIONAL_NAMESPACES );
_locale._versionAll++;
_locale._versionSansText++;
}
//
// Really primitive load context operations
//
private void start ( Xobj xo )
{
assert _frontier != null;
assert !_after || _frontier._parent != null;
flushText();
if (_after)
{
_frontier = _frontier._parent;
_after = false;
}
_frontier.appendXobj( xo );
_frontier = xo;
_lastXobj = xo;
_lastPos = 0;
}
private void end ( )
{
assert _frontier != null;
assert !_after || _frontier._parent != null;
flushText();
if (_after)
_frontier = _frontier._parent;
else
_after = true;
_lastXobj = _frontier;
_lastPos = END_POS;
}
private void text ( Object src, int off, int cch )
{
if (cch <= 0)
return;
_lastXobj = _frontier;
_lastPos = _frontier._cchValue + 1;
if (_after)
{
_lastPos += _frontier._cchAfter + 1;
_frontier._srcAfter =
_charUtil.saveChars(
src, off, cch,
_frontier._srcAfter, _frontier._offAfter, _frontier._cchAfter );
_frontier._offAfter = _charUtil._offSrc;
_frontier._cchAfter = _charUtil._cchSrc;
}
else
{
_frontier._srcValue =
_charUtil.saveChars(
src, off, cch,
_frontier._srcValue, _frontier._offValue, _frontier._cchValue );
_frontier._offValue = _charUtil._offSrc;
_frontier._cchValue = _charUtil._cchSrc;
}
}
private void flushText ( )
{
if (_stripWhitespace)
{
if (_after)
{
_frontier._srcAfter =
_charUtil.stripRight(
_frontier._srcAfter, _frontier._offAfter, _frontier._cchAfter );
_frontier._offAfter = _charUtil._offSrc;
_frontier._cchAfter = _charUtil._cchSrc;
}
else
{
_frontier._srcValue =
_charUtil.stripRight(
_frontier._srcValue, _frontier._offValue, _frontier._cchValue );
_frontier._offValue = _charUtil._offSrc;
_frontier._cchValue = _charUtil._cchSrc;
}
}
}
private Xobj parent ( )
{
return _after ? _frontier._parent : _frontier;
}
private QName checkName ( QName name, boolean local )
{
if (_substituteNamespaces != null && (!local || name.getNamespaceURI().length() > 0))
{
String substituteUri = (String) _substituteNamespaces.get( name.getNamespaceURI() );
if (substituteUri != null)
name = _locale.makeQName( substituteUri, name.getLocalPart(), name.getPrefix());
}
return name;
}
//
//
//
protected void startDTD (String name, String publicId, String systemId )
{
_doctypeName = name;
_doctypePublicId = publicId;
_doctypeSystemId = systemId;
}
protected void endDTD ( )
{
}
protected void startElement ( QName name )
{
start( createElementXobj( _locale, checkName( name, false ), parent()._name ) );
_stripLeft = true;
}
protected void endElement ( )
{
assert parent().isElem();
end();
_stripLeft = true;
}
protected void xmlns ( String prefix, String uri )
{
assert parent().isContainer();
// BUGBUG - should assert there that there is no text before this attr
// Namespace attrs are different than regular attrs -- I don't change their name,
// I change their value!
if (_substituteNamespaces != null)
{
String substituteUri = (String) _substituteNamespaces.get( uri );
if (substituteUri != null)
uri = substituteUri;
}
Xobj x = new Xobj.AttrXobj( _locale, _locale.createXmlns( prefix ) );
start( x );
text( uri, 0, uri.length() );
end();
_lastXobj = x;
_lastPos = 0;
}
protected void attr ( QName name, String value )
{
assert parent().isContainer();
// BUGBUG - should assert there that there is no text before this attr
QName parentName = _after?
_lastXobj._parent.getQName(): _lastXobj.getQName();
boolean isId = isAttrOfTypeId(name, parentName);
Xobj x = isId ?
new Xobj.AttrIdXobj(_locale, checkName(name, true)) :
new Xobj.AttrXobj(_locale, checkName(name, true));
start(x);
text(value, 0, value.length());
end();
if (isId)
{
Cur c1 = x.tempCur();
c1.toRoot();
Xobj doc = c1._xobj;
c1.release();
if (doc instanceof Xobj.DocumentXobj)
((Xobj.DocumentXobj) doc).addIdElement(value,
x._parent.getDom());
}
_lastXobj = x;
_lastPos = 0;
}
protected void attr ( String local, String uri, String prefix, String value )
{
attr( _locale.makeQName( uri, local, prefix ), value );
}
protected void procInst ( String target, String value )
{
if (!_stripProcinsts)
{
Xobj x = new Xobj.ProcInstXobj( _locale, target );
start( x );
text( value, 0, value.length() );
end();
_lastXobj = x;
_lastPos = 0;
}
_stripLeft = true;
}
protected void comment ( String comment )
{
if (!_stripComments)
comment( comment, 0, comment.length() );
_stripLeft = true;
}
protected void comment ( char[] chars, int off, int cch )
{
if (!_stripComments)
{
comment(
_charUtil.saveChars( chars, off, cch ),
_charUtil._offSrc, _charUtil._cchSrc );
}
_stripLeft = true;
}
private void comment ( Object src, int off, int cch )
{
Xobj x = new Xobj.CommentXobj( _locale );
start( x );
text( src, off, cch );
end();
_lastXobj = x;
_lastPos = 0;
}
private boolean _stripLeft = true;
private void stripText ( Object src, int off, int cch )
{
if (_stripWhitespace)
{
// this is to avoid bug in cases like Procter & Gamble
if (_stripLeft)
{
src = _charUtil.stripLeft( src, off, cch );
_stripLeft = false;
off = _charUtil._offSrc;
cch = _charUtil._cchSrc;
}
}
text( src, off, cch );
}
protected void text ( String s )
{
if (s == null)
return;
stripText( s, 0, s.length() );
}
protected void text ( char[] src, int off, int cch )
{
stripText( src, off, cch );
}
protected void bookmark ( XmlBookmark bm )
{
_lastXobj.setBookmark( _lastPos, bm.getKey(), bm );
}
protected void bookmarkLastNonAttr ( XmlBookmark bm )
{
if (_lastPos > 0 || !_lastXobj.isAttr())
_lastXobj.setBookmark( _lastPos, bm.getKey(), bm );
else
{
assert _lastXobj._parent != null;
_lastXobj._parent.setBookmark( 0, bm.getKey(), bm );
}
}
protected void bookmarkLastAttr ( QName attrName, XmlBookmark bm )
{
if (_lastPos == 0 && _lastXobj.isAttr())
{
assert _lastXobj._parent != null;
Xobj a = _lastXobj._parent.getAttr( attrName );
if (a != null)
a.setBookmark( 0, bm.getKey(), bm );
}
}
protected void lineNumber ( int line, int column, int offset )
{
_lastXobj.setBookmark(
_lastPos,
XmlLineNumber.class,
new XmlLineNumber( line, column, offset ) );
}
protected void abort ( )
{
_stripLeft = true;
while ( !parent().isRoot() )
end();
finish().release();
}
protected Cur finish ( )
{
flushText();
if (_after)
_frontier = _frontier._parent;
assert _frontier != null && _frontier._parent == null && _frontier.isRoot();
Cur c = _frontier.tempCur();
if (!Locale.toFirstChildElement( c ))
return c;
// See if the document element is a fragment
boolean isFrag = Locale.isFragmentQName( c.getName() );
if (_discardDocElem || isFrag)
{
if (_replaceDocElem != null)
c.setName( _replaceDocElem );
else
{
// Remove the content around the element to remove so that that content
// does not appear to have been the contents of the removed element.
while ( c.toParent() )
;
c.next();
while ( !c.isElem() )
if (c.isText()) c.moveChars( null, -1 ); else c.moveNode( null );
assert c.isElem();
c.skip();
while ( !c.isFinish() )
if (c.isText()) c.moveChars( null, -1 ); else c.moveNode( null );
c.toParent();
c.next();
assert c.isElem();
Cur c2 = c.tempCur();
c.moveNodeContents( c, true );
c.moveToCur( c2 );
c2.release();
c.moveNode( null );
}
// Remove the fragment namespace decl
if (isFrag)
{
c.moveTo( _frontier );
if (c.toFirstAttr())
{
for ( ; ; )
{
if (c.isXmlns() && c.getXmlnsUri().equals( Locale._openFragUri ))
{
c.moveNode( null );
if (!c.isAttr())
break;
}
else if (!c.toNextAttr())
break;
}
}
c.moveTo(_frontier);
_frontier = createDomDocumentRootXobj( _locale, true );
Cur c2 = _frontier.tempCur();
c2.next();
c.moveNodeContents(c2, true);
c.moveTo(_frontier);
c2.release();
}
}
if (_additionalNamespaces != null)
{
c.moveTo( _frontier );
Locale.toFirstChildElement( c );
Locale.applyNamespaces( c, _additionalNamespaces );
}
if (_doctypeName != null && (_doctypePublicId != null || _doctypeSystemId != null))
{
XmlDocumentProperties props = Locale.getDocProps(c, true);
props.setDoctypeName(_doctypeName);
if (_doctypePublicId != null)
props.setDoctypePublicId(_doctypePublicId);
if (_doctypeSystemId != null)
props.setDoctypeSystemId(_doctypeSystemId);
}
c.moveTo( _frontier );
assert c.isRoot();
return c;
}
public void dump ( )
{
_frontier.dump();
}
private Locale _locale;
private CharUtil _charUtil;
private Xobj _frontier;
private boolean _after;
private Xobj _lastXobj;
private int _lastPos;
private boolean _discardDocElem;
private QName _replaceDocElem;
private boolean _stripWhitespace;
private boolean _stripComments;
private boolean _stripProcinsts;
private Map _substituteNamespaces;
private Map _additionalNamespaces;
private String _doctypeName;
private String _doctypePublicId;
private String _doctypeSystemId;
}
//
//
//
static String kindName ( int kind )
{
switch ( kind )
{
case ROOT : return "ROOT";
case ELEM : return "ELEM";
case ATTR : return "ATTR";
case COMMENT : return "COMMENT";
case PROCINST : return "PROCINST";
case TEXT : return "TEXT";
default : return "<< Unknown Kind (" + kind + ") >>";
}
}
static void dump ( PrintStream o, Dom d, Object ref )
{
}
static void dump ( PrintStream o, Dom d )
{
d.dump( o );
}
static void dump ( Dom d )
{
dump( System.out, d );
}
static void dump ( Node n )
{
dump( System.out, n );
}
static void dump ( PrintStream o, Node n )
{
dump( o, (Dom) n );
}
void dump ( )
{
dump( System.out, _xobj, this );
}
void dump ( PrintStream o )
{
if (_xobj == null)
{
o.println( "Unpositioned xptr" );
return;
}
dump( o, _xobj, this );
}
public static void dump ( PrintStream o, Xobj xo, Object ref )
{
if (ref == null)
ref = xo;
while ( xo._parent != null )
xo = xo._parent;
dumpXobj( o, xo, 0, ref );
o.println();
}
private static void dumpCur ( PrintStream o, String prefix, Cur c, Object ref )
{
o.print( " " );
if (ref == c)
o.print( "*:" );
o.print( prefix + (c._id == null ? "" : c._id) + "[" + c._pos + "]" );
}
private static void dumpCurs ( PrintStream o, Xobj xo, Object ref )
{
for ( Cur c = xo._embedded ; c != null ; c = c._next )
dumpCur( o, "E:", c, ref );
for ( Cur c = xo._locale._registered ; c != null ; c = c._next )
{
if (c._xobj == xo)
dumpCur( o, "R:", c, ref );
}
}
private static void dumpBookmarks ( PrintStream o, Xobj xo, Object ref )
{
for ( Bookmark b = xo._bookmarks ; b != null ; b = b._next )
{
o.print( " " );
if (ref == b)
o.print( "*:" );
if (b._value instanceof XmlLineNumber)
{
XmlLineNumber l = (XmlLineNumber) b._value;
o.print( "" + "[" + b._pos + "]" );
}
else
o.print( "" + "[" + b._pos + "]" );
}
}
private static void dumpCharNodes ( PrintStream o, CharNode nodes, Object ref )
{
for ( CharNode n = nodes ; n != null ; n = n._next )
{
o.print( " " );
if (n == ref)
o.print( "*" );
o.print( (n instanceof TextNode ? "TEXT" : "CDATA") + "[" + n._cch + "]" );
}
}
private static void dumpChars ( PrintStream o, Object src, int off, int cch )
{
// CharUtil.dumpChars( o, src, off, cch );
o.print( "\"" );
String s = CharUtil.getString( src, off, cch );
for ( int i = 0 ; i < s.length() ; i++ )
{
if (i== 36)
{
o.print( "..." );
break;
}
char ch = s.charAt( i );
if (ch >= 32 && ch < 127)
o.print( ch );
else if (ch == '\n')
o.print( "\\n" );
else if (ch == '\r')
o.print( "\\r" );
else if (ch == '\t')
o.print( "\\t" );
else if (ch == '\"')
o.print( "\\\"" );
else
o.print( "<#" + ((int) ch) + ">" );
}
o.print( "\"" );
}
private static void dumpXobj ( PrintStream o, Xobj xo, int level, Object ref )
{
if (xo == null)
return;
if (xo == ref)
o.print( "* " );
else
o.print( " " );
for ( int i = 0 ; i < level ; i++ )
o.print( " " );
o.print( kindName( xo.kind() ) );
if (xo._name != null)
{
o.print( " " );
if (xo._name.getPrefix().length() > 0)
o.print( xo._name.getPrefix() + ":" );
o.print( xo._name.getLocalPart() );
if (xo._name.getNamespaceURI().length() > 0)
o.print( "@" + xo._name.getNamespaceURI() );
}
if (xo._srcValue != null || xo._charNodesValue != null)
{
o.print( " Value( " );
dumpChars( o, xo._srcValue, xo._offValue, xo._cchValue );
dumpCharNodes( o, xo._charNodesValue, ref );
o.print( " )" );
}
if (xo._user != null)
o.print( " (USER)" );
if (xo.isVacant())
o.print( " (VACANT)" );
if (xo._srcAfter != null || xo._charNodesAfter != null)
{
o.print( " After( " );
dumpChars( o, xo._srcAfter, xo._offAfter, xo._cchAfter );
dumpCharNodes( o, xo._charNodesAfter, ref );
o.print( " )" );
}
dumpCurs( o, xo, ref );
dumpBookmarks( o, xo, ref );
String className = xo.getClass().getName();
int i = className.lastIndexOf( '.' );
if (i > 0)
{
className = className.substring( i + 1 );
i = className.lastIndexOf( '$' );
if (i > 0)
className = className.substring( i + 1 );
}
o.print( " (" );
o.print( className );
o.print( ")" );
o.println();
for ( xo = xo._firstChild ; xo != null ; xo = xo._nextSibling )
dumpXobj( o, xo, level + 1, ref );
}
void setId ( String id )
{
_id = id;
}
//
//
//
Locale _locale;
Xobj _xobj;
int _pos;
int _state;
String _id;
Cur _nextTemp;
Cur _prevTemp;
int _tempFrame;
Cur _next;
Cur _prev;
Locale.Ref _ref;
int _stackTop;
int _selectionFirst;
int _selectionN;
int _selectionLoc;
int _selectionCount;
private int _posTemp;
int _offSrc;
int _cchSrc;
} xmlbeans-2.6.0/src/store/org/apache/xmlbeans/impl/store/Validate.java 0000644 0001750 0001750 00000016620 11361341572 023715 0 ustar apo apo /* 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.impl.store;
import org.apache.xmlbeans.impl.common.ValidatorListener;
import javax.xml.stream.Location;
import org.apache.xmlbeans.XmlCursor;
import javax.xml.namespace.QName;
final class Validate implements ValidatorListener.Event
{
Validate ( Cur c, ValidatorListener sink )
{
if (!c.isUserNode())
throw new IllegalStateException( "Inappropriate location to validate" );
_sink = sink;
_cur = c;
_textCur = c.tempCur();
_hasText = false;
_cur.push();
try
{
process();
}
finally
{
_cur.pop();
_cur = null;
_sink = null;
_textCur.release();
}
}
private void process ( )
{
emitEvent( ValidatorListener.BEGIN );
if (_cur.isAttr())
{
// If validating an attr, I'm really validating the contents of that attr. So, go to
// any text value and shove it thru the validator.
_cur.next();
if (_cur.isText())
emitText();
}
else
{
assert _cur.isContainer();
// Do the attrs of the top container
doAttrs();
for ( _cur.next() ; ! _cur.isAtEndOfLastPush() ; _cur.next() )
{
switch ( _cur.kind() )
{
case Cur.ELEM :
emitEvent( ValidatorListener.BEGIN );
doAttrs();
break;
case - Cur.ELEM :
emitEvent( ValidatorListener.END );
break;
case Cur.TEXT :
emitText();
break;
case Cur.COMMENT :
case Cur.PROCINST :
_cur.toEnd();
break;
default :
throw new RuntimeException( "Unexpected kind: " + _cur.kind() );
}
}
}
emitEvent( ValidatorListener.END );
}
private void doAttrs ( )
{
// When processing attrs, there can be no accumulated text because there would have been
// a preceeding event which would have flushged the text.
assert !_hasText;
if (_cur.toFirstAttr())
{
do
{
if (_cur.isNormalAttr() && !_cur.getUri().equals( Locale._xsi ))
_sink.nextEvent( ValidatorListener.ATTR, this );
}
while ( _cur.toNextAttr() );
_cur.toParent();
}
_sink.nextEvent( ValidatorListener.ENDATTRS, this );
}
private void emitText ( )
{
assert _cur.isText();
if (_hasText)
{
if (_oneChunk)
{
if (_textSb == null)
_textSb = new StringBuffer();
else
_textSb.delete( 0, _textSb.length() );
assert _textCur.isText();
CharUtil.getString(
_textSb, _textCur.getChars( -1 ), _textCur._offSrc, _textCur._cchSrc );
_oneChunk = false;
}
assert _textSb != null && _textSb.length() > 0;
CharUtil.getString( _textSb, _cur.getChars( -1 ), _cur._offSrc, _cur._cchSrc );
}
else
{
_hasText = true;
_oneChunk = true;
_textCur.moveToCur( _cur );
}
}
private void emitEvent ( int kind )
{
assert kind != ValidatorListener.TEXT;
assert kind != ValidatorListener.ATTR || !_hasText;
assert kind != ValidatorListener.ENDATTRS || !_hasText;
if (_hasText)
{
_sink.nextEvent( ValidatorListener.TEXT, this );
_hasText = false;
}
_sink.nextEvent( kind, this );
}
public String getText ( )
{
if (_cur.isAttr())
return _cur.getValueAsString();
assert _hasText;
assert _oneChunk || (_textSb != null && _textSb.length() > 0);
assert !_oneChunk || _textCur.isText();
return _oneChunk ? _textCur.getCharsAsString( -1 ) : _textSb.toString();
}
public String getText ( int wsr )
{
if (_cur.isAttr())
return _cur.getValueAsString( wsr );
assert _hasText;
assert _oneChunk || (_textSb != null && _textSb.length() > 0);
assert !_oneChunk || _textCur.isText();
if (_oneChunk)
return _textCur.getCharsAsString( -1, wsr );
return Locale.applyWhiteSpaceRule( _textSb.toString(), wsr );
}
public boolean textIsWhitespace ( )
{
if (_cur.isAttr())
{
return
_cur._locale.getCharUtil().isWhiteSpace(
_cur.getFirstChars(), _cur._offSrc, _cur._cchSrc );
}
assert _hasText;
if (_oneChunk)
{
return
_cur._locale.getCharUtil().isWhiteSpace(
_textCur.getChars( -1 ), _textCur._offSrc, _textCur._cchSrc );
}
String s = _textSb.toString();
return _cur._locale.getCharUtil().isWhiteSpace( s, 0, s.length() );
}
public String getNamespaceForPrefix ( String prefix )
{
return _cur.namespaceForPrefix( prefix, true );
}
public XmlCursor getLocationAsCursor ( )
{
return new Cursor( _cur );
}
public Location getLocation ( )
{
return null;
}
public String getXsiType ( )
{
return _cur.getAttrValue( Locale._xsiType );
}
public String getXsiNil ( )
{
return _cur.getAttrValue( Locale._xsiNil );
}
public String getXsiLoc ( )
{
return _cur.getAttrValue( Locale._xsiLoc );
}
public String getXsiNoLoc ( )
{
return _cur.getAttrValue( Locale._xsiNoLoc );
}
public QName getName ( )
{
return _cur.isAtLastPush() ? null : _cur.getName();
}
//
//
//
private ValidatorListener _sink;
private Cur _cur;
// Two ways to accumulate text. First, I can have a Cur positioned at the text. I do this
// instead of getting the there there because white space rules are applied at a later point.
// This way, when I turn the text into a String, I can cache the string. If multiple chunks
// of text exists for one event, then I accumulate all the text into a string buffer and I,
// then, don't care about caching Strings.
private boolean _hasText;
private boolean _oneChunk;
private Cur _textCur;
private StringBuffer _textSb;
} xmlbeans-2.6.0/src/store/org/apache/xmlbeans/impl/store/QueryDelegate.java 0000644 0001750 0001750 00000005353 11361341572 024725 0 ustar apo apo /* 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.impl.store;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.lang.reflect.Constructor;
public final class QueryDelegate
{
private static HashMap _constructors = new HashMap();
private QueryDelegate()
{}
private static synchronized void init(String implClassName)
{
// default to Saxon
if (implClassName == null)
implClassName = "org.apache.xmlbeans.impl.xquery.saxon.XBeansXQuery";
Class queryInterfaceImpl = null;
boolean engineAvailable = true;
try
{
queryInterfaceImpl = Class.forName(implClassName);
}
catch (ClassNotFoundException e)
{
engineAvailable = false;
}
catch (NoClassDefFoundError e)
{
engineAvailable = false;
}
if (engineAvailable)
{
try
{
Constructor constructor = queryInterfaceImpl.getConstructor(
new Class[] {String.class, String.class, Integer.class});
_constructors.put(implClassName, constructor);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
public static synchronized QueryInterface createInstance(String implClassName,
String query, String contextVar, int boundary)
{
if (_constructors.get(implClassName) == null)
init(implClassName);
if (_constructors.get(implClassName) == null)
return null;
Constructor constructor = (Constructor)_constructors.get(implClassName);
try
{
return (QueryInterface)constructor.newInstance(
new Object[] {query, contextVar, new Integer(boundary)});
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public static interface QueryInterface
{
public List execQuery(Object node, Map variableBindings);
}
}
xmlbeans-2.6.0/src/typeholder/ 0000755 0001750 0001750 00000000000 11361341570 014417 5 ustar apo apo xmlbeans-2.6.0/src/typeholder/org/ 0000755 0001750 0001750 00000000000 11361341570 015206 5 ustar apo apo xmlbeans-2.6.0/src/typeholder/org/apache/ 0000755 0001750 0001750 00000000000 11361341570 016427 5 ustar apo apo xmlbeans-2.6.0/src/typeholder/org/apache/xmlbeans/ 0000755 0001750 0001750 00000000000 11361341570 020240 5 ustar apo apo xmlbeans-2.6.0/src/typeholder/org/apache/xmlbeans/impl/ 0000755 0001750 0001750 00000000000 11361341570 021201 5 ustar apo apo xmlbeans-2.6.0/src/typeholder/org/apache/xmlbeans/impl/schema/ 0000755 0001750 0001750 00000000000 13041512717 022441 5 ustar apo apo xmlbeans-2.6.0/src/typeholder/org/apache/xmlbeans/impl/schema/TypeSystemHolder.java 0000644 0001750 0001750 00000006626 11361341570 026602 0 ustar apo apo /* 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.impl.schema;
import org.apache.xmlbeans.SchemaTypeSystem;
/**
* This class is the hook which causes the SchemaTypeSystem to be loaded when
* a generated class is used. It isn't used by the runtime directly, instead
* this class is used by the schema compiler as a template class. By using a
* template class, the SchemaTypeSystemImpl can create all the binary files
* required without needing to rely on javac. The generated source still
* requires a java compiler.
*
* @see SchemaTypeSystemImpl.save()
*/
//
// !!! It's important that there never NEVER be any references to this class because
// !!! the static initializer will fail. This class must only be used as a class file.
// !!! If this scares you, turn back now !!!
//
// !!! If you modify this class, you will have to run bootstrap.
// !!! If this scares you, turn back now !!!
//
public class TypeSystemHolder
{
private TypeSystemHolder() { }
public static final SchemaTypeSystem typeSystem = loadTypeSystem();
// Commenting out this line has the effect of not loading all components in a
// typesystem upfront, but just as they are needed, which may improve
// performance significantly
//static { typeSystem.resolve(); }
private static final SchemaTypeSystem loadTypeSystem()
{
try
{
// The fact that we are using TypeSystemHolder.class.getClassLoader()
// to load the SchemaTypeSystem class means that the TypeSystemHolder's
// classloader MUST be a descendant of the XmlBeans classloader, even
// though it can be different.
// In other words, each Schema type has only one copy per VM, not one
// copy per copy of XmlBeans in use, therefore this implies that
// there either must be one copy of XmlBeans in the VM or copies in
// different classloaders will each need a different copy of one
// Schema type, which seems a reasonable restriction, but needs to be
// understood nevertheless
return (SchemaTypeSystem)
Class.forName(
"org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl",
true, TypeSystemHolder.class.getClassLoader())
.getConstructor(new Class[] { Class.class })
.newInstance(new java.lang.Object[] { TypeSystemHolder.class });
}
catch (ClassNotFoundException e)
{
throw new RuntimeException("Cannot load org.apache.xmlbeans.impl.SchemaTypeSystemImpl: make sure xbean.jar is on the classpath.", e);
}
catch (Exception e)
{
throw new RuntimeException("Could not instantiate SchemaTypeSystemImpl (" + e.toString() + "): is the version of xbean.jar correct?", e);
}
}
}
xmlbeans-2.6.0/src/typeimpl/ 0000755 0001750 0001750 00000000000 11361341573 014106 5 ustar apo apo xmlbeans-2.6.0/src/typeimpl/org/ 0000755 0001750 0001750 00000000000 11361341573 014675 5 ustar apo apo xmlbeans-2.6.0/src/typeimpl/org/apache/ 0000755 0001750 0001750 00000000000 11361341573 016116 5 ustar apo apo xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/ 0000755 0001750 0001750 00000000000 11361341574 017730 5 ustar apo apo xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/ 0000755 0001750 0001750 00000000000 11365605076 020675 5 ustar apo apo xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/util/ 0000755 0001750 0001750 00000000000 13041512717 021642 5 ustar apo apo xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/util/XsTypeConverter.java 0000644 0001750 0001750 00000060544 11361341574 025646 0 ustar apo apo /* 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.impl.util;
import org.apache.xmlbeans.GDate;
import org.apache.xmlbeans.GDateBuilder;
import org.apache.xmlbeans.GDateSpecification;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlCalendar;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.impl.common.InvalidLexicalValueException;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.net.URI;
public final class XsTypeConverter
{
private static final String POS_INF_LEX = "INF";
private static final String NEG_INF_LEX = "-INF";
private static final String NAN_LEX = "NaN";
private static final char NAMESPACE_SEP = ':';
private static final String EMPTY_PREFIX = "";
private static final BigDecimal DECIMAL__ZERO = new BigDecimal(0.0);
// See Section 2.4.3 of FRC2396 http://www.ietf.org/rfc/rfc2396.txt
private static final String[] URI_CHARS_TO_BE_REPLACED = {" " , "{" , "}" , "|" , "\\" , "^" , "[" , "]" , "`" };
private static final String[] URI_CHARS_REPLACED_WITH = {"%20", "%7b", "%7d", "%7c", "%5c", "%5e", "%5b", "%5d", "%60"};
// ======================== float ========================
public static float lexFloat(CharSequence cs)
throws NumberFormatException
{
final String v = cs.toString();
try {
//current jdk impl of parseFloat calls trim() on the string.
//Any other space is illegal anyway, whether there are one or more spaces.
//so no need to do a collapse pass through the string.
if (cs.length() > 0) {
char ch = cs.charAt(cs.length() - 1);
if (ch == 'f' || ch == 'F') {
if (cs.charAt(cs.length() - 2) != 'N')
throw new NumberFormatException("Invalid char '" + ch + "' in float.");
}
}
return Float.parseFloat(v);
}
catch (NumberFormatException e) {
if (v.equals(POS_INF_LEX)) return Float.POSITIVE_INFINITY;
if (v.equals(NEG_INF_LEX)) return Float.NEGATIVE_INFINITY;
if (v.equals(NAN_LEX)) return Float.NaN;
throw e;
}
}
public static float lexFloat(CharSequence cs, Collection errors)
{
try {
return lexFloat(cs);
}
catch (NumberFormatException e) {
String msg = "invalid float: " + cs;
errors.add(XmlError.forMessage(msg));
return Float.NaN;
}
}
public static String printFloat(float value)
{
if (value == Float.POSITIVE_INFINITY)
return POS_INF_LEX;
else if (value == Float.NEGATIVE_INFINITY)
return NEG_INF_LEX;
else if (Float.isNaN(value))
return NAN_LEX;
else
return Float.toString(value);
}
// ======================== double ========================
public static double lexDouble(CharSequence cs)
throws NumberFormatException
{
final String v = cs.toString();
try {
//current jdk impl of parseDouble calls trim() on the string.
//Any other space is illegal anyway, whether there are one or more spaces.
//so no need to do a collapse pass through the string.
if (cs.length() > 0) {
char ch = cs.charAt(cs.length() - 1);
if (ch == 'd' || ch == 'D')
throw new NumberFormatException("Invalid char '" + ch + "' in double.");
}
return Double.parseDouble(v);
}
catch (NumberFormatException e) {
if (v.equals(POS_INF_LEX)) return Double.POSITIVE_INFINITY;
if (v.equals(NEG_INF_LEX)) return Double.NEGATIVE_INFINITY;
if (v.equals(NAN_LEX)) return Double.NaN;
throw e;
}
}
public static double lexDouble(CharSequence cs, Collection errors)
{
try {
return lexDouble(cs);
}
catch (NumberFormatException e) {
String msg = "invalid double: " + cs;
errors.add(XmlError.forMessage(msg));
return Double.NaN;
}
}
public static String printDouble(double value)
{
if (value == Double.POSITIVE_INFINITY)
return POS_INF_LEX;
else if (value == Double.NEGATIVE_INFINITY)
return NEG_INF_LEX;
else if (Double.isNaN(value))
return NAN_LEX;
else
return Double.toString(value);
}
// ======================== decimal ========================
public static BigDecimal lexDecimal(CharSequence cs)
throws NumberFormatException
{
final String v = cs.toString();
//TODO: review this
//NOTE: we trim unneeded zeros from the string because
//java.math.BigDecimal considers them significant for its
//equals() method, but the xml value
//space does not consider them significant.
//See http://www.w3.org/2001/05/xmlschema-errata#e2-44
return new BigDecimal(trimTrailingZeros(v));
}
public static BigDecimal lexDecimal(CharSequence cs, Collection errors)
{
try {
return lexDecimal(cs);
}
catch (NumberFormatException e) {
String msg = "invalid long: " + cs;
errors.add(XmlError.forMessage(msg));
return DECIMAL__ZERO;
}
}
private static final char[] CH_ZEROS = new char[] {'0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
public static String printDecimal(BigDecimal value)
{
// We can't simply use value.toString() here, because in JDK1.5 that returns an
// exponent String and exponents are not allowed in XMLSchema decimal values
// The following code comes from Apache Harmony
String intStr = value.unscaledValue().toString();
int scale = value.scale();
if ((scale == 0) || ((value.longValue() == 0) && (scale < 0)))
return intStr;
int begin = (value.signum() < 0) ? 1 : 0;
int delta = scale;
// We take space for all digits, plus a possible decimal point, plus 'scale'
StringBuffer result = new StringBuffer(intStr.length() + 1 + Math.abs(scale));
if (begin == 1)
{
// If the number is negative, we insert a '-' character at front
result.append('-');
}
if (scale > 0)
{
delta -= (intStr.length() - begin);
if (delta >= 0)
{
result.append("0."); //$NON-NLS-1$
// To append zeros after the decimal point
for (; delta > CH_ZEROS.length; delta -= CH_ZEROS.length)
result.append(CH_ZEROS);
result.append(CH_ZEROS, 0, delta);
result.append(intStr.substring(begin));
}
else
{
delta = begin - delta;
result.append(intStr.substring(begin, delta));
result.append('.');
result.append(intStr.substring(delta));
}
}
else
{// (scale <= 0)
result.append(intStr.substring(begin));
// To append trailing zeros
for (; delta < -CH_ZEROS.length; delta += CH_ZEROS.length)
result.append(CH_ZEROS);
result.append(CH_ZEROS, 0, -delta);
}
return result.toString();
}
// ======================== integer ========================
public static BigInteger lexInteger(CharSequence cs)
throws NumberFormatException
{
if (cs.length() > 1) {
if (cs.charAt(0) == '+' && cs.charAt(1) == '-')
throw new NumberFormatException("Illegal char sequence '+-'");
}
final String v = cs.toString();
//TODO: consider special casing zero and one to return static values
//from BigInteger to avoid object creation.
return new BigInteger(trimInitialPlus(v));
}
public static BigInteger lexInteger(CharSequence cs, Collection errors)
{
try {
return lexInteger(cs);
}
catch (NumberFormatException e) {
String msg = "invalid long: " + cs;
errors.add(XmlError.forMessage(msg));
return BigInteger.ZERO;
}
}
public static String printInteger(BigInteger value)
{
return value.toString();
}
// ======================== long ========================
public static long lexLong(CharSequence cs)
throws NumberFormatException
{
final String v = cs.toString();
return Long.parseLong(trimInitialPlus(v));
}
public static long lexLong(CharSequence cs, Collection errors)
{
try {
return lexLong(cs);
}
catch (NumberFormatException e) {
String msg = "invalid long: " + cs;
errors.add(XmlError.forMessage(msg));
return 0L;
}
}
public static String printLong(long value)
{
return Long.toString(value);
}
// ======================== short ========================
public static short lexShort(CharSequence cs)
throws NumberFormatException
{
return parseShort(cs);
}
public static short lexShort(CharSequence cs, Collection errors)
{
try {
return lexShort(cs);
}
catch (NumberFormatException e) {
String msg = "invalid short: " + cs;
errors.add(XmlError.forMessage(msg));
return 0;
}
}
public static String printShort(short value)
{
return Short.toString(value);
}
// ======================== int ========================
public static int lexInt(CharSequence cs)
throws NumberFormatException
{
return parseInt(cs);
}
public static int lexInt(CharSequence cs, Collection errors)
{
try {
return lexInt(cs);
}
catch (NumberFormatException e) {
String msg = "invalid int:" + cs;
errors.add(XmlError.forMessage(msg));
return 0;
}
}
public static String printInt(int value)
{
return Integer.toString(value);
}
// ======================== byte ========================
public static byte lexByte(CharSequence cs)
throws NumberFormatException
{
return parseByte(cs);
}
public static byte lexByte(CharSequence cs, Collection errors)
{
try {
return lexByte(cs);
}
catch (NumberFormatException e) {
String msg = "invalid byte: " + cs;
errors.add(XmlError.forMessage(msg));
return 0;
}
}
public static String printByte(byte value)
{
return Byte.toString(value);
}
// ======================== boolean ========================
public static boolean lexBoolean(CharSequence v)
{
switch (v.length()) {
case 1: // "0" or "1"
final char c = v.charAt(0);
if ('0' == c) return false;
if ('1' == c) return true;
break;
case 4: //"true"
if ('t' == v.charAt(0) &&
'r' == v.charAt(1) &&
'u' == v.charAt(2) &&
'e' == v.charAt(3)) {
return true;
}
break;
case 5: //"false"
if ('f' == v.charAt(0) &&
'a' == v.charAt(1) &&
'l' == v.charAt(2) &&
's' == v.charAt(3) &&
'e' == v.charAt(4)) {
return false;
}
break;
}
//reaching here means an invalid boolean lexical
String msg = "invalid boolean: " + v;
throw new InvalidLexicalValueException(msg);
}
public static boolean lexBoolean(CharSequence value, Collection errors)
{
try {
return lexBoolean(value);
}
catch (InvalidLexicalValueException e) {
errors.add(XmlError.forMessage(e.getMessage()));
return false;
}
}
public static String printBoolean(boolean value)
{
return (value ? "true" : "false");
}
// ======================== string ========================
public static String lexString(CharSequence cs, Collection errors)
{
final String v = cs.toString();
return v;
}
public static String lexString(CharSequence lexical_value)
{
return lexical_value.toString();
}
public static String printString(String value)
{
return value;
}
// ======================== QName ========================
public static QName lexQName(CharSequence charSeq, NamespaceContext nscontext)
{
String prefix, localname;
int firstcolon;
boolean hasFirstCollon = false;
for (firstcolon = 0; firstcolon < charSeq.length(); firstcolon++)
if (charSeq.charAt(firstcolon) == NAMESPACE_SEP) {
hasFirstCollon = true;
break;
}
if (hasFirstCollon) {
prefix = charSeq.subSequence(0, firstcolon).toString();
localname = charSeq.subSequence(firstcolon + 1, charSeq.length()).toString();
if (firstcolon == 0) {
throw new InvalidLexicalValueException("invalid xsd:QName '" + charSeq.toString() + "'");
}
} else {
prefix = EMPTY_PREFIX;
localname = charSeq.toString();
}
String uri = nscontext.getNamespaceURI(prefix);
if (uri == null) {
if (prefix != null && prefix.length() > 0)
throw new InvalidLexicalValueException("Can't resolve prefix: " + prefix);
uri = "";
}
return new QName(uri, localname);
}
public static QName lexQName(String xsd_qname, Collection errors,
NamespaceContext nscontext)
{
try {
return lexQName(xsd_qname, nscontext);
}
catch (InvalidLexicalValueException e) {
errors.add(XmlError.forMessage(e.getMessage()));
final int idx = xsd_qname.indexOf(NAMESPACE_SEP);
return new QName(null, xsd_qname.substring(idx));
}
}
public static String printQName(QName qname, NamespaceContext nsContext,
Collection errors)
{
final String uri = qname.getNamespaceURI();
assert uri != null; //qname is not allowed to have null uri values
final String prefix;
if (uri.length() > 0) {
prefix = nsContext.getPrefix(uri);
if (prefix == null) {
String msg = "NamespaceContext does not provide" +
" prefix for namespaceURI " + uri;
errors.add(XmlError.forMessage(msg));
}
} else {
prefix = null;
}
return getQNameString(uri, qname.getLocalPart(), prefix);
}
public static String getQNameString(String uri,
String localpart,
String prefix)
{
if (prefix != null &&
uri != null &&
uri.length() > 0 &&
prefix.length() > 0) {
return (prefix + NAMESPACE_SEP + localpart);
} else {
return localpart;
}
}
// ======================== GDate ========================
public static GDate lexGDate(CharSequence charSeq)
{
return new GDate(charSeq);
}
public static GDate lexGDate(String xsd_gdate, Collection errors)
{
try {
return lexGDate(xsd_gdate);
}
catch (IllegalArgumentException e) {
errors.add(XmlError.forMessage(e.getMessage()));
return new GDateBuilder().toGDate();
}
}
public static String printGDate(GDate gdate, Collection errors)
{
return gdate.toString();
}
// ======================== dateTime ========================
public static XmlCalendar lexDateTime(CharSequence v)
{
GDateSpecification value = getGDateValue(v, SchemaType.BTC_DATE_TIME);
return value.getCalendar();
}
public static String printDateTime(Calendar c)
{
return printDateTime(c, SchemaType.BTC_DATE_TIME);
}
public static String printTime(Calendar c)
{
return printDateTime(c, SchemaType.BTC_TIME);
}
public static String printDate(Calendar c)
{
return printDateTime(c, SchemaType.BTC_DATE);
}
public static String printDate(Date d)
{
GDateSpecification value = getGDateValue(d, SchemaType.BTC_DATE);
return value.toString();
}
public static String printDateTime(Calendar c, int type_code)
{
GDateSpecification value = getGDateValue(c, type_code);
return value.toString();
}
public static String printDateTime(Date c)
{
GDateSpecification value = getGDateValue(c, SchemaType.BTC_DATE_TIME);
return value.toString();
}
// ======================== hexBinary ========================
public static CharSequence printHexBinary(byte[] val)
{
return HexBin.bytesToString(val);
}
public static byte[] lexHexBinary(CharSequence lexical_value)
{
byte[] buf = HexBin.decode(lexical_value.toString().getBytes());
if (buf != null)
return buf;
else
throw new InvalidLexicalValueException("invalid hexBinary value");
}
// ======================== base64binary ========================
public static CharSequence printBase64Binary(byte[] val)
{
final byte[] bytes = Base64.encode(val);
return new String(bytes);
}
public static byte[] lexBase64Binary(CharSequence lexical_value)
{
byte[] buf = Base64.decode(lexical_value.toString().getBytes());
if (buf != null)
return buf;
else
throw new InvalidLexicalValueException("invalid base64Binary value");
}
// date utils
public static GDateSpecification getGDateValue(Date d,
int builtin_type_code)
{
GDateBuilder gDateBuilder = new GDateBuilder(d);
gDateBuilder.setBuiltinTypeCode(builtin_type_code);
GDate value = gDateBuilder.toGDate();
return value;
}
public static GDateSpecification getGDateValue(Calendar c,
int builtin_type_code)
{
GDateBuilder gDateBuilder = new GDateBuilder(c);
gDateBuilder.setBuiltinTypeCode(builtin_type_code);
GDate value = gDateBuilder.toGDate();
return value;
}
public static GDateSpecification getGDateValue(CharSequence v,
int builtin_type_code)
{
GDateBuilder gDateBuilder = new GDateBuilder(v);
gDateBuilder.setBuiltinTypeCode(builtin_type_code);
GDate value = gDateBuilder.toGDate();
return value;
}
private static String trimInitialPlus(String xml)
{
if (xml.length() > 0 && xml.charAt(0) == '+') {
return xml.substring(1);
} else {
return xml;
}
}
private static String trimTrailingZeros(String xsd_decimal)
{
final int last_char_idx = xsd_decimal.length() - 1;
if (xsd_decimal.charAt(last_char_idx) == '0')
{
final int last_point = xsd_decimal.lastIndexOf('.');
if (last_point >= 0) {
//find last trailing zero
for (int idx = last_char_idx; idx > last_point; idx--) {
if (xsd_decimal.charAt(idx) != '0') {
return xsd_decimal.substring(0, idx + 1);
}
}
//reaching here means the string matched xxx.0*
return xsd_decimal.substring(0, last_point);
}
}
return xsd_decimal;
}
private static int parseInt(CharSequence cs)
{
return parseIntXsdNumber(cs, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
private static short parseShort(CharSequence cs)
{
return (short)parseIntXsdNumber(cs, Short.MIN_VALUE, Short.MAX_VALUE);
}
private static byte parseByte(CharSequence cs)
{
return (byte)parseIntXsdNumber(cs, Byte.MIN_VALUE, Byte.MAX_VALUE);
}
private static int parseIntXsdNumber(CharSequence ch, int min_value, int max_value)
{
// int parser on a CharSequence
int length = ch.length();
if (length < 1)
throw new NumberFormatException("For input string: \"" + ch.toString() + "\"");
int sign = 1;
int result = 0;
int start = 0;
int limit;
int limit2;
char c = ch.charAt(0);
if (c == '-') {
start++;
limit = (min_value / 10);
limit2 = -(min_value % 10);
} else if (c == '+') {
start++;
sign = -1;
limit = -(max_value / 10);
limit2 = (max_value % 10);
} else {
sign = -1;
limit = -(max_value / 10);
limit2 = (max_value % 10);
}
for (int i = 0; i < length - start; i++) {
c = ch.charAt(i + start);
int v = Character.digit(c, 10);
if (v < 0)
throw new NumberFormatException("For input string: \"" + ch.toString() + "\"");
if (result < limit || (result==limit && v > limit2))
throw new NumberFormatException("For input string: \"" + ch.toString() + "\"");
result = result * 10 - v;
}
return sign * result;
}
// ======================== anyURI ========================
public static CharSequence printAnyURI(CharSequence val)
{
return val;
}
/**
* Checkes the regular expression of URI, defined by RFC2369 http://www.ietf.org/rfc/rfc2396.txt Appendix B.
* Note: The whitespace normalization rule collapse must be applied priot to calling this method.
* @param lexical_value the lexical value
* @return same input value if input value is in the lexical space
* @throws InvalidLexicalValueException
*/
public static CharSequence lexAnyURI(CharSequence lexical_value)
{
/* // Reg exp from RFC2396, but it's too forgiving for XQTS
Pattern p = Pattern.compile("^([^:/?#]+:)?(//[^/?#]*)?([^?#]*)(\\?[^#]*)?(#.*)?");
Matcher m = p.matcher(lexical_value);
if ( !m.matches() )
throw new InvalidLexicalValueException("invalid anyURI value");
else
{
for ( int i = 0; i<= m.groupCount(); i++ )
{
System.out.print(" " + i + ": " + m.group(i));
}
System.out.println("");
return lexical_value;
} */
// Per XMLSchema spec allow spaces inside URIs
StringBuffer s = new StringBuffer(lexical_value.toString());
for (int ic = 0; ic= 0)
{
s.replace(i, i + 1, URI_CHARS_REPLACED_WITH[ic]);
i += 3;
}
}
try
{
URI.create(s.toString());
}
catch (IllegalArgumentException e)
{
throw new InvalidLexicalValueException("invalid anyURI value: " + lexical_value, e);
}
return lexical_value;
}
} xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/util/Diff.java 0000644 0001750 0001750 00000003733 11361341574 023367 0 ustar apo apo /* 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.impl.util;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.util.List;
/**
* This needs to be here so that it can be accessed by FilerImpl
*/
public class Diff
{
public static void readersAsText(Reader r1, String name1, Reader r2, String name2,
List diffs)
throws IOException
{
LineNumberReader reader1 = new LineNumberReader(r1);
LineNumberReader reader2 = new LineNumberReader(r2);
String line1 = reader1.readLine();
String line2 = reader2.readLine();
while (line1 != null && line2 != null)
{
if (!line1.equals(line2))
{
diffs.add("File \"" + name1 + "\" and file \"" +
name2 + "\" differ at line " + reader1.getLineNumber() +
":" + "\n" + line1 + "\n========\n" + line2);
break;
}
line1 = reader1.readLine();
line2 = reader2.readLine();
}
if (line1 == null && line2 != null)
diffs.add("File \"" + name2 + "\" has extra lines at line " +
reader2.getLineNumber() + ":\n" + line2);
if (line1 != null && line2 == null)
diffs.add("File \"" + name1 + "\" has extra lines at line " +
reader1.getLineNumber() + ":\n" + line1);
}
}
xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/util/Base64.java 0000644 0001750 0001750 00000030630 11361341574 023537 0 ustar apo apo /* 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.impl.util;
import java.io.UnsupportedEncodingException;
/**
* This class provides encode/decode for RFC 2045 Base64 as
* defined by RFC 2045, N. Freed and N. Borenstein.
* RFC 2045: Multipurpose Internet Mail Extensions (MIME)
* Part One: Format of Internet Message Bodies. Reference
* 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
* This class is used by XML Schema binary format validation
*
* This implementation does not encode/decode streaming
* data. You need the data that you will encode/decode
* already on a byte arrray.
*
* @author Jeffrey Rodriguez
* @author Sandy Gao
* @version $Id: Base64.java 111285 2004-12-08 16:54:26Z cezar $
*/
public final class Base64 {
static private final int BASELENGTH = 255;
static private final int LOOKUPLENGTH = 64;
static private final int TWENTYFOURBITGROUP = 24;
static private final int EIGHTBIT = 8;
static private final int SIXTEENBIT = 16;
//static private final int SIXBIT = 6;
static private final int FOURBYTE = 4;
static private final int SIGN = -128;
static private final byte PAD = ( byte ) '=';
static private final boolean fDebug = false;
static private byte [] base64Alphabet = new byte[BASELENGTH];
static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
static {
for (int i = 0; i= 'A'; i--) {
base64Alphabet[i] = (byte) (i-'A');
}
for (int i = 'z'; i>= 'a'; i--) {
base64Alphabet[i] = (byte) ( i-'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i-'0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i<=25; i++)
lookUpBase64Alphabet[i] = (byte) ('A'+i );
for (int i = 26, j = 0; i<=51; i++, j++)
lookUpBase64Alphabet[i] = (byte) ('a'+ j );
for (int i = 52, j = 0; i<=61; i++, j++)
lookUpBase64Alphabet[i] = (byte) ('0' + j );
lookUpBase64Alphabet[62] = (byte) '+';
lookUpBase64Alphabet[63] = (byte) '/';
}
protected static boolean isWhiteSpace(byte octect) {
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
}
protected static boolean isPad(byte octect) {
return (octect == PAD);
}
protected static boolean isData(byte octect) {
return (base64Alphabet[octect] != -1);
}
protected static boolean isBase64(byte octect) {
return (isWhiteSpace(octect) || isPad(octect) || isData(octect));
}
/**
* Encodes hex octects into Base64
*
* @param binaryData Array containing binaryData
* @return Encoded Base64 array
*/
public static byte[] encode(byte[] binaryData) {
if (binaryData == null)
return null;
int lengthDataBits = binaryData.length*EIGHTBIT;
int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
byte encodedData[] = null;
if (fewerThan24bits != 0) //data not divisible by 24 bit
encodedData = new byte[ (numberTriplets + 1 )*4 ];
else // 16 or 8 bit
encodedData = new byte[ numberTriplets*4 ];
byte k=0, l=0, b1=0,b2=0,b3=0;
int encodedIndex = 0;
int dataIndex = 0;
int i = 0;
if (fDebug) {
System.out.println("number of triplets = " + numberTriplets );
}
for (i = 0; i>2) );
}
byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
encodedData[encodedIndex + 2] = PAD;
encodedData[encodedIndex + 3] = PAD;
} else if (fewerThan24bits == SIXTEENBIT) {
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex +1 ];
l = ( byte ) ( b2 &0x0f );
k = ( byte ) ( b1 &0x03 );
byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
encodedData[encodedIndex + 3] = PAD;
}
return encodedData;
}
/**
* Decodes Base64 data into octects
*
* @param base64Data Byte array containing Base64 data
* @return Array containind decoded data.
*/
public static byte[] decode(byte[] base64Data) {
if (base64Data == null)
return null;
// remove white spaces
base64Data = removeWhiteSpace(base64Data);
if (base64Data.length%FOURBYTE != 0) {
return null;//should be divisible by four
}
int numberQuadruple = (base64Data.length/FOURBYTE );
if (numberQuadruple == 0)
return new byte[0];
byte decodedData[] = null;
byte b1=0,b2=0,b3=0, b4=0;//, marker0=0, marker1=0;
byte d1=0,d2=0,d3=0,d4=0;
// Throw away anything not in normalizedBase64Data
// Adjust size
int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
decodedData = new byte[ (numberQuadruple)*3];
for (; i>4 ) ;
decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
}
if (!isData( (d1 = base64Data[dataIndex++]) ) ||
!isData( (d2 = base64Data[dataIndex++]) )) {
return null;//if found "no data" just return null
}
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
d3 = base64Data[dataIndex++];
d4 = base64Data[dataIndex++];
if (!isData( (d3 ) ) ||
!isData( (d4 ) )) {//Check if they are PAD characters
if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad]
if ((b2 & 0xf) != 0)//last 4 bits should be zero
return null;
byte[] tmp = new byte[ i*3 + 1 ];
System.arraycopy( decodedData, 0, tmp, 0, i*3 );
tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
return tmp;
} else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad]
b3 = base64Alphabet[ d3 ];
if ((b3 & 0x3 ) != 0)//last 2 bits should be zero
return null;
byte[] tmp = new byte[ i*3 + 2 ];
System.arraycopy( decodedData, 0, tmp, 0, i*3 );
tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 );
tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
return tmp;
} else {
return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
}
} else { //No PAD e.g 3cQl
b3 = base64Alphabet[ d3 ];
b4 = base64Alphabet[ d4 ];
decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ;
decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
}
return decodedData;
}
// /**
// * Decodes Base64 data into octects
// *
// * @param base64Data String containing Base64 data
// * @return string containing decoded data.
// */
// public static String decode(String base64Data) {
// if (base64Data == null)
// return null;
//
// byte[] decoded = null;
// try {
// decoded = decode(base64Data.getBytes("utf-8"));
// }
// catch(UnsupportedEncodingException e) {
// }
// finally {
// return decoded == null ? null : new String(decoded);
// }
// }
//
// /**
// * Encodes octects (using utf-8) into Base64 data
// *
// * @param binaryData String containing Hex data
// * @return string containing decoded data.
// */
// public static String encode(String binaryData) {
// if (binaryData == null)
// return null;
//
// byte[] encoded = null;
// try {
// encoded = encode(binaryData.getBytes("utf-8"));
// }
// catch(UnsupportedEncodingException e) {}
// finally {
// return encoded == null ? null : new String(encoded);
// }
// }
/**
* remove WhiteSpace from MIME containing encoded Base64 data.
*
* @param data the byte array of base64 data (with WS)
* @return the byte array of base64 data (without WS)
*/
protected static byte[] removeWhiteSpace(byte[] data) {
if (data == null)
return null;
// count characters that's not whitespace
int newSize = 0;
int len = data.length;
for (int i = 0; i < len; i++) {
if (!isWhiteSpace(data[i]))
newSize++;
}
// if no whitespace, just return the input array
if (newSize == len)
return data;
// create the array to return
byte[] newArray = new byte[newSize];
int j = 0;
for (int i = 0; i < len; i++) {
if (!isWhiteSpace(data[i]))
newArray[j++] = data[i];
}
return newArray;
}
}
xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/util/FilerImpl.java 0000644 0001750 0001750 00000015340 11361341574 024377 0 ustar apo apo /* 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.impl.util;
import org.apache.xmlbeans.Filer;
import java.io.IOException;
import java.io.File;
import java.io.Writer;
import java.io.FileReader;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import repackage.Repackager;
/**
* This implementation of Filer writes to disk.
*/
public class FilerImpl implements Filer
{
private File classdir;
private File srcdir;
private Repackager repackager;
private boolean verbose;
private List sourceFiles;
private boolean incrSrcGen;
private Set seenTypes;
private static final Charset CHARSET;
static
{
Charset temp = null;
try
{
temp = Charset.forName(System.getProperty("file.encoding"));
}
catch (Exception e) {}
CHARSET = temp;
}
public FilerImpl(File classdir, File srcdir, Repackager repackager, boolean verbose, boolean incrSrcGen)
{
this.classdir = classdir;
this.srcdir = srcdir;
this.repackager = repackager;
this.verbose = verbose;
this.sourceFiles = (sourceFiles != null ? sourceFiles : new ArrayList());
this.incrSrcGen = incrSrcGen;
if (this.incrSrcGen)
seenTypes = new HashSet();
}
/**
* Creates a new schema binary file (.xsb) and returns a stream for writing to it.
*
* @param typename fully qualified type name
* @return a stream to write the type to
* @throws java.io.IOException
*/
public OutputStream createBinaryFile(String typename) throws IOException
{
if (verbose)
System.err.println("created binary: " + typename);
// KHK: for now the typename will already be a relative filename for the binary
//String filename = typename.replace('.', File.separatorChar) + ".xsb";
File source = new File(classdir, typename);
source.getParentFile().mkdirs();
return new FileOutputStream( source );
}
/**
* Creates a new binding source file (.java) and returns a writer for it.
*
* @param typename fully qualified type name
* @return a stream to write the type to
* @throws java.io.IOException
*/
public Writer createSourceFile(String typename) throws IOException
{
if (incrSrcGen)
seenTypes.add(typename);
if (typename.indexOf('$') > 0)
{
typename =
typename.substring( 0, typename.lastIndexOf( '.' ) ) + "." +
typename.substring( typename.indexOf( '$' ) + 1 );
}
String filename = typename.replace('.', File.separatorChar) + ".java";
File sourcefile = new File(srcdir, filename);
sourcefile.getParentFile().mkdirs();
if (verbose)
System.err.println("created source: " + sourcefile.getAbsolutePath());
sourceFiles.add(sourcefile);
if (incrSrcGen && sourcefile.exists())
{
// Generate the file in a buffer and then compare it to the
// file already on disk
return new IncrFileWriter(sourcefile, repackager);
}
else
{
return repackager == null ?
(Writer) writerForFile( sourcefile ) :
(Writer) new RepackagingWriter( sourcefile, repackager );
}
}
public List getSourceFiles()
{
return new ArrayList(sourceFiles);
}
public Repackager getRepackager()
{
return repackager;
}
private static final Writer writerForFile(File f) throws IOException
{
if (CHARSET == null)
return new FileWriter(f);
FileOutputStream fileStream = new FileOutputStream(f);
CharsetEncoder ce = CHARSET.newEncoder();
ce.onUnmappableCharacter(CodingErrorAction.REPORT);
return new OutputStreamWriter(fileStream, ce);
}
static class IncrFileWriter extends StringWriter
{
private File _file;
private Repackager _repackager;
public IncrFileWriter(File file, Repackager repackager)
{
_file = file;
_repackager = repackager;
}
public void close() throws IOException
{
super.close();
// This is where all the real work happens
StringBuffer sb = _repackager != null ?
_repackager.repackage(getBuffer()) :
getBuffer();
String str = sb.toString();
List diffs = new ArrayList();
StringReader sReader = new StringReader(str);
FileReader fReader = new FileReader(_file);
try
{
Diff.readersAsText(sReader, "",
fReader, _file.getName(), diffs);
}
finally
{
sReader.close();
fReader.close();
}
if (diffs.size() > 0)
{
// Diffs encountered, replace the file on disk with text from
// the buffer
Writer fw = writerForFile(_file);
try
{ fw.write(str); }
finally
{ fw.close(); }
}
else
; // If no diffs, don't do anything
}
}
static class RepackagingWriter extends StringWriter
{
public RepackagingWriter ( File file, Repackager repackager )
{
_file = file;
_repackager = repackager;
}
public void close ( ) throws IOException
{
super.close();
Writer fw = writerForFile( _file );
try
{ fw.write( _repackager.repackage( getBuffer() ).toString() ); }
finally
{ fw.close(); }
}
private File _file;
private Repackager _repackager;
}
}
xmlbeans-2.6.0/src/typeimpl/org/apache/xmlbeans/impl/util/HexBin.java 0000644 0001750 0001750 00000011054 11361341574 023667 0 ustar apo apo /* 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.impl.util;
import java.io.UnsupportedEncodingException;
/**
* format validation
*
* This class encodes/decodes hexadecimal data
* @author Jeffrey Rodriguez
* @version $Id: HexBin.java 125124 2005-01-14 00:23:54Z kkrouse $
*/
public final class HexBin {
static private final int BASELENGTH = 255;
static private final int LOOKUPLENGTH = 16;
static private byte [] hexNumberTable = new byte[BASELENGTH];
static private byte [] lookUpHexAlphabet = new byte[LOOKUPLENGTH];
static {
for (int i = 0; i= '0'; i--) {
hexNumberTable[i] = (byte) (i-'0');
}
for ( int i = 'F'; i>= 'A'; i--) {
hexNumberTable[i] = (byte) ( i-'A' + 10 );
}
for ( int i = 'f'; i>= 'a'; i--) {
hexNumberTable[i] = (byte) ( i-'a' + 10 );
}
for(int i = 0; i<10; i++ )
lookUpHexAlphabet[i] = (byte) ('0'+i );
for(int i = 10; i<=15; i++ )
lookUpHexAlphabet[i] = (byte) ('A'+i -10);
}
/**
* byte to be tested if it is Base64 alphabet
*
* @param octect
* @return
*/
static boolean isHex(byte octect) {
return (hexNumberTable[octect] != -1);
}
/**
* Converts bytes to a hex string
*/
static public String bytesToString(byte[] binaryData)
{
if (binaryData == null)
return null;
return new String(encode(binaryData));
}
/**
* Converts a hex string to a byte array.
*/
static public byte[] stringToBytes(String hexEncoded)
{
return decode(hexEncoded.getBytes());
}
/**
* array of byte to encode
*
* @param binaryData
* @return return encode binary array
*/
static public byte[] encode(byte[] binaryData) {
if (binaryData == null)
return null;
int lengthData = binaryData.length;
int lengthEncode = lengthData * 2;
byte[] encodedData = new byte[lengthEncode];
for( int i = 0; i> 4) & 0xf];
encodedData[i*2+1] = lookUpHexAlphabet[ binaryData[i] & 0xf];
}
return encodedData;
}
static public byte[] decode(byte[] binaryData) {
if (binaryData == null)
return null;
int lengthData = binaryData.length;
if (lengthData % 2 != 0)
return null;
int lengthDecode = lengthData / 2;
byte[] decodedData = new byte[lengthDecode];
for( int i = 0; i