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:03 UTC
[11/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/TextFormat.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/TextFormat.java b/commons/marmotta-commons/src/ext/java/javolution/text/TextFormat.java
new file mode 100644
index 0000000..5ba009a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/TextFormat.java
@@ -0,0 +1,125 @@
+/*
+ * 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.IOException;
+
+import javolution.lang.Parallelizable;
+
+/**
+ * <p> The service for plain text parsing and formatting;
+ * it supports {@link CharSequence} and {@link Appendable} interfaces
+ * for greater flexibility.</p>
+ *
+ * <p> Instances of this class are typically retrieved from the
+ * current {@link TextContext} (OSGi service or not).
+ * [code]
+ * @DefaultTextFormat(Complex.Cartesian.class)
+ * public class Complex extends Number {
+ * public static Complex valueOf(CharSequence csq) {
+ * return TextContext.getFormat(Complex.class).parse(csq);
+ * }
+ * public String toString() {
+ * return TextContext.getFormat(Complex.class).format(this);
+ * }
+ * public static class Cartesian extends javolution.text.TextFormat<Complex> { ... }
+ * public static class Polar extends javolution.text.TextFormat<Complex> { ... }
+ * }[/code]</p>
+ *
+ * <p> Text formats can be locally overridden.
+ * [code]
+ * TextContext ctx = TextContext.enter();
+ * try {
+ * ctx.setFormat(Complex.class, Complex.Polar.class); // No impact on others threads.
+ * System.out.println(complexMatrix); // Displays complex numbers in polar coordinates.
+ * } finally {
+ * ctx.exit(); // Reverts to previous cartesian format for complex numbers.
+ * }[/code]</p>
+ *
+ * <p> For parsing/formatting of primitive types, the {@link TypeFormat}
+ * utility class is recommended.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle </a>
+ * @version 6.0, July 21, 2013
+ */
+@Parallelizable
+public abstract class TextFormat<T> {
+
+ /**
+ * Reads a portion of the specified <code>CharSequence</code> from the
+ * specified cursor position to produce an object. If parsing succeeds,
+ * then the index of the <code>cursor</code> argument is updated to the
+ * index after the last character used.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor holding the current parsing index.
+ * @return the object parsed.
+ * @throws IllegalArgumentException if the syntax of the specified
+ * character sequence is incorrect.
+ * @throws UnsupportedOperationException if parsing is not supported.
+ */
+ public abstract T parse(CharSequence csq, Cursor cursor);
+
+ /**
+ * Formats the specified object into an <code>Appendable</code>
+ *
+ * @param obj the object to format.
+ * @param dest the appendable destination.
+ * @return the specified <code>Appendable</code>.
+ */
+ public abstract Appendable format(T obj, Appendable dest)
+ throws IOException;
+
+ /**
+ * Convenience method to parse the whole character sequence; if there are
+ * unread extraneous characters after parsing then an exception is raised.
+ *
+ * @param csq the <code>CharSequence</code> to parse from the first character
+ * to the last.
+ * @throws IllegalArgumentException if the syntax of the specified
+ * character sequence is incorrect or if there are extraneous
+ * characters at the end not parsed.
+ */
+ public T parse(CharSequence csq) throws IllegalArgumentException {
+ Cursor cursor = new Cursor();
+ T obj = parse(csq, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous character(s) \""
+ + cursor.tail(csq) + "\"");
+ return obj;
+ }
+
+ /**
+ * Convenience method to format the specified object to a {@link TextBuilder};
+ * unlike the abstract format method, this method does not throw {@link IOException}.
+ *
+ * @param obj the object to format.
+ * @param dest the appendable destination.
+ * @return the specified <code>TextBuilder</code>.
+ */
+ public TextBuilder format(T obj, TextBuilder dest) {
+ try {
+ this.format(obj, (Appendable) dest);
+ return dest;
+ } catch (IOException e) {
+ throw new Error(e); // Cannot happens.
+ }
+ }
+
+ /**
+ * Convenience method to format the specified object to a {@link String}.
+ *
+ * @param obj the object to format.
+ * @return the formatting result as a string.
+ */
+ public String format(T obj) {
+ return this.format(obj, new TextBuilder()).toString();
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/text/TypeFormat.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/TypeFormat.java b/commons/marmotta-commons/src/ext/java/javolution/text/TypeFormat.java
new file mode 100644
index 0000000..70207ff
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/TypeFormat.java
@@ -0,0 +1,732 @@
+/*
+ * 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.IOException;
+import javolution.lang.MathLib;
+import javolution.lang.Realtime;
+
+/**
+ * <p> Utility class to parse {@link CharSequence} into primitive types and
+ * to format primitive types into any {@link Appendable}.</p>
+ *
+ * <p> Methods from this class <b>do not create temporary objects</b> and
+ * are typically faster than standard library methods.</p>
+ *
+ * <p> The number of digits when formatting floating point numbers can be
+ * specified. The default setting for <code>double</code> is 17 digits
+ * or even 16 digits when the conversion is lossless back and forth
+ * (mimic the standard library formatting).</p>
+ * <p>[code]
+ * TypeFormat.format(0.2, a) = "0.2" // 17 or 16 digits (as long as lossless conversion), remove trailing zeros.
+ * TypeFormat.format(0.2, 17, false, false, a) = "0.20000000000000001" // Closest 17 digits number.
+ * TypeFormat.format(0.2, 19, false, false, a) = "0.2000000000000000111" // Closest 19 digits.
+ * TypeFormat.format(0.2, 4, false, false, a) = "0.2" // Fixed-point notation, remove trailing zeros.
+ * TypeFormat.format(0.2, 4, false, true, a) = "0.2000" // Fixed-point notation, fixed number of digits.
+ * TypeFormat.format(0.2, 4, true, false, a) = "2.0E-1" // Scientific notation, remove trailing zeros.
+ * TypeFormat.format(0.2, 4, true, true, a) = "2.000E-1" // Scientific notation, fixed number of digits.
+ * [/code]</p>
+ *
+ * <p> For non-primitive objects, formatting is typically performed using
+ * specialized {@link TextFormat} instances.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.3, February 15, 2009
+ */
+@Realtime
+public final class TypeFormat {
+
+ /**
+ * Default constructor (forbids derivation).
+ */
+ private TypeFormat() {}
+
+ /////////////
+ // PARSING //
+ /////////////
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a <code>boolean</code> ignoring cases.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position (being maintained).
+ * @return the next boolean value.
+ * @throws IllegalArgumentException if the character sequence from the
+ * specified position is different from "true" or "false" ignoring
+ * cases.
+ */
+ public static boolean parseBoolean(CharSequence csq, Cursor cursor) {
+ int start = cursor.getIndex();
+ int end = csq.length();
+ if ((end >= start + 5)
+ && (csq.charAt(start) == 'f' || csq.charAt(start) == 'F')) { // False.
+ if ((csq.charAt(++start) == 'a' || csq.charAt(start) == 'A')
+ && (csq.charAt(++start) == 'l' || csq.charAt(start) == 'L')
+ && (csq.charAt(++start) == 's' || csq.charAt(start) == 'S')
+ && (csq.charAt(++start) == 'e' || csq.charAt(start) == 'E')) {
+ cursor.increment(5);
+ return false;
+ }
+ } else if ((end >= start + 4)
+ && (csq.charAt(start) == 't' || csq.charAt(start) == 'T')) // True.
+ if ((csq.charAt(++start) == 'r' || csq.charAt(start) == 'R')
+ && (csq.charAt(++start) == 'u' || csq.charAt(start) == 'U')
+ && (csq.charAt(++start) == 'e' || csq.charAt(start) == 'E')) {
+ cursor.increment(4);
+ return true;
+ }
+ throw new IllegalArgumentException("Invalid boolean representation");
+ }
+
+ /**
+ * Parses the whole specified character sequence as a <code>boolean</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return <code>parseBoolean(csq, new Cursor())</code>
+ * @throws IllegalArgumentException if the specified character sequence
+ * is different from "true" or "false" ignoring cases.
+ */
+ public static boolean parseBoolean(CharSequence csq) {
+ Cursor cursor = new Cursor();
+ boolean result = parseBoolean(csq, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous characters \""
+ + cursor.tail(csq) + "\"");
+ return result;
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed <code>byte</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>byte</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>byte</code>.
+ */
+ public static byte parseByte(CharSequence csq, int radix, Cursor cursor) {
+ int i = parseInt(csq, radix, cursor);
+ if ((i < Byte.MIN_VALUE) || (i > Byte.MAX_VALUE))
+ throw new NumberFormatException("Overflow");
+ return (byte) i;
+ }
+
+ /**
+ * Parses the whole specified character sequence
+ * as a signed <code>byte</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @return the corresponding <code>byte</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>byte</code> or contains
+ * extraneous characters.
+ */
+ public static byte parseByte(CharSequence csq, int radix) {
+ Cursor cursor = new Cursor();
+ byte result = parseByte(csq, radix, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous characters \""
+ + cursor.tail(csq) + "\"");
+ return result;
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed decimal <code>byte</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>byte</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>byte</code>.
+ */
+ public static byte parseByte(CharSequence csq, Cursor cursor) {
+ return parseByte(csq, 10, cursor);
+ }
+
+ /**
+ * Parses the whole specified character sequence as a signed decimal
+ * <code>byte</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return <code>parseByte(csq, 10)</code>
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>byte</code> or contains
+ * extraneous characters.
+ */
+ public static byte parseByte(CharSequence csq) {
+ return parseByte(csq, 10);
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed <code>short</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>short</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>short</code>.
+ */
+ public static short parseShort(CharSequence csq, int radix, Cursor cursor) {
+ int i = parseInt(csq, radix, cursor);
+ if ((i < Short.MIN_VALUE) || (i > Short.MAX_VALUE))
+ throw new NumberFormatException("Overflow");
+ return (short) i;
+ }
+
+ /**
+ * Parses the whole specified character sequence
+ * as a signed <code>short</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @return the corresponding <code>short</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>short</code> or contains
+ * extraneous characters.
+ */
+ public static short parseShort(CharSequence csq, int radix) {
+ Cursor cursor = new Cursor();
+ short result = parseShort(csq, radix, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous characters \""
+ + cursor.tail(csq) + "\"");
+ return result;
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed decimal <code>short</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>short</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>short</code>.
+ */
+ public static short parseShort(CharSequence csq, Cursor cursor) {
+ return parseShort(csq, 10, cursor);
+ }
+
+ /**
+ * Parses the whole specified character sequence as a signed decimal
+ * <code>short</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return <code>parseShort(csq, 10)</code>
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>short</code> or contains
+ * extraneous characters.
+ */
+ public static short parseShort(CharSequence csq) {
+ return parseShort(csq, 10);
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed <code>int</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>int</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>int</code>.
+ */
+ public static int parseInt(CharSequence csq, int radix, Cursor cursor) {
+ int start = cursor.getIndex();
+ int end = csq.length();
+ boolean isNegative = false;
+ int result = 0; // Accumulates negatively (avoid MIN_VALUE overflow).
+ int i = start;
+ for (; i < end; i++) {
+ char c = csq.charAt(i);
+ int digit = (c <= '9') ? c - '0'
+ : ((c <= 'Z') && (c >= 'A')) ? c - 'A' + 10
+ : ((c <= 'z') && (c >= 'a')) ? c - 'a' + 10 : -1;
+ if ((digit >= 0) && (digit < radix)) {
+ int newResult = result * radix - digit;
+ if (newResult > result)
+ throw new NumberFormatException("Overflow parsing "
+ + csq.subSequence(start, end));
+ result = newResult;
+ } else if ((c == '-') && (i == start))
+ isNegative = true;
+ else if ((c == '+') && (i == start)) {
+ // Ok.
+ } else
+ break;
+ }
+ // Requires one valid digit character and checks for opposite overflow.
+ if ((result == 0) && ((end == 0) || (csq.charAt(i - 1) != '0')))
+ throw new NumberFormatException(
+ "Invalid integer representation for "
+ + csq.subSequence(start, end));
+ if ((result == Integer.MIN_VALUE) && !isNegative)
+ throw new NumberFormatException("Overflow parsing "
+ + csq.subSequence(start, end));
+ cursor.increment(i - start);
+ return isNegative ? result : -result;
+ }
+
+ /**
+ * Parses the whole specified character sequence
+ * as a signed <code>int</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @return the corresponding <code>int</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>int</code> or contains
+ * extraneous characters.
+ */
+ public static int parseInt(CharSequence csq, int radix) {
+ Cursor cursor = new Cursor();
+ int result = parseInt(csq, radix, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous characters \""
+ + cursor.tail(csq) + "\"");
+ return result;
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed decimal <code>int</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>int</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>int</code>.
+ */
+ public static int parseInt(CharSequence csq, Cursor cursor) {
+ return parseInt(csq, 10, cursor);
+ }
+
+ /**
+ * Parses the whole specified character sequence as a signed decimal
+ * <code>int</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return <code>parseInt(csq, 10)</code>
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>int</code> or contains
+ * extraneous characters.
+ */
+ public static int parseInt(CharSequence csq) {
+ return parseInt(csq, 10);
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed <code>long</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>long</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>long</code>.
+ */
+ public static long parseLong(CharSequence csq, int radix, Cursor cursor) {
+ final int start = cursor.getIndex();
+ final int end = csq.length();
+ boolean isNegative = false;
+ long result = 0; // Accumulates negatively (avoid MIN_VALUE overflow).
+ int i = start;
+ for (; i < end; i++) {
+ char c = csq.charAt(i);
+ int digit = (c <= '9') ? c - '0'
+ : ((c <= 'Z') && (c >= 'A')) ? c - 'A' + 10
+ : ((c <= 'z') && (c >= 'a')) ? c - 'a' + 10 : -1;
+ if ((digit >= 0) && (digit < radix)) {
+ long newResult = result * radix - digit;
+ if (newResult > result)
+ throw new NumberFormatException("Overflow parsing "
+ + csq.subSequence(start, end));
+ result = newResult;
+ } else if ((c == '-') && (i == start))
+ isNegative = true;
+ else if ((c == '+') && (i == start)) {
+ // Ok.
+ } else
+ break;
+ }
+ // Requires one valid digit character and checks for opposite overflow.
+ if ((result == 0) && ((end == 0) || (csq.charAt(i - 1) != '0')))
+ throw new NumberFormatException(
+ "Invalid integer representation for "
+ + csq.subSequence(start, end));
+ if ((result == Long.MIN_VALUE) && !isNegative)
+ throw new NumberFormatException("Overflow parsing "
+ + csq.subSequence(start, end));
+ cursor.increment(i - start);
+ return isNegative ? result : -result;
+ }
+
+ /**
+ * Parses the whole specified character sequence
+ * as a signed <code>long</code> in the specified radix.
+ *
+ * @param csq the character sequence to parse.
+ * @param radix the radix to be used while parsing.
+ * @return the corresponding <code>long</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>long</code> or contains
+ * extraneous characters.
+ */
+ public static long parseLong(CharSequence csq, int radix) {
+ Cursor cursor = new Cursor();
+ long result = parseLong(csq, radix, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous characters \""
+ + cursor.tail(csq) + "\"");
+ return result;
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a signed decimal <code>long</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position being updated.
+ * @return the corresponding <code>long</code>.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>long</code>.
+ */
+ public static long parseLong(CharSequence csq, Cursor cursor) {
+ return parseLong(csq, 10, cursor);
+ }
+
+ /**
+ * Parses the whole specified character sequence as a signed decimal
+ * <code>long</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return <code>parseLong(csq, 10)</code>
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>long</code> or contains
+ * extraneous characters.
+ */
+ public static long parseLong(CharSequence csq) {
+ return parseLong(csq, 10);
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a <code>float</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position (being maintained) or
+ * <code>null></code> to parse the whole character sequence.
+ * @return the float number represented by the specified character sequence.
+ */
+ public static float parseFloat(CharSequence csq, Cursor cursor) {
+ return (float) parseDouble(csq, cursor);
+ }
+
+ /**
+ * Parses the whole specified character sequence as a <code>float</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return the float number represented by the specified character sequence.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>long</code> or contains
+ * extraneous characters.
+ */
+ public static float parseFloat(CharSequence csq) {
+ return (float) parseDouble(csq);
+ }
+
+ /**
+ * Parses the specified character sequence from the specified position
+ * as a <code>double</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @param cursor the cursor position (being maintained) or
+ * <code>null></code> to parse the whole character sequence.
+ * @return the double number represented by this character sequence.
+ * @throws NumberFormatException if the character sequence does not contain
+ * a parsable <code>double</code>.
+ */
+ public static double parseDouble(CharSequence csq, Cursor cursor)
+ throws NumberFormatException {
+ final int start = cursor.getIndex();
+ final int end = csq.length();
+ int i = start;
+ char c = csq.charAt(i);
+
+ // Checks for NaN.
+ if ((c == 'N') && match("NaN", csq, i, end)) {
+ cursor.increment(3);
+ return Double.NaN;
+ }
+
+ // Reads sign.
+ boolean isNegative = (c == '-');
+ if ((isNegative || (c == '+')) && (++i < end))
+ c = csq.charAt(i);
+
+ // Checks for Infinity.
+ if ((c == 'I') && match("Infinity", csq, i, end)) {
+ cursor.increment(i + 8 - start);
+ return isNegative ? Double.NEGATIVE_INFINITY
+ : Double.POSITIVE_INFINITY;
+ }
+
+ // At least one digit or a '.' required.
+ if (((c < '0') || (c > '9')) && (c != '.'))
+ throw new NumberFormatException("Digit or '.' required");
+
+ // Reads decimal and fraction (both merged to a long).
+ long decimal = 0;
+ int decimalPoint = -1;
+ while (true) {
+ int digit = c - '0';
+ if ((digit >= 0) && (digit < 10)) {
+ long tmp = decimal * 10 + digit;
+ if ((decimal > LONG_MAX_DIV10) || (tmp < decimal))
+ throw new NumberFormatException(
+ "Too many digits - Overflow");
+ decimal = tmp;
+ } else if ((c == '.') && (decimalPoint < 0))
+ decimalPoint = i;
+ else
+ break;
+ if (++i >= end)
+ break;
+ c = csq.charAt(i);
+ }
+ if (isNegative)
+ decimal = -decimal;
+ int fractionLength = (decimalPoint >= 0) ? i - decimalPoint - 1 : 0;
+
+ // Reads exponent.
+ int exp = 0;
+ if ((i < end) && ((c == 'E') || (c == 'e'))) {
+ c = csq.charAt(++i);
+ boolean isNegativeExp = (c == '-');
+ if ((isNegativeExp || (c == '+')) && (++i < end))
+ c = csq.charAt(i);
+ if ((c < '0') || (c > '9')) // At least one digit required.
+ throw new NumberFormatException("Invalid exponent");
+ while (true) {
+ int digit = c - '0';
+ if ((digit >= 0) && (digit < 10)) {
+ int tmp = exp * 10 + digit;
+ if ((exp > INT_MAX_DIV10) || (tmp < exp))
+ throw new NumberFormatException("Exponent Overflow");
+ exp = tmp;
+ } else
+ break;
+ if (++i >= end)
+ break;
+ c = csq.charAt(i);
+ }
+ if (isNegativeExp)
+ exp = -exp;
+ }
+ cursor.increment(i - start);
+ return javolution.lang.MathLib.toDoublePow10(decimal, exp
+ - fractionLength);
+ }
+ private static final int INT_MAX_DIV10 = Integer.MAX_VALUE / 10;
+ private static final long LONG_MAX_DIV10 = Long.MAX_VALUE / 10;
+
+ /**
+ * Parses the whole specified character sequence as a <code>double</code>.
+ * The format must be of the form:<code>
+ * <decimal>{'.'<fraction>}{'E|e'<exponent>}</code>.
+ *
+ * @param csq the character sequence to parse.
+ * @return the double number represented by this character sequence.
+ * @throws NumberFormatException if the specified character sequence
+ * does not contain a parsable <code>long</code> or contains
+ * extraneous characters.
+ */
+ public static double parseDouble(CharSequence csq)
+ throws NumberFormatException {
+ Cursor cursor = new Cursor();
+ double result = parseDouble(csq, cursor);
+ if (!cursor.atEnd(csq))
+ throw new IllegalArgumentException("Extraneous characters \""
+ + cursor.tail(csq) + "\"");
+ return result;
+ }
+
+ static boolean match(String str, CharSequence csq, int start, int length) {
+ for (int i = 0; i < str.length(); i++) {
+ if ((start + i >= length) || csq.charAt(start + i) != str.charAt(i))
+ return false;
+ }
+ return true;
+ }
+
+ static boolean match(String str, String csq, int start, int length) {
+ for (int i = 0; i < str.length(); i++) {
+ if ((start + i >= length) || csq.charAt(start + i) != str.charAt(i))
+ return false;
+ }
+ return true;
+ }
+
+ ////////////////
+ // FORMATTING //
+ ////////////////
+ /**
+ * Formats the specified <code>boolean</code> and appends the resulting
+ * text to the <code>Appendable</code> argument.
+ *
+ * @param b a <code>boolean</code>.
+ * @param a the <code>Appendable</code> to append.
+ * @return the specified <code>StringBuffer</code> object.
+ * @throws IOException if an I/O exception occurs.
+ */
+ public static Appendable format(boolean b, Appendable a) throws IOException {
+ return b ? a.append("true") : a.append("false");
+ }
+
+ /**
+ * Formats the specified <code>int</code> and appends the resulting
+ * text (decimal representation) to the <code>Appendable</code> argument.
+ *
+ *
+ * @param i the <code>int</code> number.
+ * @param a the <code>Appendable</code> to append.
+ * @return the specified <code>Appendable</code> object.
+ * @throws IOException if an I/O exception occurs.
+ */
+ public static Appendable format(int i, Appendable a) throws IOException {
+ if (a instanceof TextBuilder)
+ return ((TextBuilder) a).append(i);
+ TextBuilder tb = new TextBuilder();
+ tb.append(i);
+ return a.append(tb);
+ }
+
+ /**
+ * Formats the specified <code>int</code> in the specified radix and appends
+ * the resulting text to the <code>Appendable</code> argument.
+ *
+ * @param i the <code>int</code> number.
+ * @param radix the radix.
+ * @param a the <code>Appendable</code> to append.
+ * @return the specified <code>Appendable</code> object.
+ * @throws IllegalArgumentException if radix is not in [2 .. 36] range.
+ * @throws IOException if an I/O exception occurs.
+ */
+ public static Appendable format(int i, int radix, Appendable a)
+ throws IOException {
+ if (a instanceof TextBuilder)
+ return ((TextBuilder) a).append(i, radix);
+ TextBuilder tb = new TextBuilder();
+ tb.append(i, radix);
+ return a.append(tb);
+ }
+
+ /**
+ * Formats the specified <code>long</code> and appends the resulting
+ * text (decimal representation) to the <code>Appendable</code> argument.
+ *
+ * @param l the <code>long</code> number.
+ * @param a the <code>Appendable</code> to append.
+ * @return the specified <code>Appendable</code> object.
+ * @throws IOException if an I/O exception occurs.
+ * @see #parseLong
+ */
+ public static Appendable format(long l, Appendable a) throws IOException {
+ if (a instanceof TextBuilder)
+ return ((TextBuilder) a).append(l);
+ TextBuilder tb = new TextBuilder();
+ tb.append(l);
+ return a.append(tb);
+ }
+
+ /**
+ * Formats the specified <code>long</code> in the specified radix and
+ * appends the resulting text to the <code>Appendable</code> argument.
+ *
+ * @param l the <code>long</code> number.
+ * @param radix the radix.
+ * @param a the <code>Appendable</code> to append.
+ * @return the specified <code>Appendable</code> object.
+ * @throws IllegalArgumentException if radix is not in [2 .. 36] range.
+ * @throws IOException if an I/O exception occurs.
+ * @see #parseLong(CharSequence, int)
+ */
+ public static Appendable format(long l, int radix, Appendable a)
+ throws IOException {
+ if (a instanceof TextBuilder)
+ return ((TextBuilder) a).append(l, radix);
+ TextBuilder tb = new TextBuilder();
+ tb.append(l, radix);
+ return a.append(tb);
+ }
+
+ /**
+ * Formats the specified <code>float</code> value.
+ *
+ * @param f the <code>float</code> value.
+ * @param a the <code>Appendable</code> to append.
+ * @return <code>TypeFormat.format(f, 10, (MathLib.abs(f) >= 1E7) || (MathLib.abs(f) < 0.001), false, a)</code>
+ * @throws IOException if an I/O exception occurs.
+ */
+ public static Appendable format(float f, Appendable a) throws IOException {
+ return TypeFormat.format(f, 10,
+ (MathLib.abs(f) >= 1E7) || (MathLib.abs(f) < 0.001), false, a);
+ }
+
+ /**
+ * Formats the specified <code>double</code> value (16 or 17 digits output).
+ *
+ * @param d the <code>double</code> value.
+ * @param a the <code>Appendable</code> to append.
+ * @return <code>TypeFormat.format(d, -1, (MathLib.abs(d) >= 1E7) || (MathLib.abs(d) < 0.001), false, a)</code>
+ * @throws IOException if an I/O exception occurs.
+ * @see TextBuilder#append(double)
+ */
+ public static Appendable format(double d, Appendable a) throws IOException {
+ return TypeFormat.format(d, -1,
+ (MathLib.abs(d) >= 1E7) || (MathLib.abs(d) < 0.001), false, a);
+ }
+
+ /**
+ * Formats the specified <code>double</code> value 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.
+ * @param a the <code>Appendable</code> to append.
+ * @return the specified <code>Appendable</code> object.
+ * @throws IllegalArgumentException if <code>(digits > 19)</code>)
+ * @throws IOException if an I/O exception occurs.
+ * @see TextBuilder#append(double, int, boolean, boolean)
+ */
+ public static Appendable format(double d, int digits, boolean scientific,
+ boolean showZero, Appendable a) throws IOException {
+ if (a instanceof TextBuilder)
+ return ((TextBuilder) a).append(d, digits, scientific, showZero);
+ TextBuilder tb = new TextBuilder();
+ tb.append(d, digits, scientific, showZero);
+ return a.append(tb);
+ }
+
+}
\ 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/internal/TextContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/internal/TextContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/text/internal/TextContextImpl.java
new file mode 100644
index 0000000..9e92f81
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/internal/TextContextImpl.java
@@ -0,0 +1,345 @@
+/*
+ * 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.internal;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import javolution.context.LogContext;
+import javolution.text.CharSet;
+import javolution.text.Cursor;
+import javolution.text.DefaultTextFormat;
+import javolution.text.TextContext;
+import javolution.text.TextFormat;
+import javolution.text.TypeFormat;
+import javolution.util.FastMap;
+
+/**
+ * Holds the default implementation of TextContext.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public final class TextContextImpl extends TextContext {
+
+ private static final TextFormat<?> OBJECT_FORMAT = new TextFormat<Object>() {
+ ThreadLocal<Object> objToString = new ThreadLocal<Object>();
+
+ public Appendable format(Object obj, Appendable dest)
+ throws IOException {
+ if (obj == null) return dest.append("null");
+ if (objToString.get() == obj) // Circularity in toString !
+ return TypeFormat.format(System.identityHashCode(obj),
+ dest.append("Object#"));
+ objToString.set(obj);
+ try {
+ String str = obj.toString();
+ return dest.append(str);
+ } finally {
+ objToString.set(null);
+ }
+ }
+
+ public Object parse(CharSequence csq, Cursor cursor) {
+ throw new UnsupportedOperationException(
+ "Generic object parsing not supported.");
+ }
+
+ };
+ // Holds class->format local mapping.
+ private final FastMap<Class<?>, TextFormat<?>> localFormats;
+
+ // Caches class->format from class annotations.
+ private final FastMap<Class<?>, TextFormat<?>> defaultFormats;
+
+ /** Default constructor for root */
+ public TextContextImpl() {
+ localFormats = new FastMap<Class<?>, TextFormat<?>>(); // Updated only during configuration.
+ defaultFormats = new FastMap<Class<?>, TextFormat<?>>().shared(); // Can be updated concurrently.
+ storePrimitiveTypesFormats();
+ }
+
+ /** Inner constructor */
+ public TextContextImpl(TextContextImpl parent) {
+ localFormats = new FastMap<Class<?>, TextFormat<?>>()
+ .putAll(parent.localFormats);
+ defaultFormats = parent.defaultFormats;
+ }
+
+ @Override
+ protected TextContext inner() {
+ return new TextContextImpl(this);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> TextFormat<T> searchFormat(Class<? extends T> type) {
+ Class<?> cls = type;
+ while (cls != null) {
+ TextFormat<?> format;
+ // Search local format first.
+ if (localFormats.size() > 0) {
+ format = localFormats.get(cls);
+ if (format != null) return (TextFormat<T>) format;
+ }
+ // Then search default format.
+ format = defaultFormats.get(cls);
+ if (format != null) return (TextFormat<T>) format;
+
+ // Search annotations.
+ DefaultTextFormat annotation = cls
+ .getAnnotation(DefaultTextFormat.class);
+ if (annotation != null) { // Found it.
+ try {
+ format = annotation.value().newInstance();
+ } catch (Throwable error) {
+ LogContext.warning(error);
+ }
+ // Updates the default mapping.
+ Class<?> mappedClass = type;
+ while (true) {
+ defaultFormats.put(mappedClass, format);
+ if (mappedClass.equals(cls)) break;
+ mappedClass = mappedClass.getSuperclass();
+ }
+ return (TextFormat<T>) format;
+ }
+
+ // Search superclass.
+ cls = cls.getSuperclass();
+ }
+ throw new Error("Object default format not found !");
+ }
+
+ @Override
+ public <T> void setFormat(Class<? extends T> type, TextFormat<T> format) {
+ localFormats.put(type, format);
+ }
+
+ ////////////////////////
+ // PREDEFINED FORMATS //
+ ////////////////////////
+
+ private void storePrimitiveTypesFormats() {
+ defaultFormats.put(Object.class, OBJECT_FORMAT);
+ defaultFormats.put(Boolean.class, new TextFormat<Boolean>() {
+
+ public Appendable format(Boolean obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.booleanValue(), dest);
+ }
+
+ public Boolean parse(CharSequence csq, Cursor cursor) {
+ return TypeFormat.parseBoolean(csq, cursor);
+ }
+
+ });
+ defaultFormats.put(Character.class, new TextFormat<Character>() {
+
+ public Appendable format(Character obj, Appendable dest)
+ throws IOException {
+ return dest.append(obj.charValue());
+ }
+
+ public Character parse(CharSequence csq, Cursor cursor) {
+ return Character.valueOf(cursor.nextChar(csq));
+ }
+
+ });
+ defaultFormats.put(Byte.class, new TextFormat<Byte>() {
+
+ public Appendable format(Byte obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.byteValue(), dest);
+ }
+
+ public Byte parse(CharSequence csq, Cursor cursor) {
+ return Byte.valueOf(TypeFormat.parseByte(csq, 10, cursor));
+ }
+
+ });
+ defaultFormats.put(Short.class, new TextFormat<Short>() {
+
+ public Appendable format(Short obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.shortValue(), dest);
+ }
+
+ public Short parse(CharSequence csq, Cursor cursor) {
+ return Short.valueOf(TypeFormat.parseShort(csq, 10, cursor));
+ }
+
+ });
+ defaultFormats.put(Integer.class, new TextFormat<Integer>() {
+
+ public Appendable format(Integer obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.intValue(), dest);
+ }
+
+ public Integer parse(CharSequence csq, Cursor cursor) {
+ return Integer.valueOf(TypeFormat.parseInt(csq, 10, cursor));
+ }
+
+ });
+ defaultFormats.put(Long.class, new TextFormat<Long>() {
+
+ public Appendable format(Long obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.longValue(), dest);
+ }
+
+ public Long parse(CharSequence csq, Cursor cursor) {
+ return Long.valueOf(TypeFormat.parseLong(csq, 10, cursor));
+ }
+
+ });
+ defaultFormats.put(Float.class, new TextFormat<Float>() {
+
+ public Appendable format(Float obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.floatValue(), dest);
+ }
+
+ public Float parse(CharSequence csq, Cursor cursor) {
+ return new Float(TypeFormat.parseFloat(csq, cursor));
+ }
+
+ });
+ defaultFormats.put(Double.class, new TextFormat<Double>() {
+
+ public Appendable format(Double obj, Appendable dest)
+ throws IOException {
+ return TypeFormat.format(obj.doubleValue(), dest);
+ }
+
+ public Double parse(CharSequence csq, Cursor cursor) {
+ return new Double(TypeFormat.parseDouble(csq, cursor));
+ }
+
+ });
+ defaultFormats.put(String.class, new TextFormat<String>() {
+
+ public Appendable format(String obj, Appendable dest)
+ throws IOException {
+ return dest.append(obj);
+ }
+
+ public String parse(CharSequence csq, Cursor cursor) {
+ CharSequence tmp = csq.subSequence(cursor.getIndex(),
+ csq.length());
+ cursor.setIndex(csq.length());
+ return tmp.toString();
+ }
+
+ });
+ defaultFormats.put(Class.class, new TextFormat<Class<?>>() {
+
+ public Appendable format(Class<?> obj, Appendable dest)
+ throws IOException {
+ return dest.append(obj.getName());
+ }
+
+ public Class<?> parse(CharSequence csq, Cursor cursor) {
+ CharSequence name = cursor.nextToken(csq, CharSet.WHITESPACES);
+ try {
+ return Class.forName(name.toString());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Class " + name
+ + " Not Found");
+ }
+ }
+
+ });
+ defaultFormats.put(Date.class, new TextFormat<Date>() {
+ TimeZone tz = TimeZone.getTimeZone("UTC");
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+ {
+ df.setTimeZone(tz);
+ }
+
+ public Appendable format(Date obj, Appendable dest)
+ throws IOException {
+ return dest.append(df.format(obj));
+ }
+
+ public Date parse(CharSequence csq, Cursor cursor) {
+ CharSequence date = cursor.nextToken(csq, CharSet.WHITESPACES);
+ try {
+ return df.parse(date.toString());
+ } catch (ParseException error) {
+ throw new IllegalArgumentException(error);
+ }
+ }
+ });
+ defaultFormats.put(BigInteger.class, new TextFormat<BigInteger>() {
+
+ public Appendable format(BigInteger obj, Appendable dest)
+ throws IOException {
+ return dest.append(obj.toString());
+ }
+
+ public BigInteger parse(CharSequence csq, Cursor cursor) {
+ CharSequence value = cursor.nextToken(csq, CharSet.WHITESPACES);
+ return new BigInteger(value.toString());
+ }
+
+ });
+ defaultFormats.put(BigDecimal.class, new TextFormat<BigDecimal>() {
+
+ public Appendable format(BigDecimal obj, Appendable dest)
+ throws IOException {
+ return dest.append(obj.toString());
+ }
+
+ public BigDecimal parse(CharSequence csq, Cursor cursor) {
+ CharSequence value = cursor.nextToken(csq, CharSet.WHITESPACES);
+ return new BigDecimal(value.toString());
+ }
+
+ });
+ defaultFormats.put(Font.class, new TextFormat<Font>() {
+
+ public Appendable format(Font obj, Appendable dest)
+ throws IOException {
+ return dest.append(obj.getName());
+ }
+
+ public Font parse(CharSequence csq, Cursor cursor) {
+ CharSequence name = cursor.nextToken(csq, CharSet.WHITESPACES);
+ return Font.decode(name.toString());
+ }
+
+ });
+ defaultFormats.put(Color.class, new TextFormat<Color>() {
+
+ public Appendable format(Color obj, Appendable dest)
+ throws IOException {
+ return dest.append('#').append(
+ Integer.toHexString(obj.getRGB()));
+ }
+
+ public Color parse(CharSequence csq, Cursor cursor) {
+ CharSequence name = cursor.nextToken(csq, CharSet.WHITESPACES);
+ return Color.decode(name.toString());
+ }
+
+ });
+
+ }
+
+}
\ 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/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/text/package-info.java
new file mode 100644
index 0000000..3c82f97
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/package-info.java
@@ -0,0 +1,67 @@
+/**
+<p> Text handling package.</p>
+<h2><a name="FAQ">FAQ:</a></h2>
+<ol>
+ <a name="FAQ-1"></a>
+ <li><b> Is parsing/formatting of floating-points numbers (e.g. <code>double</code>)
+ equivalent to standard String/Double methods?</b>
+ <p> With Javolution 4.1, <code>double</code> formatting/parsing is lossless
+ and functionally the same as with the standard library. Parsing a character
+ sequence will always result in the same number whether it is performed with
+ {@link javolution.text.TypeFormat TypeFormat} or using <code>Double.parseDouble(String))</code>.
+ When formatting a <code>double</code> number, the number of digits output
+ is adjustable. The default (if the number of digits is unspecified) is <code>17</code>
+ or <code>16</code> when the the 16 digits representation can be parsed back to
+ the same <code>double</code> (mimic the standard library formatting).</p>
+ <p> Javolution parsing/formatting do not generate garbage and has no adverse
+ effect on GC. Better, it does not force the user to create intermediate <code>String</code>
+ objects, any <code>CharSequence/Appendable</code> can be used! Serial parsing is also supported
+ (cursor parameter).</p>
+ <p></p>
+ <a name="FAQ-2"></a>
+ <li><b> I'm accumulating a large string, and all I want to do is
+append to the end of the current string, which is the better class to use,
+Text or TextBuilder? Bearing in mind that speed is important, but I also want
+to conserve memory.</b>
+ <p> It all depends of the size of the text to append (the actual size of the
+ document being appended has almost no impact in both cases).</p>
+ <p> If the text being appended is large (or arbitrarily large) then using
+ {@link javolution.text.Text Text} is preferable.
+[code]
+class FastCollection<T> {
+ public final Text toText() {
+ // We don't know the length of the text representation for
+ // the collection's elements, we use Text concatenation
+ // to avoid copying what could be quite large.
+ Text text = Text.valueOf("{");
+ boolean isFirst = true;
+ for (T e : this) {
+ if (!isFirst) { text = text.plus(", "); isFirst = false; }
+ text = text.plus(e);
+ }
+ return text.plus("}");
+ }
+}[/code]</p>
+ <p></p>
+ <a name="FAQ-3"></a>
+ <li><b> In our project's use of strings, there are a lot of
+ instances of directory path names, such as
+<code>"/proj/lodecase/src/com/lodecase/util/foo.java"</code>, and
+<code>"/proj/lodecase/src/com/lodecase/util/bar.java"</code>.
+Can the 'Text' class save us memory when strings
+have common prefixes?</b>
+ <p> It depends how you build your text. For example in following code:
+[code]
+Text directoryName = Text.valueOf("/proj/lodecase/src/com/lodecase/util/");
+Text fooFileName = directoryName.plus("foo.java");
+Text barFileName = directoryName.plus("bar.java");[/code]
+ The prefix (directoryName)is shared between <code>fooFileName</code> and <code>barFileName</code>.</p>
+ <p> Text is a binary tree of blocks of characters. In the example,
+ above, <code>fooFileName</code> is a node with <code>directoryName</code> for
+ head and "foo.java" for tail. The tree is maintained balanced automatically
+ through <a href="http://en.wikipedia.org/wiki/Tree_rotation">tree rotations</a>.</p>
+ <p></p>
+</ol>
+ */
+package javolution.text;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/FastBitSet.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastBitSet.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastBitSet.java
new file mode 100644
index 0000000..f7c6234
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastBitSet.java
@@ -0,0 +1,361 @@
+/*
+ * 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.util;
+
+import static javolution.lang.Realtime.Limit.LINEAR;
+import javolution.lang.Realtime;
+import javolution.util.internal.bitset.BitSetServiceImpl;
+import javolution.util.service.BitSetService;
+
+/**
+ * <p> A high-performance bitset with {@link Realtime real-time} behavior.</p>
+ *
+ * <p> This class is integrated with the collection framework as
+ * a set of {@link Index indices} and obeys the collection semantic
+ * for methods such as {@link #size} (cardinality) or {@link #equals}
+ * (same set of indices).</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class FastBitSet extends FastSet<Index> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Holds the bit set implementation.
+ */
+ private final BitSetService service;
+
+ /**
+ * Creates an empty bit set.
+ */
+ public FastBitSet() {
+ service = new BitSetServiceImpl();
+ }
+
+ /**
+ * Creates a fast bit set based on the specified implementation.
+ */
+ protected FastBitSet(BitSetService impl) {
+ this.service = impl;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ @Override
+ public FastBitSet unmodifiable() {
+ throw new UnsupportedOperationException("NOT DONE YET"); // TODO
+ }
+
+ @Override
+ public FastBitSet shared() {
+ throw new UnsupportedOperationException("NOT DONE YET"); // TODO
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // BitSet Operations.
+ //
+
+ /**
+ * Performs the logical AND operation on this bit set and the
+ * given bit set. This means it builds the intersection
+ * of the two sets. The result is stored into this bit set.
+ *
+ * @param that the second bit set.
+ */
+ @Realtime(limit = LINEAR)
+ public void and(FastBitSet that) {
+ service.and(that.service);
+ }
+
+ /**
+ * Performs the logical AND operation on this bit set and the
+ * complement of the given bit set. This means it
+ * selects every element in the first set, that isn't in the
+ * second set. The result is stored into this bit set.
+ *
+ * @param that the second bit set
+ */
+ @Realtime(limit = LINEAR)
+ public void andNot(FastBitSet that) {
+ service.andNot(that.service);
+ }
+
+ /**
+ * Returns the number of bits set to {@code true} (or the size of this
+ * set).
+ *
+ * @return the number of bits being set.
+ */
+ public int cardinality() {
+ return service.cardinality();
+ }
+
+ /**
+ * Sets all bits in the set to {@code false} (empty the set).
+ */
+ @Override
+ public void clear() {
+ service.clear();
+ }
+
+ /**
+ * Removes the specified integer value from this set. That is
+ * the corresponding bit is cleared.
+ *
+ * @param bitIndex a non-negative integer.
+ * @throws IndexOutOfBoundsException if {@code index < 0}
+ */
+ public void clear(int bitIndex) {
+ service.clear(bitIndex);
+ }
+
+ /**
+ * Sets the bits from the specified {@code fromIndex} (inclusive) to the
+ * specified {@code toIndex} (exclusive) to {@code false}.
+ *
+ * @param fromIndex index of the first bit to be cleared.
+ * @param toIndex index after the last bit to be cleared.
+ * @throws IndexOutOfBoundsException if
+ * {@code (fromIndex < 0) | (toIndex < fromIndex)}
+ */
+ @Realtime(limit = LINEAR)
+ public void clear(int fromIndex, int toIndex) {
+ service.clear(fromIndex, toIndex);
+ }
+
+ /**
+ * Sets the bit at the index to the opposite value.
+ *
+ * @param bitIndex the index of the bit.
+ * @throws IndexOutOfBoundsException if {@code bitIndex < 0}
+ */
+ public void flip(int bitIndex) {
+ service.flip(bitIndex);
+ }
+
+ /**
+ * Sets a range of bits to the opposite value.
+ *
+ * @param fromIndex the low index (inclusive).
+ * @param toIndex the high index (exclusive).
+ * @throws IndexOutOfBoundsException if
+ * {@code (fromIndex < 0) | (toIndex < fromIndex)}
+ */
+ @Realtime(limit = LINEAR)
+ public void flip(int fromIndex, int toIndex) {
+ service.flip(fromIndex, toIndex);
+ }
+
+ /**
+ * Returns {@code true } if the specified integer is in
+ * this bit set; {@code false } otherwise.
+ *
+ * @param bitIndex a non-negative integer.
+ * @return the value of the bit at the specified index.
+ * @throws IndexOutOfBoundsException if {@code bitIndex < 0}
+ */
+ public boolean get(int bitIndex) {
+ return service.get(bitIndex);
+ }
+
+ /**
+ * Returns a new bit set composed of a range of bits from this one.
+ *
+ * @param fromIndex the low index (inclusive).
+ * @param toIndex the high index (exclusive).
+ * @return a context allocated bit set instance.
+ * @throws IndexOutOfBoundsException if
+ * {@code (fromIndex < 0) | (toIndex < fromIndex)}
+ */
+ @Realtime(limit = LINEAR)
+ public FastBitSet get(int fromIndex, int toIndex) {
+ return new FastBitSet(service.get(fromIndex, toIndex));
+ }
+
+ /**
+ * Returns {@code true} if this bit set shares at least one
+ * common bit with the specified bit set.
+ *
+ * @param that the bit set to check for intersection
+ * @return {@code true} if the sets intersect; {@code false} otherwise.
+ */
+ @Realtime(limit = LINEAR)
+ public boolean intersects(FastBitSet that) {
+ return service.intersects(that.service);
+ }
+
+ /**
+ * Returns the logical number of bits actually used by this bit
+ * set. It returns the index of the highest set bit plus one.
+ *
+ * <p> Note: This method does not return the number of set bits
+ * which is returned by {@link #size} </p>
+ *
+ * @return the index of the highest set bit plus one.
+ */
+ public int length() {
+ return service.length();
+ }
+
+ /**
+ * Returns the index of the next {@code false} bit, from the specified bit
+ * (inclusive).
+ *
+ * @param fromIndex the start location.
+ * @return the first {@code false} bit.
+ * @throws IndexOutOfBoundsException if {@code fromIndex < 0}
+ */
+ public int nextClearBit(int fromIndex) {
+ return service.nextClearBit(fromIndex);
+ }
+
+ /**
+ * Returns the index of the next {@code true} bit, from the specified bit
+ * (inclusive). If there is none, {@code -1} is returned.
+ * The following code will iterates through the bit set:[code]
+ * for (int i=nextSetBit(0); i >= 0; i = nextSetBit(i+1)) {
+ * ...
+ * }[/code]
+ *
+ * @param fromIndex the start location.
+ * @return the first {@code false} bit.
+ * @throws IndexOutOfBoundsException if {@code fromIndex < 0}
+ */
+ public int nextSetBit(int fromIndex) {
+ return service.nextSetBit(fromIndex);
+ }
+
+ /**
+ * Returns the index of the previous {@code false} bit,
+ * from the specified bit (inclusive).
+ *
+ * @param fromIndex the start location.
+ * @return the first {@code false} bit.
+ * @throws IndexOutOfBoundsException if {@code fromIndex < -1}
+ */
+ public int previousClearBit(int fromIndex) {
+ return service.previousClearBit(fromIndex);
+ }
+
+ /**
+ * Returns the index of the previous {@code true} bit, from the
+ * specified bit (inclusive). If there is none, {@code -1} is returned.
+ * The following code will iterates through the bit set:[code]
+ * for (int i = length(); (i = previousSetBit(i-1)) >= 0; ) {
+ * ...
+ * }[/code]
+ *
+ * @param fromIndex the start location.
+ * @return the first {@code false} bit.
+ * @throws IndexOutOfBoundsException if {@code fromIndex < -1}
+ */
+ public int previousSetBit(int fromIndex) {
+ return service.previousSetBit(fromIndex);
+ }
+
+ /**
+ * Performs the logical OR operation on this bit set and the one specified.
+ * In other words, builds the union of the two sets.
+ * The result is stored into this bit set.
+ *
+ * @param that the second bit set.
+ */
+ @Realtime(limit = LINEAR)
+ public void or(FastBitSet that) {
+ service.or(that.service);
+ }
+
+ /**
+ * Adds the specified integer to this set (corresponding bit is set to
+ * {@code true}.
+ *
+ * @param bitIndex a non-negative integer.
+ * @throws IndexOutOfBoundsException if {@code bitIndex < 0}
+ */
+ public void set(int bitIndex) {
+ service.set(bitIndex);
+ }
+
+ /**
+ * Sets the bit at the given index to the specified value.
+ *
+ * @param bitIndex the position to set.
+ * @param value the value to set it to.
+ * @throws IndexOutOfBoundsException if {@code bitIndex < 0}
+ */
+ public void set(int bitIndex, boolean value) {
+ service.set(bitIndex, value);
+ }
+
+ /**
+ * Sets the bits from the specified {@code fromIndex} (inclusive) to the
+ * specified {@code toIndex} (exclusive) to {@code true}.
+ *
+ * @param fromIndex index of the first bit to be set.
+ * @param toIndex index after the last bit to be set.
+ * @throws IndexOutOfBoundsException if
+ * {@code (fromIndex < 0) | (toIndex < fromIndex)}
+ */
+ @Realtime(limit = LINEAR)
+ public void set(int fromIndex, int toIndex) {
+ if ((fromIndex < 0) || (toIndex < fromIndex)) throw new IndexOutOfBoundsException();
+ service.set(fromIndex, toIndex);
+ }
+
+ /**
+ * Sets the bits between from (inclusive) and to (exclusive) to the
+ * specified value.
+ *
+ * @param fromIndex the start range (inclusive).
+ * @param toIndex the end range (exclusive).
+ * @param value the value to set it to.
+ * @throws IndexOutOfBoundsException if {@code bitIndex < 0}
+ */
+ @Realtime(limit = LINEAR)
+ public void set(int fromIndex, int toIndex, boolean value) {
+ service.set(fromIndex, toIndex, value);
+ }
+
+ /**
+ * Performs the logical XOR operation on this bit set and the one specified.
+ * In other words, builds the symmetric remainder of the two sets
+ * (the elements that are in one set, but not in the other).
+ * The result is stored into this bit set.
+ *
+ * @param that the second bit set.
+ */
+ @Realtime(limit = LINEAR)
+ public void xor(FastBitSet that) {
+ service.xor(that.service);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ @Override
+ public FastBitSet addAll(Index... elements) {
+ return (FastBitSet) super.addAll(elements);
+ }
+
+ @Override
+ public FastBitSet addAll(FastCollection<? extends Index> elements) {
+ return (FastBitSet) super.addAll(elements);
+ }
+
+ @Override
+ protected BitSetService service() {
+ return service;
+ }
+
+}