2362N/A * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/Apackage xmlkit;
// -*- mode: java; indent-tabs-mode: nil -*- 0N/A// XML Implementation packages: 0N/A * A kit of methods and classes useful for manipulating XML trees in 0N/A * memory. They are very compact and easy to use. An XML element 0N/A * occupies six pointers of overhead (like two arrays) plus a pointer 0N/A * for its name, each attribute name and value, and each sub-element. 0N/A * Many useful XML operations (or Lisp-like calls) can be accomplished 0N/A * with a single method call on an element itself. 0N/A * There is strong integration with the Java collection classes. 0N/A * There are viewing and conversion operators to and from various 0N/A * collection types. Elements directly support list iterators. 0N/A * Most <tt>List</tt> methods work analogously on elements. 0N/A * Because of implementation compromises, these XML trees are less 0N/A * functional than many standard XML classes. 0N/A * <li>There are no parent or sibling pointers in the tree.</li> 0N/A * <li>Attribute names are simple strings, with no namespaces.</li> 0N/A * <li>There is no internal support for schemas or validation.</li> 0N/A * Here is a summary of functionality in <tt>XMLKit</tt>. 0N/A * (Overloaded groups of methods are summarized by marking some 0N/A * arguments optional with their default values. Some overloaded 0N/A * arguments are marked with their alternative types separated by 0N/A * a bar "|". Arguments or return values for which a null is 0N/A * specially significant are marked by an alternative "|null". 0N/A * Accessors which have corresponding setters are marked 0N/A * by "/set". Removers which have corresponding retainers are marked 0N/A * --- element construction 0N/A * new Element(int elemCapacity=4), String name="" 0N/A * new Element(String name, String[] attrs={}, Element[] elems={}, int elemCapacity=4) 0N/A * new Element(String name, String[] attrs, Object[] elems, int elemCapacity=4) 0N/A * new Element(Element original) // shallow copy 0N/A * new Element(String name="", Collection elems) // coercion 0N/A * Element shallowCopy() 0N/A * Element shallowFreeze() // side-effecting 0N/A * Element deepCopy() 0N/A * Element deepFreeze() // not side-effecting 0N/A * EMPTY // frozen empty anonymous element 0N/A * void ensureExtraCapacity(int) 0N/A * void sortAttrs() // sort by key 0N/A * --- field accessors 0N/A * String getName()/set 0N/A * boolean isFrozen() 0N/A * boolean isAnonymous() 0N/A * int getExtraCapacity()/set 0N/A * --- attribute accessors 0N/A * String getAttr(int i)/set 0N/A * String getAttrName(int i) 0N/A * String getAttr(String key)/set 0N/A * List getAttrList(String key)/set 0N/A * Number getAttrNumber(String key)/set 0N/A * long getAttrLong(String key)/set 0N/A * double getAttrDouble(String key)/set 0N/A * String getAttr(String key, String dflt=null) 0N/A * long getAttrLong(String key, long dflt=0) 0N/A * double getAttrDouble(String key, double dflt=0) 0N/A * Element copyAttrsOnly() 0N/A * Element getAttrs()/set => <em><><key>value</key>...</></em> 0N/A * void addAttrs(Element attrs) 0N/A * void removeAttr(int i) 0N/A * --- element accessors 0N/A * Object get(int i)/set 0N/A * Object getLast() | null 0N/A * Object[] toArray() 0N/A * Element copyContentOnly() 0N/A * void add(int i=0, Object subElem) 0N/A * int addAll(int i=0, Collection | Element elems) 0N/A * int addContent(int i=0, TokenList|Element|Object|null) 0N/A * void XMLKit.addContent(TokenList|Element|Object|null, Collection sink|null) 0N/A * void clear(int beg=0, int end=size) 0N/A * void sort(Comparator=contentOrder()) 0N/A * void shuffle(Random rnd=(anonymous)) 0N/A * void rotate(int distance) 0N/A * --- text accessors 0N/A * CharSequence getText()/set 0N/A * CharSequence getUnmarkedText() 0N/A * int addText(int i=size, CharSequence) 0N/A * List asList() // element view 0N/A * ListIterator iterator() 0N/A * PrintWriter asWriter() 0N/A * Iterable<CharSequence> texts() 0N/A * Iterable<Element> elements() 0N/A * Iterable<T> partsOnly(Class<T>) 0N/A * String[] toStrings() 0N/A * boolean equals(Element | Object) 0N/A * int compareTo(Element | Object) 0N/A * boolean equalAttrs(Element) 0N/A * boolean isText() // every sub-elem is CharSequence 0N/A * boolean hasText() // some sub-elem is CharSequence 0N/A * boolean contains(Object) 0N/A * boolean containsAttr(String) 0N/A * int indexOf(Object) 0N/A * int indexOf(Filter, int fromIndex=0) 0N/A * int lastIndexOf(Object) 0N/A * int lastIndexOf(Filter, int fromIndex=size-1) 0N/A * int indexOfAttr(String) 0N/A * // finders, removers, and replacers do addContent of each filtered value 0N/A * // (i.e., TokenLists and anonymous Elements are broken out into their parts) 0N/A * boolean matches(Filter) 0N/A * Object find(Filter, int fromIndex=0) 0N/A * Object findLast(Filter, int fromIndex=size-1) 0N/A * Element findAll(Filter, int fromIndex=0 & int toIndex=size) 0N/A * int findAll(Filter, Collection sink | null, int fromIndex=0 & int toIndex=size) 0N/A * Element removeAllInTree(Filter)/retain 0N/A * int findAllInTree(Filter, Collection sink | null) 0N/A * int countAllInTree(Filter) 0N/A * Element removeAllInTree(Filter)/retain 0N/A * int removeAllInTree(Filter, Collection sink | null)/retain 0N/A * void replaceAllInTree(Filter) 0N/A * Element findElement(String name=any) 0N/A * Element findAllElements(String name=any) 0N/A * Element findWithAttr(String key, String value=any) 0N/A * Element findAllWithAttr(String key, String value=any) 0N/A * Element removeElement(String name=any) 0N/A * Element removeAllElements(String name=any)/retain 0N/A * Element removeWithAttr(String key, String value=any) 0N/A * Element removeAllWithAttr(String key, String value=any)/retain 0N/A * //countAll is the same as findAll but with null sink 0N/A * int countAll(Filter) 0N/A * int countAllElements(String name=any) 0N/A * int countAllWithAttr(String key, String value=any) 0N/A * void replaceAll(Filter, int fromIndex=0 & int toIndex=size) 0N/A * void replaceAllInTree(Filter) 0N/A * void XMLKit.replaceAll(Filter, List target) //if(fx){remove x;addContent fx} 0N/A * --- element mutators 0N/A * boolean remove(Object) 0N/A * Object remove(int) 0N/A * Object removeLast() | null 0N/A * Object remove(Filter, int fromIndex=0) 0N/A * Object removeLast(Filter, int fromIndex=size-1) 0N/A * Element sink = removeAll(Filter, int fromIndex=0 & int toIndex=size)/retain 0N/A * int count = removeAll(Filter, int fromIndex=0 & int toIndex=size, Collection sink | null)/retain 0N/A * Element removeAllElements(String name=any) 0N/A * --- attribute mutators 0N/A * ??int addAllAttrsFrom(Element attrSource) 0N/A * --- parsing and printing 0N/A * void tokenize(String delims=whitespace, returnDelims=false) 0N/A * void writeTo(Writer) 0N/A * void writePrettyTo(Writer) 0N/A * String prettyString() 0N/A * ContentHandler XMLKit.makeBuilder(Collection sink, tokenizing=false, makeFrozen=false) // for standard XML parser 0N/A * Element XMLKit.readFrom(Reader, tokenizing=false, makeFrozen=false) 0N/A * void XMLKit.prettyPrintTo(Writer | OutputStream, Element) 0N/A * void XMLKit.output(Object elem, ContentHandler, LexicalHandler=null) 0N/A * void XMLKit.writeToken(String, char quote, Writer) 0N/A * void XMLKit.writeCData(String, Writer) 0N/A * Number XMLKit.convertToNumber(String, Number dflt=null) 0N/A * long XMLKit.convertToLong(String, long dflt=0) 0N/A * double XMLKit.convertToDouble(String, double dflt=0) 0N/A * XMLKit.ElementFilter { Element filter(Element) } 0N/A * XMLKit.elementFilter(String name=any | Collection nameSet) 0N/A * XMLKit.AttrFilter(String key) { boolean test(String value) } 0N/A * XMLKit.attrFilter(String key, String value=any) 0N/A * XMLKit.attrFilter(Element matchThis, String key) 0N/A * XMLKit.classFilter(Class) 0N/A * XMLKit.textFilter() // matches any CharSequence 0N/A * XMLKit.specialFilter() // matches any Special element 0N/A * XMLKit.methodFilter(Method m, Object[] args=null, falseResult=null) 0N/A * XMLKit.testMethodFilter(Method m, Object[] args=null) 0N/A * XMLKit.not(Filter) // inverts sense of Filter 0N/A * XMLKit.and(Filter&Filter | Filter[]) 0N/A * XMLKit.or(Filter&Filter | Filter[]) 0N/A * XMLKit.stack(Filter&Filter | Filter[]) // result is (fx && g(fx)) 0N/A * XMLKit.content(Filter, Collection sink) // copies content to sink 0N/A * XMLKit.replaceInTree(Filter pre, Filter post=null) // pre-replace else recur 0N/A * XMLKit.findInTree(Filter pre, Collection sink=null) // pre-find else recur 0N/A * XMLKit.nullFilter() // ignores input, always returns null (i.e., false) 0N/A * XMLKit.selfFilter( ) // always returns input (i.e., true) 0N/A * XMLKit.emptyFilter() // ignores input, always returns EMPTY 0N/A * XMLKit.constantFilter(Object) // ignores input, always returns constant 0N/A * Method XMLKit.Element.method(String name) // returns Element method 0N/A // We need at least this much slop if the element is to stay unfrozen. 0N/A // Note: Does not implement List, because it has more 0N/A // significant parts besides its sub-elements. Therefore, 0N/A // hashCode and equals must be more distinctive than Lists. 0N/A // <name> of element 0N/A // number of child elements, in parts[0..size-1] 0N/A // The parts start with child elements:: {e0, e1, e2, ...}. 0N/A // Following that are optional filler elements, all null. 0N/A // They are in reverse: {...key2, val2, key1, val1, key0, val0}. 0N/A // Child elements and attr keys and values are never null. 0N/A // Build a partially-constructed node. 0N/A // Caller is responsible for initializing promised attributes. 0N/A /** An anonymous, empty element. 0N/A * Optional elemCapacity argument is expected number of sub-elements. 0N/A /** An empty element with the given name. 0N/A * Optional extraCapacity argument is expected number of sub-elements. 0N/A /** An empty element with the given name and attributes. 0N/A * Optional extraCapacity argument is expected number of sub-elements. 0N/A /** An empty element with the given name and sub-elements. 0N/A * Optional extraCapacity argument is expected extra sub-elements. 0N/A /** An empty element with the given name, attributes, and sub-elements. 0N/A * Optional extraCapacity argument is expected extra sub-elements. for (
int i =
0; i <
ne; i++) {
for (
int i =
0; i <
na; i +=
2) {
/** Shallow copy. Same as old.shallowCopy(). * Optional extraCapacity argument is expected extra sub-elements. /** Shallow copy. Same as new Element(this). */ return this;
// no need to copy it for (
int i =
0; i <
size; i++) {
if (e
instanceof Element) {
// recursion is common case // Freeze StringBuffers, etc. /** Returns new Element(this), and also recursively copies sub-elements. */ /** Returns frozen version of deepCopy. */ * Throw an IllegalArgumentException if any sub-element is not already frozen. * (Use deepFreeze() to make a frozen copy of an entire element tree.) for (
int i =
0; i <
size; i++) {
if (e
instanceof Element) {
// recursion is common case // Freeze StringBuffers, etc. /** Return the name of this element. */ /** Change the name of this element. */ /** Reports if the element's name is a particular string (spelled "*"). * Such elements are created by the nullary Element constructor, * and by query functions which return multiple values, * such as <tt>findAll</tt>. /** Return number of elements. (Does not include attributes.) */ /** True if no elements. (Does not consider attributes.) */ /** True if this element does not allow modification. */ // It is frozen iff there is no slop space. /** Remove specified elements. (Does not affect attributes.) */ // If no attributes, free the parts array. for (
int i =
beg; i <
end; i++) {
/** True if name, attributes, and elements are the same. */ // elements must be equal and ordered for (
int i =
0; i <
size; i++) {
// If either is a non-string char sequence, normalize it. // finally, attributes must be equal (unordered) for (
int i =
0; i <
size; i++) {
/** Compare lexicographically. Earlier-spelled attrs are more sigificant. */ // Primary key is element name. // Secondary key is attributes, as if in normal key order. // The key/value pairs are sorted as a token sequence. // Finally, elements should be equal and ordered, // and the first difference rules. for (
int i =
0; i <
minSize; i++) {
//if (this.size < that.size) return -1; /** Remove the first element matching the given filter. * Return the filtered value. /** Remove the last element matching the given filter. * Return the filtered value. /** Remove all elements matching the given filter. * If there is a non-null collection given as a sink, * transfer removed elements to the given collection. * The int result is the number of removed elements. * If there is a null sink given, the removed elements * are discarded. If there is no sink given, the removed * elements are returned in an anonymous container element. /** Remove all elements not matching the given filter. * If there is a non-null collection given as a sink, * transfer removed elements to the given collection. * The int result is the number of removed elements. * If there is a null sink given, the removed elements * are discarded. If there is no sink given, the removed * elements are returned in an anonymous container element. // (The shape of this method is tweaked for common cases.) e.
getClass();
// force a null check on e // Common case: Have some slop space. // Most common case: Append. // Second most common case: Shift right by one. // Ran out of space. Do something complicated. /** Returns the text of this Element. * All sub-elements of this Element must be of type CharSequence. * A ClassCastException is raised if there are non-character sub-elements. * If there is one sub-element, return it. * Otherwise, returns a TokenList of all sub-elements. * This results in a space being placed between each adjacent pair of sub-elements. /** Provides an iterable view of this object as a series of texts. * All sub-elements of this Element must be of type CharSequence. * A ClassCastException is raised if there are non-character sub-elements. /** Returns an array of strings derived from the sub-elements of this object. * All sub-elements of this Element must be of type CharSequence. * A ClassCastException is raised if there are non-character sub-elements. for (
int i =
0; i <
size; i++) {
/** Like getText, except that it disregards non-text elements. * Non-text elements are replaced by their textual contents, if any. * Text elements which were separated only by non-text element * boundaries are merged into single tokens. * There is no corresponding setter, since this accessor does * not report the full state of the element. for (
int i =
0; i <
size; i++) {
// Skip, but erase this boundary. // Merge w/ previous token. /** Return true if all sub-elements are of type CharSequence. */ for (
int i =
0; i <
size; i++) {
/** Return true if at least one sub-element is of type CharSequence. */ for (
int i =
0; i <
size; i++) {
/** Raise a ClassCastException if !isText. */ for (
int i =
0; i <
size; i++) {
/** Clears out all sub-elements, and replaces them by the given text. * A ClassCastException is raised if there are non-character sub-elements, * either before or after the change. // TL's contain only strings /** Add text at the given position, merging with any previous * text element, but preserving token boundaries where possible. * In all cases, the new value of getText() is the string * concatenation of the old value of getText() plus the new text. * The total effect is to concatenate the given text to any * pre-existing text, and to do so efficiently even if there * are many such concatenations. Also, getText calls which * return multiple tokens (in a TokenList) are respected. * For example, if x is empty, x.addText(y.getText()) puts * an exact structural copy of y's text into x. * Internal token boundaries in the original text, and in the new * text (i.e., if it is a TokenList), are preserved. However, * at the point where new text joins old text, a StringBuffer * or new String may be created to join the last old and first * If the given text is a TokenList, add the tokens as * separate sub-elements, possibly merging the first token to * a previous text item (to avoid making a new token boundary). * If the element preceding position i is a StringBuffer, * append the first new token to it. * If the preceding element is a CharSequence, replace it by a * StringBuffer containing both its and the first new token. * If tokens are added after a StringBuffer, freeze it into a String. * Every token not merged into a previous CharSequence is added * as a new sub-element, starting at position i. * Returns the number of elements added, which is useful * for further calls to addText. This number is zero * if the input string was null, or was successfully * merged into a StringBuffer at position i-1. * By contrast, calling add(text) always adds a new sub-element. * In that case, if there is a previous string, a separating * space is virtually present also, and will be observed if * getText() is used to return all the text together. // Text is a list of tokens. // Add the n-1 remaining tokens. private // no reason to make this helper public return 0;
// Trivial success. return 0;
// Merged with previous token. // Tries to merge token with previous contents. // Returns true if token is successfully disposed of. // If keepSB is false, any previous StringBuffer is frozen. // If keepSB is true, a StringBuffer may be created to hold if (i ==
0)
// Trivial success if the token is length zero. return true;
// Trivial success. /** Trim all strings, using String.trim(). * Normalize CharSequences to Strings. for (
int i =
0; i <
size; i++) {
/** Add one or more subelements at the given position. * If the object reference is null, nothing happens. * If the object is an anonymous Element, addAll is called. * If the object is a TokenList, addAll is called (to add the tokens). * Otherwise, add is called, adding a single subelement or string. * The net effect is to add zero or more tokens. * The returned value is the number of added elements. * Note that getText() can return a TokenList which preserves * token boundaries in the text source. Such a text will be * added as multiple text sub-elements. * If a text string is added adjacent to an immediately * preceding string, there will be a token boundary between * the strings, which will print as an extra space. /** Equivalent to Collections.reverse(this.asList()). */ /** Equivalent to Collections.shuffle(this.asList() [, rnd]). */ /** Equivalent to Collections.rotate(this.asList(), dist). */ /** Equivalent to Collections.min(this.asList(), c). */ /** Equivalent to Collections.max(this.asList(), c). */ if (c
instanceof LView) {
// Return number of added (not merely changed) attrs. /** Find the last element matching the given filter. * Return the filtered value. /** Find all elements matching the given filter. * If there is a non-null collection given as a sink, * transfer matching elements to the given collection. * The int result is the number of matching elements. * If there is a null sink given, the matching elements are * not collected. If there is no sink given, the matching * elements are returned in an anonymous container element. * In no case is the receiver element changed. * Note that a simple count of matching elements can be * obtained by passing a null collection argument. // findAllInTree(f) == findAll(findInTree(f,S)), S.toElement // findAllInTree(f,S) == findAll(findInTree(content(f,S))) // removeAllInTree(f) == replaceAll(replaceInTree(and(f,emptyF))) // removeAllInTree(f,S) == replaceAll(replaceInTree(and(content(f,S),emptyF))) // retainAllInTree(f) == removeAllInTree(not(f)) // replaceAllInTree(f) == replaceAll(replaceInTree(f)) for (
int i =
0; i <
size; i++) {
/** Raise a ClassCastException if any subelements are the wrong type. */ for (
int i =
0; i <
size; i++) {
/** Return true if all sub-elements are of the given type. */ for (
int i =
0; i <
size; i++) {
/** Provides an iterable view of this object as a series of elements. * All sub-elements of this Element must be of type Element. * A ClassCastException is raised if there are non-Element sub-elements. // Finding or removing elements w/o regard to their type or content. // Finding or removing by element tag or selected attribute, // as if by elementFilter(name) or attrFilter(name, value). // Roughly akin to Common Lisp ASSOC. for (
int i =
0; i <
size; i++) {
for (
int i =
size -
1; i >=
0; i--) {
/** Remove the first element matching the given filter. * Return the filtered value. /** Remove the last element matching the given filter. * Return the filtered value. //parts[i+1] = ""; //caller responsibility // If we fell through, we ran into an element part. // Therefore we have run out of empty slots. expand(
size,
2);
// generally expands by more than 2 // since there was a reallocation, the garbage slots are really null //parts[i+1] = ""; //caller responsibility //return asAttrMap().keySet(); // Hand-inlined replacement for asAttrMap().keySet().iterator(): int cursor = -
2;
// pointer from end of parts /** Return an anonymous copy of self, but only with attributes. /** Get all attributes, represented as an element with sub-elements. * The name of each sub-element is the attribute key, and the text * This is a fresh copy, and can be updated with affecting the original. * of each sub-element is the corresponding attribute value. * See also asAttrMap() for a "live" view of all the attributes as a Map. for (
int i =
0; i <
asize; i++) {
// %%% normalize attrs to token lists? while ((i -=
2) >=
size) {
return;
// no attrs to clear // If no elements, free the parts array. /** Are the attributes of the two two elements equal? * Disregards name, sub-elements, and ordering of attributes. // search indexes into unmatched parts of this.attrs: // search indexes into unmatched parts of that.attrs: // try to find the mismatch with the first key: // Optimization: Narrow subsequent searches when easy. // Found the key in this but not that. // Such a mismatch puts the guy missing the key last. // found a mismatch, key present in both elems // We have located the first mismatch of all keys in this.attrs. // In general we must also look for keys in that.attrs but missing // from this.attrs; such missing keys, if earlier than firstKey, // We can sometimes prove quickly there is no missing key. // Exhausted all keys in that.attrs. // Search for a missing key in that.attrs earlier than firstKey. // Found a better key; is it missing? // If we get here, there was no match in this.attrs. // No missing key. Previous comparison value rules. // Binary search looking for first non-null after size. // Smallest & largest possible attribute indexes: // earlist possible attribute position: // binary search using scaled indexes: /** Sort attributes by name. */ for (
int k =
0; k <
alen /
2; k++) {
for (
int k =
0; k <
alen /
2; k++) {
// reorder keys and values for (
int k =
0; k <
alen /
2; k++) {
Notes on whitespace and tokenization. On input, never split CDATA blocks. They remain single tokens. ?Try to treat encoded characters as CDATA-quoted, also? Internally, each String sub-element is logically a token. However, if there was no token-splitting on input, consecutive strings are merged by the parser. Internally, we need addToken (intervening blank) and addText Optionally on input, tokenize unquoted text into words. Between each adjacent word pair, elide either one space On output, we always add spaces between tokens. The Element("a", {"b", "c", Element("d"), "e f"}) outputs as "<a>b c<d/>e f</a>" /** Split strings into tokens, using a StringTokenizer. */ for (
int i =
0; i <
size; i++) {
for (
int j =
0; j <
nstrs; j++) {
// Others: toArray(Object[]), containsAll, removeAll, retainAll /** Produce a list view of sub-elements. * (The list view does not provide access to the element's * Changes to this view are immediately reflected in the /** Produce a list iterator on all sub-elements. */ //return asList().listIterator(); // Hand-inlined replacement for LView.listIterator(): /** A PrintWriter which always appends as if by addText. * Use of this stream may insert a StringBuffer at the end * of the Element. The user must not directly modify this * StringBuffer, or use it in other data structures. * From time to time, the StringBuffer may be replaced by a * constant string as a result of using the PrintWriter. }
// synchronize on this buffer //buf.append(s.substring(off, off+len)); // Freeze the pre-existing use of buf. /** Produce a map view of attributes, in which the attribute * name strings are the keys. * (The map view does not provide access to the element's * Changes to this view are immediately reflected in the int k =
0;
// index of pending next() attribute /** Reports number of additional elements this object can accommodate /** Ensures that at least the given number of additional elements * can be added to this object without reallocation. * Trim excess capacity to zero, or do nothing if frozen. * This minimizes the space occupied by this Element, * at the expense of a reallocation if sub-elements or attributes /** Changes the number of additional elements this object can accommodate // Return true if there are at least len nulls of slop available. // Opens up parts array at pos by len spaces. // Reallocate and open up at parts[pos] to at least len empty places. // Shift anything after pos right by len. Reallocate if necessary. // If pos < size, caller must fill it in with non-null values. // Returns incremented size; caller is responsible for storing it // There must be at least len nulls between elems and attrs. int tlen =
size -
pos;
// length of elements in post-pos tail // copy head of sub-elements // copy tail of sub-elements //assert(hasNulls(len)); <- not yet true, since size != nsize // Open or expand at the given position, as appropriate. // Close up at parts[pos] len old places. // Shift anything after pos left by len. // Fill unused end of parts with null. // reinitialize the unoccupied slots to null throw new Error(
ee);
// should not happen throw new Error(
ee);
// should not happen // For debugging only. Reveals internal layout. &&
args.
length >
0 &&
args[
0] ==
int.
class)
// ignore getAttr(int), etc. // Delete ambiguous methods. //System.out.println("ambig: "+pm); //System.out.println(" with: "+m); //ambig: int addAll(int,Element) // with: int addAll(int,Collection) //System.out.println("allM: "+allM); /** Supports sorting of mixed content. Sorts strings first, * then Elements, then everything else (as Comparable). /** Used to find, filter, or transform sub-elements. * When used as a predicate, the filter returns a null * value for false, and the original object value for true. * When used as a transformer, the filter may return * null, for no values, the original object, a new object, * or an anonymous Element (meaning multiple results). /** Use this to find an element, perhaps with a given name. */ /** Subclasses may override this to implement better value tests. * By default, it returns the element itself, thus recognizing * all elements, regardless of name. return elem;
// override this return "<ElementFilter name='*'/>";
return "<ElementFilter name='" +
name +
"'/>";
return "<ElementFilter name='" +
nameSet +
"'/>";
/** Use this to find an element with a named attribute, * possibly with a particular value. * (Note that an attribute is missing if and only if its value is null.) /** Subclasses may override this to implement better value tests. * By default, it returns true for any non-null value, thus * recognizing any attribute of the given name, regardless of value. return "<AttrFilter name='" +
attrName +
"' value='*'/>";
/** Use this to find a sub-element of a given class. */ /** This filter always returns its own argument. */ /** This filter always returns a fixed value, regardless of argument. */ return "<Constant>" +
value +
"</Constant>";
/** Use this to invert the logical sense of the given filter. */ return "<Not>" + f +
"</Not>";
/** Use this to combine several filters with logical AND. * Returns either the first null or the last non-null value. return selfFilter();
// always true (on non-null inputs) /** Use this to combine several filters with logical OR. * Returns either the first non-null or the last null value. /** Use this to combine several filters with logical AND, * and where each non-null result is passed as the argument * Returns either the first null or the last non-null value. /** Copy everything produced by f to sink, using addContent. */ /** Look down the tree using f, collecting fx, else recursing into x. * findInTree(f, s) == findInTree(content(f, s)) * findInTree(f) == replaceInTree(and(f, selfFilter())). /** Look down the tree using f, recursing into x unless fx. */ /** Look down the tree using f. Replace each x with fx, else recurse. * If post filter g is given, optionally replace with gx after recursion. // Optional postorder traversal: return res;
// usually null, meaning no replacement /** Make a filter which calls this method on the given element. * If the method is static, the first argument is passed the * the subtree value being filtered. * If the method is non-static, the receiver is the subtree value itself. * Optionally, additional arguments may be specified. * If the filtered value does not match the receiver class * (or else the first argument type, if the method is static), * the filter returns null without invoking the method. * The returned filter value is the result returned from the method. * Optionally, a non-null special false result value may be specified. * If the result returned from the method is equal to that false value, * the filter will return null. return null;
// filter fails quickly // Void methods return self by convention. // (But void "tests" always return false.) // Tests return self by convention. return "<Method>" + m +
"</Method>";
/** Call the filter on each list element x, and replace x with the * resulting filter value e, or its parts. * If e is null, keep x. (This eases use of partial-domain filters.) * If e is a TokenList or an anonymous Element, add e's parts * to the list instead of x. * Otherwise, replace x by e. * The effect at each list position <code>n</code> may be expressed * in terms of XMLKit.addContent as follows: * Object e = f.filter(target.get(n)); * addContent(e, target.subList(n,n)); * Note: To force deletion of x, simply have the filter return * Element.EMPTY or TokenList.EMPTY. * To force null filter values to have this effect, * use the expression: <code>or(f, emptyFilter())</code>. // Unliked addContent, a null is a no-op here. /** If e is null, return zero. * If e is a TokenList or an anonymous Element, add e's parts * to the collection, and return the number of parts. * Otherwise, add e to the collection, and return one. * If the collection reference is null, the result is as if * a throwaway collection were used. /** SAX2 document handler for building Element trees. */ /*, EntityResolver, DTDHandler, ErrorHandler*/ int[]
attrBases =
new int[
10];
// index into parts int[]
elemBases =
new int[
10];
// index into parts int depth = -
1;
// index into attrBases, elemBases // Parts is organized this way: // | name0 | akey aval ... | subelem ... | name1 | ... | // The position of the first "akey" after name0 is attrBases[0]. // The position of the first "subelem" after name0 is elemBases[0]. // The position after the last part is always nparts. //System.out.println("addPart "+x); // Freeze temporary StringBuffers into strings. // ContentHandler callbacks for (
int k =
0; k <
na; k++) {
// Get ready to collect elements. for (
int k =
0; k <
alen; k +=
2) {
// Back out of this level. // Strip unquoted blanks. // If buffer was empty, or had only ignorable blanks, do nothing. // Decide whether to merge some of these chars into a previous token. // Replace previous string with new StringBuffer. // Appended only the first token. // Add the rest as separate parts. /** Produce a ContentHandler for use with an XML parser. * The object is <em>also</em> a LexicalHandler. * Every top-level Element produced will get added to sink. * All elements will be frozen iff makeFrozen is true. //parser.setFastStandalone(true); // Ignore. We will miss the comments and whitespace. for (
int i =
0; i < e.
size(); i++) {
public boolean abbreviated;
// nonstandard format cuts down on noise w.
write(
"null");
// Should not happen.... for (
int i =
0; i < e.
size(); i++) {
for (
int i =
0; i <
len; i++) {
esc =
"&#" + (
int)
ch +
";";
vpos = i +
1;
// skip escaped char // write the unquoted tail split +=
2;
// bisect the "]]>" goo /** If str is null, empty, or blank, returns null. * Otherwise, return a Double if str spells a double value and contains '.' or 'e'. * Otherwise, return an Integer if str spells an int value. * Otherwise, return a Long if str spells a long value. * Otherwise, return a BigInteger for the string. * Otherwise, throw NumberFormatException. // Narrow to Integer, if possible. // Could not represent it as a long. //new org.jdom.input.SAXBuilder().build(file).getRootElement(); //Document build(InputSource in) throws JDOMException char[]
cbuf =
new char[
1024];
for (
int i =
1; i <
reps; i++) {
//System.out.println(ru);