You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/09/06 14:27:04 UTC

[12/18] temporarily added a patched version of javolution with fast collections, because the released version has several bugs (see https://java.net/jira/browse/JAVOLUTION-106 and https://java.net/jira/browse/JAVOLUTION-105)

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/text/Text.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/Text.java b/commons/marmotta-commons/src/ext/java/javolution/text/Text.java
new file mode 100644
index 0000000..285ab34
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/Text.java
@@ -0,0 +1,1333 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ * 
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.text;
+
+import java.io.PrintStream;
+
+import javolution.lang.MathLib;
+import javolution.lang.Realtime;
+import javolution.lang.ValueType;
+import javolution.util.FastMap;
+import javolution.util.function.Equalities;
+import javolution.xml.XMLSerializable;
+
+/**
+ * <p> An immutable character sequence with fast {@link #concat concatenation}, 
+ *     {@link #insert insertion} and 
+ *     {@link #delete deletion} capabilities (O[Log(n)]) instead of 
+ *     O[n] for StringBuffer/StringBuilder).</p>
+ * <p> This class has the same methods as 
+ *     <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html">
+ *     Java String</a> and 
+ *     <a href="http://msdn2.microsoft.com/en-us/library/system.string.aspx">
+ *     .NET String</a> with the following benefits:<ul>
+ *     <li> No need for an intermediate 
+ *          {@link StringBuffer}/{@link StringBuilder} in order to manipulate 
+ *          textual documents (insertion, deletion or concatenation).</li>
+ *     <li> Bug free. They are not plagued by the {@link String#substring} <a
+ *          href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4513622">
+ *          memory leak bug</a> (when small substrings prevent memory from 
+ *          larger string from being garbage collected).</li>
+ *     <li> More flexible as they allows for search and comparison with any 
+ *          <code>java.lang.String</code> or <code>CharSequence</code>.</li>
+ *     </ul></p>
+ * <p> {@link Text} literals should be explicitly {@link #intern interned}. 
+ *     Unlike strings literals and strings-value constant expressions,
+ *     interning is not implicit. For example:[code]
+ *         final static Text TRUE = new Text("true").intern();
+ *         final static Text FALSE = new Text("true").intern("false");
+ *     [/code]</p>
+ *     
+ * <p><i> Implementation Note: To avoid expensive copy operations , 
+ *        {@link Text} instances are broken down into smaller immutable 
+ *        sequences, they form a minimal-depth binary tree.
+ *        The tree is maintained balanced automatically through <a 
+ *        href="http://en.wikipedia.org/wiki/Tree_rotation">tree rotations</a>. 
+ *        Insertion/deletions are performed in <code>O[Log(n)]</code>
+ *        instead of <code>O[n]</code> for 
+ *        <code>StringBuffer/StringBuilder</code>.</i></p>
+ * 
+ * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @author Wilfried Middleton
+ * @version 6.0, July 21, 2013
+ */
+@Realtime
+public final class Text implements CharSequence, Comparable<CharSequence>,
+        XMLSerializable, ValueType<Text> {
+
+    private static final long serialVersionUID = 0x600L; // Version.
+
+    /**
+     * Holds the default size for primitive blocks of characters.
+     */
+    private static final int BLOCK_SIZE = 1 << 5;
+
+    /**
+     * Holds the mask used to ensure a block boundary cesures.
+     */
+    private static final int BLOCK_MASK = ~(BLOCK_SIZE - 1);
+
+    /**
+     * Holds the texts interned in immortal memory.
+     */
+    private static final FastMap<Text, Text> INTERN = new FastMap<Text, Text>()
+            .shared();
+
+    /**
+     * Holds an empty character sequence.
+     */
+    public static final Text EMPTY = new Text("").intern();
+
+    /**
+     * Holds the raw data (primitive) or <code>null</code> (composite).
+     */
+    private final char[] _data;
+
+    /**
+     * Holds the total number of characters.
+     */
+    private int _count;
+
+    /**
+     * Holds the head block of character (composite).
+     */
+    private Text _head;
+
+    /**
+     * Holds the tail block of character (composite).
+     */
+    private Text _tail;
+
+    /**
+     * Creates a new text instance.
+     * 
+     * @param isPrimitive indicates if primitive or composite.
+     */
+    private Text(boolean isPrimitive) {
+        _data = isPrimitive ? new char[BLOCK_SIZE] : null;
+    }
+
+    /**
+     * Creates a text holding the characters from the specified <code>String
+     * </code>.
+     * 
+     * @param str the string holding the character content. 
+     */
+    public Text(String str) {
+        this(str.length() <= BLOCK_SIZE);
+        _count = str.length();
+        if (_data != null) { // Primitive.
+            str.getChars(0, _count, _data, 0);
+        } else { // Composite, splits on a block boundary. 
+            int half = ((_count + BLOCK_SIZE) >> 1) & BLOCK_MASK;
+            _head = new Text(str.substring(0, half));
+            _tail = new Text(str.substring(half, _count));
+        }
+    }
+
+    /**
+     * Returns the text representing the specified object.
+     *
+     * @param  obj the object to represent as text.
+     * @return {@code new TextBuilder().append(obj).toText()}
+     */
+    public static Text valueOf(Object obj) {
+        return new TextBuilder().append(obj).toText();
+    }
+
+    private static Text valueOf(String str) {
+        return Text.valueOf(str, 0, str.length());
+    }
+
+    private static Text valueOf(String str, int start, int end) {
+        int length = end - start;
+        if (length <= BLOCK_SIZE) {
+            Text text = newPrimitive(length);
+            str.getChars(start, end, text._data, 0);
+            return text;
+        } else { // Splits on a block boundary.
+            int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
+            return newComposite(Text.valueOf(str, start, start + half),
+                    Text.valueOf(str, start + half, end));
+        }
+    }
+
+    /**
+     * Returns the text that contains the characters from the specified 
+     * array.
+     *
+     * @param chars the array source of the characters.
+     * @return the corresponding instance.
+     */
+    public static Text valueOf(char[] chars) {
+        return Text.valueOf(chars, 0, chars.length);
+    }
+
+    /**
+     * Returns the text that contains the characters from the specified 
+     * subarray of characters.
+     *
+     * @param chars the source of the characters.
+     * @param offset the index of the first character in the data soure.
+     * @param length the length of the text returned.
+     * @return the corresponding instance.
+     * @throws IndexOutOfBoundsException if <code>(offset < 0) || 
+     *         (length < 0) || ((offset + length) > chars.length)</code>
+     */
+    public static Text valueOf(char[] chars, int offset, int length) {
+        if ((offset < 0) || (length < 0) || ((offset + length) > chars.length))
+            throw new IndexOutOfBoundsException();
+        if (length <= BLOCK_SIZE) {
+            Text text = Text.newPrimitive(length);
+            System.arraycopy(chars, offset, text._data, 0, length);
+            return text;
+        } else { // Splits on a block boundary.
+            int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
+            return Text.newComposite(Text.valueOf(chars, offset, half),
+                    Text.valueOf(chars, offset + half, length - half));
+        }
+    }
+
+    /**
+     * Converts a text builder to a text instance (optimization for 
+     * TextBuilder.toText()).
+     * 
+     * @param  start the index of the first character inclusive.
+     * @param  end the index of the last character exclusive.
+     * @return the corresponding text instance.
+     */
+    static Text valueOf(TextBuilder tb, int start, int end) {
+        int length = end - start;
+        if (length <= BLOCK_SIZE) {
+            Text text = Text.newPrimitive(length);
+            tb.getChars(start, end, text._data, 0);
+            return text;
+        } else { // Splits on a block boundary.
+            int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
+            return Text.newComposite(Text.valueOf(tb, start, start + half),
+                    Text.valueOf(tb, start + half, end));
+        }
+    }
+
+    /**
+     * Returns the text representation of the <code>boolean</code> argument.
+     *
+     * @param b a <code>boolean</code>.
+     * @return if the argument is <code>true</code>, the text 
+     *          <code>"true"</code> is returned; otherwise, the text 
+     *          <code>"false"</code> is returned.
+     */
+    public static Text valueOf(boolean b) {
+        return b ? TRUE : FALSE;
+    }
+
+    private static final Text TRUE = new Text("true").intern();
+
+    private static final Text FALSE = new Text("false").intern();
+
+    /**
+     * Returns the text instance corresponding to the specified character. 
+     *
+     * @param c a character.
+     * @return a text of length <code>1</code> containing <code>'c'</code>.
+     */
+    public static Text valueOf(char c) {
+        Text text = Text.newPrimitive(1);
+        text._data[0] = c;
+        return text;
+    }
+
+    /**
+     * Returns the decimal representation of the specified <code>int</code>
+     * argument.
+     *
+     * @param  i the <code>int</code> to format.
+     * @return the corresponding text instance.
+     */
+    public static Text valueOf(int i) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(i).toText();
+    }
+
+    /**
+     * Returns the radix representation of the specified <code>int</code>
+     * argument.
+     *
+     * @param  i the <code>int</code> to format.
+     * @param  radix the radix (e.g. <code>16</code> for hexadecimal).
+     * @return the corresponding text instance.
+     */
+    public static Text valueOf(int i, int radix) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(i, radix).toText();
+    }
+
+    /**
+     * Returns the decimal representation of the specified <code>long</code>
+     * argument.
+     *
+     * @param  l the <code>long</code> to format.
+     * @return the corresponding text instance.
+     */
+    public static Text valueOf(long l) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(l).toText();
+    }
+
+    /**
+     * Returns the radix representation of the specified <code>long</code>
+     * argument.
+     *
+     * @param  l the <code>long</code> to format.
+     * @param  radix the radix (e.g. <code>16</code> for hexadecimal).
+     * @return the corresponding text instance.
+     */
+    public static Text valueOf(long l, int radix) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(l, radix).toText();
+    }
+
+    /**
+     * Returns the textual representation of the specified <code>float</code>
+     * instance.
+     *
+     * @param  f the <code>float</code> to format.
+     * @return the corresponding text instance.
+     */
+    public static Text valueOf(float f) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(f).toText();
+    }
+
+    /**
+     * Returns the textual representation of the specified <code>double</code>
+     * argument.
+     *
+     * @param  d the <code>double</code> to format.
+     * @return the corresponding text instance.
+     */
+    public static Text valueOf(double d) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(d).toText();
+    }
+
+    /**
+     * Returns the textual representation of the specified <code>double</code>
+     * argument formatted as specified.
+     *
+     * @param  d the <code>double</code> to format.
+     * @param  digits the number of significative digits (excludes exponent) or
+     *         <code>-1</code> to mimic the standard library (16 or 17 digits).
+     * @param  scientific <code>true</code> to forces the use of the scientific 
+     *         notation (e.g. <code>1.23E3</code>); <code>false</code> 
+     *         otherwise. 
+     * @param  showZero <code>true</code> if trailing fractional zeros are 
+     *         represented; <code>false</code> otherwise.
+     * @return the corresponding text instance.
+     * @throws IllegalArgumentException if <code>(digits &gt; 19)</code>)
+     */
+    public static Text valueOf(double d, int digits, boolean scientific,
+            boolean showZero) {
+        TextBuilder tb = new TextBuilder();
+        return tb.append(d, digits, scientific, showZero).toText();
+    }
+
+    /**
+     * Returns the length of this text.
+     *
+     * @return the number of characters (16-bits Unicode) composing this text.
+     */
+    public int length() {
+        return _count;
+    }
+
+    /**
+     * Returns the concatenation of this text and the textual 
+     * representation of the specified object.
+     * 
+     * @param  obj the object whose textual representation is concatenated.
+     * @return <code>this.concat(Text.valueOf(obj))</code>
+     */
+    public Text plus(Object obj) {
+        return this.concat(Text.valueOf(obj));
+    }
+
+    /**
+     * Returns the concatenation of this text and the specified 
+     * <code>String</code> (optimization).
+     * 
+     * @param  str the string whose characters are concatenated.
+     * @return <code>this.concat(Text.valueOf(obj))</code>
+     */
+    public Text plus(String str) {
+
+        Text merge = this.append(str);
+        return merge != null ? merge : concat(Text.valueOf(str));
+    }
+
+    private Text append(String str) { // Try to append, returns null if cannot.
+        int length = str.length();
+        if (_data == null) {
+            Text merge = _tail.append(str);
+            return merge != null ? Text.newComposite(_head, merge) : null;
+        } else { // Primitive.
+            if (_count + length > BLOCK_SIZE)
+                return null; // Cannot merge.
+            Text text = Text.newPrimitive(_count + length);
+            System.arraycopy(_data, 0, text._data, 0, _count);
+            str.getChars(0, length, text._data, _count);
+            return text;
+        }
+    }
+
+    /**
+     * Concatenates the specified text to the end of this text. 
+     * This method is very fast (faster even than 
+     * <code>StringBuffer.append(String)</code>) and still returns
+     * a text instance with an internal binary tree of minimal depth!
+     *
+     * @param  that the text that is concatenated.
+     * @return <code>this + that</code>
+     */
+    public Text concat(Text that) {
+        // All Text instances are maintained balanced:
+        //   (head < tail * 2) & (tail < head * 2)
+
+        final int length = this._count + that._count;
+        if (length <= BLOCK_SIZE) { // Merges to primitive.
+            Text text = Text.newPrimitive(length);
+            this.getChars(0, this._count, text._data, 0);
+            that.getChars(0, that._count, text._data, this._count);
+            return text;
+
+        } else { // Returns a composite.
+            Text head = this;
+            Text tail = that;
+
+            if (((head._count << 1) < tail._count) && (tail._data == null)) { // tail is composite
+                // head too small, returns (head + tail/2) + (tail/2) 
+                if (tail._head._count > tail._tail._count) {
+                    // Rotates to concatenate with smaller part.
+                    tail = tail.rightRotation();
+                }
+                head = head.concat(tail._head);
+                tail = tail._tail;
+
+            } else if (((tail._count << 1) < head._count)
+                    && (head._data == null)) { // head is composite.
+                // tail too small, returns (head/2) + (head/2 concat tail)
+                if (head._tail._count > head._head._count) {
+                    // Rotates to concatenate with smaller part.
+                    head = head.leftRotation();
+                }
+                tail = head._tail.concat(tail);
+                head = head._head;
+            }
+            return Text.newComposite(head, tail);
+        }
+    }
+
+    private Text rightRotation() {
+        // See: http://en.wikipedia.org/wiki/Tree_rotation
+        Text P = this._head;
+        if (P._data != null)
+            return this; // Head not a composite, cannot rotate.
+        Text A = P._head;
+        Text B = P._tail;
+        Text C = this._tail;
+        return Text.newComposite(A, Text.newComposite(B, C));
+    }
+
+    private Text leftRotation() {
+        // See: http://en.wikipedia.org/wiki/Tree_rotation
+        Text Q = this._tail;
+        if (Q._data != null)
+            return this; // Tail not a composite, cannot rotate.
+        Text B = Q._head;
+        Text C = Q._tail;
+        Text A = this._head;
+        return Text.newComposite(Text.newComposite(A, B), C);
+    }
+
+    /**
+     * Returns a portion of this text.
+     * 
+     * @param  start the index of the first character inclusive.
+     * @return the sub-text starting at the specified position.
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || 
+     *          (start > this.length())</code>
+     */
+    public Text subtext(int start) {
+        return subtext(start, length());
+    }
+
+    /**
+     * Returns the text having the specified text inserted at 
+     * the specified location.
+     *
+     * @param index the insertion position.
+     * @param txt the text being inserted.
+     * @return <code>subtext(0, index).concat(txt).concat(subtext(index))</code>
+     * @throws IndexOutOfBoundsException if <code>(index < 0) ||
+     *            (index > this.length())</code>
+     */
+    public Text insert(int index, Text txt) {
+        return subtext(0, index).concat(txt).concat(subtext(index));
+    }
+
+    /**
+     * Returns the text without the characters between the specified indexes.
+     *
+     * @param start the beginning index, inclusive.
+     * @param end the ending index, exclusive.
+     * @return <code>subtext(0, start).concat(subtext(end))</code>
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+     *         (start > end) || (end > this.length()</code>
+     */
+    public Text delete(int start, int end) {
+        if (start > end)
+            throw new IndexOutOfBoundsException();
+        return subtext(0, start).concat(subtext(end));
+    }
+
+    /**
+     * Replaces each character sequence of this text that matches the specified 
+     * target sequence with the specified replacement sequence.
+     *
+     * @param target the character sequence to be replaced.
+     * @param replacement the replacement sequence.
+     * @return the resulting text.
+     */
+    public Text replace(java.lang.CharSequence target,
+            java.lang.CharSequence replacement) {
+        int i = indexOf(target);
+        return (i < 0) ? this : // No target sequence found.
+                subtext(0, i).concat(Text.valueOf(replacement)).concat(
+                        subtext(i + target.length()).replace(target,
+                                replacement));
+    }
+
+    /**
+     * Replaces the specified characters in this text with the specified 
+     * replacement sequence.
+     *
+     * @param charSet the set of characters to be replaced.
+     * @param replacement the replacement sequence.
+     * @return the resulting text.
+     */
+    public Text replace(CharSet charSet, java.lang.CharSequence replacement) {
+        int i = indexOfAny(charSet);
+        return (i < 0) ? this : // No character to replace.
+                subtext(0, i).concat(Text.valueOf(replacement)).concat(
+                        subtext(i + 1).replace(charSet, replacement));
+    }
+
+    /**
+     * Returns {@link #subtext(int, int) subtext(start, end)}.
+     *
+     * @param  start the index of the first character inclusive.
+     * @param  end the index of the last character exclusive.
+     * @return <code>this.subtext(start, end)</code>
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+     *         (start > end) || (end > this.length())</code>
+     */
+    public java.lang.CharSequence subSequence(int start, int end) {
+        return subtext(start, end);
+    }
+
+    /**
+     * Returns the index within this text of the first occurrence
+     * of the specified character sequence searching forward.
+     *
+     * @param  csq a character sequence.
+     * @return the index of the first character of the character sequence found;
+     *         or <code>-1</code> if the character sequence is not found.
+     */
+    public int indexOf(java.lang.CharSequence csq) {
+        return indexOf(csq, 0);
+    }
+
+    /**
+     * Returns the index within this text of the first occurrence
+     * of the specified characters sequence searching forward from
+     * the specified index.
+     *
+     * @param  csq a character sequence.
+     * @param  fromIndex the index to start the search from.
+     * @return the index in the range
+     *         <code>[fromIndex, length() - csq.length()]</code> 
+     *         or <code>-1</code> if the character sequence is not found.
+     */
+    public int indexOf(java.lang.CharSequence csq, int fromIndex) {
+
+        // Limit cases.
+        final int csqLength = csq.length();
+        final int min = Math.max(0, fromIndex);
+        final int max = _count - csqLength;
+        if (csqLength == 0) { return (min > max) ? -1 : min; }
+
+        // Searches for csq.
+        final char c = csq.charAt(0);
+        for (int i = indexOf(c, min); (i >= 0) && (i <= max); i = indexOf(c,
+                ++i)) {
+            boolean match = true;
+            for (int j = 1; j < csqLength; j++) {
+                if (this.charAt(i + j) != csq.charAt(j)) {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) { return i; }
+        }
+        return -1;
+    }
+
+    /**
+     * Returns the index within this text of the last occurrence of
+     * the specified characters sequence searching backward.
+     *
+     * @param  csq a character sequence.
+     * @return the index of the first character of the character sequence found;
+     *         or <code>-1</code> if the character sequence is not found.
+     */
+    public int lastIndexOf(java.lang.CharSequence csq) {
+        return lastIndexOf(csq, _count);
+    }
+
+    /**
+     * Returns the index within this text of the last occurrence of
+     * the specified character sequence searching backward from the specified
+     * index.
+     *
+     * @param  csq a character sequence.
+     * @param  fromIndex the index to start the backward search from.
+     * @return the index in the range <code>[0, fromIndex]</code> or
+     *         <code>-1</code> if the character sequence is not found.
+     */
+    public int lastIndexOf(java.lang.CharSequence csq, int fromIndex) {
+
+        // Limit cases.
+        final int csqLength = csq.length();
+        final int min = 0;
+        final int max = Math.min(fromIndex, _count - csqLength);
+        if (csqLength == 0) { return (min > max) ? -1 : max; }
+
+        // Searches for csq.
+        final char c = csq.charAt(0);
+        for (int i = lastIndexOf(c, max); (i >= 0); i = lastIndexOf(c, --i)) {
+            boolean match = true;
+            for (int j = 1; j < csqLength; j++) {
+                if (this.charAt(i + j) != csq.charAt(j)) {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) { return i; }
+        }
+        return -1;
+
+    }
+
+    /**
+     * Indicates if this text starts with the specified prefix.
+     *
+     * @param  prefix the prefix.
+     * @return <code>true</code> if the character sequence represented by the
+     *         argument is a prefix of the character sequence represented by
+     *         this text; <code>false</code> otherwise.
+     */
+    public boolean startsWith(java.lang.CharSequence prefix) {
+        return startsWith(prefix, 0);
+    }
+
+    /**
+     * Indicates if this text ends with the specified suffix.
+     *
+     * @param  suffix the suffix.
+     * @return <code>true</code> if the character sequence represented by the
+     *         argument is a suffix of the character sequence represented by
+     *         this text; <code>false</code> otherwise.
+     */
+    public boolean endsWith(java.lang.CharSequence suffix) {
+        return startsWith(suffix, length() - suffix.length());
+    }
+
+    /**
+     * Indicates if this text starts with the specified prefix
+     * at the specified index.
+     *
+     * @param  prefix the prefix.
+     * @param  index the index of the prefix location in this string.
+     * @return <code>this.substring(index).startsWith(prefix)</code>
+     */
+    public boolean startsWith(java.lang.CharSequence prefix, int index) {
+        final int prefixLength = prefix.length();
+        if ((index >= 0) && (index <= (this.length() - prefixLength))) {
+            for (int i = 0, j = index; i < prefixLength;) {
+                if (prefix.charAt(i++) != this.charAt(j++)) { return false; }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns a copy of this text, with leading and trailing
+     * whitespace omitted.
+     *
+     * @return a copy of this text with leading and trailing white
+     *          space removed, or this text if it has no leading or
+     *          trailing white space.
+     */
+    public Text trim() {
+        int first = 0; // First character index.
+        int last = length() - 1; // Last character index.
+        while ((first <= last) && (charAt(first) <= ' ')) {
+            first++;
+        }
+        while ((last >= first) && (charAt(last) <= ' ')) {
+            last--;
+        }
+        return subtext(first, last + 1);
+    }
+
+    /**
+     * Returns a text equals to this one from a pool of
+     * unique text instances.  
+     * 
+     * @return an unique text instance allocated in permanent memory.
+     */
+    public Text intern() {
+        Text txt = INTERN.putIfAbsent(this, this);
+        return txt == null ? this : txt;
+    }
+
+    /**
+     * Indicates if this text has the same character content as the specified
+     * character sequence.
+     *
+     * @param csq the character sequence to compare with.
+     * @return <code>true</code> if the specified character sequence has the 
+     *        same character content as this text; <code>false</code> otherwise.
+     */
+    public boolean contentEquals(java.lang.CharSequence csq) {
+        if (csq.length() != _count)
+            return false;
+        for (int i = 0; i < _count;) {
+            if (this.charAt(i) != csq.charAt(i++))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Indicates if this text has the same character contend as the specified
+     * character sequence ignoring case considerations. 
+     *
+     * @param  csq the <code>CharSequence</code> to compare this text against.
+     * @return <code>true</code> if the argument and this text are equal, 
+     *         ignoring case; <code>false</code> otherwise.
+     */
+    public boolean contentEqualsIgnoreCase(java.lang.CharSequence csq) {
+        if (this._count != csq.length())
+            return false;
+        for (int i = 0; i < _count;) {
+            char u1 = this.charAt(i);
+            char u2 = csq.charAt(i++);
+            if (u1 != u2) {
+                u1 = Character.toUpperCase(u1);
+                u2 = Character.toUpperCase(u2);
+                if ((u1 != u2)
+                        && (Character.toLowerCase(u1) != Character
+                                .toLowerCase(u2)))
+                    return false;
+
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Compares this text against the specified object for equality.
+     * Returns <code>true</code> if the specified object is a text having
+     * the same character sequence as this text. 
+     * For generic comparaison with any character sequence the 
+     * {@link #contentEquals(CharSequence)} should be used.
+     * 
+     * @param  obj the object to compare with or <code>null</code>.
+     * @return <code>true</code> if that is a text with the same character
+     *         sequence as this text; <code>false</code> otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (!(obj instanceof Text))
+            return false;
+        final Text that = (Text) obj;
+        if (this._count != that._count)
+            return false;
+        for (int i = 0; i < _count;) {
+            if (this.charAt(i) != that.charAt(i++))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns the hash code for this text.
+     *
+     * @return the hash code value.
+     */
+    @Override
+    public int hashCode() {
+        int h = 0;
+        final int length = this.length();
+        for (int i = 0; i < length;) {
+            h = 31 * h + charAt(i++);
+        }
+        return h;
+    }
+
+    /**
+     * Compares this text to another character sequence or string 
+     * lexicographically.
+     *
+     * @param   csq the character sequence to be compared.
+     * @return  <code>TypeFormat.LEXICAL_COMPARATOR.compare(this, csq)</code>
+     * @throws  ClassCastException if the specifed object is not a
+     *          <code>CharSequence</code> or a <code>String</code>.
+     */
+    public int compareTo(CharSequence csq) {
+        return Equalities.LEXICAL.compare(this, csq);
+    }
+
+    /**
+     * Returns <code>this</code> (implements 
+     * {@link javolution.lang.ValueType Realtime} interface).
+     *
+     * @return <code>this</code>
+     */
+    public Text toText() {
+        return this;
+    }
+
+    /**
+     * Prints the current statistics on this text tree structure.
+     *  
+     * @param out the stream to use for output (e.g. <code>System.out</code>)
+     */
+    public void printStatistics(PrintStream out) {
+        int length = this.length();
+        int leaves = getNbrOfLeaves();
+        synchronized (out) {
+            out.print("LENGTH: " + length());
+            out.print(", MAX DEPTH: " + getDepth());
+            out.print(", NBR OF BRANCHES: " + getNbrOfBranches());
+            out.print(", NBR OF LEAVES: " + leaves);
+            out.print(", AVG LEAVE LENGTH: " + (length + (leaves >> 1))
+                    / leaves);
+            out.println();
+        }
+    }
+
+    private int getDepth() {
+        if (_data != null) // Primitive.
+            return 0;
+        return MathLib.max(_head.getDepth(), _tail.getDepth()) + 1;
+    }
+
+    private int getNbrOfBranches() {
+        return (_data == null) ? _head.getNbrOfBranches()
+                + _tail.getNbrOfBranches() + 1 : 0;
+    }
+
+    private int getNbrOfLeaves() {
+        return (_data == null) ? _head.getNbrOfLeaves()
+                + _tail.getNbrOfLeaves() : 1;
+    }
+
+    /**
+     * Converts the characters of this text to lower case.
+     * 
+     * @return the text in lower case.
+     * @see Character#toLowerCase(char) 
+     */
+    public Text toLowerCase() {
+        if (_data == null) // Composite.
+            return Text.newComposite(_head.toLowerCase(), _tail.toLowerCase());
+        Text text = Text.newPrimitive(_count);
+        for (int i = 0; i < _count;) {
+            text._data[i] = Character.toLowerCase(_data[i++]);
+        }
+        return text;
+    }
+
+    /**
+     * Converts the characters of this text to upper case.
+     * 
+     * @return the text in lower case.
+     * @see Character#toUpperCase(char) 
+     */
+    public Text toUpperCase() {
+        if (_data == null) // Composite.
+            return newComposite(_head.toUpperCase(), _tail.toUpperCase());
+        Text text = Text.newPrimitive(_count);
+        for (int i = 0; i < _count;) {
+            text._data[i] = Character.toUpperCase(_data[i++]);
+        }
+        return text;
+    }
+
+    /**
+     * Returns the character at the specified index.
+     *
+     * @param  index the index of the character.
+     * @return the character at the specified index.
+     * @throws IndexOutOfBoundsException if <code>(index < 0) || 
+     *         (index >= this.length())</code>
+     */
+    public char charAt(int index) {
+        if (index >= _count)
+            throw new IndexOutOfBoundsException();
+        return (_data != null) ? _data[index] : (index < _head._count) ? _head
+                .charAt(index) : _tail.charAt(index - _head._count);
+    }
+
+    /**
+     * Returns the index within this text of the first occurrence of the
+     * specified character, starting the search at the beginning.
+     *
+     * @param c the character to search for.
+     * @return the index of the first occurrence of the character in this text
+     *         that is greater than or equal to <code>0</code>,
+     *         or <code>-1</code> if the character does not occur.
+     */
+    public int indexOf(char c) {
+        return indexOf(c, 0);
+    }
+
+    /**
+     * Returns the index within this text of the first occurrence of the
+     * specified character, starting the search at the specified index.
+     *
+     * @param c the character to search for.
+     * @param fromIndex the index to start the search from.
+     * @return the index of the first occurrence of the character in this text
+     *         that is greater than or equal to <code>fromIndex</code>, 
+     *         or <code>-1</code> if the character does not occur.
+     */
+    public int indexOf(char c, int fromIndex) {
+        if (_data != null) { // Primitive.
+            for (int i = MathLib.max(fromIndex, 0); i < _count; i++) {
+                if (_data[i] == c)
+                    return i;
+            }
+            return -1;
+        } else { // Composite.
+            final int cesure = _head._count;
+            if (fromIndex < cesure) {
+                final int headIndex = _head.indexOf(c, fromIndex);
+                if (headIndex >= 0)
+                    return headIndex; // Found in head.
+            }
+            final int tailIndex = _tail.indexOf(c, fromIndex - cesure);
+            return (tailIndex >= 0) ? tailIndex + cesure : -1;
+        }
+    }
+
+    /**
+     * Returns the index within this text of the first occurrence of the
+     * specified character, searching backward and starting at the specified
+     * index.
+     *
+     * @param c the character to search for.
+     * @param fromIndex the index to start the search backward from.
+     * @return the index of the first occurrence of the character in this text
+     *         that is less than or equal to <code>fromIndex</code>, 
+     *         or <code>-1</code> if the character does not occur.
+     */
+    public int lastIndexOf(char c, int fromIndex) {
+        if (_data != null) { // Primitive.
+            for (int i = MathLib.min(fromIndex, _count - 1); i >= 0; i--) {
+                if (_data[i] == c)
+                    return i;
+            }
+            return -1;
+        } else { // Composite.
+            final int cesure = _head._count;
+            if (fromIndex >= cesure) {
+                final int tailIndex = _tail.lastIndexOf(c, fromIndex - cesure);
+                if (tailIndex >= 0)
+                    return tailIndex + cesure; // Found in tail.
+            }
+            return _head.lastIndexOf(c, fromIndex);
+        }
+    }
+
+    /**
+     * Returns a portion of this text.
+     *
+     * @param  start the index of the first character inclusive.
+     * @param  end the index of the last character exclusive.
+     * @return the sub-text starting at the specified start position and 
+     *         ending just before the specified end position.
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+     *         (start > end) || (end > this.length())</code>
+     */
+    public Text subtext(int start, int end) {
+        if (_data != null) { // Primitive.
+            if ((start < 0) || (start > end) || (end > _count))
+                throw new IndexOutOfBoundsException();
+            if ((start == 0) && (end == _count))
+                return this;
+            if (start == end)
+                return Text.EMPTY;
+            int length = end - start;
+            Text text = Text.newPrimitive(length);
+            System.arraycopy(_data, start, text._data, 0, length);
+            return text;
+        } else { // Composite.
+            final int cesure = _head._count;
+            if (end <= cesure)
+                return _head.subtext(start, end);
+            if (start >= cesure)
+                return _tail.subtext(start - cesure, end - cesure);
+            if ((start == 0) && (end == _count))
+                return this;
+            // Overlaps head and tail.
+            return _head.subtext(start, cesure).concat(
+                    _tail.subtext(0, end - cesure));
+        }
+    }
+
+    /**
+     * Copies the characters from this text into the destination
+     * character array.
+     *
+     * @param start the index of the first character to copy.
+     * @param end the index after the last character to copy.
+     * @param dest the destination array.
+     * @param destPos the start offset in the destination array.
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+     *         (start > end) || (end > this.length())</code>
+     */
+    public void getChars(int start, int end, char dest[], int destPos) {
+        if (_data != null) { // Primitive.
+            if ((start < 0) || (end > _count) || (start > end))
+                throw new IndexOutOfBoundsException();
+            System.arraycopy(_data, start, dest, destPos, end - start);
+        } else { // Composite.
+            final int cesure = _head._count;
+            if (end <= cesure) {
+                _head.getChars(start, end, dest, destPos);
+            } else if (start >= cesure) {
+                _tail.getChars(start - cesure, end - cesure, dest, destPos);
+            } else { // Overlaps head and tail.
+                _head.getChars(start, cesure, dest, destPos);
+                _tail.getChars(0, end - cesure, dest, destPos + cesure - start);
+            }
+        }
+    }
+
+    /**
+     * Returns the <code>String</code> representation of this text.
+     *
+     * @return the <code>java.lang.String</code> for this text.
+     */
+    public String toString() {
+        if (_data != null) { // Primitive.
+            return new String(_data, 0, _count);
+        } else { // Composite.
+            char[] data = new char[_count];
+            this.getChars(0, _count, data, 0);
+            return new String(data, 0, _count);
+        }
+    }
+
+    // Implements ValueType interface.
+    public Text copy() {
+        if (_data != null) { // Primitive.
+            Text text = Text.newPrimitive(_count);
+            System.arraycopy(_data, 0, text._data, 0, _count);
+            return text;
+        } else { // Composite.
+            return Text.newComposite((Text) _head.copy(), (Text) _tail.copy());
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // Wilfried add-ons (methods provided by Microsoft .Net in C#)
+    //
+    /**
+     * Returns the text that contains a specific length sequence of the
+     * character specified.
+     *
+     * @param c the character to fill this text with.
+     * @param length the length of the text returned.
+     * @return the corresponding instance.
+     * @throws IndexOutOfBoundsException if <code>(length < 0)</code>
+     */
+    public static Text valueOf(char c, int length) {
+        if (length < 0)
+            throw new IndexOutOfBoundsException();
+        if (length <= BLOCK_SIZE) {
+            Text text = Text.newPrimitive(length);
+            for (int i = 0; i < length;) {
+                text._data[i++] = c;
+            }
+            return text;
+        } else {
+            final int middle = (length >> 1);
+            return Text.newComposite(Text.valueOf(c, middle),
+                    Text.valueOf(c, length - middle));
+        }
+    }
+
+    /**
+     * Indicates if all characters of this text are whitespaces
+     * (no characters greater than the space character).
+     *
+     *@return <code>true</code> if this text  contains only whitespace.
+     */
+    public boolean isBlank() {
+        return isBlank(0, length());
+    }
+
+    /**
+     * Indicates if the specified sub-range of characters of this text
+     * are whitespaces (no characters greater than the space character).
+     *
+     *@param start the start index.
+     *@param length the number of characters to inspect.
+     */
+    public boolean isBlank(int start, int length) {
+        for (; start < length; start++) {
+            if (charAt(start) > ' ')
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns a copy of this text, with leading whitespace omitted.
+     *
+     * @return a copy of this text with leading white space removed,
+     * or this text if it has no leading white space.
+     */
+    public Text trimStart() {
+        int first = 0; // First character index.
+        int last = length() - 1; // Last character index.
+        while ((first <= last) && (charAt(first) <= ' ')) {
+            first++;
+        }
+        return subtext(first, last + 1);
+    }
+
+    /**
+     * Returns a copy of this text, with trailing
+     * whitespace omitted.
+     *
+     * @return a copy of this text with trailing white space removed,
+     * or this text if it has no trailing white space.
+     */
+    public Text trimEnd() {
+        int first = 0; // First character index.
+        int last = length() - 1; // Last character index.
+        while ((last >= first) && (charAt(last) <= ' ')) {
+            last--;
+        }
+        return subtext(first, last + 1);
+    }
+
+    /**
+     * Pads this text on the left with spaces to make the minimum total length
+     * as specified.
+     * The new length of the new text is equal to the original length plus
+     * <code>(length()-len)</code> spaces.
+     *
+     * @param len the total number of characters to make this text equal to.
+     * @return a new text or the same text if no padding required.
+     * @throws an IllegalArgumentException if the <code>(len<0)</code>.
+     */
+    public Text padLeft(int len) {
+        return padLeft(len, ' ');
+    }
+
+    /**
+     * Pads this text on the left to make the minimum total length as specified.
+     * Spaces or the given Unicode character are used to pad with.
+     * <br>
+     * The new length of the new text is equal to the original length plus
+     * <code>(length()-len)</code> pad characters.
+     *
+     * @param len the total number of characters to make this text equal to.
+     * @param c the character to pad using.
+     * @return a new text or the same text if no padding required.
+     * @throws an IllegalArgumentException if the <code>(len<0)</code>.
+     */
+    public Text padLeft(int len, char c) {
+        final int padSize = (len <= length()) ? 0 : len - length();
+        return insert(0, Text.valueOf(c, padSize));
+    }
+
+    /**
+     * Pads this text on the right with spaces to make the minimum total length
+     * as specified.
+     * The new length of the new text is equal to the original length plus
+     * <code>(length()-len)</code> spaces.
+     *
+     * @param len the total number of characters to make this text equal to.
+     * @return a new text or the same text if no padding required.
+     * @throws an IllegalArgumentException if the <code>(len<0)</code>.
+     */
+    public Text padRight(int len) {
+        return padRight(len, ' ');
+    }
+
+    /**
+     * Pads this text on the right to make the minimum total length as specified.
+     * Spaces or the given Unicode character are used to pad with.
+     * <br>
+     * The new length of the new text is equal to the original length plus
+     * <code>(length()-len)</code> pad characters.
+     *
+     * @param len the total number of characters to make this text equal to.
+     * @param c the character to pad using.
+     * @return a new text or the same text if no padding required.
+     * @throws an IllegalArgumentException if the <code>(len<0)</code>.
+     */
+    public Text padRight(int len, char c) {
+        final int padSize = (len <= length()) ? 0 : len - length();
+        return concat(Text.valueOf(c, padSize));
+    }
+
+    /**
+     * Returns the index within this text of the first occurrence
+     * of any character in the specified character set.
+     *
+     * @param  charSet the character set.
+     * @return the index of the first character that matches one of the
+     *         characters in the supplied set; or <code>-1</code> if none.
+     */
+    public int indexOfAny(CharSet charSet) {
+        return indexOfAny(charSet, 0, length());
+    }
+
+    /**
+     * Returns the index within a region of this text of the first occurrence
+     * of any character in the specified character set.
+     *
+     * @param charSet the character set.
+     * @param start the index of the start of the search region in this text.
+     * @return the index of the first character that matches one of the
+     *         characters in the supplied set; or <code>-1</code> if none.
+     */
+    public int indexOfAny(CharSet charSet, int start) {
+        return indexOfAny(charSet, start, length() - start);
+    }
+
+    /**
+     * Returns the index within a region of this text of the first occurrence
+     * of any character in the specified character set.
+     *
+     * @param charSet the character set.
+     * @param start the index of the start of the search region in this text.
+     * @param length the length of the region to search.
+     * @return the index of the first character that matches one of the
+     *         characters in the supplied array; or <code>-1</code> if none.
+     */
+    public int indexOfAny(CharSet charSet, int start, int length) {
+        final int stop = start + length;
+        for (int i = start; i < stop; i++) {
+            if (charSet.contains(charAt(i)))
+                return i;
+        }
+        return -1;
+    }
+
+    /**
+     * Returns the index within this text of the last occurrence
+     * of any character in the specified character set.
+     *
+     * @param charSet the character set.
+     * @return the index of the last character that matches one of the
+     *         characters in the supplied array; or <code>-1</code> if none.
+     */
+    public int lastIndexOfAny(CharSet charSet) {
+        return lastIndexOfAny(charSet, 0, length());
+    }
+
+    /**
+     * Returns the index within a region of this text of the last occurrence
+     * of any character in the specified character set.
+     *
+     * @param charSet the character set.
+     * @param start the index of the start of the search region in this text.
+     * @return the index of the last character that matches one of the
+     *         characters in the supplied array; or <code>-1</code> if none.
+     */
+    public int lastIndexOfAny(CharSet charSet, int start) {
+        return lastIndexOfAny(charSet, start, length() - start);
+    }
+
+    /**
+     * Returns the index within a region of this text of the last occurrence
+     * of any character in the specified character set.
+     *
+     * @param charSet the character set.
+     * @param start the index of the start of the search region in this text.
+     * @param length the length of the region to search.
+     * @return the index of the last character that matches one of the
+     *         characters in the supplied array; or <code>-1</code> if none.
+     */
+    public int lastIndexOfAny(CharSet charSet, int start, int length) {
+        for (int i = start + length; --i >= start;) {
+            if (charSet.contains(charAt(i)))
+                return i;
+        }
+        return -1;
+    }
+
+    //
+    ////////////////////////////////////////////////////////////////////////////
+    /**
+     * Returns a {@link javolution.context.AllocatorContext context allocated}
+     * primitive text instance.
+     *
+     * @param length the primitive length.
+     */
+    private static Text newPrimitive(int length) {
+        Text text = new Text(true);
+        text._count = length;
+        return text;
+    }
+
+    /**
+     * Returns a {@link javolution.context.AllocatorContext context allocated}
+     * composite text instance.
+     *
+     * @param head the composite head.
+     * @param tail the composite tail.
+     */
+    private static Text newComposite(Text head, Text tail) {
+        Text text = new Text(false);
+        text._count = head._count + tail._count;
+        text._head = head;
+        text._tail = tail;
+        return text;
+    }
+
+    @Override
+    public Text value() {
+        return this;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/text/TextBuilder.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/TextBuilder.java b/commons/marmotta-commons/src/ext/java/javolution/text/TextBuilder.java
new file mode 100644
index 0000000..c5f0a9f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/TextBuilder.java
@@ -0,0 +1,888 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ * 
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.text;
+
+import java.io.Serializable;
+import javolution.lang.MathLib;
+
+/**
+ * <p> An {@link Appendable} text whose capacity expands 
+ *     gently without incurring expensive resize/copy operations ever.</p>
+ *     
+ * <p> This class is not intended for large documents manipulations which 
+ *     should be performed with the {@link Text} class directly 
+ *     (<code>O(Log(n))</code> {@link Text#insert insertion} and 
+ *     {@link Text#delete deletion} capabilities).</p>
+ *     
+ * <p> The textual format of any appended object is retrieved 
+ *     from the current {@link TextContext}.</p>
+ *     
+ * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.3, January 20, 2008
+ */
+public class TextBuilder implements Appendable, CharSequence, Serializable {
+
+    private static final long serialVersionUID = 0x600L; // Version.
+    // We do a full resize (and copy) only when the capacity is less than C1.
+    // For large collections, multi-dimensional arrays are employed.
+    private static final int B0 = 5; // Initial capacity in bits.
+    private static final int C0 = 1 << B0; // Initial capacity (32)
+    private static final int B1 = 10; // Low array maximum capacity in bits.
+    private static final int C1 = 1 << B1; // Low array maximum capacity (1024).
+    private static final int M1 = C1 - 1; // Mask.
+    // Resizes up to 1024 maximum (32, 64, 128, 256, 512, 1024). 
+    private char[] _low = new char[C0];
+    // For larger capacity use multi-dimensional array.
+    private char[][] _high = new char[1][];
+
+    /**
+     * Holds the current length.
+     */
+    private int _length;
+
+    /**
+     * Holds current capacity.
+     */
+    private int _capacity = C0;
+
+    /**
+     * Creates a text builder of small initial capacity.
+     */
+    public TextBuilder() {
+        _high[0] = _low;
+    }
+
+    /**
+     * Creates a text builder holding the specified <code>String</code>
+     * (convenience method).
+     * 
+     * @param str the initial string content of this text builder.
+     */
+    public TextBuilder(String str) {
+        this();
+        append(str);
+    }
+
+    /**
+     * Creates a text builder of specified initial capacity.
+     * Unless the text length exceeds the specified capacity, operations 
+     * on this text builder will not allocate memory.
+     * 
+     * @param capacity the initial capacity.
+     */
+    public TextBuilder(int capacity) {
+        this();
+        while (capacity > _capacity) {
+            increaseCapacity();
+        }
+    }
+
+    /**
+     * Returns the length (character count) of this text builder.
+     *
+     * @return the number of characters (16-bits Unicode).
+     */
+    public final int length() {
+        return _length;
+    }
+
+    /**
+     * Returns the character at the specified index.
+     *
+     * @param  index the index of the character.
+     * @return the character at the specified index.
+     * @throws IndexOutOfBoundsException if 
+     *         <code>(index < 0) || (index >= this.length())</code>.
+     */
+    public final char charAt(int index) {
+        if (index >= _length)
+            throw new IndexOutOfBoundsException();
+        return index < C1 ? _low[index] : _high[index >> B1][index & M1];
+    }
+
+    /**
+     * Copies the character from this text builder into the destination
+     * character array. 
+     *
+     * @param srcBegin this text start index.
+     * @param srcEnd this text end index (not included).
+     * @param dst the destination array to copy the data into.
+     * @param dstBegin the offset into the destination array. 
+     * @throws IndexOutOfBoundsException if <code>(srcBegin < 0) ||
+     *  (dstBegin < 0) || (srcBegin > srcEnd) || (srcEnd > this.length())
+     *  || ((dstBegin + srcEnd - srcBegin) >  dst.length)</code>
+     */
+    public final void getChars(int srcBegin, int srcEnd, char[] dst,
+            int dstBegin) {
+        if ((srcBegin < 0) || (srcBegin > srcEnd) || (srcEnd > this._length))
+            throw new IndexOutOfBoundsException();
+        for (int i = srcBegin, j = dstBegin; i < srcEnd;) {
+            char[] chars0 = _high[i >> B1];
+            int i0 = i & M1;
+            int length = MathLib.min(C1 - i0, srcEnd - i);
+            System.arraycopy(chars0, i0, dst, j, length);
+            i += length;
+            j += length;
+        }
+    }
+
+    /**
+     * Sets the character at the specified position.
+     *
+     * @param index the index of the character to modify.
+     * @param c the new character. 
+     * @throws IndexOutOfBoundsException if <code>(index < 0) || 
+     *          (index >= this.length())</code>
+     */
+    public final void setCharAt(int index, char c) {
+        if ((index < 0) || (index >= _length))
+            throw new IndexOutOfBoundsException();
+        _high[index >> B1][index & M1] = c;
+    }
+
+    /**
+     * Convenience method equivalent to {@link #setLength(int, char)
+     *  setLength(newLength, '\u0000')}.
+     *
+     * @param newLength the new length of this builder.
+     * @throws IndexOutOfBoundsException if <code>(newLength < 0)</code>
+     */
+    public final void setLength(int newLength) {
+        setLength(newLength, '\u0000');
+    }
+
+    /**
+     * Sets the length of this character builder.
+     * If the length is greater than the current length; the 
+     * specified character is inserted.
+     *
+     * @param newLength the new length of this builder.
+     * @param fillChar the character to be appended if required.
+     * @throws IndexOutOfBoundsException if <code>(newLength < 0)</code>
+     */
+    public final void setLength(int newLength, char fillChar) {
+        if (newLength < 0)
+            throw new IndexOutOfBoundsException();
+        if (newLength <= _length)
+            _length = newLength;
+        else
+            for (int i = _length; i++ < newLength;) {
+                append(fillChar);
+            }
+    }
+
+    /**
+     * Returns a {@link java.lang.CharSequence} corresponding 
+     * to the character sequence between the specified indexes.
+     *
+     * @param  start the index of the first character inclusive.
+     * @param  end the index of the last character exclusive.
+     * @return a character sequence.
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+     *         (start > end) || (end > this.length())</code>
+     */
+    public final java.lang.CharSequence subSequence(int start, int end) {
+        if ((start < 0) || (end < 0) || (start > end) || (end > _length))
+            throw new IndexOutOfBoundsException();
+        return Text.valueOf(this, start, end);
+    }
+
+    /**
+     * Appends the specified character.
+     *
+     * @param  c the character to append.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(char c) {
+        if (_length >= _capacity)
+            increaseCapacity();
+        _high[_length >> B1][_length & M1] = c;
+        _length++;
+        return this;
+    }
+
+    /**
+     * Appends the textual representation of the specified object. 
+     * This method is equivalent to 
+     * {@code TextContext.getFormat(obj.getClass()).format(obj, this)}
+     */
+    public final TextBuilder append(Object obj) {
+        if (obj == null) return append("null");
+        TextFormat<Object> textFormat = TextContext.getFormat(obj.getClass());
+        if (textFormat == null) return append(obj.toString());
+        return textFormat.format(obj, this);
+    }
+
+    /**
+     * Appends the specified character sequence. If the specified character
+     * sequence is <code>null</code> this method is equivalent to
+     * <code>append("null")</code>.
+     *
+     * @param  csq the character sequence to append or <code>null</code>.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(CharSequence csq) {
+        return (csq == null) ? append("null") : append(csq, 0, csq.length());
+    }
+
+    /**
+     * Appends a subsequence of the specified character sequence.
+     * If the specified character sequence is <code>null</code> this method 
+     * is equivalent to <code>append("null")</code>. 
+     *
+     * @param  csq the character sequence to append or <code>null</code>.
+     * @param  start the index of the first character to append.
+     * @param  end the index after the last character to append.
+     * @return <code>this</code>
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) 
+     *         || (start > end) || (end > csq.length())</code>
+     */
+    public final TextBuilder append(CharSequence csq, int start,
+            int end) {
+        if (csq == null)
+            return append("null");
+        if ((start < 0) || (end < 0) || (start > end) || (end > csq.length()))
+            throw new IndexOutOfBoundsException();
+        for (int i = start; i < end;) {
+            append(csq.charAt(i++));
+        }
+        return this;
+    }
+
+    /**
+     * Appends the specified string to this text builder. 
+     * If the specified string is <code>null</code> this method 
+     * is equivalent to <code>append("null")</code>. 
+     *
+     * @param str the string to append or <code>null</code>.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(String str) {
+        return (str == null) ? append("null") : append(str, 0, str.length());
+    }
+
+    /**
+     * Appends a subsequence of the specified string.
+     * If the specified character sequence is <code>null</code> this method 
+     * is equivalent to <code>append("null")</code>. 
+     *
+     * @param  str the string to append or <code>null</code>.
+     * @param  start the index of the first character to append.
+     * @param  end the index after the last character to append.
+     * @return <code>this</code>
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) 
+     *         || (start > end) || (end > str.length())</code>
+     */
+    public final TextBuilder append(String str, int start, int end) {
+        if (str == null)
+            return append("null");
+        if ((start < 0) || (end < 0) || (start > end) || (end > str.length()))
+            throw new IndexOutOfBoundsException("start: " + start + ", end: "
+                    + end + ", str.length(): " + str.length());
+        int newLength = _length + end - start;
+        while (_capacity < newLength) {
+            increaseCapacity();
+        }
+        for (int i = start, j = _length; i < end;) {
+            char[] chars = _high[j >> B1];
+            int dstBegin = j & M1;
+            int inc = MathLib.min(C1 - dstBegin, end - i);
+            str.getChars(i, (i += inc), chars, dstBegin);
+            j += inc;
+        }
+        _length = newLength;
+        return this;
+    }
+
+    /**
+     * Appends the specified text to this text builder. 
+     * If the specified text is <code>null</code> this method 
+     * is equivalent to <code>append("null")</code>. 
+     *
+     * @param txt the text to append or <code>null</code>.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(Text txt) {
+        return (txt == null) ? append("null") : append(txt, 0, txt.length());
+    }
+
+    /**
+     * Appends a subsequence of the specified text.
+     * If the specified character sequence is <code>null</code> this method 
+     * is equivalent to <code>append("null")</code>. 
+     *
+     * @param  txt the text to append or <code>null</code>.
+     * @param  start the index of the first character to append.
+     * @param  end the index after the last character to append.
+     * @return <code>this</code>
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) 
+     *         || (start > end) || (end > txt.length())</code>
+     */
+    public final TextBuilder append(Text txt, int start, int end) {
+        if (txt == null)
+            return append("null");
+        if ((start < 0) || (end < 0) || (start > end) || (end > txt.length()))
+            throw new IndexOutOfBoundsException();
+        int newLength = _length + end - start;
+        while (_capacity < newLength) {
+            increaseCapacity();
+        }
+        for (int i = start, j = _length; i < end;) {
+            char[] chars = _high[j >> B1];
+            int dstBegin = j & M1;
+            int inc = MathLib.min(C1 - dstBegin, end - i);
+            txt.getChars(i, (i += inc), chars, dstBegin);
+            j += inc;
+        }
+        _length = newLength;
+        return this;
+    }
+
+    /**
+     * Appends the characters from the char array argument.
+     *
+     * @param  chars the character array source.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(char chars[]) {
+        append(chars, 0, chars.length);
+        return this;
+    }
+
+    /**
+     * Appends the characters from a subarray of the char array argument.
+     *
+     * @param  chars the character array source.
+     * @param  offset the index of the first character to append.
+     * @param  length the number of character to append.
+     * @return <code>this</code>
+     * @throws IndexOutOfBoundsException if <code>(offset < 0) || 
+     *         (length < 0) || ((offset + length) > chars.length)</code>
+     */
+    public final TextBuilder append(char chars[], int offset, int length) {
+        final int end = offset + length;
+        if ((offset < 0) || (length < 0) || (end > chars.length))
+            throw new IndexOutOfBoundsException();
+        int newLength = _length + length;
+        while (_capacity < newLength) {
+            increaseCapacity();
+        }
+        for (int i = offset, j = _length; i < end;) {
+            char[] dstChars = _high[j >> B1];
+            int dstBegin = j & M1;
+            int inc = MathLib.min(C1 - dstBegin, end - i);
+            System.arraycopy(chars, i, dstChars, dstBegin, inc);
+            i += inc;
+            j += inc;
+        }
+        _length = newLength;
+        return this;
+    }
+
+    /**
+     * Appends the textual representation of the specified <code>boolean</code>
+     * argument.
+     *
+     * @param  b the <code>boolean</code> to format.
+     * @return <code>this</code>
+     * @see    TypeFormat
+     */
+    public final TextBuilder append(boolean b) {
+        return b ? append("true") : append("false");
+    }
+
+    /**
+     * Appends the decimal representation of the specified <code>int</code>
+     * argument.
+     *
+     * @param  i the <code>int</code> to format.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(int i) {
+        if (i <= 0) {
+            if (i == 0)
+                return append("0");
+            if (i == Integer.MIN_VALUE) // Negation would overflow.
+                return append("-2147483648");
+            append('-');
+            i = -i;
+        }
+        int digits = MathLib.digitLength(i);
+        if (_capacity < _length + digits)
+            increaseCapacity();
+        _length += digits;
+        for (int index = _length - 1;; index--) {
+            int j = i / 10;
+            _high[index >> B1][index & M1] = (char) ('0' + i - (j * 10));
+            if (j == 0)
+                return this;
+            i = j;
+        }
+    }
+
+    /**
+     * Appends the radix representation of the specified <code>int</code>
+     * argument.
+     *
+     * @param  i the <code>int</code> to format.
+     * @param  radix the radix (e.g. <code>16</code> for hexadecimal).
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(int i, int radix) {
+        if (radix == 10)
+            return append(i); // Faster.
+        if (radix < 2 || radix > 36)
+            throw new IllegalArgumentException("radix: " + radix);
+        if (i < 0) {
+            append('-');
+            if (i == Integer.MIN_VALUE) { // Negative would overflow.
+                appendPositive(-(i / radix), radix);
+                return (TextBuilder) append(DIGIT_TO_CHAR[-(i % radix)]);
+            }
+            i = -i;
+        }
+        appendPositive(i, radix);
+        return this;
+    }
+
+    private void appendPositive(int l1, int radix) {
+        if (l1 >= radix) {
+            int l2 = l1 / radix;
+            // appendPositive(l2, radix);
+            if (l2 >= radix) {
+                int l3 = l2 / radix;
+                // appendPositive(l3, radix);
+                if (l3 >= radix) {
+                    int l4 = l3 / radix;
+                    appendPositive(l4, radix);
+                    append(DIGIT_TO_CHAR[l3 - (l4 * radix)]);
+                } else
+                    append(DIGIT_TO_CHAR[l3]);
+                append(DIGIT_TO_CHAR[l2 - (l3 * radix)]);
+            } else
+                append(DIGIT_TO_CHAR[l2]);
+            append(DIGIT_TO_CHAR[l1 - (l2 * radix)]);
+        } else
+            append(DIGIT_TO_CHAR[l1]);
+    }
+
+    private final static char[] DIGIT_TO_CHAR = { '0', '1', '2', '3', '4', '5',
+            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+            'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+            'w', 'x', 'y', 'z' };
+
+    /**
+     * Appends the decimal representation of the specified <code>long</code>
+     * argument.
+     *
+     * @param  l the <code>long</code> to format.
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(long l) {
+        if (l <= 0) {
+            if (l == 0)
+                return append("0");
+            if (l == Long.MIN_VALUE) // Negation would overflow.
+                return append("-9223372036854775808");
+            append('-');
+            l = -l;
+        }
+        if (l <= Integer.MAX_VALUE)
+            return append((int) l);
+        append(l / 1000000000);
+        int i = (int) (l % 1000000000);
+        int digits = MathLib.digitLength(i);
+        append("000000000", 0, 9 - digits);
+        return append(i);
+    }
+
+    /**
+     * Appends the radix representation of the specified <code>long</code>
+     * argument.
+     *
+     * @param  l the <code>long</code> to format.
+     * @param  radix the radix (e.g. <code>16</code> for hexadecimal).
+     * @return <code>this</code>
+     */
+    public final TextBuilder append(long l, int radix) {
+        if (radix == 10)
+            return append(l); // Faster.
+        if (radix < 2 || radix > 36)
+            throw new IllegalArgumentException("radix: " + radix);
+        if (l < 0) {
+            append('-');
+            if (l == Long.MIN_VALUE) { // Negative would overflow.
+                appendPositive(-(l / radix), radix);
+                return (TextBuilder) append(DIGIT_TO_CHAR[(int) -(l % radix)]);
+            }
+            l = -l;
+        }
+        appendPositive(l, radix);
+        return this;
+    }
+
+    private void appendPositive(long l1, int radix) {
+        if (l1 >= radix) {
+            long l2 = l1 / radix;
+            // appendPositive(l2, radix);
+            if (l2 >= radix) {
+                long l3 = l2 / radix;
+                // appendPositive(l3, radix);
+                if (l3 >= radix) {
+                    long l4 = l3 / radix;
+                    appendPositive(l4, radix);
+                    append(DIGIT_TO_CHAR[(int) (l3 - (l4 * radix))]);
+                } else
+                    append(DIGIT_TO_CHAR[(int) l3]);
+                append(DIGIT_TO_CHAR[(int) (l2 - (l3 * radix))]);
+            } else
+                append(DIGIT_TO_CHAR[(int) l2]);
+            append(DIGIT_TO_CHAR[(int) (l1 - (l2 * radix))]);
+        } else
+            append(DIGIT_TO_CHAR[(int) l1]);
+    }
+
+    /**
+     * Appends the textual representation of the specified <code>float</code>.
+     *
+     * @param  f the <code>float</code> to format.
+     * @return <code>append(f, 10, (abs(f) &gt;= 1E7) || (abs(f) &lt; 0.001), false)</code>
+     */
+    public final TextBuilder append(float f) {
+        return append(f, 10, (MathLib.abs(f) >= 1E7)
+                || (MathLib.abs(f) < 0.001), false);
+    }
+
+    /**
+     * Appends the textual representation of the specified <code>double</code>;
+     * the number of digits is 17 or 16 when the 16 digits representation 
+     * can be parsed back to the same <code>double</code> (mimic the standard
+     * library formatting).
+     * 
+     * @param  d the <code>double</code> to format.
+     * @return <code>append(d, -1, (MathLib.abs(d) >= 1E7) ||
+     *        (MathLib.abs(d) < 0.001), false)</code>
+     */
+    public final TextBuilder append(double d) {
+        return append(d, -1, (MathLib.abs(d) >= 1E7)
+                || (MathLib.abs(d) < 0.001), false);
+    }
+
+    /**
+     * Appends the textual representation of the specified <code>double</code>
+     * according to the specified formatting arguments.
+     *
+     * @param  d the <code>double</code> value.
+     * @param  digits the number of significative digits (excludes exponent) or
+     *         <code>-1</code> to mimic the standard library (16 or 17 digits).
+     * @param  scientific <code>true</code> to forces the use of the scientific 
+     *         notation (e.g. <code>1.23E3</code>); <code>false</code> 
+     *         otherwise. 
+     * @param  showZero <code>true</code> if trailing fractional zeros are 
+     *         represented; <code>false</code> otherwise.
+     * @return <code>TypeFormat.format(d, digits, scientific, showZero, this)</code>
+     * @throws IllegalArgumentException if <code>(digits &gt; 19)</code>)
+     */
+    public final TextBuilder append(double d, int digits, boolean scientific,
+            boolean showZero) {
+        if (digits > 19)
+            throw new IllegalArgumentException("digits: " + digits);
+        if (d != d) // NaN
+            return append("NaN");
+        if (d == Double.POSITIVE_INFINITY)
+            return append("Infinity");
+        if (d == Double.NEGATIVE_INFINITY)
+            return append("-Infinity");
+        if (d == 0.0) { // Zero.
+            if (digits < 0)
+                return append("0.0");
+            append('0');
+            if (showZero) {
+                append('.');
+                for (int j = 1; j < digits; j++) {
+                    append('0');
+                }
+            }
+            return this;
+        }
+        if (d < 0) { // Work with positive number.
+            d = -d;
+            append('-');
+        }
+
+        // Find the exponent e such as: value == x.xxx * 10^e
+        int e = MathLib.floorLog10(d);
+
+        long m;
+        if (digits < 0) { // Use 16 or 17 digits.
+            // Try 17 digits.
+            long m17 = MathLib.toLongPow10(d, (17 - 1) - e);
+            // Check if we can use 16 digits.
+            long m16 = m17 / 10;
+            double dd = MathLib.toDoublePow10(m16, e - 16 + 1);
+            if (dd == d) { // 16 digits is enough.
+                digits = 16;
+                m = m16;
+            } else { // We cannot remove the last digit.
+                digits = 17;
+                m = m17;
+            }
+        } else
+            // Use the specified number of digits.
+            m = MathLib.toLongPow10(d, (digits - 1) - e);
+
+        // Formats.
+        if (scientific || (e >= digits)) {
+            // Scientific notation has to be used ("x.xxxEyy").
+            long pow10 = POW10_LONG[digits - 1];
+            int k = (int) (m / pow10); // Single digit.
+            append((char) ('0' + k));
+            m = m - pow10 * k;
+            appendFraction(m, digits - 1, showZero);
+            append('E');
+            append(e);
+        } else { // Dot within the string ("xxxx.xxxxx").
+            int exp = digits - e - 1;
+            if (exp < POW10_LONG.length) {
+                long pow10 = POW10_LONG[exp];
+                long l = m / pow10;
+                append(l);
+                m = m - pow10 * l;
+            } else
+                append('0'); // Result of the division by a power of 10 larger than any long.
+            appendFraction(m, exp, showZero);
+        }
+        return this;
+    }
+
+    private void appendFraction(long l, int digits, boolean showZero) {
+        append('.');
+        if (l == 0)
+            if (showZero)
+                for (int i = 0; i < digits; i++) {
+                    append('0');
+                }
+            else
+                append('0');
+        else { // l is different from zero.
+            int length = MathLib.digitLength(l);
+            for (int j = length; j < digits; j++) {
+                append('0'); // Add leading zeros.
+            }
+            if (!showZero)
+                while (l % 10 == 0) {
+                    l /= 10; // Remove trailing zeros.
+                }
+            append(l);
+        }
+    }
+
+    private static final long[] POW10_LONG = new long[] { 1L, 10L, 100L, 1000L,
+            10000L, 100000L, 1000000L, 10000000L, 100000000L, 1000000000L,
+            10000000000L, 100000000000L, 1000000000000L, 10000000000000L,
+            100000000000000L, 1000000000000000L, 10000000000000000L,
+            100000000000000000L, 1000000000000000000L };
+
+    /**
+     * Inserts the specified character sequence at the specified location.
+     *
+     * @param index the insertion position.
+     * @param csq the character sequence being inserted.
+     * @return <code>this</code>
+     * @throws IndexOutOfBoundsException if <code>(index < 0) || 
+     *         (index > this.length())</code>
+     */
+    public final TextBuilder insert(int index, java.lang.CharSequence csq) {
+        if ((index < 0) || (index > _length))
+            throw new IndexOutOfBoundsException("index: " + index);
+        final int shift = csq.length();
+        int newLength = _length + shift;
+        while (newLength >= _capacity) {
+            increaseCapacity();
+        }
+        _length = newLength;
+        for (int i = _length - shift; --i >= index;) {
+            this.setCharAt(i + shift, this.charAt(i));
+        }
+        for (int i = csq.length(); --i >= 0;) {
+            this.setCharAt(index + i, csq.charAt(i));
+        }
+        return this;
+    }
+
+    /**
+     * Removes all the characters of this text builder 
+     * (equivalent to <code>this.delete(start, this.length())</code>).
+     * 
+     * @return <code>this.delete(0, this.length())</code>
+     */
+    public final TextBuilder clear() {
+        _length = 0;
+        return this;
+    }
+
+    /**
+     * Removes the characters between the specified indices.
+     * 
+     * @param start the beginning index, inclusive.
+     * @param end the ending index, exclusive.
+     * @return <code>this</code>
+     * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) 
+     *         || (start > end) || (end > this.length())</code>
+     */
+    public final TextBuilder delete(int start, int end) {
+        if ((start < 0) || (end < 0) || (start > end) || (end > this.length()))
+            throw new IndexOutOfBoundsException();
+        for (int i = end, j = start; i < _length;) {
+            this.setCharAt(j++, this.charAt(i++));
+        }
+        _length -= end - start;
+        return this;
+    }
+
+    /**
+     * Reverses this character sequence.
+     *
+     * @return <code>this</code>
+     */
+    public final TextBuilder reverse() {
+        final int n = _length - 1;
+        for (int j = (n - 1) >> 1; j >= 0;) {
+            char c = charAt(j);
+            setCharAt(j, charAt(n - j));
+            setCharAt(n - j--, c);
+        }
+        return this;
+    }
+
+    /**
+     * Returns the {@link Text} corresponding to this {@link TextBuilder}.
+     *
+     * @return the corresponding {@link Text} instance.
+     */
+    public final Text toText() {
+        return Text.valueOf(this, 0, _length);
+    }
+
+    /**
+     * Returns the <code>String</code> representation of this 
+     * {@link TextBuilder}.
+     *
+     * @return the <code>java.lang.String</code> for this text builder.
+     */
+    @Override
+    public final String toString() {
+        return (_length < C1) ? new String(_low, 0, _length) : toLargeString();
+    }
+
+    private String toLargeString() {
+        char[] data = new char[_length];
+        this.getChars(0, _length, data, 0);
+        return new String(data, 0, _length);
+    }
+
+    /**
+     * Returns the <code>CharArray</code> representation of this
+     * {@link TextBuilder}.
+     *
+     * @return the corresponding {@link CharArray} instance.
+     */
+    public final CharArray toCharArray() {
+        CharArray cArray = new CharArray();
+        char[] data;
+        if (_length < C1) {
+            data = _low;
+        } else {
+            data = new char[_length];
+            this.getChars(0, _length, data, 0);
+        }
+        cArray.setArray(data, 0, _length);
+        return cArray;
+    }
+
+    /**
+     * Returns the hash code for this text builder.
+     *
+     * @return the hash code value.
+     */
+    @Override
+    public final int hashCode() {
+        int h = 0;
+        for (int i = 0; i < _length;) {
+            h = 31 * h + charAt(i++);
+        }
+        return h;
+    }
+
+    /**
+     * Compares this text builder against the specified object for equality.
+     * Returns <code>true</code> if the specified object is a text builder 
+     * having the same character content.
+     * 
+     * @param  obj the object to compare with or <code>null</code>.
+     * @return <code>true</code> if that is a text builder with the same 
+     *         character content as this text; <code>false</code> otherwise.
+     */
+    @Override
+    public final boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (!(obj instanceof TextBuilder))
+            return false;
+        TextBuilder that = (TextBuilder) obj;
+        if (this._length != that._length)
+            return false;
+        for (int i = 0; i < _length;) {
+            if (this.charAt(i) != that.charAt(i++))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Indicates if this text builder has the same character content as the 
+     * specified character sequence.
+     *
+     * @param csq the character sequence to compare with.
+     * @return <code>true</code> if the specified character sequence has the 
+     *        same character content as this text; <code>false</code> otherwise.
+     */
+    public final boolean contentEquals(java.lang.CharSequence csq) {
+        if (csq.length() != _length)
+            return false;
+        for (int i = 0; i < _length;) {
+            char c = _high[i >> B1][i & M1];
+            if (csq.charAt(i++) != c)
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Increases this text builder capacity.
+     */
+    private void increaseCapacity() {
+        if (_capacity < C1) { // For small capacity, resize.
+            _capacity <<= 1;
+            char[] tmp = new char[_capacity];
+            System.arraycopy(_low, 0, tmp, 0, _length);
+            _low = tmp;
+            _high[0] = tmp;
+        } else { // Add a new low block of 1024 elements.
+            int j = _capacity >> B1;
+            if (j >= _high.length) { // Resizes _high.
+                char[][] tmp = new char[_high.length * 2][];
+                System.arraycopy(_high, 0, tmp, 0, _high.length);
+                _high = tmp;
+            }
+            _high[j] = new char[C1];
+            _capacity += C1;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/text/TextContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/TextContext.java b/commons/marmotta-commons/src/ext/java/javolution/text/TextContext.java
new file mode 100644
index 0000000..cc8311b
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/TextContext.java
@@ -0,0 +1,93 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ * 
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.text;
+
+import javolution.context.AbstractContext;
+import javolution.context.FormatContext;
+import javolution.osgi.internal.OSGiServices;
+
+/**
+ * <p> A context for plain text parsing/formatting. This context provides 
+ *     the {@link javolution.text.TextFormat TextFormat} to parse/format objects
+ *     of any class. If not superseded, the text format for a class is specified
+ *     by the {@link javolution.text.DefaultTextFormat DefaultTextFormat} 
+ *     annotation.</p>
+ * 
+ * <p> A text context always returns the most specialized format. If the class 
+ *     has no default format annotation (inherited or not), then the default 
+ *     {@link java.lang.Object} format (which calls {@link Object#toString})
+ *     is returned. A predefined format exists for the following standard types:
+ *     <code><ul>
+ *       <li>java.lang.Object (parsing not supported, formatting calls toString())</li>
+ *       <li>java.lang.Boolean</li>
+ *       <li>java.lang.Character</li>
+ *       <li>java.lang.Byte</li>
+ *       <li>java.lang.Short</li>
+ *       <li>java.lang.Integer</li>
+ *       <li>java.lang.Long</li>
+ *       <li>java.lang.Float</li>
+ *       <li>java.lang.Double</li>
+ *       <li>java.lang.Class</li>
+ *       <li>java.lang.String</li>
+ *       <li>java.util.Date (ISO 8601)</li> 
+ *       <li>java.math.BigInteger</li>
+ *       <li>java.math.BigDecimal</li>
+ *       <li>java.awt.Color (hexadecimal RGB value, e.g. {@code 0x112233})</li>
+ *       <li>java.awt.Font</li>
+ *     </ul></code>
+ *     </p>
+ *     
+ * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+public abstract class TextContext extends FormatContext {
+
+    /**
+     * Default constructor.
+     */
+    protected TextContext() {}
+
+    /**
+     * Enters and returns a new text context instance.
+     */
+    public static TextContext enter() {
+        return (TextContext) TextContext.currentTextContext().enterInner();
+    }
+
+    /**
+     * Returns the text format for the specified type. It is the most 
+     * specialized format able to parse/format instances of the specified 
+     * class. If there is no default format for the specified class, 
+     * the standard object format (toString based) is returned.
+     */
+    public static <T> TextFormat<T> getFormat(Class<? extends T> type) {
+        return TextContext.currentTextContext().searchFormat(type);
+    }
+
+    /**
+     * Sets the text format for the specified type (and its sub-types).
+     */
+    public abstract <T> void setFormat(Class<? extends T> type,
+            TextFormat<T> newFormat);
+
+    /**
+     * Searches the most specialized format for the specified type.
+     */
+    protected abstract <T> TextFormat<T> searchFormat(Class<? extends T> type);
+
+    /**
+     * Returns the current text context.
+     */
+    private static TextContext currentTextContext() {
+        TextContext ctx = AbstractContext.current(TextContext.class);
+        if (ctx != null)
+            return ctx;
+        return OSGiServices.getTextContext();
+    }
+}
\ No newline at end of file