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:26:53 UTC
[01/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)
Updated Branches:
refs/heads/develop 1c4b4a5c8 -> e43574efa
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamWriter.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamWriter.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamWriter.java
new file mode 100644
index 0000000..4c0770d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamWriter.java
@@ -0,0 +1,365 @@
+/*
+ * 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.xml.stream;
+
+import java.lang.CharSequence;
+
+/**
+ * <p> This interface is similar to
+ * <code>javax.xml.stream.XMLStreamWriter</code>; but it does not forces
+ * dynamic allocation when formatting (any {@link CharSequence CharSequence}
+ * can be used instead of {@link String}).</p>
+ *
+ * <p> Except for the speed (faster) and the added flexibility, the
+ * usage/behavior is about the same as its StAX counterpart.</p>
+ *
+ * <p> This writer does not require creating new <code>String</code> objects
+ * during XML formatting. Attributes values can be held by a single/reusable
+ * {@link javolution.text.TextBuilder TextBuilder}
+ * (or <code>StringBuilder</code>) instance to avoid adverse effects
+ * on memory footprint (heap), garbage collection and performance.
+ * [code]
+ * // Creates a new writer (potentially recycled).
+ * XMLOutputFactory factory = OSGiServices.getXMLOutputFactory();
+ * XMLStreamWriter writer = factory.createXMLStreamWriter(outputStream);
+ *
+ * TextBuilder tmp = new TextBuilder(); // To avoid creating new String instances.
+ * writer.writeStartDocument();
+ * writer.writeStartElement("Time");
+ * writer.writeAttribute("hour", tmp.clear().append(time.hour);
+ * writer.writeAttribute("minute", tmp.clear().append(time.minute);
+ * writer.writeAttribute("second", tmp.clear().append(time.second);
+ * writer.writeEndElement();
+ * writer.writeStartDocument();
+ *
+ * writer.close(); // Closes the writer (does not close underlying output stream).
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+public interface XMLStreamWriter {
+
+ /**
+ * Writes a start tag to the output. All writeStartElement methods open a
+ * new scope in the internal namespace context. Writing the corresponding
+ * EndElement causes the scope to be closed.
+ *
+ * @param localName local name of the tag.
+ * @throws XMLStreamException
+ */
+ void writeStartElement(CharSequence localName)
+ throws XMLStreamException;
+
+ /**
+ * Writes a start tag to the output.
+ *
+ * @param namespaceURI the namespaceURI of the prefix to use.
+ * @param localName local name of the tag.
+ * @throws XMLStreamException if the namespace URI has not been bound
+ * to a prefix and this writer does not {@link
+ * XMLOutputFactory#IS_REPAIRING_NAMESPACES repair namespaces}.
+ */
+ void writeStartElement(CharSequence namespaceURI,
+ CharSequence localName) throws XMLStreamException;
+
+ /**
+ * Writes a start tag to the output.
+ *
+ * @param localName local name of the tag.
+ * @param prefix the prefix of the tag.
+ * @param namespaceURI the uri to bind the prefix to.
+ * @throws XMLStreamException if the namespace URI has not been bound
+ * to a prefix and this writer does not {@link
+ * XMLOutputFactory#IS_REPAIRING_NAMESPACES repair namespaces}.
+ */
+ void writeStartElement(CharSequence prefix, CharSequence localName,
+ CharSequence namespaceURI) throws XMLStreamException;
+
+ /**
+ * Writes an empty element tag to the output.
+ *
+ * @param namespaceURI the uri to bind the tag to.
+ * @param localName local name of the tag.
+ * @throws XMLStreamException if the namespace URI has not been bound
+ * to a prefix and this writer does not {@link
+ * XMLOutputFactory#IS_REPAIRING_NAMESPACES repair namespaces}.
+ */
+ void writeEmptyElement(CharSequence namespaceURI,
+ CharSequence localName) throws XMLStreamException;
+
+ /**
+ * Writes an empty element tag to the output.
+ *
+ * @param prefix the prefix of the tag.
+ * @param localName local name of the tag.
+ * @param namespaceURI the uri to bind the tag to.
+ * @throws XMLStreamException if the namespace URI has not been bound
+ * to a prefix and this writer does not {@link
+ * XMLOutputFactory#IS_REPAIRING_NAMESPACES repair namespaces}.
+ */
+ void writeEmptyElement(CharSequence prefix, CharSequence localName,
+ CharSequence namespaceURI) throws XMLStreamException;
+
+ /**
+ * Writes an empty element tag to the output.
+ *
+ * @param localName local name of the tag.
+ * @throws XMLStreamException
+ */
+ void writeEmptyElement(CharSequence localName)
+ throws XMLStreamException;
+
+ /**
+ * Writes an end tag to the output relying on the internal state of the
+ * writer to determine the prefix and local name of the event.
+ *
+ * @throws XMLStreamException
+ */
+ void writeEndElement() throws XMLStreamException;
+
+ /**
+ * Closes any start tags and writes corresponding end tags.
+ *
+ * @throws XMLStreamException
+ */
+ void writeEndDocument() throws XMLStreamException;
+
+ /**
+ * Close this writer and free any resources associated with the writer. This
+ * must not close the underlying output stream.
+ *
+ * @throws XMLStreamException
+ */
+ void close() throws XMLStreamException;
+
+ /**
+ * Write any cached data to the underlying output mechanism.
+ *
+ * @throws XMLStreamException
+ */
+ void flush() throws XMLStreamException;
+
+ /**
+ * Writes an attribute to the output stream without a prefix.
+ *
+ * @param localName the local name of the attribute.
+ * @param value the value of the attribute.
+ * @throws IllegalStateException if the current state does not allow
+ * attribute writing.
+ * @throws XMLStreamException
+ */
+ void writeAttribute(CharSequence localName, CharSequence value)
+ throws XMLStreamException;
+
+ /**
+ * Writes an attribute to the output stream.
+ *
+ * @param prefix the prefix for this attribute.
+ * @param namespaceURI the uri of the prefix for this attribute
+ * @param localName the local name of the attribute.
+ * @param value the value of the attribute.
+ * @throws IllegalStateException if the current state does not allow
+ * attribute writing.
+ * @throws XMLStreamException if the namespace URI has not been bound
+ * to a prefix and this writer does not {@link
+ * XMLOutputFactory#IS_REPAIRING_NAMESPACES repair namespaces}.
+ */
+
+ void writeAttribute(CharSequence prefix, CharSequence namespaceURI,
+ CharSequence localName, CharSequence value)
+ throws XMLStreamException;
+
+ /**
+ * Writes an attribute to the output stream.
+ *
+ * @param namespaceURI the uri of the prefix for this attribute.
+ * @param localName the local name of the attribute.
+ * @param value the value of the attribute.
+ * @throws IllegalStateException if the current state does not allow
+ * attribute writing.
+ * @throws XMLStreamException if the namespace URI has not been bound
+ * to a prefix and this writer does not {@link
+ * XMLOutputFactory#IS_REPAIRING_NAMESPACES repair namespaces}.
+ */
+ void writeAttribute(CharSequence namespaceURI,
+ CharSequence localName, CharSequence value)
+ throws XMLStreamException;
+
+ /**
+ * Writes a namespace to the output stream. If the prefix argument to this
+ * method is the empty string, "xmlns", or <code>null</code> this method
+ * will delegate to writeDefaultNamespace.
+ *
+ * @param prefix the prefix to bind this namespace to or <code>null</code>
+ * @param namespaceURI the uri to bind the prefix.
+ * @throws IllegalStateException if the current state does not allow
+ * namespace writing.
+ * @throws XMLStreamException
+ */
+ void writeNamespace(CharSequence prefix, CharSequence namespaceURI)
+ throws XMLStreamException;
+
+ /**
+ * Writes the default namespace to the stream.
+ *
+ * @param namespaceURI the uri to bind the default namespace to or
+ * <code>null</code> (to map the prefix to <code>""</code> URI)
+ * @throws IllegalStateException if the current state does not allow
+ * namespace writing.
+ * @throws XMLStreamException
+ */
+ void writeDefaultNamespace(CharSequence namespaceURI)
+ throws XMLStreamException;
+
+ /**
+ * Writes an xml comment with the data enclosed.
+ *
+ * @param data the data contained in the comment or <code>null</code>
+ * @throws XMLStreamException
+ */
+ void writeComment(CharSequence data) throws XMLStreamException;
+
+ /**
+ * Writes a processing instruction.
+ *
+ * @param target the target of the processing instruction.
+ * @throws XMLStreamException
+ */
+ void writeProcessingInstruction(CharSequence target)
+ throws XMLStreamException;
+
+ /**
+ * Writes a processing instruction
+ *
+ * @param target the target of the processing instruction.
+ * @param data the data contained in the processing instruction.
+ * @throws XMLStreamException
+ */
+ void writeProcessingInstruction(CharSequence target,
+ CharSequence data) throws XMLStreamException;
+
+ /**
+ * Writes a CData section.
+ *
+ * @param data the data contained in the CData Section.
+ * @throws XMLStreamException
+ */
+ void writeCData(CharSequence data) throws XMLStreamException;
+
+ /**
+ * Writes a DTD section (representing the entire doctypedecl
+ * production from the XML 1.0 specification).
+ *
+ * @param dtd the DTD to be written.
+ * @throws XMLStreamException
+ */
+ void writeDTD(CharSequence dtd) throws XMLStreamException;
+
+ /**
+ * Writes an entity reference
+ *
+ * @param name the name of the entity.
+ * @throws XMLStreamException
+ */
+ void writeEntityRef(CharSequence name) throws XMLStreamException;
+
+ /**
+ * Writes the XML Declaration. Defaults the XML version to 1.0 and the
+ * encoding (if any) to the one specified when the instance is created
+ * using {@link XMLOutputFactory}.
+ *
+ * @throws XMLStreamException
+ */
+ void writeStartDocument() throws XMLStreamException;
+
+ /**
+ * Writes the XML Declaration. Default the encoding (if any) to the one
+ * specified when the instance is created using {@link XMLOutputFactory}.
+ *
+ * @param version the version of the xml document or <code>null</code>.
+ * @throws XMLStreamException
+ */
+ void writeStartDocument(CharSequence version)
+ throws XMLStreamException;
+
+ /**
+ * Writes the XML Declaration. Note that the encoding parameter does not set
+ * the actual encoding of the underlying output. That must be set when the
+ * instance when the instance is created using {@link XMLOutputFactory}.
+ *
+ * @param encoding the encoding of the xml declaration or <code>null</code>.
+ * @param version the version of the xml document or <code>null</code>.
+ * @throws XMLStreamException
+ */
+ void writeStartDocument(CharSequence encoding, CharSequence version)
+ throws XMLStreamException;
+
+ /**
+ * Writes text to the output.
+ *
+ * @param text the value to write or <code>null</code>.
+ * @throws XMLStreamException
+ */
+ void writeCharacters(CharSequence text) throws XMLStreamException;
+
+ /**
+ * Writes text to the output.
+ *
+ * @param text the value to write
+ * @param start the starting position in the array.
+ * @param length the number of characters to write.
+ * @throws XMLStreamException
+ */
+ void writeCharacters(char[] text, int start, int length)
+ throws XMLStreamException;
+
+ /**
+ * Gets the prefix the specified uri is bound to.
+ *
+ * @param uri namespace URI
+ * @return the prefix for the URI or <code>null</code>
+ * @throws XMLStreamException
+ */
+ CharSequence getPrefix(CharSequence uri) throws XMLStreamException;
+
+ /**
+ * Sets the prefix the uri is bound to. This prefix is bound in the scope of
+ * the current START_ELEMENT / END_ELEMENT pair. If this method is called
+ * before a START_ELEMENT has been written the prefix is bound in the root
+ * scope.
+ *
+ * @param prefix the prefix to bind to the uri.
+ * @param uri the uri to bind to the prefix or <code>null</code>
+ * @throws XMLStreamException
+ */
+ void setPrefix(CharSequence prefix, CharSequence uri)
+ throws XMLStreamException;
+
+ /**
+ * Binds a URI to the default namespace. This URI is bound in the scope of
+ * the current START_ELEMENT / END_ELEMENT pair. If this method is called
+ * before a START_ELEMENT has been written the uri is bound in the root
+ * scope.
+ *
+ * @param uri the uri to bind to the default namespace or <code>null</code>.
+ * @throws XMLStreamException
+ */
+ void setDefaultNamespace(CharSequence uri) throws XMLStreamException;
+
+ /**
+ * Gets the value of a feature/property from the underlying implementation.
+ *
+ * @param name the name of the property.
+ * @return the value of the property.
+ * @throws IllegalArgumentException if the property is not supported.
+ */
+ Object getProperty(String name) throws IllegalArgumentException;
+
+}
\ 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/xml/stream/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/package-info.java
new file mode 100644
index 0000000..7e0d279
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/package-info.java
@@ -0,0 +1,17 @@
+/**
+<p> StAX-like XML readers/writers which do not require object
+ creation (such as String) and are consequently faster than standard StAX.</p>
+<p> The main difference with "javax.xml.stream.*" classes is the integration with
+ OSGi to retrieve {@code XMLInputFactory/XMLOutputFactory} instances and the use
+ of <code>CharSequence</code> instead of <code>String</code>. Since
+ <code>String</code> is a <code>CharSequence</code> (JDK 1.4+), most
+ existing StAX code requires very little modification to be used with these
+ new classes.</p>
+<p> For more information about the usage of this package please read the
+ documentation for the {@link javolution.xml.stream.XMLStreamReader} and
+ {@link javolution.xml.stream.XMLStreamWriter} interfaces.</p>
+<p> For more information about StAX (Streaming API for XML) in general see
+ <a href="http://en.wikipedia.org/wiki/StAX">Wikipedia: StAX</a></p>
+ */
+package javolution.xml.stream;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/ws/WebServiceClient.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/ws/WebServiceClient.java b/commons/marmotta-commons/src/ext/java/javolution/xml/ws/WebServiceClient.java
new file mode 100644
index 0000000..d960cdf
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/ws/WebServiceClient.java
@@ -0,0 +1,223 @@
+/*
+ * 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.xml.ws;
+
+import java.io.IOException;
+import javolution.io.AppendableWriter;
+import javolution.io.UTF8StreamWriter;
+import javolution.text.Text;
+import javolution.text.TextBuilder;
+import javolution.xml.XMLObjectReader;
+import javolution.xml.XMLObjectWriter;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class provides a simple web service client capable of leveraging
+ * Javolution XML marshalling/unmarshalling.</p>
+ *
+ * <p> Sub-classes may work from WSDL files, {@link javolution.xml.XMLFormat
+ * XMLFormat} or directly with the XML streams (StAX). For example:[code]
+ * private static class HelloWorld extends WebServiceClient {
+ * protected void writeRequest(XMLObjectWriter out) throws XMLStreamException {
+ * XMLStreamWriter xml = out.getStreamWriter();
+ * xml.writeDefaultNamespace("http://www.openuri.org/");
+ * xml.writeEmptyElement("helloWorld"); // Operation name.
+ * }
+ * protected void readResponse(XMLObjectReader in) throws XMLStreamException {
+ * XMLStreamReader xml = in.getStreamReader();
+ * xml.require(START_ELEMENT, "http://www.openuri.org/", "string");
+ * xml.next(); // Move to character content.
+ * System.out.println(xml.getText());
+ * }
+ * }
+ * WebServiceClient ws = new HelloWorld().setAddress("http://acme.com:80/HelloWorld.jws");
+ * ws.invoke();
+ *
+ * > Hello World!
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.2, September 16, 2007
+ */
+public abstract class WebServiceClient {
+
+ /**
+ * Holds standard SOAP envelope prefix.
+ */
+ public static final String ENVELOPE_PREFIX = "env";
+
+ /**
+ * Holds standard SOAP envelope namespace.
+ */
+ public static final String ENVELOPE_URI = "http://schemas.xmlsoap.org/soap/envelope/";
+
+ /**
+ * Holds the URL (J2SE).
+ */
+ Object _url;
+
+ /**
+ * Default constructor (address not set).
+ */
+ public WebServiceClient() {}
+
+ /**
+ * Sets the address of this web service.
+ *
+ * @param address the service full address.
+ */
+ public WebServiceClient setAddress(String address) {
+ try {
+ _url = new java.net.URL(address);
+ } catch (java.net.MalformedURLException e) {
+ throw new IllegalArgumentException("Malformed URL: " + address);
+ }
+ return this;
+ }
+
+ /**
+ * Invokes the web service.
+ */
+ public void invoke() throws IOException, XMLStreamException {
+ try {
+ // Formats the request message (we cannot write directly to
+ // the output stream because the http request requires the length.
+ _out.setOutput(_buffer);
+ _writer.setOutput(_out);
+ final XMLStreamWriter xmlOut = _writer.getStreamWriter();
+ xmlOut.setPrefix(csq(ENVELOPE_PREFIX), csq(ENVELOPE_URI));
+ xmlOut.writeStartElement(csq(ENVELOPE_URI), csq("Envelope"));
+ xmlOut.writeNamespace(csq(ENVELOPE_PREFIX), csq(ENVELOPE_URI));
+ xmlOut.writeStartElement(csq(ENVELOPE_URI), csq("Header"));
+ xmlOut.writeEndElement();
+ xmlOut.writeStartElement(csq(ENVELOPE_URI), csq("Body"));
+ writeRequest(_writer);
+ _writer.close();
+
+ // Sends the request.
+ if (_url == null)
+ throw new IOException("URL not set");
+ /**/
+ java.net.HttpURLConnection http = (java.net.HttpURLConnection) ((java.net.URL) _url)
+ .openConnection();
+ http.setRequestProperty("Content-Length",
+ String.valueOf(_buffer.length()));
+ http.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
+ // httpConn.setRequestProperty("SOAPAction", "");
+ http.setRequestMethod("POST");
+ http.setDoOutput(true);
+ http.setDoInput(true);
+ _utf8Writer.setOutput(http.getOutputStream());
+ /**/
+ _utf8Writer.append(_buffer);
+ _utf8Writer.close();
+
+ // Reads the response.
+ /**/
+ _reader.setInput(http.getInputStream());
+ /**/
+ final XMLStreamReader xmlIn = _reader.getStreamReader();
+ while (xmlIn.hasNext()) {
+ if ((xmlIn.next() == XMLStreamReader.START_ELEMENT)
+ && xmlIn.getLocalName().equals("Body")
+ && xmlIn.getNamespaceURI().equals(ENVELOPE_URI)) {
+ // Found body, position reader to next element.
+ xmlIn.next();
+ readResponse(_reader);
+ break;
+ }
+ }
+
+ } finally {
+ _reader.close();
+ _writer.reset();
+ _out.reset();
+ _buffer.clear();
+ _utf8Writer.reset();
+ _reader.reset();
+ }
+ }
+
+ private final TextBuilder _buffer = new TextBuilder();
+ private final AppendableWriter _out = new AppendableWriter();
+ private final XMLObjectWriter _writer = new XMLObjectWriter();
+ private final UTF8StreamWriter _utf8Writer = new UTF8StreamWriter();
+ private final XMLObjectReader _reader = new XMLObjectReader();
+
+ /**/
+
+ /**
+ * Writes the web service request (SOAP body).
+ *
+ * @param out the XML object writer.
+ */
+ protected abstract void writeRequest(XMLObjectWriter out)
+ throws XMLStreamException;
+
+ /**
+ * Reads the web service response (SOAP body). The default implementation
+ * writes the body XML events to <code>System.out</code>.
+ *
+ * @param in the XML object reader.
+ */
+ protected void readResponse(XMLObjectReader in) throws XMLStreamException {
+ final XMLStreamReader xml = in.getStreamReader();
+ while (xml.hasNext()) {
+ switch (xml.next()) {
+ case XMLStreamReader.START_DOCUMENT:
+ System.out.println("Start Document");
+ break;
+ case XMLStreamReader.END_DOCUMENT:
+ System.out.println("End Document.");
+ break;
+ case XMLStreamReader.START_ELEMENT:
+ System.out.println("Start Element: " + xml.getLocalName()
+ + "(" + xml.getNamespaceURI() + ")");
+ for (int i = 0, n = xml.getAttributeCount(); i < n; i++) {
+ System.out.println(" Attribute: "
+ + xml.getAttributeLocalName(i) + "("
+ + xml.getAttributeNamespace(i) + "), Value: "
+ + xml.getAttributeValue(i));
+ }
+ break;
+ case XMLStreamReader.END_ELEMENT:
+ if (xml.getLocalName().equals("Body")
+ && xml.getNamespaceURI().equals(ENVELOPE_URI))
+ return; // End body.
+ System.out.println("End Element: " + xml.getLocalName()
+ + "(" + xml.getNamespaceURI() + ")");
+ break;
+ case XMLStreamReader.CHARACTERS:
+ System.out.println("Characters: " + xml.getText());
+ break;
+ case XMLStreamReader.CDATA:
+ System.out.println("CDATA: " + xml.getText());
+ break;
+ case XMLStreamReader.COMMENT:
+ System.out.println("Comment: " + xml.getText());
+ break;
+ case XMLStreamReader.SPACE:
+ System.out.println("Space");
+ break;
+ default:
+ System.out.println(xml);
+ }
+ }
+
+ }
+
+ // For J2ME compatiblity.
+ private static final CharSequence csq(Object string) {
+ return (string instanceof CharSequence) ? (CharSequence) string : Text
+ .valueOf(string);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/ws/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/ws/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/xml/ws/package-info.java
new file mode 100644
index 0000000..0eef27c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/ws/package-info.java
@@ -0,0 +1,5 @@
+/**
+<p> Classes and interfaces to create and handle web services.</p>
+ */
+package javolution.xml.ws;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/sesame/model/StatementCommons.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/sesame/model/StatementCommons.java b/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/sesame/model/StatementCommons.java
index 41e68e4..c04e7be 100644
--- a/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/sesame/model/StatementCommons.java
+++ b/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/sesame/model/StatementCommons.java
@@ -19,8 +19,16 @@ package org.apache.marmotta.commons.sesame.model;
import com.google.common.base.Equivalence;
import com.google.common.base.Objects;
+import javolution.util.FastMap;
+import javolution.util.FastSet;
+import javolution.util.function.Equality;
+import org.apache.marmotta.commons.collections.EquivalenceHashMap;
+import org.apache.marmotta.commons.collections.EquivalenceHashSet;
import org.openrdf.model.Statement;
+import java.util.Map;
+import java.util.Set;
+
/**
* Provide some utility functions for managing statements (e.g. different forms of equivalence)
*
@@ -28,74 +36,155 @@ import org.openrdf.model.Statement;
*/
public class StatementCommons {
+ private final static Equivalence<Statement> TRIPLE_EQUIVALENCE = new Equivalence<Statement>() {
+ @Override
+ protected boolean doEquivalent(Statement a, Statement b) {
+ if(a == b) return true;
+
+ if(!Objects.equal(a.getSubject(), b.getSubject())) return false;
+ if(!Objects.equal(a.getPredicate(), b.getPredicate())) return false;
+ if(!Objects.equal(a.getObject(), b.getObject())) return false;
+ return true;
+ }
+
+ @Override
+ protected int doHash(Statement statement) {
+ return Objects.hashCode(statement.getSubject(), statement.getPredicate(), statement.getObject());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this.getClass().equals(obj.getClass());
+ }
+
+ @Override
+ public int hashCode() {
+ return this.getClass().hashCode();
+ }
+ };
+
+
+ private final static Equivalence<Statement> QUADRUPLE_EQUIVALENCE = new Equivalence<Statement>() {
+ @Override
+ protected boolean doEquivalent(Statement a, Statement b) {
+ if(a == b) return true;
+
+ if(!Objects.equal(a.getSubject(), b.getSubject())) return false;
+ if(!Objects.equal(a.getPredicate(), b.getPredicate())) return false;
+ if(!Objects.equal(a.getObject(), b.getObject())) return false;
+ if(!Objects.equal(a.getContext(), b.getContext())) return false;
+ return true;
+ }
+
+ @Override
+ protected int doHash(Statement statement) {
+ return Objects.hashCode(statement.getSubject(), statement.getPredicate(), statement.getObject(), statement.getContext());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this.getClass().equals(obj.getClass());
+ }
+
+ @Override
+ public int hashCode() {
+ return this.getClass().hashCode();
+ }
+ };
+
/**
* Return triple equivalence, taking only into account subject, predicate and object
*
* @return
*/
public static Equivalence<Statement> tripleEquivalence() {
- return new Equivalence<Statement>() {
- @Override
- protected boolean doEquivalent(Statement a, Statement b) {
- if(a == b) return true;
+ return TRIPLE_EQUIVALENCE;
+ }
- if(!Objects.equal(a.getSubject(), b.getSubject())) return false;
- if(!Objects.equal(a.getPredicate(), b.getPredicate())) return false;
- if(!Objects.equal(a.getObject(), b.getObject())) return false;
- return true;
- }
+ /**
+ * Return quadruple equivalence, taking into account subject, predicate, object, and context.
+ *
+ * @return
+ */
+ public static Equivalence<Statement> quadrupleEquivalence() {
+ return QUADRUPLE_EQUIVALENCE;
- @Override
- protected int doHash(Statement statement) {
- return Objects.hashCode(statement.getSubject(), statement.getPredicate(), statement.getObject());
- }
+ }
- @Override
- public boolean equals(Object obj) {
- return this.getClass().equals(obj.getClass());
- }
+ /**
+ * Create a new set for statements using the triple equivalence (based on subject, predicate, object only)
+ * @param <T>
+ * @return
+ */
+ public static <T extends Statement> Set<T> newTripleSet() {
+ //return new EquivalenceHashSet<>(tripleEquivalence());
+ return new FastSet<>(equivalenceEquality(tripleEquivalence()));
+ }
- @Override
- public int hashCode() {
- return this.getClass().hashCode();
- }
- };
+ /**
+ * Create a new set for statements using the triple equivalence (based on subject, predicate, object and context)
+ * @param <T>
+ * @return
+ */
+ public static <T extends Statement> Set<T> newQuadrupleSet() {
+ //return new EquivalenceHashSet<>(quadrupleEquivalence());
+ return new FastSet<>(equivalenceEquality(quadrupleEquivalence()));
}
/**
- * Return quadruple equivalence, taking into account subject, predicate, object, and context.
+ * Create a new map where the keys are statements and the equivalence relation used for keys is triple
+ * equivalence (based on subject, predicate, object only)
*
+ * @param <K>
+ * @param <V>
* @return
*/
- public static Equivalence<Statement> quadrupleEquivalence() {
- return new Equivalence<Statement>() {
+ public static <K extends Statement, V> Map<K,V> newTripleMap() {
+ //return new EquivalenceHashMap<>(tripleEquivalence());
+ return new FastMap<>(equivalenceEquality(tripleEquivalence()));
+ }
+
+ /**
+ * Create a new map where the keys are statements and the equivalence relation used for keys is triple
+ * equivalence (based on subject, predicate, object only)
+ *
+ * @param <K>
+ * @param <V>
+ * @return
+ */
+ public static <K extends Statement, V> Map<K,V> newQuadrupleMap() {
+ //return new EquivalenceHashMap<>(quadrupleEquivalence());
+ return new FastMap<>(equivalenceEquality(quadrupleEquivalence()));
+ }
+
+
+
+ private static <E> Equality<E> equivalenceEquality(final Equivalence<E> equivalence) {
+ return new Equality<E>() {
@Override
- protected boolean doEquivalent(Statement a, Statement b) {
- if(a == b) return true;
-
- if(!Objects.equal(a.getSubject(), b.getSubject())) return false;
- if(!Objects.equal(a.getPredicate(), b.getPredicate())) return false;
- if(!Objects.equal(a.getObject(), b.getObject())) return false;
- if(!Objects.equal(a.getContext(), b.getContext())) return false;
- return true;
+ public int hashCodeOf(E object) {
+ return equivalence.hash(object);
}
@Override
- protected int doHash(Statement statement) {
- return Objects.hashCode(statement.getSubject(), statement.getPredicate(), statement.getObject(), statement.getContext());
+ public boolean areEqual(E left, E right) {
+ return equivalence.equivalent(left, right);
}
@Override
- public boolean equals(Object obj) {
- return this.getClass().equals(obj.getClass());
+ public int compare(E left, E right) {
+ return equivalence.hash(left) - equivalence.hash(right);
}
@Override
public int hashCode() {
- return this.getClass().hashCode();
+ return equivalence.hashCode();
}
- };
+ @Override
+ public boolean equals(Object obj) {
+ return obj.hashCode() == hashCode();
+ }
+ };
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSet2Test.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSet2Test.java b/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSet2Test.java
new file mode 100644
index 0000000..185b0be
--- /dev/null
+++ b/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSet2Test.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.marmotta.commons.collections;
+
+import com.google.common.base.Equivalence;
+import javolution.util.FastSet;
+import javolution.util.function.Equality;
+
+import java.util.Set;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class EquivalenceHashSet2Test extends EquivalenceHashSetTest {
+
+ @Override
+ public Set<String> createHashSet(final Equivalence<String> equivalence) {
+ return new FastSet<>(new Equality<String>() {
+ @Override
+ public int hashCodeOf(String object) {
+ return equivalence.hash(object);
+ }
+
+ @Override
+ public boolean areEqual(String left, String right) {
+ return equivalence.equivalent(left, right);
+ }
+
+ @Override
+ public int compare(String left, String right) {
+ return equivalence.hash(left) - equivalence.hash(right);
+ }
+
+ @Override
+ public int hashCode() {
+ return equivalence.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj.hashCode() == hashCode();
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSetTest.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSetTest.java b/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSetTest.java
new file mode 100644
index 0000000..4aa3e9c
--- /dev/null
+++ b/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/collections/EquivalenceHashSetTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.marmotta.commons.collections;
+
+import com.google.common.base.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Set;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class EquivalenceHashSetTest {
+
+ // a simple equivalence function on strings, saying they are equal if their first character is the same
+ Equivalence<String> equivalence = new Equivalence<String>() {
+ @Override
+ protected boolean doEquivalent(String a, String b) {
+ return a.charAt(0) == b.charAt(0);
+ }
+
+ @Override
+ protected int doHash(String s) {
+ return s.charAt(0) * 31;
+ }
+ };
+
+ public Set<String> createHashSet(Equivalence<String> equivalence) {
+ return new EquivalenceHashSet<>(equivalence);
+ }
+
+ @Test
+ public void testEquivalence() {
+ Assert.assertTrue(equivalence.equivalent("abc","axy"));
+ Assert.assertFalse(equivalence.equivalent("abc", "xyz"));
+
+ Assert.assertTrue(equivalence.hash("abc") == equivalence.hash("axy"));
+ Assert.assertFalse(equivalence.hash("abc") == equivalence.hash("xyz"));
+ }
+
+ @Test
+ public void testSetContains() {
+ String a = "abc";
+ String b = "axy";
+ String c = "xyz";
+
+ Set<String> set = createHashSet(equivalence);
+ set.add(a);
+
+ // set should now also contain b (because first character the same)
+ Assert.assertTrue(set.contains(b));
+
+ set.add(b);
+
+ // adding b should not change the set
+ Assert.assertEquals(1, set.size());
+
+ set.add(c);
+
+ Assert.assertEquals(2, set.size());
+
+ }
+
+
+ @Test
+ public void testSetEquals() {
+ String a1 = "abc";
+ String a2 = "axy";
+ String b1 = "bcd";
+ String b2 = "bxy";
+ String c1 = "cde";
+
+ Set<String> set1 = createHashSet(equivalence);
+ Set<String> set2 = createHashSet(equivalence);
+
+ // test empty sets
+ Assert.assertEquals(set1,set2);
+
+ set1.add(a1);
+ set1.add(b1);
+
+ set2.add(b2);
+ set2.add(a2);
+
+
+ Assert.assertEquals(2, set1.size());
+ Assert.assertEquals(2, set2.size());
+
+
+ // test sets with elements, insertion order different
+ Assert.assertEquals(set1,set2);
+
+ set1.add(c1);
+
+ Assert.assertNotEquals(set1,set2);
+
+
+ }
+
+ @Test
+ public void testIteration() {
+ String a = "abc";
+ String b = "axy";
+ String c = "xyz";
+
+ Set<String> set = createHashSet(equivalence);
+ set.add(a);
+ set.add(b);
+ set.add(c);
+
+ int count = 0;
+ for(String x : set) {
+ count++;
+ }
+ Assert.assertEquals(2,count);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
index c7eb138..415fa3c 100644
--- a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
@@ -17,27 +17,20 @@
*/
package org.apache.marmotta.kiwi.reasoner.engine;
+import com.google.common.base.Equivalence;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import info.aduna.iteration.CloseableIteration;
import info.aduna.iteration.EmptyIteration;
import info.aduna.iteration.Iterations;
import info.aduna.iteration.SingletonIteration;
-import org.apache.marmotta.commons.collections.EquivalenceHashMap;
-import org.apache.marmotta.commons.collections.EquivalenceHashSet;
import org.apache.marmotta.commons.sesame.model.StatementCommons;
import org.apache.marmotta.kiwi.model.caching.TripleTable;
import org.apache.marmotta.kiwi.model.rdf.KiWiNode;
import org.apache.marmotta.kiwi.model.rdf.KiWiResource;
import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
-import org.apache.marmotta.kiwi.reasoner.model.program.Justification;
-import org.apache.marmotta.kiwi.reasoner.model.program.LiteralField;
-import org.apache.marmotta.kiwi.reasoner.model.program.Pattern;
-import org.apache.marmotta.kiwi.reasoner.model.program.Program;
-import org.apache.marmotta.kiwi.reasoner.model.program.ResourceField;
-import org.apache.marmotta.kiwi.reasoner.model.program.Rule;
-import org.apache.marmotta.kiwi.reasoner.model.program.VariableField;
+import org.apache.marmotta.kiwi.reasoner.model.program.*;
import org.apache.marmotta.kiwi.reasoner.model.query.QueryResult;
import org.apache.marmotta.kiwi.reasoner.persistence.KiWiReasoningConnection;
import org.apache.marmotta.kiwi.reasoner.persistence.KiWiReasoningPersistence;
@@ -56,14 +49,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -139,6 +125,8 @@ public class ReasoningEngine implements TransactionListener {
*/
private SKWRLReasoner reasonerThread;
+ private static Equivalence<Statement> equivalence = StatementCommons.quadrupleEquivalence();
+
/**
* A lock to ensure that only once thread at a time is carrying out persistence
*/
@@ -349,7 +337,7 @@ public class ReasoningEngine implements TransactionListener {
private void executeReasoner(TransactionData data) {
updateTaskStatus("fetching worklist");
- Set<KiWiTriple> newTriples = new EquivalenceHashSet<>(StatementCommons.quadrupleEquivalence());
+ Set<KiWiTriple> newTriples = StatementCommons.newQuadrupleSet();
for(Statement stmt : data.getAddedTriples()) {
KiWiTriple t = (KiWiTriple)stmt;
if(t.isMarkedForReasoning()) {
@@ -517,24 +505,30 @@ public class ReasoningEngine implements TransactionListener {
updateTaskStatus("loading unsupported triples");
CloseableIteration<KiWiTriple,SQLException> tripleIterator = connection.listUnsupportedTriples();
-
- updateTaskStatus("deleting unsupported triples");
- SailConnection tc = store.getConnection();
- KiWiSailConnection ic = getWrappedConnection(tc);
try {
- tc.begin();
- while(tripleIterator.hasNext()) {
- ic.removeInferredStatement(tripleIterator.next());
- count++;
+ if(tripleIterator.hasNext()) {
+
+ updateTaskStatus("deleting unsupported triples");
+ SailConnection tc = store.getConnection();
+ KiWiSailConnection ic = getWrappedConnection(tc);
+ try {
+ tc.begin();
+ while(tripleIterator.hasNext()) {
+ ic.removeInferredStatement(tripleIterator.next());
+ count++;
+ }
+ log.debug("removed {} unsupported triples",count);
+ tc.commit();
+ } catch(SailException ex) {
+ ic.rollback();
+ throw ex;
+ } finally {
+ ic.close();
+ }
}
- log.debug("removed {} unsupported triples",count);
- tc.commit();
- } catch(SailException ex) {
- ic.rollback();
- throw ex;
} finally {
Iterations.closeCloseable(tripleIterator);
- ic.close();
+
}
}
@@ -768,7 +762,7 @@ public class ReasoningEngine implements TransactionListener {
HashSet<Justification> justifications = new HashSet<Justification>();
Iterations.addAll(connection.listJustificationsForTriple(t), justifications);
for(Justification j : transactionJustifications) {
- if(j.getTriple().equals(t)) {
+ if(equivalence.equivalent(j.getTriple(), t)) {
justifications.add(j);
}
}
@@ -784,7 +778,7 @@ public class ReasoningEngine implements TransactionListener {
*/
private Set<Justification> getBaseJustifications(KiWiReasoningConnection connection, Set<Justification> justifications) throws SQLException {
Set<Justification> baseJustifications = new HashSet<Justification>();
- Map<KiWiTriple,Collection<Justification>> justificationCache = new HashMap<KiWiTriple, Collection<Justification>>();
+ Map<KiWiTriple,Collection<Justification>> justificationCache = StatementCommons.newQuadrupleMap();
for(Justification justification : justifications) {
KiWiTriple triple = justification.getTriple();
@@ -842,7 +836,7 @@ public class ReasoningEngine implements TransactionListener {
*/
private void removeDuplicateJustifications(KiWiReasoningConnection connection, Set<Justification> justifications) throws SQLException {
// remove duplicate justifications
- Map<KiWiTriple,Collection<Justification>> justificationCache = new EquivalenceHashMap<KiWiTriple, Collection<Justification>>(StatementCommons.quadrupleEquivalence());
+ Map<KiWiTriple,Collection<Justification>> justificationCache = StatementCommons.newQuadrupleMap();
for(Iterator<Justification> it = justifications.iterator(); it.hasNext(); ) {
Justification j = it.next();
@@ -928,6 +922,8 @@ public class ReasoningEngine implements TransactionListener {
}
public void shutdown() {
+ log.info("shutting down reasoning service ...");
+
for(int i = 0; i<10 && isRunning(); i++) {
log.warn("reasoner not yet finished, waiting for 10 seconds (try={})", i+1);
try {
@@ -936,7 +932,6 @@ public class ReasoningEngine implements TransactionListener {
}
}
- log.info("shutting down reasoning service ...");
reasonerThread.shutdown();
}
@@ -970,6 +965,7 @@ public class ReasoningEngine implements TransactionListener {
}
public void shutdown() {
+ log.info("REASONER: signalling shutdown to reasoner thread");
shutdown = true;
this.interrupt();
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/model/program/Justification.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/model/program/Justification.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/model/program/Justification.java
index c6f5a6e..5de904e 100644
--- a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/model/program/Justification.java
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/model/program/Justification.java
@@ -18,9 +18,10 @@
package org.apache.marmotta.kiwi.reasoner.model.program;
-import org.apache.marmotta.commons.collections.EquivalenceHashSet;
+import com.google.common.base.Equivalence;
import org.apache.marmotta.commons.sesame.model.StatementCommons;
import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
+import org.openrdf.model.Statement;
import java.util.Date;
import java.util.HashSet;
@@ -65,8 +66,11 @@ public class Justification {
*/
private Date createdAt;
+
+ private static Equivalence<Statement> equivalence = StatementCommons.quadrupleEquivalence();
+
public Justification() {
- supportingTriples = new EquivalenceHashSet<>(StatementCommons.quadrupleEquivalence());
+ supportingTriples = StatementCommons.newQuadrupleSet();
supportingRules = new HashSet<Rule>();
}
@@ -120,7 +124,7 @@ public class Justification {
//if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (!supportingRules.equals(that.supportingRules)) return false;
if (!supportingTriples.equals(that.supportingTriples)) return false;
- if (!triple.equals(that.triple)) return false;
+ if (!equivalence.equivalent(this.triple, that.triple)) return false;
return true;
}
@@ -128,7 +132,7 @@ public class Justification {
@Override
public int hashCode() {
int result = 0; // id != null ? id.hashCode() : 0;
- result = 31 * result + triple.hashCode();
+ result = 31 * result + equivalence.hash(triple);
result = 31 * result + supportingTriples.hashCode();
result = 31 * result + supportingRules.hashCode();
return result;
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/ReasoningEngineTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/ReasoningEngineTest.java b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/ReasoningEngineTest.java
index a9a3dcf..75b7cad 100644
--- a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/ReasoningEngineTest.java
+++ b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/ReasoningEngineTest.java
@@ -326,6 +326,9 @@ public class ReasoningEngineTest {
log.debug("sleeping for 100ms to let engine finish processing ... ");
Thread.sleep(100);
}
+
+ log.debug("reasoning finished, running tests");
+
con.begin();
List<Statement> inferred4 = Iterations.asList(con.getStatements(a,property,d, true));
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
index b08c0cf..c6b7f2e 100644
--- a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
+++ b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
@@ -79,6 +79,7 @@ public class KiWiRDFSchemaRepositoryConnectionTest extends RDFSchemaRepositoryCo
Sail wsail = new SailWrapper(rsail) {
@Override
public void shutDown() throws SailException {
+ rsail.getEngine().shutdown();
try {
rsail.getPersistence().dropDatabase();
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
index 8e329e8..1e5cade 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
@@ -1195,7 +1195,7 @@ public class KiWiConnection {
// need to remove from triple batch and from database
commitLock.lock();
try {
- if(!tripleBatch.remove(triple)) {
+ if(tripleBatch == null || !tripleBatch.remove(triple)) {
requireJDBCConnection();
PreparedStatement deleteTriple = getPreparedStatement("delete.triple");
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
index 7fc39cd..98ff1b9 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
@@ -444,7 +444,7 @@ public class KiWiPersistence {
}
}
- if(connectionPool != null) {
+ if(initialized && connectionPool != null) {
Connection conn = connectionPool.getConnection();
conn.setAutoCommit(false);
@@ -508,6 +508,8 @@ public class KiWiPersistence {
public void shutdown() {
+ initialized = false;
+
if(!droppedDatabase && !configuration.isCommitSequencesOnCommit()) {
log.info("storing in-memory sequences in database ...");
try {
@@ -531,7 +533,6 @@ public class KiWiPersistence {
connectionPool = null;
memorySequences = null;
- initialized = false;
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/libraries/kiwi/kiwi-tripletable/src/main/java/org/apache/marmotta/kiwi/model/caching/TripleTable.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-tripletable/src/main/java/org/apache/marmotta/kiwi/model/caching/TripleTable.java b/libraries/kiwi/kiwi-tripletable/src/main/java/org/apache/marmotta/kiwi/model/caching/TripleTable.java
index 5740b91..6a6a261 100644
--- a/libraries/kiwi/kiwi-tripletable/src/main/java/org/apache/marmotta/kiwi/model/caching/TripleTable.java
+++ b/libraries/kiwi/kiwi-tripletable/src/main/java/org/apache/marmotta/kiwi/model/caching/TripleTable.java
@@ -56,7 +56,7 @@ public class TripleTable<Triple extends Statement> implements Set<Triple>, Seria
private NavigableMap<IntArray,Triple> indexCSPO;
public TripleTable() {
- data = new EquivalenceHashSet<Triple>(StatementCommons.quadrupleEquivalence());
+ data = StatementCommons.newQuadrupleSet();
indexSPOC = new TreeMap<IntArray, Triple>();
indexCSPO = new TreeMap<IntArray, Triple>();
}
[18/18] git commit: 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)
Posted by ss...@apache.org.
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)
Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/e43574ef
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/e43574ef
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/e43574ef
Branch: refs/heads/develop
Commit: e43574efa9e27f39c58449737b480bee4f7916b9
Parents: 1c4b4a5
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Fri Sep 6 14:26:51 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Fri Sep 6 14:26:52 2013 +0200
----------------------------------------------------------------------
commons/marmotta-commons/pom.xml | 68 +
.../java/javolution/util/FastTableTest.java | 331 ++++
.../ext/java/javax/realtime/RealtimeThread.java | 13 +
.../javolution/context/AbstractContext.java | 178 ++
.../javolution/context/ConcurrentContext.java | 258 +++
.../java/javolution/context/FormatContext.java | 39 +
.../java/javolution/context/LocalContext.java | 125 ++
.../ext/java/javolution/context/LogContext.java | 157 ++
.../javolution/context/SecurityContext.java | 256 +++
.../java/javolution/context/StorageContext.java | 125 ++
.../context/internal/ConcurrentContextImpl.java | 120 ++
.../context/internal/ConcurrentThreadImpl.java | 74 +
.../context/internal/LocalContextImpl.java | 44 +
.../context/internal/LogContextImpl.java | 91 +
.../context/internal/SecurityContextImpl.java | 61 +
.../context/internal/StorageContextImpl.java | 87 +
.../java/javolution/context/package-info.java | 103 ++
.../ext/java/javolution/doc-files/overview.html | 149 ++
.../java/javolution/io/AppendableWriter.java | 163 ++
.../java/javolution/io/CharSequenceReader.java | 156 ++
.../src/ext/java/javolution/io/Struct.java | 1749 ++++++++++++++++++
.../javolution/io/UTF8ByteBufferReader.java | 267 +++
.../javolution/io/UTF8ByteBufferWriter.java | 224 +++
.../java/javolution/io/UTF8StreamReader.java | 316 ++++
.../java/javolution/io/UTF8StreamWriter.java | 338 ++++
.../src/ext/java/javolution/io/Union.java | 54 +
.../ext/java/javolution/io/package-info.java | 7 +
.../ext/java/javolution/lang/Configurable.java | 283 +++
.../src/ext/java/javolution/lang/Immutable.java | 45 +
.../ext/java/javolution/lang/Initializer.java | 149 ++
.../src/ext/java/javolution/lang/MathLib.java | 1471 +++++++++++++++
.../java/javolution/lang/Parallelizable.java | 78 +
.../src/ext/java/javolution/lang/Realtime.java | 118 ++
.../src/ext/java/javolution/lang/ValueType.java | 71 +
.../ext/java/javolution/lang/package-info.java | 5 +
.../osgi/internal/ConfigurableListenerImpl.java | 32 +
.../osgi/internal/JavolutionActivator.java | 75 +
.../osgi/internal/LogServiceImpl.java | 115 ++
.../javolution/osgi/internal/OSGiServices.java | 150 ++
.../osgi/internal/ServiceTrackerImpl.java | 62 +
.../osgi/internal/XMLInputFactoryProvider.java | 34 +
.../osgi/internal/XMLOutputFactoryProvider.java | 34 +
.../ext/java/javolution/test/Perfometer.java | 271 +++
.../ext/java/javolution/test/package-info.java | 5 +
.../src/ext/java/javolution/text/CharArray.java | 393 ++++
.../src/ext/java/javolution/text/CharSet.java | 327 ++++
.../src/ext/java/javolution/text/Cursor.java | 397 ++++
.../java/javolution/text/DefaultTextFormat.java | 60 +
.../src/ext/java/javolution/text/Text.java | 1333 +++++++++++++
.../ext/java/javolution/text/TextBuilder.java | 888 +++++++++
.../ext/java/javolution/text/TextContext.java | 93 +
.../ext/java/javolution/text/TextFormat.java | 125 ++
.../ext/java/javolution/text/TypeFormat.java | 732 ++++++++
.../text/internal/TextContextImpl.java | 345 ++++
.../ext/java/javolution/text/package-info.java | 67 +
.../ext/java/javolution/util/FastBitSet.java | 361 ++++
.../java/javolution/util/FastCollection.java | 715 +++++++
.../src/ext/java/javolution/util/FastMap.java | 422 +++++
.../src/ext/java/javolution/util/FastSet.java | 146 ++
.../ext/java/javolution/util/FastSortedMap.java | 205 ++
.../ext/java/javolution/util/FastSortedSet.java | 153 ++
.../java/javolution/util/FastSortedTable.java | 137 ++
.../src/ext/java/javolution/util/FastTable.java | 453 +++++
.../src/ext/java/javolution/util/Index.java | 262 +++
.../util/doc-files/FastTable-WCET.png | Bin 0 -> 36829 bytes
.../javolution/util/doc-files/architecture.png | Bin 0 -> 11414 bytes
.../java/javolution/util/function/Consumer.java | 29 +
.../javolution/util/function/Equalities.java | 79 +
.../java/javolution/util/function/Equality.java | 77 +
.../java/javolution/util/function/Function.java | 33 +
.../javolution/util/function/Iteration.java | 32 +
.../javolution/util/function/MultiVariable.java | 54 +
.../javolution/util/function/Predicate.java | 32 +
.../java/javolution/util/function/Reducer.java | 26 +
.../java/javolution/util/function/Reducers.java | 229 +++
.../javolution/util/function/Splittable.java | 53 +
.../java/javolution/util/function/Supplier.java | 30 +
.../javolution/util/function/package-info.java | 25 +
.../util/internal/ReadWriteLockImpl.java | 138 ++
.../internal/bitset/BitSetIteratorImpl.java | 51 +
.../util/internal/bitset/BitSetServiceImpl.java | 373 ++++
.../collection/AtomicCollectionImpl.java | 194 ++
.../internal/collection/CollectionView.java | 268 +++
.../collection/DistinctCollectionImpl.java | 102 +
.../collection/FilteredCollectionImpl.java | 111 ++
.../collection/MappedCollectionImpl.java | 101 +
.../collection/ParallelCollectionImpl.java | 120 ++
.../collection/ReversedCollectionImpl.java | 98 +
.../collection/SequentialCollectionImpl.java | 83 +
.../collection/SharedCollectionImpl.java | 270 +++
.../collection/SortedCollectionImpl.java | 109 ++
.../collection/UnmodifiableCollectionImpl.java | 98 +
.../comparator/ArrayComparatorImpl.java | 72 +
.../comparator/IdentityComparatorImpl.java | 42 +
.../LexicalCaseInsensitiveComparatorImpl.java | 73 +
.../comparator/LexicalComparatorImpl.java | 76 +
.../comparator/LexicalFastComparatorImpl.java | 30 +
.../comparator/StandardComparatorImpl.java | 48 +
.../comparator/WrapperComparatorImpl.java | 52 +
.../util/internal/map/AtomicMapImpl.java | 192 ++
.../util/internal/map/FastMapImpl.java | 250 +++
.../util/internal/map/FractalMapImpl.java | 121 ++
.../util/internal/map/MapEntryImpl.java | 46 +
.../javolution/util/internal/map/MapView.java | 363 ++++
.../util/internal/map/ParallelMapImpl.java | 130 ++
.../util/internal/map/SequentialMapImpl.java | 93 +
.../util/internal/map/SharedMapImpl.java | 240 +++
.../util/internal/map/UnmodifiableMapImpl.java | 109 ++
.../map/sorted/AtomicSortedMapImpl.java | 82 +
.../internal/map/sorted/FastSortedMapImpl.java | 115 ++
.../util/internal/map/sorted/MapEntryImpl.java | 50 +
.../map/sorted/SharedSortedMapImpl.java | 107 ++
.../util/internal/map/sorted/SortedMapView.java | 163 ++
.../internal/map/sorted/SubSortedMapImpl.java | 143 ++
.../map/sorted/UnmodifiableSortedMapImpl.java | 85 +
.../util/internal/set/AtomicSetImpl.java | 31 +
.../util/internal/set/FilteredSetImpl.java | 43 +
.../util/internal/set/MappedSetImpl.java | 43 +
.../javolution/util/internal/set/SetView.java | 49 +
.../util/internal/set/SharedSetImpl.java | 52 +
.../util/internal/set/UnmodifiableSetImpl.java | 42 +
.../set/sorted/AtomicSortedSetImpl.java | 62 +
.../set/sorted/SharedSortedSetImpl.java | 88 +
.../util/internal/set/sorted/SortedSetView.java | 60 +
.../internal/set/sorted/SubSortedSetImpl.java | 144 ++
.../set/sorted/UnmodifiableSortedSetImpl.java | 67 +
.../util/internal/table/AtomicTableImpl.java | 236 +++
.../util/internal/table/FastTableImpl.java | 210 +++
.../util/internal/table/FractalTableImpl.java | 172 ++
.../util/internal/table/QuickSort.java | 75 +
.../util/internal/table/ReversedTableImpl.java | 76 +
.../util/internal/table/SharedTableImpl.java | 315 ++++
.../util/internal/table/SubTableImpl.java | 101 +
.../util/internal/table/TableIteratorImpl.java | 93 +
.../util/internal/table/TableView.java | 259 +++
.../internal/table/UnmodifiableTableImpl.java | 84 +
.../table/sorted/AtomicSortedTableImpl.java | 55 +
.../table/sorted/FastSortedTableImpl.java | 67 +
.../table/sorted/SharedSortedTableImpl.java | 57 +
.../internal/table/sorted/SortedTableView.java | 68 +
.../table/sorted/SubSortedTableImpl.java | 87 +
.../sorted/UnmodifiableSortedTableImpl.java | 46 +
.../ext/java/javolution/util/package-info.java | 32 +
.../javolution/util/service/BitSetService.java | 116 ++
.../util/service/CollectionService.java | 39 +
.../javolution/util/service/MapService.java | 73 +
.../javolution/util/service/SetService.java | 24 +
.../util/service/SortedMapService.java | 41 +
.../util/service/SortedSetService.java | 33 +
.../util/service/SortedTableService.java | 36 +
.../javolution/util/service/TableService.java | 29 +
.../javolution/util/service/package-info.java | 6 +
.../java/javolution/xml/DefaultXMLFormat.java | 59 +
.../src/ext/java/javolution/xml/QName.java | 233 +++
.../src/ext/java/javolution/xml/XMLBinding.java | 298 +++
.../src/ext/java/javolution/xml/XMLContext.java | 74 +
.../src/ext/java/javolution/xml/XMLFormat.java | 1029 +++++++++++
.../java/javolution/xml/XMLObjectReader.java | 291 +++
.../java/javolution/xml/XMLObjectWriter.java | 311 ++++
.../javolution/xml/XMLReferenceResolver.java | 206 +++
.../java/javolution/xml/XMLSerializable.java | 47 +
.../javolution/xml/doc-files/xmlDataBinding.png | Bin 0 -> 15305 bytes
.../javolution/xml/internal/XMLContextImpl.java | 151 ++
.../xml/internal/stream/AttributesImpl.java | 170 ++
.../xml/internal/stream/EntitiesImpl.java | 155 ++
.../xml/internal/stream/NamespacesImpl.java | 276 +++
.../internal/stream/XMLInputFactoryImpl.java | 106 ++
.../internal/stream/XMLOutputFactoryImpl.java | 151 ++
.../internal/stream/XMLStreamReaderImpl.java | 1523 +++++++++++++++
.../internal/stream/XMLStreamWriterImpl.java | 939 ++++++++++
.../ext/java/javolution/xml/package-info.java | 346 ++++
.../ext/java/javolution/xml/sax/Attributes.java | 178 ++
.../java/javolution/xml/sax/ContentHandler.java | 144 ++
.../java/javolution/xml/sax/DefaultHandler.java | 116 ++
.../java/javolution/xml/sax/SAX2ReaderImpl.java | 386 ++++
.../ext/java/javolution/xml/sax/XMLReader.java | 346 ++++
.../java/javolution/xml/sax/XMLReaderImpl.java | 363 ++++
.../java/javolution/xml/sax/package-info.java | 8 +
.../java/javolution/xml/stream/Location.java | 56 +
.../javolution/xml/stream/NamespaceContext.java | 55 +
.../javolution/xml/stream/XMLInputFactory.java | 150 ++
.../javolution/xml/stream/XMLOutputFactory.java | 169 ++
.../xml/stream/XMLStreamConstants.java | 98 +
.../xml/stream/XMLStreamException.java | 128 ++
.../javolution/xml/stream/XMLStreamReader.java | 604 ++++++
.../javolution/xml/stream/XMLStreamWriter.java | 365 ++++
.../javolution/xml/stream/package-info.java | 17 +
.../javolution/xml/ws/WebServiceClient.java | 223 +++
.../java/javolution/xml/ws/package-info.java | 5 +
.../commons/sesame/model/StatementCommons.java | 169 +-
.../collections/EquivalenceHashSet2Test.java | 62 +
.../collections/EquivalenceHashSetTest.java | 136 ++
.../kiwi/reasoner/engine/ReasoningEngine.java | 68 +-
.../reasoner/model/program/Justification.java | 12 +-
.../test/engine/ReasoningEngineTest.java | 3 +
.../KiWiRDFSchemaRepositoryConnectionTest.java | 1 +
.../kiwi/persistence/KiWiConnection.java | 2 +-
.../kiwi/persistence/KiWiPersistence.java | 5 +-
.../kiwi/model/caching/TripleTable.java | 2 +-
199 files changed, 34925 insertions(+), 84 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/pom.xml
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/pom.xml b/commons/marmotta-commons/pom.xml
index b0b9dfe..890d36a 100644
--- a/commons/marmotta-commons/pom.xml
+++ b/commons/marmotta-commons/pom.xml
@@ -28,6 +28,52 @@
<artifactId>marmotta-commons</artifactId>
<name>Apache Marmotta: Common Utilities</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.7</version>
+ <executions>
+ <execution>
+ <id>add-ext</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src/ext/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>add-ext-test</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <inherited>false</inherited>
+ <configuration>
+ <sources>
+ <source>src/ext-test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src/ext/resources</directory>
+ </resource>
+ </resources>
+ </build>
+
+
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
@@ -83,6 +129,28 @@
<scope>test</scope>
</dependency>
+ <!-- for fast hash sets and maps with custom equivalence relations -->
+
+ <!-- TODO: for now we use the source code in ext/ because it contains some bug fixes -->
+ <!--
+ <dependency>
+ <groupId>org.javolution</groupId>
+ <artifactId>javolution-core-java</artifactId>
+ <version>6.0.1-SNAPSHOT</version>
+ </dependency>
+ -->
+
+ <!-- OSGi dependencies for Javolution -->
+ <dependency> <!-- OSGI Core Library -->
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>4.3.1</version>
+ </dependency>
+ <dependency> <!-- OSGI Compendium (log service) -->
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>4.3.1</version>
+ </dependency>
</dependencies>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext-test/java/javolution/util/FastTableTest.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext-test/java/javolution/util/FastTableTest.java b/commons/marmotta-commons/src/ext-test/java/javolution/util/FastTableTest.java
new file mode 100644
index 0000000..bee5ca0
--- /dev/null
+++ b/commons/marmotta-commons/src/ext-test/java/javolution/util/FastTableTest.java
@@ -0,0 +1,331 @@
+/*
+ * 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 java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Random;
+
+import javolution.context.LogContext;
+import javolution.osgi.internal.OSGiServices;
+import javolution.test.Perfometer;
+
+/**
+ * Validation and performance tests of FastTable.
+ */
+public class FastTableTest {
+
+ static final boolean INITIALIZE_REALTIME_CLASSES = OSGiServices
+ .initializeRealtimeClasses();
+
+ @SuppressWarnings("rawtypes")
+ Perfometer<Class<? extends List>> addPerf = new Perfometer<Class<? extends List>>(
+ "java.util.List#add(Object)") {
+ List<Object> list;
+
+ @SuppressWarnings("unchecked")
+ public void initialize() throws Exception {
+ list = getInput().newInstance();
+ }
+
+ protected void run(boolean measure) {
+ Object obj = new Object();
+ if (measure) list.add(obj);
+ }
+ };
+
+ @SuppressWarnings("rawtypes")
+ Perfometer<Class<? extends List>> insertPerf = new Perfometer<Class<? extends List>>(
+ "java.util.List#add(int, Object)") {
+ List<Object> list;
+ Random random;
+
+ @SuppressWarnings("unchecked")
+ public void initialize() throws Exception {
+ list = getInput().newInstance();
+ random = new Random(-1);
+ }
+
+ protected void run(boolean measure) {
+ Object obj = new Object();
+ int i = random.nextInt(list.size() + 1);
+ if (measure) list.add(i, obj);
+ }
+
+ protected void validate() {
+ assert list.size() == getNbrOfIterations();
+ }
+ };
+
+ @SuppressWarnings("rawtypes")
+ Perfometer<Class<? extends List>> newPerf = new Perfometer<Class<? extends List>>(
+ "new java.util.List()") {
+ Class<? extends List> cls;
+
+ protected void initialize() throws Exception {
+ cls = getInput();
+ }
+
+ protected void run(boolean measure) throws Exception {
+ if (measure) cls.newInstance();
+ }
+ };
+
+ @SuppressWarnings("rawtypes")
+ Perfometer<Class<? extends List>> removePerf = new Perfometer<Class<? extends List>>(
+ "java.util.List#remove(int)") {
+ List<Object> list;
+ Random random;
+
+ @SuppressWarnings("unchecked")
+ public void initialize() throws Exception {
+ list = getInput().newInstance();
+ random = new Random(-1);
+ for (int i = 0; i < getNbrOfIterations(); i++) {
+ list.add(new Object());
+ }
+ }
+
+ protected void run(boolean measure) {
+ int i = random.nextInt(list.size());
+ if (measure) list.remove(i);
+ }
+
+ protected void validate() {
+ assert list.size() == 0;
+ }
+ };
+
+ private final long ONE_SECOND_IN_NS = 1000 * 1000 * 1000L;
+ private Random random = new Random();
+
+ public void testDequeuOperations() {
+ Deque<Integer> ft = new FastTable<Integer>();
+ Deque<Integer> ad = new ArrayDeque<Integer>();
+ for (long start = System.nanoTime(), time = start; time < start + 2
+ * ONE_SECOND_IN_NS; time = System.nanoTime()) {
+ long seed = random.nextLong();
+ Throwable found = anyDequeOperation(seed, ft);
+ Throwable expected = anyDequeOperation(seed, ad);
+ assertEquals(found, expected);
+ assert areEquals(ad, ft) : found.getMessage() + "\nFound: " + ft
+ + "\nExpected: " + ad;
+ }
+ LogContext.info("FastTable - Deque Operations Validated!");
+ }
+
+ public void testListOperations() {
+ List<Integer> ft = new FastTable<Integer>();
+ List<Integer> al = new ArrayList<Integer>();
+ for (long start = System.nanoTime(), time = start; time < start + 2
+ * ONE_SECOND_IN_NS; time = System.nanoTime()) {
+ long seed = random.nextLong();
+ Throwable found = anyListOperation(seed, ft);
+ Throwable expected = anyListOperation(seed, al);
+ assertEquals(found, expected);
+ assert al.equals(ft) && ft.equals(al) : found.getMessage()
+ + "\nFound: " + ft + "\nExpected: " + al;
+ }
+ LogContext.info("FastTable - List Operations Validated!");
+ }
+
+ public void testPerformance() {
+ int N = 10000;
+ newPerf.measure(ArrayList.class, 1).print();
+ newPerf.measure(LinkedList.class, 1).print();
+ newPerf.measure(FastTable.class, 1).print();
+ addPerf.measure(ArrayList.class, N).print();
+ addPerf.measure(LinkedList.class, N).print();
+ addPerf.measure(FastTable.class, N).print();
+ insertPerf.measure(ArrayList.class, N).print();
+ insertPerf.measure(LinkedList.class, N).print();
+ insertPerf.measure(FastTable.class, N).print();
+ removePerf.measure(ArrayList.class, N).print();
+ removePerf.measure(LinkedList.class, N).print();
+ removePerf.measure(FastTable.class, N).print();
+ }
+
+ private Throwable anyDequeOperation(long seed, Deque<Integer> deque) {
+ random.setSeed(seed);
+ int operation = random.nextInt(20);
+ String test = "N/A";
+ try {
+ switch (operation) {
+ case 1: {
+ test = "Test add(E)";
+ deque.add(random.nextInt());
+ break;
+ }
+ case 2: {
+ test = "Test addFirst(E)";
+ deque.addFirst(random.nextInt());
+ break;
+ }
+ case 3: {
+ test = "Test addLast(E)";
+ deque.addLast(random.nextInt());
+ break;
+ }
+ case 4: {
+ test = "Test removeFirst(E)";
+ deque.removeFirst();
+ break;
+ }
+ case 5: {
+ test = "Test removeLast(E)";
+ deque.removeLast();
+ break;
+ }
+ case 6: {
+ test = "Test peekFirst/peekLast/element/pop/push/pollFirst/pollLast";
+ deque.push(random.nextInt());
+ deque.addFirst(deque.peekLast());
+ deque.addLast(deque.peekFirst());
+ deque.add(deque.element());
+ deque.addFirst(deque.pop());
+ deque.push(random.nextInt());
+ deque.addLast(deque.pollFirst());
+ deque.addFirst(deque.pollLast());
+ break;
+ }
+ case 7: {
+ test = "Test descendingIterator";
+ int obj = random.nextInt();
+ for (Iterator<Integer> i = deque.descendingIterator(); i
+ .hasNext(); i.next()) {
+ if (random.nextInt(deque.size()) == 0) obj = i.next();
+ }
+ deque.add(obj);
+ break;
+ }
+ default:
+ if (deque.size() > 100000) deque.clear();
+ deque.add(random.nextInt());
+ }
+ } catch (Throwable error) {
+ return error;
+ }
+ return new Throwable(test);
+ }
+
+ private Throwable anyListOperation(long seed, List<Integer> list) {
+ random.setSeed(seed);
+ int operation = random.nextInt(20);
+ String test = "N/A";
+ try {
+ switch (operation) {
+ case 1: {
+ test = "Test add(int, E)";
+ int i = random.nextInt(list.size() + 1);
+ list.add(i, random.nextInt());
+ break;
+ }
+ case 2: {
+ test = "Test remove(int)";
+ int i = random.nextInt(list.size());
+ list.remove(i);
+ break;
+ }
+ case 3: {
+ test = "Test add(E)";
+ list.add(random.nextInt());
+ break;
+ }
+ case 4: {
+ test = "Test contains(Object)";
+ int r = random.nextInt();
+ int i = random.nextInt(list.size() + 1);
+ list.add(i, r);
+ list.add(list.contains(r) ? 1 : 0);
+ break;
+ }
+ case 5: {
+ test = "Test indexOf/lastIndexOf";
+ int r = random.nextInt();
+ list.add(random.nextInt(list.size() + 1), r);
+ list.add(random.nextInt(list.size() + 1), r);
+ int first = list.indexOf(r);
+ int last = list.lastIndexOf(r);
+ list.add(first);
+ list.add(last);
+ break;
+ }
+ case 6: {
+ test = "Test subList/addAll";
+ int s = list.size();
+ int i = random.nextInt(s);
+ int j = random.nextInt(s);
+ if (i > j) break; // ArrayList throw IllegalArgumentException instead of
+ // IndexOutOfBoundsException (which is incorrect as per List.subList contract).
+ list.addAll(list.subList(i, j));
+ break;
+ }
+ case 7: {
+ test = "Test subList/clear";
+ int s = list.size();
+ int i = random.nextInt(s);
+ int j = random.nextInt(s);
+ if (i > j) break;
+ list.subList(i, j).clear();
+ break;
+ }
+ case 8: {
+ test = "Test subList/containsAll";
+ int s = list.size();
+ int i = random.nextInt(s);
+ int j = random.nextInt(s);
+ if (i > j) break;
+ boolean containsAll = list.containsAll(list.subList(i, j));
+ list.add(containsAll ? 1 : 0);
+ break;
+ }
+ case 9: {
+ test = "Test iterator";
+ int j = 0;
+ for (ListIterator<Integer> i = list.listIterator(); i
+ .hasNext(); i.next()) {
+ if (random.nextInt(list.size()) == 0) j = i.next();
+ if (random.nextInt(list.size()) == 0) j = i.previous();
+ if (random.nextInt(list.size()) == 0) i.remove();
+ }
+ list.add(j);
+ break;
+ }
+ default:
+ if (list.size() > 100000) list.clear();
+ list.add(random.nextInt());
+ }
+ } catch (Throwable error) {
+ return error;
+ }
+ return new Throwable(test);
+ }
+
+ private boolean areEquals(Deque<?> left, Deque<?> right) {
+ if (left.size() != right.size()) return false;
+ for (Iterator<?> il = left.iterator(), ir = right.iterator(); il
+ .hasNext();) {
+ if (!il.next().equals(ir.next())) return false;
+ }
+ return true;
+ }
+
+ private void assertEquals(Throwable found, Throwable expected) {
+ if (found.getClass().equals(expected.getClass())) return;
+ found.printStackTrace(System.err);
+ expected.printStackTrace(System.err);
+ assert false : "Exception mismatch found: " + found + ", expected: "
+ + expected;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javax/realtime/RealtimeThread.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javax/realtime/RealtimeThread.java b/commons/marmotta-commons/src/ext/java/javax/realtime/RealtimeThread.java
new file mode 100644
index 0000000..9823076
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javax/realtime/RealtimeThread.java
@@ -0,0 +1,13 @@
+package javax.realtime;
+/**
+ * Stub version (replaced by the actual class on RTSJ VM).
+ */
+public class RealtimeThread extends Thread {
+
+ /**
+ * Default constructor.
+ */
+ public RealtimeThread() {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/AbstractContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/AbstractContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/AbstractContext.java
new file mode 100644
index 0000000..3258d53
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/AbstractContext.java
@@ -0,0 +1,178 @@
+/*
+ * 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.context;
+
+import javolution.lang.Parallelizable;
+import javolution.context.SecurityContext.Permission;
+import javolution.lang.Realtime;
+
+/**
+ * <p> The parent class for all contexts.
+ * Contexts allow for cross cutting concerns (performance, logging,
+ * security, ...) to be addressed at run-time through OSGi published
+ * services without polluting the application code
+ * (<a href="http://en.wikipedia.org/wiki/Separation_of_concerns">
+ * Separation of Concerns</a>).</p>
+ *
+ * <p> Context configuration is performed in a {@code try, finally}
+ * block statement and impacts only the current thread (although inherited
+ * by inner {@link ConcurrentContext} threads).
+ * [code]
+ * AnyContext ctx = AnyContext.enter(); // Enters a context scope.
+ * try {
+ * ctx.configure(...); // Local configuration (optional).
+ * ... // Current thread executes using the configured context.
+ * } finally {
+ * ctx.exit();
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+@Realtime
+@Parallelizable(comment = "Sequential configuration, parallel use")
+public abstract class AbstractContext {
+
+ /**
+ * Holds the last context entered (thread-local).
+ */
+ private static final ThreadLocal<AbstractContext> CURRENT = new ThreadLocal<AbstractContext>();
+
+ /**
+ * Holds the outer context or {@code null} if none (top context).
+ */
+ private AbstractContext outer;
+
+ /**
+ * Default constructor.
+ */
+ protected AbstractContext() {}
+
+ /**
+ * Returns the current context for the current thread or {@code null}
+ * if this thread has no context (default).
+ */
+ public static AbstractContext current() {
+ return AbstractContext.CURRENT.get();
+ }
+
+ /**
+ * Returns the current context of specified type or {@code null} if none.
+ */
+ @SuppressWarnings("unchecked")
+ protected static <T extends AbstractContext> T current(Class<T> type) {
+ AbstractContext ctx = AbstractContext.CURRENT.get();
+ while (ctx != null) {
+ if (type.isInstance(ctx))
+ return (T) ctx;
+ ctx = ctx.outer;
+ }
+ return null;
+ }
+
+ /**
+ * <p> Enters the scope of a custom context. This method raises a
+ * {@link SecurityException} if the permission to enter contexts of
+ * the specified class is not granted. For example, the following
+ * disallow entering any custom context.
+ *[code]
+ * SecurityContext ctx = SecurityContext.enter();
+ * try {
+ * ctx.revoke(new SecurityContext.Permission(AbstractContext.class, "enter"));
+ * ... // Cannot enter any custom context.
+ * } finally {
+ * ctx.exit(); // Back to previous security settings.
+ * }[/code]</p>
+ *
+ * @param custom the custom context to enter.
+ * @throws IllegalArgumentException if the specified class default constructor
+ * cannot be instantiated.
+ * @throws SecurityException if {@code SecurityContext.Permission(custom, "enter")}
+ * is not granted.
+ * @see SecurityContext.Permission
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends AbstractContext> T enter(Class<T> custom) {
+ SecurityContext.check(new Permission<T>(custom, "enter"));
+ try {
+ return (T) custom.newInstance().enterInner();
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException(
+ "Cannot instantiate instance of " + custom, e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Cannot access " + custom, e);
+ }
+ }
+
+ /**
+ * Inherits the specified context which becomes the context of the current
+ * thread. This method is particularly useful when creating new threads to
+ * make them inherits from the context stack of the parent thread.
+ * [code]
+ * //Spawns a new thread inheriting the context of the current thread.
+ * MyThread myThread = new MyThread();
+ * myThread.inherited = AbstractContext.current();
+ * myThread.start();
+ * ...
+ * class MyThread extends Thread {
+ * AbstractContext inherited;
+ * public void run() {
+ * AbstractContext.inherit(inherited); // Sets current context.
+ * ...
+ * }
+ * }[/code]</p>
+ */
+ public static void inherit(AbstractContext ctx) {
+ CURRENT.set(ctx);
+ }
+
+ /**
+ * Enters the scope of an inner context which becomes the current context;
+ * the previous current context becomes the outer of this context.
+ *
+ * @return the inner context entered.
+ */
+ protected AbstractContext enterInner() {
+ AbstractContext inner = inner();
+ inner.outer = AbstractContext.CURRENT.get();
+ AbstractContext.CURRENT.set(inner);
+ return inner;
+ }
+
+ /**
+ * Exits the scope of this context; the outer of this context becomes
+ * the current context.
+ *
+ * @throws IllegalStateException if this context is not the current
+ * context.
+ */
+ public void exit() {
+ if (this != AbstractContext.CURRENT.get())
+ throw new IllegalStateException(
+ "This context is not the current context");
+ AbstractContext.CURRENT.set(outer);
+ outer = null;
+ }
+
+ /**
+ * Returns the outer context of this context or {@code null} if this
+ * context has no outer context.
+ */
+ protected AbstractContext getOuter() {
+ return outer;
+ }
+
+ /**
+ * Returns a new inner instance of this context inheriting the properties
+ * of this context. The new instance can be configured independently
+ * from its parent.
+ */
+ protected abstract AbstractContext inner();
+
+}
\ 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/context/ConcurrentContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/ConcurrentContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/ConcurrentContext.java
new file mode 100644
index 0000000..8e1442a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/ConcurrentContext.java
@@ -0,0 +1,258 @@
+/*
+ * 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.context;
+
+import javolution.lang.Configurable;
+import javolution.lang.MathLib;
+import javolution.osgi.internal.OSGiServices;
+
+/**
+ * <p> A context able to take advantage of concurrent algorithms on
+ * multi-processors systems.</p>
+ *
+ * <p> When a thread enters a concurrent context, it may performs concurrent
+ * executions by calling the {@link #execute(Runnable)} static method.
+ * The logic is then executed by a concurrent thread or by the current
+ * thread itself if there is no concurrent thread immediately available
+ * (the number of concurrent threads is limited, see {@link #CONCURRENCY}).
+ * [code]
+ * ConcurrentContext ctx = ConcurrentContext.enter();
+ * try {
+ * ctx.execute(new Runnable() {...});
+ * ctx.execute(new Runnable() {...});
+ * } finally {
+ * ctx.exit(); // Waits for all concurrent executions to complete.
+ * // Re-exports any exception raised during concurrent executions.
+ * }[/code]</p>
+ *
+ * <p> or equivalent shorter notation:
+ * [code]
+ * ConcurrentContext.execute(new Runnable() {...}, new Runnable() {...});[/code]</p>
+ *
+ * <p> Only after all concurrent executions are completed, is the current
+ * thread allowed to exit the scope of the concurrent context
+ * (internal synchronization).</p>
+ *
+ * <p> Concurrent logics always execute within the same {@link AbstractContext
+ * context} as the calling thread.</p>
+ *
+ * <p> Concurrent contexts ensure the same behavior whether or not the execution
+ * is performed by the current thread or a concurrent thread. Any error or
+ * runtime exception raised during the concurrent logic executions is
+ * propagated to the current thread.</p>
+ *
+ * <p> Concurrent contexts are easy to use, and provide automatic
+ * load-balancing between processors with almost no overhead.
+ * Here is a concurrent/recursive quick/merge sort using anonymous inner
+ * classes.
+ * [code]
+ * static void concurrentSort(final FastTable<? extends Comparable> table) {
+ * final int size = table.size();
+ * if (size < 100) {
+ * table.sort(); // Direct quick sort.
+ * } else {
+ * // Splits table in two and sort both part concurrently.
+ * final FastTable<? extends Comparable> t1 = new FastTable();
+ * final FastTable<? extends Comparable> t2 = new FastTable();
+ * ConcurrentContext ctx = ConcurrentContext.enter();
+ * try {
+ * ctx.execute(new Runnable() {
+ * public void run() {
+ * t1.addAll(table.subList(0, size / 2));
+ * concurrentSort(t1); // Recursive.
+ * }
+ * });
+ * ctx.execute(new Runnable() {
+ * public void run() {
+ * t2.addAll(table.subList(size / 2, size));
+ * concurrentSort(t2); // Recursive.
+ * }
+ * });
+ * } finally {
+ * ctx.exit(); // Joins.
+ * }
+ * // Merges results.
+ * for (int i=0, i1=0, i2=0; i < size; i++) {
+ * if (i1 >= t1.size()) {
+ * table.set(i, t2.get(i2++));
+ * } else if (i2 >= t2.size()) {
+ * table.set(i, t1.get(i1++));
+ * } else {
+ * Comparable o1 = t1.get(i1);
+ * Comparable o2 = t2.get(i2);
+ * if (o1.compareTo(o2) < 0) {
+ * table.set(i, o1);
+ * i1++;
+ * } else {
+ * table.set(i, o2);
+ * i2++;
+ * }
+ * }
+ * }
+ * }
+ * }[/code]</p>
+ *
+ * <p> Here is another example using {@link #execute(java.lang.Runnable[])
+ * execute(Runnable ...)} static method
+ * (Karatsuba recursive multiplication for large integers).
+ * [code]
+ * public LargeInteger times(LargeInteger that) {
+ * if (that._size <= 1) {
+ * return times(that.longValue()); // Direct multiplication.
+ * } else { // Karatsuba multiplication in O(n^log2(3))
+ * int bitLength = this.bitLength();
+ * int n = (bitLength >> 1) + (bitLength & 1);
+ *
+ * // this = a + 2^n b, that = c + 2^n d
+ * LargeInteger b = this.shiftRight(n);
+ * LargeInteger a = this.minus(b.shiftLeft(n));
+ * LargeInteger d = that.shiftRight(n);
+ * LargeInteger c = that.minus(d.shiftLeft(n));
+ * Multiply ac = new Multiply(a, c);
+ * Multiply bd = new Multiply(b, d);
+ * Multiply abcd = new Multiply(a.plus(b), c.plus(d));
+ * ConcurrentContext.execute(ac, bd, abcd); // Convenience method.
+ * // a*c + ((a+b)*(c+d)-a*c-b*d) 2^n + b*d 2^2n
+ * return ac.result.plus(abcd.result.minus(ac.result.plus(bd.result)).shiftWordLeft(n))
+ * .plus(bd.result.shiftWordLeft(n << 1));
+ * }
+ * }
+ * private static class Multiply implements Runnable {
+ * LargeInteger left, right, result;
+ * Multiply(LargeInteger left, LargeInteger right) {
+ * this.left = left;
+ * this.right = right;
+ * }
+ * public void run() {
+ * result = left.times(right); // Recursive.
+ * }
+ * }[/code]</p>
+ *
+ * <p> Concurrency can be adjusted or disabled. The default concurrency
+ * is defined by the {@link #CONCURRENCY} configurable.
+ * [code]
+ * ConcurrentContext ctx = ConcurrentContext.enter();
+ * try {
+ * ctx.setConcurrency(0); // Disables concurrency
+ * runAnalysis(); // Performs analysis sequentially.
+ * } finally {
+ * ctx.exit(); // Back to previous concurrency settings.
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+public abstract class ConcurrentContext extends AbstractContext {
+
+ /**
+ * Holds the maximum concurrency
+ * (default {@code Runtime.getRuntime().availableProcessors() - 1}).
+ * The maximum concurrency is configurable. For example, the JVM option
+ * {@code -Djavolution.context.ConcurrentContext#CONCURRENCY=0}
+ * disables concurrency.
+ */
+ public static final Configurable<Integer> CONCURRENCY = new Configurable<Integer>() {
+ @Override
+ protected Integer getDefault() {
+ return Runtime.getRuntime().availableProcessors() - 1;
+ }
+
+ @Override
+ protected Integer initialized(Integer value) {
+ return MathLib.min(value, 65536); // Hard-limiting
+ }
+
+ @Override
+ protected Integer reconfigured(Integer oldCount, Integer newCount) {
+ throw new UnsupportedOperationException(
+ "Concurrency reconfiguration not supported.");
+ }
+ };
+
+ /**
+ * Default constructor.
+ */
+ protected ConcurrentContext() {}
+
+ /**
+ * Enters and returns a new concurrent context instance.
+ */
+ public static ConcurrentContext enter() {
+ ConcurrentContext ctx = current(ConcurrentContext.class);
+ if (ctx == null) { // Root.
+ ctx = OSGiServices.getConcurrentContext();
+ }
+ return (ConcurrentContext) ctx.enterInner();
+ }
+
+ /**
+ * Convenience method to executes the specified logics concurrently.
+ * This method is equivalent to:
+ * [code]
+ * ConcurrentContext ctx = ConcurrentContext.enter();
+ * try {
+ * ctx.execute(logics[0]);
+ * ctx.execute(logics[1]);
+ * ...
+ * } finally {
+ * ctx.exit();
+ * }[/code]
+ *
+ * @param logics the logics to execute concurrently if possible.
+ */
+ public static void execute(Runnable... logics) {
+ ConcurrentContext ctx = ConcurrentContext.enter();
+ try {
+ for (Runnable logic : logics) {
+ ctx.execute(logic);
+ }
+ } finally {
+ ctx.exit();
+ }
+ }
+
+ /**
+ * Executes the specified logic by a concurrent thread if
+ * one available; otherwise the logic is executed by the current thread.
+ * Any exception or error occurring during the concurrent execution is
+ * propagated to the current thread upon exit of the concurrent context.
+ *
+ * @param logic the logic to be executed concurrently when possible.
+ */
+ public abstract void execute(Runnable logic);
+
+ /**
+ * Sets the maximum concurrency. Setting a value greater than the
+ * {@link #getConcurrency() current concurrency} has no effect
+ * (concurrency can only be reduced).
+ */
+ public abstract void setConcurrency(int concurrency);
+
+ /**
+ * Returns the current concurrency which is basically the number of
+ * concurrent threads authorized to do concurrent work (on top of all
+ * others threads of course).
+ */
+ public abstract int getConcurrency();
+
+ /**
+ * Exits the scope of this concurrent context; this method blocks until
+ * all the concurrent executions are completed.
+ *
+ * @throws RuntimeException re-exports any exception raised during concurrent
+ * executions.
+ * @throws Error re-exports any error raised during concurrent executions.
+ * @throws IllegalStateException if this context is not the current
+ * context.
+ */
+ @Override
+ public void exit() { // Redefine here for documentation purpose.
+ super.exit();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/FormatContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/FormatContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/FormatContext.java
new file mode 100644
index 0000000..a17b595
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/FormatContext.java
@@ -0,0 +1,39 @@
+/*
+ * 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.context;
+
+/**
+ * <p> The parent class for all serializer/deserializer contexts.
+ * The context format type (plain text, XML, JSON, ...) is specified by
+ * sub-classes. Classes may identify the plain text format through the
+ * {@link javolution.text.DefaultTextFormat DefaultTextFormat} annotation
+ * or the default XML format through the
+ * {@link javolution.xml.DefaultXMLFormat DefaultXMLFormat} annotation.
+ * [code]
+ * @DefaultTextFormat(Complex.Cartesian.class)
+ * @DefaultXMLFormat(Complex.XML.class)
+ * public Complex {
+ * public static final class Cartesian extends javolution.text.TextFormat<Complex> { ... }
+ * public static final class Polar extends javolution.text.TextFormat<Complex> { ... }
+ * public static final class XML extends javolution.text.XMLFormat<Complex> { ... }
+ * ...
+ * }
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+public abstract class FormatContext extends AbstractContext {
+
+ /**
+ * Default constructor.
+ */
+ protected FormatContext() {}
+
+}
\ 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/context/LocalContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/LocalContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/LocalContext.java
new file mode 100644
index 0000000..e4c5c28
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/LocalContext.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.context;
+
+import javolution.context.SecurityContext.Permission;
+import javolution.lang.Configurable;
+import javolution.osgi.internal.OSGiServices;
+
+/**
+ * <p> A context holding locally scoped {@link Parameter parameters} values.</p>
+ * <p> For example, when performing modulo arithmetics the actual modulo
+ * being used is usually the same for most operations and does not need
+ * to be specified for each operation.
+ * [code]
+ * import javolution.context.LocalContext.Parameter;
+ * public class ModuloInteger extends Number {
+ * public static final Parameter<Integer> MODULO = new Parameter<Integer>() {
+ * protected Integer getDefault() { return -1; }
+ * };
+ * public ModuloInteger times(ModuloInteger that) { ... }
+ * }
+ * LocalContext ctx = LocalContext.enter();
+ * try {
+ * ctx.supersede(ModuloInteger.MODULO, 13); // Sets local modulo value.
+ * x = a.times(b).plus(c.times(d)); // Operations modulo 13
+ * ...
+ * } finally {
+ * ctx.exit(); // Reverts to previous modulo setting.
+ * }[/code]</p>
+ *
+ * <p> As for any context, local context settings are inherited during
+ * {@link ConcurrentContext} executions.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+public abstract class LocalContext extends AbstractContext {
+
+ /**
+ * A {@link Configurable configurable} parameter whose value can
+ * be locally superseded within the scope of {@link LocalContext}.</p>
+ */
+ public static abstract class Parameter<T> extends Configurable<T> {
+
+ /**
+ * Holds the general permission to supersede any parameter value
+ * (action "supersede").
+ */
+ public static final Permission<Parameter<?>> SUPERSEDE_PERMISSION = new Permission<Parameter<?>>(
+ Parameter.class, "supersede");
+
+ /**
+ * Holds this instance supersede permission.
+ */
+ private final Permission<Parameter<T>> supersedePermission;
+
+ /**
+ * Creates a new parameter (configurable).
+ */
+ public Parameter() {
+ this.supersedePermission = new Permission<Parameter<T>>(
+ Parameter.class, "supersede", this);
+ }
+
+ /**
+ * Returns the permission to locally supersede the current value
+ * of this instance.
+ */
+ public Permission<Parameter<T>> getSupersedePermission() {
+ return supersedePermission;
+ }
+
+ /**
+ * Returns the current parameter value (the default value if not
+ * reconfigured nor {@link LocalContext#supersede superseded}).
+ */
+ public T get() {
+ LocalContext ctx = current(LocalContext.class);
+ return (ctx != null) ? ctx.getValue(this, super.get()) : super.get();
+ }
+ }
+
+ /**
+ * Default constructor.
+ */
+ protected LocalContext() {}
+
+ /**
+ * Enters and returns a new local context instance.
+ */
+ public static LocalContext enter() {
+ LocalContext ctx = current(LocalContext.class);
+ if (ctx == null) { // Root.
+ ctx = OSGiServices.getLocalContext();
+ }
+ return (LocalContext) ctx.enterInner();
+ }
+
+ /**
+ * Supersedes the value of the specified parameter.
+ *
+ * @param param the local parameter whose local value is overridden.
+ * @param localValue the new local value.
+ * @throws SecurityException if the permission to override the specified
+ * parameter is not granted.
+ * @throws NullPointerException if the specified local value is {@code null}.
+ */
+ public abstract <T> void supersede(Parameter<T> param, T localValue);
+
+ /**
+ * Returns the local value of the specified parameter or the specified
+ * default value if not {@link LocalContext#supersede superseded}.
+ *
+ * @param param the local parameter whose local value is returned.
+ * @param defaultValue the parameter value if not superseded.
+ */
+ protected abstract <T> T getValue(Parameter<T> param, T defaultValue);
+
+}
\ 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/context/LogContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/LogContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/LogContext.java
new file mode 100644
index 0000000..2856244
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/LogContext.java
@@ -0,0 +1,157 @@
+/*
+ * 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.context;
+
+import javolution.lang.Configurable;
+import javolution.osgi.internal.OSGiServices;
+import javolution.text.TextContext;
+
+/**
+ * <p> Asynchronous logging context integrated with the OSGi logging framework.
+ * The logging back-end, or how the log entries are displayed, stored, or
+ * processed is unspecified but always performed asynchronously.
+ * When running outside OSGi, log messages are sent to {@link System#out}.
+ * Message formatting itself is always performed synchronously using the
+ * current {@link TextContext}.</p>
+ *
+ * <p> Logging contexts support automatic prefixing/suffixing of any information
+ * relevant to the user/developer (thread info, user id, and so on).
+ * [code]
+ * void run() {
+ * LogContext ctx = LogContext.enter();
+ * try {
+ * // Prefix the executing thread to any message being logged.
+ * ctx.prefix("[Thread: ", Thead.currentThread(), "] ");
+ * ...
+ * } finally {
+ * ctx.exit();
+ * }
+ * }[/code]</p>
+ *
+ * <p> Applications should separate messages elements by commas and not
+ * use {@link String} concatenations when calling log methods otherwise
+ * the concatenation is performed even when log events are filtered out.
+ * [code]
+ * LogContext ctx = LogContext.enter();
+ * try {
+ * ctx.setLevel(Level.INFO); // Does not log debug messages.
+ * ...
+ * LogContext.debug("Index: ", index, " at maximum value"); // GOOD, no formatting performed !
+ * LogContext.debug("Index: " + index + " at maximum value"); // BAD, formatting performed even though nothing is logged !
+ * ...
+ * } finally {
+ * ctx.exit();
+ * }[/code]</p>
+ *
+ * <p> In general, the {@link Level#DEBUG} level provides information only
+ * relevant to developers and can be turned off after deployment.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see <a href="https://code.google.com/p/osgi-logging/wiki/UnderstandingTheOSGiLogging">Understanding OSGi Logging</a>
+ */
+public abstract class LogContext extends AbstractContext {
+
+ /**
+ * Defines the logging levels.
+ */
+ public enum Level {
+
+ DEBUG, INFO, WARNING, ERROR, FATAL
+
+ }
+
+ /**
+ * Holds the default logging level (<code>DEBUG</code>).
+ * This level is configurable. For example, running with
+ * the option <code>-Djavolution.context.LogContext#LEVEL=WARNING</code>
+ * causes the debug/info not to be logged.
+ */
+ public static final Configurable<Level> LEVEL = new Configurable<Level>() {
+ @Override
+ protected Level getDefault() {
+ return Level.DEBUG;
+ }
+ @Override
+ public Level parse(String str) {
+ return Level.valueOf(str);
+ }
+ };
+
+ /**
+ * Logs the specified debug message.
+ */
+ public static void debug(Object... message) {
+ currentLogContext().log(Level.DEBUG, message);
+ }
+
+ /**
+ * Enters and returns a new log context instance.
+ */
+ public static LogContext enter() {
+ return (LogContext) currentLogContext().enterInner();
+ }
+
+ /**
+ * Logs the specified error message (which may include any {@link Throwable}
+ * instance).
+ */
+ public static void error(Object... message) {
+ currentLogContext().log(Level.ERROR, message);
+ }
+
+ /**
+ * Logs the specified info message.
+ */
+ public static void info(Object... message) {
+ currentLogContext().log(Level.INFO, message);
+ }
+
+ /**
+ * Logs the specified warning message.
+ */
+ public static void warning(Object... message) {
+ currentLogContext().log(Level.WARNING, message);
+ }
+
+ private static LogContext currentLogContext() {
+ LogContext ctx = current(LogContext.class);
+ if (ctx != null)
+ return ctx;
+ return OSGiServices.getLogContext();
+ }
+
+ /**
+ * Default constructor.
+ */
+ protected LogContext() {}
+
+ /**
+ * Prefixes all messages being logged by the specified prefixes
+ * (prefixing existing prefixes if any).
+ */
+ public abstract void prefix(Object... prefixes);
+
+ /**
+ * Set the logging level, messages below that level are not logged.
+ */
+ public abstract void setLevel(Level level);
+
+ /**
+ * Suffixes all messages being logged by the specified suffixes
+ * (suffixing existing suffixes if any).
+ */
+ public abstract void suffix(Object... suffixes);
+
+ /**
+ * Logs the specified message at the specified level.
+ */
+ protected abstract void log(Level level, Object... message);
+
+}
\ 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/context/SecurityContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/SecurityContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/SecurityContext.java
new file mode 100644
index 0000000..6fab057
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/SecurityContext.java
@@ -0,0 +1,256 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2007 - 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.context;
+
+import javolution.osgi.internal.OSGiServices;
+
+/**
+ * <p> A high-level security context integrated with OSGi.</p>
+ *
+ * <p> When granting/revoking permission the order is important.
+ * For example, the following code revokes all configurable permissions
+ * except for setting the concurrency level.
+ * [code]
+ * SecurityContext ctx = SecurityContext.enter();
+ * try {
+ * ctx.revoke(Configurable.RECONFIGURE_PERMISSION);
+ * ctx.grant(ConcurrentContext.CONCURRENCY.getReconfigurePermission());
+ * ...
+ * ConcurrentContext.CONCURRENCY.reconfigure(0); // Ok (permission specifically granted).
+ * ...
+ * } finally {
+ * ctx.exit(); // Back to previous security settings.
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public abstract class SecurityContext extends AbstractContext {
+
+ /**
+ * A permission associated to a specific class/action/instance.
+ * There are three levels of permission possible, at
+ * the class/category level, at the action level and at the instance level.
+ * Any permission granted/revoked at the higher level is explicitly
+ * granted/revoked at the lower level. The order in which the permission
+ * are granted/revoked is important. For example, it is possible to grant
+ * a permission at the class level, then to revoke it at the action or
+ * instance level. In which case, for that class the permission is granted
+ * for all actions/instances except for those actions/instances for which the
+ * permission has been explicitly revoked.
+ */
+ public static class Permission<T> {
+
+ /**
+ * Holds the global permission for anything.
+ */
+ public static final Permission<Object> ALL = new Permission<Object>(
+ null);
+
+ private final Class<? super T> category;
+
+ private final String action;
+
+ private final T instance;
+
+ /**
+ * Creates a security permission for all actions of the specified category.
+ */
+ public Permission(Class<? super T> category) {
+ this(category, null, null);
+ }
+
+ /**
+ * Creates a security permission for the specified action of the
+ * specified category.
+ */
+ public Permission(Class<? super T> category, String action) {
+ this(category, action, null);
+ }
+
+ /**
+ * Creates a security permission for the specified instance and the
+ * specified action of the specified category.
+ */
+ public Permission(Class<? super T> category, String action, T instance) {
+ this.category = category;
+ this.action = action;
+ this.instance = instance;
+ }
+
+ /**
+ * Returns the permission category or <code>null</code> for all categories.
+ */
+ public Class<? super T> getCategory() {
+ return category;
+ }
+
+ /**
+ * Returns the permission action or <code>null</code> for all actions.
+ */
+ public String getAction() {
+ return action;
+ }
+
+ /**
+ * Returns the permission instance or <code>null</code> for all instances.
+ */
+ public T getInstance() {
+ return instance;
+ }
+
+ /**
+ * Checks if the specified permission is automatically granted/revoked
+ * by 'this' permission being granted/revoked.
+ *
+ * @param that the permission to check.
+ * @return <code>true</code> if this permission being granted/revoked
+ * implies that the specified permission is granted/revoked;
+ * <code>false</code> otherwise.
+ */
+ public boolean implies(Permission<?> that) {
+ if (category == null)
+ return true;
+ if (!category.isAssignableFrom(that.category))
+ return false;
+ if (action == null)
+ return true;
+ if (!action.equals(that.action))
+ return false;
+ if (instance == null)
+ return true;
+ if (!instance.equals(that.instance))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ if (category == null)
+ return "All permissions";
+ if (action == null)
+ return "Permission for any action on " + category.getName();
+ if (instance == null)
+ return "Permission for " + action + " on " + category.getName();
+ return "Permission for " + action + " on instance " + instance
+ + " of " + category.getName();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (!(obj instanceof Permission))
+ return false;
+ Permission<?> that = (Permission<?>) obj;
+ if ((category == null) && (that.category != null))
+ return false;
+ if ((category != null) && (!category.equals(that.category)))
+ return false;
+ if ((action == null) && (that.action != null))
+ return false;
+ if ((action != null) && (!action.equals(that.action)))
+ return false;
+ if ((instance == null) && (that.instance != null))
+ return false;
+ if ((instance != null) && (!instance.equals(that.instance)))
+ return false;
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (category != null ? category.hashCode() : 0)
+ + (action != null ? action.hashCode() : 0)
+ + (instance != null ? instance.hashCode() : 0);
+ }
+ }
+
+ /**
+ * Default constructor.
+ */
+ protected SecurityContext() {}
+
+ /**
+ * Enters and returns a new security context instance.
+ *
+ * @return the new security context implementation entered.
+ */
+ public static SecurityContext enter() {
+ return (SecurityContext) currentSecurityContext().enterInner();
+ }
+
+ /**
+ * Checks if the specified permission is granted.
+ *
+ * @param permission the permission to check.
+ * @throws SecurityException if the specified permission is not granted.
+ */
+ public static void check(Permission<?> permission) {
+ if (!currentSecurityContext().isGranted(permission))
+ throw new SecurityException(permission + " is not granted.");
+ }
+
+ /**
+ * Indicates if the specified permission is granted.
+ *
+ * @param permission the permission to check.
+ */
+ public abstract boolean isGranted(Permission<?> permission);
+
+ /**
+ * Grants the specified permission.
+ *
+ * @param permission the permission to grant.
+ * @param certificate the certificate used to grant that permission or
+ * <code>null</code> if none.
+ * @throws SecurityException if the specified permission cannot be granted.
+ */
+ public abstract void grant(Permission<?> permission, Object certificate);
+
+ /**
+ * Revokes the specified permission.
+ *
+ * @param permission the permission to grant.
+ * @param certificate the certificate used to grant that permission or
+ * <code>null</code> if none.
+ * @throws SecurityException if the specified permission cannot be revoked.
+ */
+ public abstract void revoke(Permission<?> permission, Object certificate);
+
+ /**
+ * Grants the specified permission (convenience method).
+ *
+ * @param permission the permission to grant.
+ * @throws SecurityException if the specified permission cannot be granted.
+ */
+ public final void grant(Permission<?> permission) {
+ grant(permission, null);
+ }
+
+ /**
+ * Revokes the specified permission (convenience method).
+ *
+ * @param permission the permission to grant.
+ * @throws SecurityException if the specified permission cannot be revoked.
+ */
+ public final void revoke(Permission<?> permission) {
+ revoke(permission, null);
+ }
+
+ /**
+ * Returns the current security context.
+ */
+ private static SecurityContext currentSecurityContext() {
+ SecurityContext ctx = current(SecurityContext.class);
+ if (ctx != null)
+ return ctx;
+ return OSGiServices.getSecurityContext();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/StorageContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/StorageContext.java b/commons/marmotta-commons/src/ext/java/javolution/context/StorageContext.java
new file mode 100644
index 0000000..fe7cdba
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/StorageContext.java
@@ -0,0 +1,125 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2007 - 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.context;
+
+import java.io.File;
+import java.io.Serializable;
+
+import javolution.lang.Configurable;
+import javolution.osgi.internal.OSGiServices;
+
+/**
+ * <p> A context for persistent storage integrated with OSGi and
+ * {@link SecurityContext}.</p>
+ *
+ * <p> How the data is going to be stored (database, files) is implementation
+ * dependent. But how the resources are structured (hierarchical, semantics)
+ * is defined by the client implementing the {@link Resource} class.
+ * [code]
+ * class SemanticResource<T> extends SemanticEntity implements Resource<T> { ... }
+ * ...
+ * StorageContext ctx = StorageContext.enter(); // Enters the current storage service.
+ * try {
+ * // Stores resource.
+ * SemanticResource<Image> logoId = new SemanticResource<Image>(
+ * "http://purl.org/goodrelations/v1#Logo|MyCompany");
+ * ctx.write(logoId, logoImg); // May raise SecurityException.
+ * ...
+ * // Retrieves resource.
+ * Image logoImg = ctx.read(logoId); // May raise SecurityException.
+ * } finally {
+ * ctx.exit();
+ * }[/code]</p>
+ *
+ * <p> Permission to read/write resource values may or not be granted at all
+ * or only for particular resources. Sensitive data should always be
+ * encrypted (e.g. using a {@code SecuredStorageContext} sub-class).
+ * There is no limit in the size of the data being stored (except the actual
+ * storage available). It is nonetheless recommended to split large data
+ * set in smaller resources to allow for partial/concurrent retrieval.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public abstract class StorageContext extends AbstractContext {
+
+ /**
+ * Holds the default storage location for file based-implementations
+ * (default {@code new File("storage")}).
+ */
+ public static final Configurable<File> FILE_STORAGE_LOCATION = new Configurable<File>() {
+ @Override
+ protected File getDefault() {
+ return new File("storage");
+ }
+
+ protected File parse(String pathname) {
+ return new File(pathname);
+ }
+ };
+
+ /**
+ * A resource identifier.
+ *
+ * @param <T> The resource type (the type of the value stored).
+ */
+ public interface Resource<T> {
+
+ /**
+ * Returns an unique identifier for this resource.
+ */
+ public String uniqueID();
+
+ }
+
+ /**
+ * Default constructor.
+ */
+ protected StorageContext() {}
+
+ /**
+ * Enters and returns a storage context instance.
+ */
+ public static StorageContext enter() {
+ return (StorageContext) currentStorageContext().enterInner();
+ }
+
+ /**
+ * Reads the persistent value of the specified resource value.
+ *
+ * @param resource the entity whose persistent value is returned.
+ * @return the resource value or <code>null</code> if none.
+ * @throws SecurityException if the permission to read the resource
+ * is not granted ({@code new
+ * Permission<Resource<V>>(Resource.class, "read", resource)}).
+ */
+ public abstract <V extends Serializable> V read(Resource<V> resource)
+ throws SecurityException;
+
+ /**
+ * Writes the persistent value of the specified resource.
+ *
+ * @param resource the entity whose persistent value is stored.
+ * @param value the persistent value.
+ * @throws SecurityException if the permission to write the resource
+ * is not granted ({@code new
+ * Permission<Resource<V>>(Resource.class, "write", resource)}).
+ */
+ public abstract <V extends Serializable> void write(Resource<V> resource,
+ V value) throws SecurityException;
+
+ /**
+ * Returns the current storage context.
+ */
+ private static StorageContext currentStorageContext() {
+ StorageContext ctx = current(StorageContext.class);
+ if (ctx != null) return ctx;
+ return OSGiServices.getStorageContext();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentContextImpl.java
new file mode 100644
index 0000000..1a3d341
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentContextImpl.java
@@ -0,0 +1,120 @@
+/*
+ * 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.context.internal;
+
+import javolution.context.ConcurrentContext;
+import javolution.lang.MathLib;
+
+/**
+ * Holds the default implementation of ConcurrentContext.
+ */
+public final class ConcurrentContextImpl extends ConcurrentContext {
+
+ private int completedCount; // Nbr of concurrent task completed.
+ private Throwable error; // Any error raised.
+
+ private int initiatedCount; // Nbr of concurrent task initiated.
+ private final ConcurrentContextImpl parent;
+ private ConcurrentThreadImpl[] threads;
+ private int lastThreadInitiated; // Holds index of the last thread initiated.
+
+ /**
+ * Default constructor (root).
+ */
+ public ConcurrentContextImpl() {
+ this.parent = null;
+ int nbThreads = ConcurrentContext.CONCURRENCY.get();
+ threads = new ConcurrentThreadImpl[nbThreads];
+ for (int i = 0; i < nbThreads; i++) {
+ threads[i] = new ConcurrentThreadImpl();
+ threads[i].start();
+ }
+ }
+
+ /**
+ * Inner implementation.
+ */
+ public ConcurrentContextImpl(ConcurrentContextImpl parent) {
+ this.parent = parent;
+ this.threads = parent.threads; // Inherit threads from parents.
+ }
+
+ // Informs this context of the completion of a task (with possible error).
+ public synchronized void completed(Throwable error) {
+ if (error != null) {
+ this.error = error;
+ }
+ completedCount++;
+ this.notify();
+ }
+
+ @Override
+ public void execute(Runnable logic) {
+ if (threads.length > 0) {
+ int i = lastThreadInitiated;
+ while (true) { // Searches available thread.
+ i++;
+ if (i >= threads.length) i = 0;
+ if (threads[i].execute(logic, this)) {
+ initiatedCount++;
+ lastThreadInitiated = i;
+ return;
+ }
+ if (i == lastThreadInitiated) break; // Cycled through.
+ }
+ }
+ // No concurrent thread to do the job, lets do it ourself.
+ try {
+ logic.run();
+ } catch (Throwable e) {
+ error = e;
+ }
+ }
+
+ @Override
+ public synchronized void exit() {
+ super.exit();
+ try {
+ while (initiatedCount != completedCount) {
+ this.wait();
+ }
+ } catch (InterruptedException ex) {
+ this.error = ex;
+ }
+ if (error == null)
+ return; // Everything fine.
+ if (error instanceof RuntimeException)
+ throw (RuntimeException) error;
+ if (error instanceof Error)
+ throw (Error) error;
+ throw new RuntimeException(error);
+ }
+
+ @Override
+ public int getConcurrency() {
+ return threads.length;
+ }
+
+ @Override
+ public void setConcurrency(int concurrency) {
+ // The setting of the concurrency can only reduce the number
+ // of threads available in the context.
+ int nbThreads = MathLib.min(parent.threads.length, concurrency);
+ threads = new ConcurrentThreadImpl[nbThreads];
+ for (int i = 0; i < nbThreads; i++) { // Reused from parent threads.
+ threads[i] = parent.threads[i];
+ }
+ }
+
+ @Override
+ protected ConcurrentContext inner() {
+ return new ConcurrentContextImpl(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentThreadImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentThreadImpl.java b/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentThreadImpl.java
new file mode 100644
index 0000000..78ca5c4
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/internal/ConcurrentThreadImpl.java
@@ -0,0 +1,74 @@
+/*
+ * 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.context.internal;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.realtime.RealtimeThread;
+
+import javolution.context.AbstractContext;
+
+/**
+ * A worker thread executing in a concurrent context.
+ */
+public class ConcurrentThreadImpl extends RealtimeThread {
+
+ private static int count;
+ private ConcurrentContextImpl context;
+ private AtomicBoolean isBusy = new AtomicBoolean();
+ private Runnable logic;
+ private int priority;
+
+ /**
+ * Default constructor.
+ */
+ public ConcurrentThreadImpl() {
+ this.setName("ConcurrentThread-" + ++count);
+ setDaemon(true);
+ }
+
+ /**
+ * Executes the specified logic by this thread if ready; returns
+ * {@code false} if this thread is busy.
+ */
+ public boolean execute(Runnable logic, ConcurrentContextImpl inContext) {
+ if (!isBusy.compareAndSet(false, true))
+ return false;
+ synchronized (this) {
+ this.priority = Thread.currentThread().getPriority();
+ this.context = inContext;
+ this.logic = logic;
+ this.notify();
+ }
+ return true;
+ }
+
+ @Override
+ public void run() {
+ while (true) { // Main loop.
+ try {
+ synchronized (this) {
+ while (logic == null) this.wait();
+ }
+ this.setPriority(priority);
+ AbstractContext.inherit(context);
+ logic.run();
+ context.completed(null);
+ } catch (Throwable error) {
+ context.completed(error);
+ }
+ // Clean up.
+ logic = null;
+ context = null;
+ AbstractContext.inherit(null);
+ isBusy.set(false);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/internal/LocalContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/internal/LocalContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/context/internal/LocalContextImpl.java
new file mode 100644
index 0000000..ff8685d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/internal/LocalContextImpl.java
@@ -0,0 +1,44 @@
+/*
+ * 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.context.internal;
+
+import javolution.context.LocalContext;
+import javolution.util.FastMap;
+
+/**
+ * Holds the default implementation of LocalContext.
+ */
+public final class LocalContextImpl extends LocalContext {
+
+ private FastMap<Parameter<?>, Object> localSettings = new FastMap<Parameter<?>, Object>();
+ private LocalContextImpl parent;
+
+ @Override
+ protected LocalContext inner() {
+ LocalContextImpl ctx = new LocalContextImpl();
+ ctx.parent = this;
+ return ctx;
+ }
+
+ @Override
+ public <T> void supersede(Parameter<T> param, T localValue) {
+ if (localValue == null) throw new NullPointerException();
+ localSettings.put(param, localValue);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> T getValue(Parameter<T> param, T defaultValue) {
+ Object value = localSettings.get(param);
+ if (value != null) return (T) value;
+ if (parent != null) return parent.getValue(param, defaultValue);
+ return defaultValue;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/internal/LogContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/internal/LogContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/context/internal/LogContextImpl.java
new file mode 100644
index 0000000..3005d03
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/internal/LogContextImpl.java
@@ -0,0 +1,91 @@
+/*
+ * 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.context.internal;
+
+import javolution.context.LogContext;
+import javolution.osgi.internal.OSGiServices;
+import javolution.text.TextBuilder;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * The default implementation of LogContext.
+ */
+public final class LogContextImpl extends LogContext {
+
+ private static final Object[] NONE = new Object[0];
+ private static final int[] TO_OSGI_LEVEL = { LogService.LOG_DEBUG,
+ LogService.LOG_INFO, LogService.LOG_WARNING, LogService.LOG_ERROR };
+
+ private Level level; // Null to use configurable LEVEL.
+ private Object[] prefix = NONE;
+ private Object[] suffix = NONE;
+
+ @Override
+ public void prefix(Object... pfx) {
+ Object[] tmp = new Object[prefix.length + pfx.length];
+ System.arraycopy(pfx, 0, tmp, 0, pfx.length);
+ System.arraycopy(prefix, 0, tmp, pfx.length, prefix.length);
+ prefix = tmp;
+ }
+
+ @Override
+ public void setLevel(Level level) {
+ this.level = level;
+ }
+
+ @Override
+ public void suffix(Object... sfx) {
+ Object[] tmp = new Object[suffix.length + sfx.length];
+ System.arraycopy(suffix, 0, tmp, 0, suffix.length);
+ System.arraycopy(sfx, 0, tmp, suffix.length, sfx.length);
+ suffix = tmp;
+ }
+
+ @Override
+ protected LogContext inner() {
+ LogContextImpl ctx = new LogContextImpl();
+ ctx.prefix = prefix;
+ ctx.suffix = suffix;
+ ctx.level = level;
+ return ctx;
+ }
+
+ @Override
+ protected void log(Level level, Object... message) {
+ if (level.compareTo(currentLevel()) < 0)
+ return;
+ TextBuilder tmp = new TextBuilder();
+ Throwable exception = null;
+ for (Object pfx : prefix) {
+ tmp.append(pfx); // Uses TextContext for formatting.
+ }
+ for (Object obj : message) {
+ if ((exception == null) && (obj instanceof Throwable)) {
+ exception = (Throwable) obj;
+ } else {
+ tmp.append(obj); // Uses TextContext for formatting.
+ }
+ }
+ for (Object sfx : suffix) {
+ tmp.append(sfx); // Uses TextContext for formatting.
+ }
+ int osgiLevel = TO_OSGI_LEVEL[level.ordinal()];
+ String msg = tmp.toString();
+ Object[] logServices = OSGiServices.getLogServices();
+ for (Object logService : logServices) {
+ ((LogService)logService).log(osgiLevel, msg, exception);
+ }
+ }
+ private Level currentLevel() {
+ if (LEVEL == null) return Level.DEBUG; // Only during class initialization.
+ if (level == null) return LEVEL.get();
+ return level;
+ }
+}
[03/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamWriterImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamWriterImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamWriterImpl.java
new file mode 100644
index 0000000..4305189
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamWriterImpl.java
@@ -0,0 +1,939 @@
+/*
+ * 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.xml.internal.stream;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+
+import javolution.io.UTF8StreamWriter;
+import javolution.lang.Realtime;
+import javolution.text.CharArray;
+import javolution.text.TextBuilder;
+import javolution.xml.stream.XMLOutputFactory;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class represents an implementation of {@link XMLStreamWriter}.</p>
+ *
+ * <p> The <code>writeCharacters</code> methods will escape & , < and
+ * >. For attribute values, the <code>writeAttribute</code> methods will
+ * escape the above characters plus " and control characters.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+@Realtime
+public final class XMLStreamWriterImpl implements XMLStreamWriter {
+
+ /**
+ * Holds the length of intermediate buffer.
+ */
+ private static final int BUFFER_LENGTH = 2048;
+
+ /**
+ * Holds the current nesting level.
+ */
+ private int _nesting = 0;
+
+ /**
+ * Holds the element qualified name (indexed per nesting level)
+ */
+ private TextBuilder[] _qNames = new TextBuilder[16];
+
+ /**
+ * Indicates if the current element is open.
+ */
+ private boolean _isElementOpen;
+
+ /**
+ * Indicates if the current element is an empty element.
+ */
+ private boolean _isEmptyElement;
+
+ /**
+ * Holds intermediate buffer.
+ */
+ private final char[] _buffer = new char[BUFFER_LENGTH];
+
+ /**
+ * Holds the namespace stack.
+ */
+ private final NamespacesImpl _namespaces = new NamespacesImpl();
+
+ /**
+ * Holds the buffer current index.
+ */
+ private int _index;
+
+ /**
+ * Holds repairing namespace property.
+ */
+ private boolean _isRepairingNamespaces;
+
+ /**
+ * Holds repairing prefix property.
+ */
+ private String _repairingPrefix = "ns";
+
+ /**
+ * Holds indentation property.
+ */
+ private String _indentation;
+
+ /**
+ * Holds line separator property.
+ */
+ private String _lineSeparator = "\n";
+
+ /**
+ * Holds current indentation level.
+ */
+ private int _indentationLevel;
+
+ /**
+ * Holds automatic empty elements property.
+ */
+ private boolean _automaticEmptyElements;
+
+ /**
+ * Holds no empty element tag property.
+ */
+ private boolean _noEmptyElementTag;
+
+ /**
+ * Holds counter for automatic namespace generation.
+ */
+ private int _autoNSCount;
+
+ /**
+ * Indicates if the current object written is an attribute value.
+ */
+ private boolean _isAttributeValue;
+
+ ////////////////////////
+ // Temporary Settings //
+ ////////////////////////
+
+ /**
+ * Holds the writer destination (<code>null</code> when unused).
+ */
+ private Writer _writer;
+
+ /**
+ * Holds the encoding (<code>null</code> if N/A).
+ */
+ private String _encoding;
+
+ /**
+ * Holds the default writer for output streams.
+ */
+ private final UTF8StreamWriter _utf8StreamWriter = new UTF8StreamWriter();
+
+ /**
+ * Holds the factory (if any)
+ */
+ private final XMLOutputFactoryImpl _factory;
+
+ /**
+ * Default constructor.
+ */
+ public XMLStreamWriterImpl() {
+ this(null);
+ }
+
+ /**
+ * Factory-based constructor.
+ */
+ XMLStreamWriterImpl(XMLOutputFactoryImpl factory) {
+ _factory = factory;
+ for (int i = 0; i < _qNames.length;) {
+ _qNames[i++] = new TextBuilder();
+ }
+ }
+
+ /**
+ * Sets the output stream destination for this XML stream writer
+ * (UTF-8 encoding).
+ *
+ * @param out the output source with utf-8 encoding.
+ */
+ public void setOutput(OutputStream out) throws XMLStreamException {
+ _utf8StreamWriter.setOutput(out);
+ _encoding = "UTF-8";
+ setOutput(_utf8StreamWriter);
+ }
+
+ /**
+ * Sets the output stream destination and encoding for this XML stream
+ * writer.
+ *
+ * @param out the output source.
+ * @param encoding the associated encoding.
+ * @throws XMLStreamException if the specified encoding is not supported.
+ */
+ public void setOutput(OutputStream out, String encoding)
+ throws XMLStreamException {
+ if (encoding.equals("UTF-8") || encoding.equals("utf-8")
+ || encoding.equals("ASCII")) {
+ setOutput(out); // Default encoding.
+ } else {
+ try {
+ _encoding = encoding;
+ setOutput(new OutputStreamWriter(out, encoding));
+ } catch (UnsupportedEncodingException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+ }
+
+ /**
+ * Sets the writer output destination for this XML stream writer.
+ *
+ * @param writer the output destination writer.
+ * @see javolution.io.UTF8StreamWriter
+ * @see javolution.io.UTF8ByteBufferWriter
+ * @see javolution.io.AppendableWriter
+ */
+ public void setOutput(Writer writer) throws XMLStreamException {
+ if (_writer != null)
+ throw new IllegalStateException("Writer not closed or reset");
+ _writer = writer;
+ }
+
+ /**
+ * Requires this writer to create a new prefix when a namespace has none
+ * (default <code>false</code>).
+ *
+ * @param isRepairingNamespaces <code>true</code> if namespaces
+ * are repaired; <code>false</code> otherwise.
+ */
+ public void setRepairingNamespaces(boolean isRepairingNamespaces) {
+ _isRepairingNamespaces = isRepairingNamespaces;
+ }
+
+ /**
+ * Specifies the prefix to be append by a trailing part
+ * (a sequence number) in order to make it unique to be usable as
+ * a temporary non-colliding prefix when repairing namespaces
+ * (default <code>"ns"</code>).
+ *
+ * @param repairingPrefix the prefix root.
+ */
+ public void setRepairingPrefix(String repairingPrefix) {
+ _repairingPrefix = repairingPrefix;
+ }
+
+ /**
+ * Specifies the indentation string; non-null indentation
+ * forces the writer to write elements into separate lines
+ * (default <code>null</code>).
+ *
+ * @param indentation the indentation string.
+ */
+ public void setIndentation(String indentation) {
+ _indentation = indentation;
+ }
+
+ /**
+ * Specifies the line separator (default <code>"\n"</code>).
+ *
+ * @param lineSeparator the line separator string.
+ */
+ public void setLineSeparator(String lineSeparator) {
+ _lineSeparator = lineSeparator;
+ }
+
+ /**
+ * Requires this writer to automatically output empty elements when a
+ * start element is immediately followed by matching end element
+ * (default <code>false</code>).
+ *
+ * @param automaticEmptyElements <code>true</code> if start element
+ * immediately followed by end element results in an empty element
+ * beign written; <code>false</code> otherwise.
+ */
+ public void setAutomaticEmptyElements(boolean automaticEmptyElements) {
+ _automaticEmptyElements = automaticEmptyElements;
+ }
+
+ /**
+ * Prevent this writer from using empty element tags
+ * (default <code>false</code>).
+ *
+ * @param noEmptyElementTag <code>true</code> if empty element tags
+ * are replaced by start/end elements with no content;
+ * <code>false</code> otherwise.
+ */
+ public void setNoEmptyElementTag(boolean noEmptyElementTag) {
+ _noEmptyElementTag = noEmptyElementTag;
+ }
+
+ // Implements reusable.
+ public void reset() {
+ _automaticEmptyElements = false;
+ _autoNSCount = 0;
+ _encoding = null;
+ _indentation = null;
+ _indentationLevel = 0;
+ _index = 0;
+ _isAttributeValue = false;
+ _isElementOpen = false;
+ _isEmptyElement = false;
+ _isRepairingNamespaces = false;
+ _namespaces.reset();
+ _nesting = 0;
+ _noEmptyElementTag = false;
+ _repairingPrefix = "ns";
+ _utf8StreamWriter.reset();
+ _writer = null;
+
+ if (_factory != null)
+ _factory.recycle(this);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeStartElement(CharSequence localName)
+ throws XMLStreamException {
+ if (localName == null)
+ throw new XMLStreamException("Local name cannot be null");
+ writeNewElement(null, localName, null);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeStartElement(CharSequence namespaceURI,
+ CharSequence localName) throws XMLStreamException {
+ if (localName == null)
+ throw new XMLStreamException("Local name cannot be null");
+ if (namespaceURI == null)
+ throw new XMLStreamException("Namespace URI cannot be null");
+ writeNewElement(null, localName, namespaceURI);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeStartElement(CharSequence prefix, CharSequence localName,
+ CharSequence namespaceURI) throws XMLStreamException {
+ if (localName == null)
+ throw new XMLStreamException("Local name cannot be null");
+ if (namespaceURI == null)
+ throw new XMLStreamException("Namespace URI cannot be null");
+ if (prefix == null)
+ throw new XMLStreamException("Prefix cannot be null");
+ writeNewElement(prefix, localName, namespaceURI);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeEmptyElement(CharSequence localName)
+ throws XMLStreamException {
+ writeStartElement(localName);
+ _isEmptyElement = true;
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeEmptyElement(CharSequence namespaceURI,
+ CharSequence localName) throws XMLStreamException {
+ writeStartElement(namespaceURI, localName);
+ _isEmptyElement = true;
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeEmptyElement(CharSequence prefix, CharSequence localName,
+ CharSequence namespaceURI) throws XMLStreamException {
+ writeStartElement(prefix, localName, namespaceURI);
+ _isEmptyElement = true;
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeEndElement() throws XMLStreamException {
+ if (_isElementOpen) { // Empty element.
+ if (_isEmptyElement) { // Closes the empty element tag.
+ closeOpenTag();
+ } else { // Start element open.
+ if (_automaticEmptyElements) { // Do as if empty element written.
+ _isEmptyElement = true;
+ closeOpenTag();
+ return;
+ } else { // Closes the start element tag.
+ closeOpenTag();
+ }
+ }
+ }
+ if ((_indentation != null) && (_indentationLevel != _nesting - 1)) {
+ // Do not indent if no change in indentation level
+ // to avoid interfering with text only elements.
+ writeNoEscape(_lineSeparator);
+ for (int i = 1; i < _nesting; i++) {
+ writeNoEscape(_indentation);
+ }
+ }
+
+ write('<');
+ write('/');
+ writeNoEscape(_qNames[_nesting--]);
+ write('>');
+ _namespaces.pop();
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeEndDocument() throws XMLStreamException {
+ if (_isElementOpen)
+ closeOpenTag();
+ while (_nesting > 0) { // Implicits closing of all elements.
+ writeEndElement();
+ }
+ flush(); // Not mandatory but safer.
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void close() throws XMLStreamException {
+ if (_writer != null) {
+ if (_nesting != 0) { // Closes all elements.
+ writeEndDocument();
+ }
+ flush();
+ }
+ reset(); // Explicit reset.
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void flush() throws XMLStreamException {
+ flushBuffer();
+ try {
+ _writer.flush();
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeAttribute(CharSequence localName, CharSequence value)
+ throws XMLStreamException {
+ if (localName == null)
+ throw new XMLStreamException("Local name cannot be null");
+ if (value == null)
+ throw new XMLStreamException("Value cannot be null");
+ writeAttributeOrNamespace(null, null, localName, value);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeAttribute(CharSequence namespaceURI,
+ CharSequence localName, CharSequence value)
+ throws XMLStreamException {
+ if (localName == null)
+ throw new XMLStreamException("Local name cannot be null");
+ if (value == null)
+ throw new XMLStreamException("Value cannot be null");
+ if (namespaceURI == null)
+ throw new XMLStreamException("Namespace URI cannot be null");
+ writeAttributeOrNamespace(null, namespaceURI, localName, value);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeAttribute(CharSequence prefix, CharSequence namespaceURI,
+ CharSequence localName, CharSequence value)
+ throws XMLStreamException {
+ if (localName == null)
+ throw new XMLStreamException("Local name cannot be null");
+ if (value == null)
+ throw new XMLStreamException("Value cannot be null");
+ if (namespaceURI == null)
+ throw new XMLStreamException("Namespace URI cannot be null");
+ if (prefix == null)
+ throw new XMLStreamException("Prefix cannot be null");
+ writeAttributeOrNamespace(prefix, namespaceURI, localName, value);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeNamespace(CharSequence prefix, CharSequence namespaceURI)
+ throws XMLStreamException {
+ if ((prefix == null) || (prefix.length() == 0)
+ || _namespaces._xmlns.equals(prefix)) {
+ prefix = _namespaces._defaultNsPrefix;
+ }
+ if (!_isElementOpen) // Check now as the actual writting is queued.
+ throw new IllegalStateException("No open start element");
+ _namespaces.setPrefix(prefix,
+ (namespaceURI == null) ? _namespaces._nullNsURI : namespaceURI,
+ true);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeDefaultNamespace(CharSequence namespaceURI)
+ throws XMLStreamException {
+ writeNamespace(_namespaces._defaultNsPrefix, namespaceURI);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeComment(CharSequence data) throws XMLStreamException {
+ if (_isElementOpen)
+ closeOpenTag();
+ writeNoEscape("<!--");
+ if (data != null) { // null values allowed.
+ writeNoEscape(data);
+ }
+ writeNoEscape("-->");
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeProcessingInstruction(CharSequence target)
+ throws XMLStreamException {
+ writeProcessingInstruction(target, _noChar);
+ }
+
+ private final CharArray _noChar = new CharArray("");
+
+ // Implements XMLStreamWriter interface.
+ public void writeProcessingInstruction(CharSequence target,
+ CharSequence data) throws XMLStreamException {
+ if (target == null)
+ throw new XMLStreamException("Target cannot be null");
+ if (data == null)
+ throw new XMLStreamException("Data cannot be null");
+ if (_isElementOpen)
+ closeOpenTag();
+ writeNoEscape("<?");
+ writeNoEscape(target);
+ write(' ');
+ writeNoEscape(data);
+ writeNoEscape(" ?>");
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeCData(CharSequence data) throws XMLStreamException {
+ if (data == null)
+ throw new XMLStreamException("Data cannot be null");
+ if (_isElementOpen)
+ closeOpenTag();
+ writeNoEscape("<![CDATA[");
+ writeNoEscape(data);
+ writeNoEscape("]]>");
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeDTD(CharSequence dtd) throws XMLStreamException {
+ if (dtd == null)
+ throw new XMLStreamException("DTD cannot be null");
+ if (_nesting > 0)
+ throw new XMLStreamException(
+ "DOCTYPE declaration (DTD) when not in document root (prolog)");
+ writeNoEscape(dtd);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeEntityRef(CharSequence name) throws XMLStreamException {
+ write('&');
+ writeNoEscape(name);
+ write(';');
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeStartDocument() throws XMLStreamException {
+ writeStartDocument(null, null);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeStartDocument(CharSequence version)
+ throws XMLStreamException {
+ writeStartDocument(null, version);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeStartDocument(CharSequence encoding, CharSequence version)
+ throws XMLStreamException {
+ if (_nesting > 0)
+ throw new XMLStreamException("Not in document root");
+ writeNoEscape("<?xml version=\"");
+ if (version != null) {
+ writeNoEscape(version);
+ write('"');
+ } else { // Default to 1.0
+ writeNoEscape("1.0\"");
+ }
+ if (encoding != null) {
+ writeNoEscape(" encoding=\"");
+ writeNoEscape(encoding);
+ write('"');
+ } else if (_encoding != null) { // Use init encoding (if any).
+ writeNoEscape(" encoding=\"");
+ writeNoEscape(_encoding);
+ write('"');
+ }
+ writeNoEscape(" ?>");
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeCharacters(CharSequence text) throws XMLStreamException {
+ if (_isElementOpen)
+ closeOpenTag();
+ if (text == null)
+ return;
+ writeEscape(text);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void writeCharacters(char[] text, int start, int length)
+ throws XMLStreamException {
+ _tmpCharArray.setArray(text, start, length);
+ writeCharacters(_tmpCharArray);
+ }
+
+ private final CharArray _tmpCharArray = new CharArray();
+
+ // Implements XMLStreamWriter interface.
+ public CharSequence getPrefix(CharSequence uri) throws XMLStreamException {
+ return _namespaces.getPrefix(uri);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void setPrefix(CharSequence prefix, CharSequence uri)
+ throws XMLStreamException {
+ _namespaces.setPrefix(prefix, (uri == null) ? _namespaces._nullNsURI
+ : uri, false);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public void setDefaultNamespace(CharSequence uri) throws XMLStreamException {
+ setPrefix(_namespaces._defaultNsPrefix, uri);
+ }
+
+ // Implements XMLStreamWriter interface.
+ public Object getProperty(String name) throws IllegalArgumentException {
+ if (name.equals(XMLOutputFactory.IS_REPAIRING_NAMESPACES)) {
+ return new Boolean(_isRepairingNamespaces);
+ } else if (name.equals(XMLOutputFactory.REPAIRING_PREFIX)) {
+ return _repairingPrefix;
+ } else if (name.equals(XMLOutputFactory.AUTOMATIC_EMPTY_ELEMENTS)) {
+ return new Boolean(_automaticEmptyElements);
+ } else if (name.equals(XMLOutputFactory.NO_EMPTY_ELEMENT_TAG)) {
+ return new Boolean(_noEmptyElementTag);
+ } else if (name.equals(XMLOutputFactory.INDENTATION)) {
+ return _indentation;
+ } else if (name.equals(XMLOutputFactory.LINE_SEPARATOR)) {
+ return _lineSeparator;
+ } else {
+ throw new IllegalArgumentException("Property: " + name
+ + " not supported");
+ }
+ }
+
+ // Writes a new start or empty element.
+ private void writeNewElement(CharSequence prefix, CharSequence localName,
+ CharSequence namespaceURI) throws XMLStreamException {
+
+ // Close any open element and gets ready to write a new one.
+ if (_isElementOpen)
+ closeOpenTag();
+ if (_indentation != null) {
+ writeNoEscape(_lineSeparator);
+ _indentationLevel = _nesting;
+ for (int i = 0; i < _indentationLevel; i++) {
+ writeNoEscape(_indentation);
+ }
+ }
+ write('<');
+ _isElementOpen = true;
+
+ // Enters a new local scope.
+ if (++_nesting >= _qNames.length)
+ resizeElemStack();
+ _namespaces.push();
+
+ // Constructs qName.
+ TextBuilder qName = _qNames[_nesting].clear();
+
+ // Writes prefix if any.
+ if ((namespaceURI != null)
+ && (!_namespaces._defaultNamespace.equals(namespaceURI))) {
+ if (_isRepairingNamespaces) { // Repairs prefix.
+ prefix = getRepairedPrefix(prefix, namespaceURI);
+ } else if (prefix == null) { // Retrieves prefix.
+ prefix = getPrefix(namespaceURI);
+ if (prefix == null)
+ throw new XMLStreamException("URI: " + namespaceURI
+ + " not bound and repairing namespaces disabled");
+ }
+ if (prefix.length() > 0) {
+ qName.append(prefix);
+ qName.append(':');
+ }
+ }
+ qName.append(localName);
+ writeNoEscape(qName);
+ }
+
+ // Writes a new attribute.
+ private void writeAttributeOrNamespace(CharSequence prefix,
+ CharSequence namespaceURI, CharSequence localName,
+ CharSequence value) throws XMLStreamException {
+ if (!_isElementOpen)
+ throw new IllegalStateException("No open start element");
+ write(' ');
+
+ // Writes prefix if any.
+ if ((namespaceURI != null)
+ && (!_namespaces._defaultNamespace.equals(namespaceURI))) {
+ if (_isRepairingNamespaces) { // Repairs prefix if current prefix is not correct.
+ prefix = getRepairedPrefix(prefix, namespaceURI);
+ } else if (prefix == null) {
+ prefix = getPrefix(namespaceURI);
+ if (prefix == null)
+ throw new XMLStreamException("URI: " + namespaceURI
+ + " not bound and repairing namespaces disabled");
+ }
+ if (prefix.length() > 0) {
+ writeNoEscape(prefix);
+ write(':');
+ }
+ }
+
+ writeNoEscape(localName);
+ write('=');
+ write('"');
+ _isAttributeValue = true;
+ writeEscape(value);
+ _isAttributeValue = false;
+ write('"');
+ }
+
+ // Closes the current element (scope if empty element).
+ private void closeOpenTag() throws XMLStreamException {
+
+ // Writes namespaces now.
+ writeNamespaces();
+
+ // Closes the tag.
+ _isElementOpen = false;
+ if (_isEmptyElement) {
+ if (_noEmptyElementTag) {
+ write('<');
+ write('/');
+ writeNoEscape(_qNames[_nesting]);
+ write('>');
+ } else { // Use empty element tag.
+ write('/');
+ write('>');
+ }
+ _nesting--;
+ _namespaces.pop();
+ _isEmptyElement = false;
+ } else {
+ write('>');
+ }
+ }
+
+ // Writes all namespaces, these include namespaces set but
+ // not written in outer scope.
+ private void writeNamespaces() throws XMLStreamException {
+ int i0 = (_nesting > 1) ? _namespaces._namespacesCount[_nesting - 2]
+ : NamespacesImpl.NBR_PREDEFINED_NAMESPACES;
+ int i1 = _namespaces._namespacesCount[_nesting - 1];
+ int i2 = _namespaces._namespacesCount[_nesting];
+ for (int i = i0; i < i2; i++) {
+ if (((_isRepairingNamespaces && (i < i1) && !_namespaces._prefixesWritten[i]))
+ || ((i >= i1) && _namespaces._prefixesWritten[i])) { // Write namespace.
+
+ // In repairing mode, removes redondancy.
+ if (_isRepairingNamespaces) {
+ CharArray prefix = _namespaces.getPrefix(
+ _namespaces._namespaces[i], i);
+ if (_namespaces._prefixes[i].equals(prefix))
+ continue; // Not necessary.
+ } // Direct mode, just write them as requested (no check).
+
+ // Writes namespace.
+ if (_namespaces._prefixes[i].length() == 0) { // Default namespace.
+ writeAttributeOrNamespace(null, null, _namespaces._xmlns,
+ _namespaces._namespaces[i]);
+ } else {
+ writeAttributeOrNamespace(_namespaces._xmlns,
+ _namespaces._xmlnsURI, _namespaces._prefixes[i],
+ _namespaces._namespaces[i]);
+ }
+ }
+ }
+ }
+
+ // Returns the prefix for the specified namespace.
+ private CharSequence getRepairedPrefix(CharSequence prefix,
+ CharSequence namespaceURI) throws XMLStreamException {
+ CharArray prefixForURI = _namespaces.getPrefix(namespaceURI);
+ if ((prefixForURI != null)
+ && ((prefix == null) || prefixForURI.equals(prefix)))
+ return prefixForURI; // No repair needed.
+ if ((prefix == null) || (prefix.length() == 0)) { // Creates new prefix.
+ prefix = _autoPrefix.clear().append(_repairingPrefix)
+ .append(_autoNSCount++);
+ }
+ _namespaces.setPrefix(prefix, namespaceURI, true); // Map to namespace URI.
+ return prefix;
+ }
+
+ private final TextBuilder _autoPrefix = new TextBuilder();
+
+ // Resizes element stack (same memory area as the writer).
+ private void resizeElemStack() {
+ final int oldLength = _qNames.length;
+ final int newLength = oldLength * 2;
+
+ // Resizes elements qNames stack.
+ TextBuilder[] tmp = new TextBuilder[newLength];
+ System.arraycopy(_qNames, 0, tmp, 0, oldLength);
+ _qNames = tmp;
+ for (int i = oldLength; i < newLength; i++) {
+ _qNames[i] = new TextBuilder();
+ }
+ }
+
+ // Writes methods.
+ //
+
+ private final void writeNoEscape(String str) throws XMLStreamException {
+ write(str, 0, str.length(), false);
+ }
+
+ private final void writeNoEscape(TextBuilder tb) throws XMLStreamException {
+ write(tb, 0, tb.length(), false);
+ }
+
+ private final void writeNoEscape(CharSequence csq)
+ throws XMLStreamException {
+ write(csq, 0, csq.length(), false);
+ }
+
+ private final void writeEscape(CharSequence csq) throws XMLStreamException {
+ write(csq, 0, csq.length(), true);
+ }
+
+ private final void write(Object csq, int start, int length,
+ boolean escapeMarkup) throws XMLStreamException {
+ if (_index + length <= BUFFER_LENGTH) { // Enough buffer space.
+ if (csq instanceof String) {
+ ((String) csq).getChars(start, start + length, _buffer, _index);
+ } else if (csq instanceof javolution.text.Text) {
+ ((javolution.text.Text) csq).getChars(start, start + length,
+ _buffer, _index);
+ } else if (csq instanceof javolution.text.TextBuilder) {
+ ((javolution.text.TextBuilder) csq).getChars(start, start
+ + length, _buffer, _index);
+ } else if (csq instanceof javolution.text.CharArray) {
+ ((javolution.text.CharArray) csq).getChars(start, start
+ + length, _buffer, _index);
+ } else {
+ getChars((CharSequence) csq, start, start + length, _buffer,
+ _index);
+ }
+ if (escapeMarkup) {
+ int end = _index + length;
+ for (int i = _index; i < end; i++) {
+ char c = _buffer[i];
+ if ((c >= '?') || !isEscaped(c))
+ continue;
+ // Found character to escape.
+ _index = i;
+ flushBuffer();
+ writeDirectEscapedCharacters(_buffer, i, end);
+ return; // Done (buffer is empty).
+ }
+ }
+ _index += length;
+
+ } else { // Not enough remaining space.
+ if (length <= BUFFER_LENGTH) { // Enough space if buffer emptied.
+ flushBuffer();
+ write(csq, start, length, escapeMarkup);
+ } else {
+ int half = length >> 1;
+ write(csq, start, half, escapeMarkup);
+ write(csq, start + half, length - half, escapeMarkup);
+ }
+ }
+ }
+
+ private static void getChars(CharSequence csq, int start, int end,
+ char dest[], int destPos) {
+ for (int i = start, j = destPos; i < end;) {
+ dest[j++] = csq.charAt(i++);
+ }
+ }
+
+ // The buffer must have been flushed prior to calling this method.
+ private final void writeDirectEscapedCharacters(char[] chars, int start,
+ int end) throws XMLStreamException {
+ try {
+ int blockStart = start;
+ for (int i = start; i < end;) {
+ char c = chars[i++];
+ if ((c >= '?') || !isEscaped(c))
+ continue;
+ // Flush already read characters (excluding escaped one).
+ int blockLength = i - blockStart - 1;
+ if (blockLength > 0) {
+ _writer.write(_buffer, blockStart, blockLength);
+ }
+ blockStart = i;
+ switch (c) {
+ case '<':
+ _writer.write("<");
+ break;
+ case '>':
+ _writer.write(">");
+ break;
+ case '\'':
+ _writer.write("'");
+ break;
+ case '"':
+ _writer.write(""");
+ break;
+ case '&':
+ _writer.write("&");
+ break;
+ default:
+ _writer.write("&#");
+ _writer.write((char) ('0' + c / 10));
+ _writer.write((char) ('0' + c % 10));
+ _writer.write(';');
+ }
+ }
+ // Flush the current block.
+ int blockLength = end - blockStart;
+ if (blockLength > 0) {
+ _writer.write(_buffer, blockStart, blockLength);
+ }
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ private boolean isEscaped(char c) {
+ return ((c < ' ') && _isAttributeValue)
+ || (c == '"' && _isAttributeValue) || (c == '<') || (c == '>')
+ || (c == '&');
+ }
+
+ private final void write(char c) throws XMLStreamException {
+ if (_index == BUFFER_LENGTH) {
+ flushBuffer();
+ }
+ _buffer[_index++] = c;
+ }
+
+ private void flushBuffer() throws XMLStreamException {
+ try {
+ _writer.write(_buffer, 0, _index);
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ } finally {
+ _index = 0;
+ }
+ }
+
+}
\ 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/xml/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/xml/package-info.java
new file mode 100644
index 0000000..32c5661
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/package-info.java
@@ -0,0 +1,346 @@
+/**
+<p>Support for the encoding of objects, and the objects reachable from them,
+ into <code>XML</code>; and the complementary reconstruction of the
+ object graph from <code>XML</code>.
+</p>
+<p><i> This page has been translated into
+<a href="http://www.webhostinghub.com/support/es/misc/paquete-javolutionxml">Spanish</a>
+language by Maria Ramos from <a href="http://www.webhostinghub.com/support/edu">
+Webhostinghub.com/support/edu</a>.</i></p>
+
+<h2><a name="OVERVIEW">XML marshalling/unmarshalling facility:</a></h2>
+
+
+<IMG alt="XML Data Binding" src="doc-files/xmlDataBinding.png">
+
+<p> Key Advantages:<ul>
+ <li> Real-time characteristics with no adverse effect on memory footprint or
+ garbage collection (e.g. it can be used for time critical communications).
+ {@link javolution.xml.XMLFormat XMLFormat} is basically a "smart"
+ wrapper around our real-time StAX-like
+ {@link javolution.xml.stream.XMLStreamReader XMLStreamReader} and
+ {@link javolution.xml.stream.XMLStreamWriter XMLStreamWriter}.</li>
+ <li> Works directly with your existing Java classes, no need to create new classes
+ or customize your implementation in any way.</li>
+ <li> The XML representation can be high level and impervious to obfuscation
+ or changes to your implementation.</li>
+ <li> Performance on a par or better than default Java<sup>TM</sup> Serialization/Deserialization
+ (See <a href="https://bindmark.dev.java.net/">bindmark</a> for performance comparison).</li>
+ <li> Small footprint, runs on any platform including Android.</li>
+ <li> The XML mapping can be defined for a top class (or interface) and is automatically
+ inherited by all sub-classes (or all implementing classes).</li>
+ <li> Supports object references (to avoid expanding objects already serialized).</li>
+ </ul>
+</p>
+
+<p> The default XML format for a class is typically defined using
+ the {@link javolution.xml.DefaultXMLFormat} annotation tag.
+[code]
+@DefaultXMLFormat(Graphic.XML.class)
+public abstract class Graphic implements XMLSerializable {
+ private boolean isVisible;
+ private Paint paint; // null if none.
+ private Stroke stroke; // null if none.
+ private Transform transform; // null if none.
+
+ // Default XML format with name associations (members identified by an unique name).
+ // See XMLFormat for examples of positional associations.
+ public static class XML extends XMLFormat {
+ public void write(Graphic g, OutputElement xml) throws XMLStreamException {
+ xml.setAttribute("isVisible", g.isVisible);
+ xml.add(g.paint, "Paint");
+ xml.add(g.stroke, "Stroke");
+ xml.add(g.transform, "Transform");
+ }
+ public void read(InputElement xml, Graphic g) throws XMLStreamException {
+ g.isVisible = xml.getAttribute("isVisible", true);
+ g.paint = xml.get("Paint");
+ g.stroke = xml.get("Stroke");
+ g.transform = xml.get("Transform");
+ }
+ };
+}[/code]
+ Sub-classes may override the inherited XML format:
+[code]
+@DefaultXMLFormat(Area.XML.class)
+public class Area extends Graphic {
+ private Shape geometry;
+
+ // Adds geometry to format.
+ public static class XML extends XMLFormat<Area> {
+ XMLFormat graphicXML = new Graphic.XML();
+ public void write(Area area, OutputElement xml) throws XMLStreamException {
+ graphicXML.write(area, xml); // Calls parent write.
+ xml.add(area.geometry, "Geometry");
+ }
+ public void read(InputElement xml, Area area) throws XMLStreamException {
+ graphicXML.read(xml, area); // Calls parent read.
+ area.geometry = xml.get("Geometry");
+ }
+ };
+}[/code]
+
+The following writes a graphic area to a file, then reads it:
+
+[code]
+// Creates some useful aliases for class names.
+XMLBinding binding = new XMLBinding();
+binding.setAlias(Color.class, "Color");
+binding.setAlias(Polygon.class, "Polygon");
+binding.setClassAttribute("type"); // Use "type" instead of "class" for class attribute.
+
+// Writes the area to a file.
+XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream("C:/area.xml"));
+writer.setBinding(binding); // Optional.
+writer.setIndentation("\t"); // Optional (use tabulation for indentation).
+writer.write(area, "Area", Area.class);
+writer.close();
+
+// Reads the area back
+XMLObjectReader reader = XMLObjectReader.newInstance(new FileInputStream("C:/area.xml"));
+reader.setBinding(binding);
+Area a = reader.read("Area", Area.class);
+reader.close();
+[/code]
+
+ Here is an example of valid XML representation for an area:
+
+[code]
+<Area isVisible="true">
+ <Paint type="Color" rgb="#F3EBC6" />
+ <Geometry type="Polygon">
+ <Vertex x="123" y="-34" />
+ <Vertex x="-43" y="-34" />
+ <Vertex x="-12" y="123" />
+ </Geometry>
+</Area>[/code]
+
+</p>
+<p> The following table illustrates the variety of XML representations supported
+ (Foo class with a single String member named text):
+ <center>
+ <table cellpadding="2" cellspacing="2" border="1" style="text-align: left"><tbody>
+ <tr>
+ <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">XML FORMAT</span></td>
+ <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">XML DATA</span></td>
+ </tr>
+ <tr>
+<td>[code]
+XMLFormat<Foo> XML = new XMLFormat<Foo>() {
+ public void write(Foo foo, OutputElement xml) throws XMLStreamException {
+ xml.setAttribute("text", foo.text);
+ }
+ public void read(InputElement xml, Foo foo) throws XMLStreamException {
+ foo.text = xml.getAttribute("text", "");
+ }
+};[/code]</td>
+<td><pre>
+ <b><!-- Member as attribute --></b>
+ <Foo text="This is a text"/>
+</pre></td>
+ </tr>
+
+ <tr>
+<td>
+[code]
+XMLFormat<Foo> XML = new XMLFormat<Foo>() {
+ public void write(Foo foo, OutputElement xml) throws XMLStreamException {
+ xml.add(foo.text);
+ }
+ public void read(InputElement xml, Foo foo) throws XMLStreamException {
+ foo.text = xml.getNext();
+ }
+};[/code]</td>
+<td><pre>
+ <b><!-- Member as anonymous nested element --></b>
+ <Foo>
+ <java.lang.String value="This is a text"/>
+ </Foo>
+</pre></td>
+ </tr>
+
+ <tr>
+<td>
+[code]
+XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
+ public void write(Foo foo, OutputElement xml) throws XMLStreamException {
+ xml.addText(foo.text); // or xml.getStreamWriter().writeCDATA(foo.text) to use CDATA block.
+ }
+ public void read(InputElement xml, Foo foo) throws XMLStreamException {
+ foo.text = xml.getText().toString(); // Content of a text-only element.
+ }
+};[/code]</td>
+<td><pre>
+ <b><!-- Member as Character Data --></b>
+ <Foo>This is a text</Foo>
+</pre></td>
+ </tr>
+
+ <tr>
+<td>
+[code]
+XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
+ public void write(Foo foo, OutputElement xml) throws XMLStreamException {
+ xml.add(foo.text, "Text");
+ }
+ public void read(InputElement xml, Foo foo) throws XMLStreamException {
+ foo.text = xml.get("Text");
+ }
+};[/code]</td>
+<td><pre>
+ <b><!-- Member as named element of unknown type --></b>
+ <Foo>
+ <Text class="java.lang.String" value="This is a text"/>
+ </Foo>
+</pre></td>
+ </tr>
+
+ <tr>
+<td><pre>
+[code]
+XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
+ public void write(Foo foo, OutputElement xml) throws XMLStreamException {
+ xml.add(foo.text, "Text", String.class);
+ }
+ public void read(InputElement xml, Foo foo) throws XMLStreamException {
+ foo.text = xml.get("Text", String.class);
+ }
+};[/code]</td>
+<td><pre>
+ <b><!-- Member as named element of actual type known --></b>
+ <Foo>
+ <Text value="This is a text"/>
+ </Foo>
+</pre></td>
+ </tr>
+ </tbody></table>
+ </center>
+</p>
+
+<p> XML format do not have to use the classes
+ public no-arg constructors, instances can be created using factory methods,
+ private constructors (with constructor parameters set from the XML element)
+ or even retrieved from a collection
+ (if the object is shared or unique). For example:
+[code]
+@DefaultXMLFormat(Point.XML.class)
+public final class Point implements XMLSerializable {
+ private int x;
+ private int y;
+ private Point() {}; // No-arg constructor not visible.
+ public static Point valueOf(int x, int y) { ... }
+ public static class XML = new XMLFormat<Point>() {
+ public boolean isReferencable() {
+ return false; // Always manipulated by value.
+ }
+ public Point newInstance(Class<Point> cls, InputElement xml) throws XMLStreamException {
+ return Point.valueOf(xml.getAttribute("x", 0), xml.getAttribute("y", 0));
+ }
+ public void write(Point point, OutputElement xml) throws XMLStreamException {
+ xml.setAttribute("x", point.x);
+ xml.setAttribute("y", point.y);
+ }
+ public void read(InputElement xml, Point point) throws XMLStreamException {
+ // Do nothing immutable.
+ }
+ };
+}[/code]
+</p>
+
+<p> Document cross-references are supported, including circular references.
+ Let's take for example:
+[code]
+@DefaultXMLFormat(xml=Polygon.XML.class)
+public class Polygon implements Shape, XMLSerializable {
+ private Point[] vertices;
+ public static class XML extends XMLFormat<Polygon> {
+ public void write(Polygon polygon, OutputElement xml) throws XMLStreamException {
+ xml.setAttibutes("count", vertices.length);
+ for (Point p : vertices) {
+ xml.add(p, "Vertex", Point.class);
+ }
+ }
+ public void read(InputElement xml, Polygon polygon) throws XMLStreamException {
+ int count = xml.getAttributes("count", 0);
+ polygon.vertices = new Point[count];
+ for (int i=0; i < count; i++) {
+ vertices[i] = xml.get("Vertex", Point.class);
+ }
+ }
+ };
+}
+Polygon[] polygons = new Polygon[] {p1, p2, p1};
+...
+TextBuilder xml = TextBuilder.newInstance();
+AppendableWriter out = new AppendableWriter().setOutput(xml)
+XMLObjectWriter writer = XMLObjectWriter.newInstance(out);
+writer.setXMLReferenceResolver(new XMLReferenceResolver()); // Enables cross-references.
+writer.write(polygons, "Polygons", Polygon[].class);
+writer.close();
+System.out.println(xml);
+[/code]
+ Prints the following (noticed that the first polygon and last one are being shared).
+[code]
+<Polygons length="3">
+ <Polygon id="0" count="3">
+ <Vertex x="123" y="-34" />
+ <Vertex x="-43" y="-34" />
+ <Vertex x="-12" y="123" />
+ </Polygon>
+ <Polygon id="1" count="3">
+ <Vertex x="-43" y="-34" />
+ <Vertex x="123" y="-34" />
+ <Vertex x="-12" y="123" />
+ </Polygon>
+ <Polygon ref="0"/>
+ </Polygons>[/code]
+</p>
+
+<B>ALGORITHMS:</B>
+
+<p> Our {@link javolution.xml.XMLObjectReader XMLObjectReader}/{@link javolution.xml.XMLObjectWriter XMLObjectWriter}
+ are in fact simple wrappers around our <b>J</b>avolution high-performance StAX-like
+ {@link javolution.xml.stream.XMLStreamReader XMLStreamReader} and
+ {@link javolution.xml.stream.XMLStreamWriter XMLStreamWriter} classes.
+ The logic of these wrappers is described below:
+<pre>
+
+OutputElement.add(object, name, uri, class):
+
+1. if (object == null) return
+
+2. getStreamWriter().writeStartElement(uri, name)
+
+3. isReference = referenceResolver.writeReference(object, this)
+
+4. if (!isReference) binding.getFormat(class).write(object, this)
+
+5. getStreamWriter().writeEndElement()
+
+6. end
+
+
+InputElement.get(name, uri, class):
+
+1. if (!getStreamReader().getLocalName().equals(name) ||
+!getStreamReader().getNamespaceURI().equals(uri)) return null
+
+2. object = referenceResolver.readReference(inputElement)
+
+3. if (object != null) Goto 8 // Found reference
+
+4. format = binding.getFormat(class)
+
+5. object = format.newInstance(class, inputElement)
+
+6. referenceResolver.createReference(object, inputElement) // Done before parsing to support circular references.
+
+7. format.read(inputElement, object)
+
+8. getStreamReader().nextTag()
+
+9. end
+</pre></p>
+ */
+package javolution.xml;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/sax/Attributes.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/Attributes.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/Attributes.java
new file mode 100644
index 0000000..9192ffc
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/Attributes.java
@@ -0,0 +1,178 @@
+/*
+ * 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.xml.sax;
+
+import java.lang.CharSequence;
+
+import javolution.text.CharArray;
+
+/**
+ * <p> This interface represents a list of XML attributes.</p>
+ *
+ * <p> It is a more efficient version of <code>org.xml.sax.Attributes</code>
+ * with {@link CharArray CharArray}/{@link CharSequence CharSequence}
+ * instead of the <code>String</code> to avoid forcing dynamic object
+ * allocations.</p>
+ *
+ * @author <a href="mailto:sax@megginson.com">David Megginson</a>
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2006
+ */
+public interface Attributes {
+
+ /**
+ * Returns the number of attributes in this list of attributes.
+ *
+ * @return the number of attributes.
+ */
+ int getLength();
+
+ /**
+ * Looks up an attribute's Namespace URI by index.
+ *
+ * @param index the attribute index (zero-based).
+ * @return the Namespace URI, or an empty character sequence if none is
+ * available, or <code>null</code> if the index is out of range.
+ * @see #getLength
+ */
+ CharArray getURI(int index);
+
+ /**
+ * Looks up an attribute's local name by index.
+ *
+ * @param index the attribute index (zero-based).
+ * @return the local name, or an empty character sequence if Namespace
+ * processing is not being performed, or <code>null</code> if
+ * the index is out of range.
+ * @see #getLength
+ */
+ CharArray getLocalName(int index);
+
+ /**
+ * Looks up an attribute's XML 1.0 qualified name by index.
+ *
+ * @param index the attribute index (zero-based).
+ * @return the XML 1.0 qualified name, or an empty character sequence if
+ * none is available, or <code>null</code> if the index is out
+ * of range.
+ * @see #getLength
+ */
+ CharArray getQName(int index);
+
+ /**
+ * Looks up an attribute's type by index.
+ *
+ * <p> The attribute type is one of the strings "CDATA", "ID",
+ * "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES",
+ * or "NOTATION" (always in upper case).</p>
+ *
+ * <p> If the parser has not read a declaration for the attribute,
+ * or if the parser does not report attribute types, then it must
+ * return the value "CDATA" as stated in the XML 1.0 Recommentation
+ * (clause 3.3.3, "Attribute-TextBuilder Normalization").</p>
+ *
+ * <p> For an enumerated attribute that is not a notation, the
+ * parser will report the type as "NMTOKEN".</p>
+ *
+ * @param index the attribute index (zero-based).
+ * @return the attribute's type as a string, or null if the
+ * index is out of range.
+ * @see #getLength
+ */
+ CharArray getType(int index);
+
+ /**
+ * Looks up an attribute's value by index.
+ *
+ * <p> If the attribute value is a list of tokens (IDREFS,
+ * ENTITIES, or NMTOKENS), the tokens will be concatenated
+ * into a single string with each token separated by a
+ * single space.</p>
+ *
+ * @param index the attribute index (zero-based).
+ * @return the attribute's value as a character sequence,
+ * <code>null</code> if the index is out of range.
+ * @see #getLength
+ */
+ CharArray getValue(int index);
+
+ /**
+ * Looks up the index of an attribute by namespace name (convenience
+ * method).
+ * This method returns the index of the attribute whose uri/localName
+ * have the same character content as the specified uri/localName.
+ *
+ * @param uri the Namespace URI, or an empty character sequence if
+ * the name has no Namespace URI.
+ * @param localName the attribute's local name.
+ * @return the index of the attribute, or <code>-1</code> if it does not
+ * appear in the list.
+ */
+ int getIndex(CharSequence uri, CharSequence localName);
+
+ /**
+ * Looks up the index of an attribute by XML 1.0 qualified name
+ * (convenience method). This method returns the index of the attribute
+ * whose name has the same character content as the specified qName.
+ *
+ * @param qName the qualified (prefixed) name.
+ * @return the index of the attribute, or <code>-1</code> if it does not
+ * appear in the list.
+ */
+ int getIndex(CharSequence qName);
+
+ /**
+ * Looks up an attribute's type by Namespace name (convenience method).
+ * This method returns the type of the attribute whose uri/localName
+ * have the same character content as the specified uri/localName.
+ *
+ * @param uri the Namespace URI, or an empty string if the
+ * name has no Namespace URI.
+ * @param localName the local name of the attribute.
+ * @return the attribute type as a string, or null if the attribute is not
+ * in the list or if Namespace processing is not being performed.
+ */
+ CharArray getType(CharSequence uri, CharSequence localName);
+
+ /**
+ * Looks up an attribute's type by XML 1.0 qualified name.
+ * This method returns the type of the attribute whose qName
+ * has the same character content as the specified qName.
+ *
+ * @param qName The XML 1.0 qualified name.
+ * @return the attribute type as a string, or null if the attribute is not
+ * in the list or if qualified names are not available.
+ */
+ CharArray getType(CharSequence qName);
+
+ /**
+ * Looks up an attribute's value by Namespace name (convenience method).
+ * This method returns the value of the attribute whose uri/localName
+ * have the same character content as the specified uri/localName.
+ *
+ * @param uri the Namespace URI, or the empty string if the name has no
+ * Namespace URI.
+ * @param localName the local name of the attribute.
+ * @return the attribute value as a character sequence, or <code>null</code>
+ * if the attribute is not in the list.
+ */
+ CharArray getValue(CharSequence uri, CharSequence localName);
+
+ /**
+ * Looks up an attribute's value by XML 1.0 qualified name (convenience
+ * method). This method returns the value of the attribute whose qName
+ * has the same character content as the specified qName.
+ *
+ * @param qName The XML 1.0 qualified name.
+ * @return the attribute value as a character sequence, or <code>null</code>
+ * if the attribute is not in the list or if qualified names
+ * are not available.
+ */
+ CharArray getValue(CharSequence qName);
+}
\ 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/xml/sax/ContentHandler.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/ContentHandler.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/ContentHandler.java
new file mode 100644
index 0000000..3c38511
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/ContentHandler.java
@@ -0,0 +1,144 @@
+/*
+ * 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.xml.sax;
+
+import javolution.text.CharArray;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * <p> Receives notification of the logical content of a document.</p>
+ *
+ * <p> It is a more efficient version of <code>org.xml.sax.ContentHandler</code>
+ * with {@link CharArray CharArray}/{@link CharSequence CharSequence}
+ * instead of the <code>String</code> to avoid forcing dynamic object
+ * allocations.</p>
+ *
+ * @author <a href="mailto:sax@megginson.com">David Megginson</a>
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2006
+ */
+public interface ContentHandler {
+
+ /**
+ * Receives an object for locating the origin of SAX document events.
+ *
+ * @param locator the document locator.
+ */
+ void setDocumentLocator(Locator locator);
+
+ /**
+ * Receives notification of the beginning of a document.
+ *
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void startDocument() throws SAXException;
+
+ /**
+ * Receives notification of the end of a document.
+ *
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void endDocument() throws SAXException;
+
+ /**
+ * Begins the scope of a prefix-URI Namespace mapping.
+ *
+ * @param prefix the Namespace prefix being declared.
+ * @param uri the namespace URI the prefix is mapped to.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void startPrefixMapping(CharArray prefix, CharArray uri)
+ throws SAXException;
+
+ /**
+ * Ends the scope of a prefix-URI mapping.
+ *
+ * @param prefix the prefix that was being mapping.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void endPrefixMapping(CharArray prefix) throws SAXException;
+
+ /**
+ * Receives notification of the beginning of an element.
+ *
+ * @param uri the namespace URI, or an empty character sequence if the
+ * element has no Namespace URI or if namespace processing is not
+ * being performed.
+ * @param localName the local name (without prefix), or an empty character
+ * sequence if namespace processing is not being performed.
+ * @param qName the qualified name (with prefix), or an empty character
+ * sequence if qualified names are not available.
+ * @param atts the attributes attached to the element. If there are no
+ * attributes, it shall be an empty {@link Attributes} object.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void startElement(CharArray uri, CharArray localName, CharArray qName,
+ Attributes atts) throws SAXException;
+
+ /**
+ * Receives notification of the end of an element.
+ *
+ * @param uri the namespace URI, or an empty character sequence if the
+ * element has no Namespace URI or if namespace processing is not
+ * being performed.
+ * @param localName the local name (without prefix), or an empty character
+ * sequence if namespace processing is not being performed.
+ * @param qName the qualified XML 1.0 name (with prefix), or an empty
+ * character sequence if qualified names are not available.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void endElement(CharArray uri, CharArray localName, CharArray qName)
+ throws SAXException;
+
+ /**
+ * Receives notification of character data.
+ *
+ * @param ch the characters from the XML document.
+ * @param start the start position in the array.
+ * @param length the number of characters to read from the array.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void characters(char ch[], int start, int length) throws SAXException;
+
+ /**
+ * Receives notification of ignorable whitespace in element content.
+ *
+ * @param ch the characters from the XML document.
+ * @param start the start position in the array.
+ * @param length the number of characters to read from the array.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void ignorableWhitespace(char ch[], int start, int length)
+ throws SAXException;
+
+ /**
+ * Receives notification of a processing instruction.
+ *
+ * @param target the processing instruction target.
+ * @param data the processing instruction data, or null if
+ * none was supplied. The data does not include any
+ * whitespace separating it from the target.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void processingInstruction(CharArray target, CharArray data)
+ throws SAXException;
+
+ /**
+ * Receives notification of a skipped entity.
+ *
+ * @param name the name of the skipped entity. If it is a
+ * parameter entity, the name will begin with '%', and if
+ * it is the external DTD subset, it will be the character sequence
+ * "[dtd]".
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ void skippedEntity(CharArray name) throws SAXException;
+
+}
\ 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/xml/sax/DefaultHandler.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/DefaultHandler.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/DefaultHandler.java
new file mode 100644
index 0000000..325e832
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/DefaultHandler.java
@@ -0,0 +1,116 @@
+/*
+ * 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.xml.sax;
+
+import javolution.text.CharArray;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Default base class for real-time handling of XML events.
+ *
+ * @author <a href="mailto:sax@megginson.com">David Megginson</a>
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.1, March 11, 2005
+ */
+public class DefaultHandler implements ContentHandler, ErrorHandler {
+
+ /**
+ * Receives notification of a warning. The default behaviour is to take no
+ * action.
+ *
+ * @param e the warning information encapsulated in a SAX parse exception.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ public void warning(SAXParseException e) throws SAXException {}
+
+ /**
+ * Receives notification of recoverable parser error. The default behaviour
+ * is to take no action.
+ *
+ * @param e the error information encapsulated in a SAX parse exception.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ public void error(SAXParseException e) throws SAXException {}
+
+ /**
+ * Reports a fatal XML parsing error. The default behaviour is to throw
+ * the specified exception.
+ *
+ * @param e the error information encapsulated in a SAX parse exception.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ public void fatalError(SAXParseException e) throws SAXException {
+ throw e;
+ }
+
+ // Implements ContentHandler
+ public void setDocumentLocator(Locator locator) {}
+
+ // Implements ContentHandler
+ public void startDocument() throws SAXException {}
+
+ // Implements ContentHandler
+ public void endDocument() throws SAXException {}
+
+ // Implements ContentHandler
+ public void startPrefixMapping(CharArray prefix, CharArray uri)
+ throws SAXException {}
+
+ // Implements ContentHandler
+ public void endPrefixMapping(CharArray prefix) throws SAXException {}
+
+ // Implements ContentHandler
+ public void startElement(CharArray namespaceURI, CharArray localName,
+ CharArray qName, Attributes atts) throws SAXException {}
+
+ // Implements ContentHandler
+ public void endElement(CharArray namespaceURI, CharArray localName,
+ CharArray qName) throws SAXException {}
+
+ // Implements ContentHandler
+ public void characters(char ch[], int start, int length)
+ throws SAXException {}
+
+ // Implements ContentHandler
+ public void ignorableWhitespace(char ch[], int start, int length)
+ throws SAXException {}
+
+ // Implements ContentHandler
+ public void processingInstruction(CharArray target, CharArray data)
+ throws SAXException {}
+
+ // Implements ContentHandler
+ public void skippedEntity(CharArray name) throws SAXException {}
+
+ /**
+ * <p> Generates compile-time error if <code>startElement</code> is not
+ * correctly overriden. This method generates a compile-error
+ * <code>"final method cannot be overridden"</code> if
+ * <code>org.xml.sax.Attributes</code> is used instead of
+ * <code>javolution.xml.sax.Attributes</code> (common mistake).</p>
+ * @param uri the namespace URI, or an empty character sequence if the
+ * element has no Namespace URI or if namespace processing is not
+ * being performed.
+ * @param localName the local name (without prefix), or an empty character
+ * sequence if namespace processing is not being performed.
+ * @param qName the qualified name (with prefix), or an empty character
+ * sequence if qualified names are not available.
+ * @param atts the attributes attached to the element. If there are no
+ * attributes, it shall be an empty {@link Attributes} object.
+ * @throws org.xml.sax.SAXException any SAX exception.
+ */
+ protected final void startElement(CharArray uri, CharArray localName,
+ CharArray qName, org.xml.sax.Attributes atts) throws SAXException {
+ throw new UnsupportedOperationException();
+ }
+
+}
\ 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/xml/sax/SAX2ReaderImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/SAX2ReaderImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/SAX2ReaderImpl.java
new file mode 100644
index 0000000..3b51cd9
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/SAX2ReaderImpl.java
@@ -0,0 +1,386 @@
+/*
+ * 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.xml.sax;
+
+import java.io.IOException;
+
+import javolution.text.CharArray;
+import javolution.text.Text;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+import java.lang.CharSequence;
+
+/**
+ * <p> This class provides a SAX2-compliant parser wrapping a
+ * {@link javolution.xml.sax.XMLReaderImpl}. This parser allocates
+ * <code>java.lang.String</code> instances while parsing in accordance
+ * with the SAX2 specification. For faster performance (2-5x), the use of
+ * the SAX2-like {@link javolution.xml.sax.XMLReaderImpl
+ * XMLSaxParserImpl} or better{@link javolution.xml.stream.XMLStreamReader
+ * XMLStreamReader} is recommended.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2005
+ * @see <a href="http://www.saxproject.org"> SAX -- Simple API for XML</a>
+ */
+public final class SAX2ReaderImpl implements XMLReader {
+
+ /**
+ * Holds the SAX2 default handler instance.
+ */
+ private static Sax2DefaultHandler DEFAULT_HANDLER = new Sax2DefaultHandler();
+
+ /**
+ * Holds the real-time parser instance associated to this SAX2 parser.
+ */
+ private final XMLReaderImpl _parser = new XMLReaderImpl();
+
+ /**
+ * Holds the content handler proxy.
+ */
+ private final Proxy _proxy = new Proxy();
+
+ /**
+ * Default constructor.
+ */
+ public SAX2ReaderImpl() {}
+
+ // Implements org.xml.sax.XMLReader interface.
+ public boolean getFeature(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException {
+ return _parser.getFeature(name);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ _parser.setFeature(name, value);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public Object getProperty(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException {
+ return _parser.getProperty(name);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ _parser.setProperty(name, value);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void setEntityResolver(EntityResolver resolver) {
+ _parser.setEntityResolver(resolver);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public EntityResolver getEntityResolver() {
+ return _parser.getEntityResolver();
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void setDTDHandler(DTDHandler handler) {
+ _parser.setDTDHandler(handler);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public DTDHandler getDTDHandler() {
+ return _parser.getDTDHandler();
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void setContentHandler(ContentHandler handler) {
+ if (handler != null) {
+ _proxy._sax2Handler = handler;
+ _parser.setContentHandler(_proxy);
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public ContentHandler getContentHandler() {
+ return (_proxy._sax2Handler == DEFAULT_HANDLER) ? null
+ : _proxy._sax2Handler;
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void setErrorHandler(ErrorHandler handler) {
+ _parser.setErrorHandler(handler);
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public ErrorHandler getErrorHandler() {
+ return _parser.getErrorHandler();
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void parse(InputSource input) throws IOException, SAXException {
+ try {
+ _parser.parse(input);
+ } finally {
+ _parser.reset();
+ }
+ }
+
+ // Implements org.xml.sax.XMLReader interface.
+ public void parse(String systemId) throws IOException, SAXException {
+ try {
+ _parser.parse(systemId);
+ } finally {
+ _parser.reset();
+ }
+ }
+
+ // Implements Reusable interface.
+ public void reset() {
+ _parser.reset();
+ }
+
+ /**
+ * This class defines the proxy for content handler and attributes.
+ */
+ private static final class Proxy implements
+ javolution.xml.sax.ContentHandler, Attributes {
+
+ /**
+ * Holds the SAX2 content handler to which SAX2 events are forwarded.
+ */
+ private ContentHandler _sax2Handler = DEFAULT_HANDLER;
+
+ /**
+ * Holds the real-time attributes implementation from which attributes
+ * values are read.
+ */
+ private javolution.xml.sax.Attributes _attributes;
+
+ /**
+ * Default constructor.
+ */
+ public Proxy() {}
+
+ // Implements ContentHandler
+ public void setDocumentLocator(Locator locator) {
+ _sax2Handler.setDocumentLocator(locator);
+ }
+
+ // Implements ContentHandler
+ public void startDocument() throws SAXException {
+ _sax2Handler.startDocument();
+ }
+
+ // Implements ContentHandler
+ public void endDocument() throws SAXException {
+ _sax2Handler.endDocument();
+ _sax2Handler = DEFAULT_HANDLER;
+ }
+
+ // Implements ContentHandler
+ public void startPrefixMapping(CharArray prefix, CharArray uri)
+ throws SAXException {
+ _sax2Handler.startPrefixMapping(prefix.toString(), uri.toString());
+ }
+
+ // Implements ContentHandler
+ public void endPrefixMapping(CharArray prefix) throws SAXException {
+ _sax2Handler.endPrefixMapping(prefix.toString());
+ }
+
+ // Implements ContentHandler
+ public void startElement(CharArray namespaceURI, CharArray localName,
+ CharArray qName, javolution.xml.sax.Attributes atts)
+ throws SAXException {
+ _attributes = atts;
+ _sax2Handler.startElement(namespaceURI.toString(),
+ localName.toString(), qName.toString(), this);
+ }
+
+ // Implements ContentHandler
+ public void endElement(CharArray namespaceURI, CharArray localName,
+ CharArray qName) throws SAXException {
+ _sax2Handler.endElement(namespaceURI.toString(),
+ localName.toString(), qName.toString());
+ }
+
+ // Implements ContentHandler
+ public void characters(char ch[], int start, int length)
+ throws SAXException {
+ _sax2Handler.characters(ch, start, length);
+ }
+
+ // Implements ContentHandler
+ public void ignorableWhitespace(char ch[], int start, int length)
+ throws SAXException {
+ _sax2Handler.ignorableWhitespace(ch, start, length);
+ }
+
+ // Implements ContentHandler
+ public void processingInstruction(CharArray target, CharArray data)
+ throws SAXException {
+ _sax2Handler.processingInstruction(target.toString(),
+ data.toString());
+ }
+
+ // Implements ContentHandler
+ public void skippedEntity(CharArray name) throws SAXException {
+ _sax2Handler.skippedEntity(name.toString());
+ }
+
+ // Implements Attributes
+ public int getLength() {
+ return (_attributes != null ? _attributes.getLength() : 0);
+ }
+
+ // Implements Attributes
+ public String getURI(int index) {
+ CharSequence chars = (_attributes != null ? _attributes
+ .getURI(index) : null);
+ return (chars != null ? chars.toString() : "");
+ }
+
+ // Implements Attributes
+ public String getLocalName(int index) {
+ CharSequence chars = (_attributes != null ? _attributes
+ .getLocalName(index) : null);
+ return (chars != null ? chars.toString() : "");
+ }
+
+ // Implements Attributes
+ public String getQName(int index) {
+ CharSequence chars = (_attributes != null ? _attributes
+ .getQName(index) : null);
+ return (chars != null ? chars.toString() : "");
+ }
+
+ // Implements Attributes
+ public String getType(int index) {
+ return (_attributes != null ? _attributes.getType(index).toString()
+ : null);
+ }
+
+ // Implements Attributes
+ public String getValue(int index) {
+ CharSequence chars = (_attributes != null ? _attributes
+ .getValue(index) : null);
+ return (chars != null ? chars.toString() : null);
+ }
+
+ // Implements Attributes
+ public int getIndex(String uri, String localName) {
+ return (uri != null && localName != null && _attributes != null ? _attributes
+ .getIndex(toCharSequence(uri), toCharSequence(localName))
+ : -1);
+ }
+
+ // Implements Attributes
+ public int getIndex(String qName) {
+ return (qName != null && _attributes != null ? _attributes
+ .getIndex(toCharSequence(qName)) : -1);
+ }
+
+ // Implements Attributes
+ public String getType(String uri, String localName) {
+ return (uri != null && localName != null && _attributes != null ? _attributes
+ .getType(toCharSequence(uri), toCharSequence(localName))
+ .toString() : null);
+ }
+
+ // Implements Attributes
+ public String getType(String qName) {
+ return (qName != null && _attributes != null ? _attributes.getType(
+ toCharSequence(qName)).toString() : null);
+ }
+
+ // Implements Attributes
+ public String getValue(String uri, String localName) {
+ return (uri != null
+ && localName != null
+ && _attributes != null
+ && _attributes.getValue(toCharSequence(uri),
+ toCharSequence(localName)) != null ? _attributes
+ .getValue(toCharSequence(uri), toCharSequence(localName))
+ .toString() : null);
+ }
+
+ // Implements Attributes
+ public String getValue(String qName) {
+ return (qName != null && _attributes != null ? _attributes
+ .getValue(toCharSequence(qName)).toString() : null);
+ }
+ }
+
+ private static final class Sax2DefaultHandler implements EntityResolver,
+ DTDHandler, ContentHandler, ErrorHandler {
+
+ public InputSource resolveEntity(String publicId, String systemId)
+ throws SAXException, IOException {
+ return null;
+ }
+
+ public void notationDecl(String name, String publicId, String systemId)
+ throws SAXException {}
+
+ public void unparsedEntityDecl(String name, String publicId,
+ String systemId, String notationName) throws SAXException {}
+
+ public void setDocumentLocator(Locator locator) {}
+
+ public void startDocument() throws SAXException {}
+
+ public void endDocument() throws SAXException {}
+
+ public void startPrefixMapping(String prefix, String uri)
+ throws SAXException {}
+
+ public void endPrefixMapping(String prefix) throws SAXException {}
+
+ public void startElement(String uri, String localName, String qName,
+ Attributes atts) throws SAXException {}
+
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {}
+
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {}
+
+ public void ignorableWhitespace(char[] ch, int start, int length)
+ throws SAXException {}
+
+ public void processingInstruction(String target, String data)
+ throws SAXException {}
+
+ public void skippedEntity(String name) throws SAXException {}
+
+ public void warning(SAXParseException exception) throws SAXException {}
+
+ public void error(SAXParseException exception) throws SAXException {}
+
+ public void fatalError(SAXParseException exception) throws SAXException {
+ throw exception;
+ }
+ }
+
+ private static CharSequence toCharSequence(Object obj) {
+ return obj instanceof CharSequence ? (CharSequence) obj : Text
+ .valueOf(obj);
+ }
+
+}
\ No newline at end of file
[05/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java
new file mode 100644
index 0000000..ba201d8
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java
@@ -0,0 +1,1029 @@
+/*
+ * 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.xml;
+
+import javolution.text.CharArray;
+import javolution.text.TextBuilder;
+import javolution.text.TextContext;
+import javolution.text.TextFormat;
+import javolution.xml.internal.stream.XMLStreamReaderImpl;
+import javolution.xml.internal.stream.XMLStreamWriterImpl;
+import javolution.xml.sax.Attributes;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class represents the format base class for XML serialization and
+ * deserialization.</p>
+ *
+ * <p> Instances of this class are typically retrieved from the
+ * {@link XMLContext} (OSGi service or not).
+ * [code]
+ * @Format(xml=GraphicXML.class)
+ * public abstract class Graphic implements XMLSerializable {
+ * private boolean isVisible;
+ * private Paint paint; // null if none.
+ * private Stroke stroke; // null if none.
+ * private Transform transform; // null if none.
+ *
+ * // XML format with positional associations (members identified by their position),
+ * // see XML package description for examples of name associations.
+ * public static class GraphicXML extends XMLFormat<Graphic> {
+ * public void write(Graphic g, OutputElement xml) {
+ * xml.setAttribute("isVisible", g.isVisible);
+ * xml.add(g.paint); // First.
+ * xml.add(g.stroke); // Second.
+ * xml.add(g.transform); // Third.
+ * }
+ * public void read(InputElement xml, Graphic g) {
+ * g.isVisible = xml.getAttribute("isVisible", true);
+ * g.paint = xml.getNext();
+ * g.stroke = xml.getNext();
+ * g.transform = xml.getNext();
+ * return g;
+ * }
+ * };
+ * }
+ * [/code]
+ *
+ * <p> Due to the sequential nature of XML serialization/deserialization,
+ * formatting/parsing of XML attributes should always be performed before
+ * formatting/parsing of the XML content.</p>
+ *
+ * <p> The mapping between classes and XML formats can be overriden
+ * through {@link XMLBinding} instances.
+ * Here is an example of serialization/deserialization:
+ * [code]
+ * // Creates a list holding diverse objects.
+ * List list = new ArrayList();
+ * list.add("John Doe");
+ * list.add(null);
+ * Map map = new FastMap();
+ * map.put("ONE", 1);
+ * map.put("TWO", 2);
+ * list.add(map);
+ *
+ * // Use of custom binding.
+ * XMLBinding binding = new XMLBinding();
+ * binding.setAlias(FastMap.class, "Map");
+ * binding.setAlias(String.class, "String");
+ * binding.setAlias(Integer.class, "Integer");
+ *
+ * // Formats the list to XML .
+ * OutputStream out = new FileOutputStream("C:/list.xml");
+ * XMLObjectWriter writer = new XMLObjectWriter().setOutput(out).setBinding(binding);
+ * writer.write(list, "MyList", ArrayList.class);
+ * writer.close();
+ * [/code]
+ *
+ * Here is the output <code>list.xml</code> document produced:[code]
+ *
+ * <MyList>
+ * <String value="John Doe"/>
+ * <Null/>
+ * <Map>
+ * <Key class="String" value="ONE"/>
+ * <Value class="Integer" value="1"/>
+ * <Key class="String" value="TWO"/>
+ * <Value class="Integer" value="2"/>
+ * </Map>
+ * </MyList>
+ * [/code]
+ *
+ * The list can be read back with the following code:
+ * [code]
+ * // Reads back to a FastTable instance.
+ * InputStream in = new FileInputStream("C:/list.xml");
+ * XMLObjectReader reader = new XMLObjectReader().setInput(in).setBinding(binding);
+ * FastTable table = reader.read("MyList", FastTable.class);
+ * reader.close();
+ * [/code]
+ * </p>
+ *
+ * <p> <i>Note:</i> Any type for which a {@link TextFormat text format} is
+ * defined can be represented as a XML attribute.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.4, December 1, 2009
+ */
+public abstract class XMLFormat<T> {
+
+ /**
+ * Holds <code>null</code> representation.
+ */
+ private static final String NULL = "Null";
+
+ /**
+ * Default constructor.
+ */
+ protected XMLFormat() {}
+
+ /**
+ * Indicates if the object serialized through this format can be referenced
+ * to (default <code>true</code>). This method can be overriden to return
+ * <code>false</code> if serialized objects are manipulated "by value".
+ *
+ * @return <code>true</code> if serialized object may hold a reference;
+ * <code>false</code> otherwise.
+ * @see XMLReferenceResolver
+ */
+ public boolean isReferenceable() {
+ return true;
+ }
+
+ /**
+ * Allocates a new object of the specified class from the specified
+ * XML input element. By default, this method returns an object created
+ * using the public no-arg constructor of the specified class.
+ * XML formats may override this method in order to use private/multi-arg
+ * constructors.
+ *
+ * @param cls the class of the object to return.
+ * @param xml the XML input element.
+ * @return the object corresponding to the specified XML element.
+ */
+ public T newInstance(Class<? extends T> cls, InputElement xml)
+ throws XMLStreamException {
+ try {
+ return cls.newInstance();
+ } catch (InstantiationException e) {
+ throw new XMLStreamException(e);
+ } catch (IllegalAccessException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Formats an object into the specified XML output element.
+ *
+ * @param obj the object to format.
+ * @param xml the <code>XMLElement</code> destination.
+ */
+ public abstract void write(T obj, OutputElement xml)
+ throws XMLStreamException;
+
+ /**
+ * Parses an XML input element into the specified object.
+ *
+ * @param xml the XML element to parse.
+ * @param obj the object created through {@link #newInstance}
+ * and to setup from the specified XML element.
+ */
+ public abstract void read(InputElement xml, T obj)
+ throws XMLStreamException;
+
+ /**
+ * This class represents an input XML element (unmarshalling).
+ */
+ @SuppressWarnings("unchecked")
+ public static final class InputElement {
+
+ /**
+ * Holds the stream reader.
+ */
+ final XMLStreamReaderImpl _reader = new XMLStreamReaderImpl();
+
+ /**
+ * Holds the XML binding.
+ */
+ private XMLBinding _binding;
+
+ /**
+ * Holds the reference resolver.
+ */
+ private XMLReferenceResolver _referenceResolver;
+
+ /**
+ * Indicates if the reader is currently positioned on the next element.
+ */
+ private boolean _isReaderAtNext;
+
+ /**
+ * Default constructor.
+ */
+ InputElement() {
+ reset();
+ }
+
+ /**
+ * Returns the StAX-like stream reader (provides complete control
+ * over the unmarshalling process).
+ *
+ * @return the stream reader.
+ */
+ public XMLStreamReader getStreamReader() {
+ return _reader;
+ }
+
+ /**
+ * Indicates if more nested XML element can be read. This method
+ * positions the {@link #getStreamReader reader} at the start of the
+ * next XML element to be read (if any).
+ *
+ * @return <code>true</code> if there is more XML element to be read;
+ * <code>false</code> otherwise.
+ */
+ public boolean hasNext() throws XMLStreamException {
+ if (!_isReaderAtNext) {
+ _isReaderAtNext = true;
+ _reader.nextTag();
+ }
+ return _reader.getEventType() == XMLStreamReader.START_ELEMENT;
+ }
+
+ /**
+ * Returns the next object whose type is identified by the local name
+ * and URI of the current XML element.
+ *
+ * @return the next nested object which can be <code>null</code>.
+ * @throws XMLStreamException if <code>hasNext() == false</code>.
+ */
+ public <T> T getNext() throws XMLStreamException {
+ if (!hasNext()) // Asserts isReaderAtNext == true
+ throw new XMLStreamException("No more element to read",
+ _reader.getLocation());
+
+ // Checks for null.
+ if (_reader.getLocalName().equals(NULL)) {
+ if (_reader.next() != XMLStreamReader.END_ELEMENT)
+ throw new XMLStreamException("Non Empty Null Element");
+ _isReaderAtNext = false;
+ return null;
+ }
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ // Retrieves object's class from element tag.
+ Class<?> cls = _binding.readClass(_reader, false);
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object whose type is identified by a XML class attribute
+ * only if the XML element has the specified local name.
+ *
+ * @param name the local name of the next element.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String name) throws XMLStreamException {
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(name))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ // Retrieves object's class from class attribute.
+ Class<?> cls = _binding.readClass(_reader, true);
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object whose type is identified by a XML class attribute
+ * only if the XML element has the specified local name and URI.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI or <code>null</code>.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String localName, String uri)
+ throws XMLStreamException {
+ if (uri == null)
+ return (T) get(localName);
+
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(localName)
+ || !_reader.getNamespaceURI().equals(uri))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ // Retrieves object's class from class attribute.
+ Class<?> cls = _binding.readClass(_reader, true);
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object of specified type only if the XML element has the
+ * specified local name.
+ *
+ * @param name the local name of the element to match.
+ * @param cls the class identifying the format of the object to return.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String name, Class<T> cls) throws XMLStreamException {
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(name))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object of specified type only if the
+ * XML element has the specified local name and namespace URI.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI or <code>null</code>.
+ * @param cls the class identifying the format of the object to return.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ if (uri == null)
+ return get(localName, cls);
+
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(localName)
+ || !_reader.getNamespaceURI().equals(uri))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ return readInstanceOf(cls);
+ }
+
+ // Returns the referenced object if any.
+ private Object readReference() throws XMLStreamException {
+ if (_referenceResolver == null)
+ return null;
+ Object ref = _referenceResolver.readReference(this);
+ if (ref == null)
+ return null;
+ if (_reader.next() != XMLStreamReader.END_ELEMENT)
+ throw new XMLStreamException("Non Empty Reference Element");
+ _isReaderAtNext = false;
+ return ref;
+ }
+
+ // Builds object of specified class.
+ @SuppressWarnings("rawtypes")
+ private <T> T readInstanceOf(Class cls) throws XMLStreamException {
+
+ // Retrieves format.
+ XMLFormat xmlFormat = _binding.getFormat(cls);
+
+ // Creates object.
+ _isReaderAtNext = false; // Makes attributes accessible.
+ Object obj = xmlFormat.newInstance(cls, this);
+
+ // Adds reference (before reading to support circular reference).
+ if (_referenceResolver != null) {
+ _referenceResolver.createReference(obj, this);
+ }
+
+ // Parses xml.
+ xmlFormat.read(this, obj);
+ if (hasNext()) // Asserts _isReaderAtNext == true
+ throw new XMLStreamException("Incomplete element reading",
+ _reader.getLocation());
+ _isReaderAtNext = false; // Skips end element.
+ return (T) obj;
+ }
+
+ /**
+ * Returns the content of a text-only element (equivalent to
+ * {@link javolution.xml.stream.XMLStreamReader#getElementText
+ * getStreamReader().getElementText()}).
+ *
+ * @return the element text content or an empty sequence if none.
+ */
+ public CharArray getText() throws XMLStreamException {
+ CharArray txt = _reader.getElementText();
+ _isReaderAtNext = true; // End element is next.
+ return txt;
+ }
+
+ /**
+ * Returns the attributes for this XML input element.
+ *
+ * @return the attributes mapping.
+ */
+ public Attributes getAttributes() throws XMLStreamException {
+ if (_isReaderAtNext)
+ throw new XMLStreamException(
+ "Attributes should be read before content");
+ return _reader.getAttributes();
+ }
+
+ /**
+ * Searches for the attribute having the specified name.
+ *
+ * @param name the name of the attribute.
+ * @return the value for the specified attribute or <code>null</code>
+ * if the attribute is not found.
+ */
+ public CharArray getAttribute(String name) throws XMLStreamException {
+ if (_isReaderAtNext)
+ throw new XMLStreamException(
+ "Attributes should be read before reading content");
+ return _reader.getAttributeValue(null, name);
+ }
+
+ /**
+ * Returns the specified <code>String</code> attribute.
+ *
+ * @param name the name of the attribute.
+ * @param defaultValue a default value.
+ * @return the value for the specified attribute or
+ * the <code>defaultValue</code> if the attribute is not found.
+ */
+ public String getAttribute(String name, String defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toString() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>boolean</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>boolean</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public boolean getAttribute(String name, boolean defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toBoolean() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>char</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>char</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public char getAttribute(String name, char defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ if (value == null)
+ return defaultValue;
+ if (value.length() != 1)
+ throw new XMLStreamException(
+ "Single character expected (read '" + value + "')");
+ return value.charAt(0);
+ }
+
+ /**
+ * Returns the specified <code>byte</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>byte</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public byte getAttribute(String name, byte defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? (byte) value.toInt() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>short</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>short</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public short getAttribute(String name, short defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? (short) value.toInt() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>int</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>int</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public int getAttribute(String name, int defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toInt() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>long</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>long</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public long getAttribute(String name, long defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toLong() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>float</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>float</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public float getAttribute(String name, float defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toFloat() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>double</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>double</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public double getAttribute(String name, double defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toDouble() : defaultValue;
+ }
+
+ /**
+ * Returns the attribute of same type as the specified
+ * default value.
+ *
+ * @param name the name of the attribute.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the parse value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public <T> T getAttribute(String name, T defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ if (value == null)
+ return defaultValue;
+ // Parses attribute value.
+ Class<?> type = defaultValue.getClass();
+ TextFormat<?> format = TextContext.getFormat(type);
+ if (format == null)
+ throw new XMLStreamException("No TextFormat defined for "
+ + type);
+ return (T) format.parse(value);
+ }
+
+ // Sets XML binding.
+ void setBinding(XMLBinding xmlBinding) {
+ _binding = xmlBinding;
+ }
+
+ // Sets XML reference resolver.
+ void setReferenceResolver(XMLReferenceResolver xmlReferenceResolver) {
+ _referenceResolver = xmlReferenceResolver;
+ }
+
+ // Resets for reuse.
+ void reset() {
+ _binding = XMLBinding.DEFAULT;
+ _isReaderAtNext = false;
+ _reader.reset();
+ _referenceResolver = null;
+ }
+ }
+
+ /**
+ * This class represents an output XML element (marshalling).
+ */
+ @SuppressWarnings("unchecked")
+ public static final class OutputElement {
+
+ /**
+ * Holds the stream writer.
+ */
+ final XMLStreamWriterImpl _writer = new XMLStreamWriterImpl();
+
+ /**
+ * Holds the XML binding.
+ */
+ private XMLBinding _binding;
+
+ /**
+ * Holds the reference resolver.
+ */
+ private XMLReferenceResolver _referenceResolver;
+
+ /**
+ * Default constructor.
+ */
+ OutputElement() {
+ reset();
+ }
+
+ /**
+ * Returns the StAX-like stream writer (provides complete control over
+ * the marshalling process).
+ *
+ * @return the stream writer.
+ */
+ public XMLStreamWriter getStreamWriter() {
+ return _writer;
+ }
+
+ /**
+ * Adds the specified object or <code>null</code> as an anonymous
+ * nested element of unknown type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ */
+ public void add(Object obj) throws XMLStreamException {
+ if (obj == null) {
+ _writer.writeEmptyElement(NULL);
+ return;
+ }
+
+ // Writes start element.
+ Class<?> cls = obj.getClass();
+ _binding.writeClass(cls, _writer, false);
+
+ // Checks if reference written.
+ XMLFormat<Object> xmlFormat = (XMLFormat<Object>) _binding
+ .getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a named nested element of unknown type
+ * (<code>null</code> objects are ignored).
+ * The nested XML element contains a class attribute identifying
+ * the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ */
+ public void add(Object obj, String name) throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(name);
+
+ // Writes class attribute.
+ Class<?> cls = obj.getClass();
+ _binding.writeClass(cls, _writer, true);
+
+ // Checks if reference written.
+ XMLFormat<Object> xmlFormat = (XMLFormat<Object>) _binding
+ .getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a fully qualified nested element of
+ * unknown type (<code>null</code> objects are ignored).
+ * The nested XML element contains a class attribute identifying
+ * the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ */
+ public void add(Object obj, String localName, String uri)
+ throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(uri, localName);
+
+ // Writes class attribute.
+ Class<?> cls = obj.getClass();
+ _binding.writeClass(cls, _writer, true);
+
+ // Checks if reference written.
+ XMLFormat<Object> xmlFormat = (XMLFormat<Object>) _binding
+ .getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a named nested element of specified
+ * actual type (<code>null</code> objects are ignored).
+ * The nested XML element does not contain any class attribute.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ * @param cls the class identifying the format of the specified object.
+ */
+ public <T> void add(T obj, String name, Class<T> cls)
+ throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(name);
+
+ // Checks if reference written.
+ XMLFormat<T> xmlFormat = (XMLFormat<T>) _binding.getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a fully qualified nested element of
+ * specified actual type (<code>null</code> objects are ignored).
+ * The nested XML element does not contain any class attribute.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ * @param cls the class identifying the format of the specified object.
+ */
+ public <T> void add(T obj, String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(uri, localName);
+
+ // Checks if reference written.
+ XMLFormat<T> xmlFormat = (XMLFormat<T>) _binding.getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ // Returns true if reference written.
+ private boolean writeReference(Object obj) throws XMLStreamException {
+ if ((_referenceResolver == null)
+ || !_referenceResolver.writeReference(obj, this))
+ return false;
+ _writer.writeEndElement();
+ return true; // Reference written.
+ }
+
+ /**
+ * Adds the content of a text-only element (equivalent to {@link
+ * javolution.xml.stream.XMLStreamWriter#writeCharacters(CharSequence)
+ * getStreamWriter().writeCharacters(text)}).
+ *
+ * @param text the element text content or an empty sequence if none.
+ */
+ public void addText(CharSequence text) throws XMLStreamException {
+ _writer.writeCharacters(text);
+ }
+
+ /**
+ * Equivalent to {@link #addText(CharSequence)}
+ * (for J2ME compatibility).
+ *
+ * @param text the element text content or an empty sequence if none.
+ */
+ public void addText(String text) throws XMLStreamException {
+ _writer.writeCharacters(text);
+ }
+
+ /**
+ * Sets the specified <code>CharSequence</code> attribute
+ * (<code>null</code> values are ignored).
+ *
+ * @param name the attribute name.
+ * @param value the attribute value or <code>null</code>.
+ */
+ public void setAttribute(String name, CharSequence value)
+ throws XMLStreamException {
+ if (value == null)
+ return;
+ _writer.writeAttribute(name, value);
+ }
+
+ /**
+ * Sets the specified <code>String</code> attribute
+ * (<code>null</code> values are ignored).
+ *
+ * @param name the attribute name.
+ * @param value the attribute value.
+ */
+ public void setAttribute(String name, String value)
+ throws XMLStreamException {
+ if (value == null)
+ return;
+ _writer.writeAttribute(name, value);
+ }
+
+ /**
+ * Sets the specified <code>boolean</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>boolean</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, boolean value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ private TextBuilder _tmpTextBuilder = new TextBuilder();
+
+ /**
+ * Sets the specified <code>char</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>char</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, char value)
+ throws XMLStreamException {
+ setAttribute(name,
+ (TextBuilder) _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>byte</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>byte</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, byte value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>short</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>short</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, short value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>int</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>int</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, int value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>long</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>long</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, long value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>float</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>float</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, float value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>double</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>double</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, double value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified attribute using its associated
+ * {@link javolution.text.TextFormat TextFormat}.
+ *
+ * @param name the name of the attribute.
+ * @param value the value for the specified attribute
+ * or <code>null</code> in which case the attribute is not set.
+ */
+ public void setAttribute(String name, Object value)
+ throws XMLStreamException {
+ if (value == null)
+ return;
+ setAttribute(name, _tmpTextBuilder.clear().append(value.toString()));
+ }
+
+ // Sets XML binding.
+ void setBinding(XMLBinding xmlBinding) {
+ _binding = xmlBinding;
+ }
+
+ // Sets XML reference resolver.
+ void setReferenceResolver(XMLReferenceResolver xmlReferenceResolver) {
+ _referenceResolver = xmlReferenceResolver;
+ }
+
+ // Resets for reuse.
+ void reset() {
+ _binding = XMLBinding.DEFAULT;
+ _writer.reset();
+ _writer.setRepairingNamespaces(true);
+ _writer.setAutomaticEmptyElements(true);
+ _referenceResolver = null;
+ }
+ }
+
+ /**
+ * Returns the default XML format for any object having a
+ * {@link TextFormat plain text format}; this XML representation consists
+ * of the plain text representation of the object as a "value" attribute.
+ */
+ public static class Default extends XMLFormat<Object> {
+
+ /**
+ * Default constructor.
+ */
+ public Default() {}
+
+ @Override
+ public boolean isReferenceable() {
+ return false; // Always by value (immutable).
+ }
+
+ @Override
+ public Object newInstance(Class<?> cls,
+ javolution.xml.XMLFormat.InputElement xml)
+ throws XMLStreamException {
+ TextFormat<?> format = TextContext.getFormat(cls);
+ if (format == null)
+ throw new XMLStreamException(
+ "No TextFormat defined to parse instances of " + cls);
+ CharArray value = xml.getAttribute("value");
+ if (value == null)
+ throw new XMLStreamException(
+ "Missing value attribute (to be able to parse the instance of "
+ + cls + ")");
+ return format.parse(value);
+ }
+
+ public void read(XMLFormat.InputElement xml, Object obj)
+ throws XMLStreamException {
+ // Do nothing.
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ TextBuilder tmp = new TextBuilder();
+ TextFormat<?> tf = TextContext.getFormat(obj.getClass());
+ ((TextFormat<Object>) tf).format(obj, tmp);
+ xml.setAttribute("value", tmp);
+ }
+
+ };
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java
new file mode 100644
index 0000000..f51ebaf
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java
@@ -0,0 +1,291 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import javolution.xml.internal.stream.XMLStreamReaderImpl;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+
+/**
+ * <p> This class restores objects which have been serialized in XML
+ * format using an {@link XMLObjectWriter}.</p>
+ *
+ * <p> When the XML document is parsed, each elements are recursively
+ * processed and Java objects are created using the {@link XMLFormat}
+ * of the class as identified by the {@link XMLBinding}.</p>
+ *
+ * <p> Multiple objects can be read from the same XML input.
+ * For example:[code]
+ * XMLObjectReader reader = XMLObjectReader.newInstance(inputStream);
+ * while (reader.hasNext()) {
+ * Message message = reader.read("Message", Message.class);
+ * }
+ * reader.close(); // The underlying stream is closed.
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+public class XMLObjectReader {
+
+ /**
+ * Hold the xml element used when parsing.
+ */
+ private final XMLFormat.InputElement _xml = new XMLFormat.InputElement();
+
+ /**
+ * Holds reader if any.
+ */
+ private Reader _reader;
+
+ /**
+ * Holds input stream if any.
+ */
+ private InputStream _inputStream;
+
+ /**
+ * Returns a XML object reader having the specified
+ * input stream as input.
+ *
+ * @param in the input stream.
+ */
+ public static XMLObjectReader newInstance(InputStream in)
+ throws XMLStreamException {
+ XMLObjectReader reader = new XMLObjectReader();
+ reader.setInput(in);
+ return reader;
+ }
+
+ /**
+ * Returns a XML object reader (potentially recycled) having the specified
+ * input stream/encoding as input.
+ *
+ * @param in the input stream.
+ * @param encoding the input stream encoding
+ */
+ public static XMLObjectReader newInstance(InputStream in, String encoding)
+ throws XMLStreamException {
+ XMLObjectReader reader = new XMLObjectReader();
+ reader.setInput(in, encoding);
+ return reader;
+ }
+
+ /**
+ * Returns a XML object reader (potentially recycled) having the specified
+ * reader as input.
+ *
+ * @param in the reader source.
+ */
+ public static XMLObjectReader newInstance(Reader in)
+ throws XMLStreamException {
+ XMLObjectReader reader = new XMLObjectReader();
+ reader.setInput(in);
+ return reader;
+ }
+
+ /**
+ * Default constructor.
+ */
+ public XMLObjectReader() {}
+
+ /**
+ * Returns the stream reader being used by this reader (it can be
+ * used to set prefix, read prologs, etc).
+ *
+ * @return the stream reader.
+ */
+ public XMLStreamReader getStreamReader() {
+ return _xml._reader;
+ }
+
+ /**
+ * Sets the input stream source for this XML object reader
+ * (encoding retrieved from XML prolog if any).
+ *
+ * @param in the source input stream.
+ * @return <code>this</code>
+ * @see XMLStreamReaderImpl#setInput(InputStream)
+ */
+ public XMLObjectReader setInput(InputStream in) throws XMLStreamException {
+ if ((_inputStream != null) || (_reader != null))
+ throw new IllegalStateException("Reader not closed or reset");
+ _xml._reader.setInput(in);
+ _inputStream = in;
+ return this;
+ }
+
+ /**
+ * Sets the input stream source and encoding for this XML object reader.
+ *
+ * @param in the input source.
+ * @param encoding the associated encoding.
+ * @return <code>this</code>
+ * @see XMLStreamReaderImpl#setInput(InputStream, String)
+ */
+ public XMLObjectReader setInput(InputStream in, String encoding)
+ throws XMLStreamException {
+ if ((_inputStream != null) || (_reader != null))
+ throw new IllegalStateException("Reader not closed or reset");
+ _xml._reader.setInput(in, encoding);
+ _inputStream = in;
+ return this;
+ }
+
+ /**
+ * Sets the reader input source for this XML stream reader.
+ *
+ * @param in the source reader.
+ * @return <code>this</code>
+ * @see XMLStreamReaderImpl#setInput(Reader)
+ */
+ public XMLObjectReader setInput(Reader in) throws XMLStreamException {
+ if ((_inputStream != null) || (_reader != null))
+ throw new IllegalStateException("Reader not closed or reset");
+ _xml._reader.setInput(in);
+ _reader = in;
+ return this;
+ }
+
+ /**
+ * Sets the XML binding to use with this object reader.
+ *
+ * @param binding the XML binding to use.
+ * @return <code>this</code>
+ */
+ public XMLObjectReader setBinding(XMLBinding binding) {
+ _xml.setBinding(binding);
+ return this;
+ }
+
+ /**
+ * Sets the XML reference resolver to use with this object reader
+ * (the same resolver can be used accross multiple readers).
+ *
+ * @param referenceResolver the XML reference resolver.
+ * @return <code>this</code>
+ */
+ public XMLObjectReader setReferenceResolver(
+ XMLReferenceResolver referenceResolver) {
+ _xml.setReferenceResolver(referenceResolver);
+ return this;
+ }
+
+ /**
+ * Indicates if more elements can be read. This method
+ * positions the reader at the start of the
+ * next element to be read (if any).
+ *
+ * @return <code>true</code> if more element/data to be read;
+ * <code>false</code> otherwise.
+ * @see XMLFormat.InputElement#hasNext()
+ */
+ public boolean hasNext() throws XMLStreamException {
+ return _xml.hasNext();
+ }
+
+ /**
+ * Returns the object corresponding to the next element/data.
+ *
+ * @return the next nested object (can be <code>null</code>)
+ * @throws XMLStreamException if <code>hasNext() == false</code>
+ * @see XMLFormat.InputElement#getNext()
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T read() throws XMLStreamException {
+ return (T) _xml.getNext();
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name.
+ *
+ * @param name the local name of the next element.
+ * @return the next content object or <code>null</code> if the
+ * local name does not match.
+ * @see XMLFormat.InputElement#get(String)
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T read(String name) throws XMLStreamException {
+ return (T) _xml.get(name);
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name and namespace URI.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI.
+ * @return the next content object or <code>null</code> if the
+ * name/uri does not match.
+ * @see XMLFormat.InputElement#get(String, String)
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T read(String localName, String uri) throws XMLStreamException {
+ return (T) _xml.get(localName, uri);
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name; the actual object type is identified
+ * by the specified class parameter.
+ *
+ * @param name the name of the element to match.
+ * @param cls the non-abstract class identifying the object to return.
+ * @return <code>read(name, null, cls)</code>
+ */
+ public <T> T read(String name, Class<T> cls) throws XMLStreamException {
+ return _xml.get(name, cls);
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name and namespace URI; the
+ * actual object type is identified by the specified class parameter.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI.
+ * @param cls the non-abstract class identifying the object to return.
+ * @return the next content object or <code>null</code> if no match.
+ */
+ public <T> T read(String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ return _xml.get(localName, uri, cls);
+ }
+
+ /**
+ * Closes this reader and its underlying input then {@link #reset reset}
+ * this reader for potential reuse.
+ */
+ public void close() throws XMLStreamException {
+ try {
+ if (_inputStream != null) {
+ _inputStream.close();
+ reset();
+ } else if (_reader != null) {
+ _reader.close();
+ reset();
+ }
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Resets this object reader for reuse.
+ */
+ public void reset() {
+ _xml.reset();
+ _reader = null;
+ _inputStream = null;
+ }
+}
\ 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/xml/XMLObjectWriter.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java
new file mode 100644
index 0000000..7cb3d80
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java
@@ -0,0 +1,311 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import javolution.xml.internal.stream.XMLStreamWriterImpl;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class takes an object and formats it to XML; the resulting
+ * XML can be deserialized using a {@link XMLObjectReader}.</p>
+ *
+ * <p> When an object is formatted, the {@link XMLFormat} of the
+ * object's class as identified by the {@link XMLBinding} is used to
+ * write its XML representation.</p>
+ *
+ * <p> Multiple objects can be written to the same XML output.
+ * For example:[code]
+ * XMLObjectWriter writer = XMLObjectWriter.newInstance(outputStream);
+ * while (true)) {
+ * Message message = ...
+ * writer.write(message, "Message", Message.class);
+ * }
+ * writer.close(); // The underlying stream is closed.
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+public class XMLObjectWriter {
+
+ /**
+ * Hold the xml element used when formatting.
+ */
+ private final XMLFormat.OutputElement _xml = new XMLFormat.OutputElement();
+
+ /**
+ * Holds writer if any.
+ */
+ private Writer _writer;
+
+ /**
+ * Holds input stream if any.
+ */
+ private OutputStream _outputStream;
+
+ /**
+ * Default constructor.
+ */
+ public XMLObjectWriter() {}
+
+ /**
+ * Returns a XML object writer (potentially recycled) having the specified
+ * output stream as output.
+ *
+ * @param out the output stream.
+ */
+ public static XMLObjectWriter newInstance(OutputStream out)
+ throws XMLStreamException {
+ XMLObjectWriter writer = new XMLObjectWriter();
+ writer.setOutput(out);
+ return writer;
+ }
+
+ /**
+ * Returns a XML object writer (potentially recycled) having the specified
+ * output stream/encoding as output.
+ *
+ * @param out the output stream.
+ * @param encoding the output stream encoding.
+ */
+ public static XMLObjectWriter newInstance(OutputStream out, String encoding)
+ throws XMLStreamException {
+ XMLObjectWriter writer = new XMLObjectWriter();
+ writer.setOutput(out, encoding);
+ return writer;
+ }
+
+ /**
+ * Returns a XML object writer (potentially recycled) having the specified
+ * writer as output.
+ *
+ * @param out the writer output.
+ */
+ public static XMLObjectWriter newInstance(Writer out)
+ throws XMLStreamException {
+ XMLObjectWriter writer = new XMLObjectWriter();
+ writer.setOutput(out);
+ return writer;
+ }
+
+ /**
+ * Returns the stream writer used by this object writer (it can be used
+ * to write prolog, write namespaces, etc). The stream writer is setup to
+ * automatically repair namespaces and to automatically output empty
+ * elements when a start element is immediately followed by matching end
+ * element.
+ *
+ * @return the stream writer.
+ */
+ public XMLStreamWriter getStreamWriter() {
+ return _xml._writer;
+ }
+
+ /**
+ * Sets the output stream for this XML object writer.
+ *
+ * @param out the output stream destination.
+ * @return <code>this</code>
+ * @see XMLStreamWriterImpl#setOutput(OutputStream)
+ */
+ public XMLObjectWriter setOutput(OutputStream out)
+ throws XMLStreamException {
+ if ((_outputStream != null) || (_writer != null))
+ throw new IllegalStateException("Writer not closed or reset");
+ _xml._writer.setOutput(out);
+ _outputStream = out;
+ _xml._writer.writeStartDocument();
+ return this;
+ }
+
+ /**
+ * Sets the output stream and encoding for this XML object writer.
+ *
+ * @param out the output stream destination.
+ * @param encoding the stream encoding.
+ * @return <code>this</code>
+ * @see XMLStreamWriterImpl#setOutput(OutputStream, String)
+ */
+ public XMLObjectWriter setOutput(OutputStream out, String encoding)
+ throws XMLStreamException {
+ if ((_outputStream != null) || (_writer != null))
+ throw new IllegalStateException("Writer not closed or reset");
+ _xml._writer.setOutput(out, encoding);
+ _outputStream = out;
+ _xml._writer.writeStartDocument();
+ return this;
+ }
+
+ /**
+ * Sets the output writer for this XML object writer.
+ *
+ * @param out the writer destination.
+ * @return <code>this</code>
+ * @see XMLStreamWriterImpl#setOutput(Writer)
+ */
+ public XMLObjectWriter setOutput(Writer out) throws XMLStreamException {
+ if ((_outputStream != null) || (_writer != null))
+ throw new IllegalStateException("Writer not closed or reset");
+ _xml._writer.setOutput(out);
+ _writer = out;
+ _xml._writer.writeStartDocument();
+ return this;
+ }
+
+ /**
+ * Sets the XML binding to use with this object writer.
+ *
+ * @param binding the XML binding to use.
+ * @return <code>this</code>
+ */
+ public XMLObjectWriter setBinding(XMLBinding binding) {
+ _xml.setBinding(binding);
+ return this;
+ }
+
+ /**
+ * Sets the indentation to be used by this writer (no indentation
+ * by default).
+ *
+ * @param indentation the indentation string.
+ * @return <code>this</code>
+ */
+ public XMLObjectWriter setIndentation(String indentation) {
+ _xml._writer.setIndentation(indentation);
+ return this;
+ }
+
+ /**
+ * Sets the XML reference resolver to use with this object writer
+ * (the same reference resolver can be used accross multiple writers).
+ *
+ * @param referenceResolver the XML reference resolver.
+ * @return <code>this</code>
+ */
+ public XMLObjectWriter setReferenceResolver(
+ XMLReferenceResolver referenceResolver) {
+ _xml.setReferenceResolver(referenceResolver);
+ return this;
+ }
+
+ /**
+ * Writes the specified object as an anonymous nested element of
+ * unknown type. This result in the actual type of the object being
+ * identified by the element name.
+ *
+ * @param obj the object written as nested element or <code>null</code>.
+ * @see XMLFormat.OutputElement#add(Object)
+ */
+ public void write(Object obj) throws XMLStreamException {
+ _xml.add(obj);
+ }
+
+ /**
+ * Writes the specified object as a named nested element of unknown type
+ * (<code>null</code> objects are ignored). The nested XML element
+ * may contain a class attribute identifying the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ * @see XMLFormat.OutputElement#add(Object, String)
+ */
+ public void write(Object obj, String name) throws XMLStreamException {
+ _xml.add(obj, name);
+ }
+
+ /**
+ * Writes the specified object as a fully qualified nested element of
+ * unknown type (<code>null</code> objects are ignored).
+ * The nested XML element may contain a class attribute identifying
+ * the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ * @see XMLFormat.OutputElement#add(Object, String, String)
+ */
+ public void write(Object obj, String localName, String uri)
+ throws XMLStreamException {
+ _xml.add(obj, localName, uri);
+ }
+
+ /**
+ * Writes the specified object as a named nested element of actual type
+ * known (<code>null</code> objects are ignored).
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ * @param cls the non-abstract class identifying the XML format to use.
+ * @see XMLFormat.OutputElement#add(Object, String, Class)
+ */
+ public <T> void write(T obj, String name, Class<T> cls)
+ throws XMLStreamException {
+ _xml.add(obj, name, cls);
+ }
+
+ /**
+ * Writes the specified object as a fully qualified nested element of
+ * actual type known (<code>null</code> objects are ignored).
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ * @param cls the class identifying the XML format to use.
+ * @see XMLFormat.OutputElement#add(Object, String, String, Class)
+ */
+ public <T> void write(T obj, String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ _xml.add(obj, localName, uri, cls);
+ }
+
+ /**
+ * Flushes the output stream of this writer (automatically done
+ * when {@link #close() closing}).
+ */
+ public void flush() throws XMLStreamException {
+ _xml._writer.flush();
+ }
+
+ /**
+ * Ends document writting, closes this writer and its underlying
+ * output then {@link #reset reset} this Writer for potential reuse.
+ */
+ public void close() throws XMLStreamException {
+ try {
+ if (_outputStream != null) {
+ _xml._writer.writeEndDocument();
+ _xml._writer.close();
+ _outputStream.close();
+ reset();
+ } else if (_writer != null) {
+ _xml._writer.writeEndDocument();
+ _xml._writer.close();
+ _writer.close();
+ reset();
+ }
+
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Resets this object writer for reuse.
+ */
+ public void reset() {
+ _xml.reset();
+ _outputStream = null;
+ _writer = null;
+ }
+}
\ 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/xml/XMLReferenceResolver.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java
new file mode 100644
index 0000000..2730cf2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java
@@ -0,0 +1,206 @@
+/*
+ * 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.xml;
+
+import javolution.text.CharArray;
+import javolution.text.TextBuilder;
+import javolution.util.FastMap;
+import javolution.util.FastTable;
+import javolution.util.Index;
+import javolution.util.function.Equalities;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * <p> This class represents a resolver for XML cross references during
+ * the marshalling/unmarshalling process.</p>
+ *
+ * <p> Instances of this class may only be shared by {@link XMLObjectReader}/
+ * {@link XMLObjectWriter} running sequentially (for cross references
+ * spawning multiple documents).</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+public class XMLReferenceResolver {
+
+ /**
+ * Holds object to identifier (FastTable.Index) mapping.
+ */
+ private FastMap<Object, Index> _objectToId = new FastMap<Object, Index>(
+ Equalities.IDENTITY);
+
+ /**
+ * Holds the objects (index to object mapping).
+ */
+ private FastTable<Object> _idToObject = new FastTable<Object>();
+
+ /**
+ * Holds the id counter.
+ */
+ private int _counter;
+
+ /**
+ * Holds the identifier attribute name.
+ */
+ private String _idName = "id";
+
+ /**
+ * Holds the identifier attribute URI if any.
+ */
+ private String _idURI = null;
+
+ /**
+ * Holds the reference attribute name.
+ */
+ private String _refName = "ref";
+
+ /**
+ * Holds the reference attribute URI if any.
+ */
+ private String _refURI = null;
+
+ /**
+ * Default constructor.
+ */
+ public XMLReferenceResolver() {}
+
+ /**
+ * Sets the name of the identifier attribute (by default<code>"id"</code>).
+ * If the name is <code>null</code> then the identifier attribute
+ * is never read/written (which may prevent unmarshalling).
+ *
+ * @param name the name of the attribute or <code>null</code>.
+ */
+ public void setIdentifierAttribute(String name) {
+ setIdentifierAttribute(name, null);
+ }
+
+ /**
+ * Sets the local name and namespace URI of the identifier attribute.
+ *
+ * @param localName the local name of the attribute or <code>null</code>.
+ * @param uri the URI of the attribute or <code>null</code> if the attribute
+ * has no namespace URI.
+ */
+ public void setIdentifierAttribute(String localName, String uri) {
+ _idName = localName;
+ _idURI = uri;
+ }
+
+ /**
+ * Sets the name of the reference attribute (by default<code>"ref"</code>).
+ * If the name is <code>null</code> then the reference attribute
+ * is never read/written (which may prevent unmarshalling).
+ *
+ * @param name the name of the attribute or <code>null</code>.
+ */
+ public void setReferenceAttribute(String name) {
+ setReferenceAttribute(name, null);
+ }
+
+ /**
+ * Sets the local name and namespace URI of the identifier attribute.
+ *
+ * @param localName the local name of the attribute or <code>null</code>.
+ * @param uri the URI of the attribute or <code>null</code> if the attribute
+ * has no namespace URI.
+ */
+ public void setReferenceAttribute(String localName, String uri) {
+ _refName = localName;
+ _refURI = uri;
+ }
+
+ /**
+ * Writes a reference to the specified object into the specified XML
+ * element. The default implementation writes the reference into the
+ * reference attribute and for the first occurences an identifier
+ * (counter starting at 1) is written into the identifier attribute.
+ *
+ * @param obj the object for which the reference is written.
+ * @param xml the output XML element.
+ * @return <code>true</code> if a reference is written;
+ * <code>false</code> if a new identifier is written.
+ */
+ public boolean writeReference(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ Index id = (Index) _objectToId.get(obj);
+ if (id == null) { // New identifier.
+ id = Index.valueOf(_counter++);
+ _objectToId.put(obj, id);
+ _tmp.clear().append(id.intValue());
+ if (_idURI == null) {
+ xml.getStreamWriter().writeAttribute(_idName, _tmp);
+ } else {
+ xml.getStreamWriter().writeAttribute(_idURI, _idName, _tmp);
+ }
+ return false;
+ }
+ _tmp.clear().append(id.intValue());
+ if (_refURI == null) {
+ xml._writer.writeAttribute(_refName, _tmp);
+ } else {
+ xml._writer.writeAttribute(_refURI, _refName, _tmp);
+ }
+ return true;
+ }
+
+ private TextBuilder _tmp = new TextBuilder();
+
+ /**
+ * Reads the object referenced by the specified xml input element if any.
+ * The default implementation reads the reference attribute to retrieve
+ * the object.
+ *
+ * @param xml the input XML element.
+ * @return the referenced object or <code>null</code> if the specified
+ * XML input does not have a reference attribute.
+ */
+ public Object readReference(XMLFormat.InputElement xml)
+ throws XMLStreamException {
+ CharArray value = xml._reader.getAttributeValue(_refURI, _refName);
+ if (value == null)
+ return null;
+ int ref = value.toInt();
+ if (ref >= _idToObject.size())
+ throw new XMLStreamException("Reference: " + value + " not found");
+ return _idToObject.get(ref);
+ }
+
+ /**
+ * Creates a reference for the specified object (the identifier
+ * being specified by the input XML element).
+ * The default implementation reads the identifier attribute (if any)
+ * and associates it to the specified object.
+ *
+ * @param obj the object being referenced.
+ * @param xml the input XML element holding the reference identifier.
+ */
+ public void createReference(Object obj, XMLFormat.InputElement xml)
+ throws XMLStreamException {
+ CharArray value = xml._reader.getAttributeValue(_idURI, _idName);
+ if (value == null)
+ return;
+ int i = value.toInt();
+ if (_idToObject.size() != i)
+ throw new XMLStreamException("Identifier discontinuity detected "
+ + "(expected " + _idToObject.size() + " found " + i + ")");
+ _idToObject.add(obj);
+ }
+
+ public void reset() {
+ _idName = "id";
+ _idURI = null;
+ _refName = "ref";
+ _refURI = null;
+ _idToObject.clear();
+ _objectToId.clear();
+ _counter = 0;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java
new file mode 100644
index 0000000..46cacde
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java
@@ -0,0 +1,47 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2007 - 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.xml;
+
+import java.io.Serializable;
+
+/**
+ * <p> This interface identifies classes supporting XML serialization
+ * (XML serialization is still possible for classes not implementing this
+ * interface through dynamic {@link XMLBinding} though).</p>
+ *
+ * <p> Typically, classes implementing this interface have a protected static
+ * {@link XMLFormat} holding their default XML representation.
+ * For example:[code]
+ * public final class Complex implements XMLSerializable {
+ *
+ * // Use the cartesien form for the default XML representation.
+ * protected static final XMLFormat<Complex> XML = new XMLFormat<Complex>(Complex.class) {
+ * public Complex newInstance(Class<Complex> cls, InputElement xml) throws XMLStreamException {
+ * return Complex.valueOf(xml.getAttribute("real", 0.0),
+ * xml.getAttribute("imaginary", 0.0));
+ * }
+ * public void write(Complex complex, OutputElement xml) throws XMLStreamException {
+ * xml.setAttribute("real", complex.getReal());
+ * xml.setAttribute("imaginary", complex.getImaginary());
+ * }
+ * public void read(InputElement xml, Complex complex) {
+ * // Immutable, deserialization occurs at creation, ref. newIntance(...)
+* }
+ * };
+ * ...
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.2, April 15, 2007
+ */
+public interface XMLSerializable extends Serializable {
+
+ // No method. Tagging interface.
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png b/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png
new file mode 100644
index 0000000..46c6efd
Binary files /dev/null and b/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png differ
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java
new file mode 100644
index 0000000..d4a3f6b
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java
@@ -0,0 +1,151 @@
+/*
+ * 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.xml.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import javolution.util.FastMap;
+import javolution.xml.DefaultXMLFormat;
+import javolution.xml.XMLContext;
+import javolution.xml.XMLFormat;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * Holds the default implementation of XMLContext.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+@SuppressWarnings("rawtypes")
+public final class XMLContextImpl extends XMLContext {
+
+ private final FastMap<Class<?>, XMLFormat<?>> formats = new FastMap<Class<?>, XMLFormat<?>>();
+
+ @Override
+ protected XMLContext inner() {
+ XMLContextImpl ctx = new XMLContextImpl();
+ ctx.formats.putAll(formats);
+ return ctx;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> XMLFormat<T> searchFormat(Class<? extends T> type) {
+ XMLFormat xml = formats.get(type);
+ if (xml != null)
+ return xml;
+ DefaultXMLFormat format = type.getAnnotation(DefaultXMLFormat.class);
+ if (format != null) {
+ Class<? extends XMLFormat> formatClass = format.value();
+ try {
+ xml = formatClass.newInstance();
+ synchronized (formats) { // Required since possible concurrent use
+ // (getFormatInContext is not a configuration method).
+ formats.put(type, xml);
+ }
+ return xml;
+ } catch (Throwable ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ // Check predefined format as last resource.
+ if (Map.class.isAssignableFrom(type))
+ return MAP_XML;
+ if (Collection.class.isAssignableFrom(type))
+ return COLLECTION_XML;
+ return OBJECT_XML;
+ }
+
+ @Override
+ public <T> void setFormat(Class<? extends T> type, XMLFormat<T> format) {
+ formats.put(type, format);
+ }
+
+ /////////////////////////
+ // PREDEFINED FORMATS //
+ /////////////////////////
+ /**
+ * Holds the static XML format for <code>java.lang.Object.class</code> instances.
+ * The XML representation consists of the text representation of the object
+ * as a "value" attribute.
+ */
+ private static final XMLFormat OBJECT_XML = new XMLFormat.Default();
+
+ /**
+ * Holds the default XML representation for <code>java.util.Collection</code>
+ * instances. This representation consists of nested XML elements one for
+ * each element of the collection. The elements' order is defined by
+ * the collection iterator order. Collections are deserialized using their
+ * default constructor.
+ */
+ private static final XMLFormat COLLECTION_XML = new XMLFormat() {
+
+ @SuppressWarnings("unchecked")
+ public void read(XMLFormat.InputElement xml, Object obj)
+ throws XMLStreamException {
+ Collection collection = (Collection) obj;
+ while (xml.hasNext()) {
+ collection.add(xml.getNext());
+ }
+ }
+
+ public void write(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ Collection collection = (Collection) obj;
+ for (Iterator i = collection.iterator(); i.hasNext();) {
+ xml.add(i.next());
+ }
+ }
+
+ };
+
+ /**
+ * Holds the default XML representation for <code>java.util.Map</code>
+ * instances. This representation consists of key/value pair as nested
+ * XML elements. For example:[code]
+ * <javolution.util.FastMap>
+ * <Key class="java.lang.String" value="ONE"/>
+ * <Value class="java.lang.Integer" value="1"/>
+ * <Key class="java.lang.String" value="TWO"/>
+ * <Value class="java.lang.Integer" value="2"/>
+ * <Key class="java.lang.String" value="THREE"/>
+ * <Value class="java.lang.Integer" value="3"/>
+ * </javolution.util.FastMap>[/code]
+ *
+ * The elements' order is defined by the map's entries iterator order.
+ * Maps are deserialized using their default constructor.
+ */
+ private static final XMLFormat MAP_XML = new XMLFormat() {
+
+ @SuppressWarnings("unchecked")
+ public void read(XMLFormat.InputElement xml, Object obj)
+ throws XMLStreamException {
+ final Map map = (Map) obj;
+ while (xml.hasNext()) {
+ Object key = xml.get("Key");
+ Object value = xml.get("Value");
+ map.put(key, value);
+ }
+ }
+
+ public void write(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ final Map map = (Map) obj;
+ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ xml.add(entry.getKey(), "Key");
+ xml.add(entry.getValue(), "Value");
+ }
+ }
+
+ };
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java
new file mode 100644
index 0000000..9953441
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java
@@ -0,0 +1,170 @@
+package javolution.xml.internal.stream;
+
+import javolution.text.CharArray;
+import javolution.util.FastTable;
+import javolution.xml.sax.Attributes;
+
+/**
+ * This class provides the implementation of the {@link Attributes}
+ * interface for the StAX parser.
+ */
+public final class AttributesImpl implements Attributes {
+
+ /**
+ * Attribute implementation.
+ */
+ private static class AttributeImpl {
+ CharArray localName;
+ CharArray prefix; // null if no namespace URI.
+ CharArray qName;
+ CharArray value;
+ public String toString() {
+ return qName + "=" + value;
+ }
+ }
+
+ private static final CharArray CDATA = new CharArray("CDATA");
+
+ private static final CharArray EMPTY = new CharArray();
+
+ /**
+ * Holds the attributes.
+ */
+ private final FastTable<AttributeImpl> attributes = new FastTable<AttributeImpl>();
+
+ /**
+ * Holds the current number of attributes set.
+ */
+ private int length;
+
+ /**
+ * Holds the namespace stack.
+ */
+ private final NamespacesImpl namespaces;
+
+ /**
+ * Creates a list of attribute using the specified namespace stack.
+ */
+ public AttributesImpl(NamespacesImpl namespaces) {
+ this.namespaces = namespaces;
+ }
+
+ /**
+ * Adds an attribute to the end of the attribute list.
+ *
+ * @param localName the local name.
+ * @param prefix the prefix or <code>null</code> if none.
+ * @param qName the qualified (prefixed) name.
+ * @param value the attribute value.
+ */
+ public void addAttribute(CharArray localName, CharArray prefix,
+ CharArray qName, CharArray value) {
+ AttributeImpl attribute;
+ if (length >= attributes.size()) {
+ attribute = new AttributeImpl();
+ attributes.add(attribute);
+ } else {
+ attribute = attributes.get(length);
+ }
+ attribute.localName = localName;
+ attribute.prefix = prefix;
+ attribute.qName = qName;
+ attribute.value = value;
+ length++;
+ }
+
+ @Override
+ public int getIndex(CharSequence qName) {
+ for (int i = 0; i < length; i++) {
+ if (qName.equals(attributes.get(i).qName))
+ return i;
+ }
+ return -1;
+ }
+
+ @Override
+ public int getIndex(CharSequence uri, CharSequence localName) {
+ for (int i = 0; i < length; i++) {
+ AttributeImpl attribute = attributes.get(i);
+ if (localName.equals(attribute.localName)) {
+ if (attribute.prefix == null) { // No namespace URI.
+ if (uri.length() == 0)
+ return i;
+ } else { // Check if matching namespace URI.
+ if (uri.equals(namespaces.getNamespaceURI(attribute.prefix)))
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getLength() {
+ return length;
+ }
+
+ @Override
+ public CharArray getLocalName(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).localName;
+ }
+
+ public CharArray getPrefix(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).prefix;
+ }
+
+ @Override
+ public CharArray getQName(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).qName;
+ }
+
+ @Override
+ public CharArray getType(CharSequence qName) {
+ return (getIndex(qName) >= 0) ? CDATA : null;
+ }
+
+ @Override
+ public CharArray getType(CharSequence uri, CharSequence localName) {
+ return (getIndex(uri, localName) >= 0) ? CDATA : null;
+ }
+
+ @Override
+ public CharArray getType(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return CDATA;
+ }
+ @Override
+ public CharArray getURI(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ CharArray prefix = attributes.get(index).prefix;
+ return (prefix == null) ? EMPTY : namespaces.getNamespaceURI(prefix);
+ }
+
+ @Override
+ public CharArray getValue(CharSequence qName) {
+ final int index = getIndex(qName);
+ return (index >= 0) ? attributes.get(index).value : null;
+ }
+
+ @Override
+ public CharArray getValue(CharSequence uri, CharSequence localName) {
+ final int index = getIndex(uri, localName);
+ return (index >= 0) ? attributes.get(index).value : null;
+ }
+
+ @Override
+ public CharArray getValue(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).value;
+ }
+
+ /**
+ * Clear the attribute list for reuse.
+ */
+ public void reset() {
+ length = 0;
+ }
+}
\ 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/xml/internal/stream/EntitiesImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java
new file mode 100644
index 0000000..72422d3
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java
@@ -0,0 +1,155 @@
+/*
+ * 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.xml.internal.stream;
+
+import java.util.Map;
+
+import javolution.text.CharArray;
+import javolution.util.FastTable;
+import javolution.util.function.Function;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * Defines entities while parsing.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2006
+ */
+public final class EntitiesImpl {
+
+ /**
+ * Holds maximum length.
+ */
+ private int _maxLength = 1;
+
+ /**
+ * Holds the user defined entities mapping.
+ */
+ private Map<String, String> _entitiesMapping;
+
+ /**
+ * Default constructor.
+ */
+ EntitiesImpl() {}
+
+ /**
+ * Returns the length of the largest entity defined (default {@code 1}).
+ */
+ public int getMaxLength() {
+ return _maxLength;
+ }
+
+ /**
+ * Replaces the entity at the specified position.
+ * The five predefined XML entities "&lt;", "&gt;", "&apos;",
+ * "&quot;", "&amp;" as well as character refererences
+ * (decimal or hexadecimal) are always recognized.
+ *
+ * @param buffer the data buffer.
+ * @param start the index of entity first character (index of '&')
+ * @return the length of the replacement entity (including ';')
+ * @throws XMLStreamException if the entity is not recognized.
+ */
+ public int replaceEntity(char[] buffer, int start, int length)
+ throws XMLStreamException {
+
+ // Checks for character references.
+ if (buffer[start + 1] == '#') {
+ char c = buffer[start + 2];
+ int base = (c == 'x') ? 16 : 10;
+ int i = (c == 'x') ? 3 : 2;
+ int charValue = 0;
+ for (; i < length - 1; i++) {
+ c = buffer[start + i];
+ charValue *= base;
+ charValue += (c <= '9') ? (c - '0') : (c <= 'Z') ? c - 'A'
+ : c - 'a';
+ }
+ buffer[start] = (char) charValue;
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'l') && (buffer[start + 2] == 't')
+ && (buffer[start + 3] == ';')) {
+ buffer[start] = '<';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'g') && (buffer[start + 2] == 't')
+ && (buffer[start + 3] == ';')) {
+ buffer[start] = '>';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'a') && (buffer[start + 2] == 'p')
+ && (buffer[start + 3] == 'o') && (buffer[start + 4] == 's')
+ && (buffer[start + 5] == ';')) {
+ buffer[start] = '\'';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'q') && (buffer[start + 2] == 'u')
+ && (buffer[start + 3] == 'o') && (buffer[start + 4] == 't')
+ && (buffer[start + 5] == ';')) {
+ buffer[start] = '"';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'a') && (buffer[start + 2] == 'm')
+ && (buffer[start + 3] == 'p') && (buffer[start + 4] == ';')) {
+ buffer[start] = '&';
+ return 1;
+ }
+
+ // Searches user defined entities.
+ _tmp.setArray(buffer, start + 1, length - 2);
+ CharSequence replacementText = (_entitiesMapping != null) ? _entitiesMapping
+ .get(_tmp) : null;
+ if (replacementText == null)
+ throw new XMLStreamException("Entity " + _tmp + " not recognized");
+ int replacementTextLength = replacementText.length();
+ for (int i = 0; i < replacementTextLength; i++) {
+ buffer[start + i] = replacementText.charAt(i);
+ }
+ return replacementTextLength;
+ }
+
+ private CharArray _tmp = new CharArray();
+
+ /**
+ * Sets the current custom entity mapping. For example: {@code
+ * new FastMap().put("copy", "©")} to define the copyright entity.
+ */
+ public void setEntitiesMapping(Map<String, String> entityToReplacementText) {
+ FastTable<String> values = new FastTable<String>();
+ values.addAll(entityToReplacementText.values());
+ _maxLength = values.mapped(new Function<CharSequence, Integer>() {
+
+ @Override
+ public Integer apply(CharSequence csq) {
+ return csq.length();
+ }}).max();
+
+ _entitiesMapping = entityToReplacementText;
+ }
+
+ /**
+ * Returns the custom entity mapping or {@code null} if none.
+ */
+ public Map<String, String> getEntitiesMapping() {
+ return _entitiesMapping;
+ }
+
+ // Implements Reusable.
+ public void reset() {
+ _maxLength = 1;
+ _entitiesMapping = null;
+ }
+
+}
[06/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SubTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SubTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SubTableImpl.java
new file mode 100644
index 0000000..682a900
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SubTableImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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.internal.table;
+
+import javolution.util.function.Equality;
+import javolution.util.service.TableService;
+
+/**
+ * A view over a portion of a table.
+ */
+public class SubTableImpl<E> extends TableView<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /** Splits the specified table. */
+ @SuppressWarnings("unchecked")
+ public static <E> TableService<E>[] splitOf(TableService<E> table,
+ int n, boolean updateable) {
+ if (updateable) table = new SharedTableImpl<E>(table);
+ if (n < 1) throw new IllegalArgumentException("Invalid argument n: "
+ + n);
+ TableService<E>[] subTables = new TableService[n];
+ int minSize = table.size() / n;
+ int start = 0;
+ for (int i = 0; i < n - 1; i++) {
+ subTables[i] = new SubTableImpl<E>(table, start, start + minSize);
+ start += minSize;
+ }
+ subTables[n - 1] = new SubTableImpl<E>(table, start, table.size());
+ return subTables;
+ }
+
+ protected final int fromIndex;
+ protected int toIndex;
+
+ public SubTableImpl(TableService<E> target, int from, int to) {
+ super(target);
+ if ((from < 0) || (to > target.size()) || (from > to)) throw new IndexOutOfBoundsException(
+ "fromIndex: " + from + ", toIndex: " + to + ", size(): "
+ + target.size()); // As per List.subList contract.
+ fromIndex = from;
+ toIndex = to;
+ }
+
+ @Override
+ public boolean add(E element) {
+ target().add(toIndex++, element);
+ return true;
+ }
+
+ @Override
+ public void add(int index, E element) {
+ if ((index < 0) && (index > size())) indexError(index);
+ target().add(index + fromIndex, element);
+ toIndex++;
+ }
+
+ @Override
+ public void clear() {
+ for (int i = toIndex - 1; i >= fromIndex; i--) { // Better to do it from the end (less shift).
+ target().remove(i);
+ }
+ toIndex = fromIndex;
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public E get(int index) {
+ if ((index < 0) && (index >= size())) indexError(index);
+ return target().get(index + fromIndex);
+ }
+
+ @Override
+ public E remove(int index) {
+ if ((index < 0) && (index >= size())) indexError(index);
+ toIndex--;
+ return target().remove(index + fromIndex);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ if ((index < 0) && (index >= size())) indexError(index);
+ return target().set(index + fromIndex, element);
+ }
+
+ @Override
+ public int size() {
+ return toIndex - fromIndex;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableIteratorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableIteratorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableIteratorImpl.java
new file mode 100644
index 0000000..913e9a0
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableIteratorImpl.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.util.internal.table;
+
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.service.TableService;
+
+/**
+ * A generic iterator over a table.
+ */
+public final class TableIteratorImpl<E> implements ListIterator<E> {
+
+ private int currentIndex = -1;
+ private int end;
+ private int nextIndex;
+ private final TableService<E> table;
+
+ public TableIteratorImpl(TableService<E> table, int index) {
+ this.table = table;
+ this.nextIndex = index;
+ this.end = table.size();
+ }
+
+ @Override
+ public void add(E e) {
+ table.add(nextIndex++, e);
+ end++;
+ currentIndex = -1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return (nextIndex < end);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return nextIndex > 0;
+ }
+
+ @Override
+ public E next() {
+ if (nextIndex >= end) throw new NoSuchElementException();
+ currentIndex = nextIndex++;
+ return table.get(currentIndex);
+ }
+
+ @Override
+ public int nextIndex() {
+ return nextIndex;
+ }
+
+ @Override
+ public E previous() {
+ if (nextIndex <= 0) throw new NoSuchElementException();
+ currentIndex = --nextIndex;
+ return table.get(currentIndex);
+ }
+
+ @Override
+ public int previousIndex() {
+ return nextIndex - 1;
+ }
+
+ @Override
+ public void remove() {
+ if (currentIndex < 0) throw new IllegalStateException();
+ table.remove(currentIndex);
+ end--;
+ if (currentIndex < nextIndex) {
+ nextIndex--;
+ }
+ currentIndex = -1;
+ }
+
+ @Override
+ public void set(E e) {
+ if (currentIndex >= 0) {
+ table.set(currentIndex, e);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableView.java
new file mode 100644
index 0000000..eaa8a4d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/TableView.java
@@ -0,0 +1,259 @@
+/*
+ * 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.internal.table;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.function.Equality;
+import javolution.util.internal.collection.CollectionView;
+import javolution.util.service.TableService;
+
+/**
+ * Table view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ */
+public abstract class TableView<E> extends CollectionView<E> implements TableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public TableView(TableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public abstract void add(int index, E element);
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
+ return subList(index, index).addAll(c);
+ }
+
+ @Override
+ public void addFirst(E element) {
+ add(0, element);
+ }
+
+ @Override
+ public void addLast(E element) {
+ add(size(), element);
+ }
+
+ @Override
+ public abstract void clear();
+
+ @Override
+ public final boolean contains(Object o) {
+ return indexOf(o) >= 0;
+ }
+
+ @Override
+ public Iterator<E> descendingIterator() {
+ return new ReversedTableImpl<E>(this).iterator();
+ }
+
+ @Override
+ public final E element() {
+ return getFirst();
+ }
+
+ @Override
+ public abstract E get(int index);
+
+ @Override
+ public E getFirst() {
+ if (size() == 0) emptyError();
+ return get(0);
+ }
+
+ @Override
+ public E getLast() {
+ if (size() == 0) emptyError();
+ return get(size() - 1);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int indexOf(Object o) {
+ Equality<Object> cmp = (Equality<Object>) this.comparator();
+ for (int i = 0, n = size(); i < n; i++) {
+ if (cmp.areEqual(o, get(i))) return i;
+ }
+ return -1;
+ }
+
+ @Override
+ public final boolean isEmpty() {
+ return size() == 0;
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return listIterator(0);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int lastIndexOf(Object o) {
+ Equality<Object> cmp = (Equality<Object>) this.comparator();
+ for (int i = size() - 1; i >= 0; i--) {
+ if (cmp.areEqual(o, get(i))) return i;
+ }
+ return -1;
+ }
+
+ @Override
+ public final ListIterator<E> listIterator() {
+ return listIterator(0);
+ }
+
+ @Override
+ public ListIterator<E> listIterator(int index) {
+ return new TableIteratorImpl<E>(this, index);
+ }
+
+ @Override
+ public final boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ @Override
+ public final boolean offerFirst(E e) {
+ addFirst(e);
+ return true;
+ }
+
+ @Override
+ public final boolean offerLast(E e) {
+ addLast(e);
+ return true;
+ }
+
+ @Override
+ public final E peek() {
+ return peekFirst();
+ }
+
+ @Override
+ public E peekFirst() {
+ return (size() == 0) ? null : getFirst();
+ }
+
+ @Override
+ public E peekLast() {
+ return (size() == 0) ? null : getLast();
+ }
+
+ @Override
+ public final E poll() {
+ return pollFirst();
+ }
+
+ @Override
+ public E pollFirst() {
+ return (size() == 0) ? null : removeFirst();
+ }
+
+ @Override
+ public E pollLast() {
+ return (size() == 0) ? null : removeLast();
+ }
+
+ @Override
+ public final E pop() {
+ return removeFirst();
+ }
+
+ @Override
+ public final void push(E e) {
+ addFirst(e);
+ }
+
+ @Override
+ public final E remove() {
+ return removeFirst();
+ }
+
+ @Override
+ public abstract E remove(int index);
+
+ @Override
+ public final boolean remove(Object o) {
+ int i = indexOf(o);
+ if (i < 0) return false;
+ remove(i);
+ return true;
+ }
+
+ @Override
+ public E removeFirst() {
+ if (size() == 0) emptyError();
+ return remove(0);
+ }
+
+ @Override
+ public boolean removeFirstOccurrence(Object o) {
+ int i = indexOf(o);
+ if (i < 0) return false;
+ remove(i);
+ return true;
+ }
+
+ @Override
+ public E removeLast() {
+ if (size() == 0) emptyError();
+ return remove(size() - 1);
+ }
+
+ @Override
+ public boolean removeLastOccurrence(Object o) {
+ int i = lastIndexOf(o);
+ if (i < 0) return false;
+ remove(i);
+ return true;
+ }
+
+ @Override
+ public abstract E set(int index, E element);
+
+ @Override
+ public abstract int size();
+
+ @Override
+ public TableService<E>[] split(int n, boolean updateable) {
+ return SubTableImpl.splitOf(this, n, updateable); // Sub-views over this.
+ }
+
+ @Override
+ public TableService<E> subList(int fromIndex, int toIndex) {
+ return new SubTableImpl<E>(this, fromIndex, toIndex);
+ }
+
+ /** Throws NoSuchElementException */
+ protected void emptyError() {
+ throw new NoSuchElementException("Empty Table");
+ }
+
+ /** Throws IndexOutOfBoundsException */
+ protected void indexError(int index) {
+ throw new IndexOutOfBoundsException("index: " + index + ", size: "
+ + size());
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected TableService<E> target() {
+ return (TableService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/UnmodifiableTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/UnmodifiableTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/UnmodifiableTableImpl.java
new file mode 100644
index 0000000..138723f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/UnmodifiableTableImpl.java
@@ -0,0 +1,84 @@
+/*
+ * 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.internal.table;
+
+import javolution.util.function.Equality;
+import javolution.util.service.TableService;
+
+/**
+ * An unmodifiable view over a table.
+ */
+public class UnmodifiableTableImpl<E> extends TableView<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableTableImpl(TableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean add(E element) {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public void add(int index, E element) {
+ throw new UnsupportedOperationException("Unmodifiable");
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public E get(int index) {
+ return target().get(index);
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return target().indexOf(o);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return target().lastIndexOf(o);
+ }
+
+ @Override
+ public E remove(int index) {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public E set(int index, E element) {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @Override
+ public TableService<E>[] split(int n, boolean updateable) {
+ return SubTableImpl.splitOf(this, n, false); // Sub-views over this.
+ }
+
+ @Override
+ protected TableService<E> target() {
+ return (TableService<E>) super.target();
+ }
+ }
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/AtomicSortedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/AtomicSortedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/AtomicSortedTableImpl.java
new file mode 100644
index 0000000..3e624e4
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/AtomicSortedTableImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.internal.table.sorted;
+
+import javolution.util.internal.table.AtomicTableImpl;
+import javolution.util.service.SortedTableService;
+import javolution.util.service.TableService;
+
+/**
+ * An atomic view over a sorted table.
+ */
+public class AtomicSortedTableImpl<E> extends AtomicTableImpl<E> implements
+ SortedTableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public AtomicSortedTableImpl(TableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public synchronized boolean addIfAbsent(E element) {
+ boolean changed = target().addIfAbsent(element);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public int positionOf(E element) {
+ return targetView().positionOf(element);
+ }
+
+ @Override
+ public SortedTableService<E>[] split(int n, boolean updateable) {
+ return SubSortedTableImpl.splitOf(this, n, false); // Sub-views over this.
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected SortedTableService<E> target() {
+ return (SortedTableService<E>) super.target();
+ }
+
+ @Override
+ protected SortedTableService<E> targetView() {
+ return (SortedTableService<E>) super.targetView();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/FastSortedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/FastSortedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/FastSortedTableImpl.java
new file mode 100644
index 0000000..0fbd5ef
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/FastSortedTableImpl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.internal.table.sorted;
+
+import javolution.util.function.Equality;
+import javolution.util.internal.table.FastTableImpl;
+import javolution.util.service.SortedTableService;
+
+/**
+ * The default {@link javolution.util.FastSortedTable FastSortedTable} implementation.
+ */
+public class FastSortedTableImpl<E> extends FastTableImpl<E> implements
+ SortedTableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public FastSortedTableImpl(Equality<? super E> comparator) {
+ super(comparator);
+ }
+
+ @Override
+ public boolean add(E element) {
+ add(positionOf(element), element);
+ return true;
+ }
+
+ @Override
+ public boolean addIfAbsent(E element) {
+ int i = positionOf(element);
+ if ((i < size()) && comparator().areEqual(element, get(i))) return false; // Already there.
+ add(i, element);
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int indexOf(Object element) {
+ int i = positionOf((E) element);
+ if (i >= size() || !comparator().areEqual(get(i), (E) element)) return -1;
+ return i;
+ }
+
+ @Override
+ public int positionOf(E element) {
+ return positionOf(element, 0, size());
+ }
+
+ @Override
+ public SortedTableService<E>[] split(int n, boolean updateable) {
+ return SubSortedTableImpl.splitOf(this, n, updateable); // Sub-views over this.
+ }
+
+ private int positionOf(E element, int start, int length) {
+ if (length == 0) return start;
+ int half = length >> 1;
+ return (comparator().compare(element, get(start + half)) <= 0) ? positionOf(
+ element, start, half) : positionOf(element, start + half + 1,
+ length - half - 1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SharedSortedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SharedSortedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SharedSortedTableImpl.java
new file mode 100644
index 0000000..8b8ebfe
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SharedSortedTableImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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.internal.table.sorted;
+
+import javolution.util.internal.table.SharedTableImpl;
+import javolution.util.service.SortedTableService;
+
+/**
+ * A shared view over a sorted table allowing concurrent access and sequential updates.
+ */
+public class SharedSortedTableImpl<E> extends SharedTableImpl<E> implements
+ SortedTableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SharedSortedTableImpl(SortedTableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean addIfAbsent(E element) {
+ lock.writeLock.lock();
+ try {
+ return target().addIfAbsent(element);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public int positionOf(E element) {
+ lock.readLock.lock();
+ try {
+ return target().positionOf(element);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public SortedTableService<E>[] split(int n, boolean updateable) {
+ return SubSortedTableImpl.splitOf(this, n, false); // Sub-views over this.
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected SortedTableService<E> target() {
+ return (SortedTableService<E>) super.target();
+ }
+
+}
\ 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/util/internal/table/sorted/SortedTableView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SortedTableView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SortedTableView.java
new file mode 100644
index 0000000..0c212b3
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SortedTableView.java
@@ -0,0 +1,68 @@
+/*
+ * 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.internal.table.sorted;
+
+import javolution.util.internal.table.TableView;
+import javolution.util.service.SortedTableService;
+
+/**
+ * Sorted table view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ */
+public abstract class SortedTableView<E> extends TableView<E> implements
+ SortedTableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public SortedTableView(SortedTableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean addIfAbsent(E element) {
+ if (!contains(element)) return add(element);
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int indexOf(Object o) {
+ int i = positionOf((E) o);
+ if ((i >= size()) || !comparator().areEqual((E) o, get(i))) return -1;
+ return i;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int lastIndexOf(Object o) {
+ int i = positionOf((E) o);
+ int result = -1;
+ while ((i < size()) && comparator().areEqual((E) o, get(i))) {
+ result = i++;
+ }
+ return result;
+ }
+
+ @Override
+ public abstract int positionOf(E element);
+
+ @Override
+ public SortedTableService<E>[] split(int n, boolean updateable) {
+ return SubSortedTableImpl.splitOf(this, n, updateable); // Sub-views over this.
+ }
+
+ @Override
+ protected SortedTableService<E> target() {
+ return (SortedTableService<E>) super.target();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SubSortedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SubSortedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SubSortedTableImpl.java
new file mode 100644
index 0000000..7bb9eba
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/SubSortedTableImpl.java
@@ -0,0 +1,87 @@
+/*
+ * 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.internal.table.sorted;
+
+import javolution.util.internal.table.SubTableImpl;
+import javolution.util.service.SortedTableService;
+import javolution.util.service.TableService;
+
+/**
+ * A view over a portion of a sorted table.
+ */
+public class SubSortedTableImpl<E> extends SubTableImpl<E> implements SortedTableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /** Splits the specified table. */
+ @SuppressWarnings("unchecked")
+ public static <E> SortedTableService<E>[] splitOf(SortedTableService<E> table,
+ int n, boolean updateable) {
+ if (updateable) table = new SharedSortedTableImpl<E>(table);
+ if (n < 1) throw new IllegalArgumentException("Invalid argument n: "
+ + n);
+ SortedTableService<E>[] subTables = new SortedTableService[n];
+ int minSize = table.size() / n;
+ int start = 0;
+ for (int i = 0; i < n - 1; i++) {
+ subTables[i] = new SubSortedTableImpl<E>(table, start, start + minSize);
+ start += minSize;
+ }
+ subTables[n - 1] = new SubSortedTableImpl<E>(table, start, table.size());
+ return subTables;
+ }
+
+ public SubSortedTableImpl(TableService<E> target, int from, int to) {
+ super(target, from, to);
+ }
+
+ @Override
+ public boolean addIfAbsent(E element) {
+ if (!contains(element)) return add(element);
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int indexOf(Object o) {
+ int i = positionOf((E) o);
+ if ((i >= size()) || !comparator().areEqual((E) o, get(i))) return -1;
+ return i;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int lastIndexOf(Object o) {
+ int i = positionOf((E) o);
+ int result = -1;
+ while ((i < size()) && comparator().areEqual((E) o, get(i))) {
+ result = i++;
+ }
+ return result;
+ }
+
+ @Override
+ public int positionOf(E element) {
+ int i = target().positionOf(element);
+ if (i < fromIndex) return 0;
+ if (i >= toIndex) return size();
+ return i - fromIndex;
+ }
+
+ @Override
+ public SortedTableService<E>[] split(int n, boolean updateable) {
+ return SubSortedTableImpl.splitOf(this, n, updateable); // Sub-views over this.
+ }
+
+ @Override
+ protected SortedTableService<E> target() {
+ return (SortedTableService<E>) super.target();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/UnmodifiableSortedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/UnmodifiableSortedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/UnmodifiableSortedTableImpl.java
new file mode 100644
index 0000000..7c1efff
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/sorted/UnmodifiableSortedTableImpl.java
@@ -0,0 +1,46 @@
+/*
+ * 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.internal.table.sorted;
+
+import javolution.util.internal.table.UnmodifiableTableImpl;
+import javolution.util.service.SortedTableService;
+
+/**
+ * An unmodifiable view over a sorted table.
+ */
+public class UnmodifiableSortedTableImpl<E> extends UnmodifiableTableImpl<E>
+ implements SortedTableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableSortedTableImpl(SortedTableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean addIfAbsent(E element) {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public int positionOf(E element) {
+ return target().positionOf(element);
+ }
+
+ @Override
+ public SortedTableService<E>[] split(int n, boolean updateable) {
+ return SubSortedTableImpl.splitOf(this, n, false); // Sub-views over this.
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected SortedTableService<E> target() {
+ return (SortedTableService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/util/package-info.java
new file mode 100644
index 0000000..697f95f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/package-info.java
@@ -0,0 +1,32 @@
+/**
+<p> High-performance collection classes with {@link javolution.lang.Realtime
+ worst case execution time behavior} documented.</p>
+<p> Whereas Java current evolution leads to more and more classes being parts of
+ the standard library; Javolution approach is quite the opposite. It aims to
+ provide only the quintessential classes from which all others can be derived.
+ </p>
+ <img src="doc-files/architecture.png" />
+
+<h2><a name="FAQ">FAQ:</a></h2>
+<ol>
+ <li><b>Does <b>J</b>avolution provide immutable collections similar to
+ the ones provided by Scala or .NET ?</b>
+ <p> Using <b>J</b>avolution you may return an {@link javolution.lang.Immutable Immutable}
+ reference (const reference) over any object which cannot be modified including collections or maps.
+[code]
+public class UnitSystem {
+ Set<Unit> units;
+ public UnitSystem(Immutable<Set<Unit>> units) {
+ this.units = units.value(); // Defensive copy unnecessary (immutable)
+ }
+}
+...
+Immutable<Set<Unit>> unitsMKSA = new FastSet<Unit>().addAll(M, K, S, A).toImmutable();
+UnitSystem MKSA = new UnitSystem(unitsMKSA);
+[/code]</p>
+ </li>
+</ol>
+
+ */
+package javolution.util;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/service/BitSetService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/BitSetService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/BitSetService.java
new file mode 100644
index 0000000..6c45891
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/BitSetService.java
@@ -0,0 +1,116 @@
+/*
+ * 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.service;
+
+import javolution.util.FastBitSet;
+import javolution.util.FastTable;
+import javolution.util.Index;
+
+/**
+ * The set of related functionalities which can be used/reused to
+ * implement bit-sets collections.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see FastTable
+ */
+public interface BitSetService extends SetService<Index> {
+
+ //
+ // Read Accessors.
+ //
+
+ /** See {@link FastBitSet#cardinality() } */
+ int cardinality();
+
+ /** See {@link FastBitSet#get(int) } */
+ boolean get(int bitIndex);
+
+ /** See {@link FastBitSet#get(int, int) } */
+ BitSetService get(int fromIndex, int toIndex);
+
+ /** See {@link FastBitSet#intersects(FastBitSet) } */
+ boolean intersects(BitSetService that);
+
+ /** See {@link FastBitSet#length() } */
+ int length();
+
+ //
+ // Iterations
+ //
+
+ /** See {@link FastBitSet#nextClearBit(int) } */
+ int nextClearBit(int fromIndex);
+
+ /** See {@link FastBitSet#nextSetBit(int) } */
+ int nextSetBit(int fromIndex);
+
+ /** See {@link FastBitSet#previousClearBit(int) } */
+ int previousClearBit(int fromIndex);
+
+ /** See {@link FastBitSet#previousSetBit(int) } */
+ int previousSetBit(int fromIndex);
+
+ //
+ // Clear/Set/Flip Operations
+ //
+
+ /** See {@link FastBitSet#clear(int) } */
+ void clear(int bitIndex);
+
+ /** See {@link FastBitSet#clear(int, int) } */
+ void clear(int fromIndex, int toIndex);
+
+ /** Clear or sets the specified bit, returns <code>true</code>
+ * if previously set; <code>false</code> otherwise. */
+ boolean getAndSet(int bitIndex, boolean value);
+
+ /** See {@link FastBitSet#set(int) } */
+ void set(int bitIndex);
+
+ /** See {@link FastBitSet#set(int, boolean) } */
+ void set(int bitIndex, boolean value);
+
+ /** See {@link FastBitSet#set(int, int) } */
+ void set(int fromIndex, int toIndex);
+
+ /** See {@link FastBitSet#set(int, int, boolean) } */
+ void set(int fromIndex, int toIndex, boolean value);
+
+ /** See {@link FastBitSet#flip(int) } */
+ void flip(int bitIndex);
+
+ /** See {@link FastBitSet#flip(int, int) } */
+ void flip(int fromIndex, int toIndex);
+
+ //
+ // Operators Operations
+ //
+
+ /** See {@link FastBitSet#and(FastBitSet) } */
+ void and(BitSetService that);
+
+ /** See {@link FastBitSet#andNot(FastBitSet) } */
+ void andNot(BitSetService that);
+
+ /** See {@link FastBitSet#or(FastBitSet) } */
+ void or(BitSetService that);
+
+ /** See {@link FastBitSet#xor(FastBitSet) } */
+ void xor(BitSetService that);
+
+ //
+ // Misc.
+ //
+
+ /** Returns the minimal length <code>long[]</code> representation of this
+ * bitset. */
+ long[] toLongArray();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/service/CollectionService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/CollectionService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/CollectionService.java
new file mode 100644
index 0000000..37dbb8a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/CollectionService.java
@@ -0,0 +1,39 @@
+/*
+ * 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.service;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import javolution.util.function.Equality;
+import javolution.util.function.Splittable;
+
+/**
+ * The fundamental set of related functionalities required to implement
+ * fast collections.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface CollectionService<E> extends Collection<E>,
+ Splittable<CollectionService<E>>, Serializable, Cloneable {
+
+ /**
+ * Returns a copy of this collection; updates of the copy should not
+ * impact the original.
+ */
+ CollectionService<E> clone() throws CloneNotSupportedException;
+
+ /**
+ * Returns the comparator used for element equality or order if the
+ * collection is sorted.
+ */
+ Equality<? super E> comparator();
+
+}
\ 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/util/service/MapService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/MapService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/MapService.java
new file mode 100644
index 0000000..20090a3
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/MapService.java
@@ -0,0 +1,73 @@
+/*
+ * 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.service;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+import javolution.util.function.Equality;
+import javolution.util.function.Splittable;
+
+/**
+ * The set of related map functionalities required to implement fast maps.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see javolution.util.FastMap#FastMap()
+ */
+public interface MapService<K, V> extends
+ Map<K, V>, ConcurrentMap<K, V>, Splittable<MapService<K, V>>, Serializable, Cloneable {
+
+ /**
+ * Returns a copy of this map; updates of the copy should not
+ * impact the original.
+ */
+ MapService<K, V> clone() throws CloneNotSupportedException;
+
+
+ /**
+ * Returns a set view over the entries of this map. The set
+ * support adding/removing entries. Two entries are considered
+ * equals if they have the same key regardless of their values.
+ */
+ @Override
+ SetService<Map.Entry<K, V>> entrySet();
+
+ /**
+ * Returns an iterator over this map entries.
+ */
+ Iterator<Entry<K, V>> iterator();
+
+ /**
+ * Returns the key comparator used for key equality or order if the
+ * map is sorted.
+ */
+ Equality<? super K> keyComparator();
+
+ /**
+ * Returns a set view over the key of this map, the set support
+ * adding new key for which the value is automatically {@code null}.
+ */
+ @Override
+ SetService<K> keySet();
+
+ /**
+ * Returns the value comparator used for value equality.
+ */
+ Equality<? super V> valueComparator();
+
+ /**
+ * Returns a collection view over the values of this map, the collection
+ * support value/entry removal but not adding new values.
+ */
+ @Override
+ CollectionService<V> values();
+}
\ 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/util/service/SetService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/SetService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/SetService.java
new file mode 100644
index 0000000..7d2049a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/SetService.java
@@ -0,0 +1,24 @@
+/*
+ * 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.service;
+
+import java.util.Set;
+
+/**
+ * The set of related functionalities used to implement set collections.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface SetService<E> extends CollectionService<E>, Set<E> {
+
+ @Override
+ SetService<E>[] split(int n, boolean updateable);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedMapService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedMapService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedMapService.java
new file mode 100644
index 0000000..9febb73
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedMapService.java
@@ -0,0 +1,41 @@
+/*
+ * 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.service;
+
+import java.util.Map;
+import java.util.SortedMap;
+
+/**
+ * The set of related functionalities used to implement sorted map.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface SortedMapService<K, V> extends MapService<K, V>,
+ SortedMap<K, V> {
+
+ @Override
+ SortedSetService<Map.Entry<K, V>> entrySet();
+
+ @Override
+ SortedMapService<K, V> headMap(K toKey);
+
+ @Override
+ SortedSetService<K> keySet();
+
+ @Override
+ SortedMapService<K, V> subMap(K fromKey, K toKey);
+
+ @Override
+ SortedMapService<K, V> tailMap(K fromKey);
+
+ @Override
+ SortedMapService<K, V>[] split(int n, boolean updateable);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedSetService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedSetService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedSetService.java
new file mode 100644
index 0000000..5028ae5
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedSetService.java
@@ -0,0 +1,33 @@
+/*
+ * 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.service;
+
+import java.util.SortedSet;
+
+/**
+ * The set of related functionalities used to implement sorted set collections.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface SortedSetService<E> extends SetService<E>, SortedSet<E> {
+
+ @Override
+ SortedSetService<E> headSet(E toElement);
+
+ @Override
+ SortedSetService<E> subSet(E fromElement, E toElement);
+
+ @Override
+ SortedSetService<E> tailSet(E fromElement);
+
+ @Override
+ SortedSetService<E>[] split(int n, boolean updateable);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedTableService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedTableService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedTableService.java
new file mode 100644
index 0000000..74e47e2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/SortedTableService.java
@@ -0,0 +1,36 @@
+/*
+ * 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.service;
+
+/**
+ * The set of related functionalities used to implement sorted tables collections.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface SortedTableService<E> extends TableService<E> {
+
+ /**
+ * Adds the specified element only if not already present.
+ *
+ * @return {@code true} if the element has been added;
+ * {@code false} otherwise.
+ */
+ boolean addIfAbsent(E element);
+
+ /**
+ * Returns what would be the index of the specified element if it were
+ * to be added or the index of the specified element if already present.
+ */
+ int positionOf(E element);
+
+ @Override
+ SortedTableService<E>[] split(int n, boolean updateable);
+
+}
\ 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/util/service/TableService.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/TableService.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/TableService.java
new file mode 100644
index 0000000..21af9d7
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/TableService.java
@@ -0,0 +1,29 @@
+/*
+ * 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.service;
+
+import java.util.List;
+import java.util.Deque;
+import java.util.RandomAccess;
+
+/**
+ * The set of related functionalities used to implement tables collections.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface TableService<E> extends CollectionService<E>, List<E>, Deque<E>, RandomAccess {
+
+ @Override
+ TableService<E> subList(int fromIndex, int toIndex);
+
+ @Override
+ TableService<E>[] split(int n, boolean updateable);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/service/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/service/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/util/service/package-info.java
new file mode 100644
index 0000000..26fa4aa
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/service/package-info.java
@@ -0,0 +1,6 @@
+/**
+<p> Service interfaces to be implemented by {@code javolution.util.*}
+ collections and collections views.</p>
+ */
+package javolution.util.service;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/DefaultXMLFormat.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/DefaultXMLFormat.java b/commons/marmotta-commons/src/ext/java/javolution/xml/DefaultXMLFormat.java
new file mode 100644
index 0000000..f4e894e
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/DefaultXMLFormat.java
@@ -0,0 +1,59 @@
+/*
+ * 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.xml;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * <p> Specifies the default xml format of a class (for xml serialization/deserialization).
+ * The default format is used by the {@link javolution.xml.XMLObjectReader}
+ * and {@link javolution.xml.XMLObjectWriter} classes. It can be locally overridden
+ * in the scope of a {@link javolution.xml.XMLContext XMLContext}.</p>
+ *
+ * [code]
+ * @DefaultXMLFormat(Complex.XML.class)
+ * public class Complex {
+ * public Complex(double real, double imaginary) { ... }
+ * public double getReal() { ... }
+ * public double getImaginary() { ... }
+ * public static class XML extends XMLFormat<Complex> {
+ * public Complex newInstance(Class<? extends Complex> cls, InputElement xml) throws XMLStreamException {
+ * return new Complex(xml.getAttribute("real", 0.0), xml.getAttribute("imaginary", 0.0));
+ * }
+ * public void read(InputElement xml, Complex c) throws XMLStreamException {
+ * // Immutable object, no further processing.
+ * }
+ * public void write(Complex c, OutputElement xml) throws XMLStreamException {
+ * xml.setAttribute("real", c.getReal());
+ * xml.setAttribute("imaginary", c.getImaginary());
+ * }
+ * };
+ * }[/code]
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+@Documented
+@Inherited
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DefaultXMLFormat {
+
+ /**
+ * Returns the default xml format of the annotated class.
+ */
+ Class<? extends XMLFormat<?>> value();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/QName.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/QName.java b/commons/marmotta-commons/src/ext/java/javolution/xml/QName.java
new file mode 100644
index 0000000..0b8298a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/QName.java
@@ -0,0 +1,233 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2007 - 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.xml;
+
+import java.io.ObjectStreamException;
+import java.lang.CharSequence;
+
+import javolution.lang.Immutable;
+import javolution.text.CharArray;
+import javolution.text.TextBuilder;
+import javolution.util.FastMap;
+import javolution.util.function.Equalities;
+
+/**
+ * <p> This class represents unique identifiers for XML elements (tags) or
+ * attributes (names).</p>
+ *
+ * <p> It should be noted that <code>QName.valueOf(null, "name")</code> and
+ * <code>QName.valueOf("", "name")</code> are distinct; the first one has no
+ * namespace associated with; whereas the second is associated
+ * to the root namespace.</p>
+ *
+ * <p> {@link QName} have a textual representation ({@link CharSequence}) which
+ * is either the local name (if no namespace URI) or
+ * <code>{namespaceURI}localName</code> (otherwise).</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.3, January 14, 2007
+ * @see <a href="http://en.wikipedia.org/wiki/Qname">Wikipedia: QName</a>
+ */
+public final class QName implements XMLSerializable, Immutable<QName>, CharSequence {
+
+ /**
+ * Holds the local name.
+ */
+ private transient final CharArray _localName;
+
+ /**
+ * Holds the namespace URI reference or <code>null</code> if none.
+ */
+ private transient final CharArray _namespaceURI;
+
+ /**
+ * Holds the string representation.
+ */
+ private final String _toString;
+
+ /**
+ * Holds the full name (String) to QName mapping.
+ */
+ private static final FastMap<CharSequence, QName> FULL_NAME_TO_QNAME = new FastMap<CharSequence, QName>(
+ Equalities.LEXICAL);
+
+ /**
+ * Creates a qualified name having the specified local name and namespace
+ * reference.
+ *
+ * @param namespaceURI the URI reference or <code>null</code> if none.
+ * @param localName the local name.
+ * @param toString the string representation.
+ */
+ private QName(String namespaceURI, String localName, String toString) {
+ _namespaceURI = (namespaceURI == null) ? null : new CharArray(
+ namespaceURI);
+ _localName = new CharArray(localName);
+ _toString = toString;
+ }
+
+ /**
+ * Returns the qualified name corresponding to the specified character
+ * sequence representation (may include the "{namespaceURI}" prefix).
+ *
+ * @param name the qualified name lexical representation.
+ * @see #toString()
+ */
+ public static QName valueOf(CharSequence name) {
+ QName qName = (QName) FULL_NAME_TO_QNAME.get(name);
+ return (qName != null) ? qName : QName.createNoNamespace(name
+ .toString());
+ }
+
+ private static QName createNoNamespace(String name) {
+ String localName = name;
+ String namespaceURI = null;
+ if (name.length() > 0 && name.charAt(0) == '{') { // Namespace URI.
+ int index = name.lastIndexOf('}');
+ localName = name.substring(index + 1);
+ namespaceURI = name.substring(1, index);
+ }
+ QName qName = new QName(namespaceURI, localName, name);
+ synchronized (FULL_NAME_TO_QNAME) {
+ QName tmp = (QName) FULL_NAME_TO_QNAME.putIfAbsent(name, qName);
+ return tmp == null ? qName : tmp;
+ }
+ }
+
+ /**
+ * Equivalent to {@link #valueOf(CharSequence)} (for J2ME compatibility).
+ *
+ * @param name the qualified name lexical representation.
+ * @see #toString()
+ */
+ public static QName valueOf(String name) {
+ QName qName = (QName) FULL_NAME_TO_QNAME.get(name);
+ return (qName != null) ? qName : QName.createNoNamespace(name);
+ }
+
+ /**
+ * Returns the qualified name corresponding to the specified namespace URI
+ * and local name.
+ *
+ * @param namespaceURI the URI reference or <code>null</code> if none.
+ * @param localName the local name.
+ * @see #toString()
+ */
+ public static QName valueOf(CharSequence namespaceURI,
+ CharSequence localName) {
+ if (namespaceURI == null)
+ return QName.valueOf(localName);
+ TextBuilder tmp = new TextBuilder();
+ tmp.append('{');
+ tmp.append(namespaceURI);
+ tmp.append('}');
+ tmp.append(localName);
+ return QName.valueOf(tmp);
+ }
+
+ /**
+ * Returns the local part of this qualified name or the full qualified
+ * name if there is no namespace.
+ *
+ * @return the local name.
+ */
+ public CharSequence getLocalName() {
+ return _localName;
+ }
+
+ /**
+ * Returns the namespace URI of this qualified name or <code>null</code>
+ * if none (the local name is then the full qualified name).
+ *
+ * @return the URI reference or <code>null</code>
+ */
+ public CharSequence getNamespaceURI() {
+ return _namespaceURI;
+ }
+
+ /**
+ * Instances of this class are unique; object's equality can be
+ * replaced object identity (<code>==</code>).
+ *
+ * @return <code>this == obj</code>
+ */
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+
+ /**
+ * Returns the <code>String</code> representation of this qualified name.
+ *
+ * @return the textual representation.
+ */
+ public String toString() {
+ return _toString;
+ }
+
+ /**
+ * Returns the hash code for this qualified name.
+ *
+ * <p> Note: Returns the same hashCode as <code>java.lang.String</code>
+ * (consistent with {@link #equals})</p>
+ * @return the hash code value.
+ */
+ public int hashCode() {
+ return _toString.hashCode();
+ }
+
+ /**
+ * Returns the character at the specified index.
+ *
+ * @param index the index of the character starting at <code>0</code>.
+ * @return the character at the specified index of this character sequence.
+ * @throws IndexOutOfBoundsException if <code>((index < 0) ||
+ * (index >= length))</code>
+ */
+ public char charAt(int index) {
+ return _toString.charAt(index);
+ }
+
+ /**
+ * Returns the length of this character sequence.
+ *
+ * @return the number of characters (16-bits Unicode) composing this
+ * character sequence.
+ */
+ public int length() {
+ return _toString.length();
+ }
+
+ /**
+ * Returns a new character sequence that is a subsequence of this sequence.
+ *
+ * @param start the index of the first character inclusive.
+ * @param end the index of the last character exclusive.
+ * @return the character sequence starting at the specified
+ * <code>start</code> position and ending just before the specified
+ * <code>end</code> position.
+ * @throws IndexOutOfBoundsException if {@code (start < 0) || (end < 0) ||
+ * (start > end) || (end > this.length())}
+ */
+ public CharSequence subSequence(int start, int end) {
+ return _toString.substring(start, end);
+ }
+
+ //Maintains unicity.
+ private Object readResolve() throws ObjectStreamException {
+ return QName.valueOf(_toString);
+ }
+
+ private static final long serialVersionUID = -6126031630693748647L;
+
+ @Override
+ public QName 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/xml/XMLBinding.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLBinding.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLBinding.java
new file mode 100644
index 0000000..a15c002
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLBinding.java
@@ -0,0 +1,298 @@
+/*
+ * 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.xml;
+
+import javolution.util.FastMap;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class represents the binding between Java classes and
+ * their XML representation ({@link XMLFormat}).</p>
+ *
+ * <p> Custom XML bindings can also be used to alias class names and
+ * ensure that the XML representation is:<ul>
+ * <li> Impervious to obfuscation.</li>
+ * <li> Unaffected by any class refactoring.</li>
+ * <li> Can be mapped to multiple implementations. For example:[code]
+ *
+ * // Creates a binding to serialize Swing components into high-level XML
+ * // and deserialize the same XML into SWT components.
+ * XMLBinding swingBinding = new XMLBinding();
+ * swingBinding.setAlias(javax.swing.JButton.class, "Button");
+ * swingBinding.setAlias(javax.swing.JTable.class, "Table");
+ * ...
+ * XMLBinding swtBinding = new XMLBinding();
+ * swtBinding.setAlias(org.eclipse.swt.widgets.Button.class, "Button");
+ * swtBinding.setAlias(org.eclipse.swt.widgets.Table.class, "Table");
+ * ...
+ *
+ * // Writes Swing Desktop to XML.
+ * XMLObjectWriter writer = new XMLObjectWriter().setBinding(swingBinding);
+ * writer.setOutput(new FileOutputStream("C:/desktop.xml"));
+ * writer.write(swingDesktop, "Desktop", SwingDesktop.class);
+ * writer.close();
+ *
+ * // Reads back high-level XML to a SWT implementation!
+ * XMLObjectReader reader = new XMLObjectReader().setXMLBinding(swtBinding);
+ * reader.setInput(new FileInputStream("C:/desktop.xml"));
+ * SWTDesktop swtDesktop = reader.read("Desktop", SWTDesktop.class);
+ * reader.close();
+ * [/code]</li>
+ * </ul></p>
+ *
+ * <p> More advanced bindings can also be created through sub-classing.[code]
+ *
+ * // XML binding using reflection.
+ * public ReflectionBinding extends XMLBinding {
+ * protected XMLFormat getFormat(Class forClass) {
+ * Field[] fields = forClass.getDeclaredFields();
+ * return new XMLReflectionFormat(fields);
+ * }
+ * }
+ *
+ * // XML binding read from DTD input source.
+ * public DTDBinding extends XMLBinding {
+ * public DTDBinding(InputStream dtd) {
+ * ...
+ * }
+ * }
+ *
+ * // XML binding overriding default formats.
+ * public MyBinding extends XMLBinding {
+ * // Non-static formats use unmapped XMLFormat instances.
+ * XMLFormat<String> myStringFormat = new XMLFormat<String>(null) {...}
+ * XMLFormat<Collection> myCollectionFormat = new XMLFormat<Collection>(null) {...}
+ * protected XMLFormat getFormat(Class forClass) throws XMLStreamException {
+ * if (String.class.equals(forClass))
+ * return myStringFormat;
+ * if (Collection.class.isAssignableFrom(forClass))
+ * return myCollectionFormat;
+ * return super.getFormat(cls);
+ * }
+ * }
+ * [/code]
+ *
+ * <p> The default XML binding implementation supports all static XML formats
+ * (static members of the classes being mapped) as well as the
+ * following types:<ul>
+ * <li><code>java.lang.Object</code> (empty element)</li>
+ * <li><code>java.lang.Class</code></li>
+ * <li><code>java.lang.String</code></li>
+ * <li><code>java.lang.Appendable</code></li>
+ * <li><code>java.util.Collection</code></li>
+ * <li><code>java.util.Map</code></li>
+ * <li><code>java.lang.Object[]</code></li>
+ * <li> all primitive types wrappers (e.g.
+ * <code>Boolean, Integer ...</code>)</li>
+ * </ul></p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.4, December 1, 2009
+ */
+public class XMLBinding implements XMLSerializable {
+
+ /**
+ * Holds the default instance used by readers/writers (thread-safe).
+ */
+ static final XMLBinding DEFAULT = new XMLBinding();
+
+ /**
+ * Holds the class attribute.
+ */
+ private QName _classAttribute = QName.valueOf("class");
+
+ /**
+ * Holds the class to alias (QName) mapping.
+ */
+ private final FastMap<Class<?>, QName> _classToAlias = new FastMap<Class<?>, QName>();
+
+ /**
+ * Holds the alias (QName) to class mapping.
+ */
+ private final FastMap<QName, Class<?>> _aliasToClass = new FastMap<QName, Class<?>>();
+
+ /**
+ * Default constructor.
+ */
+ public XMLBinding() {}
+
+ /**
+ * Sets the qualified alias for the specified class.
+ *
+ * @param cls the class being aliased.
+ * @param qName the qualified name.
+ */
+ public void setAlias(Class<?> cls, QName qName) {
+ _classToAlias.put(cls, qName);
+ _aliasToClass.put(qName, cls);
+ }
+
+ /**
+ * Convenient method equivalent to {@link #setAlias(Class, QName)
+ * setAlias(cls, QName.valueOf(alias))}.
+ *
+ * @param cls the class being aliased.
+ * @param alias the alias for the specified class.
+ */
+ public final void setAlias(Class<?> cls, String alias) {
+ setAlias(cls, QName.valueOf(alias));
+ }
+
+ /**
+ * Sets the qualified name of the attribute holding the
+ * class identifier. If the local name is <code>null</code> the class
+ * attribute is never read/written (which may prevent unmarshalling).
+ *
+ * @param classAttribute the qualified name of the class attribute or
+ * <code>null<code>.
+ */
+ public void setClassAttribute(QName classAttribute) {
+ _classAttribute = classAttribute;
+ }
+
+ /**
+ * Convenience method equivalent to {@link #setClassAttribute(QName)
+ * setClassAttribute(QName.valueOf(name))}.
+ *
+ * @param name the name of the class attribute or <code>null<code>.
+ */
+ public final void setClassAttribute(String name) {
+ setClassAttribute(name == null ? null : QName.valueOf(name));
+ }
+
+ /**
+ * Returns the XML format for the specified class/interface.
+ * The default implementation returns the {@link XMLContext#getFormat}
+ * for the specified class.
+ *
+ * @param forClass the class for which the XML format is returned.
+ * @return the XML format for the specified class (never <code>null</code>).
+ */
+ protected XMLFormat<?> getFormat(Class<?> forClass)
+ throws XMLStreamException {
+ return XMLContext.getFormat(forClass);
+ }
+
+ /**
+ * Reads the class corresponding to the current XML element.
+ *
+ * This method is called by {@link XMLFormat.InputElement#getNext()}
+ * {@link XMLFormat.InputElement#get(String)} and
+ * {@link XMLFormat.InputElement#get(String, String)} to retrieve the
+ * Java class corresponding to the current XML element.
+ *
+ * If <code>useAttributes</code> is set, the default implementation
+ * reads the class name from the class attribute; otherwise the class
+ * name (or alias) is read from the current element qualified name.
+ *
+ * @param reader the XML stream reader.
+ * @param useAttributes indicates if the element's attributes should be
+ * used to identify the class (e.g. when the element name is
+ * specified by the user then attributes have to be used).
+ * @return the corresponding class.
+ * @throws XMLStreamException
+ */
+ protected Class<?> readClass(XMLStreamReader reader, boolean useAttributes)
+ throws XMLStreamException {
+ try {
+ QName classQName;
+ if (useAttributes) {
+ if (_classAttribute == null)
+ throw new XMLStreamException(
+ "Binding has no class attribute defined, cannot retrieve class");
+ classQName = QName.valueOf(reader.getAttributeValue(
+ _classAttribute.getNamespaceURI(),
+ _classAttribute.getLocalName()));
+ if (classQName == null)
+ throw new XMLStreamException(
+ "Cannot retrieve class (class attribute not found)");
+ } else {
+ classQName = QName.valueOf(reader.getNamespaceURI(),
+ reader.getLocalName());
+ }
+
+ // Searches aliases with namespace URI.
+ Class<?> cls = _aliasToClass.get(classQName);
+ if (cls != null)
+ return cls;
+
+ // Searches aliases without namespace URI.
+ cls = _aliasToClass.get(QName.valueOf(classQName.getLocalName()));
+ if (cls != null)
+ return cls;
+
+ // Finally convert the qualified name to a class (ignoring namespace URI).
+ cls = Class.forName(classQName.getLocalName().toString());
+ if (cls == null)
+ throw new XMLStreamException(
+ "Class "
+ + classQName.getLocalName()
+ + " not found (see javolution.lang.Reflection to support additional class loader)");
+ _aliasToClass.put(classQName, cls);
+ return cls;
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Writes the specified class to the current XML element attributes or to
+ * a new element if the element attributes cannot be used.
+ *
+ * This method is called by
+ * {@link XMLFormat.OutputElement#add(Object)} and
+ * {@link XMLFormat.OutputElement#add(Object, String)} and
+ * {@link XMLFormat.OutputElement#add(Object, String, String)} to
+ * identify the Java class corresponding to the XML element.
+ *
+ *
+ * @param cls the class to be written.
+ * @param writer the XML stream writer.
+ * @param useAttributes indicates if the element's attributes should be
+ * used to identify the class (e.g. when the element name is
+ * specified by the user then attributes have to be used).
+ * @throws XMLStreamException
+ */
+ protected void writeClass(Class<?> cls, XMLStreamWriter writer,
+ boolean useAttributes) throws XMLStreamException {
+ QName qName = (QName) _classToAlias.get(cls);
+ String name = qName != null ? qName.toString() : cls.getName();
+ if (useAttributes) {
+ if (_classAttribute == null)
+ return;
+ if (_classAttribute.getNamespaceURI() == null) {
+ writer.writeAttribute(_classAttribute.getLocalName(), name);
+ } else {
+ writer.writeAttribute(_classAttribute.getNamespaceURI(),
+ _classAttribute.getLocalName(), name);
+ }
+ } else {
+ if (qName != null) {
+ if (qName.getNamespaceURI() == null) {
+ writer.writeStartElement(qName.getLocalName());
+ } else {
+ writer.writeStartElement(qName.getNamespaceURI(),
+ qName.getLocalName());
+ }
+ } else {
+ writer.writeStartElement(name);
+ }
+ }
+ }
+
+ public void reset() {
+ _classAttribute = QName.valueOf("class");
+ _aliasToClass.clear();
+ _classToAlias.clear();
+ }
+
+ private static final long serialVersionUID = 6611041662550083919L;
+}
\ 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/xml/XMLContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLContext.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLContext.java
new file mode 100644
index 0000000..5b29017
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLContext.java
@@ -0,0 +1,74 @@
+/*
+ * 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.xml;
+
+import javolution.context.AbstractContext;
+import javolution.context.FormatContext;
+import javolution.osgi.internal.OSGiServices;
+import javolution.text.TextFormat;
+
+/**
+ * <p> A context for xml serialization/deserialization.
+ * The default xml format for any class is given by the
+ * {@link javolution.text.DefaultTextFormat Format} inheritable annotation.</p>
+ *
+ * <p> A default xml format exists for the following predefined types:
+ * <code><ul>
+ * <li>java.lang.Object (value attribute parsed/formatted using {@link TextFormat})</li>
+ * <li>java.util.Collection</li>
+ * <li>java.util.Map</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 XMLContext extends FormatContext {
+
+ /**
+ * Default constructor.
+ */
+ protected XMLContext() {}
+
+ /**
+ * Enters and returns a new xml context instance.
+ */
+ public static XMLContext enter() {
+ return (XMLContext) XMLContext.currentXMLContext().enterInner();
+ }
+
+ /**
+ * Returns the xml format for the specified type; if none defined
+ * the default object xml format (based on {@link TextFormat}) is returned.
+ */
+ public static <T> XMLFormat<T> getFormat(Class<? extends T> type) {
+ return XMLContext.currentXMLContext().searchFormat(type);
+ }
+
+ /**
+ * Sets the xml format for the specified type (and its sub-types).
+ */
+ public abstract <T> void setFormat(Class<? extends T> type,
+ XMLFormat<T> format);
+
+ /**
+ * Searches the xml format for the specified type.
+ */
+ protected abstract <T> XMLFormat<T> searchFormat(
+ Class<? extends T> type);
+
+ /**
+ * Returns the current xml context.
+ */
+ private static XMLContext currentXMLContext() {
+ XMLContext ctx = AbstractContext.current(XMLContext.class);
+ if (ctx != null)
+ return ctx;
+ return OSGiServices.getXMLContext();
+ }
+}
\ No newline at end of file
[14/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/lang/MathLib.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/MathLib.java b/commons/marmotta-commons/src/ext/java/javolution/lang/MathLib.java
new file mode 100644
index 0000000..331d516
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/MathLib.java
@@ -0,0 +1,1471 @@
+/*
+ * 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.lang;
+
+
+/**
+ * <p> An utility class providing a {@link Realtime} implementation of
+ * the math library.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.2, January 6, 2007
+ */
+@Realtime
+public final class MathLib {
+
+ /**
+ * Default constructor.
+ */
+ private MathLib() {}
+
+ /**
+ * Returns the number of bits in the minimal two's-complement representation
+ * of the specified <code>int</code>, excluding a sign bit.
+ * For positive <code>int</code>, this is equivalent to the number of bits
+ * in the ordinary binary representation. For negative <code>int</code>,
+ * it is equivalent to the number of bits of the positive value
+ * <code>-(i + 1)</code>.
+ *
+ * @param i the <code>int</code> value for which the bit length is returned.
+ * @return the bit length of <code>i</code>.
+ */
+ public static int bitLength(int i) {
+ if (i < 0)
+ i = -++i;
+ return (i < 1 << 16) ? (i < 1 << 8) ? BIT_LENGTH[i]
+ : BIT_LENGTH[i >>> 8] + 8
+ : (i < 1 << 24) ? BIT_LENGTH[i >>> 16] + 16
+ : BIT_LENGTH[i >>> 24] + 24;
+ }
+
+ private static final byte[] BIT_LENGTH = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+ 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8 };
+
+ /**
+ * Returns the number of bits in the minimal two's-complement representation
+ * of the specified <code>long</code>, excluding a sign bit.
+ * For positive <code>long</code>, this is equivalent to the number of bits
+ * in the ordinary binary representation. For negative <code>long</code>,
+ * it is equivalent to the number of bits of the positive value
+ * <code>-(l + 1)</code>.
+ *
+ * @param l the <code>long</code> value for which the bit length is returned.
+ * @return the bit length of <code>l</code>.
+ */
+ public static int bitLength(long l) {
+ int i = (int) (l >> 32);
+ if (i > 0)
+ return (i < 1 << 16) ? (i < 1 << 8) ? BIT_LENGTH[i] + 32
+ : BIT_LENGTH[i >>> 8] + 40
+ : (i < 1 << 24) ? BIT_LENGTH[i >>> 16] + 48
+ : BIT_LENGTH[i >>> 24] + 56;
+ if (i < 0)
+ return bitLength(-++l);
+ i = (int) l;
+ return (i < 0) ? 32 : (i < 1 << 16) ? (i < 1 << 8) ? BIT_LENGTH[i]
+ : BIT_LENGTH[i >>> 8] + 8
+ : (i < 1 << 24) ? BIT_LENGTH[i >>> 16] + 16
+ : BIT_LENGTH[i >>> 24] + 24;
+ }
+
+ /**
+ * Returns the number of one-bits in the two's complement binary
+ * representation of the specified <code>long</code> value.
+ * This function is sometimes referred to as the <i>population count</i>.
+ *
+ * @param longValue the <code>long</code> value.
+ * @return the number of one-bits in the two's complement binary
+ * representation of the specified <code>longValue</code>.
+ */
+ public static int bitCount(long longValue) {
+ longValue = longValue - ((longValue >>> 1) & 0x5555555555555555L);
+ longValue = (longValue & 0x3333333333333333L)
+ + ((longValue >>> 2) & 0x3333333333333333L);
+ longValue = (longValue + (longValue >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
+ longValue = longValue + (longValue >>> 8);
+ longValue = longValue + (longValue >>> 16);
+ longValue = longValue + (longValue >>> 32);
+ return (int) longValue & 0x7f;
+ }
+
+ /**
+ * Returns the number of zero bits preceding the highest-order
+ * ("leftmost") one-bit in the two's complement binary representation
+ * of the specified <code>long</code> value. Returns 64 if the specifed
+ * value is zero.
+ *
+ * @param longValue the <code>long</code> value.
+ * @return the number of leading zero bits.
+ */
+ public static int numberOfLeadingZeros(long longValue) {
+ // From Hacker's Delight
+ if (longValue == 0)
+ return 64;
+ int n = 1;
+ int x = (int)(longValue >>> 32);
+ if (x == 0) { n += 32; x = (int)longValue; }
+ if (x >>> 16 == 0) { n += 16; x <<= 16; }
+ if (x >>> 24 == 0) { n += 8; x <<= 8; }
+ if (x >>> 28 == 0) { n += 4; x <<= 4; }
+ if (x >>> 30 == 0) { n += 2; x <<= 2; }
+ n -= x >>> 31;
+ return n;
+ }
+
+ /**
+ * Returns the number of zero bits following the lowest-order ("rightmost")
+ * one-bit in the two's complement binary representation of the specified
+ * <code>long</code> value. Returns 64 if the specifed value is zero.
+ *
+ * @param longValue the <code>long</code> value.
+ * @return the number of trailing zero bits.
+ */
+ public static int numberOfTrailingZeros(long longValue) {
+ // From Hacker's Delight
+ int x, y;
+ if (longValue == 0) return 64;
+ int n = 63;
+ y = (int)longValue; if (y != 0) { n = n -32; x = y; } else x = (int)(longValue>>>32);
+ y = x <<16; if (y != 0) { n = n -16; x = y; }
+ y = x << 8; if (y != 0) { n = n - 8; x = y; }
+ y = x << 4; if (y != 0) { n = n - 4; x = y; }
+ y = x << 2; if (y != 0) { n = n - 2; x = y; }
+ return n - ((x << 1) >>> 31);
+ }
+
+ /**
+ * Returns the number of digits of the decimal representation of the
+ * specified <code>int</code> value, excluding the sign character if any.
+ *
+ * @param i the <code>int</code> value for which the digit length is returned.
+ * @return <code>String.valueOf(i).length()</code> for zero or positive values;
+ * <code>String.valueOf(i).length() - 1</code> for negative values.
+ */
+ public static int digitLength(int i) {
+ if (i >= 0)
+ return (i >= 100000) ? (i >= 10000000) ? (i >= 1000000000) ? 10
+ : (i >= 100000000) ? 9 : 8 : (i >= 1000000) ? 7 : 6
+ : (i >= 100) ? (i >= 10000) ? 5 : (i >= 1000) ? 4 : 3
+ : (i >= 10) ? 2 : 1;
+ if (i == Integer.MIN_VALUE)
+ return 10; // "2147483648".length()
+ return digitLength(-i); // No overflow possible.
+ }
+
+ /**
+ * Returns the number of digits of the decimal representation of the
+ * the specified <code>long</code>, excluding the sign character if any.
+ *
+ * @param l the <code>long</code> value for which the digit length is returned.
+ * @return <code>String.valueOf(l).length()</code> for zero or positive values;
+ * <code>String.valueOf(l).length() - 1</code> for negative values.
+ */
+ public static int digitLength(long l) {
+ if (l >= 0)
+ return (l <= Integer.MAX_VALUE) ? digitLength((int) l)
+ : // At least 10 digits or more.
+ (l >= 100000000000000L) ? (l >= 10000000000000000L) ? (l >= 1000000000000000000L) ? 19
+ : (l >= 100000000000000000L) ? 18 : 17
+ : (l >= 1000000000000000L) ? 16 : 15
+ : (l >= 100000000000L) ? (l >= 10000000000000L) ? 14
+ : (l >= 1000000000000L) ? 13 : 12
+ : (l >= 10000000000L) ? 11 : 10;
+ if (l == Long.MIN_VALUE)
+ return 19; // "9223372036854775808".length()
+ return digitLength(-l);
+ }
+
+ /**
+ * Returns the closest <code>double</code> representation of the
+ * specified <code>long</code> number multiplied by a power of two.
+ *
+ * @param m the <code>long</code> multiplier.
+ * @param n the power of two exponent.
+ * @return <code>m * 2<sup>n</sup></code>.
+ */
+ public static double toDoublePow2(long m, int n) {
+ if (m == 0)
+ return 0.0;
+ if (m == Long.MIN_VALUE)
+ return toDoublePow2(Long.MIN_VALUE >> 1, n + 1);
+ if (m < 0)
+ return -toDoublePow2(-m, n);
+ int bitLength = MathLib.bitLength(m);
+ int shift = bitLength - 53;
+ long exp = 1023L + 52 + n + shift; // Use long to avoid overflow.
+ if (exp >= 0x7FF)
+ return Double.POSITIVE_INFINITY;
+ if (exp <= 0) { // Degenerated number (subnormal, assume 0 for bit 52)
+ if (exp <= -54)
+ return 0.0;
+ return toDoublePow2(m, n + 54) / 18014398509481984L; // 2^54 Exact.
+ }
+ // Normal number.
+ long bits = (shift > 0) ? (m >> shift) + ((m >> (shift - 1)) & 1) : // Rounding.
+ m << -shift;
+ if (((bits >> 52) != 1) && (++exp >= 0x7FF))
+ return Double.POSITIVE_INFINITY;
+ bits &= 0x000fffffffffffffL; // Clears MSB (bit 52)
+ bits |= exp << 52;
+ return Double.longBitsToDouble(bits);
+ }
+
+ /**/
+
+ /**
+ * Returns the closest <code>double</code> representation of the
+ * specified <code>long</code> number multiplied by a power of ten.
+ *
+ * @param m the <code>long</code> multiplier.
+ * @param n the power of ten exponent.
+ * @return <code>multiplier * 10<sup>n</sup></code>.
+ **/
+ public static double toDoublePow10(long m, int n) {
+ if (m == 0)
+ return 0.0;
+ if (m == Long.MIN_VALUE)
+ return toDoublePow10(Long.MIN_VALUE / 10, n + 1);
+ if (m < 0)
+ return -toDoublePow10(-m, n);
+ if (n >= 0) { // Positive power.
+ if (n > 308)
+ return Double.POSITIVE_INFINITY;
+ // Works with 4 x 32 bits registers (x3:x2:x1:x0)
+ long x0 = 0; // 32 bits.
+ long x1 = 0; // 32 bits.
+ long x2 = m & MASK_32; // 32 bits.
+ long x3 = m >>> 32; // 32 bits.
+ int pow2 = 0;
+ while (n != 0) {
+ int i = (n >= POW5_INT.length) ? POW5_INT.length - 1 : n;
+ int coef = POW5_INT[i]; // 31 bits max.
+
+ if (((int) x0) != 0)
+ x0 *= coef; // 63 bits max.
+ if (((int) x1) != 0)
+ x1 *= coef; // 63 bits max.
+ x2 *= coef; // 63 bits max.
+ x3 *= coef; // 63 bits max.
+
+ x1 += x0 >>> 32;
+ x0 &= MASK_32;
+
+ x2 += x1 >>> 32;
+ x1 &= MASK_32;
+
+ x3 += x2 >>> 32;
+ x2 &= MASK_32;
+
+ // Adjusts powers.
+ pow2 += i;
+ n -= i;
+
+ // Normalizes (x3 should be 32 bits max).
+ long carry = x3 >>> 32;
+ if (carry != 0) { // Shift.
+ x0 = x1;
+ x1 = x2;
+ x2 = x3 & MASK_32;
+ x3 = carry;
+ pow2 += 32;
+ }
+ }
+
+ // Merges registers to a 63 bits mantissa.
+ int shift = 31 - MathLib.bitLength(x3); // -1..30
+ pow2 -= shift;
+ long mantissa = (shift < 0) ? (x3 << 31) | (x2 >>> 1) : // x3 is 32 bits.
+ (((x3 << 32) | x2) << shift) | (x1 >>> (32 - shift));
+ return toDoublePow2(mantissa, pow2);
+
+ } else { // n < 0
+ if (n < -324 - 20)
+ return 0.0;
+
+ // Works with x1:x0 126 bits register.
+ long x1 = m; // 63 bits.
+ long x0 = 0; // 63 bits.
+ int pow2 = 0;
+ while (true) {
+
+ // Normalizes x1:x0
+ int shift = 63 - MathLib.bitLength(x1);
+ x1 <<= shift;
+ x1 |= x0 >>> (63 - shift);
+ x0 = (x0 << shift) & MASK_63;
+ pow2 -= shift;
+
+ // Checks if division has to be performed.
+ if (n == 0)
+ break; // Done.
+
+ // Retrieves power of 5 divisor.
+ int i = (-n >= POW5_INT.length) ? POW5_INT.length - 1 : -n;
+ int divisor = POW5_INT[i];
+
+ // Performs the division (126 bits by 31 bits).
+ long wh = (x1 >>> 32);
+ long qh = wh / divisor;
+ long r = wh - qh * divisor;
+ long wl = (r << 32) | (x1 & MASK_32);
+ long ql = wl / divisor;
+ r = wl - ql * divisor;
+ x1 = (qh << 32) | ql;
+
+ wh = (r << 31) | (x0 >>> 32);
+ qh = wh / divisor;
+ r = wh - qh * divisor;
+ wl = (r << 32) | (x0 & MASK_32);
+ ql = wl / divisor;
+ x0 = (qh << 32) | ql;
+
+ // Adjusts powers.
+ n += i;
+ pow2 -= i;
+ }
+ return toDoublePow2(x1, pow2);
+ }
+ }
+
+ private static final long MASK_63 = 0x7FFFFFFFFFFFFFFFL;
+
+ private static final long MASK_32 = 0xFFFFFFFFL;
+
+ private static final int[] POW5_INT = { 1, 5, 25, 125, 625, 3125, 15625,
+ 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125 };
+
+ /**/
+
+ /**
+ * Returns the closest <code>long</code> representation of the
+ * specified <code>double</code> number multiplied by a power of two.
+ *
+ * @param d the <code>double</code> multiplier.
+ * @param n the power of two exponent.
+ * @return <code>d * 2<sup>n</sup></code>
+ * @throws ArithmeticException if the conversion cannot be performed
+ * (NaN, Infinity or overflow).
+ **/
+ public static long toLongPow2(double d, int n) {
+ long bits = Double.doubleToLongBits(d);
+ boolean isNegative = (bits >> 63) != 0;
+ int exp = ((int) (bits >> 52)) & 0x7FF;
+ long m = bits & 0x000fffffffffffffL;
+ if (exp == 0x7FF)
+ throw new ArithmeticException(
+ "Cannot convert to long (Infinity or NaN)");
+ if (exp == 0) {
+ if (m == 0)
+ return 0L;
+ return toLongPow2(d * 18014398509481984L, n - 54); // 2^54 Exact.
+ }
+ m |= 0x0010000000000000L; // Sets MSB (bit 52)
+ long shift = exp - 1023L - 52 + n; // Use long to avoid overflow.
+ if (shift <= -64)
+ return 0L;
+ if (shift >= 11)
+ throw new ArithmeticException("Cannot convert to long (overflow)");
+ m = (shift >= 0) ? m << shift : (m >> -shift)
+ + ((m >> -(shift + 1)) & 1); // Rounding.
+ return isNegative ? -m : m;
+ }
+
+ /**/
+
+ /**
+ * Returns the closest <code>long</code> representation of the
+ * specified <code>double</code> number multiplied by a power of ten.
+ *
+ * @param d the <code>double</code> multiplier.
+ * @param n the power of two exponent.
+ * @return <code>d * 10<sup>n</sup></code>.
+ */
+ public static long toLongPow10(double d, int n) {
+ long bits = Double.doubleToLongBits(d);
+ boolean isNegative = (bits >> 63) != 0;
+ int exp = ((int) (bits >> 52)) & 0x7FF;
+ long m = bits & 0x000fffffffffffffL;
+ if (exp == 0x7FF)
+ throw new ArithmeticException(
+ "Cannot convert to long (Infinity or NaN)");
+ if (exp == 0) {
+ if (m == 0)
+ return 0L;
+ return toLongPow10(d * 1E16, n - 16);
+ }
+ m |= 0x0010000000000000L; // Sets MSB (bit 52)
+ int pow2 = exp - 1023 - 52;
+ // Retrieves 63 bits m with n == 0.
+ if (n >= 0) {
+ // Works with 4 x 32 bits registers (x3:x2:x1:x0)
+ long x0 = 0; // 32 bits.
+ long x1 = 0; // 32 bits.
+ long x2 = m & MASK_32; // 32 bits.
+ long x3 = m >>> 32; // 32 bits.
+ while (n != 0) {
+ int i = (n >= POW5_INT.length) ? POW5_INT.length - 1 : n;
+ int coef = POW5_INT[i]; // 31 bits max.
+
+ if (((int) x0) != 0)
+ x0 *= coef; // 63 bits max.
+ if (((int) x1) != 0)
+ x1 *= coef; // 63 bits max.
+ x2 *= coef; // 63 bits max.
+ x3 *= coef; // 63 bits max.
+
+ x1 += x0 >>> 32;
+ x0 &= MASK_32;
+
+ x2 += x1 >>> 32;
+ x1 &= MASK_32;
+
+ x3 += x2 >>> 32;
+ x2 &= MASK_32;
+
+ // Adjusts powers.
+ pow2 += i;
+ n -= i;
+
+ // Normalizes (x3 should be 32 bits max).
+ long carry = x3 >>> 32;
+ if (carry != 0) { // Shift.
+ x0 = x1;
+ x1 = x2;
+ x2 = x3 & MASK_32;
+ x3 = carry;
+ pow2 += 32;
+ }
+ }
+
+ // Merges registers to a 63 bits mantissa.
+ int shift = 31 - MathLib.bitLength(x3); // -1..30
+ pow2 -= shift;
+ m = (shift < 0) ? (x3 << 31) | (x2 >>> 1) : // x3 is 32 bits.
+ (((x3 << 32) | x2) << shift) | (x1 >>> (32 - shift));
+
+ } else { // n < 0
+
+ // Works with x1:x0 126 bits register.
+ long x1 = m; // 63 bits.
+ long x0 = 0; // 63 bits.
+ while (true) {
+
+ // Normalizes x1:x0
+ int shift = 63 - MathLib.bitLength(x1);
+ x1 <<= shift;
+ x1 |= x0 >>> (63 - shift);
+ x0 = (x0 << shift) & MASK_63;
+ pow2 -= shift;
+
+ // Checks if division has to be performed.
+ if (n == 0)
+ break; // Done.
+
+ // Retrieves power of 5 divisor.
+ int i = (-n >= POW5_INT.length) ? POW5_INT.length - 1 : -n;
+ int divisor = POW5_INT[i];
+
+ // Performs the division (126 bits by 31 bits).
+ long wh = (x1 >>> 32);
+ long qh = wh / divisor;
+ long r = wh - qh * divisor;
+ long wl = (r << 32) | (x1 & MASK_32);
+ long ql = wl / divisor;
+ r = wl - ql * divisor;
+ x1 = (qh << 32) | ql;
+
+ wh = (r << 31) | (x0 >>> 32);
+ qh = wh / divisor;
+ r = wh - qh * divisor;
+ wl = (r << 32) | (x0 & MASK_32);
+ ql = wl / divisor;
+ x0 = (qh << 32) | ql;
+
+ // Adjusts powers.
+ n += i;
+ pow2 -= i;
+ }
+ m = x1;
+ }
+ if (pow2 > 0)
+ throw new ArithmeticException("Overflow");
+ if (pow2 < -63)
+ return 0;
+ m = (m >> -pow2) + ((m >> -(pow2 + 1)) & 1); // Rounding.
+ return isNegative ? -m : m;
+ }
+
+ /**/
+
+ /**
+ * Returns the largest power of 2 that is less than or equal to the
+ * the specified positive value.
+ *
+ * @param d the <code>double</code> number.
+ * @return <code>floor(Log2(abs(d)))</code>
+ * @throws ArithmeticException if <code>d <= 0<code> or <code>d</code>
+ * is <code>NaN</code> or <code>Infinity</code>.
+ **/
+ public static int floorLog2(double d) {
+ if (d <= 0)
+ throw new ArithmeticException("Negative number or zero");
+ long bits = Double.doubleToLongBits(d);
+ int exp = ((int) (bits >> 52)) & 0x7FF;
+ if (exp == 0x7FF)
+ throw new ArithmeticException("Infinity or NaN");
+ if (exp == 0)
+ return floorLog2(d * 18014398509481984L) - 54; // 2^54 Exact.
+ return exp - 1023;
+ }
+
+ /**/
+
+ /**
+ * Returns the largest power of 10 that is less than or equal to the
+ * the specified positive value.
+ *
+ * @param d the <code>double</code> number.
+ * @return <code>floor(Log10(abs(d)))</code>
+ * @throws ArithmeticException if <code>d <= 0<code> or <code>d</code>
+ * is <code>NaN</code> or <code>Infinity</code>.
+ **/
+ public static int floorLog10(double d) {
+ int guess = (int) (LOG2_DIV_LOG10 * MathLib.floorLog2(d));
+ double pow10 = MathLib.toDoublePow10(1, guess);
+ if ((pow10 <= d) && (pow10 * 10 > d))
+ return guess;
+ if (pow10 > d)
+ return guess - 1;
+ return guess + 1;
+ }
+
+ private static final double LOG2_DIV_LOG10 = 0.3010299956639811952137388947;
+
+ /**
+ * The natural logarithm.
+ **/
+ public static final double E = 2.71828182845904523536028747135266;
+
+ /**
+ * The ratio of the circumference of a circle to its diameter.
+ **/
+ public static final double PI = 3.1415926535897932384626433832795;
+
+ /**
+ * Half the ratio of the circumference of a circle to its diameter.
+ **/
+ public static final double HALF_PI = 1.5707963267948966192313216916398;
+
+ /**
+ * Twice the ratio of the circumference of a circle to its diameter.
+ **/
+ public static final double TWO_PI = 6.283185307179586476925286766559;
+
+ /**
+ * Four time the ratio of the circumference of a circle to its diameter.
+ **/
+ public static final double FOUR_PI = 12.566370614359172953850573533118;
+
+ /**
+ * Holds {@link #PI} * {@link #PI}.
+ **/
+ public static final double PI_SQUARE = 9.8696044010893586188344909998762;
+
+ /**
+ * The natural logarithm of two.
+ **/
+ public static final double LOG2 = 0.69314718055994530941723212145818;
+
+ /**
+ * The natural logarithm of ten.
+ **/
+ public static final double LOG10 = 2.3025850929940456840179914546844;
+
+ /**
+ * The square root of two.
+ **/
+ public static final double SQRT2 = 1.4142135623730950488016887242097;
+
+ /**
+ * Not-A-Number.
+ **/
+ public static final double NaN = 0.0 / 0.0;
+
+ /**
+ * Infinity.
+ **/
+ public static final double Infinity = 1.0 / 0.0;
+
+ /**/
+ /**
+ * Converts an angle in degrees to radians.
+ *
+ * @param degrees the angle in degrees.
+ * @return the specified angle in radians.
+ **/
+ public static double toRadians(double degrees) {
+ return degrees * (PI / 180.0);
+ }
+
+ /**/
+
+ /**
+ * Converts an angle in radians to degrees.
+ *
+ * @param radians the angle in radians.
+ * @return the specified angle in degrees.
+ **/
+ public static double toDegrees(double radians) {
+ return radians * (180.0 / PI);
+ }
+
+ /**/
+
+ /**
+ * Returns the positive square root of the specified value.
+ *
+ * @param x the value.
+ * @return <code>java.lang.Math.sqrt(x)</code>
+ **/
+ public static double sqrt(double x) {
+ return Math.sqrt(x); // CLDC 1.1
+ }
+
+ /**/
+
+ /**
+ * Returns the remainder of the division of the specified two arguments.
+ *
+ * @param x the dividend.
+ * @param y the divisor.
+ * @return <code>x - round(x / y) * y</code>
+ **/
+ public static double rem(double x, double y) {
+ double tmp = x / y;
+ if (MathLib.abs(tmp) <= Long.MAX_VALUE)
+ return x - MathLib.round(tmp) * y;
+ else
+ return NaN;
+ }
+
+ /**/
+
+ /**
+ * Returns the smallest (closest to negative infinity)
+ * <code>double</code> value that is not less than the argument and is
+ * equal to a mathematical integer.
+ *
+ * @param x the value.
+ * @return <code>java.lang.Math.ceil(x)</code>
+ **/
+ public static double ceil(double x) {
+ return Math.ceil(x); // CLDC 1.1
+ }
+
+ /**/
+
+ /**
+ * Returns the largest (closest to positive infinity)
+ * <code>double</code> value that is not greater than the argument and
+ * is equal to a mathematical integer.
+ *
+ * @param x the value.
+ * @return <code>java.lang.Math.ceil(x)</code>
+ **/
+ public static double floor(double x) {
+ return Math.floor(x); // CLDC 1.1
+ }
+
+ /**/
+
+ /**
+ * Returns the trigonometric sine of the specified angle in radians.
+ *
+ * @param radians the angle in radians.
+ * @return <code>java.lang.Math.sin(radians)</code>
+ **/
+ public static double sin(double radians) {
+ return Math.sin(radians); // CLDC 1.1
+ }
+
+ /**/
+
+ /**
+ * Returns the trigonometric cosine of the specified angle in radians.
+ *
+ * @param radians the angle in radians.
+ * @return <code>java.lang.Math.cos(radians)</code>
+ **/
+ public static double cos(double radians) {
+ return Math.cos(radians); // CLDC 1.1
+ }
+
+ /**/
+
+ /**
+ * Returns the trigonometric tangent of the specified angle in radians.
+ *
+ * @param radians the angle in radians.
+ * @return <code>java.lang.Math.tan(radians)</code>
+ **/
+ public static double tan(double radians) {
+ return Math.tan(radians); // CLDC 1.1
+ }
+
+ /**/
+
+ /**
+ * Returns the arc sine of the specified value,
+ * in the range of -<i>pi</i>/2 through <i>pi</i>/2.
+ *
+ * @param x the value whose arc sine is to be returned.
+ * @return the arc sine in radians for the specified value.
+ **/
+ public static double asin(double x) {
+ if (x < -1.0 || x > 1.0)
+ return MathLib.NaN;
+ if (x == -1.0)
+ return -HALF_PI;
+ if (x == 1.0)
+ return HALF_PI;
+ return MathLib.atan(x / MathLib.sqrt(1.0 - x * x));
+ }
+
+ /**/
+
+ /**
+ * Returns the arc cosine of the specified value,
+ * in the range of 0.0 through <i>pi</i>.
+ *
+ * @param x the value whose arc cosine is to be returned.
+ * @return the arc cosine in radians for the specified value.
+ **/
+ public static double acos(double x) {
+ return HALF_PI - MathLib.asin(x);
+ }
+
+ /**/
+
+ /**
+ * Returns the arc tangent of the specified value,
+ * in the range of -<i>pi</i>/2 through <i>pi</i>/2.
+ *
+ * @param x the value whose arc tangent is to be returned.
+ * @return the arc tangent in radians for the specified value.
+ * @see <a href="http://mathworld.wolfram.com/InverseTangent.html">
+ * Inverse Tangent -- from MathWorld</a>
+ **/
+ public static double atan(double x) {
+ return MathLib._atan(x);
+ }
+
+ /**/
+
+ /**
+ * Returns the angle theta such that
+ * <code>(x == cos(theta)) && (y == sin(theta))</code>.
+ *
+ * @param y the y value.
+ * @param x the x value.
+ * @return the angle theta in radians.
+ * @see <a href="http://en.wikipedia.org/wiki/Atan2">Wikipedia: Atan2</a>
+ **/
+ public static double atan2(double y, double x) {
+ // From Wikipedia.
+ if (x > 0) return MathLib.atan(y / x);
+ if ((y >= 0) && (x < 0)) return MathLib.atan(y / x) + PI;
+ if ((y < 0) && (x < 0)) return MathLib.atan(y / x) - PI;
+ if ((y > 0) && (x == 0)) return PI / 2;
+ if ((y < 0) && (x == 0)) return -PI / 2;
+ return Double.NaN; // ((y == 0) && (x == 0))
+ }
+
+ /**/
+
+ /**
+ * Returns the hyperbolic sine of x.
+ *
+ * @param x the value for which the hyperbolic sine is calculated.
+ * @return <code>(exp(x) - exp(-x)) / 2</code>
+ **/
+ public static double sinh(double x) {
+ return (MathLib.exp(x) - MathLib.exp(-x)) * 0.5;
+ }
+
+ /**/
+
+ /**
+ * Returns the hyperbolic cosine of x.
+ *
+ * @param x the value for which the hyperbolic cosine is calculated.
+ * @return <code>(exp(x) + exp(-x)) / 2</code>
+ **/
+ public static double cosh(double x) {
+ return (MathLib.exp(x) + MathLib.exp(-x)) * 0.5;
+ }
+
+ /**/
+
+ /**
+ * Returns the hyperbolic tangent of x.
+ *
+ * @param x the value for which the hyperbolic tangent is calculated.
+ * @return <code>(exp(2 * x) - 1) / (exp(2 * x) + 1)</code>
+ **/
+ public static double tanh(double x) {
+ return (MathLib.exp(2 * x) - 1) / (MathLib.exp(2 * x) + 1);
+ }
+
+ /**/
+
+ /**
+ * Returns <i>{@link #E e}</i> raised to the specified power.
+ *
+ * @param x the exponent.
+ * @return <code><i>e</i><sup>x</sup></code>
+ * @see <a href="http://mathworld.wolfram.com/ExponentialFunction.html">
+ * Exponential Function -- from MathWorld</a>
+ **/
+ public static double exp(double x) {
+ return MathLib._ieee754_exp(x);
+ }
+
+ /**/
+
+ /**
+ * Returns the natural logarithm (base <i>{@link #E e}</i>) of the specified
+ * value.
+ *
+ * @param x the value greater than <code>0.0</code>.
+ * @return the value y such as <code><i>e</i><sup>y</sup> == x</code>
+ **/
+ public static double log(double x) {
+ return MathLib._ieee754_log(x);
+ }
+
+ /**/
+
+ /**
+ * Returns the decimal logarithm of the specified value.
+ *
+ * @param x the value greater than <code>0.0</code>.
+ * @return the value y such as <code>10<sup>y</sup> == x</code>
+ **/
+ public static double log10(double x) {
+ return log(x) * INV_LOG10;
+ }
+
+ private static double INV_LOG10 = 0.43429448190325182765112891891661;
+
+ /**
+ * Returns the value of the first argument raised to the power of the
+ * second argument.
+ *
+ * @param x the base.
+ * @param y the exponent.
+ * @return <code>x<sup>y</sup></code>
+ **/
+ public static double pow(double x, double y) {
+ // Use close approximation (+/- LSB)
+ if ((x < 0) && (y == (int) y))
+ return (((int) y) & 1) == 0 ? pow(-x, y) : -pow(-x, y);
+ return MathLib.exp(y * MathLib.log(x));
+ }
+
+ /**
+ * Returns the closest <code>int</code> to the specified argument.
+ *
+ * @param f the <code>float</code> value to be rounded to a <code>int</code>
+ * @return the nearest <code>int</code> value.
+ **/
+ public static int round(float f) {
+ return (int) floor(f + 0.5f);
+ }
+
+ /**/
+
+ /**
+ * Returns the closest <code>long</code> to the specified argument.
+ *
+ * @param d the <code>double</code> value to be rounded to a
+ * <code>long</code>
+ * @return the nearest <code>long</code> value.
+ **/
+ public static long round(double d) {
+ return (long) floor(d + 0.5d);
+ }
+
+ /**
+ * Returns the absolute value of the specified <code>int</code> argument.
+ *
+ * @param i the <code>int</code> value.
+ * @return <code>i</code> or <code>-i</code>
+ */
+ public static int abs(int i) {
+ return (i < 0) ? -i : i;
+ }
+
+ /**
+ * Returns the absolute value of the specified <code>long</code> argument.
+ *
+ * @param l the <code>long</code> value.
+ * @return <code>l</code> or <code>-l</code>
+ */
+ public static long abs(long l) {
+ return (l < 0) ? -l : l;
+ }
+
+ /**
+ * Returns the absolute value of the specified <code>float</code> argument.
+ *
+ * @param f the <code>float</code> value.
+ * @return <code>f</code> or <code>-f</code>
+ **/
+ public static float abs(float f) {
+ return (f < 0) ? -f : f;
+ }
+
+ /**
+ * Returns the absolute value of the specified <code>double</code> argument.
+ *
+ * @param d the <code>double</code> value.
+ * @return <code>d</code> or <code>-d</code>
+ **/
+ public static double abs(double d) {
+ return (d < 0) ? -d : d;
+ }
+
+ /**/
+
+ /**
+ * Returns the greater of two <code>int</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the larger of <code>x</code> and <code>y</code>.
+ */
+ public static int max(int x, int y) {
+ return (x >= y) ? x : y;
+ }
+
+ /**
+ * Returns the greater of two <code>long</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the larger of <code>x</code> and <code>y</code>.
+ */
+ public static long max(long x, long y) {
+ return (x >= y) ? x : y;
+ }
+
+ /**
+ * Returns the greater of two <code>float</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the larger of <code>x</code> and <code>y</code>.
+ **/
+ public static float max(float x, float y) {
+ return (x >= y) ? x : y;
+ }
+
+ /**
+ * Returns the greater of two <code>double</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the larger of <code>x</code> and <code>y</code>.
+ **/
+ public static double max(double x, double y) {
+ return (x >= y) ? x : y;
+ }
+
+ /**/
+
+ /**
+ * Returns the smaller of two <code>int</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the smaller of <code>x</code> and <code>y</code>.
+ */
+ public static int min(int x, int y) {
+ return (x < y) ? x : y;
+ }
+
+ /**
+ * Returns the smaller of two <code>long</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the smaller of <code>x</code> and <code>y</code>.
+ */
+ public static long min(long x, long y) {
+ return (x < y) ? x : y;
+ }
+
+ /**
+ * Returns the smaller of two <code>float</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the smaller of <code>x</code> and <code>y</code>.
+ **/
+ public static float min(float x, float y) {
+ return (x < y) ? x : y;
+ }
+
+ /**/
+
+ /**
+ * Returns the smaller of two <code>double</code> values.
+ *
+ * @param x the first value.
+ * @param y the second value.
+ * @return the smaller of <code>x</code> and <code>y</code>.
+ **/
+ public static double min(double x, double y) {
+ return (x < y) ? x : y;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ /* @(#)s_atan.c 1.3 95/01/18 */
+ /*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+ /* atan(x)
+ * Method
+ * 1. Reduce x to positive by atan(x) = -atan(-x).
+ * 2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ * is further reduced to one of the following intervals and the
+ * arctangent of t is evaluated by the corresponding formula:
+ *
+ * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ * [39/16,INF] atan(x) = atan(INF) + atan( -1/t )
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+ static final double atanhi[] = { 4.63647609000806093515e-01, // atan(0.5)hi 0x3FDDAC67, 0x0561BB4F
+ 7.85398163397448278999e-01, // atan(1.0)hi 0x3FE921FB, 0x54442D18
+ 9.82793723247329054082e-01, // atan(1.5)hi 0x3FEF730B, 0xD281F69B
+ 1.57079632679489655800e+00, // atan(inf)hi 0x3FF921FB, 0x54442D18
+ };
+
+ static final double atanlo[] = { 2.26987774529616870924e-17, // atan(0.5)lo 0x3C7A2B7F, 0x222F65E2
+ 3.06161699786838301793e-17, // atan(1.0)lo 0x3C81A626, 0x33145C07
+ 1.39033110312309984516e-17, // atan(1.5)lo 0x3C700788, 0x7AF0CBBD
+ 6.12323399573676603587e-17, // atan(inf)lo 0x3C91A626, 0x33145C07
+ };
+
+ static final double aT[] = { 3.33333333333329318027e-01, // 0x3FD55555, 0x5555550D
+ -1.99999999998764832476e-01, // 0xBFC99999, 0x9998EBC4
+ 1.42857142725034663711e-01, // 0x3FC24924, 0x920083FF
+ -1.11111104054623557880e-01, // 0xBFBC71C6, 0xFE231671
+ 9.09088713343650656196e-02, // 0x3FB745CD, 0xC54C206E
+ -7.69187620504482999495e-02, // 0xBFB3B0F2, 0xAF749A6D
+ 6.66107313738753120669e-02, // 0x3FB10D66, 0xA0D03D51
+ -5.83357013379057348645e-02, // 0xBFADDE2D, 0x52DEFD9A
+ 4.97687799461593236017e-02, // 0x3FA97B4B, 0x24760DEB
+ -3.65315727442169155270e-02, // 0xBFA2B444, 0x2C6A6C2F
+ 1.62858201153657823623e-02, // 0x3F90AD3A, 0xE322DA11
+ };
+
+ static final double one = 1.0, huge = 1.0e300;
+
+ static double _atan(double x) {
+ double w, s1, s2, z;
+ int ix, hx, id;
+ long xBits = Double.doubleToLongBits(x);
+ int __HIx = (int) (xBits >> 32);
+ int __LOx = (int) xBits;
+
+ hx = __HIx;
+ ix = hx & 0x7fffffff;
+ if (ix >= 0x44100000) { // if |x| >= 2^66
+ if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (__LOx != 0)))
+ return x + x; // NaN
+ if (hx > 0)
+ return atanhi[3] + atanlo[3];
+ else
+ return -atanhi[3] - atanlo[3];
+ }
+ if (ix < 0x3fdc0000) { // |x| < 0.4375
+ if (ix < 0x3e200000) // |x| < 2^-29
+ if (huge + x > one)
+ return x;
+ id = -1;
+ } else {
+ x = MathLib.abs(x);
+ if (ix < 0x3ff30000) // |x| < 1.1875
+ if (ix < 0x3fe60000) { // 7/16 <=|x|<11/16
+ id = 0;
+ x = (2.0 * x - one) / (2.0 + x);
+ } else { // 11/16<=|x|< 19/16
+ id = 1;
+ x = (x - one) / (x + one);
+ }
+ else if (ix < 0x40038000) { // |x| < 2.4375
+ id = 2;
+ x = (x - 1.5) / (one + 1.5 * x);
+ } else { // 2.4375 <= |x| < 2^66
+ id = 3;
+ x = -1.0 / x;
+ }
+ }
+ // end of argument reduction
+ z = x * x;
+ w = z * z;
+ // break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly
+ s1 = z
+ * (aT[0] + w
+ * (aT[2] + w
+ * (aT[4] + w
+ * (aT[6] + w * (aT[8] + w * aT[10])))));
+ s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
+ if (id < 0)
+ return x - x * (s1 + s2);
+ else {
+ z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
+ return (hx < 0) ? -z : z;
+ }
+ }
+
+ /**/
+ ////////////////////////////////////////////////////////////////////////////
+ /* @(#)e_log.c 1.3 95/01/18 */
+ /*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+ /* __ieee754_log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * 2. Approximation of log(1+f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
+ * (the values of Lg1 to Lg7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lg1*s +...+Lg7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log(1+f) = f - s*(f - R) (if f is not too large)
+ * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ * 3. Finally, log(x) = k*ln2 + log(1+f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log(x) is NaN with signal if x < 0 (including -INF) ;
+ * log(+INF) is +INF; log(0) is -INF with signal;
+ * log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+ static final double ln2_hi = 6.93147180369123816490e-01, // 3fe62e42 fee00000
+ ln2_lo = 1.90821492927058770002e-10, // 3dea39ef 35793c76
+ two54 = 1.80143985094819840000e+16, // 43500000 00000000
+ Lg1 = 6.666666666666735130e-01, // 3FE55555 55555593
+ Lg2 = 3.999999999940941908e-01, // 3FD99999 9997FA04
+ Lg3 = 2.857142874366239149e-01, // 3FD24924 94229359
+ Lg4 = 2.222219843214978396e-01, // 3FCC71C5 1D8E78AF
+ Lg5 = 1.818357216161805012e-01, // 3FC74664 96CB03DE
+ Lg6 = 1.531383769920937332e-01, // 3FC39A09 D078C69F
+ Lg7 = 1.479819860511658591e-01; // 3FC2F112 DF3E5244
+
+ static final double zero = 0.0;
+
+ static double _ieee754_log(double x) {
+ double hfsq, f, s, z, R, w, t1, t2, dk;
+ int k, hx, i, j;
+ int lx; // unsigned
+
+ long xBits = Double.doubleToLongBits(x);
+ hx = (int) (xBits >> 32);
+ lx = (int) xBits;
+
+ k = 0;
+ if (hx < 0x00100000) { // x < 2**-1022
+ if (((hx & 0x7fffffff) | lx) == 0)
+ return -two54 / zero; // log(+-0)=-inf
+ if (hx < 0)
+ return (x - x) / zero; // log(-#) = NaN
+ k -= 54;
+ x *= two54; // subnormal number, scale up x
+ xBits = Double.doubleToLongBits(x);
+ hx = (int) (xBits >> 32); // high word of x
+ }
+ if (hx >= 0x7ff00000)
+ return x + x;
+ k += (hx >> 20) - 1023;
+ hx &= 0x000fffff;
+ i = (hx + 0x95f64) & 0x100000;
+ xBits = Double.doubleToLongBits(x);
+ int HIx = hx | (i ^ 0x3ff00000); // normalize x or x/2
+ xBits = ((HIx & 0xFFFFFFFFL) << 32) | (xBits & 0xFFFFFFFFL);
+ x = Double.longBitsToDouble(xBits);
+ k += (i >> 20);
+ f = x - 1.0;
+ if ((0x000fffff & (2 + hx)) < 3) { // |f| < 2**-20
+ if (f == zero)
+ if (k == 0)
+ return zero;
+ else {
+ dk = (double) k;
+ return dk * ln2_hi + dk * ln2_lo;
+ }
+ R = f * f * (0.5 - 0.33333333333333333 * f);
+ if (k == 0)
+ return f - R;
+ else {
+ dk = (double) k;
+ return dk * ln2_hi - ((R - dk * ln2_lo) - f);
+ }
+ }
+ s = f / (2.0 + f);
+ dk = (double) k;
+ z = s * s;
+ i = hx - 0x6147a;
+ w = z * z;
+ j = 0x6b851 - hx;
+ t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
+ t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
+ i |= j;
+ R = t2 + t1;
+ if (i > 0) {
+ hfsq = 0.5 * f * f;
+ if (k == 0)
+ return f - (hfsq - s * (hfsq + R));
+ else
+ return dk * ln2_hi
+ - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
+ } else if (k == 0)
+ return f - s * (f - R);
+ else
+ return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
+ }
+
+ /**/
+ ////////////////////////////////////////////////////////////////////////////
+ /* @(#)e_exp.c 1.6 04/04/22 */
+ /*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+ /* __ieee754_exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2.
+ *
+ * Here r will be represented as r = hi-lo for better
+ * accuracy.
+ *
+ * 2. Approximation of exp(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Write
+ * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ * We use a special Remes algorithm on [0,0.34658] to generate
+ * a polynomial of degree 5 to approximate R. The maximum error
+ * of this polynomial approximation is bounded by 2**-59. In
+ * other words,
+ * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ * (where z=r*r, and the values of P1 to P5 are listed below)
+ * and
+ * | 5 | -59
+ * | 2.0+P1*z+...+P5*z - R(z) | <= 2
+ * | |
+ * The computation of exp(r) thus becomes
+ * 2*r
+ * exp(r) = 1 + -------
+ * R - r
+ * r*R1(r)
+ * = 1 + r + ----------- (for better accuracy)
+ * 2 - R1(r)
+ * where
+ * 2 4 10
+ * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
+ *
+ * 3. Scale back to obtain exp(x):
+ * From step 1, we have
+ * exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF) is 0, and
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then exp(x) overflow
+ * if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+ static final double halF[] = { 0.5, -0.5, },
+ twom1000 = 9.33263618503218878990e-302, // 2**-1000=0x01700000,0
+ o_threshold = 7.09782712893383973096e+02, // 0x40862E42, 0xFEFA39EF
+ u_threshold = -7.45133219101941108420e+02, // 0xc0874910, 0xD52D3051
+ ln2HI[] = { 6.93147180369123816490e-01, // 0x3fe62e42, 0xfee00000
+ -6.93147180369123816490e-01, },// 0xbfe62e42, 0xfee00000
+ ln2LO[] = { 1.90821492927058770002e-10, // 0x3dea39ef, 0x35793c76
+ -1.90821492927058770002e-10, },// 0xbdea39ef, 0x35793c76
+ invln2 = 1.44269504088896338700e+00, // 0x3ff71547, 0x652b82fe
+ P1 = 1.66666666666666019037e-01, // 0x3FC55555, 0x5555553E
+ P2 = -2.77777777770155933842e-03, // 0xBF66C16C, 0x16BEBD93
+ P3 = 6.61375632143793436117e-05, // 0x3F11566A, 0xAF25DE2C
+ P4 = -1.65339022054652515390e-06, // 0xBEBBBD41, 0xC5D26BF1
+ P5 = 4.13813679705723846039e-08; // 0x3E663769, 0x72BEA4D0
+
+ static double _ieee754_exp(double x) // default IEEE double exp
+ {
+ double y, hi = 0, lo = 0, c, t;
+ int k = 0, xsb;
+ int hx; // Unsigned.
+ long xBits = Double.doubleToLongBits(x);
+ int __HIx = (int) (xBits >> 32);
+ int __LOx = (int) xBits;
+
+ hx = __HIx; // high word of x
+ xsb = (hx >> 31) & 1; // sign bit of x
+ hx &= 0x7fffffff; // high word of |x|
+
+ // filter out non-finite argument
+ if (hx >= 0x40862E42) { // if |x|>=709.78...
+ if (hx >= 0x7ff00000)
+ if (((hx & 0xfffff) | __LOx) != 0)
+ return x + x; // NaN
+ else
+ return (xsb == 0) ? x : 0.0;
+ if (x > o_threshold)
+ return huge * huge; // overflow
+ if (x < u_threshold)
+ return twom1000 * twom1000; // underflow
+ }
+
+ // argument reduction
+ if (hx > 0x3fd62e42) { // if |x| > 0.5 ln2
+ if (hx < 0x3FF0A2B2) { // and |x| < 1.5 ln2
+ hi = x - ln2HI[xsb];
+ lo = ln2LO[xsb];
+ k = 1 - xsb - xsb;
+ } else {
+ k = (int) (invln2 * x + halF[xsb]);
+ t = k;
+ hi = x - t * ln2HI[0]; // t*ln2HI is exact here
+ lo = t * ln2LO[0];
+ }
+ x = hi - lo;
+ } else if (hx < 0x3e300000) { // when |x|<2**-28
+ if (huge + x > one)
+ return one + x;// trigger inexact
+ } else
+ k = 0;
+
+ // x is now in primary range
+ t = x * x;
+ c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+ if (k == 0)
+ return one - ((x * c) / (c - 2.0) - x);
+ else
+ y = one - ((lo - (x * c) / (2.0 - c)) - hi);
+ long yBits = Double.doubleToLongBits(y);
+ int __HIy = (int) (yBits >> 32);
+ if (k >= -1021) {
+ __HIy += (k << 20); // add k to y's exponent
+ yBits = ((__HIy & 0xFFFFFFFFL) << 32) | (yBits & 0xFFFFFFFFL);
+ y = Double.longBitsToDouble(yBits);
+ return y;
+ } else {
+ __HIy += ((k + 1000) << 20);// add k to y's exponent
+ yBits = ((__HIy & 0xFFFFFFFFL) << 32) | (yBits & 0xFFFFFFFFL);
+ y = Double.longBitsToDouble(yBits);
+ return y * twom1000;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/lang/Parallelizable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/Parallelizable.java b/commons/marmotta-commons/src/ext/java/javolution/lang/Parallelizable.java
new file mode 100644
index 0000000..5238c1d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/Parallelizable.java
@@ -0,0 +1,78 @@
+/*
+ * 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.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p> Indicates that a class, a method or a field can be used by multiple
+ * threads concurrently and whether or not it is
+ * {@link Parallelizable#mutexFree() mutex-free} (not blocking).</p>
+ *
+ * [code]
+ * public class Operators {
+ * @Parallelizable
+ * public static final Reducer<Object> ANY = new Reducer<Object>() { ... }
+ *
+ * @Parallelizable(mutexFree = false, comment="Internal use of synchronization")
+ * public static final Reducer<Object> MAX = new Reducer<Object>() { ... }
+ *
+ * @Parallelizable(mutexFree = false, comment="Internal use of synchronization")
+ * public static final Reducer<Object> MIN = new Reducer<Object>() { ... }
+ *
+ * @Parallelizable
+ * public static final Reducer<Boolean> AND = new Reducer<Boolean>() { ... }
+ *
+ * @Parallelizable
+ * public static final Reducer<Boolean> OR = new Reducer<Boolean>() { ... }
+ *
+ * @Parallelizable(comment="Internal use of AtomicInteger")
+ * public static final Reducer<Integer> SUM = new Reducer<Integer>() { ... }
+ * }[/code]
+ *
+ * <p> Classes with no internal fields or {@link javolution.lang.Immutable
+ * Immutable} are usually parallelizable and mutex-free.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see <a href="http://en.wikipedia.org/wiki/Mutual_exclusion">Wikipedia: Mutual Exclusion</a>
+ */
+@Documented
+@Inherited
+@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Parallelizable {
+
+ /**
+ * Indicates if this element can safely be used concurrently
+ * (default {@code true}).
+ */
+ boolean value() default true;
+
+ /**
+ * Indicates if this element does not use any form of mutex to
+ * access shared resources (default {@code true}). To avoid
+ * <a href="http://en.wikipedia.org/wiki/Priority_inversion">
+ * priority inversion</a> and possibly unbounded response times,
+ * a real-time VM (with priority inheritance) is recommended
+ * when using {@link Realtime real-time} elements which are not mutex-free.
+ */
+ boolean mutexFree() default true;
+
+ /**
+ * Provides additional information (default {@code ""}).
+ */
+ String comment() default "";
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/lang/Realtime.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/Realtime.java b/commons/marmotta-commons/src/ext/java/javolution/lang/Realtime.java
new file mode 100644
index 0000000..2757ad3
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/Realtime.java
@@ -0,0 +1,118 @@
+/*
+ * 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.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p> Indicates if an element has a bounded
+ * <a href="http://en.wikipedia.org/wiki/Worst-case_execution_time">
+ * worst-case execution time</a>. The {@link #limit limit} behavior
+ * of the execution time with the input size may be specified (if no limit
+ * specified the worst case execution time is assumed to be constant).</p>
+ *
+ * [code]
+ * public class Equalities {
+ * @Realtime(limit = UNKNOWN)
+ * public static final Equality<Object> STANDARD = new StandardComparatorImpl<Object>();
+ *
+ * @Realtime(limit = CONSTANT)
+ * public static final Equality<Object> IDENTITY = new IdentityComparatorImpl<Object>();
+ *
+ * @Realtime(limit = LINEAR)
+ * public static final Equality<Object> ARRAY = new ArrayComparatorImpl();
+ *
+ * @Realtime(limit = LINEAR)
+ * public static final Equality<CharSequence> LEXICAL = new LexicalComparatorImpl();
+ * }[/code]
+ *
+ * <p> Analysis tools / compilers may produce warnings if program elements
+ * use or override elements with incompatible real-time characteristics.</p>
+ *
+ * <p> Note: For multi-cores systems, if a real-time element is {@link Parallelizable}
+ * but not {@link Parallelizable#mutexFree() mutex-free}, response
+ * time even for high priority threads may be unbounded due to
+ * <a href="http://en.wikipedia.org/wiki/Priority_inversion">priority
+ * inversion</a>. This is no longer the case when running on real-time
+ * VMs due to their support for priority inheritance.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see <a href="http://en.wikipedia.org/wiki/Real-time_computing">Real-Time Computing</a>
+ */
+@Documented
+@Inherited
+@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
+ ElementType.CONSTRUCTOR })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Realtime {
+
+ /**
+ * Indicates if this element has a bounded worst-case execution time
+ * (default {@code true}).
+ */
+ boolean value() default true;
+
+ /**
+ * Returns the limit behavior for the worst-case execution time
+ * (default {@link Limit#CONSTANT}).
+ */
+ Limit limit() default Limit.CONSTANT;
+
+ /**
+ * Provides additional information (default {@code ""}).
+ */
+ String comment() default "";
+
+ /**
+ * Identifies the limit behavior for the worst case execution time.
+ */
+ public enum Limit {
+
+ /**
+ * The worst case execution time is constant.
+ */
+ CONSTANT,
+
+ /**
+ * The worst case execution time is bounded in <i>O(log(n))</i>
+ * with <i>n</i> characteristic of the current size of the inputs.
+ */
+ LOG_N,
+
+ /**
+ * The worst case execution time is bounded in <i>O(n)</i>
+ * with <i>n</i> characteristic of the current size of the inputs.
+ */
+ LINEAR,
+
+ /**
+ * The worst case execution time is bounded in <i>O(n log(n))</i>
+ * with <i>n</i> characteristic of the current size of the inputs.
+ */
+ N_LOG_N,
+
+ /**
+ * The worst case execution time is bounded in <i>O(n²)</i>
+ * with <i>n</i> characteristic of the current size of the inputs.
+ */
+ N_SQUARE,
+
+ /**
+ * The limit behavior of the worst case execution time is unknown
+ * or unspecified.
+ */
+ UNKNOWN,
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/lang/ValueType.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/ValueType.java b/commons/marmotta-commons/src/ext/java/javolution/lang/ValueType.java
new file mode 100644
index 0000000..d26cb01
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/ValueType.java
@@ -0,0 +1,71 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2007 - 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.lang;
+
+
+/**
+ * <p> An {@link Immutable immutable} object which can be manipulated by value;
+ * a JVM implementation may allocate instances of this class on the stack.</p>
+ *
+ * <p> {@link ValueType ValueType} extends {@link Immutable} with the additional
+ * constraint that its value is itself (the {@link #value value} method
+ * returns {@code this}).
+ * [code]
+ * public final class Complex implements ValueType<Complex> { // Complex is immutable.
+ * public class Variable implements Immutable<Complex> { // Variable has immutable value.
+ * private Variable() {} // Do not provide access outside.
+ * public Variable add(Complex that) {
+ * real += that.real;
+ * imaginary += that.imaginary;
+ * return this;
+ * }
+ * @Override
+ * public Complex value() { return new Complex(real, imaginary); }
+ * }
+ * private double real, imaginary;
+ * public Complex(double real, double imaginary) {
+ * this.real = real;
+ * this.imaginary = imaginary;
+ * }
+ * public Complex plus(Complex that) {
+ * return new Complex(this.real + that.real, this.imaginary + this.imaginary);
+ * }
+ * @Override
+ * public Complex value() { return this; } // As per ValueType contract.
+ * public Variable newVariable() { return new Complex(real, imaginary).new Variable(); }
+ * }
+ * // Calculates the sum of an array of complex values.
+ * Complex[] values = ...;
+ *
+ * // Standard calculations (stresses GC due to the high number of objects allocated).
+ * Complex sum = Complex.ZERO;
+ * for (Complex c : values) sum = sum.plus(c);
+ *
+ * // Using variables, 2-3x faster and almost no garbage generated !
+ * Complex.Variable sum = Complex.ZERO.newVariable();
+ * for (Complex c : values) sum.add(c);
+ * [/code]</p>
+ *
+ * <p> <b>Note:</b> "Stack" allocation is not the only optimization that a VM
+ * can do on {@link ValueType}. The VM might decide not to perform any
+ * allocation at all and store values directly in registers.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @param <T> The type of the immutable constant value.
+ */
+public interface ValueType<T> extends Immutable<T> {
+
+ /**
+ * Returns {@code this}.
+ */
+ @Override
+ T value();
+
+}
\ 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/lang/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/lang/package-info.java
new file mode 100644
index 0000000..0e2643e
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/package-info.java
@@ -0,0 +1,5 @@
+/**
+<p> Fundamental classes, interfaces and annotations. </p>
+ */
+package javolution.lang;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ConfigurableListenerImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ConfigurableListenerImpl.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ConfigurableListenerImpl.java
new file mode 100644
index 0000000..8983824
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ConfigurableListenerImpl.java
@@ -0,0 +1,32 @@
+/*
+ * 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.osgi.internal;
+
+import javolution.context.LogContext;
+import javolution.lang.Configurable;
+
+/**
+ * Holds the default implementation of Configurable.Listener when running
+ * outside OSGi (logs configuration events).
+ */
+public final class ConfigurableListenerImpl implements Configurable.Listener {
+
+ @Override
+ public <T> void configurableInitialized(Configurable<T> configurable,
+ T value) {
+ LogContext.debug(configurable.getName(), "=", value);
+ }
+
+ @Override
+ public <T> void configurableReconfigured(Configurable<T> configurable,
+ T oldValue, T newValue) {
+ LogContext.debug(configurable.getName(),
+ " reconfigured from ", oldValue, " to ", newValue);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/JavolutionActivator.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/JavolutionActivator.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/JavolutionActivator.java
new file mode 100644
index 0000000..a4b1c6d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/JavolutionActivator.java
@@ -0,0 +1,75 @@
+/*
+ * 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.osgi.internal;
+
+import javolution.xml.stream.XMLInputFactory;
+import javolution.xml.stream.XMLOutputFactory;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Javolution OSGi bundle activator.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class JavolutionActivator implements BundleActivator {
+
+ // Services provided by Javolution.
+ private ServiceRegistration<XMLInputFactory> xmlInputFactoryRegistration;
+ private ServiceRegistration<XMLOutputFactory> xmlOutputFactoryRegistration;
+
+ @SuppressWarnings("unchecked")
+ public void start(BundleContext bc) throws Exception {
+
+ // Activate services trackers.
+ OSGiServices.CONCURRENT_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.CONFIGURABLE_LISTENER_TRACKER.activate(bc);
+ OSGiServices.LOCAL_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.LOG_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.LOG_SERVICE_TRACKER.activate(bc);
+ OSGiServices.SECURITY_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.STORAGE_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.TEXT_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.XML_CONTEXT_TRACKER.activate(bc);
+ OSGiServices.XML_INPUT_FACTORY_TRACKER.activate(bc);
+ OSGiServices.XML_OUTPUT_FACTORY_TRACKER.activate(bc);
+
+ // Publish XMLInputFactory/XMLOutputFactory services.
+ xmlInputFactoryRegistration = (ServiceRegistration<XMLInputFactory>) bc
+ .registerService(XMLInputFactory.class.getName(),
+ new XMLInputFactoryProvider(), null);
+ xmlOutputFactoryRegistration = (ServiceRegistration<XMLOutputFactory>) bc
+ .registerService(XMLOutputFactory.class.getName(),
+ new XMLOutputFactoryProvider(), null);
+
+ // Ensures low latency for real-time classes.
+ OSGiServices.initializeRealtimeClasses();
+ }
+
+ public void stop(BundleContext bc) throws Exception {
+ OSGiServices.CONCURRENT_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.CONFIGURABLE_LISTENER_TRACKER.deactivate(bc);
+ OSGiServices.LOCAL_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.LOG_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.LOG_SERVICE_TRACKER.deactivate(bc);
+ OSGiServices.SECURITY_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.STORAGE_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.TEXT_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.XML_CONTEXT_TRACKER.deactivate(bc);
+ OSGiServices.XML_INPUT_FACTORY_TRACKER.deactivate(bc);
+ OSGiServices.XML_OUTPUT_FACTORY_TRACKER.deactivate(bc);
+
+ xmlInputFactoryRegistration.unregister();
+ xmlOutputFactoryRegistration.unregister();
+ }
+
+}
\ 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/osgi/internal/LogServiceImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/LogServiceImpl.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/LogServiceImpl.java
new file mode 100644
index 0000000..8fa4ece
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/LogServiceImpl.java
@@ -0,0 +1,115 @@
+/*
+ * 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.osgi.internal;
+
+import javolution.util.FastTable;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * Holds the default implementation of LogService to be used when running
+ * outside OSGi or when the Javolution bundle is not started.
+ */
+public final class LogServiceImpl extends Thread implements LogService {
+
+ private static class LogEvent {
+ Throwable exception;
+ int level;
+ String message;
+ }
+
+ private final FastTable<LogEvent> eventQueue = new FastTable<LogEvent>();
+
+ public LogServiceImpl() {
+ super("Logging-Thread");
+ setDaemon(true);
+ this.start();
+ Thread hook = new Thread(new Runnable() {
+ @Override
+ public void run() { // Maintains the VM alive until the event queue is flushed
+ synchronized (eventQueue) {
+ try {
+ while (!eventQueue.isEmpty())
+ eventQueue.wait();
+ } catch (InterruptedException e) {}
+ }
+ }
+ });
+ Runtime.getRuntime().addShutdownHook(hook);
+ }
+
+ @Override
+ public void log(int level, String message) {
+ log(level, message, null);
+ }
+
+ @Override
+ public void log(int level, String message, Throwable exception) {
+ LogEvent event = new LogEvent();
+ event.level = level;
+ event.message = message;
+ event.exception = exception;
+ synchronized (eventQueue) {
+ eventQueue.addFirst(event);
+ eventQueue.notify();
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void log(ServiceReference sr, int level, String message) {
+ throw new UnsupportedOperationException();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void log(ServiceReference sr, int level, String message,
+ Throwable exception) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ LogEvent event;
+ synchronized (eventQueue) {
+ while (eventQueue.isEmpty())
+ eventQueue.wait();
+ event = eventQueue.pollLast();
+ eventQueue.notify();
+ }
+ switch (event.level) {
+ case LogService.LOG_DEBUG:
+ System.out.println("[DEBUG] " + event.message);
+ break;
+ case LogService.LOG_INFO:
+ System.out.println("[INFO] " + event.message);
+ break;
+ case LogService.LOG_WARNING:
+ System.out.println("[WARNING] " + event.message);
+ break;
+ case LogService.LOG_ERROR:
+ System.out.println("[ERROR] " + event.message);
+ break;
+ default:
+ System.out.println("[UNKNOWN] " + event.message);
+ break;
+ }
+ if (event.exception != null) {
+ event.exception.printStackTrace(System.out);
+ }
+ } catch (InterruptedException error) {
+ error.printStackTrace(System.err);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/OSGiServices.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/OSGiServices.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/OSGiServices.java
new file mode 100644
index 0000000..5c35abe
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/OSGiServices.java
@@ -0,0 +1,150 @@
+/*
+ * 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.osgi.internal;
+
+import javolution.context.ConcurrentContext;
+import javolution.context.LocalContext;
+import javolution.context.LogContext;
+import javolution.context.SecurityContext;
+import javolution.context.StorageContext;
+import javolution.context.internal.ConcurrentContextImpl;
+import javolution.context.internal.LocalContextImpl;
+import javolution.context.internal.LogContextImpl;
+import javolution.context.internal.SecurityContextImpl;
+import javolution.context.internal.StorageContextImpl;
+import javolution.io.Struct;
+import javolution.lang.Configurable;
+import javolution.lang.Initializer;
+import javolution.lang.MathLib;
+import javolution.text.Text;
+import javolution.text.TextContext;
+import javolution.text.TypeFormat;
+import javolution.text.internal.TextContextImpl;
+import javolution.util.FastBitSet;
+import javolution.util.FastSortedMap;
+import javolution.util.FastSortedSet;
+import javolution.util.FastSortedTable;
+import javolution.util.Index;
+import javolution.util.function.Equalities;
+import javolution.util.function.Reducers;
+import javolution.xml.XMLContext;
+import javolution.xml.internal.XMLContextImpl;
+import javolution.xml.internal.stream.XMLInputFactoryImpl;
+import javolution.xml.internal.stream.XMLOutputFactoryImpl;
+import javolution.xml.internal.stream.XMLStreamReaderImpl;
+import javolution.xml.internal.stream.XMLStreamWriterImpl;
+import javolution.xml.stream.XMLInputFactory;
+import javolution.xml.stream.XMLOutputFactory;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * The OSGi services tracked by the Javolution bundle.
+ * When running outside OSGi or when the Javolution bundle is not started
+ * the default service implementation is returned.
+ */
+public class OSGiServices {
+
+ final static ServiceTrackerImpl<ConcurrentContext> CONCURRENT_CONTEXT_TRACKER = new ServiceTrackerImpl<ConcurrentContext>(
+ ConcurrentContext.class, ConcurrentContextImpl.class);
+ final static ServiceTrackerImpl<Configurable.Listener> CONFIGURABLE_LISTENER_TRACKER = new ServiceTrackerImpl<Configurable.Listener>(
+ Configurable.Listener.class, ConfigurableListenerImpl.class);
+ final static ServiceTrackerImpl<LocalContext> LOCAL_CONTEXT_TRACKER = new ServiceTrackerImpl<LocalContext>(
+ LocalContext.class, LocalContextImpl.class);
+ final static ServiceTrackerImpl<LogContext> LOG_CONTEXT_TRACKER = new ServiceTrackerImpl<LogContext>(
+ LogContext.class, LogContextImpl.class);
+ final static ServiceTrackerImpl<LogService> LOG_SERVICE_TRACKER = new ServiceTrackerImpl<LogService>(
+ LogService.class, LogServiceImpl.class);
+ final static ServiceTrackerImpl<SecurityContext> SECURITY_CONTEXT_TRACKER = new ServiceTrackerImpl<SecurityContext>(
+ SecurityContext.class, SecurityContextImpl.class);
+ final static ServiceTrackerImpl<StorageContext> STORAGE_CONTEXT_TRACKER = new ServiceTrackerImpl<StorageContext>(
+ StorageContext.class, StorageContextImpl.class);
+ final static ServiceTrackerImpl<TextContext> TEXT_CONTEXT_TRACKER = new ServiceTrackerImpl<TextContext>(
+ TextContext.class, TextContextImpl.class);
+ final static ServiceTrackerImpl<XMLContext> XML_CONTEXT_TRACKER = new ServiceTrackerImpl<XMLContext>(
+ XMLContext.class, XMLContextImpl.class);
+ final static ServiceTrackerImpl<XMLInputFactory> XML_INPUT_FACTORY_TRACKER = new ServiceTrackerImpl<XMLInputFactory>(
+ XMLInputFactory.class, XMLInputFactoryImpl.class);
+ final static ServiceTrackerImpl<XMLOutputFactory> XML_OUTPUT_FACTORY_TRACKER = new ServiceTrackerImpl<XMLOutputFactory>(
+ XMLOutputFactory.class, XMLOutputFactoryImpl.class);
+
+ /** Returns concurrent context services. */
+ public static ConcurrentContext getConcurrentContext() {
+ return (ConcurrentContext)CONCURRENT_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns configurable listener services. */
+ public static Object[] getConfigurableListeners() {
+ return CONFIGURABLE_LISTENER_TRACKER.getServices();
+ }
+
+ /** Returns local context service. */
+ public static LocalContext getLocalContext() {
+ return (LocalContext)LOCAL_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns log context service. */
+ public static LogContext getLogContext() {
+ return (LogContext)LOG_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns OSGi log service. */
+ public static Object[] getLogServices() {
+ return LOG_SERVICE_TRACKER.getServices();
+ }
+
+ /** Returns security context service. */
+ public static SecurityContext getSecurityContext() {
+ return (SecurityContext) SECURITY_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns storage context service. */
+ public static StorageContext getStorageContext() {
+ return (StorageContext) STORAGE_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns text context service. */
+ public static TextContext getTextContext() {
+ return (TextContext)TEXT_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns xml context service. */
+ public static XMLContext getXMLContext() {
+ return (XMLContext)XML_CONTEXT_TRACKER.getServices()[0];
+ }
+
+ /** Returns xml input factory service. */
+ public static XMLInputFactory getXMLInputFactory() {
+ return (XMLInputFactory)XML_INPUT_FACTORY_TRACKER.getServices()[0];
+ }
+
+ /** Returns xml output factory service. */
+ public static XMLOutputFactory getXMLOutputFactory() {
+ return (XMLOutputFactory)XML_OUTPUT_FACTORY_TRACKER.getServices()[0];
+ }
+
+ /** Initializes all real-time classes. */
+ public static boolean initializeRealtimeClasses() {
+ Initializer initializer = new Initializer(OSGiServices.class.getClassLoader());
+ initializer.loadClass(MathLib.class);
+ initializer.loadClass(Text.class);
+ initializer.loadClass(TypeFormat.class);
+ initializer.loadClass(Struct.class);
+ initializer.loadClass(FastBitSet.class);
+ initializer.loadClass(FastSortedMap.class);
+ initializer.loadClass(FastSortedSet.class);
+ initializer.loadClass(FastSortedTable.class);
+ initializer.loadClass(Index.class); // Preallocates.
+ initializer.loadClass(Reducers.class);
+ initializer.loadClass(Equalities.class);
+ initializer.loadClass(XMLStreamReaderImpl.class);
+ initializer.loadClass(XMLStreamWriterImpl.class);
+ return initializer.initializeLoadedClasses();
+ }
+}
\ 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/osgi/internal/ServiceTrackerImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ServiceTrackerImpl.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ServiceTrackerImpl.java
new file mode 100644
index 0000000..ac4afdf
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/ServiceTrackerImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.osgi.internal;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Bridge to service tracker (does not trigger class loading exception
+ * if running outside OSGi).
+ */
+public final class ServiceTrackerImpl<C> {
+
+ private volatile ServiceTracker<C, C> tracker;
+ private final Class<C> type;
+ private final Class<? extends C> defaultImplClass;
+ private C defaultImpl;
+
+ /** Creates a context tracker for the specified context type. */
+ public ServiceTrackerImpl(Class<C> type, Class<? extends C> defaultImplClass) {
+ this.defaultImplClass = defaultImplClass;
+ this.type = type;
+ }
+
+ /** Activates OSGi tracking. */
+ public void activate(BundleContext bc) {
+ ServiceTracker<C, C> trk = new ServiceTracker<C, C>(bc, type, null);
+ trk.open();
+ tracker = trk;
+ }
+
+ /** Deactivates OSGi tracking. */
+ public void deactivate(BundleContext bc) {
+ tracker.close();
+ tracker = null;
+ }
+
+ /** Returns the published services or the default implementation if none. */
+ public Object[] getServices() {
+ ServiceTracker<C, C> trk = tracker;
+ if (trk != null) {
+ Object[] services = trk.getServices();
+ if (services != null) return services;
+ }
+ synchronized (this) {
+ if (defaultImpl == null) {
+ try {
+ defaultImpl = defaultImplClass.newInstance();
+ } catch (Throwable error) {
+ throw new RuntimeException(error);
+ }
+ }
+ }
+ return new Object[] { defaultImpl };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLInputFactoryProvider.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLInputFactoryProvider.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLInputFactoryProvider.java
new file mode 100644
index 0000000..e051200
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLInputFactoryProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.osgi.internal;
+
+import javolution.xml.internal.stream.XMLInputFactoryImpl;
+import javolution.xml.stream.XMLInputFactory;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Holds the service factory providing XMLInputFactory instances.
+ */
+public final class XMLInputFactoryProvider implements ServiceFactory<XMLInputFactory> {
+
+ @Override
+ public XMLInputFactory getService(Bundle bundle,
+ ServiceRegistration<XMLInputFactory> registration) {
+ return new XMLInputFactoryImpl();
+ }
+
+ @Override
+ public void ungetService(Bundle bundle,
+ ServiceRegistration<XMLInputFactory> registration,
+ XMLInputFactory service) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLOutputFactoryProvider.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLOutputFactoryProvider.java b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLOutputFactoryProvider.java
new file mode 100644
index 0000000..e606805
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/osgi/internal/XMLOutputFactoryProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.osgi.internal;
+
+import javolution.xml.internal.stream.XMLOutputFactoryImpl;
+import javolution.xml.stream.XMLOutputFactory;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Holds the service factory providing XMLInputFactory instances.
+ */
+public final class XMLOutputFactoryProvider implements ServiceFactory<XMLOutputFactory> {
+
+ @Override
+ public XMLOutputFactory getService(Bundle bundle,
+ ServiceRegistration<XMLOutputFactory> registration) {
+ return new XMLOutputFactoryImpl();
+ }
+
+ @Override
+ public void ungetService(Bundle bundle,
+ ServiceRegistration<XMLOutputFactory> registration,
+ XMLOutputFactory service) {
+ }
+}
[10/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/FastCollection.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastCollection.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastCollection.java
new file mode 100644
index 0000000..8160097
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastCollection.java
@@ -0,0 +1,715 @@
+/*
+ * 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.CONSTANT;
+import static javolution.lang.Realtime.Limit.LINEAR;
+import static javolution.lang.Realtime.Limit.N_SQUARE;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+import javolution.lang.Immutable;
+import javolution.lang.Parallelizable;
+import javolution.lang.Realtime;
+import javolution.text.Cursor;
+import javolution.text.DefaultTextFormat;
+import javolution.text.TextContext;
+import javolution.text.TextFormat;
+import javolution.util.function.Consumer;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.function.Function;
+import javolution.util.function.Predicate;
+import javolution.util.function.Reducer;
+import javolution.util.function.Reducers;
+import javolution.util.internal.collection.AtomicCollectionImpl;
+import javolution.util.internal.collection.DistinctCollectionImpl;
+import javolution.util.internal.collection.FilteredCollectionImpl;
+import javolution.util.internal.collection.MappedCollectionImpl;
+import javolution.util.internal.collection.ParallelCollectionImpl;
+import javolution.util.internal.collection.ReversedCollectionImpl;
+import javolution.util.internal.collection.SequentialCollectionImpl;
+import javolution.util.internal.collection.SharedCollectionImpl;
+import javolution.util.internal.collection.SortedCollectionImpl;
+import javolution.util.internal.collection.UnmodifiableCollectionImpl;
+import javolution.util.service.CollectionService;
+
+/**
+ * <p> A closure-based collection supporting numerous views which can be chained.
+ * <ul>
+ * <li>{@link #atomic} - Thread-safe view for which all reads are mutex-free
+ * and collection updates (including {@link #addAll addAll}, {@link #removeIf removeIf}} are atomic.</li>
+ * <li>{@link #shared} - Thread-safe view using allowing concurrent reads based
+ * on mutex (<a href="http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock">
+ * readers-writer locks).</li>
+ * <li>{@link #parallel} - A view allowing parallel processing including {@link #update updates}.</li>
+ * <li>{@link #sequential} - View disallowing parallel processing.</li>
+ * <li>{@link #unmodifiable} - View which does not allow any modification.</li>
+ * <li>{@link #filtered filtered(filter)} - View exposing only the elements matching the specified filter.</li>
+ * <li>{@link #mapped mapped(function)} - View exposing elements through the specified mapping function.</li>
+ * <li>{@link #sorted sorted(comparator)} - View exposing elements sorted according to their natural order
+ * of using a specified comparator.</li>
+ * <li>{@link #reversed} - View exposing elements in the reverse iterative order.</li>
+ * <li>{@link #distinct} - View exposing each element only once.</li>
+ * </ul></p>
+ *
+ * <p> Unmodifiable collections are not always immutable. An {@link javolution.lang.Immutable immutable}.
+ * reference (or const reference) can only be {@link #toImmutable() obtained} when the originator
+ * guarantees that the collection source will not be modified even by himself
+ * (the value of the immutable reference being an {@link #unmodifiable unmodifiable} collection).
+ * [code]
+ * Immutable<List<String>> winners
+ * = new FastTable<String>().addAll("John Deuff", "Otto Graf", "Sim Kamil").toImmutable();
+ * // Immutability is guaranteed, no reference left on the collection source.
+ * [/code]</p>
+ *
+ * <p> Atomic collections use <a href="http://en.wikipedia.org/wiki/Copy-on-write">Copy-On-Write</a>
+ * optimizations in order to provide mutex-free read access. Only writes operations are mutually
+ * exclusive. Collections can be optimized to not require the full copy during write operations
+ * (e.g. immutable parts don't need to be copied). Still, when multiple updates are performed,
+ * it is beneficial to group them into one single {@link #update update} operation.
+ * [code]
+ * FastTable<String> tokens = new FastTable<String>().atomic();
+ * ...
+ * // Replace null with "" in tokens. If tokens is atomic the update is atomic.
+ * // If tokens is parallel, the update is also performed concurrently !
+ * tokens.update(new Consumer<List<String>>() {
+ * public void accept(List<String> view) {
+ * for (int i=0, n = view.size(); i < n; i++)
+ * if (view.get(i) == null) view.set(i, "");
+ * }
+ * }
+ * });[/code]</p>
+ * <p> The same code using closure (Java 8).
+ * [code]
+ * tokens.update((List<String> view) -> {
+ * for (int i = 0, n = view.size(); i < n; i++) {
+ * if (view.get(i) == null) view.set(i, "");
+ * }
+ * });[/code]</p>
+ *
+ * <p> Views are similar to <a href="http://lambdadoc.net/api/java/util/stream/package-summary.html">
+ * Java 8 streams</a> except that views are themselves collections (virtual collections)
+ * and actions on a view can impact the original collection. Collection views are nothing "new"
+ * since they already existed in the original java.util collection classes (e.g. List.subList(...),
+ * Map.keySet(), Map.values()). Javolution extends to this concept and allows views to be chained
+ * which addresses the concern of class proliferation.</p>
+ * [code]
+ * FastTable<String> names = new FastTable<String>().addAll("Oscar Thon", "Eva Poret", "Paul Auchon");
+ * boolean found = names.comparator(Equalities.LEXICAL_CASE_INSENSITIVE).contains("LUC SURIEUX");
+ * names.subTable(0, n).clear(); // Removes the n first names (see java.util.List.subList).
+ * names.distinct().add("Guy Liguili"); // Adds "Guy Liguili" only if not already present.
+ * names.filtered(isLong).clear(); // Removes all the persons with long names.
+ * names.filtered(isLong).parallel().clear(); // Same as above but performed concurrently !
+ * ...
+ * Predicate<CharSequence> isLong = new Predicate<CharSequence>() {
+ * public boolean test(CharSequence csq) {
+ * return csq.length() > 16;
+ * }
+ * });[/code]</p>
+ *
+ * <p> Views can of course be used to perform "stream" oriented filter-map-reduce operations with the same benefits:
+ * Parallelism support, excellent memory characteristics (no caching and cost nothing to create), etc.
+ * [code]
+ * String anyLongName = names.filtered(isLong).any(String.class); // Returns any long name.
+ * int nbrChars = names.mapped(toLength).reduce(Reducers.sum()); // Returns the total number of characters.
+ * int maxLength = names.mapped(toLength).parallel().max(); // Finds the longest name in parallel.
+ * ...
+ * Function<CharSequence, Integer> toLength = new Function<CharSequence, Integer>() {
+ * public Integer apply(CharSequence csq) {
+ * return csq.length();
+ * }
+ * });
+ *
+ * // JDK Class.getEnclosingMethod using Javolution's views and Java 8 (to be compared with the current 20 lines implementation !).
+ * Method matching = new FastTable<Method>().addAll(enclosingInfo.getEnclosingClass().getDeclaredMethods())
+ * .filtered(m -> Equalities.STANDARD.areEqual(m.getName(), enclosingInfo.getName())
+ * .filtered(m -> Equalities.ARRAY.areEqual(m.getParameterTypes(), parameterClasses))
+ * .filtered(m -> Equalities.STANDARD.areEqual(m.getReturnType(), returnType))
+ * .any(Method.class);
+ * if (matching == null) throw new InternalError("Enclosing method not found");
+ * return matching;[/code]</p>
+ *
+ * <p> If a collection (or a map) is shared, derived views are also thread-safe.
+ * Similarly, if a collection is {@link #parallel parallel}, closure-based iterations
+ * on derived views are performed concurrently.
+ * [code]
+ * FastTable<Person> persons = new FastTable<Person>().parallel();
+ * ...
+ * // Since persons is parallel, the search is done concurrently.
+ * Person john = persons.filtered(new Predicate<Person>() {
+ * public boolean test(Person person) {
+ * return person.getName().equals("John");
+ * }
+ * }).any(Person.class);[/code]</p>
+ *
+ * <p> With Java 8, closures are greatly simplified using lambda expressions.
+ * [code]
+ * Person john = persons.filtered(person -> person.getName().equals("John")).any(Person.class); // Same as above.
+ * tasks.parallel().forEach(task -> task.run());
+ * names.sorted().reversed().forEach(str -> System.out.println(str)); // Prints names in reverse alphabetical order.
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+@Realtime
+@DefaultTextFormat(FastCollection.Format.class)
+public abstract class FastCollection<E> implements Collection<E>, Serializable {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Default constructor.
+ */
+ protected FastCollection() {}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ /**
+ * Returns an atomic view over this collection. All operations that write
+ * or access multiple elements in the collection (such as addAll(),
+ * retainAll()) are atomic.
+ * Iterators on atomic collections are <b>thread-safe</b>
+ * (no {@link ConcurrentModificationException} possible).
+ */
+ @Parallelizable(mutexFree = true, comment = "Except for write operations, all read operations are mutex-free.")
+ public FastCollection<E> atomic() {
+ return new AtomicCollectionImpl<E>(service());
+ }
+
+ /**
+ * Returns a thread-safe view over this collection. The shared view
+ * allows for concurrent read as long as there is no writer.
+ * The default implementation is based on <a href=
+ * "http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock">
+ * readers-writers locks</a> giving priority to writers.
+ * Iterators on shared collections are <b>thread-safe</b>
+ * (no {@link ConcurrentModificationException} possible).
+ */
+ @Parallelizable(mutexFree = false, comment = "Use multiple-readers/single-writer lock.")
+ public FastCollection<E> shared() {
+ return new SharedCollectionImpl<E>(service());
+ }
+
+ /**
+ * Returns a parallel collection. Closure-based operations are
+ * performed {@link javolution.context.ConcurrentContext in parallel}
+ * on {@link CollectionService#split sub-views} of this collection.
+ * The number of parallel views is equals to
+ * {@link javolution.context.ConcurrentContext#getConcurrency()
+ * concurrency}{@code + 1}.
+ *
+ * @see #perform(Consumer)
+ * @see #update(Consumer)
+ * @see #forEach(Consumer)
+ * @see #removeIf(Predicate)
+ * @see #reduce(Reducer)
+ */
+ public FastCollection<E> parallel() {
+ return new ParallelCollectionImpl<E>(service());
+ }
+
+ /**
+ * Returns a sequential view of this collection. Using this view,
+ * all closure-based iterations are performed sequentially.
+ */
+ public FastCollection<E> sequential() {
+ return new SequentialCollectionImpl<E>(service());
+ }
+
+ /**
+ * Returns an unmodifiable view over this collection. Any attempt to
+ * modify the collection through this view will result into
+ * a {@link java.lang.UnsupportedOperationException} being raised.
+ */
+ public FastCollection<E> unmodifiable() {
+ return new UnmodifiableCollectionImpl<E>(service());
+ }
+
+ /**
+ * Returns a view exposing only the elements matching the specified
+ * filter. Adding elements not matching the specified filter has
+ * no effect. If this collection is initially empty, using a filtered
+ * view to add new elements ensure that this collection has only elements
+ * satisfying the filter predicate.
+ */
+ public FastCollection<E> filtered(Predicate<? super E> filter) {
+ return new FilteredCollectionImpl<E>(service(), filter);
+ }
+
+ /**
+ * Returns a view exposing elements through the specified mapping function.
+ * The returned view does not allow new elements to be added.
+ */
+ public <R> FastCollection<R> mapped(
+ Function<? super E, ? extends R> function) {
+ return new MappedCollectionImpl<E, R>(service(), function);
+ }
+
+ /**
+ * Returns a view exposing elements sorted according to the
+ * collection {@link #comparator() order}.
+ */
+ public FastCollection<E> sorted() {
+ return new SortedCollectionImpl<E>(service(), comparator());
+ }
+
+ /**
+ * Returns a view exposing elements sorted according to the specified
+ * comparator.
+ */
+ public FastCollection<E> sorted(Comparator<? super E> cmp) {
+ return new SortedCollectionImpl<E>(service(), cmp);
+ }
+
+ /**
+ * Returns a view exposing elements in reverse iterative order.
+ */
+ public FastCollection<E> reversed() {
+ return new ReversedCollectionImpl<E>(service());
+ }
+
+ /**
+ * Returns a view exposing only distinct elements (it does not iterate twice
+ * over the {@link #comparator() same} elements). Adding elements already
+ * in the collection through this view has no effect. If this collection is
+ * initially empty, using a distinct view to add new elements ensures that
+ * this collection has no duplicate.
+ */
+ public FastCollection<E> distinct() {
+ return new DistinctCollectionImpl<E>(service());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Closure operations.
+ //
+
+ /**
+ * Executes the specified read action on this collection.
+ * That logic may be performed concurrently (on parallel views)
+ * if this collection is {@link #parallel() parallel}.
+ *
+ *
+ * @param action the read-only action.
+ * @throws ClassCastException if the action type is not compatible with
+ * this collection (e.g. action on set and this is a list).
+ * @see #update(Consumer)
+ */
+ @SuppressWarnings("unchecked")
+ @Realtime(limit = LINEAR)
+ public void perform(Consumer<? extends Collection<E>> action) {
+ service().perform((Consumer<CollectionService<E>>) action, service());
+ }
+
+ /**
+ * Executes the specified update action on this collection.
+ * For {@link #atomic() atomic} collections the update is atomic
+ * (either concurrent readers see the full result of the action or
+ * nothing).
+ * The update may be performed concurrently (through parallel views)
+ * if this collection is {@link #parallel() parallel}.
+ *
+ * @param action the update action.
+ * @throws ClassCastException if the action type is not compatible with
+ * this collection (e.g. action on a {@link java.util.Set Set}
+ * and this is a {@link java.util.List List}).
+ * @see #perform(Consumer)
+ */
+ @SuppressWarnings("unchecked")
+ @Realtime(limit = LINEAR)
+ public void update(Consumer<? extends Collection<E>> action) {
+ service().update((Consumer<CollectionService<E>>) action, service());
+ }
+
+ /**
+ * Iterates over all this collection elements applying the specified
+ * consumer (convenience method). Iterations are performed concurrently
+ * if the collection is {@link #parallel() parallel}.
+ *
+ * @param consumer the functional consumer applied to the collection elements.
+ */
+ @Realtime(limit = LINEAR)
+ public void forEach(final Consumer<? super E> consumer) {
+ perform(new Consumer<Collection<E>>() {
+ public void accept(Collection<E> view) {
+ Iterator<E> it = view.iterator();
+ while (it.hasNext()) {
+ consumer.accept(it.next());
+ }
+ }
+ });
+ }
+
+ /**
+ * Removes from this collection all the elements matching the specified
+ * functional predicate (convenience method). Removals are performed
+ * concurrently if this collection is {@link #parallel() parallel} and
+ * atomically if this collection is {@link #atomic() atomic}.
+ *
+ * @param filter a predicate returning {@code true} for elements to be removed.
+ * @return {@code true} if at least one element has been removed;
+ * {@code false} otherwise.
+ */
+ @Realtime(limit = LINEAR)
+ public boolean removeIf(final Predicate<? super E> filter) {
+ final boolean[] removed = new boolean[1];
+ update(new Consumer<Collection<E>>() {
+ public void accept(Collection<E> view) {
+ Iterator<E> it = view.iterator();
+ while (it.hasNext()) {
+ if (filter.test(it.next())) {
+ it.remove(); // Ok mutable iteration.
+ removed[0] = true;
+ }
+ }
+ }
+ });
+ return removed[0];
+ }
+
+ /**
+ * Performs a reduction of the elements of this collection using the
+ * specified reducer. This may not involve iterating over all the
+ * collection elements, for example the reducers: {@link Reducers#any},
+ * {@link Reducers#and} and {@link Reducers#or} may stop iterating
+ * early. Reduction is performed concurrently if this collection is
+ * {@link #parallel() parallel}.
+ *
+ * @param reducer the collection reducer.
+ * @return the reduction result.
+ * @see #any(Class)
+ * @see #min()
+ * @see #max()
+ */
+ @Realtime(limit = LINEAR)
+ public E reduce(Reducer<E> reducer) {
+ perform(reducer);
+ return reducer.get();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Collection operations.
+ //
+
+ /** Adds the specified element to this collection */
+ @Override
+ @Realtime(limit = LINEAR, comment = "Could iterate the whole collection (e.g. distinct view).")
+ public boolean add(E element) {
+ return service().add(element);
+ }
+
+ /** Indicates if this collection is empty. */
+ @Override
+ @Realtime(limit = LINEAR, comment = "Could iterate the whole collection (e.g. filtered view).")
+ public boolean isEmpty() {
+ return iterator().hasNext();
+ }
+
+ /** Returns the size of this collection. */
+ @Override
+ @Realtime(limit = LINEAR, comment = "Could count the elements (e.g. filtered view).")
+ public int size() {
+ return service().size();
+ }
+
+ /** Removes all elements from this collection. */
+ @Override
+ @Realtime(limit = LINEAR, comment = "Could remove the elements one at a time.")
+ public void clear() {
+ service().clear();
+ }
+
+ /** Indicates if this collection contains the specified element. */
+ @Override
+ @Realtime(limit = LINEAR, comment = "Could search the whole collection.")
+ public boolean contains(Object searched) {
+ return service().contains(searched);
+ }
+
+ /** Removes the specified element from this collection.*/
+ @Override
+ @Realtime(limit = LINEAR, comment = "Could search the whole collection.")
+ public boolean remove(Object searched) {
+ return service().remove(searched);
+ }
+
+ /**
+ * Returns an iterator over this collection elements. For
+ * shared/atomic collections the iterator is immune to
+ * concurrent modifications. In other words the elements iterated over
+ * may or may not reflect the current state of the collection.
+ */
+ @Override
+ @Realtime(limit = N_SQUARE, comment = "Sorted view iterator require sorting the elements.")
+ public Iterator<E> iterator() {
+ return service().iterator();
+ }
+
+ /** Adds all the specified elements to this collection. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public boolean addAll(final Collection<? extends E> that) {
+ return service().addAll(that);
+ }
+
+ /** Indicates if this collection contains all the specified elements. */
+ @Override
+ @Realtime(limit = N_SQUARE)
+ public boolean containsAll(Collection<?> that) {
+ return service().containsAll(that);
+ }
+
+ /** Removes all the specified element from this collection. */
+ @Override
+ @Realtime(limit = N_SQUARE)
+ public boolean removeAll(final Collection<?> that) {
+ return service().removeAll(that);
+ }
+
+ /** Removes all the elements except those in the specified collection. */
+ @Override
+ @Realtime(limit = N_SQUARE)
+ public boolean retainAll(final Collection<?> that) {
+ return service().retainAll(that);
+ }
+
+ /** Returns an array holding this collection elements. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public Object[] toArray() {
+ return service().toArray();
+ }
+
+ /**
+ * Returns the specified array holding this collection elements if
+ * enough capacity.
+ */
+ @Override
+ @Realtime(limit = LINEAR)
+ public <T> T[] toArray(final T[] array) {
+ return service().toArray(array);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ /**
+ * Returns any non-null element of the specified type (convenience method).
+ * The search is performed concurrently if this collection is
+ * {@link #parallel() parallel}.
+ *
+ * @param type the element type searched for.
+ * @return {@code reduce(Reducers.any(type))}
+ * @see Reducers#any
+ */
+ @SuppressWarnings("unchecked")
+ @Realtime(limit = LINEAR)
+ public <T extends E> T any(Class<T> type) {
+ return (T) reduce((Reducer<E>) Reducers.any(type));
+ }
+
+ /**
+ * Returns the smallest element of this collection using this
+ * collection {@link #comparator() comparator} (convenience method).
+ * Returns {@code null} if this collection is empty.
+ * The search is performed concurrently if this collection is
+ * {@link #parallel() parallel}.
+ *
+ * @return {@code reduce(Reducers.min(comparator()))}
+ * @see Reducers#min
+ */
+ @Realtime(limit = LINEAR)
+ public E min() {
+ return reduce((Reducer<E>)Reducers.min(comparator())); // Cast only necessary on JDK 1.6 !
+ }
+
+ /**
+ * Returns the largest element of this collection using this
+ * collection {@link #comparator() comparator} (convenience method).
+ * Returns {@code null} if this collection is empty.
+ * The search is performed concurrently if this collection is
+ * {@link #parallel() parallel}.
+ *
+ * @return {@code reduce(Reducers.max(comparator()))}
+ * @see Reducers#max
+ */
+ @Realtime(limit = LINEAR)
+ public E max() {
+ return reduce((Reducer<E>)Reducers.max(comparator())); // Cast only necessary on JDK 1.6 !
+ }
+
+ /**
+ * Returns this collection with the specified element added.
+ *
+ * @param elements the elements to be added.
+ * @return {@code this}
+ */
+ @Realtime(limit = LINEAR)
+ public FastCollection<E> addAll(E... elements) {
+ for (E e : elements) {
+ add(e);
+ }
+ return this;
+ }
+
+ /**
+ * Returns this collection with the specified collection's elements added
+ * in sequence.
+ */
+ @Realtime(limit = LINEAR)
+ public FastCollection<E> addAll(FastCollection<? extends E> that) {
+ addAll((Collection<? extends E>) that);
+ return this;
+ }
+
+ /**
+ * Returns the comparator uses by this collection for equality and/or
+ * ordering if this collection is sorted.
+ */
+ @Realtime(limit = CONSTANT)
+ public Equality<? super E> comparator() {
+ return service().comparator();
+ }
+
+ /**
+ * Returns an immutable reference over this collection. The immutable
+ * value is an {@link #unmodifiable() unmodifiable} view of this collection.
+ * The caller must guarantees that the original collection is never going
+ * to be updated (e.g. there is no reference left on the original collection).
+ */
+ @Realtime(limit = CONSTANT)
+ public <T extends Collection<E>> Immutable<T> toImmutable() {
+ return new Immutable<T>() {
+ @SuppressWarnings("unchecked")
+ final T value = (T) unmodifiable();
+
+ @Override
+ public T value() {
+ return value;
+ }
+ };
+ }
+
+ /**
+ * Compares the specified object with this collection for equality.
+ * This method follows the {@link Collection#equals(Object)} specification
+ * if this collection {@link #comparator comparator} is
+ * {@link Equalities#STANDARD} (default). Otherwise, only collections
+ * using the same comparator can be considered equals.
+ *
+ * @param obj the object to be compared for equality with this collection
+ * @return <code>true</code> if both collections are considered equals;
+ * <code>false</code> otherwise.
+ */
+ @Override
+ @Realtime(limit = LINEAR)
+ public boolean equals(Object obj) {
+ if(obj instanceof FastCollection) {
+ return service().equals(((FastCollection) obj).service());
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the hash code of this collection.
+ * This method follows the {@link Collection#hashCode()} specification
+ * if this collection {@link #comparator comparator} is
+ * {@link Equalities#STANDARD}.
+ *
+ * @return this collection hash code.
+ */
+ @Override
+ @Realtime(limit = LINEAR)
+ public int hashCode() {
+ return service().hashCode();
+ }
+
+ /**
+ * Returns the string representation of this collection using its
+ * default {@link TextFormat format}.
+ *
+ * @see TextContext
+ */
+ @Override
+ @Realtime(limit = LINEAR)
+ public String toString() {
+ return TextContext.getFormat(FastCollection.class).format(this);
+ }
+
+ /**
+ * Returns the service implementation of this collection (for sub-classes).
+ */
+ protected abstract CollectionService<E> service();
+
+ /**
+ * Returns the service implementation of any fast collection
+ * (for sub-classes).
+ */
+ protected static <E> CollectionService<E> serviceOf(
+ FastCollection<E> collection) {
+ return collection.service();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Textual format.
+ //
+
+ /**
+ * Default text format for fast collections (parsing not supported).
+ * It is the format used when printing standard {@code java.util.Collection}
+ * instances except that elements are written using
+ * their current {@link TextContext TextContext} format.
+ */
+ @Parallelizable
+ public static class Format extends TextFormat<FastCollection<?>> {
+
+ @Override
+ public FastCollection<Object> parse(CharSequence csq, Cursor cursor)
+ throws IllegalArgumentException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Appendable format(FastCollection<?> that, final Appendable dest)
+ throws IOException {
+ dest.append('[');
+ Class<?> elementType = null;
+ TextFormat<Object> format = null;
+ for (Object element : that) {
+ if (elementType == null) elementType = Void.class;
+ else dest.append(", "); // Not the first.
+ if (element == null) {
+ dest.append("null");
+ continue;
+ }
+ Class<?> cls = element.getClass();
+ if (elementType.equals(cls)) {
+ format.format(element, dest);
+ continue;
+ }
+ elementType = cls;
+ format = TextContext.getFormat(cls);
+ format.format(element, dest);
+ }
+ return dest.append(']');
+ }
+
+ }
+
+}
\ 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/util/FastMap.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastMap.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastMap.java
new file mode 100644
index 0000000..852d86c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastMap.java
@@ -0,0 +1,422 @@
+/*
+ * 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.CONSTANT;
+import static javolution.lang.Realtime.Limit.LINEAR;
+
+import java.io.Serializable;
+import java.util.ConcurrentModificationException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+
+import javolution.lang.Immutable;
+import javolution.lang.Parallelizable;
+import javolution.lang.Realtime;
+import javolution.text.TextContext;
+import javolution.util.function.Consumer;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.internal.map.AtomicMapImpl;
+import javolution.util.internal.map.FastMapImpl;
+import javolution.util.internal.map.ParallelMapImpl;
+import javolution.util.internal.map.SequentialMapImpl;
+import javolution.util.internal.map.SharedMapImpl;
+import javolution.util.internal.map.UnmodifiableMapImpl;
+import javolution.util.service.CollectionService;
+import javolution.util.service.MapService;
+
+/**
+ * <p> A high-performance hash map with {@link Realtime real-time} behavior.
+ * Related to {@link FastCollection}, fast map supports various views.
+ * <ul>
+ * <li>{@link #atomic} - Thread-safe view for which all reads are mutex-free
+ * and map updates (e.g. {@link #putAll putAll}) are atomic.</li>
+ * <li>{@link #shared} - View allowing concurrent modifications.</li>
+ * <li>{@link #parallel} - A view allowing parallel processing including {@link #update updates}.</li>
+ * <li>{@link #sequential} - View disallowing parallel processing.</li>
+ * <li>{@link #unmodifiable} - View which does not allow any modifications.</li>
+ * <li>{@link #entrySet} - {@link FastSet} view over the map entries allowing
+ * entries to be added/removed.</li>
+ * <li>{@link #keySet} - {@link FastSet} view over the map keys allowing keys
+ * to be added (map entry with {@code null} value).</li>
+ * <li>{@link #values} - {@link FastCollection} view over the map values (add not supported).</li>
+ * </ul>
+ * <p> The iteration order over the map keys, values or entries is deterministic
+ * (unlike {@link java.util.HashMap}). It is either the insertion order (default)
+ * or the key order for the {@link FastSortedMap} subclass.
+ * This class permits {@code null} keys.</p>
+ *
+ * <p> Fast maps can advantageously replace any of the standard <code>java.util</code> maps.</p>
+ * [code]
+ * FastMap<Foo, Bar> hashMap = new FastMap<Foo, Bar>();
+ * FastMap<Foo, Bar> concurrentHashMap = new FastMap<Foo, Bar>().shared(); // FastMap implements ConcurrentMap interface.
+ * FastMap<Foo, Bar> linkedHashMap = new FastMap<Foo, Bar>(); // Deterministic iteration order (insertion order).
+ * FastMap<Foo, Bar> treeMap = new FastSortedMap<Foo, Bar>();
+ * FastMap<Foo, Bar> concurrentSkipListMap = new FastSortedMap<Foo, Bar>().shared();
+ * FastMap<Foo, Bar> identityHashMap = new FastMap<Foo, Bar>(Equalities.IDENTITY);[/code]</p>
+ * <p> and adds more ...
+ * [code]
+ * FastMap<Foo, Bar> atomicMap = new FastMap<Foo, Bar>().atomic(); // Mutex-free access, all updates (e.g. putAll) atomics (unlike ConcurrentHashMap).
+ * FastMap<Foo, Bar> atomicTree = new FastSortedMap<Foo, Bar>().atomic(); // Mutex-free access, all updates (e.g. putAll) atomics.
+ * FastMap<Foo, Bar> parallelMap = new FastMap<Foo, Bar>().parallel(); // Map actions (perform/update) performed concurrently.
+ * FastMap<Foo, Bar> linkedConcurrentHashMap = new FastMap<Foo, Bar>().shared(); // No equivalent in java.util !
+ * FastMap<String, Bar> lexicalHashMap = new FastMap<String, Bar>(Equalities.LEXICAL); // Allows for value retrieval using any CharSequence key.
+ * FastMap<String, Bar> fastStringHashMap = new FastMap<String, Bar>(Equalities.LEXICAL_FAST); // Same with faster hashcode calculations.
+ * ...[/code]</p>
+ *
+ * <p> Of course all views (entry, key, values) over a fast map are fast collections
+ * and allow parallel processing.
+ * [code]
+ * Consumer<Collection<String>> removeNull = new Consumer<Collection<String>>() {
+ * public void accept(Collection<String> view) {
+ * Iterator<String> it = view.iterator();
+ * while (it.hasNext()) {
+ * if (it.next() == null) it.remove();
+ * }
+ * }
+ * };
+ * FastMap<Person, String> names = ...
+ * names.values().update(removeNull); // Remove all entries with null values.
+ * names.atomic().values().update(removeNull); // Same but performed atomically.
+ * names.parallel().values().update(removeNull); // Same but performed in parallel.
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle </a>
+ * @version 6.0, July 21, 2013
+ */
+@Realtime
+public class FastMap<K, V> implements Map<K, V>, ConcurrentMap<K, V>,
+ Serializable {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Holds the actual map service implementation.
+ */
+ private final MapService<K, V> service;
+
+ /**
+ * Creates an empty fast map.
+ */
+ public FastMap() {
+ this(Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty fast map using the specified comparator for keys
+ * equality.
+ */
+ public FastMap(Equality<? super K> keyEquality) {
+ this(keyEquality, Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty fast map using the specified comparators for keys
+ * equality and values equality.
+ */
+ public FastMap(Equality<? super K> keyEquality,
+ Equality<? super V> valueEquality) {
+ service = new FastMapImpl<K, V>(keyEquality, valueEquality);
+ }
+
+ /**
+ * Creates a map backed up by the specified service implementation.
+ */
+ protected FastMap(MapService<K, V> service) {
+ this.service = service;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ /**
+ * Returns an atomic view over this map. All operations that write
+ * or access multiple elements in the map (such as putAll(),
+ * keySet().retainAll(), ...) are atomic.
+ * Iterators on atomic collections are <b>thread-safe</b>
+ * (no {@link ConcurrentModificationException} possible).
+ */
+ @Parallelizable(mutexFree = true, comment = "Except for write operations, all read operations are mutex-free.")
+ public FastMap<K, V> atomic() {
+ return new FastMap<K, V>(new AtomicMapImpl<K, V>(service));
+ }
+
+ /**
+ * Returns a thread-safe view over this map. The shared view
+ * allows for concurrent read as long as there is no writer.
+ * The default implementation is based on <a href=
+ * "http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock">
+ * readers-writers locks</a> giving priority to writers.
+ * Iterators on shared collections are <b>thread-safe</b>
+ * (no {@link ConcurrentModificationException} possible).
+ */
+ @Parallelizable(mutexFree = false, comment = "Use multiple-readers/single-writer lock.")
+ public FastMap<K, V> shared() {
+ return new FastMap<K, V>(new SharedMapImpl<K, V>(service));
+ }
+
+ /**
+ * Returns a parallel map. Parallel maps affect closure-based operations
+ * over the map or any of its views (entry, key, values, etc.), all others
+ * operations behaving the same. Parallel maps do not require this map
+ * to be thread-safe (internal synchronization).
+ *
+ * @see #perform(Consumer)
+ * @see #update(Consumer)
+ * @see FastCollection#parallel()
+ */
+ public FastMap<K, V> parallel() {
+ return new FastMap<K, V>(new ParallelMapImpl<K, V>(service));
+ }
+
+ /**
+ * Returns a sequential view of this collection. Using this view,
+ * all closure-based iterations are performed sequentially.
+ */
+ public FastMap<K, V> sequential() {
+ return new FastMap<K, V>(new SequentialMapImpl<K, V>(service));
+ }
+
+ /**
+ * Returns an unmodifiable view over this map. Any attempt to
+ * modify the map through this view will result into
+ * a {@link java.lang.UnsupportedOperationException} being raised.
+ */
+ public FastMap<K, V> unmodifiable() {
+ return new FastMap<K, V>(new UnmodifiableMapImpl<K, V>(service));
+ }
+
+ /**
+ * Returns a set view of the keys contained in this map.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports
+ * adding new keys for which the corresponding entry value
+ * is always {@code null}.
+ */
+ public FastSet<K> keySet() {
+ return new FastSet<K>(service.keySet());
+ }
+
+ /**
+ * Returns a collection view of the values contained in this map.
+ * The collection is backed by the map, so changes to the map are
+ * reflected in the collection, and vice-versa. The collection
+ * supports removing values (hence entries) but not adding new values.
+ */
+ public FastCollection<V> values() {
+ return new FastCollection<V>() {
+ private static final long serialVersionUID = 0x600L; // Version.
+ private final CollectionService<V> serviceValues = service.values();
+
+ @Override
+ protected CollectionService<V> service() {
+ return serviceValues;
+ }
+ };
+ }
+
+ /**
+ * Returns a set view of the mappings contained in
+ * this map. The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set
+ * support adding/removing entries. As far as the set is concerned,
+ * two entries are considered equals if they have the same keys regardless
+ * of their values.
+ */
+ public FastSet<Entry<K, V>> entrySet() {
+ return new FastSet<Entry<K, V>>(service.entrySet());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Closures operations.
+ //
+
+ /**
+ * Executes the specified read-only action on this map.
+ * That logic may be performed concurrently on sub-maps
+ * if this map is {@link #parallel() parallel}.
+ *
+ * @param action the read-only action.
+ * @throws UnsupportedOperationException if the action tries to update
+ * this map.
+ * @throws ClassCastException if the action type is not compatible with
+ * this map (e.g. action on sorted map and this is a hash map).
+ * @see #update(Consumer)
+ */
+ @Realtime(limit = LINEAR)
+ @SuppressWarnings("unchecked")
+ public void perform(Consumer<? extends Map<K, V>> action) {
+ service().perform((Consumer<MapService<K, V>>) action, service());
+ }
+
+ /**
+ * Executes the specified update action on this map.
+ * That logic may be performed concurrently on sub-maps
+ * if this map is {@link #parallel() parallel}.
+ * For {@link #atomic() atomic} maps the update is atomic (either concurrent
+ * readers see the full result of the action or nothing).
+ *
+ * @param action the update action.
+ * @throws ClassCastException if the action type is not compatible with
+ * this map (e.g. action on sorted map and this is a hash map).
+ * @see #perform(Consumer)
+ */
+ @Realtime(limit = LINEAR)
+ @SuppressWarnings("unchecked")
+ public void update(Consumer<? extends Map<K, V>> action) {
+ service().update((Consumer<MapService<K, V>>) action, service());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Map Interface.
+ //
+
+ /** Returns the number of entries/keys/values in this map. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public int size() {
+ return service.size();
+ }
+
+ /** Indicates if this map is empty */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean isEmpty() {
+ return service.isEmpty();
+ }
+
+ /** Indicates if this map contains the specified key. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean containsKey(Object key) {
+ return service.containsKey(key);
+ }
+
+ /** Indicates if this map contains the specified value. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public boolean containsValue(Object value) {
+ return service.containsValue(value);
+ }
+
+ /** Returns the value for the specified key. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public V get(Object key) {
+ return service.get(key);
+ }
+
+ /** Associates the specified value with the specified key. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public V put(K key, V value) {
+ return service.put(key, value);
+ }
+
+ /** Adds the specified map entries to this map. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public void putAll(Map<? extends K, ? extends V> map) {
+ service.putAll(map);
+ }
+
+ /** Removes the entry for the specified key. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public V remove(Object key) {
+ return service.remove(key);
+ }
+
+ /** Removes all this map's entries. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public void clear() {
+ service.clear();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // ConcurrentMap Interface.
+ //
+
+ /** Associates the specified value with the specified key only if the
+ * specified key has no current mapping. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public V putIfAbsent(K key, V value) {
+ return service.putIfAbsent(key, value);
+ }
+
+ /** Removes the entry for a key only if currently mapped to a given value. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean remove(Object key, Object value) {
+ return service.remove(key, value);
+ }
+
+ /** Replaces the entry for a key only if currently mapped to a given value. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean replace(K key, V oldValue, V newValue) {
+ return service.replace(key, oldValue, newValue);
+ }
+
+ /** Replaces the entry for a key only if currently mapped to some value. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public V replace(K key, V value) {
+ return service.replace(key, value);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ /**
+ * Returns this map with the specified map's entries added.
+ */
+ public FastMap<K, V> putAll(FastMap<? extends K, ? extends V> that) {
+ putAll((Map<? extends K, ? extends V>) that);
+ return this;
+ }
+
+ /**
+ * Returns an immutable reference over this map. The immutable
+ * value is an {@link #unmodifiable() unmodifiable} view of this map
+ * for which the caller guarantees that no change will ever be made
+ * (e.g. there is no reference left to the original map).
+ */
+ public <T extends Map<K, V>> Immutable<T> toImmutable() {
+ return new Immutable<T>() {
+ @SuppressWarnings("unchecked")
+ final T value = (T) unmodifiable();
+
+ @Override
+ public T value() {
+ return value;
+ }
+ };
+ }
+
+ /** Returns the string representation of this map entries. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public String toString() {
+ return TextContext.getFormat(FastCollection.class).format(entrySet());
+ }
+
+ /**
+ * Returns this map service implementation.
+ */
+ protected MapService<K, V> service() {
+ return service;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/FastSet.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastSet.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastSet.java
new file mode 100644
index 0000000..792173d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastSet.java
@@ -0,0 +1,146 @@
+/*
+ * 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.CONSTANT;
+
+import java.util.Set;
+
+import javolution.lang.Realtime;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.function.Predicate;
+import javolution.util.internal.map.FastMapImpl;
+import javolution.util.internal.set.AtomicSetImpl;
+import javolution.util.internal.set.FilteredSetImpl;
+import javolution.util.internal.set.SharedSetImpl;
+import javolution.util.internal.set.UnmodifiableSetImpl;
+import javolution.util.service.SetService;
+
+/**
+ * <p> A high-performance hash set with {@link Realtime real-time} behavior.</p>
+ *
+ * <p> The iteration order over the set elements is deterministic
+ * (unlike {@link java.util.HashSet}).It is either the insertion order (default)
+ * or the key order for the {@link FastSortedSet} subclass.
+ * This class permits {@code null} elements.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class FastSet<E> extends FastCollection<E> implements Set<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Holds the actual service implementation.
+ */
+ private final SetService<E> service;
+
+ /**
+ * Creates an empty set backed up by a {@link FastMap} and having
+ * the same real-time characteristics.
+ */
+ public FastSet() {
+ this(Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty set backed up by a {@link FastMap} and using the
+ * specified comparator for key equality.
+ */
+ public FastSet(Equality<? super E> comparator) {
+ service = new FastMapImpl<E, Void>(comparator, Equalities.IDENTITY)
+ .keySet();
+ }
+
+ /**
+ * Creates a fast set backed up by the specified service implementation.
+ */
+ protected FastSet(SetService<E> service) {
+ this.service = service;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ @Override
+ public FastSet<E> atomic() {
+ return new FastSet<E>(new AtomicSetImpl<E>(service()));
+ }
+
+ @Override
+ public FastSet<E> filtered(final Predicate<? super E> filter) {
+ return new FastSet<E>(new FilteredSetImpl<E>(service(), filter));
+ }
+
+ @Override
+ public FastSet<E> shared() {
+ return new FastSet<E>(new SharedSetImpl<E>(service()));
+ }
+
+ @Override
+ public FastSet<E> unmodifiable() {
+ return new FastSet<E>(new UnmodifiableSetImpl<E>(service()));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Set operations new annotations.
+ //
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean isEmpty() {
+ return size() == 0;
+ }
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public int size() {
+ return service.size();
+ }
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public void clear() {
+ service.clear();
+ }
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean contains(Object obj) {
+ return service.contains(obj);
+ }
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean remove(Object obj) {
+ return service.remove(obj);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ @Override
+ public FastSet<E> addAll(E... elements) {
+ return (FastSet<E>) super.addAll(elements);
+ }
+
+ @Override
+ public FastSet<E> addAll(FastCollection<? extends E> that) {
+ return (FastSet<E>) super.addAll(that);
+ }
+
+ @Override
+ protected SetService<E> service() {
+ return service;
+ }
+}
\ 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/util/FastSortedMap.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedMap.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedMap.java
new file mode 100644
index 0000000..c971a66
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedMap.java
@@ -0,0 +1,205 @@
+/*
+ * 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.LOG_N;
+
+import java.util.Comparator;
+import java.util.SortedMap;
+
+import javolution.lang.Realtime;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.internal.map.sorted.AtomicSortedMapImpl;
+import javolution.util.internal.map.sorted.FastSortedMapImpl;
+import javolution.util.internal.map.sorted.SharedSortedMapImpl;
+import javolution.util.internal.map.sorted.UnmodifiableSortedMapImpl;
+import javolution.util.service.SortedMapService;
+
+/**
+ * <p> A high-performance sorted map with {@link Realtime real-time} behavior.</p>
+ *
+ * <p> This map provides a total ordering based on the keys natural order or
+ * using custom {@link #FastSortedMap(Equality) comparators}.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class FastSortedMap<K, V> extends FastMap<K, V> implements
+ SortedMap<K, V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Creates an empty sorted map ordered on keys natural order.
+ */
+ public FastSortedMap() {
+ this(Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty sorted map ordered using the specified comparator
+ * for order.
+ */
+ public FastSortedMap(Equality<? super K> keyComparator) {
+ this(keyComparator, Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty sorted map ordered using the specified key comparator
+ * for order and value comparator for values equality.
+ */
+ public FastSortedMap(Equality<? super K> keyComparator,
+ Equality<? super V> valueComparator) {
+ super(new FastSortedMapImpl<K, V>(keyComparator, valueComparator));
+ }
+
+ /**
+ * Creates a sorted map backed up by the specified service implementation.
+ */
+ protected FastSortedMap(SortedMapService<K, V> service) {
+ super(service);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ @Override
+ public FastSortedMap<K, V> atomic() {
+ return new FastSortedMap<K, V>(new AtomicSortedMapImpl<K, V>(service()));
+ }
+
+ @Override
+ public FastSortedMap<K, V> shared() {
+ return new FastSortedMap<K, V>(new SharedSortedMapImpl<K, V>(service()));
+ }
+
+ @Override
+ public FastSortedMap<K, V> unmodifiable() {
+ return new FastSortedMap<K, V>(new UnmodifiableSortedMapImpl<K, V>(
+ service()));
+ }
+
+ @Override
+ public FastSortedSet<Entry<K, V>> entrySet() {
+ return new FastSortedSet<Entry<K, V>>(service().entrySet());
+ }
+
+ @Override
+ public FastSortedSet<K> keySet() {
+ return new FastSortedSet<K>(service().keySet());
+ }
+
+ /** Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive. */
+ @Override
+ public FastSortedMap<K, V> subMap(K fromKey, K toKey) {
+ return new FastSortedMap<K, V>(service().subMap(fromKey, toKey));
+ }
+
+ /** Returns a view of the portion of this map whose keys are strictly less than toKey. */
+ @Override
+ public FastSortedMap<K, V> headMap(K toKey) {
+ return new FastSortedMap<K, V>(service().subMap(firstKey(), toKey));
+ }
+
+ /** Returns a view of the portion of this map whose keys are greater than or equal to fromKey. */
+ @Override
+ public FastSortedMap<K, V> tailMap(K fromKey) {
+ return new FastSortedMap<K, V>(service().subMap(fromKey, lastKey()));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Change in time limit behavior.
+ //
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public boolean containsKey(Object key) {
+ return super.containsKey(key);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public V get(Object key) {
+ return super.get(key);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public V put(K key, V value) {
+ return super.put(key, value);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public V remove(Object key) {
+ return super.remove(key);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public V putIfAbsent(K key, V value) {
+ return super.putIfAbsent(key, value);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public boolean remove(Object key, Object value) {
+ return super.remove(key, value);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public boolean replace(K key, V oldValue, V newValue) {
+ return super.replace(key, oldValue, newValue);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public V replace(K key, V value) {
+ return super.replace(key, value);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // SortedMap Interface.
+ //
+
+ /** Returns the first (lowest) key currently in this map. */
+ @Override
+ public K firstKey() {
+ return service().firstKey();
+ }
+
+ /** Returns the last (highest) key currently in this map. */
+ @Override
+ public K lastKey() {
+ return service().lastKey();
+ }
+
+ /** Returns the comparator used to order the keys in this map (never null). */
+ @Override
+ public Comparator<? super K> comparator() {
+ return keySet().comparator();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ @Override
+ public FastSortedMap<K, V> putAll(FastMap<? extends K, ? extends V> that) {
+ return (FastSortedMap<K, V>) super.putAll(that);
+ }
+
+ @Override
+ protected SortedMapService<K, V> service() {
+ return (SortedMapService<K, V>) super.service();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedSet.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedSet.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedSet.java
new file mode 100644
index 0000000..1d446d7
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedSet.java
@@ -0,0 +1,153 @@
+/*
+ * 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.LOG_N;
+
+import java.util.SortedSet;
+
+import javolution.lang.Realtime;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.internal.map.sorted.FastSortedMapImpl;
+import javolution.util.internal.set.sorted.AtomicSortedSetImpl;
+import javolution.util.internal.set.sorted.SharedSortedSetImpl;
+import javolution.util.internal.set.sorted.UnmodifiableSortedSetImpl;
+import javolution.util.service.SortedSetService;
+
+/**
+ * <p> A high-performance sorted set with {@link Realtime real-time} behavior.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class FastSortedSet<E> extends FastSet<E> implements SortedSet<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Creates an empty sorted set ordered on elements natural order.
+ */
+ public FastSortedSet() {
+ this(Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty sorted set ordered using the specified comparator.
+ */
+ public FastSortedSet(Equality<? super E> comparator) {
+ super(new FastSortedMapImpl<E, Void>(comparator, Equalities.IDENTITY)
+ .keySet());
+ }
+
+ /**
+ * Creates a sorted set backed up by the specified service implementation.
+ */
+ protected FastSortedSet(SortedSetService<E> service) {
+ super(service);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ @Override
+ public FastSortedSet<E> atomic() {
+ return new FastSortedSet<E>(new AtomicSortedSetImpl<E>(service()));
+ }
+
+ @Override
+ public FastSortedSet<E> shared() {
+ return new FastSortedSet<E>(new SharedSortedSetImpl<E>(service()));
+ }
+
+ @Override
+ public FastSortedSet<E> unmodifiable() {
+ return new FastSortedSet<E>(new UnmodifiableSortedSetImpl<E>(service()));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Change in time limit behavior.
+ //
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public boolean add(E e) {
+ return super.add(e);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public boolean contains(Object obj) {
+ return super.contains(obj);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public boolean remove(Object obj) {
+ return super.remove(obj);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // SortedSet Interface.
+ //
+
+ /** Returns a view of the portion of this set whose elements range from fromElement, inclusive, to toElement, exclusive. */
+ @Override
+ @Realtime(limit = LOG_N)
+ public FastSortedSet<E> subSet(E fromElement, E toElement) {
+ return new FastSortedSet<E>(service().subSet(fromElement, toElement));
+ }
+
+ /** Returns a view of the portion of this set whose elements are strictly less than toElement. */
+ @Override
+ @Realtime(limit = LOG_N)
+ public FastSortedSet<E> headSet(E toElement) {
+ return subSet(first(), toElement);
+ }
+
+ /** Returns a view of the portion of this set whose elements are greater than or equal to fromElement. */
+ @Override
+ @Realtime(limit = LOG_N)
+ public FastSortedSet<E> tailSet(E fromElement) {
+ return subSet(fromElement, last());
+ }
+
+ /** Returns the first (lowest) element currently in this set. */
+ @Override
+ public E first() {
+ return service().first();
+ }
+
+ /** Returns the last (highest) element currently in this set. */
+ @Override
+ public E last() {
+ return service().last();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ @Override
+ public FastSortedSet<E> addAll(E... elements) {
+ return (FastSortedSet<E>) super.addAll(elements);
+ }
+
+ @Override
+ public FastSortedSet<E> addAll(FastCollection<? extends E> that) {
+ return (FastSortedSet<E>) super.addAll(that);
+ }
+
+ @Override
+ protected SortedSetService<E> service() {
+ return (SortedSetService<E>) super.service();
+ }
+
+}
\ 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/util/FastSortedTable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedTable.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedTable.java
new file mode 100644
index 0000000..9151026
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastSortedTable.java
@@ -0,0 +1,137 @@
+/*
+ * 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.LOG_N;
+import javolution.lang.Realtime;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.internal.table.sorted.AtomicSortedTableImpl;
+import javolution.util.internal.table.sorted.FastSortedTableImpl;
+import javolution.util.internal.table.sorted.SharedSortedTableImpl;
+import javolution.util.internal.table.sorted.UnmodifiableSortedTableImpl;
+import javolution.util.service.SortedTableService;
+
+/**
+ * <p> A high-performance sorted table with {@link Realtime real-time} behavior.
+ * Sorted table have significantly faster {@link #contains},
+ * {@link #indexOf} and {@link #remove} methods).</p>
+ *
+ * <p>This class is comparable to {@link FastSortedSet} in performance,
+ * but it allows for duplicate and implements the {@link java.util.List}
+ * interface.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class FastSortedTable<E> extends FastTable<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Creates an empty table sorted using its elements natural order.
+ */
+ public FastSortedTable() {
+ this(Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty table sorted using the specified element comparator.
+ */
+ public FastSortedTable(Equality<? super E> comparator) {
+ super(new FastSortedTableImpl<E>(comparator));
+ }
+
+ /**
+ * Creates a sorted table backed up by the specified service implementation.
+ */
+ protected FastSortedTable(SortedTableService<E> service) {
+ super(service);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ @Override
+ public FastSortedTable<E> atomic() {
+ return new FastSortedTable<E>(new AtomicSortedTableImpl<E>(service()));
+ }
+
+ @Override
+ public FastSortedTable<E> shared() {
+ return new FastSortedTable<E>(new SharedSortedTableImpl<E>(service()));
+ }
+
+ @Override
+ public FastSortedTable<E> unmodifiable() {
+ return new FastSortedTable<E>(new UnmodifiableSortedTableImpl<E>(
+ service()));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Change in time limit behavior.
+ //
+
+ @Realtime(limit = LOG_N)
+ public boolean contains(Object obj) {
+ return service().contains(obj);
+ }
+
+ @Realtime(limit = LOG_N)
+ public boolean remove(Object obj) {
+ return service().remove(obj);
+ }
+
+ @Override
+ @Realtime(limit = LOG_N)
+ public int indexOf(final Object obj) {
+ return service().indexOf(obj);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ /**
+ * Adds the specified element only if not already present.
+ *
+ * @return {@code true} if the element has been added;
+ * {@code false} otherwise.
+ */
+ @Realtime(limit = LOG_N)
+ public boolean addIfAbsent(E element) {
+ return service().addIfAbsent(element);
+ }
+
+ /**
+ * Returns what would be the index of the specified element if it were
+ * to be added or the index of the specified element if already present.
+ */
+ @Realtime(limit = LOG_N)
+ public int positionOf(E element) {
+ return service().positionOf(element);
+ }
+
+ @Override
+ public FastSortedTable<E> addAll(E... elements) {
+ return (FastSortedTable<E>) super.addAll(elements);
+ }
+
+ @Override
+ public FastSortedTable<E> addAll(FastCollection<? extends E> that) {
+ return (FastSortedTable<E>) super.addAll(that);
+ }
+
+ @Override
+ protected SortedTableService<E> service() {
+ return (SortedTableService<E>) super.service();
+ }
+
+}
\ 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/util/FastTable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/FastTable.java b/commons/marmotta-commons/src/ext/java/javolution/util/FastTable.java
new file mode 100644
index 0000000..1e87fb8
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/FastTable.java
@@ -0,0 +1,453 @@
+/*
+ * 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.CONSTANT;
+import static javolution.lang.Realtime.Limit.LINEAR;
+import static javolution.lang.Realtime.Limit.LOG_N;
+import static javolution.lang.Realtime.Limit.N_LOG_N;
+import static javolution.lang.Realtime.Limit.N_SQUARE;
+
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.RandomAccess;
+
+import javolution.lang.Realtime;
+import javolution.util.function.Consumer;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.internal.table.AtomicTableImpl;
+import javolution.util.internal.table.FastTableImpl;
+import javolution.util.internal.table.QuickSort;
+import javolution.util.internal.table.ReversedTableImpl;
+import javolution.util.internal.table.SharedTableImpl;
+import javolution.util.internal.table.SubTableImpl;
+import javolution.util.internal.table.UnmodifiableTableImpl;
+import javolution.util.service.TableService;
+
+/**
+ * <p> A high-performance table (fractal-based) with {@link Realtime real-time}
+ * behavior.</p>
+ *
+ * <p> The fractal-based implementation ensures that add/insertion/deletion operations
+ * <b>worst</b> execution time is always in less than <i><b>O(log(size))</b></i>.
+ * For comparison {@code ArrayList.add} is in <i><b>O(size)</b></i> due to resize. </p>
+ *
+ * <a href="doc-files/FastTable-WCET.png">
+ * <img src="doc-files/FastTable-WCET.png" alt="Worst Case Execution Time" height="210" width="306" />
+ * </a>
+ *
+ * <p> Instances of this class can advantageously replace {@link java.util.ArrayList ArrayList},
+ * {@link java.util.LinkedList LinkedList} or {@link java.util.ArrayDeque ArrayDeque}
+ * in terms of adaptability, space or performance.
+ * Fast tables can be concurrently iterated / modified using their {@link #shared() shared}/{@link #atomic() atomic}
+ * views. They inherit all the fast collection views and support the {@link #subTable subTable} view over a portion of the table.
+ * [code]
+ * FastTable<String> names = new FastTable<String>().addAll("John Deuff", "Otto Graf", "Sim Kamil");
+ * names.sort(Equalities.LEXICAL_CASE_INSENSITIVE); // Sorts the names in place (different from sorted() which returns a sorted view).
+ * names.subTable(0, names.size() / 2).clear(); // Removes the first half of the table (see java.util.List.subList specification).
+ * names.filtered(str -> str.startsWith("A")).clear(); // Removes all the names starting with "A" (Java 8 notation).
+ * names.filtered(str -> str.startsWith("A")).parallel().clear(); // Same as above but performed concurrently.
+ * [/code]</p>
+ *
+ * <p> As for any {@link FastCollection fast collection}, iterations can be
+ * performed using closures.
+ * [code]
+ * FastTable<Person> persons = ...
+ * Person findWithName(final String name) {
+ * return persons.filtered(new Predicate<Person>() {
+ * public boolean test(Person person) {
+ * return (person.getName().equals(name));
+ * }
+ * }).any(Person.class);
+ * }[/code]</p>
+ *
+ * <p> The notation is shorter with Java 8.
+ * [code]
+ * Person findWithName(String name) {
+ * return persons.filtered(person -> person.getName().equals(name)).any(Person.class);
+ * }[/code]</p>
+ *
+ * <p> FastTable iteration order is the {@link #add insertion} order; specialization may
+ * have a different order, for example the iteration order of {@link FastSortedTable}
+ * is based on the table sorting order.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class FastTable<E> extends FastCollection<E> implements List<E>,
+ Deque<E>, RandomAccess {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * Holds the actual service implementation.
+ */
+ private final TableService<E> service;
+
+ /**
+ * Creates an empty table whose capacity increments/decrements smoothly
+ * without large resize operations to best fit the table current size.
+ */
+ public FastTable() {
+ this(Equalities.STANDARD);
+ }
+
+ /**
+ * Creates an empty table using the specified comparator for element
+ * equality.
+ */
+ public FastTable(Equality<? super E> comparator) {
+ service = new FastTableImpl<E>(comparator);
+ }
+
+ /**
+ * Creates a fast table backed up by the specified service implementation.
+ */
+ protected FastTable(TableService<E> service) {
+ this.service = service;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Views.
+ //
+
+ @Override
+ public FastTable<E> atomic() {
+ return new FastTable<E>(new AtomicTableImpl<E>(service));
+ }
+
+ @Override
+ public FastTable<E> reversed() {
+ return new FastTable<E>(new ReversedTableImpl<E>(service));
+ }
+
+ @Override
+ public FastTable<E> shared() {
+ return new FastTable<E>(new SharedTableImpl<E>(service));
+ }
+
+ @Override
+ public FastTable<E> unmodifiable() {
+ return new FastTable<E>(new UnmodifiableTableImpl<E>(service));
+ }
+
+ /**
+ * Returns a view over a portion of the table (equivalent to
+ * {@link java.util.List#subList(int, int)}).
+ */
+ public FastTable<E> subTable(int fromIndex, int toIndex) {
+ return new FastTable<E>(
+ new SubTableImpl<E>(service, fromIndex, toIndex));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Change in time limit behavior.
+ //
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean isEmpty() {
+ return service.isEmpty();
+ }
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public int size() {
+ return service.size();
+ }
+
+ @Override
+ @Realtime(limit = CONSTANT)
+ public void clear() {
+ service.clear();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // List Interface.
+ //
+
+ /** Inserts the specified element at the specified position in this table. */
+ @Override
+ @Realtime(limit = LOG_N)
+ public void add(int index, E element) {
+ service.add(index, element);
+ }
+
+ /** Inserts all of the elements in the specified collection into this table
+ * at the specified position. */
+ @Override
+ @Realtime(limit = N_LOG_N)
+ public boolean addAll(final int index, Collection<? extends E> elements) {
+ return service.addAll(index, elements);
+ }
+
+ /** Removes the element at the specified position in this table. */
+ @Override
+ @Realtime(limit = LOG_N)
+ public E remove(int index) {
+ return service.remove(index);
+ }
+
+ /** Returns the element at the specified position in this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E get(int index) {
+ return service.get(index);
+ }
+
+ /** Replaces the element at the specified position in this table with the specified element. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E set(int index, E element) {
+ return service.set(index, element);
+ }
+
+ /** Returns the index of the first occurrence of the specified element in this table,
+ * or -1 if this table does not contain the element. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public int indexOf(Object element) {
+ return service.indexOf(element);
+ }
+
+ /** Returns the index of the last occurrence of the specified element in this table,
+ * or -1 if this table does not contain the element. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public int lastIndexOf(final Object element) {
+ return service.lastIndexOf(element);
+ }
+
+ /** Returns a list iterator over the elements in this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public ListIterator<E> listIterator() {
+ return service.listIterator();
+ }
+
+ /** Returns a list iterator over the elements in this table, starting
+ * at the specified position in the table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public ListIterator<E> listIterator(int index) {
+ return service.listIterator(index);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Deque Interface.
+ //
+
+ /** Inserts the specified element at the front of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public void addFirst(E element) {
+ service.addFirst(element);
+ }
+
+ /** Inserts the specified element at the end of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public void addLast(E element) {
+ service.addLast(element);
+ }
+
+ /** Retrieves, but does not remove, the first element of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E getFirst() {
+ return service.getFirst();
+ }
+
+ /** Retrieves, but does not remove, the last element of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E getLast() {
+ return service.getLast();
+ }
+
+ /** Retrieves, but does not remove, the first element of this table,
+ * or returns null if this table is empty. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E peekFirst() {
+ return service.peekFirst();
+ }
+
+ /** Retrieves, but does not remove, the last element of this table,
+ * or returns null if this table is empty. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E peekLast() {
+ return service.peekLast();
+ }
+
+ /** Retrieves and removes the first element of this table,
+ * or returns null if this table is empty. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E pollFirst() {
+ return service.pollFirst();
+ }
+
+ /** . */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E pollLast() {
+ return service.pollLast();
+ }
+
+ /** Retrieves and removes the last element of this table,
+ * or returns null if this table is empty. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E removeFirst() {
+ return service.removeFirst();
+ }
+
+ /** Retrieves and removes the last element of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E removeLast() {
+ return service.removeLast();
+ }
+
+ /** Inserts the specified element at the front of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean offerFirst(E e) {
+ return service.offerFirst(e);
+ }
+
+ /** Inserts the specified element at the end of this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean offerLast(E e) {
+ return service.offerLast(e);
+ }
+
+ /** Removes the first occurrence of the specified element from this table. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public boolean removeFirstOccurrence(Object o) {
+ return service.removeFirstOccurrence(o);
+ }
+
+ /** Removes the last occurrence of the specified element from this table. */
+ @Override
+ @Realtime(limit = LINEAR)
+ public boolean removeLastOccurrence(Object o) {
+ return service.removeLastOccurrence(o);
+ }
+
+ /** Inserts the specified element into the queue represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public boolean offer(E e) {
+ return service.offer(e);
+ }
+
+ /** Retrieves and removes the head of the queue represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E remove() {
+ return service.remove();
+ }
+
+ /** Retrieves and removes the head of the queue represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E poll() {
+ return service.poll();
+ }
+
+ /** Retrieves, but does not remove, the head of the queue represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E element() {
+ return service.element();
+ }
+
+ /** Retrieves, but does not remove, the head of the queue represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E peek() {
+ return service.peek();
+ }
+
+ /** Pushes an element onto the stack represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public void push(E e) {
+ service.push(e);
+ }
+
+ /** Pops an element from the stack represented by this table. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public E pop() {
+ return service.pop();
+ }
+
+ /** Returns an iterator over the elements in this table in reverse sequential order. */
+ @Override
+ @Realtime(limit = CONSTANT)
+ public Iterator<E> descendingIterator() {
+ return service.descendingIterator();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //
+
+ /**
+ * Sorts this table in place (quick sort).
+ */
+ @Realtime(limit = N_SQUARE)
+ public void sort() {
+ update(new Consumer<TableService<E>>() {
+ @Override
+ public void accept(TableService<E> table) {
+ QuickSort<E> qs = new QuickSort<E>(table, table.comparator());
+ qs.sort();
+ }
+ });
+ }
+
+ @Override
+ @Realtime(limit = LINEAR)
+ public FastTable<E> addAll(E... elements) {
+ return (FastTable<E>) super.addAll(elements);
+ }
+
+ @Override
+ @Realtime(limit = LINEAR)
+ public FastTable<E> addAll(FastCollection<? extends E> that) {
+ return (FastTable<E>) super.addAll(that);
+ }
+
+ /**
+ * Replaced by {@link #subTable(int, int)}. The term "List" for an
+ * interface with random access is disturbing !
+ */
+ @Override
+ @Deprecated
+ public FastTable<E> subList(int fromIndex, int toIndex) {
+ return subTable(fromIndex, toIndex);
+ }
+
+ @Override
+ protected TableService<E> service() {
+ return service;
+ }
+
+}
\ No newline at end of file
[02/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReader.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReader.java
new file mode 100644
index 0000000..31cf51b
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReader.java
@@ -0,0 +1,346 @@
+/*
+ * 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.xml.sax;
+
+import java.io.IOException;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * SAX2-like interface for reading an XML document using callbacks.
+ *
+ * @author David Megginson
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2005
+ * @see <a href="http://www.saxproject.org"> SAX -- Simple API for XML</a>
+ */
+public interface XMLReader {
+
+ /**
+ * Look up the value of a feature flag.
+ *
+ * <p>The feature name is any fully-qualified URI. It is
+ * possible for an XMLReader to recognize a feature name but
+ * temporarily be unable to return its value.
+ * Some feature values may be available only in specific
+ * contexts, such as before, during, or after a parse.
+ * Also, some feature values may not be programmatically accessible.
+ * (In the case of an adapter for SAX1 {@link org.xml.sax.Parser}, there
+ * is no implementation-independent way to expose whether the underlying
+ * parser is performing validation, expanding external entities,
+ * and so forth.) </p>
+ *
+ * <p>All XMLReaders are required to recognize the
+ * http://xml.org/sax/features/namespaces and the
+ * http://xml.org/sax/features/namespace-prefixes feature names.</p>
+ *
+ * <p>Typical usage is something like this:</p>
+ *
+ * <pre>
+ * XMLReader r = new MySAXDriver();
+ *
+ * // try to activate validation
+ * try {
+ * r.setFeature("http://xml.org/sax/features/validation", true);
+ * } catch (SAXException e) {
+ * System.err.println("Cannot activate validation.");
+ * }
+ *
+ * // register event handlers
+ * r.setContentHandler(new MyContentHandler());
+ * r.setErrorHandler(new MyErrorHandler());
+ *
+ * // parse the first document
+ * try {
+ * r.parse("http://www.foo.com/mydoc.xml");
+ * } catch (IOException e) {
+ * System.err.println("I/O exception reading XML document");
+ * } catch (SAXException e) {
+ * System.err.println("XML exception reading document.");
+ * }
+ * </pre>
+ *
+ * <p>Implementors are free (and encouraged) to invent their own features,
+ * using names built on their own URIs.</p>
+ *
+ * @param name The feature name, which is a fully-qualified URI.
+ * @return The current value of the feature (true or false).
+ * @exception org.xml.sax.SAXNotRecognizedException If the feature
+ * value can't be assigned or retrieved.
+ * @exception org.xml.sax.SAXNotSupportedException When the
+ * XMLReader recognizes the feature name but
+ * cannot determine its value at this time.
+ * @see #setFeature
+ */
+ public boolean getFeature(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException;
+
+ /**
+ * Set the value of a feature flag.
+ *
+ * <p>The feature name is any fully-qualified URI. It is
+ * possible for an XMLReader to expose a feature value but
+ * to be unable to change the current value.
+ * Some feature values may be immutable or mutable only
+ * in specific contexts, such as before, during, or after
+ * a parse.</p>
+ *
+ * <p>All XMLReaders are required to support setting
+ * http://xml.org/sax/features/namespaces to true and
+ * http://xml.org/sax/features/namespace-prefixes to false.</p>
+ *
+ * @param name The feature name, which is a fully-qualified URI.
+ * @param value The requested value of the feature (true or false).
+ * @exception org.xml.sax.SAXNotRecognizedException If the feature
+ * value can't be assigned or retrieved.
+ * @exception org.xml.sax.SAXNotSupportedException When the
+ * XMLReader recognizes the feature name but
+ * cannot set the requested value.
+ * @see #getFeature
+ */
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException;
+
+ /**
+ * Look up the value of a property.
+ *
+ * <p>The property name is any fully-qualified URI. It is
+ * possible for an XMLReader to recognize a property name but
+ * temporarily be unable to return its value.
+ * Some property values may be available only in specific
+ * contexts, such as before, during, or after a parse.</p>
+ *
+ * <p>XMLReaders are not required to recognize any specific
+ * property names, though an initial core set is documented for
+ * SAX2.</p>
+ *
+ * <p>Implementors are free (and encouraged) to invent their own properties,
+ * using names built on their own URIs.</p>
+ *
+ * @param name The property name, which is a fully-qualified URI.
+ * @return The current value of the property.
+ * @exception org.xml.sax.SAXNotRecognizedException If the property
+ * value can't be assigned or retrieved.
+ * @exception org.xml.sax.SAXNotSupportedException When the
+ * XMLReader recognizes the property name but
+ * cannot determine its value at this time.
+ * @see #setProperty
+ */
+ public Object getProperty(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException;
+
+ /**
+ * Set the value of a property.
+ *
+ * <p>The property name is any fully-qualified URI. It is
+ * possible for an XMLReader to recognize a property name but
+ * to be unable to change the current value.
+ * Some property values may be immutable or mutable only
+ * in specific contexts, such as before, during, or after
+ * a parse.</p>
+ *
+ * <p>XMLReaders are not required to recognize setting
+ * any specific property names, though a core set is defined by
+ * SAX2.</p>
+ *
+ * <p>This method is also the standard mechanism for setting
+ * extended handlers.</p>
+ *
+ * @param name The property name, which is a fully-qualified URI.
+ * @param value The requested value for the property.
+ * @exception org.xml.sax.SAXNotRecognizedException If the property
+ * value can't be assigned or retrieved.
+ * @exception org.xml.sax.SAXNotSupportedException When the
+ * XMLReader recognizes the property name but
+ * cannot set the requested value.
+ */
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException;
+
+ ////////////////////////////////////////////////////////////////////
+ // Event handlers.
+ ////////////////////////////////////////////////////////////////////
+
+ /**
+ * Allow an application to register an entity resolver.
+ *
+ * <p>If the application does not register an entity resolver,
+ * the XMLReader will perform its own default resolution.</p>
+ *
+ * <p>Applications may register a new or different resolver in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * resolver immediately.</p>
+ *
+ * @param resolver The entity resolver.
+ * @see #getEntityResolver
+ */
+ public void setEntityResolver(EntityResolver resolver);
+
+ /**
+ * Return the current entity resolver.
+ *
+ * @return The current entity resolver, or null if none
+ * has been registered.
+ * @see #setEntityResolver
+ */
+ public EntityResolver getEntityResolver();
+
+ /**
+ * Allow an application to register a DTD event handler.
+ *
+ * <p>If the application does not register a DTD handler, all DTD
+ * events reported by the SAX parser will be silently ignored.</p>
+ *
+ * <p>Applications may register a new or different handler in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * handler immediately.</p>
+ *
+ * @param handler The DTD handler.
+ * @see #getDTDHandler
+ */
+ public void setDTDHandler(DTDHandler handler);
+
+ /**
+ * Return the current DTD handler.
+ *
+ * @return The current DTD handler, or null if none
+ * has been registered.
+ * @see #setDTDHandler
+ */
+ public DTDHandler getDTDHandler();
+
+ /**
+ * Allow an application to register a content event handler.
+ *
+ * <p>If the application does not register a content handler, all
+ * content events reported by the SAX parser will be silently
+ * ignored.</p>
+ *
+ * <p>Applications may register a new or different handler in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * handler immediately.</p>
+ *
+ * @param handler The content handler.
+ * @see #getContentHandler
+ */
+ public void setContentHandler(ContentHandler handler);
+
+ /**
+ * Return the current content handler.
+ *
+ * @return The current content handler, or null if none
+ * has been registered.
+ * @see #setContentHandler
+ */
+ public ContentHandler getContentHandler();
+
+ /**
+ * Allow an application to register an error event handler.
+ *
+ * <p>If the application does not register an error handler, all
+ * error events reported by the SAX parser will be silently
+ * ignored; however, normal processing may not continue. It is
+ * highly recommended that all SAX applications implement an
+ * error handler to avoid unexpected bugs.</p>
+ *
+ * <p>Applications may register a new or different handler in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * handler immediately.</p>
+ *
+ * @param handler The error handler.
+ * @see #getErrorHandler
+ */
+ public void setErrorHandler(ErrorHandler handler);
+
+ /**
+ * Return the current error handler.
+ *
+ * @return The current error handler, or null if none
+ * has been registered.
+ * @see #setErrorHandler
+ */
+ public ErrorHandler getErrorHandler();
+
+ ////////////////////////////////////////////////////////////////////
+ // Parsing.
+ ////////////////////////////////////////////////////////////////////
+
+ /**
+ * Parse an XML document.
+ *
+ * <p>The application can use this method to instruct the XML
+ * reader to begin parsing an XML document from any valid input
+ * source (a character stream, a byte stream, or a URI).</p>
+ *
+ * <p>Applications may not invoke this method while a parse is in
+ * progress (they should create a new XMLReader instead for each
+ * nested XML document). Once a parse is complete, an
+ * application may reuse the same XMLReader object, possibly with a
+ * different input source.
+ * Configuration of the XMLReader object (such as handler bindings and
+ * values established for feature flags and properties) is unchanged
+ * by completion of a parse, unless the definition of that aspect of
+ * the configuration explicitly specifies other behavior.
+ * (For example, feature flags or properties exposing
+ * characteristics of the document being parsed.)
+ * </p>
+ *
+ * <p>During the parse, the XMLReader will provide information
+ * about the XML document through the registered event
+ * handlers.</p>
+ *
+ * <p>This method is synchronous: it will not return until parsing
+ * has ended. If a client application wants to terminate
+ * parsing early, it should throw an exception.</p>
+ *
+ * @param input The input source for the top-level of the
+ * XML document.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ * @exception j2me.io.IOException An IO exception from the parser,
+ * possibly from a byte stream or character stream
+ * supplied by the application.
+ * @see org.xml.sax.InputSource
+ * @see #setEntityResolver
+ * @see #setDTDHandler
+ * @see #setContentHandler
+ * @see #setErrorHandler
+ */
+ public void parse(InputSource input) throws IOException, SAXException;
+
+ /**
+ * Parse an XML document from a system identifier (URI).
+ *
+ * <p>This method is a shortcut for the common case of reading a
+ * document from a system identifier. It is the exact
+ * equivalent of the following:</p>
+ *
+ * <pre>
+ * parse(new InputSource(systemId));
+ * </pre>
+ *
+ * <p>If the system identifier is a URL, it must be fully resolved
+ * by the application before it is passed to the parser.</p>
+ *
+ * @param systemId The system identifier (URI).
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ * @exception j2me.io.IOException An IO exception from the parser,
+ * possibly from a byte stream or character stream
+ * supplied by the application.
+ * @see #parse(org.xml.sax.InputSource)
+ */
+ public void parse(String systemId) throws IOException, SAXException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReaderImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReaderImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReaderImpl.java
new file mode 100644
index 0000000..12cdf26
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/XMLReaderImpl.java
@@ -0,0 +1,363 @@
+/*
+ * 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.xml.sax;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import javolution.text.CharArray;
+import javolution.xml.internal.stream.XMLStreamReaderImpl;
+import javolution.xml.stream.XMLStreamConstants;
+import javolution.xml.stream.XMLStreamException;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * <p> This class provides a real-time SAX2-like XML parser; this parser is
+ * <i>extremely</i> fast and <b>does not create temporary objects</b>
+ * (no garbage generated and no GC interruption).</p>
+ *
+ * <p> The parser is implemented as a SAX2 wrapper around
+ * {@link XMLStreamReaderImpl} and share the same characteristics.</p>
+ *
+ * <p><i> Note: This parser is a <b>SAX2-like</b> parser with the
+ * <code>java.lang.String</code> type replaced by
+ * {@link CharArray}/{@link CharSequence} in the {@link ContentHandler},
+ * {@link Attributes} interfaces and {@link DefaultHandler} base class.
+ * If a standard SAX2 or JAXP parser is required, you may consider using
+ * the wrapping class {@link SAX2ReaderImpl}. Fast but not as fast as
+ * <code>java.lang.String</code> instances are dynamically allocated
+ * while parsing.</i></p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2006
+ */
+public class XMLReaderImpl implements XMLReader {
+
+ /**
+ * Holds the default handler instance.
+ */
+ private static DefaultHandler DEFAULT_HANDLER = new DefaultHandler();
+
+ /**
+ * Holds the content handler.
+ */
+ private ContentHandler _contentHandler;
+
+ /**
+ * Holds the error handler.
+ */
+ private ErrorHandler _errorHandler;
+
+ /**
+ * Holds reusable StAX reader.
+ */
+ private final XMLStreamReaderImpl _xmlReader = new XMLStreamReaderImpl();
+
+ /**
+ * Default constructor.
+ */
+ public XMLReaderImpl() {
+ // Sets default handlers.
+ setContentHandler(DEFAULT_HANDLER);
+ setErrorHandler(DEFAULT_HANDLER);
+ }
+
+ /**
+ * Parses an XML document from the specified input stream
+ * (encoding retrieved from input source and the XML prolog if any).
+ *
+ * @param in the input stream with unknown encoding.
+ * @throws org.xml.sax.SAXException any SAX exception, possibly
+ * wrapping another exception.
+ * @throws IOException an IO exception from the parser,
+ * possibly from a byte stream or character stream
+ * supplied by the application.
+ */
+ public void parse(InputStream in) throws IOException, SAXException {
+ try {
+ _xmlReader.setInput(in);
+ parseAll();
+ } catch (XMLStreamException e) {
+ if (e.getNestedException() instanceof IOException)
+ throw (IOException) e.getNestedException();
+ throw new SAXException(e.getMessage());
+ } finally {
+ _xmlReader.reset();
+ }
+ }
+
+ /**
+ * Parses an XML document from the specified input stream and encoding.
+ *
+ * @param in the input stream.
+ * @param encoding the input stream encoding.
+ * @throws org.xml.sax.SAXException any SAX exception, possibly
+ * wrapping another exception.
+ * @throws IOException an IO exception from the parser,
+ * possibly from a byte stream or character stream
+ * supplied by the application.
+ */
+ public void parse(InputStream in, String encoding) throws IOException,
+ SAXException {
+ try {
+ _xmlReader.setInput(in, encoding);
+ parseAll();
+ } catch (XMLStreamException e) {
+ if (e.getNestedException() instanceof IOException)
+ throw (IOException) e.getNestedException();
+ throw new SAXException(e.getMessage());
+ } finally {
+ _xmlReader.reset();
+ }
+ }
+
+ /**
+ * Parses an XML document using the specified reader.
+ *
+ * @param reader the document reader.
+ * @throws SAXException any SAX exception, possibly wrapping another
+ * exception.
+ * @throws IOException an IO exception from the parser, possibly from
+ * a byte stream or character stream supplied by the application.
+ * @see javolution.io.UTF8StreamReader
+ * @see javolution.io.UTF8ByteBufferReader
+ * @see javolution.io.CharSequenceReader
+ */
+ public void parse(Reader reader) throws IOException, SAXException {
+ try {
+ _xmlReader.setInput(reader);
+ parseAll();
+ } catch (XMLStreamException e) {
+ if (e.getNestedException() instanceof IOException)
+ throw (IOException) e.getNestedException();
+ throw new SAXException(e.getMessage());
+ } finally {
+ _xmlReader.reset();
+ }
+ }
+
+ // Implements XMLReader interface.
+ public void parse(InputSource input) throws IOException, SAXException {
+ Reader reader = input.getCharacterStream();
+ if (reader != null) {
+ parse(reader);
+ } else {
+ InputStream inStream = input.getByteStream();
+ if (inStream != null) {
+ parse(inStream, input.getEncoding());
+ } else {
+ parse(input.getSystemId());
+ }
+ }
+ }
+
+ // Implements XMLReader interface.
+ public void parse(String systemId) throws IOException, SAXException {
+ InputStream inStream;
+ try {
+ URL url = new URL(systemId);
+ inStream = url.openStream();
+ } catch (Exception urlException) { // Try as filename.
+ try {
+ inStream = new FileInputStream(systemId);
+ } catch (Exception fileException) {
+ throw new UnsupportedOperationException("Cannot parse "
+ + systemId);
+ }
+ }
+ parse(inStream);
+ }
+
+ // Implements XMLReader interface.
+ public void setContentHandler(ContentHandler handler) {
+ if (handler != null) {
+ _contentHandler = handler;
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ // Implements XMLReader interface.
+ public ContentHandler getContentHandler() {
+ return (_contentHandler == DEFAULT_HANDLER) ? null : _contentHandler;
+ }
+
+ // Implements XMLReader interface.
+ public void setErrorHandler(ErrorHandler handler) {
+ if (handler != null) {
+ _errorHandler = handler;
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ // Implements XMLReader interface.
+ public ErrorHandler getErrorHandler() {
+ return (_errorHandler == DEFAULT_HANDLER) ? null : _errorHandler;
+ }
+
+ // Implements XMLReader interface.
+ public boolean getFeature(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException {
+ if (name.equals("http://xml.org/sax/features/namespaces")) {
+ return true;
+ } else if (name
+ .equals("http://xml.org/sax/features/namespace-prefixes")) {
+ return true;
+ } else {
+ throw new SAXNotRecognizedException("Feature " + name
+ + " not recognized");
+ }
+ }
+
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name.equals("http://xml.org/sax/features/namespaces")
+ || name.equals("http://xml.org/sax/features/namespace-prefixes")) {
+ return; // Ignores, these features are always set.
+ } else {
+ throw new SAXNotRecognizedException("Feature " + name
+ + " not recognized");
+ }
+ }
+
+ public Object getProperty(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException {
+ throw new SAXNotRecognizedException("Property " + name
+ + " not recognized");
+ }
+
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ throw new SAXNotRecognizedException("Property " + name
+ + " not recognized");
+ }
+
+ public void setEntityResolver(EntityResolver resolver) {
+ _entityResolver = resolver;
+ }
+
+ private EntityResolver _entityResolver;
+
+ public EntityResolver getEntityResolver() {
+ return _entityResolver;
+ }
+
+ public void setDTDHandler(DTDHandler handler) {
+ _dtdHandler = handler;
+ }
+
+ private DTDHandler _dtdHandler;
+
+ public DTDHandler getDTDHandler() {
+ return _dtdHandler;
+ }
+
+ // Implements Reusable.
+ public void reset() {
+ setContentHandler(DEFAULT_HANDLER);
+ setErrorHandler(DEFAULT_HANDLER);
+ _xmlReader.reset();
+ }
+
+ /**
+ * Parses the whole document using the real-time pull parser.
+ *
+ * @throws SAXException any SAX exception, possibly wrapping another
+ * exception.
+ * @throws IOException an IO exception from the parser, possibly from
+ * a byte stream or character stream supplied by the application.
+ */
+ private void parseAll() throws XMLStreamException, SAXException {
+ int eventType = _xmlReader.getEventType();
+ if (eventType != XMLStreamConstants.START_DOCUMENT)
+ throw new SAXException("Currently parsing");
+ _contentHandler.startDocument();
+
+ boolean doContinue = true;
+ while (doContinue) {
+ CharArray uri, localName, qName, prefix, text;
+ switch (_xmlReader.next()) {
+ case XMLStreamConstants.START_ELEMENT:
+
+ // Start prefix mapping.
+ for (int i = 0, count = _xmlReader.getNamespaceCount(); i < count; i++) {
+ prefix = _xmlReader.getNamespacePrefix(i);
+ prefix = (prefix == null) ? NO_CHAR : prefix; // Default namespace is ""
+ uri = _xmlReader.getNamespaceURI(i);
+ _contentHandler.startPrefixMapping(prefix, uri);
+ }
+
+ // Start element.
+ uri = _xmlReader.getNamespaceURI();
+ uri = (uri == null) ? NO_CHAR : uri;
+ localName = _xmlReader.getLocalName();
+ qName = _xmlReader.getQName();
+ _contentHandler.startElement(uri, localName, qName,
+ _xmlReader.getAttributes());
+ break;
+
+ case XMLStreamConstants.END_ELEMENT:
+
+ // End element.
+ uri = _xmlReader.getNamespaceURI();
+ uri = (uri == null) ? NO_CHAR : uri;
+ localName = _xmlReader.getLocalName();
+ qName = _xmlReader.getQName();
+ _contentHandler.endElement(uri, localName, qName);
+
+ // End prefix mapping.
+ for (int i = 0, count = _xmlReader.getNamespaceCount(); i < count; i++) {
+ prefix = _xmlReader.getNamespacePrefix(i);
+ prefix = (prefix == null) ? NO_CHAR : prefix; // Default namespace is ""
+ _contentHandler.endPrefixMapping(prefix);
+ }
+ break;
+
+ case XMLStreamConstants.CDATA:
+ case XMLStreamConstants.CHARACTERS:
+ text = _xmlReader.getText();
+ _contentHandler.characters(text.array(), text.offset(),
+ text.length());
+ break;
+
+ case XMLStreamConstants.SPACE:
+ text = _xmlReader.getText();
+ _contentHandler.ignorableWhitespace(text.array(),
+ text.offset(), text.length());
+ break;
+
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ _contentHandler.processingInstruction(
+ _xmlReader.getPITarget(), _xmlReader.getPIData());
+ break;
+
+ case XMLStreamConstants.COMMENT:
+ // Ignores.
+ break;
+
+ case XMLStreamConstants.END_DOCUMENT:
+ doContinue = false;
+ _xmlReader.close();
+ break;
+
+ }
+ }
+ }
+
+ private static final CharArray NO_CHAR = new CharArray("");
+}
\ 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/xml/sax/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/sax/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/package-info.java
new file mode 100644
index 0000000..b418101
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/sax/package-info.java
@@ -0,0 +1,8 @@
+/**
+<p> {@link javolution.xml.sax.SAX2ReaderImpl SAX2} and high-performance
+ {@link javolution.xml.sax.XMLReaderImpl SAX2-Like} parsers. The later
+ being several times faster than conventional SAX2 parsers (by avoiding
+ <code>String</code> allocations while parsing).</p>
+ */
+package javolution.xml.sax;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/stream/Location.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/Location.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/Location.java
new file mode 100644
index 0000000..c89a30f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/Location.java
@@ -0,0 +1,56 @@
+/*
+ * 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.xml.stream;
+
+/**
+ * Provides information on the location of an event.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.8, May 22, 2006
+ */
+public interface Location {
+
+ /**
+ * Return the line number where the current event ends,
+ * returns -1 if none is available.
+ * @return the current line number
+ */
+ int getLineNumber();
+
+ /**
+ * Return the column number where the current event ends,
+ * returns -1 if none is available.
+ * @return the current column number
+ */
+ int getColumnNumber();
+
+ /**
+ * Return the byte or character offset into the input source this location
+ * is pointing to. If the input source is a file or a byte stream then
+ * this is the byte offset into that stream, but if the input source is
+ * a character media then the offset is the character offset.
+ * Returns -1 if there is no offset available.
+ *
+ * @return the current offset
+ */
+ int getCharacterOffset();
+
+ /**
+ * Returns the public ID of the XML
+ *
+ * @return the public ID, or null if not available
+ */
+ public String getPublicId();
+
+ /**
+ * Returns the system ID of the XML
+ * @return the system ID, or null if not available
+ */
+ public String getSystemId();
+}
\ 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/xml/stream/NamespaceContext.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/NamespaceContext.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/NamespaceContext.java
new file mode 100644
index 0000000..040e8f5
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/NamespaceContext.java
@@ -0,0 +1,55 @@
+/*
+ * 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.xml.stream;
+
+import java.util.Iterator;
+import javolution.text.CharArray;
+
+/**
+ * This interface represents the XML namespace context stack while parsing.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 12, 2006
+ */
+public interface NamespaceContext {
+
+ /**
+ * Returns the namespace URI bound to a prefix in the current scope
+ * or <code>null</code> if the prefix is unbound.
+ *
+ * @param prefix prefix to look up
+ * @return the namespace URI.
+ * @throws IllegalArgumentException if <code>prefix</code> is
+ * <code>null</code>
+ */
+ CharArray getNamespaceURI(CharSequence prefix);
+
+ /**
+ * Returns the prefix bound to the namespace URI in the current scope
+ * or <code>null</code> if the namespace URI is unbound.
+ *
+ * @param namespaceURI URI of the namespace to lookup.
+ * @return the prefix bound to the namespace URI.
+ * @throws IllegalArgumentException if <code>namespaceURI</code> is
+ * <code>null</code>
+ */
+ CharArray getPrefix(CharSequence namespaceURI);
+
+ /**
+ * Returns all prefixes bound to a namespace URI in the current scope
+ * (including predefined prefixes).
+ *
+ * @param namespaceURI URI of Namespace to lookup
+ * @return an <code>Iterator</code> over {@link CharArray} prefixes.
+ * @throws IllegalArgumentException if <code>namespaceURI</code> is
+ * <code>null</code>
+ */
+ Iterator<CharArray> getPrefixes(CharSequence namespaceURI);
+
+}
\ 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/xml/stream/XMLInputFactory.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLInputFactory.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLInputFactory.java
new file mode 100644
index 0000000..0ffd10c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLInputFactory.java
@@ -0,0 +1,150 @@
+/*
+ * 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.xml.stream;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+import javolution.lang.Parallelizable;
+
+/**
+ * <p> The OSGi factory service to create {@link XMLStreamReader} instances.
+ * For each bundle, a distinct factory instance is returned and can be
+ * individually configured (if not enough the factory can be
+ * {@link #clone cloned}).
+ * [code]
+ * import javolution.xml.stream.*;
+ * public class Activator implements BundleActivator {
+ * public void start(BundleContext bc) throws Exception {
+ *
+ * // Configures factory.
+ * ServiceTracker<XMLInputFactory, XMLInputFactory> tracker
+ * = new ServiceTracker<>(bc, XMLInputFactory.class, null);
+ * tracker.open();
+ * tracker.getService().setProperty(IS_COALESCING, true);
+ *
+ * // Instantiates a reader.
+ * String xml = "<test>This is a test</test>";
+ * CharSequenceReader in = new CharSequenceReader().setInput(xml);
+ * XMLStreamReader reader = tracker.getService().createXMLStreamReader(in);
+ *
+ * // Parses XML.
+ * while (reader.hasNext()) {
+ * int eventType = reader.next();
+ * if (eventType == XMLStreamConstants.CHARACTERS) {
+ * System.out.println(reader.getText());
+ * }
+ * }
+ *
+ * // Closes the reader which may be recycled back to the factory.
+ * reader.close();
+ * }
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+@Parallelizable(comment="Factory configuration should be performed sequentially.")
+public interface XMLInputFactory extends Cloneable {
+
+ /**
+ * The property that requires the parser to coalesce adjacent character data
+ * sections.
+ */
+ public static final String IS_COALESCING = "javolution.xml.stream.isCoalescing";
+
+ /**
+ * The property that requires the parser to validate the input data.
+ */
+ public static final String IS_VALIDATING = "javolution.xml.stream.isValidating";
+
+ /**
+ * Property used to specify additional entities to be recognized by the
+ * readers (type: <code>java.util.Map</code>, default: <code>null</code>).
+ * For example:[code]
+ * FastMap<String, String> HTML_ENTITIES = new FastMap<String, String>();
+ * HTML_ENTITIES.put("nbsp", " ");
+ * HTML_ENTITIES.put("copy", "©");
+ * HTML_ENTITIES.put("eacute", "é");
+ * ...
+ * XMLInputFactory factory = factoryRef.getService();
+ * factory.setProperty(ENTITIES, HTML_ENTITIES);
+ * [/code]
+ */
+ public static final String ENTITIES = "javolution.xml.stream.entities";
+
+ /**
+ * Returns a XML stream reader for the specified I/O reader.
+ *
+ * @param reader the XML data to read from.
+ * @throws XMLStreamException
+ */
+ XMLStreamReader createXMLStreamReader(Reader reader)
+ throws XMLStreamException;
+
+ /**
+ * Returns a XML stream reader for the specified input stream
+ * (encoding autodetected).
+ *
+ * @param stream the input stream to read from.
+ * @return a xml stream reader possibly recycled.
+ * @throws XMLStreamException
+ */
+ XMLStreamReader createXMLStreamReader(InputStream stream)
+ throws XMLStreamException;
+
+ /**
+ * Returns a XML stream reader for the specified input stream using the
+ * specified encoding.
+ *
+ * @param stream the input stream to read from.
+ * @param encoding the character encoding of the stream.
+ * @return a xml stream reader possibly recycled.
+ * @throws XMLStreamException
+ */
+ XMLStreamReader createXMLStreamReader(InputStream stream,
+ String encoding) throws XMLStreamException;
+
+ /**
+ * Allows the user to set specific feature/property on the underlying
+ * implementation. The underlying implementation is not required to support
+ * every setting of every property in the specification and may use
+ * <code>IllegalArgumentException</code> to signal that an unsupported
+ * property may not be set with the specified value.
+ *
+ * @param name the name of the property.
+ * @param value the value of the property
+ * @throws IllegalArgumentException if the property is not supported.
+ */
+ void setProperty(String name, Object value) throws IllegalArgumentException;
+
+ /**
+ * Gets the value of a feature/property from the underlying implementation.
+ *
+ * @param name the name of the property (may not be null).
+ * @return the value of the property.
+ * @throws IllegalArgumentException if the property is not supported.
+ */
+ Object getProperty(String name) throws IllegalArgumentException;
+
+ /**
+ * Queries the set of properties that this factory supports.
+ *
+ * @param name the name of the property.
+ * @return <code>true</code> if the property is supported;
+ * <code>false</code> otherwise.
+ */
+ boolean isPropertySupported(String name);
+
+ /**
+ * Returns a clone of this factory which can be independently configured.
+ */
+ XMLInputFactory clone();
+
+}
\ 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/xml/stream/XMLOutputFactory.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLOutputFactory.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLOutputFactory.java
new file mode 100644
index 0000000..8f93138
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLOutputFactory.java
@@ -0,0 +1,169 @@
+/*
+ * 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.xml.stream;
+
+import java.io.OutputStream;
+import java.io.Writer;
+
+import javolution.lang.Parallelizable;
+
+/**
+ * <p> The OSGi factory service to create {@link XMLStreamWriter} instances.
+ * For each bundle, a distinct factory instance is returned and can be
+ * individually configured (if not enough the factory can be
+ * {@link #clone cloned}).
+ * [code]
+ * import javolution.xml.stream.*;
+ * public class Activator implements BundleActivator {
+ * public void start(BundleContext bc) throws Exception {
+ *
+ * // Configures factory.
+ * ServiceTracker<XMLOutputFactory, XMLOutputFactory> tracker
+ * = new ServiceTracker<>(bc, XMLOutputFactory.class, null);
+ * tracker.open();
+ * tracker.getService().setProperty(XMLOutputFactory.INDENTATION, "/t"); // Use tab for indentations.
+ *
+ * // Instantiates a new writer.
+ * TextBuilder xml = new TextBuilder();
+ * AppendableWriter out = new AppendableWriter(xml);
+ * XMLStreamWriter writer = tracker.getService().createXMLStreamWriter(out);
+ *
+ * // Formats to XML.
+ * writer.writeStartDocument("1.0");
+ * writer.writeCharacters("\n");
+ * writer.writeStartElement("ns1", "sample", "http://www.e.com/ns1");
+ * writer.writeNamespace("ns1", "http://www.e.com/ns1");
+ * writer.writeEndElement();
+ * writer.writeEndDocument();
+ *
+ * // Closes the writer which may be recycled back to the factory.
+ * writer.close();
+ *
+ * // Displays the formatted output.
+ * System.out.println(xml);
+ * }
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+@Parallelizable(comment="Factory configuration should be performed sequentially.")
+public interface XMLOutputFactory extends Cloneable {
+
+ /**
+ * Property used to set prefix defaulting on the output side
+ * (type: <code>Boolean</code>, default: <code>FALSE</code>).
+ */
+ public static final String IS_REPAIRING_NAMESPACES = "javolution.xml.stream.isRepairingNamespaces";
+
+ /**
+ * Property used to specify the prefix to be appended by a trailing
+ * part (a sequence number) in order to make it unique to be usable as
+ * a temporary non-colliding prefix when repairing namespaces
+ * (type: <code>String</code>, default: <code>"ns"</code>).
+ */
+ public final static String REPAIRING_PREFIX = "javolution.xml.stream.repairingPrefix";
+
+ /**
+ * Property used to specify an indentation string; non-null indentation
+ * forces the writer to write elements into separate lines
+ * (type: <code>String</code>, default: <code>null</code>).
+ */
+ public static final String INDENTATION = "javolution.xml.stream.indentation";
+
+ /**
+ * Property used to specify the new line characters
+ * (type: <code>String</code>, default: <code>"\n"</code>).
+ */
+ public static final String LINE_SEPARATOR = "javolution.xml.stream.lineSeparator";
+
+ /**
+ * Property indicating if the stream writers are allowed to automatically
+ * output empty elements when a start element is immediately followed by
+ * matching end element
+ * (type: <code>Boolean</code>, default: <code>FALSE</code>).
+ */
+ public final static String AUTOMATIC_EMPTY_ELEMENTS = "javolution.xml.stream.automaticEmptyElements";
+
+ /**
+ * Property indicating if the stream writers are not allowed to use
+ * empty element tags
+ * (type: <code>Boolean</code>, default: <code>FALSE</code>).
+ * When set, this property forces the use of start/end element tag
+ * (e.g. i.e. "<empty />" replaced by "<empty></empty>"),
+ * This property takes precedence over {@link #AUTOMATIC_EMPTY_ELEMENTS}.
+ */
+ public final static String NO_EMPTY_ELEMENT_TAG = "javolution.xml.stream.noEmptyElementTag";
+
+ /**
+ * Returns a XML stream writer to the specified i/o writer.
+ *
+ * @param writer the writer to write to.
+ * @return a xml stream writer possibly recycled.
+ * @throws XMLStreamException
+ */
+ XMLStreamWriter createXMLStreamWriter(Writer writer)
+ throws XMLStreamException;
+
+ /**
+ * Returns a XML stream writer to the specified output stream (UTF-8
+ * encoding).
+ *
+ * @param stream the stream to write to.
+ * @return a xml stream writer possibly recycled.
+ * @throws XMLStreamException
+ */
+ XMLStreamWriter createXMLStreamWriter(OutputStream stream)
+ throws XMLStreamException;
+
+ /**
+ * Returns a XML stream writer to the specified output stream using the
+ * specified encoding.
+ *
+ * @param stream the stream to write to.
+ * @param encoding the encoding to use.
+ * @return a xml stream writer possibly recycled.
+ * @throws XMLStreamException
+ */
+ XMLStreamWriter createXMLStreamWriter(OutputStream stream, String encoding)
+ throws XMLStreamException;
+
+ /**
+ * Allows the user to set specific features/properties on the underlying
+ * implementation.
+ *
+ * @param name the name of the property.
+ * @param value the value of the property.
+ * @throws IllegalArgumentException if the property is not supported.
+ */
+ void setProperty(String name, Object value) throws IllegalArgumentException;
+
+ /**
+ * Gets a feature/property on the underlying implementation.
+ *
+ * @param name the name of the property
+ * @return the value of the property
+ * @throws IllegalArgumentException if the property is not supported.
+ */
+ Object getProperty(String name) throws IllegalArgumentException;
+
+ /**
+ * Queries the set of properties that this factory supports.
+ *
+ * @param name the name of the property (may not be null).
+ * @return <code>true</code> if the property is supported;
+ * <code>false</code> otherwise.
+ */
+ boolean isPropertySupported(String name);
+
+ /**
+ * Returns a clone of this factory which can be independently configured.
+ */
+ XMLOutputFactory clone();
+}
\ 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/xml/stream/XMLStreamConstants.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamConstants.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamConstants.java
new file mode 100644
index 0000000..aef6e60
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamConstants.java
@@ -0,0 +1,98 @@
+/*
+ * 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.xml.stream;
+
+/**
+ * This interface declares the constants used in this API. Numbers in the range
+ * 0 to 256 are reserved for the specification, user defined events must use
+ * event codes outside that range.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2006
+ */
+public interface XMLStreamConstants {
+
+ /**
+ * Indicates an event is a start element.
+ */
+ public static final int START_ELEMENT = 1;
+
+ /**
+ * Indicates an event is an end element.
+ */
+ public static final int END_ELEMENT = 2;
+
+ /**
+ * Indicates an event is a processing instruction.
+ */
+ public static final int PROCESSING_INSTRUCTION = 3;
+
+ /**
+ * Indicates an event is characters.
+ */
+ public static final int CHARACTERS = 4;
+
+ /**
+ * Indicates an event is a comment.
+ */
+ public static final int COMMENT = 5;
+
+ /**
+ * The characters are white space (see [XML], 2.10 "White Space Handling").
+ * Events are only reported as SPACE if they are ignorable white space.
+ * Otherwise they are reported as CHARACTERS.
+ */
+ public static final int SPACE = 6;
+
+ /**
+ * Indicates an event is a start document.
+ */
+ public static final int START_DOCUMENT = 7;
+
+ /**
+ * Indicates an event is an end document.
+ */
+ public static final int END_DOCUMENT = 8;
+
+ /**
+ * Indicates an event is an entity reference.
+ */
+ public static final int ENTITY_REFERENCE = 9;
+
+ /**
+ * Indicates an event is an attribute.
+ */
+ public static final int ATTRIBUTE = 10;
+
+ /**
+ * Indicates an event is a DTD.
+ */
+ public static final int DTD = 11;
+
+ /**
+ * Indicates an event is a CDATA section.
+ */
+ public static final int CDATA = 12;
+
+ /**
+ * Indicates the event is a namespace declaration.
+ */
+ public static final int NAMESPACE = 13;
+
+ /**
+ * Indicates a Notation.
+ */
+ public static final int NOTATION_DECLARATION = 14;
+
+ /**
+ * Indicates a Entity Declaration.
+ */
+ public static final int ENTITY_DECLARATION = 15;
+
+}
\ 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/xml/stream/XMLStreamException.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamException.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamException.java
new file mode 100644
index 0000000..fd449b6
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamException.java
@@ -0,0 +1,128 @@
+/*
+ * 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.xml.stream;
+
+/**
+ * This class represents the base exception for unexpected processing errors.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.8, May 22, 2006
+ */
+public class XMLStreamException extends Exception {
+
+ /**
+ * Holds the nested exception if any.
+ */
+ private Throwable _nested;
+
+ /**
+ * Holds the location.
+ */
+ private Location _location;
+
+ /**
+ * Default constructor
+ */
+ public XMLStreamException() {
+ super();
+ }
+
+ /**
+ * Constructs an exception with the assocated message.
+ *
+ * @param msg the message to report.
+ */
+ public XMLStreamException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs an exception with the assocated nested exception.
+ *
+ * @param nested the nested exception.
+ */
+ public XMLStreamException(Throwable nested) {
+ _nested = nested;
+ }
+
+ /**
+ * Constructs an exception with the assocated message and exception.
+ *
+ * @param msg the message to report.
+ * @param nested the nested exception.
+ */
+ public XMLStreamException(String msg, Throwable nested) {
+ super(msg);
+ _nested = nested;
+ }
+
+ /**
+ * Constructs an exception with the assocated message, exception and
+ * location.
+ *
+ * @param msg the message to report.
+ * @param location the location.
+ * @param nested the nested exception.
+ */
+ public XMLStreamException(String msg, Location location, Throwable nested) {
+ super(msg);
+ _nested = nested;
+ _location = location;
+ }
+
+ /**
+ * Constructs an exception with the assocated message, exception and
+ * location.
+ *
+ * @param msg the message to report
+ * @param location the location of the error
+ */
+ public XMLStreamException(String msg, Location location) {
+ super(msg);
+ _location = location;
+ }
+
+ /**
+ * Returns the nested exception.
+ *
+ * @return the nested exception
+ */
+ public Throwable getNestedException() {
+ return _nested;
+ }
+
+ /**
+ * Returns the location of the exception.
+ *
+ * @return the location of the exception or <code>null</code>
+ * if none is available
+ */
+ public Location getLocation() {
+ return _location;
+ }
+
+ /**
+ * Returns the textual representation of this exception.
+ *
+ * @return the string representation of the exception.
+ */
+ public String toString() {
+ String msg = super.toString();
+ if (_location != null) {
+ msg += " (at line " + _location.getLineNumber() + ", column "
+ + _location.getColumnNumber() + ")";
+ }
+ if (_nested != null) {
+ msg += " caused by " + _nested.toString();
+ }
+ return msg;
+ }
+
+ private static final long serialVersionUID = 1L;
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamReader.java b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamReader.java
new file mode 100644
index 0000000..fd407d6
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/stream/XMLStreamReader.java
@@ -0,0 +1,604 @@
+/*
+ * 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.xml.stream;
+
+import java.util.NoSuchElementException;
+
+import javolution.text.CharArray;
+
+/**
+ * <p> This interface is similar to
+ * <code>javax.xml.stream.XMLStreamReader</code>; but it does not forces
+ * dynamic allocation when parsing (its methods returns
+ * {@link CharArray CharArray} instances instead of {@link String}).</p>
+ *
+ * <p> Except for the speed (faster) and its real-time characteristics
+ * the usage/behavior is about the same as its StAX counterpart.</p>
+ *
+ * <p> The {@link CharArray CharArray} instances returned by this reader
+ * supports fast primitive conversions as illustrated below.
+ * [code]
+ * // Creates a new reader (potentially recycled).
+ * XMLInputFactory factory = OSGiServices.getXMLInputFactory();
+ * XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
+ *
+ * while (reader.getEventType() != XMLStreamConstants.END_DOCUMENT) {
+ * switch (reader.next()) {
+ * case XMLStreamConstants.START_ELEMENT:
+ * if (reader.getLocalName().equals("Time")) {
+ * // Reads primitive types (int) attributes directly (no memory allocation).
+ * time.hour = reader.getAttributeValue(null, "hour").toInt();
+ * time.minute = reader.getAttributeValue(null, "minute").toInt();
+ * time.second = reader.getAttributeValue(null, "second").toInt();
+ * }
+ * ...
+ * break;
+ * }
+ * }
+ * reader.close(); // Close the reader (does not close underlying input stream).
+ * [/code]
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0 December 12, 2012
+ */
+public interface XMLStreamReader extends XMLStreamConstants {
+
+ /**
+ * Gets the value of a feature/property from the underlying implementation
+ *
+ * @param name the name of the property.
+ * @return the value of the property.
+ */
+ Object getProperty(String name) throws IllegalArgumentException;
+
+ /**
+ * Gets next parsing event - contiguous character data is returned into a
+ * single chunk.
+ *
+ * By default entity references must be expanded and reported transparently
+ * to the application. An exception will be thrown if an entity reference
+ * cannot be expanded. If element content is empty (i.e. content is "") then
+ * no CHARACTERS event will be reported.
+ *
+ * <p>
+ * Given the following XML:<br>
+ * <foo><!--description-->content
+ * text<![CDATA[<greeting>Hello</greeting>]]>other content</foo><br>
+ * The behavior of calling next() when being on foo will be:<br>
+ * 1- the comment (COMMENT)<br>
+ * 2- then the characters section (CHARACTERS)<br>
+ * 3- then the CDATA section (another CHARACTERS)<br>
+ * 4- then the next characters section (another CHARACTERS)<br>
+ * 5- then the END_ELEMENT<br>
+ *
+ * <p>
+ * <b>NOTE:</b> empty element (such as <tag/>) will be reported with two
+ * separate events: START_ELEMENT, END_ELEMENT - This preserves parsing
+ * equivalency of empty element to <tag></tag>.
+ *
+ * This method will throw an IllegalStateException if it is called after
+ * hasNext() returns false.
+ *
+ * @return the integer code corresponding to the current parse event
+ * @throws NoSuchElementException if this is called when hasNext()
+ * returns false
+ * @throws XMLStreamException if there is an error processing the
+ * underlying XML source
+ */
+ int next() throws XMLStreamException;
+
+ /**
+ * Tests if the current event is of the given type and if the namespace and
+ * name match the current namespace and name of the current event. If the
+ * namespaceURI is null it is not checked for equality, if the localName is
+ * null it is not checked for equality.
+ *
+ * @param type the event type.
+ * @param namespaceURI the uri of the event, may be null.
+ * @param localName the localName of the event, may be null.
+ * @throws XMLStreamException if the required values are not matched.
+ */
+ void require(int type, CharSequence namespaceURI,
+ CharSequence localName) throws XMLStreamException;
+
+ /**
+ * Reads the content of a text-only element, an exception is thrown if this
+ * is not a text-only element. Regardless of the value of
+ * javax.xml.stream.isCoalescing this method always returns coalesced
+ * content. <br />
+ * Precondition: the current event is START_ELEMENT. <br />
+ * Postcondition: the current event is the corresponding END_ELEMENT.
+ *
+ * <br />
+ * The method does the following (implementations are free to optimized but
+ * must do equivalent processing):
+ *
+ * <pre>
+ * if (getEventType() != XMLStreamConstants.START_ELEMENT) {
+ * throw new XMLStreamException(
+ * "parser must be on START_ELEMENT to read next text", getLocation());
+ * }
+ * int eventType = next();
+ * StringBuffer content = new StringBuffer();
+ * while (eventType != XMLStreamConstants.END_ELEMENT) {
+ * if (eventType == XMLStreamConstants.CHARACTERS
+ * || eventType == XMLStreamConstants.CDATA
+ * || eventType == XMLStreamConstants.SPACE
+ * || eventType == XMLStreamConstants.ENTITY_REFERENCE) {
+ * buf.append(getText());
+ * } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
+ * || eventType == XMLStreamConstants.COMMENT) {
+ * // skipping
+ * } else if (eventType == XMLStreamConstants.END_DOCUMENT) {
+ * throw new XMLStreamException(
+ * "unexpected end of document when reading element text content",
+ * this);
+ * } else if (eventType == XMLStreamConstants.START_ELEMENT) {
+ * throw new XMLStreamException(
+ * "element text content may not contain START_ELEMENT",
+ * getLocation());
+ * } else {
+ * throw new XMLStreamException("Unexpected event type " + eventType,
+ * getLocation());
+ * }
+ * eventType = next();
+ * }
+ * return buf.toString();
+ * </pre>
+ *
+ * @throws XMLStreamException if the current event is not a START_ELEMENT
+ * or if a non text element is encountered.
+ */
+ CharArray getElementText() throws XMLStreamException;
+
+ /**
+ * Skips any white space (isWhiteSpace() returns true), COMMENT, or
+ * PROCESSING_INSTRUCTION, until a START_ELEMENT or END_ELEMENT is reached.
+ * If other than white space characters, COMMENT, PROCESSING_INSTRUCTION,
+ * START_ELEMENT, END_ELEMENT are encountered, an exception is thrown. This
+ * method should be used when processing element-only content seperated by
+ * white space.
+ *
+ * <br />
+ * Precondition: none <br />
+ * Postcondition: the current event is START_ELEMENT or END_ELEMENT and
+ * cursor may have moved over any whitespace event.
+ *
+ * <br />
+ * Essentially it does the following (implementations are free to optimized
+ * but must do equivalent processing):
+ *
+ * <pre>
+ * int eventType = next();
+ * while((eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace()) // skip whitespace
+ * || (eventType == XMLStreamConstants.CDATA && isWhiteSpace())
+ * // skip whitespace
+ * || eventType == XMLStreamConstants.SPACE
+ * || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
+ * || eventType == XMLStreamConstants.COMMENT
+ * ) {
+ * eventType = next();
+ * }
+ * if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
+ * throw new String XMLStreamException("expected start or end tag", getLocation());
+ * }
+ * return eventType;
+ * </pre>
+ *
+ * @return the event type of the element read (START_ELEMENT or END_ELEMENT)
+ * @throws XMLStreamException if the current event is not white space,
+ * PROCESSING_INSTRUCTION, START_ELEMENT or END_ELEMENT
+ * @throws NoSuchElementException if this is called when hasNext()
+ * returns false
+ */
+ int nextTag() throws XMLStreamException;
+
+ /**
+ * Returns true if there are more parsing events and false if there are no
+ * more events. This method will return false if the current state of the
+ * XMLStreamReader is END_DOCUMENT.
+ *
+ * @return true if there are more events, false otherwise.
+ * @throws XMLStreamException if there is a fatal error detecting the next
+ * state.
+ */
+ boolean hasNext() throws XMLStreamException;
+
+ /**
+ * Frees any resources associated with this Reader. This method does not
+ * close the underlying input source.
+ *
+ * @throws XMLStreamException if there are errors freeing associated
+ * resources
+ */
+ void close() throws XMLStreamException;
+
+ /**
+ * Returns the uri for the given prefix. The uri returned depends on the
+ * current state of the processor.
+ *
+ * <p>
+ * <strong>NOTE:</strong>The 'xml' prefix is bound as defined in <a
+ * href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a>
+ * specification to "http://www.w3.org/XML/1998/namespace".
+ *
+ * <p>
+ * <strong>NOTE:</strong> The 'xmlns' prefix must be resolved to following
+ * namespace <a
+ * href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a>
+ *
+ * @param prefix the prefix to lookup.
+ * @return the uri bound to the given prefix or <code>null</code> if it is
+ * not bound
+ */
+ CharArray getNamespaceURI(CharSequence prefix);
+
+ /**
+ * Indicates if the cursor points to a start tag.
+ *
+ * @return <code>true</code> if the cursor points to a start tag;
+ * <code>false</code> otherwise.
+ */
+ boolean isStartElement();
+
+ /**
+ * Indicates if the cursor points to an end tag.
+ *
+ * @return <code>true</code> if the cursor points to a end tag;
+ * <code>false</code> otherwise.
+ */
+ boolean isEndElement();
+
+ /**
+ * Indicates if the cursor points to character data.
+ *
+ * @return <code>true</code> if the cursor points to character data;
+ * <code>false</code> otherwise.
+ */
+ boolean isCharacters();
+
+ /**
+ * Indicates if the cursor points to character data that consists
+ * of all whitespace.
+ *
+ * @return <code>true</code> if the cursor points to whitespaces;
+ * <code>false</code> otherwise.
+ */
+ boolean isWhiteSpace();
+
+ /**
+ * Returns the normalized attribute value of the attribute with the
+ * namespace and localName.
+ *
+ * @param namespaceURI the namespace of the attribute or <code>null</code>.
+ * @param localName the local name of the attribute.
+ * @return returns the value of the attribute or <code>null</code>.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ CharArray getAttributeValue(CharSequence namespaceURI,
+ CharSequence localName);
+
+ /**
+ * Returns the count of attributes on this START_ELEMENT, this method is
+ * only valid on a START_ELEMENT or ATTRIBUTE. This count excludes namespace
+ * definitions. Attribute indices are zero-based.
+ *
+ * @return returns the number of attributes.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ int getAttributeCount();
+
+ /**
+ * Returns the namespace of the attribute at the provided index
+ *
+ * @param index the position of the attribute.
+ * @return the namespace URI or <code>null</code> if no prefix.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ CharArray getAttributeNamespace(int index);
+
+ /**
+ * Returns the localName of the attribute at the provided index.
+ *
+ * @param index the position of the attribute.
+ * @return the localName of the attribute.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ CharArray getAttributeLocalName(int index);
+
+ /**
+ * Returns the prefix of this attribute at the provided index
+ *
+ * @param index the position of the attribute.
+ * @return the prefix of the attribute or <code>null</code> if no prefix.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ CharArray getAttributePrefix(int index);
+
+ /**
+ * Returns the XML type of the attribute at the provided index.
+ *
+ * @param index the position of the attribute
+ * @return the XML type of the attribute.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ CharArray getAttributeType(int index);
+
+ /**
+ * Returns the value of the attribute at the index.
+ *
+ * @param index the position of the attribute.
+ * @return the attribute value.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ CharArray getAttributeValue(int index);
+
+ /**
+ * Indicates if this attribute was created by default.
+ *
+ * @param index the position of the attribute.
+ * @return <code>true</code> if this is a default attribute;
+ * <code>false</code> otherwise.
+ * @throws IllegalStateException if not a START_ELEMENT or ATTRIBUTE.
+ */
+ boolean isAttributeSpecified(int index);
+
+ /**
+ * Returns the count of namespaces declared on this START_ELEMENT or
+ * END_ELEMENT. This method is only valid on a START_ELEMENT, END_ELEMENT or
+ * NAMESPACE. On an END_ELEMENT the count is of the namespaces that are
+ * about to go out of scope. This is the equivalent of the information
+ * reported by SAX callback for an end element event.
+ *
+ * @return returns the number of namespace declarations on this specific
+ * element.
+ * @throws IllegalStateException if not a START_ELEMENT or END_ELEMENT.
+ */
+ int getNamespaceCount();
+
+ /**
+ * Returns the prefix for the namespace declared at the index.
+ *
+ * @param index the position of the namespace declaration.
+ * @return returns the namespace prefix or <code>null</code> if no prefix.
+ * @throws IllegalStateException if this is not a START_ELEMENT,
+ * END_ELEMENT or NAMESPACE.
+ */
+ CharArray getNamespacePrefix(int index);
+
+ /**
+ * Returns the URI for the namespace declared at the index.
+ *
+ * @param index the position of the namespace declaration.
+ * @return returns the namespace uri or <code>null</code> if no prefix.
+ * @throws IllegalStateException if this is not a START_ELEMENT,
+ * END_ELEMENT or NAMESPACE.
+ */
+ CharArray getNamespaceURI(int index);
+
+ /**
+ * Returns a read only namespace context for the current position.
+ *
+ * @return return a namespace context
+ */
+ NamespaceContext getNamespaceContext();
+
+ /**
+ * Returns an integer code that indicates the type of the event the cursor
+ * is pointing to.
+ *
+ * @return the event type.
+ */
+ int getEventType();
+
+ /**
+ * Returns the current value of the parse event as a string, this returns
+ * the string value of a CHARACTERS event, returns the value of a COMMENT,
+ * the replacement value for an ENTITY_REFERENCE, the string value of a
+ * CDATA section, the string value for a SPACE event, or the String value of
+ * the internal subset of the DTD. If an ENTITY_REFERENCE has been resolved,
+ * any character data will be reported as CHARACTERS events.
+ *
+ * @return the current text or <code>null</code>
+ * @throws IllegalStateException if this state is not a valid text state.
+ */
+ CharArray getText();
+
+ /**
+ * Returns an array which contains the characters from this event. This
+ * array should be treated as read-only and transient. I.e. the array will
+ * contain the text characters until the XMLStreamReader moves on to the
+ * next event. Attempts to hold onto the character array beyond that time or
+ * modify the contents of the array are breaches of the contract for this
+ * interface.
+ *
+ * @return the current text or an empty array.
+ * @throws IllegalStateException if this state is not a valid text state.
+ */
+ char[] getTextCharacters();
+
+ /**
+ * Gets the the text associated with a CHARACTERS, SPACE or CDATA event.
+ * Text starting a "sourceStart" is copied into "target" starting at
+ * "targetStart". Up to "length" characters are copied. The number of
+ * characters actually copied is returned.
+ *
+ * The "sourceStart" argument must be greater or equal to 0 and less than or
+ * equal to the number of characters associated with the event. Usually, one
+ * requests text starting at a "sourceStart" of 0. If the number of
+ * characters actually copied is less than the "length", then there is no
+ * more text. Otherwise, subsequent calls need to be made until all text has
+ * been retrieved. For example:
+ *
+ * <code>
+ * int length = 1024;
+ * char[] myBuffer = new char[ length ];
+ *
+ * for ( int sourceStart = 0 ; ; sourceStart += length )
+ * {
+ * int nCopied = stream.getTextCharacters( sourceStart, myBuffer, 0, length );
+ *
+ * if (nCopied < length)
+ * break;
+ * }
+ * </code> XMLStreamException may be thrown
+ * if there are any XML errors in the underlying source. The "targetStart"
+ * argument must be greater than or equal to 0 and less than the length of
+ * "target", Length must be greater than 0 and "targetStart + length" must
+ * be less than or equal to length of "target".
+ *
+ * @param sourceStart the index of te first character in the source array
+ * to copy
+ * @param target the destination array
+ * @param targetStart the start offset in the target array
+ * @param length the number of characters to copy
+ * @return the number of characters actually copied
+ * @throws XMLStreamException if the XML source is not well-formed.
+ * @throws IndexOutOfBoundsException
+ * if targetStart < 0 or > than the length of target
+ * @throws IndexOutOfBoundsException
+ * if length < 0 or targetStart + length > length of target
+ * @throws UnsupportedOperationException if this method is not supported.
+ */
+ int getTextCharacters(int sourceStart, char[] target,
+ int targetStart, int length) throws XMLStreamException;
+
+ /**
+ * Returns the offset into the text character array where the first
+ * character (of this text event) is stored.
+ *
+ * @throws IllegalStateException if this state is not a valid text state.
+ */
+ int getTextStart();
+
+ /**
+ * Returns the length of the sequence of characters for this Text event
+ * within the text character array.
+ *
+ * @throws IllegalStateException if this state is not a valid text state.
+ */
+ int getTextLength();
+
+ /**
+ * Returns the input encoding if known or <code>null</code> if unknown.
+ *
+ * @return the encoding of this instance or null.
+ */
+ String getEncoding();
+
+ /**
+ * Indicates if the current event has text. The following
+ * events have text: CHARACTERS, DTD ,ENTITY_REFERENCE, COMMENT, SPACE.
+ *
+ * @return <code>true</code> if the current event as text;
+ * <code>false</code> otherwise.
+ */
+ boolean hasText();
+
+ /**
+ * Return the current location of the processor. If the Location is unknown
+ * the processor should return an implementation of Location that returns -1
+ * for the location and null for the publicId and systemId. The location
+ * information is only valid until next() is called.
+ *
+ * @return the current location.
+ */
+ Location getLocation();
+
+ /**
+ * Returns the (local) name of the current event. For START_ELEMENT or
+ * END_ELEMENT returns the (local) name of the current element. For
+ * ENTITY_REFERENCE it returns entity name. The current event must be
+ * START_ELEMENT or END_ELEMENT, or ENTITY_REFERENCE.
+ *
+ * @return the localName.
+ * @throws IllegalStateException if this not a START_ELEMENT, END_ELEMENT
+ * or ENTITY_REFERENCE
+ */
+ CharArray getLocalName();
+
+ /**
+ * Indicates if the current event has a name (is a START_ELEMENT or
+ * END_ELEMENT).
+ *
+ * @return <code>true</code> if the current event has a name;
+ * <code>false</code> otherwise.
+ */
+ boolean hasName();
+
+ /**
+ * If the current event is a START_ELEMENT or END_ELEMENT this method
+ * returns the URI of the current element (URI mapping to the prefix
+ * element/attribute has; or if no prefix <code>null</code>).
+ *
+ * @return the URI bound to this elements prefix or <code>null</code>.
+ * @throws IllegalStateException if not a START_ELEMENT, END_ELEMENT
+ * or ATTRIBUTE.
+ */
+ CharArray getNamespaceURI();
+
+ /**
+ * Returns the prefix of the current event or null if the event does not
+ * have a prefix.
+ *
+ * @return the prefix or <code>null</code>
+ * @throws IllegalStateException if not a START_ELEMENT or END_ELEMENT.
+ */
+ CharArray getPrefix();
+
+ /**
+ * Gets the xml version declared on the xml declaration.
+ *
+ * @return the XML version or <code>null</code>
+ */
+ CharArray getVersion();
+
+ /**
+ * Gets the standalone declaration from the xml declaration.
+ *
+ * @return <code>true</code> if this is standalone;
+ * <code>false</code> otherwise.
+ */
+ boolean isStandalone();
+
+ /**
+ * Checks if standalone was set in the document.
+ *
+ * @return <code>true</code> if standalone was set;
+ * <code>false</code> otherwise.
+ */
+ boolean standaloneSet();
+
+ /**
+ * Returns the character encoding declared on the xml declaration.
+ *
+ * @return the encoding declared in the document or <code>null</code>
+ */
+ CharArray getCharacterEncodingScheme();
+
+ /**
+ * Returns the target of a processing instruction.
+ *
+ * @return the target.
+ * @throws IllegalStateException if the current event is not a
+ * {@link XMLStreamConstants#PROCESSING_INSTRUCTION}
+ */
+ CharArray getPITarget();
+
+ /**
+ * Get the data section of a processing instruction.
+ *
+ * @return the data (if processing instruction has any) or
+ * <code>null</code> if the processing instruction only has target.
+ * @throws IllegalStateException if the current event is not a
+ * {@link XMLStreamConstants#PROCESSING_INSTRUCTION}
+ */
+ CharArray getPIData();
+
+}
[16/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/io/Struct.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/Struct.java b/commons/marmotta-commons/src/ext/java/javolution/io/Struct.java
new file mode 100644
index 0000000..3f95451
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/Struct.java
@@ -0,0 +1,1749 @@
+/*
+ * 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.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import javolution.context.LocalContext;
+import javolution.lang.MathLib;
+import javolution.lang.Realtime;
+import javolution.text.TextBuilder;
+
+/**
+ * <p> Equivalent to a <code>C/C++ struct</code>; this class confers
+ * interoperability between Java classes and C/C++ struct.</p>
+ *
+ * <p> Unlike <code>C/C++</code>, the storage layout of Java objects is not
+ * determined by the compiler. The layout of objects in memory is deferred
+ * to run time and determined by the interpreter (or just-in-time compiler).
+ * This approach allows for dynamic loading and binding; but also makes
+ * interfacing with <code>C/C++</code> code difficult. Hence, this class for
+ * which the memory layout is defined by the initialization order of the
+ * {@link Struct}'s {@link Member members} and follows the same wordSize
+ * rules as <code>C/C++ structs</code>.</p>
+ *
+ * <p> This class (as well as the {@link Union} sub-class) facilitates:
+ * <ul>
+ * <li> Memory sharing between Java applications and native libraries.</li>
+ * <li> Direct encoding/decoding of streams for which the structure
+ * is defined by legacy C/C++ code.</li>
+ * <li> Serialization/deserialization of Java objects (complete control,
+ * e.g. no class header)</li>
+ * <li> Mapping of Java objects to physical addresses (with JNI).</li>
+ * </ul></p>
+ *
+ * <p> Because of its one-to-one mapping, it is relatively easy to convert C
+ * header files (e.g. OpenGL bindings) to Java {@link Struct}/{@link Union}
+ * using simple text macros. Here is an example of C struct:
+ * [code]
+ * enum Gender{MALE, FEMALE};
+ * struct Date {
+ * unsigned short year;
+ * unsigned byte month;
+ * unsigned byte day;
+ * };
+ * struct Student {
+ * enum Gender gender;
+ * char name[64];
+ * struct Date birth;
+ * float grades[10];
+ * Student* next;
+ * };[/code]</p>
+ * <p> and here is the Java equivalent using this class:
+ * [code]
+ * public enum Gender { MALE, FEMALE };
+ * public static class Date extends Struct {
+ * public final Unsigned16 year = new Unsigned16();
+ * public final Unsigned8 month = new Unsigned8();
+ * public final Unsigned8 day = new Unsigned8();
+ * }
+ * public static class Student extends Struct {
+ * public final Enum32<Gender> gender = new Enum32<Gender>(Gender.values());
+ * public final UTF8String name = new UTF8String(64);
+ * public final Date birth = inner(new Date());
+ * public final Float32[] grades = array(new Float32[10]);
+ * public final Reference32<Student> next = new Reference32<Student>();
+ * }[/code]</p>
+ * <p> Struct's members are directly accessible:
+ * [code]
+ * Student student = new Student();
+ * student.gender.set(Gender.MALE);
+ * student.name.set("John Doe"); // Null terminated (C compatible)
+ * int age = 2003 - student.birth.year.get();
+ * student.grades[2].set(12.5f);
+ * student = student.next.get();[/code]</p>
+ *
+ * <p> Applications can work with the raw {@link #getByteBuffer() bytes}
+ * directly. The following illustrate how {@link Struct} can be used to
+ * decode/encode UDP messages directly:
+ * [code]
+ * class UDPMessage extends Struct {
+ * Unsigned16 xxx = new Unsigned16();
+ * ...
+ * }
+ * public void run() {
+ * byte[] bytes = new byte[1024];
+ * DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
+ * UDPMessage message = new UDPMessage();
+ * message.setByteBuffer(ByteBuffer.wrap(bytes), 0);
+ * // packet and message are now two different views of the same data.
+ * while (isListening) {
+ * multicastSocket.receive(packet);
+ * int xxx = message.xxx.get();
+ * ... // Process message fields directly.
+ * }
+ * }[/code]</p>
+ *
+ * <p> It is relatively easy to map instances of this class to any physical
+ * address using
+ * <a href="http://java.sun.com/docs/books/tutorial/native1.1/index.html">
+ * JNI</a>. Here is an example:
+ * [code]
+ * import java.nio.ByteBuffer;
+ * class Clock extends Struct { // Hardware clock mapped to memory.
+ * Unsigned16 seconds = new Unsigned16(5); // unsigned short seconds:5
+ * Unsigned16 minutes = new Unsigned16(5); // unsigned short minutes:5
+ * Unsigned16 hours = new Unsigned16(4); // unsigned short hours:4
+ * Clock() {
+ * setByteBuffer(Clock.nativeBuffer(), 0);
+ * }
+ * private static native ByteBuffer nativeBuffer();
+ * }[/code]</p>
+ * <p> Below is the <code>nativeBuffer()</code> implementation
+ * (<code>Clock.c</code>):
+ * [code]
+ * #include <jni.h>
+ * #include "Clock.h" // Generated using javah
+ * JNIEXPORT jobject JNICALL Java_Clock_nativeBuffer (JNIEnv *env, jclass) {
+ * return (*env)->NewDirectByteBuffer(env, clock_address, buffer_size)
+ * }[/code]</p>
+ *
+ * <p> Bit-fields are supported (see <code>Clock</code> example above).
+ * Bit-fields allocation order is defined by the Struct {@link #byteOrder}
+ * return value. Leftmost bit to rightmost bit if
+ * <code>BIG_ENDIAN</code> and rightmost bit to leftmost bit if
+ * <code>LITTLE_ENDIAN</code> (same layout as Microsoft Visual C++).
+ * C/C++ Bit-fields cannot straddle the storage-unit boundary as defined
+ * by their base type (padding is inserted at the end of the first bit-field
+ * and the second bit-field is put into the next storage unit).
+ * It is possible to avoid bit padding by using the {@link BitField}
+ * member (or a sub-class). In which case the allocation order is always
+ * from the leftmost to the rightmost bit (same as <code>BIG_ENDIAN</code>).
+ * </p>
+ *
+ * <p> Finally, it is possible to change the {@link #setByteBuffer ByteBuffer}
+ * and/or the Struct {@link #setByteBufferPosition position} in its
+ * <code>ByteBuffer</code> to allow for a single {@link Struct} object to
+ * encode/decode multiple memory mapped instances.</p>
+ *
+ * <p><i>Note: Because Struct/Union are basically wrappers around
+ * <code>java.nio.ByteBuffer</code>, tutorials/usages for the
+ * Java NIO package are directly applicable to Struct/Union.</i></p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.5.1, April 1, 2010
+ */
+@SuppressWarnings("unchecked")
+@Realtime
+public class Struct {
+
+ /**
+ * Configurable holding the maximum wordSize in bytes
+ * (default <code>4</code>). Should be a value greater or equal to 1.
+ */
+ public static final LocalContext.Parameter<Integer> MAXIMUM_ALIGNMENT = new LocalContext.Parameter<Integer>() {
+ @Override
+ protected Integer getDefault() {
+ return 4;
+ }
+ };
+
+ /**
+ * Holds the outer struct if any.
+ */
+ Struct _outer;
+ /**
+ * Holds the byte buffer backing the struct (top struct).
+ */
+ ByteBuffer _byteBuffer;
+ /**
+ * Holds the offset of this struct relative to the outer struct or
+ * to the byte buffer if there is no outer.
+ */
+ int _outerOffset;
+ /**
+ * Holds this struct alignment in bytes (largest word size of its members).
+ */
+ int _alignment = 1;
+ /**
+ * Holds this struct's length.
+ */
+ int _length;
+ /**
+ * Holds the index position during construction.
+ * This is the index a the first unused byte available.
+ */
+ int _index;
+ /**
+ * Holds the word size during construction (for bit fields).
+ * This is the size of the last word used.
+ */
+ int _wordSize;
+ /**
+ * Holds the bits used in the word during construction (for bit fields).
+ * This is the number of bits used in the last word.
+ */
+ int _bitsUsed;
+ /**
+ * Indicates if the index has to be reset for each new field (
+ * <code>true</code> only for Union subclasses).
+ */
+ boolean _resetIndex;
+ /**
+ * Holds bytes array for Stream I/O when byteBuffer has no intrinsic array.
+ */
+ byte[] _bytes;
+
+ /**
+ * Default constructor.
+ */
+ public Struct() {
+ _resetIndex = isUnion();
+ }
+
+ /**
+ * Returns the size in bytes of this struct. The size includes
+ * tail padding to satisfy the struct word size requirement
+ * (defined by the largest word size of its {@link Member members}).
+ *
+ * @return the C/C++ <code>sizeof(this)</code>.
+ */
+ public final int size() {
+ return (_alignment <= 1) ? _length
+ : ((_length + _alignment - 1) / _alignment) * _alignment;
+ }
+
+ /**
+ * Returns the outer of this struct or <code>null</code> if this struct
+ * is not an inner struct.
+ *
+ * @return the outer struct or <code>null</code>.
+ */
+ public Struct outer() {
+ return _outer;
+ }
+
+ /**
+ * Returns the byte buffer for this struct. This method will allocate
+ * a new <b>direct</b> buffer if none has been set.
+ *
+ * <p> Changes to the buffer's content are visible in this struct,
+ * and vice versa.</p>
+ * <p> The buffer of an inner struct is the same as its parent struct.</p>
+ * <p> If no byte buffer has been {@link Struct#setByteBuffer set},
+ * a direct buffer is allocated with a capacity equals to this
+ * struct's {@link Struct#size() size}.</p>
+ *
+ * @return the current byte buffer or a new direct buffer if none set.
+ * @see #setByteBuffer
+ */
+ public final ByteBuffer getByteBuffer() {
+ if (_outer != null) return _outer.getByteBuffer();
+ return (_byteBuffer != null) ? _byteBuffer : newBuffer();
+ }
+
+ private synchronized ByteBuffer newBuffer() {
+ if (_byteBuffer != null) return _byteBuffer; // Synchronized check.
+ ByteBuffer bf = ByteBuffer.allocateDirect(size());
+ bf.order(byteOrder());
+ setByteBuffer(bf, 0);
+ return _byteBuffer;
+ }
+
+ /**
+ * Sets the current byte buffer for this struct.
+ * The specified byte buffer can be mapped to memory for direct memory
+ * access or can wrap a shared byte array for I/O purpose
+ * (e.g. <code>DatagramPacket</code>).
+ * The capacity of the specified byte buffer should be at least the
+ * {@link Struct#size() size} of this struct plus the offset position.
+ *
+ * @param byteBuffer the new byte buffer.
+ * @param position the position of this struct in the specified byte buffer.
+ * @return <code>this</code>
+ * @throws IllegalArgumentException if the specified byteBuffer has a
+ * different byte order than this struct.
+ * @throws UnsupportedOperationException if this struct is an inner struct.
+ * @see #byteOrder()
+ */
+ public final Struct setByteBuffer(ByteBuffer byteBuffer, int position) {
+ if (byteBuffer.order() != byteOrder()) throw new IllegalArgumentException(
+ "The byte order of the specified byte buffer"
+ + " is different from this struct byte order");
+ if (_outer != null) throw new UnsupportedOperationException(
+ "Inner struct byte buffer is inherited from outer");
+ _byteBuffer = byteBuffer;
+ _outerOffset = position;
+ return this;
+ }
+
+ /**
+ * Sets the byte position of this struct within its byte buffer.
+ *
+ * @param position the position of this struct in its byte buffer.
+ * @return <code>this</code>
+ * @throws UnsupportedOperationException if this struct is an inner struct.
+ */
+ public final Struct setByteBufferPosition(int position) {
+ return setByteBuffer(this.getByteBuffer(), position);
+ }
+
+ /**
+ * Returns the absolute byte position of this struct within its associated
+ * {@link #getByteBuffer byte buffer}.
+ *
+ * @return the absolute position of this struct (can be an inner struct)
+ * in the byte buffer.
+ */
+ public final int getByteBufferPosition() {
+ return (_outer != null) ? _outer.getByteBufferPosition() + _outerOffset
+ : _outerOffset;
+ }
+
+ /**
+ * Reads this struct from the specified input stream
+ * (convenience method when using Stream I/O). For better performance,
+ * use of Block I/O (e.g. <code>java.nio.channels.*</code>) is recommended.
+ * This method behaves appropriately when not all of the data is available
+ * from the input stream. Incomplete data is extremely common when the
+ * input stream is associated with something like a TCP connection.
+ * The typical usage pattern in those scenarios is to repeatedly call
+ * read() until the entire message is received.
+ *
+ * @param in the input stream being read from.
+ * @return the number of bytes read (typically the {@link #size() size}
+ * of this struct.
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read(InputStream in) throws IOException {
+ ByteBuffer buffer = getByteBuffer();
+ int size = size();
+ int remaining = size - buffer.position();
+ if (remaining == 0) remaining = size;// at end so move to beginning
+ int alreadyRead = size - remaining; // typically 0
+ if (buffer.hasArray()) {
+ int offset = buffer.arrayOffset() + getByteBufferPosition();
+ int bytesRead = in.read(buffer.array(), offset + alreadyRead,
+ remaining);
+ buffer.position(getByteBufferPosition() + alreadyRead + bytesRead
+ - offset);
+ return bytesRead;
+ } else {
+ synchronized (buffer) {
+ if (_bytes == null) {
+ _bytes = new byte[size()];
+ }
+ int bytesRead = in.read(_bytes, 0, remaining);
+ buffer.position(getByteBufferPosition() + alreadyRead);
+ buffer.put(_bytes, 0, bytesRead);
+ return bytesRead;
+ }
+ }
+ }
+
+ /**
+ * Writes this struct to the specified output stream
+ * (convenience method when using Stream I/O). For better performance,
+ * use of Block I/O (e.g. <code>java.nio.channels.*</code>) is recommended.
+ *
+ * @param out the output stream to write to.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(OutputStream out) throws IOException {
+ ByteBuffer buffer = getByteBuffer();
+ if (buffer.hasArray()) {
+ int offset = buffer.arrayOffset() + getByteBufferPosition();
+ out.write(buffer.array(), offset, size());
+ } else {
+ synchronized (buffer) {
+ if (_bytes == null) {
+ _bytes = new byte[size()];
+ }
+ buffer.position(getByteBufferPosition());
+ buffer.get(_bytes);
+ out.write(_bytes);
+ }
+ }
+ }
+
+ /**
+ * Returns this struct address (if supported by the platform).
+ * This method allows for structs to be referenced (e.g. pointer)
+ * from other structs.
+ *
+ * @return the struct memory address.
+ * @throws UnsupportedOperationException if not supported by the platform.
+ * @see Reference32
+ * @see Reference64
+ */
+ public final long address() {
+ try {
+ Class<?> dbClass = Class.forName("sun.nio.ch.DirectBuffer");
+ java.lang.reflect.Method address = dbClass.getDeclaredMethod(
+ "address", new Class[0]);
+ return ((Long) address.invoke(this.getByteBuffer(),
+ (Object[]) null)).longValue();
+ } catch (Throwable error) {
+ error.printStackTrace();
+ throw new UnsupportedOperationException(
+ "Method Struct.address() not supported on this platform.");
+ }
+ }
+
+ /**
+ * Returns the <code>String</code> representation of this struct
+ * in the form of its constituing bytes (hexadecimal). For example:[code]
+ * public static class Student extends Struct {
+ * Utf8String name = new Utf8String(16);
+ * Unsigned16 year = new Unsigned16();
+ * Float32 grade = new Float32();
+ * }
+ * Student student = new Student();
+ * student.name.set("John Doe");
+ * student.year.set(2003);
+ * student.grade.set(12.5f);
+ * System.out.println(student);
+ *
+ * 4A 6F 68 6E 20 44 6F 65 00 00 00 00 00 00 00 00
+ * 07 D3 00 00 41 48 00 00[/code]
+ *
+ * @return a hexadecimal representation of the bytes content for this
+ * struct.
+ */
+ public String toString() {
+ TextBuilder tmp = new TextBuilder();
+ final int size = size();
+ final ByteBuffer buffer = getByteBuffer();
+ final int start = getByteBufferPosition();
+ for (int i = 0; i < size; i++) {
+ int b = buffer.get(start + i) & 0xFF;
+ tmp.append(HEXA[b >> 4]);
+ tmp.append(HEXA[b & 0xF]);
+ tmp.append(((i & 0xF) == 0xF) ? '\n' : ' ');
+ }
+ return tmp.toString();
+ }
+
+ private static final char[] HEXA = { '0', '1', '2', '3', '4', '5', '6',
+ '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ ///////////////////
+ // CONFIGURATION //
+ ///////////////////
+ /**
+ * Indicates if this struct's members are mapped to the same location
+ * in memory (default <code>false</code>). This method is useful for
+ * applications extending {@link Struct} with new member types in order to
+ * create unions from these new structs. For example:[code]
+ * public abstract class FortranStruct extends Struct {
+ * public class FortranString extends Member {...}
+ * protected FortranString[] array(FortranString[] array, int stringLength) { ... }
+ * }
+ * public abstract class FortranUnion extends FortranStruct {
+ * // Inherits new members and methods.
+ * public final isUnion() {
+ * return true;
+ * }
+ * }[/code]
+ *
+ * @return <code>true</code> if this struct's members are mapped to
+ * to the same location in memory; <code>false</code>
+ * otherwise.
+ * @see Union
+ */
+ public boolean isUnion() {
+ return false;
+ }
+
+ /**
+ * Returns the byte order for this struct (configurable).
+ * The byte order is inherited by inner structs. Sub-classes may change
+ * the byte order by overriding this method. For example:[code]
+ * public class TopStruct extends Struct {
+ * ... // Members initialization.
+ * public ByteOrder byteOrder() {
+ * // TopStruct and its inner structs use hardware byte order.
+ * return ByteOrder.nativeOrder();
+ * }
+ * }}[/code]</p></p>
+ *
+ * @return the byte order when reading/writing multibyte values
+ * (default: network byte order, <code>BIG_ENDIAN</code>).
+ */
+ public ByteOrder byteOrder() {
+ return (_outer != null) ? _outer.byteOrder() : ByteOrder.BIG_ENDIAN;
+ }
+
+ /**
+ * Indicates if this struct is packed (configurable).
+ * By default, {@link Member members} of a struct are aligned on the
+ * boundary corresponding to the member base type; padding is performed
+ * if necessary. This directive is <b>not</b> inherited by inner structs.
+ * Sub-classes may change the packing directive by overriding this method.
+ * For example:[code]
+ * public class MyStruct extends Struct {
+ * ... // Members initialization.
+ * public boolean isPacked() {
+ * return true; // MyStruct is packed.
+ * }
+ * }}[/code]
+ *
+ * @return <code>true</code> if word size requirements are ignored.
+ * <code>false</code> otherwise (default).
+ */
+ public boolean isPacked() {
+ return false;
+ }
+
+ /**
+ * Defines the specified struct as inner of this struct.
+ *
+ * @param struct the inner struct.
+ * @return the specified struct.
+ * @throws IllegalArgumentException if the specified struct is already
+ * an inner struct.
+ */
+ protected <S extends Struct> S inner(S struct) {
+ if (struct._outer != null) throw new IllegalArgumentException(
+ "struct: Already an inner struct");
+ Member inner = new Member(struct.size() << 3, struct._alignment); // Update indexes.
+ struct._outer = this;
+ struct._outerOffset = inner.offset();
+ return (S) struct;
+ }
+
+ /**
+ * Defines the specified array of structs as inner structs.
+ * The array is populated if necessary using the struct component
+ * default constructor (which must be public).
+ *
+ * @param structs the struct array.
+ * @return the specified struct array.
+ * @throws IllegalArgumentException if the specified array contains
+ * inner structs.
+ */
+ protected <S extends Struct> S[] array(S[] structs) {
+ Class<?> structClass = null;
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ for (int i = 0; i < structs.length;) {
+ S struct = structs[i];
+ if (struct == null) {
+ try {
+ if (structClass == null) {
+ String arrayName = structs.getClass().getName();
+ String structName = arrayName.substring(2,
+ arrayName.length() - 1);
+ structClass = Class.forName(structName);
+ if (structClass == null) { throw new IllegalArgumentException(
+ "Struct class: " + structName + " not found"); }
+ }
+ struct = (S) structClass.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ structs[i++] = inner(struct);
+ }
+ _resetIndex = resetIndexSaved;
+ return (S[]) structs;
+ }
+
+ /**
+ * Defines the specified two-dimensional array of structs as inner
+ * structs. The array is populated if necessary using the struct component
+ * default constructor (which must be public).
+ *
+ * @param structs the two dimensional struct array.
+ * @return the specified struct array.
+ * @throws IllegalArgumentException if the specified array contains
+ * inner structs.
+ */
+ protected <S extends Struct> S[][] array(S[][] structs) {
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ for (int i = 0; i < structs.length; i++) {
+ array(structs[i]);
+ }
+ _resetIndex = resetIndexSaved;
+ return (S[][]) structs;
+ }
+
+ /**
+ * Defines the specified three dimensional array of structs as inner
+ * structs. The array is populated if necessary using the struct component
+ * default constructor (which must be public).
+ *
+ * @param structs the three dimensional struct array.
+ * @return the specified struct array.
+ * @throws IllegalArgumentException if the specified array contains
+ * inner structs.
+ */
+ protected <S extends Struct> S[][][] array(S[][][] structs) {
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ for (int i = 0; i < structs.length; i++) {
+ array(structs[i]);
+ }
+ _resetIndex = resetIndexSaved;
+ return (S[][][]) structs;
+ }
+
+ /**
+ * Defines the specified array member. For predefined members,
+ * the array is populated when empty; custom members should use
+ * literal (populated) arrays.
+ *
+ * @param arrayMember the array member.
+ * @return the specified array member.
+ * @throws UnsupportedOperationException if the specified array
+ * is empty and the member type is unknown.
+ */
+ protected <M extends Member> M[] array(M[] arrayMember) {
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ if (BOOL.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Bool();
+ }
+ } else if (SIGNED_8.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Signed8();
+ }
+ } else if (UNSIGNED_8.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Unsigned8();
+ }
+ } else if (SIGNED_16.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Signed16();
+ }
+ } else if (UNSIGNED_16.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Unsigned16();
+ }
+ } else if (SIGNED_32.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Signed32();
+ }
+ } else if (UNSIGNED_32.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Unsigned32();
+ }
+ } else if (SIGNED_64.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Signed64();
+ }
+ } else if (FLOAT_32.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Float32();
+ }
+ } else if (FLOAT_64.isInstance(arrayMember)) {
+ for (int i = 0; i < arrayMember.length;) {
+ arrayMember[i++] = (M) this.new Float64();
+ }
+ } else {
+ throw new UnsupportedOperationException(
+ "Cannot create member elements, the arrayMember should "
+ + "contain the member instances instead of null");
+ }
+ _resetIndex = resetIndexSaved;
+ return (M[]) arrayMember;
+ }
+
+ private static final Class<? extends Bool[]> BOOL = new Bool[0].getClass();
+ private static final Class<? extends Signed8[]> SIGNED_8 = new Signed8[0]
+ .getClass();
+ private static final Class<? extends Unsigned8[]> UNSIGNED_8 = new Unsigned8[0]
+ .getClass();
+ private static final Class<? extends Signed16[]> SIGNED_16 = new Signed16[0]
+ .getClass();
+ private static final Class<? extends Unsigned16[]> UNSIGNED_16 = new Unsigned16[0]
+ .getClass();
+ private static final Class<? extends Signed32[]> SIGNED_32 = new Signed32[0]
+ .getClass();
+ private static final Class<? extends Unsigned32[]> UNSIGNED_32 = new Unsigned32[0]
+ .getClass();
+ private static final Class<? extends Signed64[]> SIGNED_64 = new Signed64[0]
+ .getClass();
+ private static final Class<? extends Float32[]> FLOAT_32 = new Float32[0]
+ .getClass();
+ private static final Class<? extends Float64[]> FLOAT_64 = new Float64[0]
+ .getClass();
+
+ /**
+ * Defines the specified two-dimensional array member. For predefined
+ * members, the array is populated when empty; custom members should use
+ * literal (populated) arrays.
+ *
+ * @param arrayMember the two-dimensional array member.
+ * @return the specified array member.
+ * @throws UnsupportedOperationException if the specified array
+ * is empty and the member type is unknown.
+ */
+ protected <M extends Member> M[][] array(M[][] arrayMember) {
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ for (int i = 0; i < arrayMember.length; i++) {
+ array(arrayMember[i]);
+ }
+ _resetIndex = resetIndexSaved;
+ return (M[][]) arrayMember;
+ }
+
+ /**
+ * Defines the specified three-dimensional array member. For predefined
+ * members, the array is populated when empty; custom members should use
+ * literal (populated) arrays.
+ *
+ * @param arrayMember the three-dimensional array member.
+ * @return the specified array member.
+ * @throws UnsupportedOperationException if the specified array
+ * is empty and the member type is unknown.
+ */
+ protected <M extends Member> M[][][] array(M[][][] arrayMember) {
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ for (int i = 0; i < arrayMember.length; i++) {
+ array(arrayMember[i]);
+ }
+ _resetIndex = resetIndexSaved;
+ return (M[][][]) arrayMember;
+ }
+
+ /**
+ * Defines the specified array of UTF-8 strings, all strings having the
+ * specified length (convenience method).
+ *
+ * @param array the string array.
+ * @param stringLength the length of the string elements.
+ * @return the specified string array.
+ */
+ protected UTF8String[] array(UTF8String[] array, int stringLength) {
+ boolean resetIndexSaved = _resetIndex;
+ if (_resetIndex) {
+ _index = 0;
+ _resetIndex = false; // Ensures the array elements are sequential.
+ }
+ for (int i = 0; i < array.length; i++) {
+ array[i] = new UTF8String(stringLength);
+ }
+ _resetIndex = resetIndexSaved;
+ return array;
+ }
+
+ /**
+ * Reads the specified bits from this Struct as an long (signed) integer
+ * value.
+ *
+ * @param bitOffset the bit start position in the Struct.
+ * @param bitSize the number of bits.
+ * @return the specified bits read as a signed long.
+ * @throws IllegalArgumentException if
+ * <code>(bitOffset + bitSize - 1) / 8 >= this.size()</code>
+ */
+ public long readBits(int bitOffset, int bitSize) {
+ if ((bitOffset + bitSize - 1) >> 3 >= this.size()) throw new IllegalArgumentException(
+ "Attempt to read outside the Struct");
+ int offset = bitOffset >> 3;
+ int bitStart = bitOffset - (offset << 3);
+ bitStart = (byteOrder() == ByteOrder.BIG_ENDIAN) ? bitStart : 64
+ - bitSize - bitStart;
+ int index = getByteBufferPosition() + offset;
+ long value = readByteBufferLong(index);
+ value <<= bitStart; // Clears preceding bits.
+ value >>= (64 - bitSize); // Signed shift.
+ return value;
+ }
+
+ private long readByteBufferLong(int index) {
+ ByteBuffer byteBuffer = getByteBuffer();
+ if (index + 8 < byteBuffer.limit()) return byteBuffer.getLong(index);
+ // Else possible buffer overflow.
+ if (byteBuffer.order() == ByteOrder.LITTLE_ENDIAN) {
+ return (readByte(index, byteBuffer) & 0xff)
+ + ((readByte(++index, byteBuffer) & 0xff) << 8)
+ + ((readByte(++index, byteBuffer) & 0xff) << 16)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 24)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 32)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 40)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 48)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 56);
+ } else {
+ return (((long) readByte(index, byteBuffer)) << 56)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 48)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 40)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 32)
+ + ((readByte(++index, byteBuffer) & 0xffL) << 24)
+ + ((readByte(++index, byteBuffer) & 0xff) << 16)
+ + ((readByte(++index, byteBuffer) & 0xff) << 8)
+ + (readByte(++index, byteBuffer) & 0xffL);
+ }
+ }
+
+ private static byte readByte(int index, ByteBuffer byteBuffer) {
+ return (index < byteBuffer.limit()) ? byteBuffer.get(index) : 0;
+ }
+
+ /**
+ * Writes the specified bits into this Struct.
+ *
+ * @param value the bits value as a signed long.
+ * @param bitOffset the bit start position in the Struct.
+ * @param bitSize the number of bits.
+ * @throws IllegalArgumentException if
+ * <code>(bitOffset + bitSize - 1) / 8 >= this.size()</code>
+ */
+ public void writeBits(long value, int bitOffset, int bitSize) {
+ if ((bitOffset + bitSize - 1) >> 3 >= this.size()) throw new IllegalArgumentException(
+ "Attempt to write outside the Struct");
+ int offset = bitOffset >> 3;
+ int bitStart = (byteOrder() == ByteOrder.BIG_ENDIAN) ? bitOffset
+ - (offset << 3) : 64 - bitSize - (bitOffset - (offset << 3));
+ long mask = -1L;
+ mask <<= bitStart; // Clears preceding bits
+ mask >>>= (64 - bitSize); // Unsigned shift.
+ mask <<= 64 - bitSize - bitStart;
+ value <<= (64 - bitSize - bitStart);
+ value &= mask; // Protects against out of range values.
+ int index = getByteBufferPosition() + offset;
+ long oldValue = readByteBufferLong(index);
+ long resetValue = oldValue & (~mask);
+ long newValue = resetValue | value;
+ writeByteBufferLong(index, newValue);
+ }
+
+ private void writeByteBufferLong(int index, long value) {
+ ByteBuffer byteBuffer = getByteBuffer();
+ if (index + 8 < byteBuffer.limit()) {
+ byteBuffer.putLong(index, value);
+ return;
+ }
+ // Else possible buffer overflow.
+ if (byteBuffer.order() == ByteOrder.LITTLE_ENDIAN) {
+ writeByte(index, byteBuffer, (byte) value);
+ writeByte(++index, byteBuffer, (byte) (value >> 8));
+ writeByte(++index, byteBuffer, (byte) (value >> 16));
+ writeByte(++index, byteBuffer, (byte) (value >> 24));
+ writeByte(++index, byteBuffer, (byte) (value >> 32));
+ writeByte(++index, byteBuffer, (byte) (value >> 40));
+ writeByte(++index, byteBuffer, (byte) (value >> 48));
+ writeByte(++index, byteBuffer, (byte) (value >> 56));
+ } else {
+ writeByte(index, byteBuffer, (byte) (value >> 56));
+ writeByte(++index, byteBuffer, (byte) (value >> 48));
+ writeByte(++index, byteBuffer, (byte) (value >> 40));
+ writeByte(++index, byteBuffer, (byte) (value >> 32));
+ writeByte(++index, byteBuffer, (byte) (value >> 24));
+ writeByte(++index, byteBuffer, (byte) (value >> 16));
+ writeByte(++index, byteBuffer, (byte) (value >> 8));
+ writeByte(++index, byteBuffer, (byte) value);
+ }
+ }
+
+ private static void writeByte(int index, ByteBuffer byteBuffer, byte value) {
+ if (index < byteBuffer.limit()) {
+ byteBuffer.put(index, value);
+ }
+ }
+
+ /////////////
+ // MEMBERS //
+ /////////////
+ /**
+ * This inner class represents the base class for all {@link Struct}
+ * members. It allows applications to define additional member types.
+ * For example:[code]
+ * public class MyStruct extends Struct {
+ * BitSet bits = new BitSet(256);
+ * ...
+ * public BitSet extends Member {
+ * public BitSet(int nbrBits) {
+ * super(nbrBits, 0); // Direct bit access.
+ * }
+ * public boolean get(int i) { ... }
+ * public void set(int i, boolean value) { ...}
+ * }
+ * }[/code]
+ */
+ protected class Member {
+
+ /**
+ * Holds the relative offset (in bytes) of this member within its struct.
+ */
+ private final int _offset;
+ /**
+ * Holds the relative bit offset of this member to its struct offset.
+ */
+ private final int _bitIndex;
+ /**
+ * Holds the bit length of this member.
+ */
+ private final int _bitLength;
+
+ /**
+ * Base constructor for custom member types.
+ *
+ * The word size can be zero, in which case the {@link #offset}
+ * of the member does not change, only {@link #bitIndex} is
+ * incremented.
+ *
+ * @param bitLength the number of bits or <code>0</code>
+ * to force next member on next word boundary.
+ * @param wordSize the word size in bytes used when accessing
+ * this member data or <code>0</code> if the data is accessed
+ * at the bit level.
+ */
+ protected Member(int bitLength, int wordSize) {
+ _bitLength = bitLength;
+
+ // Resets index if union.
+ if (_resetIndex) {
+ _index = 0;
+ }
+
+ // Check if we can merge bitfields (always true if no word boundary).
+ if ((wordSize == 0)
+ || ((bitLength != 0) && (wordSize == _wordSize) && ((_bitsUsed + bitLength) <= (wordSize << 3)))) {
+
+ _offset = _index - _wordSize;
+ _bitIndex = _bitsUsed;
+ _bitsUsed += bitLength;
+
+ // Straddling word boundary only possible if (wordSize == 0)
+ while (_bitsUsed > (_wordSize << 3)) {
+ _index++;
+ _wordSize++;
+ _length = MathLib.max(_length, _index);
+ }
+ return; // Bit field merge done.
+ }
+
+ // Check alignment.
+ if (!isPacked()) {
+
+ // Updates struct's alignment constraint, based on largest word size.
+ if ((_alignment < wordSize)) {
+ _alignment = wordSize;
+ }
+
+ // Adds padding if misaligned.
+ int misaligned = _index % wordSize;
+ if (misaligned != 0) {
+ _index += wordSize - misaligned;
+ }
+ }
+
+ // Sets member indices.
+ _offset = _index;
+ _bitIndex = 0;
+
+ // Update struct indices.
+ _index += MathLib.max(wordSize, (bitLength + 7) >> 3);
+ _wordSize = wordSize;
+ _bitsUsed = bitLength;
+ _length = MathLib.max(_length, _index);
+ // size and index may differ because of {@link Union}
+ }
+
+ /**
+ * Returns the outer {@link Struct struct} container.
+ *
+ * @return the outer struct.
+ */
+ public final Struct struct() {
+ return Struct.this;
+ }
+
+ /**
+ * Returns the byte offset of this member in its struct.
+ * Equivalent to C/C++ <code>offsetof(struct(), this)</code>
+ *
+ * @return the offset of this member in the Struct.
+ */
+ public final int offset() {
+ return _offset;
+ }
+
+ /**
+ * Holds the bit offset of this member (if any).
+ * The actual position of the bits data depends upon the endianess and
+ * the word size.
+ */
+ public final int bitIndex() {
+ return _bitIndex;
+ }
+
+ /**
+ * Returns the number of bits in this member. Can be zero if this
+ * member is used to force the next member to the next word boundary.
+ *
+ * @return the number of bits in the member.
+ */
+ public final int bitLength() {
+ return _bitLength;
+ }
+
+ // Returns the member int value.
+ final int get(int wordSize, int word) {
+ final int shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? (wordSize << 3)
+ - bitIndex() - bitLength()
+ : bitIndex();
+ word >>= shift;
+ int mask = 0xFFFFFFFF >>> (32 - bitLength());
+ return word & mask;
+ }
+
+ // Sets the member int value.
+ final int set(int value, int wordSize, int word) {
+ final int shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? (wordSize << 3)
+ - bitIndex() - bitLength()
+ : bitIndex();
+ int mask = 0xFFFFFFFF >>> (32 - bitLength());
+ mask <<= shift;
+ value <<= shift;
+ return (word & ~mask) | (value & mask);
+ }
+
+ // Returns the member long value.
+ final long get(int wordSize, long word) {
+ final int shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? (wordSize << 3)
+ - bitIndex() - bitLength()
+ : bitIndex();
+ word >>= shift;
+ long mask = 0xFFFFFFFFFFFFFFFFL >>> (64 - bitLength());
+ return word & mask;
+ }
+
+ // Sets the member long value.
+ final long set(long value, int wordSize, long word) {
+ final int shift = (byteOrder() == ByteOrder.BIG_ENDIAN) ? (wordSize << 3)
+ - bitIndex() - bitLength()
+ : bitIndex();
+ long mask = 0xFFFFFFFFFFFFFFFFL >>> (64 - bitLength());
+ mask <<= shift;
+ value <<= shift;
+ return (word & ~mask) | (value & mask);
+ }
+ }
+
+ ///////////////////////
+ // PREDEFINED FIELDS //
+ ///////////////////////
+ /**
+ * This class represents a UTF-8 character string, null terminated
+ * (for C/C++ compatibility)
+ */
+ public class UTF8String extends Member {
+
+ private final UTF8ByteBufferWriter _writer = new UTF8ByteBufferWriter();
+ private final UTF8ByteBufferReader _reader = new UTF8ByteBufferReader();
+ private final int _length;
+
+ public UTF8String(int length) {
+ super(length << 3, 1);
+ _length = length; // Takes into account 0 terminator.
+ }
+
+ public void set(String string) {
+ final ByteBuffer buffer = getByteBuffer();
+ synchronized (buffer) {
+ try {
+ int index = getByteBufferPosition() + offset();
+ buffer.position(index);
+ _writer.setOutput(buffer);
+ if (string.length() < _length) {
+ _writer.write(string);
+ _writer.write(0); // Marks end of string.
+ } else if (string.length() > _length) { // Truncates.
+ _writer.write(string.substring(0, _length));
+ } else { // Exact same length.
+ _writer.write(string);
+ }
+ } catch (IOException e) { // Should never happen.
+ throw new Error(e.getMessage());
+ } finally {
+ _writer.reset();
+ }
+ }
+ }
+
+ public String get() {
+ final ByteBuffer buffer = getByteBuffer();
+ synchronized (buffer) {
+ TextBuilder tmp = new TextBuilder();
+ try {
+ int index = getByteBufferPosition() + offset();
+ buffer.position(index);
+ _reader.setInput(buffer);
+ for (int i = 0; i < _length; i++) {
+ char c = (char) _reader.read();
+ if (c == 0) { // Null terminator.
+ return tmp.toString();
+ } else {
+ tmp.append(c);
+ }
+ }
+ return tmp.toString();
+ } catch (IOException e) { // Should never happen.
+ throw new Error(e.getMessage());
+ } finally {
+ _reader.reset();
+ }
+ }
+ }
+
+ public String toString() {
+ return this.get();
+ }
+ }
+
+ /**
+ * This class represents a 8 bits boolean with <code>true</code> represented
+ * by <code>1</code> and <code>false</code> represented by <code>0</code>.
+ */
+ public class Bool extends Member {
+
+ public Bool() {
+ super(8, 1);
+ }
+
+ public Bool(int nbrOfBits) {
+ super(nbrOfBits, 1);
+ }
+
+ public boolean get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().get(index);
+ word = (bitLength() == 8) ? word : get(1, word);
+ return word != 0;
+ }
+
+ public void set(boolean value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 8) {
+ getByteBuffer().put(index, (byte) (value ? -1 : 0));
+ } else {
+ getByteBuffer().put(
+ index,
+ (byte) set(value ? -1 : 0, 1, getByteBuffer()
+ .get(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 8 bits signed integer.
+ */
+ public class Signed8 extends Member {
+
+ public Signed8() {
+ super(8, 1);
+ }
+
+ public Signed8(int nbrOfBits) {
+ super(nbrOfBits, 1);
+ }
+
+ public byte get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().get(index);
+ return (byte) ((bitLength() == 8) ? word : get(1, word));
+ }
+
+ public void set(byte value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 8) {
+ getByteBuffer().put(index, value);
+ } else {
+ getByteBuffer().put(index,
+ (byte) set(value, 1, getByteBuffer().get(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 8 bits unsigned integer.
+ */
+ public class Unsigned8 extends Member {
+
+ public Unsigned8() {
+ super(8, 1);
+ }
+
+ public Unsigned8(int nbrOfBits) {
+ super(nbrOfBits, 1);
+ }
+
+ public short get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().get(index);
+ return (short) (0xFF & ((bitLength() == 8) ? word : get(1, word)));
+ }
+
+ public void set(short value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 8) {
+ getByteBuffer().put(index, (byte) value);
+ } else {
+ getByteBuffer().put(index,
+ (byte) set(value, 1, getByteBuffer().get(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 16 bits signed integer.
+ */
+ public class Signed16 extends Member {
+
+ public Signed16() {
+ super(16, 2);
+ }
+
+ public Signed16(int nbrOfBits) {
+ super(nbrOfBits, 2);
+ }
+
+ public short get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getShort(index);
+ return (short) ((bitLength() == 16) ? word : get(2, word));
+ }
+
+ public void set(short value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 16) {
+ getByteBuffer().putShort(index, value);
+ } else {
+ getByteBuffer().putShort(index,
+ (short) set(value, 2, getByteBuffer().getShort(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 16 bits unsigned integer.
+ */
+ public class Unsigned16 extends Member {
+
+ public Unsigned16() {
+ super(16, 2);
+ }
+
+ public Unsigned16(int nbrOfBits) {
+ super(nbrOfBits, 2);
+ }
+
+ public int get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getShort(index);
+ return 0xFFFF & ((bitLength() == 16) ? word : get(2, word));
+ }
+
+ public void set(int value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 16) {
+ getByteBuffer().putShort(index, (short) value);
+ } else {
+ getByteBuffer().putShort(index,
+ (short) set(value, 2, getByteBuffer().getShort(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 32 bits signed integer.
+ */
+ public class Signed32 extends Member {
+
+ public Signed32() {
+ super(32, 4);
+ }
+
+ public Signed32(int nbrOfBits) {
+ super(nbrOfBits, 4);
+ }
+
+ public int get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getInt(index);
+ return (bitLength() == 32) ? word : get(4, word);
+ }
+
+ public void set(int value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 32) {
+ getByteBuffer().putInt(index, value);
+ } else {
+ getByteBuffer().putInt(index,
+ set(value, 4, getByteBuffer().getInt(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 32 bits unsigned integer.
+ */
+ public class Unsigned32 extends Member {
+
+ public Unsigned32() {
+ super(32, 4);
+ }
+
+ public Unsigned32(int nbrOfBits) {
+ super(nbrOfBits, 4);
+ }
+
+ public long get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getInt(index);
+ return 0xFFFFFFFFL & ((bitLength() == 32) ? word : get(4, word));
+ }
+
+ public void set(long value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 32) {
+ getByteBuffer().putInt(index, (int) value);
+ } else {
+ getByteBuffer().putInt(index,
+ set((int) value, 4, getByteBuffer().getInt(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 64 bits signed integer.
+ */
+ public class Signed64 extends Member {
+
+ public Signed64() {
+ super(64, 8);
+ }
+
+ public Signed64(int nbrOfBits) {
+ super(nbrOfBits, 8);
+ }
+
+ public long get() {
+ final int index = getByteBufferPosition() + offset();
+ long word = getByteBuffer().getLong(index);
+ return (bitLength() == 64) ? word : get(8, word);
+ }
+
+ public void set(long value) {
+ final int index = getByteBufferPosition() + offset();
+ if (bitLength() == 64) {
+ getByteBuffer().putLong(index, value);
+ } else {
+ getByteBuffer().putLong(index,
+ set(value, 8, getByteBuffer().getLong(index)));
+ }
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents an arbitrary size (unsigned) bit field with
+ * no word size constraint (they can straddle words boundaries).
+ */
+ public class BitField extends Member {
+
+ public BitField(int nbrOfBits) {
+ super(nbrOfBits, 0);
+ }
+
+ public long longValue() {
+ long signedValue = readBits(bitIndex() + (offset() << 3),
+ bitLength());
+ return ~(-1L << bitLength()) & signedValue;
+ }
+
+ public int intValue() {
+ return (int) longValue();
+ }
+
+ public short shortValue() {
+ return (short) longValue();
+ }
+
+ public byte byteValue() {
+ return (byte) longValue();
+ }
+
+ public void set(long value) {
+ writeBits(value, bitIndex() + (offset() << 3), bitLength());
+ }
+
+ public String toString() {
+ return String.valueOf(longValue());
+ }
+ }
+
+ /**
+ * This class represents a 32 bits float (C/C++/Java <code>float</code>).
+ */
+ public class Float32 extends Member {
+
+ public Float32() {
+ super(32, 4);
+ }
+
+ public float get() {
+ final int index = getByteBufferPosition() + offset();
+ return getByteBuffer().getFloat(index);
+ }
+
+ public void set(float value) {
+ final int index = getByteBufferPosition() + offset();
+ getByteBuffer().putFloat(index, value);
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 64 bits float (C/C++/Java <code>double</code>).
+ */
+ public class Float64 extends Member {
+
+ public Float64() {
+ super(64, 8);
+ }
+
+ public double get() {
+ final int index = getByteBufferPosition() + offset();
+ return getByteBuffer().getDouble(index);
+ }
+
+ public void set(double value) {
+ final int index = getByteBufferPosition() + offset();
+ getByteBuffer().putDouble(index, value);
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * <p> This class represents a 32 bits reference (C/C++ pointer) to
+ * a {@link Struct} object (other types may require a {@link Struct}
+ * wrapper).</p>
+ * <p> Note: For references which can be externally modified, an application
+ * may want to check the {@link #isUpToDate up-to-date} status of
+ * the reference. For out-of-date references, a {@link Struct}
+ * can be created at the address specified by {@link #value}
+ * (using JNI) and the reference {@link #set set} accordingly.</p>
+ */
+ public class Reference32<S extends Struct> extends Member {
+
+ private S _struct;
+
+ public Reference32() {
+ super(32, 4);
+ }
+
+ public void set(S struct) {
+ final int index = getByteBufferPosition() + offset();
+ if (struct != null) {
+ getByteBuffer().putInt(index, (int) struct.address());
+ } else {
+ getByteBuffer().putInt(index, 0);
+ }
+ _struct = struct;
+ }
+
+ public S get() {
+ return _struct;
+ }
+
+ public int value() {
+ final int index = getByteBufferPosition() + offset();
+ return getByteBuffer().getInt(index);
+ }
+
+ public boolean isUpToDate() {
+ final int index = getByteBufferPosition() + offset();
+ if (_struct != null) {
+ return getByteBuffer().getInt(index) == (int) _struct.address();
+ } else {
+ return getByteBuffer().getInt(index) == 0;
+ }
+ }
+ }
+
+ /**
+ * <p> This class represents a 64 bits reference (C/C++ pointer) to
+ * a {@link Struct} object (other types may require a {@link Struct}
+ * wrapper).</p>
+ * <p> Note: For references which can be externally modified, an application
+ * may want to check the {@link #isUpToDate up-to-date} status of
+ * the reference. For out-of-date references, a new {@link Struct}
+ * can be created at the address specified by {@link #value}
+ * (using JNI) and then {@link #set set} to the reference.</p>
+ */
+ public class Reference64<S extends Struct> extends Member {
+
+ private S _struct;
+
+ public Reference64() {
+ super(64, 8);
+ }
+
+ public void set(S struct) {
+ final int index = getByteBufferPosition() + offset();
+ if (struct != null) {
+ getByteBuffer().putLong(index, struct.address());
+ } else if (struct == null) {
+ getByteBuffer().putLong(index, 0L);
+ }
+ _struct = struct;
+ }
+
+ public S get() {
+ return _struct;
+ }
+
+ public long value() {
+ final int index = getByteBufferPosition() + offset();
+ return getByteBuffer().getLong(index);
+ }
+
+ public boolean isUpToDate() {
+ final int index = getByteBufferPosition() + offset();
+ if (_struct != null) {
+ return getByteBuffer().getLong(index) == _struct.address();
+ } else {
+ return getByteBuffer().getLong(index) == 0L;
+ }
+ }
+ }
+
+ /**
+ * This class represents a 8 bits {@link Enum}.
+ */
+ public class Enum8<T extends Enum<T>> extends Member {
+
+ private final T[] _values;
+
+ public Enum8(T[] values) {
+ super(8, 1);
+ _values = values;
+ }
+
+ public Enum8(T[] values, int nbrOfBits) {
+ super(nbrOfBits, 1);
+ _values = values;
+ }
+
+ public T get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().get(index);
+ return _values[0xFF & get(1, word)];
+ }
+
+ public void set(T e) {
+ int value = e.ordinal();
+ if (_values[value] != e) throw new IllegalArgumentException(
+ "enum: "
+ + e
+ + ", ordinal value does not reflect enum values position");
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().get(index);
+ getByteBuffer().put(index, (byte) set(value, 1, word));
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 16 bits {@link Enum}.
+ */
+ public class Enum16<T extends Enum<T>> extends Member {
+
+ private final T[] _values;
+
+ public Enum16(T[] values) {
+ super(16, 2);
+ _values = values;
+ }
+
+ public Enum16(T[] values, int nbrOfBits) {
+ super(nbrOfBits, 2);
+ _values = values;
+ }
+
+ public T get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getShort(index);
+ return _values[0xFFFF & get(2, word)];
+ }
+
+ public void set(T e) {
+ int value = e.ordinal();
+ if (_values[value] != e) throw new IllegalArgumentException(
+ "enum: "
+ + e
+ + ", ordinal value does not reflect enum values position");
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getShort(index);
+ getByteBuffer().putShort(index, (short) set(value, 2, word));
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 32 bits {@link Enum}.
+ */
+ public class Enum32<T extends Enum<T>> extends Member {
+
+ private final T[] _values;
+
+ public Enum32(T[] values) {
+ super(32, 4);
+ _values = values;
+ }
+
+ public Enum32(T[] values, int nbrOfBits) {
+ super(nbrOfBits, 4);
+ _values = values;
+ }
+
+ public T get() {
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getInt(index);
+ return _values[get(4, word)];
+ }
+
+ public void set(T e) {
+ int value = e.ordinal();
+ if (_values[value] != e) throw new IllegalArgumentException(
+ "enum: "
+ + e
+ + ", ordinal value does not reflect enum values position");
+ final int index = getByteBufferPosition() + offset();
+ int word = getByteBuffer().getInt(index);
+ getByteBuffer().putInt(index, set(value, 4, word));
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+
+ /**
+ * This class represents a 64 bits {@link Enum}.
+ */
+ public class Enum64<T extends Enum<T>> extends Member {
+
+ private final T[] _values;
+
+ public Enum64(T[] values) {
+ super(64, 8);
+ _values = values;
+ }
+
+ public Enum64(T[] values, int nbrOfBits) {
+ super(nbrOfBits, 8);
+ _values = values;
+ }
+
+ public T get() {
+ final int index = getByteBufferPosition() + offset();
+ long word = getByteBuffer().getLong(index);
+ return _values[(int) get(8, word)];
+ }
+
+ public void set(T e) {
+ long value = e.ordinal();
+ if (_values[(int) value] != e) throw new IllegalArgumentException(
+ "enum: "
+ + e
+ + ", ordinal value does not reflect enum values position");
+ final int index = getByteBufferPosition() + offset();
+ long word = getByteBuffer().getLong(index);
+ getByteBuffer().putLong(index, set(value, 8, word));
+ }
+
+ public String toString() {
+ return String.valueOf(this.get());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferReader.java b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferReader.java
new file mode 100644
index 0000000..5defa8c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferReader.java
@@ -0,0 +1,267 @@
+/*
+ * 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.io;
+
+import java.io.CharConversionException;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+
+/**
+ * <p> A UTF-8 <code>java.nio.ByteBuffer</code> reader.
+ * </p>
+ *
+ * <p> This reader can be used for efficient decoding of native byte
+ * buffers (e.g. <code>MappedByteBuffer</code>), high-performance
+ * messaging (no intermediate buffer), etc.</p>
+ *
+ * <p> This reader supports surrogate <code>char</code> pairs (representing
+ * characters in the range [U+10000 .. U+10FFFF]). It can also be used
+ * to read characters unicodes (31 bits) directly
+ * (ref. {@link #read()}).</p>
+ *
+ * <p> Each invocation of one of the <code>read()</code> methods may cause one
+ * or more bytes to be read from the underlying byte buffer.
+ * The end of stream is reached when the byte buffer position and limit
+ * coincide.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 2.0, December 9, 2004
+ * @see UTF8ByteBufferWriter
+ */
+public final class UTF8ByteBufferReader extends Reader {
+
+ /**
+ * Holds the byte buffer source.
+ */
+ private ByteBuffer _byteBuffer;
+
+ /**
+ * Default constructor.
+ */
+ public UTF8ByteBufferReader() {}
+
+ /**
+ * Sets the <code>ByteBuffer</code> to use for reading available bytes
+ * from current buffer position.
+ *
+ * @param byteBuffer the <code>ByteBuffer</code> source.
+ * @return this UTF-8 reader.
+ * @throws IllegalStateException if this reader is being reused and
+ * it has not been {@link #close closed} or {@link #reset reset}.
+ */
+ public UTF8ByteBufferReader setInput(ByteBuffer byteBuffer) {
+ if (_byteBuffer != null)
+ throw new IllegalStateException("Reader not closed or reset");
+ _byteBuffer = byteBuffer;
+ return this;
+ }
+
+ /**
+ * Indicates if this stream is ready to be read.
+ *
+ * @return <code>true</code> if the byte buffer has remaining bytes to
+ * read; <code>false</code> otherwise.
+ * @throws IOException if an I/O error occurs.
+ */
+ public boolean ready() throws IOException {
+ if (_byteBuffer != null) {
+ return _byteBuffer.hasRemaining();
+ } else {
+ throw new IOException("Reader closed");
+ }
+ }
+
+ /**
+ * Closes and {@link #reset resets} this reader for reuse.
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ public void close() throws IOException {
+ if (_byteBuffer != null) {
+ reset();
+ }
+ }
+
+ /**
+ * Reads a single character. This method does not block, <code>-1</code>
+ * is returned if the buffer's limit has been reached.
+ *
+ * @return the 31-bits Unicode of the character read, or -1 if there is
+ * no more remaining bytes to be read.
+ * @throws IOException if an I/O error occurs (e.g. incomplete
+ * character sequence being read).
+ */
+ public int read() throws IOException {
+ if (_byteBuffer != null) {
+ if (_byteBuffer.hasRemaining()) {
+ byte b = _byteBuffer.get();
+ return (b >= 0) ? b : read2(b);
+ } else {
+ return -1;
+ }
+ } else {
+ throw new IOException("Reader closed");
+ }
+ }
+
+ // Reads one full character, throws CharConversionException if limit reached.
+ private int read2(byte b) throws IOException {
+ try {
+ // Decodes UTF-8.
+ if ((b >= 0) && (_moreBytes == 0)) {
+ // 0xxxxxxx
+ return b;
+ } else if (((b & 0xc0) == 0x80) && (_moreBytes != 0)) {
+ // 10xxxxxx (continuation byte)
+ _code = (_code << 6) | (b & 0x3f); // Adds 6 bits to code.
+ if (--_moreBytes == 0) {
+ return _code;
+ } else {
+ return read2(_byteBuffer.get());
+ }
+ } else if (((b & 0xe0) == 0xc0) && (_moreBytes == 0)) {
+ // 110xxxxx
+ _code = b & 0x1f;
+ _moreBytes = 1;
+ return read2(_byteBuffer.get());
+ } else if (((b & 0xf0) == 0xe0) && (_moreBytes == 0)) {
+ // 1110xxxx
+ _code = b & 0x0f;
+ _moreBytes = 2;
+ return read2(_byteBuffer.get());
+ } else if (((b & 0xf8) == 0xf0) && (_moreBytes == 0)) {
+ // 11110xxx
+ _code = b & 0x07;
+ _moreBytes = 3;
+ return read2(_byteBuffer.get());
+ } else if (((b & 0xfc) == 0xf8) && (_moreBytes == 0)) {
+ // 111110xx
+ _code = b & 0x03;
+ _moreBytes = 4;
+ return read2(_byteBuffer.get());
+ } else if (((b & 0xfe) == 0xfc) && (_moreBytes == 0)) {
+ // 1111110x
+ _code = b & 0x01;
+ _moreBytes = 5;
+ return read2(_byteBuffer.get());
+ } else {
+ throw new CharConversionException("Invalid UTF-8 Encoding");
+ }
+ } catch (BufferUnderflowException e) {
+ throw new CharConversionException("Incomplete Sequence");
+ }
+ }
+
+ private int _code;
+
+ private int _moreBytes;
+
+ /**
+ * Reads characters into a portion of an array. This method does not
+ * block.
+ *
+ * <p> Note: Characters between U+10000 and U+10FFFF are represented
+ * by surrogate pairs (two <code>char</code>).</p>
+ *
+ * @param cbuf the destination buffer.
+ * @param off the offset at which to start storing characters.
+ * @param len the maximum number of characters to read
+ * @return the number of characters read, or -1 if there is no more
+ * byte remaining.
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read(char cbuf[], int off, int len) throws IOException {
+ if (_byteBuffer == null)
+ throw new IOException("Reader closed");
+ final int off_plus_len = off + len;
+ int remaining = _byteBuffer.remaining();
+ if (remaining <= 0)
+ return -1;
+ for (int i = off; i < off_plus_len;) {
+ if (remaining-- > 0) {
+ byte b = _byteBuffer.get();
+ if (b >= 0) {
+ cbuf[i++] = (char) b; // Most common case.
+ } else {
+ if (i < off_plus_len - 1) { // Up to two 'char' can be read.
+ int code = read2(b);
+ remaining = _byteBuffer.remaining(); // Recalculates.
+ if (code < 0x10000) {
+ cbuf[i++] = (char) code;
+ } else if (code <= 0x10ffff) { // Surrogates.
+ cbuf[i++] = (char) (((code - 0x10000) >> 10) + 0xd800);
+ cbuf[i++] = (char) (((code - 0x10000) & 0x3ff) + 0xdc00);
+ } else {
+ throw new CharConversionException(
+ "Cannot convert U+"
+ + Integer.toHexString(code)
+ + " to char (code greater than U+10FFFF)");
+ }
+ } else { // Not enough space in destination (go back).
+ _byteBuffer.position(_byteBuffer.position() - 1);
+ remaining++;
+ return i - off;
+ }
+ }
+ } else {
+ return i - off;
+ }
+ }
+ return len;
+ }
+
+ /**
+ * Reads characters into the specified appendable. This method does not
+ * block.
+ *
+ * <p> Note: Characters between U+10000 and U+10FFFF are represented
+ * by surrogate pairs (two <code>char</code>).</p>
+ *
+ * @param dest the destination buffer.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void read(Appendable dest) throws IOException {
+ if (_byteBuffer == null)
+ throw new IOException("Reader closed");
+ while (_byteBuffer.hasRemaining()) {
+ byte b = _byteBuffer.get();
+ if (b >= 0) {
+ dest.append((char) b); // Most common case.
+ } else {
+ int code = read2(b);
+ if (code < 0x10000) {
+ dest.append((char) code);
+ } else if (code <= 0x10ffff) { // Surrogates.
+ dest.append((char) (((code - 0x10000) >> 10) + 0xd800));
+ dest.append((char) (((code - 0x10000) & 0x3ff) + 0xdc00));
+ } else {
+ throw new CharConversionException("Cannot convert U+"
+ + Integer.toHexString(code)
+ + " to char (code greater than U+10FFFF)");
+ }
+ }
+ }
+ }
+
+ public void reset() {
+ _byteBuffer = null;
+ _code = 0;
+ _moreBytes = 0;
+ }
+
+ /**
+ * @deprecated Replaced by {@link #setInput(ByteBuffer)}
+ */
+ public UTF8ByteBufferReader setByteBuffer(ByteBuffer byteBuffer) {
+ return this.setInput(byteBuffer);
+ }
+
+}
\ 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/io/UTF8ByteBufferWriter.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferWriter.java b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferWriter.java
new file mode 100644
index 0000000..5765c41
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8ByteBufferWriter.java
@@ -0,0 +1,224 @@
+/*
+ * 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.io;
+
+import java.io.CharConversionException;
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+
+/**
+ * <p> A UTF-8 <code>java.nio.ByteBuffer</code> writer.</p>
+ *
+ * <p> This writer supports surrogate <code>char</code> pairs (representing
+ * characters in the range [U+10000 .. U+10FFFF]). It can also be used
+ * to write characters from their unicodes (31 bits) directly
+ * (ref. {@link #write(int)}).</p>
+ *
+ * <p> Instances of this class can be reused for different output streams
+ * and can be part of a higher level component (e.g. serializer) in order
+ * to avoid dynamic buffer allocation when the destination output changes.
+ * Also wrapping using a <code>java.io.BufferedWriter</code> is unnescessary
+ * as instances of this class embed their own data buffers.</p>
+ *
+ * <p> Note: This writer is unsynchronized and always produces well-formed
+ * UTF-8 sequences.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 2.0, December 9, 2004
+ * @see UTF8ByteBufferReader
+ */
+public final class UTF8ByteBufferWriter extends Writer {
+
+ /**
+ * Holds the byte buffer destination.
+ */
+ private ByteBuffer _byteBuffer;
+
+ /**
+ * Default constructor.
+ */
+ public UTF8ByteBufferWriter() {}
+
+ /**
+ * Sets the byte buffer to use for writing until this writer is closed.
+ *
+ * @param byteBuffer the destination byte buffer.
+ * @return this UTF-8 writer.
+ * @throws IllegalStateException if this writer is being reused and
+ * it has not been {@link #close closed} or {@link #reset reset}.
+ */
+ public UTF8ByteBufferWriter setOutput(ByteBuffer byteBuffer) {
+ if (_byteBuffer != null)
+ throw new IllegalStateException("Writer not closed or reset");
+ _byteBuffer = byteBuffer;
+ return this;
+ }
+
+ /**
+ * Writes a single character. This method supports 16-bits
+ * character surrogates.
+ *
+ * @param c <code>char</code> the character to be written (possibly
+ * a surrogate).
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(char c) throws IOException {
+ if ((c < 0xd800) || (c > 0xdfff)) {
+ write((int) c);
+ } else if (c < 0xdc00) { // High surrogate.
+ _highSurrogate = c;
+ } else { // Low surrogate.
+ int code = ((_highSurrogate - 0xd800) << 10) + (c - 0xdc00)
+ + 0x10000;
+ write(code);
+ }
+ }
+
+ private char _highSurrogate;
+
+ /**
+ * Writes a character given its 31-bits Unicode.
+ *
+ * @param code the 31 bits Unicode of the character to be written.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(int code) throws IOException {
+ if ((code & 0xffffff80) == 0) {
+ _byteBuffer.put((byte) code);
+ } else { // Writes more than one byte.
+ write2(code);
+ }
+ }
+
+ private void write2(int c) throws IOException {
+ if ((c & 0xfffff800) == 0) { // 2 bytes.
+ _byteBuffer.put((byte) (0xc0 | (c >> 6)));
+ _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
+ } else if ((c & 0xffff0000) == 0) { // 3 bytes.
+ _byteBuffer.put((byte) (0xe0 | (c >> 12)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
+ } else if ((c & 0xff200000) == 0) { // 4 bytes.
+ _byteBuffer.put((byte) (0xf0 | (c >> 18)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 12) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
+ } else if ((c & 0xf4000000) == 0) { // 5 bytes.
+ _byteBuffer.put((byte) (0xf8 | (c >> 24)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 18) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 12) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
+ } else if ((c & 0x80000000) == 0) { // 6 bytes.
+ _byteBuffer.put((byte) (0xfc | (c >> 30)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 24) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 18) & 0x3f)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 12) & 0x3F)));
+ _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3F)));
+ _byteBuffer.put((byte) (0x80 | (c & 0x3F)));
+ } else {
+ throw new CharConversionException("Illegal character U+"
+ + Integer.toHexString(c));
+ }
+ }
+
+ /**
+ * Writes a portion of an array of characters.
+ *
+ * @param cbuf the array of characters.
+ * @param off the offset from which to start writing characters.
+ * @param len the number of characters to write.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(char cbuf[], int off, int len) throws IOException {
+ final int off_plus_len = off + len;
+ for (int i = off; i < off_plus_len;) {
+ char c = cbuf[i++];
+ if (c < 0x80) {
+ _byteBuffer.put((byte) c);
+ } else {
+ write(c);
+ }
+ }
+ }
+
+ /**
+ * Writes a portion of a string.
+ *
+ * @param str a String.
+ * @param off the offset from which to start writing characters.
+ * @param len the number of characters to write.
+ * @throws IOException if an I/O error occurs
+ */
+ public void write(String str, int off, int len) throws IOException {
+ final int off_plus_len = off + len;
+ for (int i = off; i < off_plus_len;) {
+ char c = str.charAt(i++);
+ if (c < 0x80) {
+ _byteBuffer.put((byte) c);
+ } else {
+ write(c);
+ }
+ }
+ }
+
+ /**
+ * Writes the specified character sequence.
+ *
+ * @param csq the character sequence.
+ * @throws IOException if an I/O error occurs
+ */
+ public void write(CharSequence csq) throws IOException {
+ final int length = csq.length();
+ for (int i = 0; i < length;) {
+ char c = csq.charAt(i++);
+ if (c < 0x80) {
+ _byteBuffer.put((byte) c);
+ } else {
+ write(c);
+ }
+ }
+ }
+
+ /**
+ * Flushes the stream (this method has no effect, the data is
+ * always directly written to the <code>ByteBuffer</code>).
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ public void flush() throws IOException {
+ if (_byteBuffer == null) { throw new IOException("Writer closed"); }
+ }
+
+ /**
+ * Closes and {@link #reset resets} this writer for reuse.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ public void close() throws IOException {
+ if (_byteBuffer != null) {
+ reset();
+ }
+ }
+
+ // Implements Reusable.
+ public void reset() {
+ _byteBuffer = null;
+ _highSurrogate = 0;
+ }
+
+ /**
+ * @deprecated Replaced by {@link #setOutput(ByteBuffer)}
+ */
+ public UTF8ByteBufferWriter setByteBuffer(ByteBuffer byteBuffer) {
+ return this.setOutput(byteBuffer);
+ }
+
+}
\ No newline at end of file
[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)
Posted by ss...@apache.org.
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;
+ }
+
+}
[08/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ReversedCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ReversedCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ReversedCollectionImpl.java
new file mode 100644
index 0000000..4eef132
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ReversedCollectionImpl.java
@@ -0,0 +1,98 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * A reversed view over a collection.
+ */
+public class ReversedCollectionImpl<E> extends CollectionView<E> {
+
+ /** Reversing Iterator. */
+ private class IteratorImpl implements Iterator<E> {
+
+ @SuppressWarnings("unchecked")
+ private final E[] elements = (E[]) new Object[size()];
+ private int index = 0;
+
+ public IteratorImpl() {
+ Iterator<E> it = target().iterator();
+ while (it.hasNext() && (index < elements.length)) {
+ elements[index++] = it.next();
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index > 0;
+ }
+
+ @Override
+ public E next() {
+ return elements[--index];
+ }
+
+ @Override
+ public void remove() {
+ target().remove(elements[index]);
+ }
+
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public ReversedCollectionImpl(CollectionService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean add(E e) {
+ return target().add(e);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public boolean contains(Object obj) {
+ return target().contains(obj);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public boolean remove(Object obj) {
+ return target().remove(obj);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SequentialCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SequentialCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SequentialCollectionImpl.java
new file mode 100644
index 0000000..5b7ff6f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SequentialCollectionImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * A sequential view over a collection.
+ */
+public class SequentialCollectionImpl<E> extends CollectionView<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SequentialCollectionImpl(CollectionService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean add(E e) {
+ return target().add(e);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public boolean contains(Object obj) {
+ return target().contains(obj);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return target().iterator();
+ }
+
+ @Override
+ public void perform(Consumer<CollectionService<E>> action, CollectionService<E> view) {
+ action.accept(view); // Executes immediately.
+ }
+
+ @Override
+ public boolean remove(Object obj) {
+ return target().remove(obj);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @Override
+ public CollectionService<E>[] split(int n, boolean threadsafe) {
+ return target().split(n, threadsafe); // Forwards.
+ }
+
+ @Override
+ public void update(Consumer<CollectionService<E>> action, CollectionService<E> view) {
+ action.accept(view); // Executes immediately.
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SharedCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SharedCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SharedCollectionImpl.java
new file mode 100644
index 0000000..74ff05c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SharedCollectionImpl.java
@@ -0,0 +1,270 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.internal.ReadWriteLockImpl;
+import javolution.util.service.CollectionService;
+
+/**
+ * A shared view over a collection (reads-write locks).
+ */
+public class SharedCollectionImpl<E> extends CollectionView<E> {
+
+ /** Thread-Safe Iterator. */
+ private class IteratorImpl implements Iterator<E> { // Thread-Safe.
+ private E next;
+ private final Iterator<E> targetIterator;
+
+ public IteratorImpl() {
+ lock.readLock.lock();
+ try {
+ targetIterator = cloneTarget().iterator(); // Copy.
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public E next() {
+ next = targetIterator.next();
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ if (next == null) throw new IllegalStateException();
+ SharedCollectionImpl.this.remove(next);
+ next = null;
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected ReadWriteLockImpl lock;
+
+ public SharedCollectionImpl(CollectionService<E> target) {
+ this(target, new ReadWriteLockImpl());
+ }
+
+ public SharedCollectionImpl(CollectionService<E> target,
+ ReadWriteLockImpl lock) {
+ super(target);
+ this.lock = lock;
+ }
+
+ @Override
+ public boolean add(E element) {
+ lock.writeLock.lock();
+ try {
+ return target().add(element);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ lock.writeLock.lock();
+ try {
+ return target().addAll(c);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public void clear() {
+ lock.writeLock.lock();
+ try {
+ target().clear();
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public SharedCollectionImpl<E> clone() {
+ lock.readLock.lock();
+ try {
+ SharedCollectionImpl<E> copy = (SharedCollectionImpl<E>) super
+ .clone();
+ copy.lock = new ReadWriteLockImpl(); // No need to share the same lock.
+ return copy;
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ lock.readLock.lock();
+ try {
+ return target().contains(o);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ lock.readLock.lock();
+ try {
+ return target().containsAll(c);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ lock.readLock.lock();
+ try {
+ return target().equals(o);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ lock.readLock.lock();
+ try {
+ return target().hashCode();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ lock.readLock.lock();
+ try {
+ return target().isEmpty();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public void perform(Consumer<CollectionService<E>> action,
+ CollectionService<E> view) {
+ lock.readLock.lock();
+ try {
+ target().perform(action, view);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ lock.writeLock.lock();
+ try {
+ return target().remove(o);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ lock.writeLock.lock();
+ try {
+ return target().removeAll(c);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ lock.writeLock.lock();
+ try {
+ return target().retainAll(c);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public int size() {
+ lock.readLock.lock();
+ try {
+ return target().size();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public CollectionService<E>[] split(int n, boolean updateable) {
+ CollectionService<E>[] tmp;
+ lock.readLock.lock();
+ try {
+ tmp = target().split(n, updateable);
+ } finally {
+ lock.readLock.unlock();
+ }
+ CollectionService<E>[] result = new CollectionService[tmp.length];
+ for (int i = 0; i < tmp.length; i++) {
+ result[i] = new SharedCollectionImpl<E>(tmp[i], lock); // Shares the same locks.
+ }
+ return result;
+ }
+
+ @Override
+ public Object[] toArray() {
+ lock.readLock.lock();
+ try {
+ return target().toArray();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ lock.readLock.lock();
+ try {
+ return target().toArray(a);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ /** Returns a clone copy of target. */
+ protected CollectionService<E> cloneTarget() {
+ try {
+ return target().clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Cannot happen since target is Cloneable.");
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SortedCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SortedCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SortedCollectionImpl.java
new file mode 100644
index 0000000..6f35d53
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/SortedCollectionImpl.java
@@ -0,0 +1,109 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import javolution.util.FastTable;
+import javolution.util.function.Equality;
+import javolution.util.internal.comparator.WrapperComparatorImpl;
+import javolution.util.service.CollectionService;
+
+/**
+ * A sorted view over a collection.
+ */
+public class SortedCollectionImpl<E> extends CollectionView<E> {
+
+ /** Sorting Iterator. */
+ private class IteratorImpl implements Iterator<E> {
+ private final Iterator<E> iterator;
+ private E next;
+
+ public IteratorImpl() {
+ FastTable<E> sorted = new FastTable<E>(comparator);
+ Iterator<E> it = target().iterator();
+ while (it.hasNext()) {
+ sorted.add(it.next());
+ }
+ sorted.sort();
+ iterator = sorted.iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public E next() {
+ next = iterator.next();
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ if (next == null) throw new IllegalStateException();
+ target().remove(next);
+ next = null;
+ }
+
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected final Equality<E> comparator;
+
+ @SuppressWarnings("unchecked")
+ public SortedCollectionImpl(CollectionService<E> target, Comparator<? super E> comparator) {
+ super(target);
+ this.comparator = (comparator instanceof Equality) ?
+ (Equality<E>) comparator : new WrapperComparatorImpl<E>(comparator);
+ }
+
+ @Override
+ public boolean add(E e) {
+ return target().add(e);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return comparator;
+ }
+
+ @Override
+ public boolean contains(Object obj) {
+ return target().contains(obj);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public boolean remove(Object obj) {
+ return target().remove(obj);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/UnmodifiableCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/UnmodifiableCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/UnmodifiableCollectionImpl.java
new file mode 100644
index 0000000..d6b0481
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/UnmodifiableCollectionImpl.java
@@ -0,0 +1,98 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * An unmodifiable view over a collection.
+ */
+public class UnmodifiableCollectionImpl<E> extends CollectionView<E> {
+
+ /** Read-Only Iterator. */
+ private class IteratorImpl implements Iterator<E> {
+ private final Iterator<E> targetIterator = target().iterator();
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public E next() {
+ return targetIterator.next();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableCollectionImpl(CollectionService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean add(E element) {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public boolean contains(Object obj) {
+ return target().contains(obj);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException("Read-Only Collection.");
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public CollectionService<E>[] split(int n, boolean updateable) {
+ CollectionService<E>[] subTargets = target().split(n, updateable);
+ CollectionService<E>[] result = new CollectionService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new UnmodifiableCollectionImpl<E>(subTargets[i]);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/ArrayComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/ArrayComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/ArrayComparatorImpl.java
new file mode 100644
index 0000000..fc1afbf
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/ArrayComparatorImpl.java
@@ -0,0 +1,72 @@
+/*
+ * 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.internal.comparator;
+
+import java.util.Arrays;
+
+/**
+ * The array comparator implementation.
+ */
+public class ArrayComparatorImpl extends StandardComparatorImpl<Object> {
+
+ private static final long serialVersionUID = 4134048629840904441L;
+
+ @Override
+ public boolean areEqual(Object array1, Object array2) {
+ if (array1 == array2)
+ return true;
+ if ((array1 == null) || (array2 == null))
+ return false;
+ if (array1 instanceof Object[] && array2 instanceof Object[])
+ return Arrays.deepEquals((Object[]) array1, (Object[]) array2);
+ if (array1 instanceof byte[] && array2 instanceof byte[])
+ return Arrays.equals((byte[]) array1, (byte[]) array2);
+ if (array1 instanceof short[] && array2 instanceof short[])
+ return Arrays.equals((short[]) array1, (short[]) array2);
+ if (array1 instanceof int[] && array2 instanceof int[])
+ return Arrays.equals((int[]) array1, (int[]) array2);
+ if (array1 instanceof long[] && array2 instanceof long[])
+ return Arrays.equals((long[]) array1, (long[]) array2);
+ if (array1 instanceof char[] && array2 instanceof char[])
+ return Arrays.equals((char[]) array1, (char[]) array2);
+ if (array1 instanceof float[] && array2 instanceof float[])
+ return Arrays.equals((float[]) array1, (float[]) array2);
+ if (array1 instanceof double[] && array2 instanceof double[])
+ return Arrays.equals((double[]) array1, (double[]) array2);
+ if (array1 instanceof boolean[] && array2 instanceof boolean[])
+ return Arrays.equals((boolean[]) array1, (boolean[]) array2);
+ return array1.equals(array2);
+ }
+
+ @Override
+ public int hashCodeOf(Object array) {
+ if (array instanceof Object[])
+ return Arrays.deepHashCode((Object[]) array);
+ if (array instanceof byte[])
+ return Arrays.hashCode((byte[]) array);
+ if (array instanceof short[])
+ return Arrays.hashCode((short[]) array);
+ if (array instanceof int[])
+ return Arrays.hashCode((int[]) array);
+ if (array instanceof long[])
+ return Arrays.hashCode((long[]) array);
+ if (array instanceof char[])
+ return Arrays.hashCode((char[]) array);
+ if (array instanceof float[])
+ return Arrays.hashCode((float[]) array);
+ if (array instanceof double[])
+ return Arrays.hashCode((double[]) array);
+ if (array instanceof boolean[])
+ return Arrays.hashCode((boolean[]) array);
+ if (array != null)
+ return array.hashCode();
+ return 0;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/IdentityComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/IdentityComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/IdentityComparatorImpl.java
new file mode 100644
index 0000000..bbc94ea
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/IdentityComparatorImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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.internal.comparator;
+
+import javolution.util.function.Equality;
+
+/**
+ * The identity comparator implementation.
+ */
+public class IdentityComparatorImpl<E> implements Equality<E> {
+
+ private static final long serialVersionUID = 6576306094743751922L;
+
+ @Override
+ public boolean areEqual(E e1, E e2) {
+ return e1 == e2;
+ }
+
+ @Override
+ public int compare(E left, E right) {
+ if (left == right)
+ return 0;
+ if (left == null)
+ return -1;
+ if (right == null)
+ return 1;
+
+ // Empirical comparison.
+ return (hashCodeOf(left) < hashCodeOf(right)) ? -1 : 1;
+ }
+
+ @Override
+ public int hashCodeOf(E obj) {
+ return System.identityHashCode(obj);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalCaseInsensitiveComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalCaseInsensitiveComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalCaseInsensitiveComparatorImpl.java
new file mode 100644
index 0000000..c391d6e
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalCaseInsensitiveComparatorImpl.java
@@ -0,0 +1,73 @@
+/*
+ * 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.internal.comparator;
+
+import javolution.util.function.Equality;
+
+/**
+ * The case insensitive lexical comparator implementation.
+ */
+public class LexicalCaseInsensitiveComparatorImpl implements
+ Equality<CharSequence> {
+
+ private static final long serialVersionUID = -1046672327934410697L;
+
+ // Converts to upper case.
+ private static char up(char c) {
+ return Character.toUpperCase(c);
+ }
+
+ @Override
+ public boolean areEqual(CharSequence csq1, CharSequence csq2) {
+ if (csq1 == csq2)
+ return true;
+ if ((csq1 == null) || (csq2 == null))
+ return false;
+ if ((csq1 instanceof String) && (csq2 instanceof String)) // Optimization.
+ return ((String) csq1).equalsIgnoreCase((String) csq2);
+ int n = csq1.length();
+ if (csq2.length() != n)
+ return false;
+ for (int i = 0; i < n;) {
+ if (up(csq1.charAt(i)) != up(csq2.charAt(i++)))
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compare(CharSequence left, CharSequence right) {
+ if (left == null)
+ return -1;
+ if (right == null)
+ return 1;
+ if ((left instanceof String) && (right instanceof String)) // Optimization.
+ return ((String) left).compareToIgnoreCase((String) right);
+ int i = 0;
+ int n = Math.min(left.length(), right.length());
+ while (n-- != 0) {
+ char c1 = up(left.charAt(i));
+ char c2 = up(right.charAt(i++));
+ if (c1 != c2)
+ return c1 - c2;
+ }
+ return left.length() - right.length();
+ }
+
+ @Override
+ public int hashCodeOf(CharSequence csq) {
+ if (csq == null)
+ return 0;
+ int h = 0;
+ for (int i = 0, n = csq.length(); i < n;) {
+ h = 31 * h + up(csq.charAt(i++));
+ }
+ return h;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalComparatorImpl.java
new file mode 100644
index 0000000..9516331
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalComparatorImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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.internal.comparator;
+
+import javolution.lang.MathLib;
+import javolution.util.function.Equality;
+
+/**
+ * The lexical comparator implementation (optimized for String).
+ */
+public class LexicalComparatorImpl implements Equality<CharSequence> {
+
+ private static final long serialVersionUID = 7904852144917623728L;
+
+ @Override
+ public boolean areEqual(CharSequence csq1, CharSequence csq2) {
+ if (csq1 == csq2)
+ return true;
+ if ((csq1 == null) || (csq2 == null))
+ return false;
+ if (csq1 instanceof String) { // Optimization.
+ if (csq2 instanceof String)
+ return csq1.equals(csq2);
+ return ((String) csq1).contentEquals(csq2);
+ } else if (csq2 instanceof String) { return ((String) csq2)
+ .contentEquals(csq1); }
+
+ // None of the CharSequence is a String.
+ int n = csq1.length();
+ if (csq2.length() != n)
+ return false;
+ for (int i = 0; i < n;) {
+ if (csq1.charAt(i) != csq2.charAt(i++))
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compare(CharSequence left, CharSequence right) {
+ if (left == null)
+ return -1;
+ if (right == null)
+ return 1;
+ if ((left instanceof String) && (right instanceof String)) // Optimization.
+ return ((String) left).compareTo((String) right);
+ int i = 0;
+ int n = MathLib.min(left.length(), right.length());
+ while (n-- != 0) {
+ char c1 = left.charAt(i);
+ char c2 = right.charAt(i++);
+ if (c1 != c2)
+ return c1 - c2;
+ }
+ return left.length() - right.length();
+ }
+
+ @Override
+ public int hashCodeOf(CharSequence csq) {
+ if (csq == null)
+ return 0;
+ if (csq instanceof String) // Optimization.
+ return csq.hashCode();
+ int h = 0;
+ for (int i = 0, n = csq.length(); i < n;) {
+ h = 31 * h + csq.charAt(i++);
+ }
+ return h;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalFastComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalFastComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalFastComparatorImpl.java
new file mode 100644
index 0000000..885bb22
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/LexicalFastComparatorImpl.java
@@ -0,0 +1,30 @@
+/*
+ * 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.internal.comparator;
+
+/**
+ * The high-performance lexical comparator.
+ */
+public class LexicalFastComparatorImpl extends LexicalComparatorImpl {
+
+ private static final long serialVersionUID = -1449702752185594025L;
+
+ @Override
+ public int hashCodeOf(CharSequence csq) {
+ if (csq == null)
+ return 0;
+ int n = csq.length();
+ if (n == 0)
+ return 0;
+ // Hash based on 5 characters only.
+ return csq.charAt(0) + csq.charAt(n - 1) * 31 + csq.charAt(n >> 1)
+ * 1009 + csq.charAt(n >> 2) * 27583
+ + csq.charAt(n - 1 - (n >> 2)) * 73408859;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/StandardComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/StandardComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/StandardComparatorImpl.java
new file mode 100644
index 0000000..c92f98a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/StandardComparatorImpl.java
@@ -0,0 +1,48 @@
+/*
+ * 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.internal.comparator;
+
+import javolution.util.function.Equality;
+
+/**
+ * The standard comparator implementation.
+ */
+public class StandardComparatorImpl<E> implements Equality<E> {
+
+ private static final long serialVersionUID = -615690677813206151L;
+
+ @Override
+ public boolean areEqual(E e1, E e2) {
+ return (e1 == e2) || (e1 != null && e1.equals(e2));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int compare(E left, E right) {
+ if (left == right)
+ return 0;
+ if (left == null)
+ return -1;
+ if (right == null)
+ return 1;
+ if (left instanceof Comparable)
+ return ((Comparable<E>) left).compareTo(right);
+
+ // Empirical method (consistent with equals).
+ if (left.equals(right))
+ return 0;
+ return left.hashCode() < right.hashCode() ? -1 : 1;
+ }
+
+ @Override
+ public int hashCodeOf(E e) {
+ return (e == null) ? 0 : e.hashCode();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/WrapperComparatorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/WrapperComparatorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/WrapperComparatorImpl.java
new file mode 100644
index 0000000..5578107
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/comparator/WrapperComparatorImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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.internal.comparator;
+
+import java.util.Comparator;
+
+import javolution.util.function.Equality;
+
+/**
+ * A comparator service wrapping a {@ link Comparator}, since
+ * consistency with hashcode cannot be maintained. The hashcode
+ * calculation method throws UnsupportedOperationException.
+ */
+public final class WrapperComparatorImpl<E> implements Equality<E> {
+
+ private static final long serialVersionUID = 8775282553794347279L;
+ private final Comparator<? super E> comparator;
+
+ public WrapperComparatorImpl(Comparator<? super E> comparator) {
+ this.comparator = comparator;
+ }
+
+ @Override
+ public boolean areEqual(E e1, E e2) {
+ return (e1 == e2) || (e1 != null && (comparator.compare(e1, e2) == 0));
+ }
+
+ @Override
+ public int compare(E left, E right) {
+ if (left == right)
+ return 0;
+ if (left == null)
+ return -1;
+ if (right == null)
+ return 1;
+ return comparator.compare(left, right);
+ }
+
+ @Override
+ public int hashCodeOf(E obj) {
+ throw new UnsupportedOperationException(
+ "Standard comparator (java.util.Comparator) cannot be used for "
+ + "hashcode calculations; please use a coherent equality comparator "
+ + "instead (e.g. javolution.util.function.Equality).");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/AtomicMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/AtomicMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/AtomicMapImpl.java
new file mode 100644
index 0000000..988b677
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/AtomicMapImpl.java
@@ -0,0 +1,192 @@
+/*
+ * 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.internal.map;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.service.MapService;
+
+/**
+ * An atomic view over a map (copy-on-write).
+ */
+public class AtomicMapImpl<K, V> extends MapView<K, V> {
+
+ /** Thread-Safe Iterator. */
+ private class IteratorImpl implements Iterator<Entry<K, V>> {
+ private Entry<K, V> current;
+ private final Iterator<Entry<K, V>> targetIterator = targetView().iterator();
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public Entry<K, V> next() {
+ current = targetIterator.next();
+ return current;
+ }
+
+ @Override
+ public void remove() {
+ if (current == null) throw new IllegalStateException();
+ AtomicMapImpl.this.remove(current.getKey());
+ current = null;
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected volatile MapService<K, V> immutable; // The copy used by readers.
+ protected transient Thread updatingThread; // The thread executing an update.
+
+ public AtomicMapImpl(MapService<K, V> target) {
+ super(target);
+ this.immutable = cloneTarget();
+ }
+
+ @Override
+ public synchronized void clear() {
+ clear();
+ if (!updateInProgress()) {
+ immutable = cloneTarget();
+ }
+ }
+
+ @Override
+ public synchronized AtomicMapImpl<K, V> clone() {
+ AtomicMapImpl<K, V> copy = (AtomicMapImpl<K, V>) super.clone();
+ copy.updatingThread = null;
+ return copy;
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return targetView().containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return targetView().containsValue(value);
+ }
+
+ @Override
+ public V get(Object key) {
+ return targetView().get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return targetView().isEmpty();
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return targetView().keyComparator();
+ }
+
+ @Override
+ public synchronized V put(K key, V value) {
+ V v = target().put(key, value);
+ if (!updateInProgress()) immutable = cloneTarget();
+ return v;
+ }
+
+ @Override
+ public synchronized void putAll(Map<? extends K, ? extends V> m) {
+ target().putAll(m);
+ if (!updateInProgress()) immutable = cloneTarget();
+ }
+
+ @Override
+ public synchronized V putIfAbsent(K key, V value) {
+ V v = target().putIfAbsent(key, value);
+ if (!updateInProgress()) immutable = cloneTarget();
+ return v;
+ }
+
+ @Override
+ public synchronized V remove(Object key) {
+ V v = target().remove(key);
+ if (!updateInProgress()) immutable = cloneTarget();
+ return v;
+ }
+
+ @Override
+ public synchronized boolean remove(Object key, Object value) {
+ boolean changed = target().remove(key, value);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized V replace(K key, V value) {
+ V v = target().replace(key, value);
+ if (!updateInProgress()) immutable = cloneTarget();
+ return v;
+ }
+
+ @Override
+ public synchronized boolean replace(K key, V oldValue, V newValue) {
+ boolean changed = target().replace(key, oldValue, newValue);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public int size() {
+ return targetView().size();
+ }
+
+ @Override
+ public synchronized void update(Consumer<MapService<K, V>> action,
+ MapService<K, V> view) {
+ updatingThread = Thread.currentThread(); // Update in progress.
+ try {
+ target().update(action, view); // No copy performed.
+ } finally {
+ updatingThread = null;
+ immutable = cloneTarget(); // One single copy !
+ }
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return targetView().valueComparator();
+ }
+
+ /** Returns a clone copy of target. */
+ protected MapService<K, V> cloneTarget() {
+ try {
+ return target().clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Cannot happen since target is Cloneable.");
+ }
+ }
+
+ /** Returns either the immutable target or the actual target if updating
+ * thread. */
+ protected MapService<K, V> targetView() {
+ return ((updatingThread == null) || (updatingThread != Thread.currentThread()))
+ ? immutable : target();
+ }
+
+
+ /** Indicates if the current thread is doing an atomic update. */
+ protected final boolean updateInProgress() {
+ return updatingThread == Thread.currentThread();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FastMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FastMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FastMapImpl.java
new file mode 100644
index 0000000..7676647
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FastMapImpl.java
@@ -0,0 +1,250 @@
+/*
+ * 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.internal.map;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.function.Equality;
+
+/**
+ * The default {@link javolution.util.FastMap FastMap} implementation
+ * based on {@link FractalMapImpl fractal maps}.
+ * This implementation ensures that no more than 3/4 of the map capacity is
+ * ever wasted.
+ */
+public class FastMapImpl<K, V> extends MapView<K, V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ transient MapEntryImpl<K, V> firstEntry = null;
+ transient FractalMapImpl fractal = new FractalMapImpl();
+ transient MapEntryImpl<K, V> freeEntry = new MapEntryImpl<K, V>();
+ final Equality<? super K> keyComparator;
+ transient MapEntryImpl<K, V> lastEntry = null;
+ transient int size;
+ final Equality<? super V> valueComparator;
+
+ public FastMapImpl(Equality<? super K> keyComparator,
+ final Equality<? super V> valueComparator) {
+ super(null); // Root.
+ this.keyComparator = keyComparator;
+ this.valueComparator = valueComparator;
+ }
+
+ @Override
+ public void clear() {
+ firstEntry = null;
+ lastEntry = null;
+ fractal = new FractalMapImpl();
+ size = 0;
+ }
+
+ @Override
+ public FastMapImpl<K, V> clone() { // Makes a copy.
+ FastMapImpl<K, V> copy = new FastMapImpl<K, V>(keyComparator(),
+ valueComparator());
+ copy.putAll(this);
+ return copy;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsKey(Object key) {
+ return fractal.getEntry(key, keyComparator.hashCodeOf((K) key), keyComparator) != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(Object key) {
+ MapEntryImpl<K, V> entry = fractal.getEntry(key,
+ keyComparator.hashCodeOf((K) key), keyComparator);
+ if (entry == null) return null;
+ return entry.value;
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new Iterator<Entry<K, V>>() {
+ MapEntryImpl<K, V> current;
+ MapEntryImpl<K, V> next = firstEntry;
+
+ @Override
+ public boolean hasNext() {
+ return (next != null);
+ }
+
+ @Override
+ public java.util.Map.Entry<K, V> next() {
+ if (next == null) throw new NoSuchElementException();
+ current = next;
+ next = next.next;
+ return current;
+ }
+
+ @Override
+ public void remove() {
+ if (current == null) throw new IllegalStateException();
+ fractal.removeEntry(current.key, current.hash, keyComparator);
+ detachEntry(current); // Entry is not referenced anymore and will be gc.
+ size--;
+ }
+ };
+
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return keyComparator;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V put(K key, V value) {
+ int hash = keyComparator.hashCodeOf(key);
+ MapEntryImpl<K, V> tmp = fractal.addEntry(freeEntry, key, hash, keyComparator);
+ if (tmp == freeEntry) { // New entry.
+ freeEntry = new MapEntryImpl<K, V>();
+ attachEntry(tmp);
+ size++;
+ tmp.value = value;
+ return null;
+ } else { // Existing entry.
+ V oldValue = (V) tmp.value;
+ tmp.value = value;
+ return oldValue;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V putIfAbsent(K key, V value) {
+ int hash = keyComparator.hashCodeOf(key);
+ MapEntryImpl<K, V> tmp = fractal.addEntry(freeEntry, key, hash, keyComparator);
+ if (tmp == freeEntry) { // New entry.
+ freeEntry = new MapEntryImpl<K, V>();
+ attachEntry(tmp);
+ size++;
+ tmp.value = value;
+ return null;
+ } else { // Existing entry.
+ return (V) tmp.value;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V remove(Object key) {
+ MapEntryImpl<K, V> entry = fractal.removeEntry(key,
+ keyComparator.hashCodeOf((K) key), keyComparator);
+ if (entry == null) return null;
+ detachEntry(entry); // Entry is not referenced anymore and will be gc.
+ size--;
+ return entry.value;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean remove(Object key, Object value) {
+ int hash = keyComparator.hashCodeOf((K) key);
+ MapEntryImpl<K, V> entry = fractal.getEntry(key, hash, keyComparator);
+ if (entry == null) return false;
+ if (!valueComparator.areEqual((V) entry.value, (V) value)) return false;
+ fractal.removeEntry(key, hash, keyComparator);
+ detachEntry(entry); // Entry is not referenced anymore and will be gc.
+ size--;
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V replace(K key, V value) {
+ MapEntryImpl<K, V> entry = fractal.getEntry(key,
+ keyComparator.hashCodeOf(key), keyComparator);
+ if (entry == null) return null;
+ V oldValue = entry.value;
+ entry.value = value;
+ return oldValue;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ MapEntryImpl<K, V> entry = fractal.getEntry(key,
+ keyComparator.hashCodeOf(key), keyComparator);
+ if (entry == null) return false;
+ if (!valueComparator.areEqual(entry.value, oldValue)) return false;
+ entry.value = newValue;
+ return true;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return valueComparator;
+ }
+
+ private void attachEntry(MapEntryImpl<K, V> entry) {
+ if (lastEntry != null) {
+ lastEntry.next = entry;
+ entry.previous = lastEntry;
+ }
+ lastEntry = entry;
+ if (firstEntry == null) {
+ firstEntry = entry;
+ }
+ }
+
+ private void detachEntry(MapEntryImpl<K, V> entry) {
+ if (entry == firstEntry) {
+ firstEntry = entry.next;
+ }
+ if (entry == lastEntry) {
+ lastEntry = entry.previous;
+ }
+ MapEntryImpl<K, V> previous = entry.previous;
+ MapEntryImpl<K, V> next = entry.next;
+ if (previous != null) {
+ previous.next = next;
+ }
+ if (next != null) {
+ next.previous = previous;
+ }
+ }
+
+ /** For serialization support */
+ @SuppressWarnings("unchecked")
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject(); // Deserialize comparator.
+ fractal = new FractalMapImpl();
+ freeEntry = new MapEntryImpl<K, V>();
+ int n = s.readInt();
+ for (int i = 0; i < n; i++) {
+ put((K) s.readObject(), (V) s.readObject());
+ }
+ }
+
+ /** For serialization support */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ s.defaultWriteObject(); // Serialize comparators.
+ s.writeInt(size);
+ Iterator<Entry<K, V>> it = iterator();
+ while (it.hasNext()) {
+ Entry<K, V> e = it.next();
+ s.writeObject(e.getKey());
+ s.writeObject(e.getValue());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FractalMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FractalMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FractalMapImpl.java
new file mode 100644
index 0000000..7159b41
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/FractalMapImpl.java
@@ -0,0 +1,121 @@
+/*
+ * 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.internal.map;
+
+import javolution.util.function.Equality;
+
+/**
+ * A fractal-based map with rehash performed only on limited size maps.
+ * It is based on a fractal structure with self-similar patterns at any scale
+ * (maps holding submaps). At each depth only a part of the hashcode is used
+ * starting by the last bits.
+ */
+@SuppressWarnings("rawtypes")
+final class FractalMapImpl {
+
+ static final int EMPTINESS_LEVEL = 2; // Can be 1 (load factor 0.5), 2 (load factor 0.25) or any greater value.
+ static final int INITIAL_BLOCK_CAPACITY = 2 << EMPTINESS_LEVEL;
+ static final int SHIFT = 10; // Number of hashcode bits per depth.
+ //private static final int MAX_BLOCK_CAPACITY = 1 << SHIFT;
+ private int count; // Number of entries different from null in this block.
+ private MapEntryImpl[] entries = new MapEntryImpl[INITIAL_BLOCK_CAPACITY]; // Entries value can be a sub-map.
+ private final int shift; // Zero if base map.
+
+ public FractalMapImpl() {
+ this.shift = 0;
+ }
+
+ public FractalMapImpl(int shift) {
+ this.shift = shift;
+ }
+
+ /** Adds the specified entry if not already present; returns
+ * either the specified entry or an existing entry for the specified key. **/
+ @SuppressWarnings("unchecked")
+ public MapEntryImpl addEntry(MapEntryImpl newEntry, Object key, int hash, Equality comparator) {
+ int i = indexOfKey(key, hash, comparator);
+ MapEntryImpl entry = entries[i];
+ if (entry != null) return entry; // Entry exists
+ entries[i] = newEntry;
+ newEntry.key = key;
+ newEntry.hash = hash;
+ // Check if we need to resize.
+ if ((++count << EMPTINESS_LEVEL) > entries.length) {
+ resize(entries.length << 1);
+ }
+ return newEntry;
+ }
+
+ public void clear() {
+ entries = new MapEntryImpl[INITIAL_BLOCK_CAPACITY];
+ count = 0;
+ }
+
+ /** Returns null if no entry with specified key */
+ public MapEntryImpl getEntry(Object key, int hash, Equality comparator) {
+ return entries[indexOfKey(key, hash, comparator)];
+ }
+
+ /** Returns the entry removed or null if none. */
+ public MapEntryImpl removeEntry(Object key, int hash, Equality comparator) {
+ int i = indexOfKey(key, hash, comparator);
+ MapEntryImpl oldEntry = entries[i];
+ if (oldEntry == null) return null; // Entry does not exist.
+ entries[i] = null;
+ // Since we have made a hole, adjacent keys might have to shift.
+ for (;;) {
+ // We use a step of 1 (improve caching through memory locality).
+ i = (i + 1) & (entries.length - 1);
+ MapEntryImpl entry = entries[i];
+ if (entry == null) break; // Done.
+ int correctIndex = indexOfKey(entry.key, entry.hash, comparator);
+ if (correctIndex != i) { // Misplaced.
+ entries[correctIndex] = entries[i];
+ entries[i] = null;
+ }
+ }
+ // Check if we need to resize.
+ if (((--count << (EMPTINESS_LEVEL + 1)) <= entries.length)
+ && (entries.length > INITIAL_BLOCK_CAPACITY)) {
+ resize(entries.length >> 1);
+ }
+ return oldEntry;
+ }
+
+ /** Returns the index of the specified key in the map
+ (points to a null key if key not present). */
+ private int indexOfKey(Object key, int hash, Equality comparator) {
+ int mask = entries.length - 1;
+ int i = (hash >> shift) & mask;
+ while (true) {
+ MapEntryImpl entry = entries[i];
+ if (entry == null) return i;
+ if ((entry.hash == hash) && comparator.areEqual(key,entry.key)) return i;
+ i = (i + 1) & mask;
+ }
+ }
+
+ // The capacity is a power of two such as:
+ // (count * 2**EMPTINESS_LEVEL) <= capacity < (count * 2**(EMPTINESS_LEVEL+1))
+ // TODO: Use submaps if max capacity reached.
+ private void resize(int newCapacity) {
+ MapEntryImpl[] newEntries = new MapEntryImpl[newCapacity];
+ int newMask = newEntries.length - 1;
+ for (int i = 0, n = entries.length; i < n; i++) {
+ MapEntryImpl entry = entries[i];
+ if (entry == null) continue;
+ int newIndex = entry.hash & newMask;
+ while (newEntries[newIndex] != null) { // Find empty slot.
+ newIndex = (newIndex + 1) & newMask;
+ }
+ newEntries[newIndex] = entry;
+ }
+ entries = newEntries;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapEntryImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapEntryImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapEntryImpl.java
new file mode 100644
index 0000000..2eddac9
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapEntryImpl.java
@@ -0,0 +1,46 @@
+/*
+ * 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.internal.map;
+
+import java.util.Map;
+
+/**
+ * The hash map entry implementation (not serializable).
+ */
+public final class MapEntryImpl<K, V> implements Map.Entry<K, V> {
+
+ int hash;
+ K key;
+ MapEntryImpl<K, V> next;
+ MapEntryImpl<K, V> previous;
+ V value;
+
+ @Override
+ public K getKey() {
+ return key;
+ }
+
+ @Override
+ public V getValue() {
+ return value;
+ }
+
+ @Override
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ @Override
+ public String toString() {
+ return key + "=" + value;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapView.java
new file mode 100644
index 0000000..6ec0238
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/MapView.java
@@ -0,0 +1,363 @@
+/*
+ * 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.internal.map;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.Map;
+
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.function.Function;
+import javolution.util.internal.collection.MappedCollectionImpl;
+import javolution.util.internal.set.MappedSetImpl;
+import javolution.util.internal.set.SetView;
+import javolution.util.service.CollectionService;
+import javolution.util.service.MapService;
+import javolution.util.service.SetService;
+
+/**
+ * Map view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ * When possible sub-classes should forward to the actual target for the methods
+ * isEmpty, size and clear rather than using the default implementation.
+ */
+public abstract class MapView<K, V> implements MapService<K, V> {
+
+ /**
+ * Entry comparator. Entries are considered equals if they have the same
+ * keys regardless of their associated values.
+ */
+ protected class EntryComparator implements Equality<Entry<K,V>>, Serializable {
+ private static final long serialVersionUID = MapView.serialVersionUID;
+
+ public EntryComparator() {
+ }
+
+ @Override
+ public boolean areEqual(Entry<K, V> left, Entry<K, V> right) {
+ return keyComparator().areEqual(left.getKey(),
+ right.getKey());
+ }
+
+ @Override
+ public int compare(Entry<K, V> left, Entry<K, V> right) {
+ return keyComparator().compare(left.getKey(),
+ right.getKey());
+ }
+
+ @Override
+ public int hashCodeOf(Entry<K, V> e) {
+ return keyComparator().hashCodeOf(e.getKey());
+ }
+ }
+
+ /** Entry Set View */
+ protected class EntrySet extends SetView<Entry<K, V>> {
+ private static final long serialVersionUID = MapView.serialVersionUID;
+ public EntrySet() {
+ super(null); // Actual target is the outer map.
+ }
+
+ @Override
+ public boolean add(Entry<K, V> entry) {
+ put(entry.getKey(), entry.getValue());
+ return true;
+ }
+
+ @Override
+ public Equality<? super Entry<K, V>> comparator() {
+ return new EntryComparator();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean contains(Object obj) {
+ if (obj instanceof Entry) {
+ Entry<K, V> e = (Entry<K, V>) obj;
+ return contains(e.getKey());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return MapView.this.isEmpty();
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return MapView.this.iterator();
+ }
+
+ @Override
+ public void perform(
+ final Consumer<CollectionService<Entry<K, V>>> action,
+ final CollectionService<Entry<K, V>> view) {
+ Consumer<MapService<K, V>> mapAction = new Consumer<MapService<K, V>>() {
+ @Override
+ public void accept(MapService<K, V> param) {
+ action.accept(view);
+ }
+ };
+ MapView.this.perform(mapAction, MapView.this);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean remove(Object obj) {
+ if (obj instanceof Entry) {
+ Entry<K, V> e = (Entry<K, V>) obj;
+ if (!contains(e.getKey())) return false;
+ MapView.this.remove(e.getKey());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return MapView.this.size();
+ }
+
+ @Override
+ public void update(
+ final Consumer<CollectionService<Entry<K, V>>> action,
+ final CollectionService<Entry<K, V>> view) {
+ Consumer<MapService<K, V>> mapAction = new Consumer<MapService<K, V>>() {
+ @Override
+ public void accept(MapService<K, V> param) {
+ action.accept(view);
+ }
+ };
+ MapView.this.update(mapAction, MapView.this);
+ }
+ }
+
+ /** Entry to key mapping function */
+ class EntryToKey implements Function<Entry<K, V>, K>, Serializable {
+ private static final long serialVersionUID = MapView.serialVersionUID;
+ @Override
+ public K apply(java.util.Map.Entry<K, V> param) {
+ return param.getKey();
+ }
+ }
+
+ /** Key Set View */
+ protected class KeySet extends MappedSetImpl<Entry<K, V>, K> {
+ private static final long serialVersionUID = MapView.serialVersionUID;
+
+ public KeySet() {
+ super(entrySet(), new EntryToKey());
+ }
+
+ @Override
+ public boolean add(K key) { // Supports adding new key with null value.
+ if (containsKey(key)) return false;
+ put(key, null);
+ return true;
+ }
+
+ @Override
+ public Equality<? super K> comparator() {
+ return keyComparator();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean contains(Object obj) {
+ return containsKey((K) obj);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean remove(Object obj) {
+ if (!containsKey((K) obj)) return false;
+ MapView.this.remove((K) obj);
+ return true;
+ }
+ }
+
+ /** Values View */
+ protected class Values extends MappedCollectionImpl<Entry<K, V>, V> {
+ private static final long serialVersionUID = MapView.serialVersionUID;
+
+ public Values() {
+ super(entrySet(), new Function<Entry<K, V>, V>() {
+ @Override
+ public V apply(Map.Entry<K, V> e) {
+ return e.getValue();
+ }
+ });
+ }
+
+ @Override
+ public Equality<? super V> comparator() {
+ return valueComparator();
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ private MapService<K, V> target;
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public MapView(MapService<K, V> target) {
+ this.target = target;
+ }
+
+ @Override
+ public void clear() {
+ Iterator<Entry<K, V>> it = iterator();
+ while (it.hasNext()) {
+ it.remove();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public MapView<K, V> clone() {
+ try {
+ MapView<K, V> copy = (MapView<K, V>) super.clone();
+ if (target != null) { // Not a root class.
+ copy.target = target.clone();
+ }
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Should not happen since target is cloneable");
+ }
+ }
+
+ @Override
+ public abstract boolean containsKey(Object key);
+
+ @Override
+ public boolean containsValue(Object value) {
+ return values().contains(value);
+ }
+
+ @Override
+ public SetService<Entry<K, V>> entrySet() {
+ return new EntrySet();
+ }
+
+ @Override
+ public abstract V get(Object key);
+
+ @Override
+ public boolean isEmpty() {
+ return !iterator().hasNext();
+ }
+
+ @Override
+ public abstract Iterator<Entry<K, V>> iterator();
+
+ @Override
+ public abstract Equality<? super K> keyComparator();
+
+ @Override
+ public SetService<K> keySet() {
+ return new KeySet();
+ }
+
+ @Override
+ public void perform(Consumer<MapService<K, V>> action, MapService<K, V> view) {
+ if (target == null) {
+ action.accept(view);
+ } else {
+ target.perform(action, view);
+ }
+ }
+
+ @Override
+ public abstract V put(K key, V value);
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ Iterator<?> it = m.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<K, V> e = (Entry<K, V>) it.next();
+ put(e.getKey(), e.getValue());
+ }
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ if (!containsKey(key)) return put(key, value);
+ else return get(key);
+ }
+
+ @Override
+ public abstract V remove(Object key);
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ if (containsKey(key) && get(key).equals(value)) {
+ remove(key);
+ return true;
+ } else return false;
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ if (containsKey(key)) {
+ return put(key, value);
+ } else return null;
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ if (containsKey(key) && get(key).equals(oldValue)) {
+ put(key, newValue);
+ return true;
+ } else return false;
+ }
+
+ @Override
+ public int size() {
+ int count = 0;
+ Iterator<Entry<K, V>> it = iterator();
+ while (it.hasNext()) {
+ count++;
+ it.next();
+ }
+ return count;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public MapService<K, V>[] split(int n, boolean threadsafe) {
+ return new MapService[] { this }; // Splits not supported.
+ }
+
+ @Override
+ public void update(Consumer<MapService<K, V>> action, MapService<K, V> view) {
+ if (target == null) {
+ action.accept(view);
+ } else {
+ target.update(action, view);
+ }
+ }
+
+ @Override
+ public abstract Equality<? super V> valueComparator();
+
+ @Override
+ public CollectionService<V> values() {
+ return new Values();
+ }
+
+ /** Returns the actual target */
+ protected MapService<K, V> target() {
+ return target;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/ParallelMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/ParallelMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/ParallelMapImpl.java
new file mode 100644
index 0000000..21d079e
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/ParallelMapImpl.java
@@ -0,0 +1,130 @@
+/*
+ * 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.internal.map;
+
+import java.util.Iterator;
+
+import javolution.context.ConcurrentContext;
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.service.MapService;
+
+/**
+ * A parallel view over a map.
+ */
+public class ParallelMapImpl<K, V> extends MapView<K, V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public ParallelMapImpl(MapService<K, V> target) {
+ super(target);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return target().containsKey(key);
+ }
+
+ @Override
+ public V get(Object key) {
+ return target().get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<java.util.Map.Entry<K, V>> iterator() {
+ return target().iterator();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public void perform(final Consumer<MapService<K, V>> action,
+ MapService<K, V> view) {
+ ConcurrentContext ctx = ConcurrentContext.enter();
+ try {
+ int concurrency = ctx.getConcurrency();
+ MapService<K, V>[] subViews = view.split(concurrency + 1, false);
+ for (int i = 1; i < subViews.length; i++) {
+ final MapService<K, V> subView = subViews[i];
+ ctx.execute(new Runnable() {
+ @Override
+ public void run() {
+ target().perform(action, subView);
+ }
+ });
+ }
+ target().perform(action, subViews[0]); // This thread works too !
+ } finally {
+ // Any exception raised during parallel iterations will be re-raised here.
+ ctx.exit();
+ }
+ }
+
+ @Override
+ public V put(K key, V value) {
+ return target().put(key, value);
+ }
+
+ @Override
+ public V remove(Object key) {
+ return target().remove(key);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @Override
+ public void update(final Consumer<MapService<K, V>> action,
+ MapService<K, V> view) {
+ ConcurrentContext ctx = ConcurrentContext.enter();
+ try {
+ int concurrency = ctx.getConcurrency();
+ MapService<K, V>[] subViews = view.split(concurrency + 1, true);
+ for (int i = 1; i < subViews.length; i++) {
+ final MapService<K, V> subView = subViews[i];
+ ctx.execute(new Runnable() {
+ @Override
+ public void run() {
+ target().update(action, subView);
+ }
+ });
+ }
+ target().perform(action, subViews[0]); // This thread works too !
+ } finally {
+ // Any exception raised during parallel iterations will be re-raised here.
+ ctx.exit();
+ }
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return target().valueComparator();
+ }
+
+ @Override
+ public MapService<K, V>[] split(int n, boolean threadsafe) {
+ return target().split(n, threadsafe); // Forwards.
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SequentialMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SequentialMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SequentialMapImpl.java
new file mode 100644
index 0000000..114a884
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SequentialMapImpl.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.util.internal.map;
+
+import java.util.Iterator;
+
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.service.MapService;
+
+/**
+ * A sequential view over a map.
+ */
+public class SequentialMapImpl<K, V> extends MapView<K, V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SequentialMapImpl(MapService<K, V> target) {
+ super(target);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return target().containsKey(key);
+ }
+
+ @Override
+ public V get(Object key) {
+ return target().get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<java.util.Map.Entry<K, V>> iterator() {
+ return target().iterator();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public void perform(Consumer<MapService<K, V>> action, MapService<K, V> view) {
+ action.accept(view); // Executes immediately.
+ }
+
+ @Override
+ public V put(K key, V value) {
+ return target().put(key, value);
+ }
+
+ @Override
+ public V remove(Object key) {
+ return target().remove(key);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @Override
+ public void update(Consumer<MapService<K, V>> action, MapService<K, V> view) {
+ action.accept(view); // Executes immediately.
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return target().valueComparator();
+ }
+
+ @Override
+ public MapService<K, V>[] split(int n, boolean threadsafe) {
+ return target().split(n, threadsafe); // Forwards.
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SharedMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SharedMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SharedMapImpl.java
new file mode 100644
index 0000000..833e728
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/SharedMapImpl.java
@@ -0,0 +1,240 @@
+/*
+ * 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.internal.map;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javolution.util.function.Equality;
+import javolution.util.internal.ReadWriteLockImpl;
+import javolution.util.service.MapService;
+
+/**
+ * A shared view over a map.
+ */
+public class SharedMapImpl<K, V> extends MapView<K, V> {
+
+ /** Thread-Safe Iterator. */
+ private class IteratorImpl implements Iterator<Entry<K, V>> {
+ private Entry<K, V> next;
+ private final Iterator<Entry<K, V>> targetIterator;
+
+ public IteratorImpl() {
+ lock.readLock.lock();
+ try {
+ targetIterator = cloneTarget().entrySet().iterator(); // Copy.
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public Entry<K, V> next() {
+ next = targetIterator.next();
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ if (next == null) throw new IllegalStateException();
+ SharedMapImpl.this.remove(next.getKey());
+ next = null;
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected ReadWriteLockImpl lock;
+ protected transient Thread updatingThread; // The thread executing an update.
+
+ public SharedMapImpl(MapService<K, V> target) {
+ this(target, new ReadWriteLockImpl());
+ }
+
+ public SharedMapImpl(MapService<K, V> target, ReadWriteLockImpl lock) {
+ super(target);
+ this.lock = lock;
+ }
+
+ @Override
+ public void clear() {
+ lock.writeLock.lock();
+ try {
+ target().clear();
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ lock.readLock.lock();
+ try {
+ return target().containsKey(key);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ lock.readLock.lock();
+ try {
+ return target().containsValue(value);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public V get(Object key) {
+ lock.readLock.lock();
+ try {
+ return target().get(key);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ lock.readLock.lock();
+ try {
+ return target().isEmpty();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public V put(K key, V value) {
+ lock.writeLock.lock();
+ try {
+ return target().put(key, value);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ lock.writeLock.lock();
+ try {
+ target().putAll(m);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ lock.writeLock.lock();
+ try {
+ return target().putIfAbsent(key, value);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public V remove(Object key) {
+ lock.writeLock.lock();
+ try {
+ return target().remove(key);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ lock.writeLock.lock();
+ try {
+ return target().remove(key, value);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ lock.writeLock.lock();
+ try {
+ return target().replace(key, value);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ lock.writeLock.lock();
+ try {
+ return target().replace(key, oldValue, newValue);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public int size() {
+ lock.readLock.lock();
+ try {
+ return target().size();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return target().valueComparator();
+ }
+
+ /** Returns a clone copy of target. */
+ protected MapService<K, V> cloneTarget() {
+ try {
+ return target().clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Cannot happen since target is Cloneable.");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public MapService<K,V>[] split(int n, boolean updateable) {
+ MapService<K,V>[] tmp;
+ lock.readLock.lock();
+ try {
+ tmp = target().split(n, updateable);
+ } finally {
+ lock.readLock.unlock();
+ }
+ MapService<K,V>[] result = new MapService[tmp.length];
+ for (int i = 0; i < tmp.length; i++) {
+ result[i] = new SharedMapImpl<K,V>(tmp[i], lock); // Shares the same locks.
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/UnmodifiableMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/UnmodifiableMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/UnmodifiableMapImpl.java
new file mode 100644
index 0000000..196e9cc
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/UnmodifiableMapImpl.java
@@ -0,0 +1,109 @@
+/*
+ * 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.internal.map;
+
+import java.util.Iterator;
+
+import javolution.util.function.Equality;
+import javolution.util.service.MapService;
+
+/**
+ * * An unmodifiable view over a map.
+ */
+public class UnmodifiableMapImpl<K, V> extends MapView<K, V> {
+
+ /** Read-Only Iterator. */
+ private class IteratorImpl implements Iterator<Entry<K, V>> {
+ private final Iterator<Entry<K, V>> targetIterator = target()
+ .iterator();
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public Entry<K, V> next() {
+ return targetIterator.next();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("Read-Only Map.");
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableMapImpl(MapService<K, V> target) {
+ super(target);
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("Unmodifiable");
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return target().containsKey(key);
+ }
+
+ @Override
+ public V get(Object key) {
+ return target().get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public V put(K key, V value) {
+ throw new UnsupportedOperationException("Unmodifiable");
+ }
+
+ @Override
+ public V remove(Object key) {
+ throw new UnsupportedOperationException("Unmodifiable");
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return target().valueComparator();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public MapService<K,V>[] split(int n, boolean updateable) {
+ MapService<K,V>[] subTargets = target().split(n, updateable);
+ MapService<K,V>[] result = new MapService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new UnmodifiableMapImpl<K,V>(subTargets[i]);
+ }
+ return result;
+ }
+
+}
[04/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/NamespacesImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/NamespacesImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/NamespacesImpl.java
new file mode 100644
index 0000000..47ff23b
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/NamespacesImpl.java
@@ -0,0 +1,276 @@
+/*
+ * 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.xml.internal.stream;
+
+import java.util.Iterator;
+import javolution.text.CharArray;
+import javolution.util.FastTable;
+import javolution.xml.stream.NamespaceContext;
+
+/**
+ * This class represents the namespaces stack while parsing.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.2, April 2, 2005
+ */
+public final class NamespacesImpl implements NamespaceContext {
+
+ /**
+ * Holds the number of predefined namespaces.
+ */
+ static final int NBR_PREDEFINED_NAMESPACES = 3;
+
+ /**
+ * Holds useful CharArray instances (non-static to avoid potential
+ * inter-thread corruption).
+ */
+ final CharArray _nullNsURI = new CharArray(""); // No namespace URI.
+
+ final CharArray _defaultNsPrefix = new CharArray("");
+
+ final CharArray _xml = new CharArray("xml");
+
+ final CharArray _xmlURI = new CharArray(
+ "http://www.w3.org/XML/1998/namespace");
+
+ final CharArray _xmlns = new CharArray("xmlns");
+
+ final CharArray _xmlnsURI = new CharArray("http://www.w3.org/2000/xmlns/");
+
+ /**
+ * Holds the current nesting level.
+ */
+ private int _nesting = 0;
+
+ /**
+ * Holds the currently mapped prefixes.
+ */
+ CharArray[] _prefixes = new CharArray[16];
+
+ /**
+ * Holds the currently mapped namespaces.
+ */
+ CharArray[] _namespaces = new CharArray[_prefixes.length];
+
+ /**
+ * Indicates if the prefix has to been written (when writing).
+ */
+ boolean[] _prefixesWritten = new boolean[_prefixes.length];
+
+ /**
+ * Holds the number of prefix/namespace association per nesting level.
+ */
+ int[] _namespacesCount = new int[16];
+
+ /**
+ * Holds the default namespace.
+ */
+ CharArray _defaultNamespace = _nullNsURI;
+
+ /**
+ * Holds the default namespace index.
+ */
+ int _defaultNamespaceIndex;
+
+ /**
+ * Default constructor.
+ */
+ public NamespacesImpl() {
+ _prefixes[0] = _defaultNsPrefix;
+ _namespaces[0] = _nullNsURI;
+ _prefixes[1] = _xml;
+ _namespaces[1] = _xmlURI;
+ _prefixes[2] = _xmlns;
+ _namespaces[2] = _xmlnsURI;
+ _namespacesCount[0] = NBR_PREDEFINED_NAMESPACES;
+ }
+
+ // Implements NamespaceContext
+ public CharArray getNamespaceURI(CharSequence prefix) {
+ if (prefix == null)
+ throw new IllegalArgumentException("null prefix not allowed");
+ return getNamespaceURINullAllowed(prefix);
+ }
+
+ CharArray getNamespaceURINullAllowed(CharSequence prefix) {
+ if ((prefix == null) || (prefix.length() == 0))
+ return _defaultNamespace;
+ final int count = _namespacesCount[_nesting];
+ for (int i = count; --i >= 0;) {
+ if (_prefixes[i].equals(prefix))
+ return _namespaces[i];
+ }
+ return null; // Not bound.
+ }
+
+ // Implements NamespaceContext
+ public CharArray getPrefix(CharSequence uri) {
+ if (uri == null)
+ throw new IllegalArgumentException("null namespace URI not allowed");
+ return _defaultNamespace.equals(uri) ? _defaultNsPrefix : getPrefix(
+ uri, _namespacesCount[_nesting]);
+ }
+
+ CharArray getPrefix(CharSequence uri, int count) {
+ for (int i = count; --i >= 0;) {
+ CharArray prefix = _prefixes[i];
+ CharArray namespace = _namespaces[i];
+ if (namespace.equals(uri)) { // Find matching uri.
+ // Checks that the prefix has not been overwriten after being set.
+ boolean isPrefixOverwritten = false;
+ for (int j = i + 1; j < count; j++) {
+ if (prefix.equals(_prefixes[j])) {
+ isPrefixOverwritten = true;
+ break;
+ }
+ }
+ if (!isPrefixOverwritten)
+ return prefix;
+ }
+ }
+ return null; // Not bound.
+ }
+
+ // Implements NamespaceContext
+ public Iterator<CharArray> getPrefixes(CharSequence namespaceURI) {
+ FastTable<CharArray> prefixes = new FastTable<CharArray>();
+ for (int i = _namespacesCount[_nesting]; --i >= 0;) {
+ if (_namespaces[i].equals(namespaceURI)) {
+ prefixes.add(_prefixes[i]);
+ }
+ }
+ return prefixes.iterator();
+ }
+
+ // Null values are not allowed.
+ void setPrefix(CharArray prefix, CharArray uri) {
+ int index = _namespacesCount[_nesting];
+ _prefixes[index] = prefix;
+ _namespaces[index] = uri;
+ if (prefix.length() == 0) { // The default namespace is set.
+ _defaultNamespaceIndex = index;
+ _defaultNamespace = uri;
+ }
+ if (++_namespacesCount[_nesting] >= _prefixes.length)
+ resizePrefixStack();
+ }
+
+ // Used only by XMLStreamWriter (converts CharSequence to CharArray).
+ // Null values are not allowed.
+ void setPrefix(final CharSequence prefix, CharSequence uri,
+ boolean isWritten) {
+ final int index = _namespacesCount[_nesting];
+ _prefixesWritten[index] = isWritten;
+ final int prefixLength = prefix.length();
+ CharArray prefixTmp = _prefixesTmp[index];
+ if ((prefixTmp == null) || (prefixTmp.array().length < prefixLength)) {
+ _prefixesTmp[index] = new CharArray().setArray(
+ new char[prefixLength + 32], 0, 0);
+ prefixTmp = _prefixesTmp[index];
+ }
+ for (int i = 0; i < prefixLength; i++) {
+ prefixTmp.array()[i] = prefix.charAt(i);
+ }
+ prefixTmp.setArray(prefixTmp.array(), 0, prefixLength);
+
+ final int uriLength = uri.length();
+ CharArray namespaceTmp = _namespacesTmp[index];
+ if ((namespaceTmp == null) || (namespaceTmp.array().length < uriLength)) {
+ _namespacesTmp[index] = new CharArray().setArray(
+ new char[uriLength + 32], 0, 0);
+ namespaceTmp = _namespacesTmp[index];
+ }
+ for (int i = 0; i < uriLength; i++) {
+ namespaceTmp.array()[i] = uri.charAt(i);
+ }
+ namespaceTmp.setArray(namespaceTmp.array(), 0, uriLength);
+
+ // Sets the prefix using CharArray instances.
+ setPrefix(prefixTmp, namespaceTmp);
+ }
+
+ private CharArray[] _prefixesTmp = new CharArray[_prefixes.length];
+
+ private CharArray[] _namespacesTmp = new CharArray[_prefixes.length];
+
+ void pop() {
+ if (_namespacesCount[--_nesting] <= _defaultNamespaceIndex) {
+ searchDefaultNamespace();
+ }
+ }
+
+ private void searchDefaultNamespace() {
+ int count = _namespacesCount[_nesting];
+ for (int i = count; --i >= 0;) {
+ if (_prefixes[i].length() == 0) {
+ _defaultNamespaceIndex = i;
+ return;
+ }
+ }
+ throw new Error("Cannot find default namespace");
+ }
+
+ void push() {
+ _nesting++;
+ if (_nesting >= _namespacesCount.length) {
+ resizeNamespacesCount();
+ }
+ _namespacesCount[_nesting] = _namespacesCount[_nesting - 1];
+ }
+
+ public void reset() {
+ _defaultNamespace = _nullNsURI;
+ _defaultNamespaceIndex = 0;
+ _namespacesCount[0] = NBR_PREDEFINED_NAMESPACES;
+ _nesting = 0;
+ }
+
+ private void resizeNamespacesCount() {
+ final int oldLength = _namespacesCount.length;
+ final int newLength = oldLength * 2;
+
+ // Resizes namespaces counts.
+ int[] tmp = new int[newLength];
+ System.arraycopy(_namespacesCount, 0, tmp, 0, oldLength);
+ _namespacesCount = tmp;
+ }
+
+ // Resizes prefix mapping stack.
+ private void resizePrefixStack() {
+ final int oldLength = _prefixes.length;
+ final int newLength = oldLength * 2;
+
+ // Resizes prefixes.
+ CharArray[] tmp0 = new CharArray[newLength];
+ System.arraycopy(_prefixes, 0, tmp0, 0, oldLength);
+ _prefixes = tmp0;
+
+ // Resizes namespaces uri.
+ CharArray[] tmp1 = new CharArray[newLength];
+ System.arraycopy(_namespaces, 0, tmp1, 0, oldLength);
+ _namespaces = tmp1;
+
+ // Resizes prefix sets.
+ boolean[] tmp2 = new boolean[newLength];
+ System.arraycopy(_prefixesWritten, 0, tmp2, 0, oldLength);
+ _prefixesWritten = tmp2;
+
+ // Resizes temporary prefix (CharSequence to CharArray conversion).
+ CharArray[] tmp3 = new CharArray[newLength];
+ System.arraycopy(_prefixesTmp, 0, tmp3, 0, oldLength);
+ _prefixesTmp = tmp3;
+
+ // Resizes temporary namespaces (CharSequence to CharArray conversion).
+ CharArray[] tmp4 = new CharArray[newLength];
+ System.arraycopy(_namespacesTmp, 0, tmp4, 0, oldLength);
+ _namespacesTmp = tmp4;
+
+ }
+
+}
\ 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/xml/internal/stream/XMLInputFactoryImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLInputFactoryImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLInputFactoryImpl.java
new file mode 100644
index 0000000..bd2eaa2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLInputFactoryImpl.java
@@ -0,0 +1,106 @@
+/*
+ * 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.xml.internal.stream;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Map;
+
+import javolution.util.FastTable;
+import javolution.xml.stream.XMLInputFactory;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * The default XML input factory implementation.
+ */
+public final class XMLInputFactoryImpl implements XMLInputFactory {
+ private Map<String, String> _entities = null;
+ private FastTable<XMLStreamReaderImpl> _recycled = new FastTable<XMLStreamReaderImpl>()
+ .shared();
+
+ // Implements XMLInputFactory abstract method.
+ public XMLStreamReaderImpl createXMLStreamReader(InputStream stream)
+ throws XMLStreamException {
+ XMLStreamReaderImpl xmlReader = newReader();
+ xmlReader.setInput(stream);
+ return xmlReader;
+ }
+
+ // Implements XMLInputFactory abstract method.
+ public XMLStreamReaderImpl createXMLStreamReader(InputStream stream,
+ String encoding) throws XMLStreamException {
+ XMLStreamReaderImpl xmlReader = newReader();
+ xmlReader.setInput(stream, encoding);
+ return xmlReader;
+ }
+
+ // Implements XMLInputFactory abstract method.
+ public XMLStreamReaderImpl createXMLStreamReader(Reader reader)
+ throws XMLStreamException {
+ XMLStreamReaderImpl xmlReader = newReader();
+ xmlReader.setInput(reader);
+ return xmlReader;
+ }
+
+ // Implements XMLInputFactory abstract method.
+ public Object getProperty(String name) throws IllegalArgumentException {
+ if (name.equals(IS_COALESCING)) {
+ return Boolean.TRUE;
+ } else if (name.equals(ENTITIES)) {
+ return _entities;
+ } else {
+ throw new IllegalArgumentException("Property: " + name
+ + " not supported");
+ }
+ }
+
+ // Implements XMLInputFactory abstract method.
+ public boolean isPropertySupported(String name) {
+ return name.equals(IS_COALESCING) || name.equals(ENTITIES);
+ }
+
+ // Implements XMLInputFactory abstract method.
+ @SuppressWarnings("unchecked")
+ public void setProperty(String name, Object value)
+ throws IllegalArgumentException {
+ if (name.equals(IS_COALESCING)) {
+ // Do nothing, always coalescing.
+ } else if (name.equals(ENTITIES)) {
+ _entities = (Map<String, String>) value;
+ } else {
+ throw new IllegalArgumentException("Property: " + name
+ + " not supported");
+ }
+ }
+
+ /** Recycles the specified instance. */
+ void recycle(XMLStreamReaderImpl reader) {
+ _recycled.addLast(reader);
+ }
+
+ private XMLStreamReaderImpl newReader() {
+ XMLStreamReaderImpl xmlReader = _recycled.pollLast();
+ if (xmlReader == null) xmlReader = new XMLStreamReaderImpl(this);
+ if (_entities != null) {
+ xmlReader.setEntities(_entities);
+ }
+ return xmlReader;
+ }
+
+ @Override
+ public XMLInputFactory clone() {
+ try {
+ XMLInputFactoryImpl clone = (XMLInputFactoryImpl) super.clone();
+ clone._recycled = new FastTable<XMLStreamReaderImpl>().shared();
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ throw new Error();// Cannot happen since cloneable.
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLOutputFactoryImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLOutputFactoryImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLOutputFactoryImpl.java
new file mode 100644
index 0000000..7dfd18f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLOutputFactoryImpl.java
@@ -0,0 +1,151 @@
+/*
+ * 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.xml.internal.stream;
+
+import java.io.OutputStream;
+import java.io.Writer;
+
+import javolution.util.FastTable;
+import javolution.xml.stream.XMLOutputFactory;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * This default XML Output factory implementation.
+ */
+public final class XMLOutputFactoryImpl implements XMLOutputFactory {
+
+ // Property setting.
+ private Boolean _automaticEmptyElements = Boolean.FALSE;
+
+ // Property setting.
+ private String _indentation;
+
+ // Property setting.
+ private Boolean _isRepairingNamespaces = Boolean.FALSE;
+
+ // Property setting.
+ private String _lineSeparator = "\n";
+
+ // Property setting.
+ private Boolean _noEmptyElementTag = Boolean.FALSE;
+
+ // Property setting.
+ private String _repairingPrefix = "ns";
+
+ private FastTable<XMLStreamWriterImpl> _recycled = new FastTable<XMLStreamWriterImpl>()
+ .shared();
+
+ // Implements XMLOutputFactory abstract method.
+ public XMLStreamWriterImpl createXMLStreamWriter(OutputStream stream)
+ throws XMLStreamException {
+ XMLStreamWriterImpl xmlWriter = newWriter();
+ xmlWriter.setOutput(stream);
+ return xmlWriter;
+ }
+
+ // Implements XMLOutputFactory abstract method.
+ public XMLStreamWriterImpl createXMLStreamWriter(OutputStream stream,
+ String encoding) throws XMLStreamException {
+ if ((encoding == null) || encoding.equals("UTF-8")
+ || encoding.equals("utf-8"))
+ return createXMLStreamWriter(stream);
+ XMLStreamWriterImpl xmlWriter = newWriter();
+ xmlWriter.setOutput(stream, encoding);
+ return xmlWriter;
+ }
+
+ // Implements XMLOutputFactory abstract method.
+ public XMLStreamWriterImpl createXMLStreamWriter(Writer writer)
+ throws XMLStreamException {
+ XMLStreamWriterImpl xmlWriter = newWriter();
+ xmlWriter.setOutput(writer);
+ return xmlWriter;
+ }
+
+ // Implements XMLOutputFactory abstract method.
+ public Object getProperty(String name) throws IllegalArgumentException {
+ if (name.equals(IS_REPAIRING_NAMESPACES)) {
+ return _isRepairingNamespaces;
+ } else if (name.equals(REPAIRING_PREFIX)) {
+ return _repairingPrefix;
+ } else if (name.equals(AUTOMATIC_EMPTY_ELEMENTS)) {
+ return _automaticEmptyElements;
+ } else if (name.equals(NO_EMPTY_ELEMENT_TAG)) {
+ return _noEmptyElementTag;
+ } else if (name.equals(INDENTATION)) {
+ return _indentation;
+ } else if (name.equals(LINE_SEPARATOR)) {
+ return _lineSeparator;
+ } else {
+ throw new IllegalArgumentException("Property: " + name
+ + " not supported");
+ }
+ }
+
+ // Implements XMLOutputFactory abstract method.
+ public boolean isPropertySupported(String name) {
+ return name.equals(IS_REPAIRING_NAMESPACES)
+ || name.equals(REPAIRING_PREFIX)
+ || name.equals(AUTOMATIC_EMPTY_ELEMENTS)
+ || name.equals(NO_EMPTY_ELEMENT_TAG)
+ || name.equals(INDENTATION) || name.equals(LINE_SEPARATOR);
+ }
+
+ // Implements XMLOutputFactory abstract method.
+ public void setProperty(String name, Object value)
+ throws IllegalArgumentException {
+ if (name.equals(IS_REPAIRING_NAMESPACES)) {
+ _isRepairingNamespaces = (Boolean) value;
+ } else if (name.equals(REPAIRING_PREFIX)) {
+ _repairingPrefix = (String) value;
+ } else if (name.equals(AUTOMATIC_EMPTY_ELEMENTS)) {
+ _automaticEmptyElements = (Boolean) value;
+ } else if (name.equals(NO_EMPTY_ELEMENT_TAG)) {
+ _noEmptyElementTag = (Boolean) value;
+ } else if (name.equals(INDENTATION)) {
+ _indentation = (String) value;
+ } else if (name.equals(LINE_SEPARATOR)) {
+ _lineSeparator = (String) value;
+ } else {
+ throw new IllegalArgumentException("Property: " + name
+ + " not supported");
+ }
+ }
+
+ /**
+ * Recycles the specified writer instance.
+ */
+ void recycle(XMLStreamWriterImpl xmlWriter) {
+ _recycled.addLast(xmlWriter);
+ }
+
+ private XMLStreamWriterImpl newWriter() {
+ XMLStreamWriterImpl xmlWriter = _recycled.pollLast();
+ if (xmlWriter == null) xmlWriter = new XMLStreamWriterImpl(this);
+ xmlWriter.setRepairingNamespaces(_isRepairingNamespaces.booleanValue());
+ xmlWriter.setRepairingPrefix(_repairingPrefix);
+ xmlWriter.setIndentation(_indentation);
+ xmlWriter.setLineSeparator(_lineSeparator);
+ xmlWriter.setAutomaticEmptyElements(_automaticEmptyElements
+ .booleanValue());
+ xmlWriter.setNoEmptyElementTag(_noEmptyElementTag.booleanValue());
+ return xmlWriter;
+ }
+
+ @Override
+ public XMLOutputFactory clone() {
+ try {
+ XMLOutputFactoryImpl clone = (XMLOutputFactoryImpl) super.clone();
+ clone._recycled = new FastTable<XMLStreamWriterImpl>().shared();
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ throw new Error();// Cannot happen since cloneable.
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamReaderImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamReaderImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamReaderImpl.java
new file mode 100644
index 0000000..57066fa
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/XMLStreamReaderImpl.java
@@ -0,0 +1,1523 @@
+/*
+ * 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.xml.internal.stream;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import javolution.io.UTF8StreamReader;
+import javolution.lang.Realtime;
+import javolution.text.CharArray;
+import javolution.xml.sax.Attributes;
+import javolution.xml.stream.Location;
+import javolution.xml.stream.NamespaceContext;
+import javolution.xml.stream.XMLInputFactory;
+import javolution.xml.stream.XMLStreamConstants;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+
+/**
+ * {@link XMLStreamReader} implementation.
+ *
+ * This implementation returns all contiguous character data in a single
+ * chunk (always coalescing). It is non-validating (DTD is returned
+ * unparsed). Although, users may define custom entities mapping using
+ * the {@link #setEntities} method (e.g. after parsing/resolving
+ * external entities).
+ */
+@Realtime
+public final class XMLStreamReaderImpl implements XMLStreamReader {
+
+ /**
+ * Holds the textual representation for events.
+ */
+ static final String[] NAMES_OF_EVENTS = new String[] { "UNDEFINED",
+ "START_ELEMENT", "END_ELEMENT", "PROCESSING_INSTRUCTIONS",
+ "CHARACTERS", "COMMENT", "SPACE", "START_DOCUMENT", "END_DOCUMENT",
+ "ENTITY_REFERENCE", "ATTRIBUTE", "DTD", "CDATA", "NAMESPACE",
+ "NOTATION_DECLARATION", "ENTITY_DECLARATION" };
+
+ /**
+ * Holds the reader buffer capacity.
+ */
+ static final int READER_BUFFER_CAPACITY = 4096;
+
+ /**
+ * Holds the prolog if any.
+ */
+ CharArray _prolog;
+
+ /**
+ * Holds the current index in the character buffer.
+ */
+ private int _readIndex;
+
+ /**
+ * Number of characters read from reader
+ */
+ private int _readCount;
+
+ /**
+ * Holds the data buffer for CharSequence produced by this parser.
+ */
+ private char[] _data = new char[READER_BUFFER_CAPACITY * 2];
+
+ /**
+ * Holds the current index of the data buffer (_data).
+ */
+ private int _index;
+
+ /**
+ * Holds the current element nesting.
+ */
+ private int _depth;
+
+ /**
+ * Holds qualified name (include prefix).
+ */
+ private CharArray _qName;
+
+ /**
+ * Holds element prefix separator index.
+ */
+ private int _prefixSep;
+
+ /**
+ * Holds attribute qualified name.
+ */
+ private CharArray _attrQName;
+
+ /**
+ * Holds attribute prefix separator index.
+ */
+ private int _attrPrefixSep;
+
+ /**
+ * Holds attribute value.
+ */
+ private CharArray _attrValue;
+
+ /**
+ * Holds current event type
+ */
+ private int _eventType = START_DOCUMENT;
+
+ /**
+ * Indicates if event type is START_TAG, and tag is empty, i.e. <sometag/>
+ */
+ private boolean _isEmpty;
+
+ /**
+ * Indicates if characters are pending for potential coalescing.
+ */
+ boolean _charactersPending = false;
+
+ /**
+ * Holds the start index for the current state within _data array.
+ */
+ private int _start;
+
+ /**
+ * Holds the parser state.
+ */
+ private int _state = STATE_CHARACTERS;
+
+ /**
+ * Holds the current text.
+ */
+ private CharArray _text;
+
+ /**
+ * Holds the reader input source (<code>null</code> when unused).
+ */
+ private Reader _reader;
+
+ /**
+ * Holds the character buffer used for reading.
+ */
+ private final char[] _readBuffer = new char[READER_BUFFER_CAPACITY];
+
+ /**
+ * Holds the start offset in the character buffer (due to auto detection
+ * of encoding).
+ */
+ private int _startOffset; // Byte Order Mark count.
+
+ /**
+ * Holds the location object.
+ */
+ private final LocationImpl _location = new LocationImpl();
+
+ /**
+ * Holds the namespace stack.
+ */
+ private final NamespacesImpl _namespaces = new NamespacesImpl();
+
+ /**
+ * Holds the current attributes.
+ */
+ private final AttributesImpl _attributes = new AttributesImpl(_namespaces);
+
+ /**
+ * Holds working stack (by nesting level).
+ */
+ private CharArray[] _elemStack = new CharArray[16];
+
+ /**
+ * Holds stream encoding if known.
+ */
+ private String _encoding;
+
+ /**
+ * Holds the entities.
+ */
+ private final EntitiesImpl _entities = new EntitiesImpl();
+
+ /**
+ * Holds the reader for input streams.
+ */
+ private final UTF8StreamReader _utf8StreamReader = new UTF8StreamReader();
+
+ /**
+ * Holds the factory (if any)
+ */
+ private final XMLInputFactoryImpl _factory;
+
+ /**
+ * Default constructor.
+ */
+ public XMLStreamReaderImpl() {
+ this(null);
+ }
+
+ /**
+ * Factory-based constructor.
+ */
+ XMLStreamReaderImpl(XMLInputFactoryImpl factory) {
+ _factory = factory;
+ }
+
+ /**
+ * Sets the input stream source for this XML stream reader
+ * (encoding retrieved from XML prolog if any). This method
+ * attempts to detect the encoding automatically.
+ *
+ * @param in the input source with unknown encoding.
+ */
+ public void setInput(InputStream in) throws XMLStreamException {
+ setInput(in, detectEncoding(in));
+ CharArray prologEncoding = getCharacterEncodingScheme();
+
+ // Checks if necessary to change the reader.
+ if ((prologEncoding != null) && !prologEncoding.equals(_encoding)
+ && !(isUTF8(prologEncoding) && isUTF8(_encoding))) {
+ // Changes reader (keep characters already read).
+ int startOffset = _readCount;
+ reset();
+ _startOffset = startOffset;
+ setInput(in, prologEncoding.toString());
+ }
+ }
+
+ private static boolean isUTF8(Object encoding) {
+ return encoding.equals("utf-8") || encoding.equals("UTF-8")
+ || encoding.equals("ASCII") || encoding.equals("utf8")
+ || encoding.equals("UTF8");
+ }
+
+ /**
+ * Sets the input stream source and encoding for this XML stream reader.
+ *
+ * @param in the input source.
+ * @param encoding the associated encoding.
+ */
+ public void setInput(InputStream in, String encoding)
+ throws XMLStreamException {
+ _encoding = encoding;
+ if (isUTF8(encoding)) { // Use our fast UTF-8 Reader.
+ setInput(_utf8StreamReader.setInput(in));
+ } else {
+ try {
+ setInput(new InputStreamReader(in, encoding));
+ } catch (UnsupportedEncodingException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+ }
+
+ /**
+ * Sets the reader input source for this XML stream reader.
+ * This method reads the prolog (if any).
+ *
+ * @param reader the input source reader.
+ * @see javolution.io.UTF8StreamReader
+ * @see javolution.io.UTF8ByteBufferReader
+ * @see javolution.io.CharSequenceReader
+ */
+ public void setInput(Reader reader) throws XMLStreamException {
+ if (_reader != null)
+ throw new IllegalStateException("Reader not closed or reset");
+ _reader = reader;
+ try { // Reads prolog (if there)
+ int readCount = reader.read(_readBuffer, _startOffset,
+ _readBuffer.length - _startOffset);
+ _readCount = (readCount >= 0) ? readCount + _startOffset
+ : _startOffset;
+ if ((_readCount >= 5) && (_readBuffer[0] == '<')
+ && (_readBuffer[1] == '?') && (_readBuffer[2] == 'x')
+ && (_readBuffer[3] == 'm') && (_readBuffer[4] == 'l')
+ && (_readBuffer[5] == ' ')) { // Prolog detected.
+ next(); // Processing instruction.
+ _prolog = this.getPIData();
+ _index = _prolog.offset() + _prolog.length(); // Keep prolog.
+ _start = _index; // Default state.
+ _eventType = START_DOCUMENT; // Resets to START_DOCUMENT.
+ }
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Returns the current depth of the element. Outside the root element,
+ * the depth is 0. The depth is incremented by 1 when a start tag is
+ * reached. The depth is decremented AFTER the end tag event was observed.
+ * [code]
+ * <!-- outside --> 0
+ * <root> 1
+ * sometext 1
+ * <foobar> 2
+ * </foobar> 2
+ * </root> 1
+ * <!-- outside --> 0 [/code]
+ *
+ * @return the nesting depth.
+ */
+ public int getDepth() {
+ return _depth;
+ }
+
+ /**
+ * Returns the qualified name of the current event.
+ *
+ * @return the qualified name.
+ * @throws IllegalStateException if this not a START_ELEMENT or END_ELEMENT.
+ */
+ public CharArray getQName() {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw new IllegalStateException(
+ "Not a start element or an end element");
+ return _qName;
+ }
+
+ /**
+ * Returns the qualified name of the element at the specified level.
+ * This method can be used to retrieve the XPath of the current element.
+ *
+ * @return the qualified name of the element at the specified level.
+ * @throws IllegalArgumentException if <code>depth > getDepth()</code>
+ */
+ public CharArray getQName(int depth) {
+ if (depth > this.getDepth())
+ throw new IllegalArgumentException();
+ return _elemStack[depth];
+ }
+
+ /**
+ * Returns the current attributes (SAX2-Like).
+ *
+ * @return returns the number of attributes.
+ * @throws IllegalStateException if not a START_ELEMENT.
+ */
+ public Attributes getAttributes() {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw new IllegalStateException("Not a start element");
+ return _attributes;
+ }
+
+ /**
+ * Defines a custom entities to replacement text mapping for this reader.
+ * For example:[code]
+ * FastMap<String, String> HTML_ENTITIES = new FastMap<String, String>();
+ * HTML_ENTITIES.put("nbsp", " ");
+ * HTML_ENTITIES.put("copy", "©");
+ * HTML_ENTITIES.put("eacute", "é");
+ * ...
+ * XMLStreamReaderImpl reader = new XMLStreamReaderImpl();
+ * reader.setEntities(HTML_ENTITIES);
+ * [/code]
+ * The entities mapping may be changed dynamically (e.g.
+ * after reading the DTD and all external entities references are resolved).
+ *
+ * @param entities the entities to replacement texts mapping
+ * (both must be <code>CharSequence</code> instances).
+ */
+ public void setEntities(Map<String, String> entities) {
+ _entities.setEntitiesMapping(entities);
+ }
+
+ /**
+ * Returns the textual representation of this reader current state.
+ *
+ * @return the textual representation of the current state.
+ */
+ public String toString() {
+ return "XMLStreamReader - State: " + NAMES_OF_EVENTS[_eventType]
+ + ", Location: " + _location.toString();
+ }
+
+ // Implements XMLStreamReader Interface.
+ public int next() throws XMLStreamException {
+
+ // Clears previous state.
+ if (_eventType == START_ELEMENT) {
+ if (_isEmpty) { // Previous empty tag, generates END_TAG automatically.
+ _isEmpty = false;
+ return _eventType = END_ELEMENT;
+ }
+ } else if (_eventType == END_ELEMENT) {
+ _namespaces.pop();
+ CharArray startElem = _elemStack[_depth--];
+ _start = _index = startElem.offset();
+ while (_seqs[--_seqsIndex] != startElem) { // Recycles CharArray instances.
+ }
+ }
+ // Reader loop.
+ while (true) {
+
+ // Main character reading block.
+ if ((_readIndex >= _readCount) && isEndOfStream())
+ return _eventType; // END_DOCUMENT or CHARACTERS.
+ char c = _readBuffer[_readIndex++];
+ if (c <= '&')
+ c = (c == '&') ? replaceEntity()
+ : (c < ' ') ? handleEndOfLine(c) : c;
+ _data[_index++] = c;
+
+ // Main processing.
+ //
+ switch (_state) {
+
+ case STATE_CHARACTERS:
+ while (true) { // Read characters data all at once.
+
+ if (c == '<') {
+ int length = _index - _start - 1;
+ if (length > 0) {
+ if (_charactersPending) {
+ _text.setArray(_data, _text.offset(),
+ _text.length() + length); // Coalescing.
+ } else {
+ _text = newSeq(_start, length);
+ _charactersPending = true;
+ }
+ _start = _index - 1; // Keeps '<' as part of markup.
+ }
+ _state = STATE_MARKUP;
+ break;
+ }
+
+ // Local character reading block.
+ if ((_readIndex >= _readCount) && isEndOfStream())
+ return _eventType;
+ c = _readBuffer[_readIndex++];
+ if (c <= '&')
+ c = (c == '&') ? replaceEntity()
+ : (c < ' ') ? handleEndOfLine(c) : c;
+ _data[_index++] = c;
+ }
+ break;
+
+ case STATE_CDATA:
+ while (true) { // Reads CDATA all at once.
+
+ if ((c == '>') && (_index - _start >= 3)
+ && (_data[_index - 2] == ']')
+ && (_data[_index - 3] == ']')) {
+ _index -= 3;
+ int length = _index - _start;
+ if (length > 0) { // Not empty.
+ if (_charactersPending) {
+ _text.setArray(_data, _text.offset(),
+ _text.length() + length); // Coalescing.
+ } else {
+ _text = newSeq(_start, length);
+ _charactersPending = true;
+ }
+ }
+ _start = _index;
+ _state = STATE_CHARACTERS;
+ break;
+ }
+
+ // Local character reading block.
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ c = _readBuffer[_readIndex++];
+ if (c < ' ')
+ c = handleEndOfLine(c);
+ _data[_index++] = c;
+ }
+ break;
+
+ case STATE_DTD:
+ if (c == '>') {
+ _text = newSeq(_start, _index - _start);
+ _index = _start; // Do not keep DTD.
+ _state = STATE_CHARACTERS;
+ return _eventType = DTD;
+ } else if (c == '[') {
+ _state = STATE_DTD_INTERNAL;
+ }
+ break;
+
+ case STATE_DTD_INTERNAL:
+ if (c == ']') {
+ _state = STATE_DTD;
+ }
+ break;
+
+ case STATE_MARKUP: // Starts with '<'
+ if (_index - _start == 2) {
+ if (c == '/') {
+ _start = _index = _index - 2;
+ _state = STATE_CLOSE_TAGxREAD_ELEM_NAME;
+ _prefixSep = -1;
+ if (_charactersPending) { // Flush characters event.
+ _charactersPending = false;
+ return _eventType = CHARACTERS;
+ }
+ } else if (c == '?') {
+ _start = _index = _index - 2;
+ _state = STATE_PI;
+ if (_charactersPending) { // Flush characters event.
+ _charactersPending = false;
+ return _eventType = CHARACTERS;
+ }
+ } else if (c != '!') { // Element tag (first letter).
+ _data[_start] = c;
+ _index = _start + 1;
+ _state = STATE_OPEN_TAGxREAD_ELEM_NAME;
+ _prefixSep = -1;
+ if (_charactersPending) { // Flush character event.
+ _charactersPending = false;
+ return _eventType = CHARACTERS;
+ }
+ }
+ } else if ((_index - _start == 4)
+ && (_data[_start + 1] == '!')
+ && (_data[_start + 2] == '-')
+ && (_data[_start + 3] == '-')) {
+ _start = _index = _index - 4; // Removes <!--
+ _state = STATE_COMMENT;
+ if (_charactersPending) { // Flush character event.
+ _charactersPending = false;
+ return _eventType = CHARACTERS;
+ }
+
+ } else if ((_index - _start == 9)
+ && (_data[_start + 1] == '!')
+ && (_data[_start + 2] == '[')
+ && (_data[_start + 3] == 'C')
+ && (_data[_start + 4] == 'D')
+ && (_data[_start + 5] == 'A')
+ && (_data[_start + 6] == 'T')
+ && (_data[_start + 7] == 'A')
+ && (_data[_start + 8] == '[')) {
+ _start = _index = _index - 9; // Do not keep <![CDATA[
+ _state = STATE_CDATA;
+
+ } else if ((_index - _start == 9)
+ && (_data[_start + 1] == '!')
+ && (_data[_start + 2] == 'D')
+ && (_data[_start + 3] == 'O')
+ && (_data[_start + 4] == 'C')
+ && (_data[_start + 5] == 'T')
+ && (_data[_start + 6] == 'Y')
+ && (_data[_start + 7] == 'P')
+ && (_data[_start + 8] == 'E')) {
+ // Keeps <!DOCTYPE as part of DTD.
+ _state = STATE_DTD;
+ } else {
+ // Ignores, e.g. <!ELEMENT <!ENTITY...
+ }
+ break;
+
+ case STATE_COMMENT:
+ while (true) { // Read comment all at once.
+
+ if ((c == '>') && (_index - _start >= 3)
+ && (_data[_index - 2] == '-')
+ && (_data[_index - 3] == '-')) {
+ _index -= 3; // Removes -->
+ _text = newSeq(_start, _index - _start);
+ _state = STATE_CHARACTERS;
+ _index = _start; // Do not keep comments.
+ return _eventType = COMMENT;
+ }
+
+ // Local character reading block.
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ c = _readBuffer[_readIndex++];
+ if (c < ' ')
+ c = handleEndOfLine(c);
+ _data[_index++] = c;
+ }
+
+ case STATE_PI:
+ if ((c == '>') && (_index - _start >= 2)
+ && (_data[_index - 2] == '?')) {
+ _index -= 2; // Removes ?>
+ _text = newSeq(_start, _index - _start);
+ _state = STATE_CHARACTERS;
+ _index = _start; // Do not keep processing instructions.
+ return _eventType = PROCESSING_INSTRUCTION;
+ }
+ break;
+
+ // OPEN_TAG:
+ case STATE_OPEN_TAGxREAD_ELEM_NAME:
+ _attributes.reset();
+ _namespaces.push();
+ while (true) { // Read element name all at once.
+
+ if (c < '@') { // Else avoid multiple checks.
+ if (c == '>') {
+ _qName = newSeq(_start, --_index - _start);
+ _start = _index;
+ _state = STATE_CHARACTERS;
+ processStartTag();
+ _isEmpty = false;
+ return _eventType = START_ELEMENT;
+ } else if (c == '/') {
+ _qName = newSeq(_start, --_index - _start);
+ _start = _index;
+ _state = STATE_OPEN_TAGxEMPTY_TAG;
+ break;
+ } else if (c == ':') {
+ _prefixSep = _index - 1;
+ } else if (c <= ' ') {
+ _qName = newSeq(_start, --_index - _start);
+ _state = STATE_OPEN_TAGxELEM_NAME_READ;
+ break;
+ }
+ }
+
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ c = _data[_index++] = _readBuffer[_readIndex++];
+ }
+ break;
+
+ case STATE_OPEN_TAGxELEM_NAME_READ:
+ if (c == '>') {
+ _start = --_index;
+ _state = STATE_CHARACTERS;
+ processStartTag();
+ _isEmpty = false;
+ return _eventType = START_ELEMENT;
+ } else if (c == '/') {
+ _state = STATE_OPEN_TAGxEMPTY_TAG;
+ } else if (c > ' ') {
+ _start = _index - 1; // Includes current character.
+ _attrPrefixSep = -1;
+ _state = STATE_OPEN_TAGxREAD_ATTR_NAME;
+ }
+ break;
+
+ case STATE_OPEN_TAGxREAD_ATTR_NAME:
+ while (true) { // Read attribute name all at once.
+
+ if (c < '@') { // Else avoid multiple checks.
+ if (c <= ' ') {
+ _attrQName = newSeq(_start, --_index - _start);
+ _state = STATE_OPEN_TAGxATTR_NAME_READ;
+ break;
+ } else if (c == '=') {
+ _attrQName = newSeq(_start, --_index - _start);
+ _state = STATE_OPEN_TAGxEQUAL_READ;
+ break;
+ } else if (c == ':') {
+ _attrPrefixSep = _index - 1;
+ }
+ }
+
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ _data[_index++] = c = _readBuffer[_readIndex++];
+ }
+ break;
+
+ case STATE_OPEN_TAGxATTR_NAME_READ:
+ if (c == '=') {
+ --_index;
+ _state = STATE_OPEN_TAGxEQUAL_READ;
+ } else if (c > ' ') { throw new XMLStreamException(
+ "'=' expected", _location); }
+ break;
+
+ case STATE_OPEN_TAGxEQUAL_READ:
+ if (c == '\'') {
+ _start = --_index;
+ _state = STATE_OPEN_TAGxREAD_ATTR_VALUE_SIMPLE_QUOTE;
+ } else if (c == '\"') {
+ _start = --_index;
+ _state = STATE_OPEN_TAGxREAD_ATTR_VALUE_DOUBLE_QUOTE;
+ } else if (c > ' ') { throw new XMLStreamException(
+ "Quotes expected", _location); }
+ break;
+
+ case STATE_OPEN_TAGxREAD_ATTR_VALUE_SIMPLE_QUOTE:
+ while (true) { // Read attribute value all at once.
+
+ if (c == '\'') {
+ _attrValue = newSeq(_start, --_index - _start);
+ processAttribute();
+ _state = STATE_OPEN_TAGxELEM_NAME_READ;
+ break;
+ }
+
+ // Local character reading block.
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ c = _readBuffer[_readIndex++];
+ if (c == '&')
+ c = replaceEntity();
+ _data[_index++] = c;
+ }
+ break;
+
+ case STATE_OPEN_TAGxREAD_ATTR_VALUE_DOUBLE_QUOTE:
+ while (true) { // Read attribute value all at once.
+
+ if (c == '\"') {
+ _attrValue = newSeq(_start, --_index - _start);
+ processAttribute();
+ _state = STATE_OPEN_TAGxELEM_NAME_READ;
+ break;
+ }
+
+ // Local character reading block.
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ c = _readBuffer[_readIndex++];
+ if (c == '&')
+ c = replaceEntity();
+ _data[_index++] = c;
+ }
+ break;
+
+ case STATE_OPEN_TAGxEMPTY_TAG:
+ if (c == '>') {
+ _start = --_index;
+ _state = STATE_CHARACTERS;
+ processStartTag();
+ _isEmpty = true;
+ return _eventType = START_ELEMENT;
+ } else {
+ throw new XMLStreamException("'>' expected", _location);
+ }
+
+ // CLOSE_TAG:
+ case STATE_CLOSE_TAGxREAD_ELEM_NAME:
+ while (true) { // Element name can be read all at once.
+
+ if (c < '@') { // Else avoid multiple checks.
+ if (c == '>') {
+ _qName = newSeq(_start, --_index - _start);
+ _start = _index;
+ _state = STATE_CHARACTERS;
+ processEndTag();
+ return _eventType = END_ELEMENT;
+ } else if (c == ':') {
+ _prefixSep = _index - 1;
+ } else if (c <= ' ') {
+ _qName = newSeq(_start, --_index - _start);
+ _state = STATE_CLOSE_TAGxELEM_NAME_READ;
+ break;
+ }
+ }
+
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ c = _data[_index++] = _readBuffer[_readIndex++];
+ }
+ break;
+
+ case STATE_CLOSE_TAGxELEM_NAME_READ:
+ if (c == '>') {
+ _start = --_index;
+ _state = STATE_CHARACTERS;
+ processEndTag();
+ return _eventType = END_ELEMENT;
+ } else if (c > ' ') { throw new XMLStreamException(
+ "'>' expected", _location); }
+ break;
+
+ default:
+ throw new XMLStreamException("State unknown: " + _state,
+ _location);
+ }
+ }
+ }
+
+ // Defines parsing states (keep values close together to avoid lookup).
+ private static final int STATE_CHARACTERS = 1;
+
+ private static final int STATE_MARKUP = 2;
+
+ private static final int STATE_COMMENT = 3;
+
+ private static final int STATE_PI = 4;
+
+ private static final int STATE_CDATA = 5;
+
+ private static final int STATE_OPEN_TAGxREAD_ELEM_NAME = 6;
+
+ private static final int STATE_OPEN_TAGxELEM_NAME_READ = 7;
+
+ private static final int STATE_OPEN_TAGxREAD_ATTR_NAME = 8;
+
+ private static final int STATE_OPEN_TAGxATTR_NAME_READ = 9;
+
+ private static final int STATE_OPEN_TAGxEQUAL_READ = 10;
+
+ private static final int STATE_OPEN_TAGxREAD_ATTR_VALUE_SIMPLE_QUOTE = 11;
+
+ private static final int STATE_OPEN_TAGxREAD_ATTR_VALUE_DOUBLE_QUOTE = 12;
+
+ private static final int STATE_OPEN_TAGxEMPTY_TAG = 13;
+
+ private static final int STATE_CLOSE_TAGxREAD_ELEM_NAME = 14;
+
+ private static final int STATE_CLOSE_TAGxELEM_NAME_READ = 15;
+
+ private static final int STATE_DTD = 16;
+
+ private static final int STATE_DTD_INTERNAL = 17;
+
+ /**
+ * Reloads data buffer.
+ *
+ * @param detectEndOfStream indicates
+ * @return <code>true</code> if the buffer has been reloaded;
+ * <code>false</code> if the end of stream has being reached
+ * and the event type (CHARACTERS or END_DOCUMENT) has been set.
+ */
+ private void reloadBuffer() throws XMLStreamException {
+ if (_reader == null)
+ throw new XMLStreamException("Input not specified");
+ _location._column += _readIndex;
+ _location._charactersRead += _readIndex;
+ _readIndex = 0;
+ try {
+ _readCount = _reader.read(_readBuffer, 0, _readBuffer.length);
+ if ((_readCount <= 0)
+ && ((_depth != 0) || (_state != STATE_CHARACTERS)))
+ throw new XMLStreamException("Unexpected end of document",
+ _location);
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ while ((_index + _readCount) >= _data.length) { // Potential overflow.
+ increaseDataBuffer();
+ }
+ }
+
+ /**
+ * Detects end of stream.
+ *
+ * @return <code>true</code> if end of stream has being reached
+ * and the event type (CHARACTERS or END_DOCUMENT) has been set;
+ * <code>false</code> otherwise.
+ */
+ private boolean isEndOfStream() throws XMLStreamException {
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ if (_readCount <= 0) {
+ // _state == STATE_CHARACTERS (otherwise reloadBuffer() exception)
+ if (_eventType == END_DOCUMENT)
+ throw new XMLStreamException(
+ "End document has already been reached");
+ int length = _index - _start;
+ if (length > 0) { // Flushes trailing characters.
+ if (_charactersPending) {
+ _text.setArray(_data, _text.offset(), _text.length()
+ + length); // Coalescing.
+ } else {
+ _text = newSeq(_start, length);
+ }
+ _start = _index;
+ _eventType = CHARACTERS;
+ } else {
+ _eventType = END_DOCUMENT;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Handles end of line as per XML Spec. 2.11
+ *
+ * @param c the potential end of line character.
+ * @return the replacement character for end of line.
+ */
+ private char handleEndOfLine(char c) throws XMLStreamException {
+ if (c == 0xD) { // Replaces #xD with #xA
+ // Unless next char is #xA, then skip,
+ // #xD#xA will be replaced by #xA
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ if ((_readIndex < _readCount) && (_readBuffer[_readIndex] == 0xA))
+ _readIndex++; // Skips 0xD
+ c = (char) 0xA;
+ }
+ if (c == 0xA) {
+ _location._line++;
+ _location._column = -_readIndex; // column = 0
+ } else if (c == 0x0) { throw new XMLStreamException(
+ "Illegal XML character U+0000", _location); }
+ return c;
+ }
+
+ /**
+ * Replaces an entity if the current state allows it.
+ *
+ * @return the next character after the text replacement or '&' if no
+ * replacement took place.
+ */
+ private char replaceEntity() throws XMLStreamException {
+ if ((_state == STATE_COMMENT) || (_state == STATE_PI)
+ || (_state == STATE_CDATA))
+ return '&'; // (&2.4)
+
+ int start = _index; // Index of first replacement character.
+ _data[_index++] = '&';
+ while (true) {
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ char c = _data[_index++] = _readBuffer[_readIndex++];
+ if (c == ';')
+ break;
+ if (c <= ' ')
+ throw new XMLStreamException("';' expected", _location);
+ }
+ // Ensures that the replacement string holds in the data buffer.
+ while (start + _entities.getMaxLength() >= _data.length) {
+ increaseDataBuffer();
+ }
+
+ // Replaces the entity.
+ int length = _entities.replaceEntity(_data, start, _index - start);
+
+ // Returns the next character after entity unless ampersand.
+ _index = start + length;
+
+ // Local character reading block.
+ if (_readIndex >= _readCount)
+ reloadBuffer();
+ char c = _readBuffer[_readIndex++];
+ return (c == '&') ? (c = replaceEntity()) : c;
+ }
+
+ /**
+ * Processes the attribute just read.
+ */
+ private void processAttribute() throws XMLStreamException {
+ if (_attrPrefixSep < 0) { // No prefix.
+ if (isXMLNS(_attrQName)) { // Sets default namespace.
+ _namespaces.setPrefix(_namespaces._defaultNsPrefix, _attrValue);
+ } else {
+ _attributes.addAttribute(_attrQName, null, _attrQName,
+ _attrValue);
+ }
+ } else { // Prefix.
+ final int offset = _attrQName.offset();
+ final int length = _attrQName.length();
+
+ CharArray prefix = newSeq(offset, _attrPrefixSep - offset);
+
+ CharArray localName = newSeq(_attrPrefixSep + 1, offset + length
+ - _attrPrefixSep - 1);
+
+ if (isXMLNS(prefix)) { // Namespace association.
+ _namespaces.setPrefix(localName, _attrValue);
+ } else {
+ _attributes.addAttribute(localName, prefix, _attrQName,
+ _attrValue);
+ }
+ }
+ }
+
+ private static boolean isXMLNS(CharArray chars) {
+ return (chars.length() == 5) && (chars.charAt(0) == 'x')
+ && (chars.charAt(1) == 'm') && (chars.charAt(2) == 'l')
+ && (chars.charAt(3) == 'n') && (chars.charAt(4) == 's');
+ }
+
+ private void processEndTag() throws XMLStreamException {
+ if (!_qName.equals(_elemStack[_depth]))
+ throw new XMLStreamException("Unexpected end tag for " + _qName,
+ _location);
+ }
+
+ private void processStartTag() throws XMLStreamException {
+ if (++_depth >= _elemStack.length) {
+ increaseStack();
+ }
+ _elemStack[_depth] = _qName;
+ }
+
+ // Implements Reusable.
+ public void reset() {
+ // Resets all members (alphabetically ordered).
+ _attributes.reset();
+ _attrPrefixSep = 0;
+ _attrQName = null;
+ _attrValue = null;
+ _attrQName = null;
+ _charactersPending = false;
+ _encoding = null;
+ _entities.reset();
+ _eventType = START_DOCUMENT;
+ _index = 0;
+ _isEmpty = false;
+ _location.reset();
+ _namespaces.reset();
+ _prolog = null;
+ _readCount = 0;
+ _reader = null;
+ _depth = 0;
+ _readIndex = 0;
+ _seqsIndex = 0;
+ _start = 0;
+ _startOffset = 0;
+ _state = STATE_CHARACTERS;
+ _utf8StreamReader.reset();
+
+ // Recycles if factory produced.
+ if (_factory != null)
+ _factory.recycle(this);
+ }
+
+ // Returns a new character sequence from the pool.
+ private CharArray newSeq(int offset, int length) {
+ CharArray seq = (_seqsIndex < _seqsCapacity) ? _seqs[_seqsIndex++]
+ : newSeq2();
+ return seq.setArray(_data, offset, length);
+ }
+
+ private CharArray newSeq2() {
+ _createSeqLogic.run();
+ return _seqs[_seqsIndex++];
+ }
+
+ private final Runnable _createSeqLogic = new Runnable() {
+
+ public void run() {
+ if (_seqsCapacity >= _seqs.length) { // Resizes.
+ CharArray[] tmp = new CharArray[_seqs.length * 2];
+ System.arraycopy(_seqs, 0, tmp, 0, _seqs.length);
+ _seqs = tmp;
+ }
+ CharArray seq = new CharArray();
+ _seqs[_seqsCapacity++] = seq;
+ }
+
+ };
+
+ private CharArray[] _seqs = new CharArray[256];
+
+ private int _seqsIndex;
+
+ private int _seqsCapacity;
+
+ // Increases internal data buffer capacity.
+ private void increaseDataBuffer() {
+ // Note: The character data at any nesting level is discarded
+ // only when moving to outer nesting level (due to coalescing).
+ // This accumulation may cause resize of the data buffer if
+ // numerous elements at the same nesting level are separated by
+ // spaces or indentation.
+ char[] tmp = new char[_data.length * 2];
+ javolution.context.LogContext.info(new CharArray(
+ "XMLStreamReaderImpl: Data buffer increased to " + tmp.length));
+ System.arraycopy(_data, 0, tmp, 0, _data.length);
+ _data = tmp;
+ }
+
+ // Increases statck.
+ private void increaseStack() {
+ CharArray[] tmp = new CharArray[_elemStack.length * 2];
+ javolution.context.LogContext.info(new CharArray(
+ "XMLStreamReaderImpl: CharArray stack increased to "
+ + tmp.length));
+ System.arraycopy(_elemStack, 0, tmp, 0, _elemStack.length);
+ _elemStack = tmp;
+ }
+
+ /**
+ * This inner class represents the parser location.
+ */
+ private final class LocationImpl implements Location {
+
+ int _column;
+
+ int _line;
+
+ int _charactersRead;
+
+ public int getLineNumber() {
+ return _line + 1;
+ }
+
+ public int getColumnNumber() {
+ return _column + _readIndex;
+ }
+
+ public int getCharacterOffset() {
+ return _charactersRead + _readIndex;
+ }
+
+ public String getPublicId() {
+ return null; // Not available.
+ }
+
+ public String getSystemId() {
+ return null; // Not available.
+ }
+
+ public String toString() {
+ return "Line " + getLineNumber() + ", Column " + getColumnNumber();
+ }
+
+ public void reset() {
+ _line = 0;
+ _column = 0;
+ _charactersRead = 0;
+ }
+
+ }
+
+ //////////////////////////////////////////
+ // Implements XMLStreamReader Interface //
+ //////////////////////////////////////////
+ // Implements XMLStreamReader Interface.
+ public void require(int type, CharSequence namespaceURI,
+ CharSequence localName) throws XMLStreamException {
+ if (_eventType != type)
+ throw new XMLStreamException("Expected event: "
+ + NAMES_OF_EVENTS[type] + ", found event: "
+ + NAMES_OF_EVENTS[_eventType]);
+ if ((namespaceURI != null) && !getNamespaceURI().equals(namespaceURI))
+ throw new XMLStreamException("Expected namespace URI: "
+ + namespaceURI + ", found: " + getNamespaceURI());
+ if ((localName != null) && !getLocalName().equals(localName))
+ throw new XMLStreamException("Expected local name: " + localName
+ + ", found: " + getLocalName());
+ }
+
+ // Implements XMLStreamReader Interface.
+ public CharArray getElementText() throws XMLStreamException {
+ // Derived from interface specification code.
+ if (getEventType() != XMLStreamConstants.START_ELEMENT) { throw new XMLStreamException(
+ "Parser must be on START_ELEMENT to read next text",
+ getLocation()); }
+ CharArray text = null;
+ int eventType = next();
+ while (eventType != XMLStreamConstants.END_ELEMENT) {
+ if (eventType == XMLStreamConstants.CHARACTERS) {
+ if (text == null) {
+ text = getText();
+ } else { // Merge (adjacent text, comments and PI are not kept).
+ text.setArray(_data, text.offset(), text.length()
+ + getText().length());
+ }
+ } else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
+ || eventType == XMLStreamConstants.COMMENT) {
+ // Skips (not kept).
+ } else if (eventType == XMLStreamConstants.END_DOCUMENT) {
+ throw new XMLStreamException(
+ "Unexpected end of document when reading element text content",
+ getLocation());
+ } else if (eventType == XMLStreamConstants.START_ELEMENT) {
+ throw new XMLStreamException(
+ "Element text content may not contain START_ELEMENT",
+ getLocation());
+ } else {
+ throw new XMLStreamException("Unexpected event type "
+ + NAMES_OF_EVENTS[eventType], getLocation());
+ }
+ eventType = next();
+ }
+ return (text != null) ? text : newSeq(0, 0);
+ }
+
+ // Implements XMLStreamReader Interface.
+ public Object getProperty(String name) throws IllegalArgumentException {
+ if (name.equals(XMLInputFactory.IS_COALESCING)) {
+ return Boolean.TRUE;
+ } else if (name.equals(XMLInputFactory.ENTITIES)) {
+ return _entities.getEntitiesMapping();
+ } else {
+ throw new IllegalArgumentException("Property: " + name
+ + " not supported");
+ }
+ }
+
+ // Implements XMLStreamReader Interface.
+ public void close() throws XMLStreamException {
+ reset();
+ }
+
+ public int getAttributeCount() {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ return _attributes.getLength();
+ }
+
+ public CharArray getAttributeLocalName(int index) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ return _attributes.getLocalName(index);
+ }
+
+ public CharArray getAttributeNamespace(int index) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ CharArray prefix = _attributes.getPrefix(index);
+ return _namespaces.getNamespaceURINullAllowed(prefix);
+ }
+
+ public CharArray getAttributePrefix(int index) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ return _attributes.getPrefix(index);
+ }
+
+ public CharArray getAttributeType(int index) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ return _attributes.getType(index);
+ }
+
+ public CharArray getAttributeValue(CharSequence uri, CharSequence localName) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ return (uri == null) ? _attributes.getValue(localName) : _attributes
+ .getValue(uri, localName);
+ }
+
+ public CharArray getAttributeValue(int index) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw illegalState("Not a start element");
+ return _attributes.getValue(index);
+ }
+
+ public CharArray getCharacterEncodingScheme() {
+ return readPrologAttribute(ENCODING);
+ }
+
+ private static final CharArray ENCODING = new CharArray("encoding");
+
+ public String getEncoding() {
+ return _encoding;
+ }
+
+ public int getEventType() {
+ return _eventType;
+ }
+
+ public CharArray getLocalName() {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw illegalState("Not a start or end element");
+ if (_prefixSep < 0)
+ return _qName;
+ CharArray localName = newSeq(_prefixSep + 1,
+ _qName.offset() + _qName.length() - _prefixSep - 1);
+ return localName;
+ }
+
+ public Location getLocation() {
+ return _location;
+ }
+
+ public int getNamespaceCount() {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw illegalState("Not a start or end element");
+ return _namespaces._namespacesCount[_depth];
+ }
+
+ public CharArray getNamespacePrefix(int index) {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw illegalState("Not a start or end element");
+ return _namespaces._prefixes[index];
+ }
+
+ public CharArray getNamespaceURI(CharSequence prefix) {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw illegalState("Not a start or end element");
+ return _namespaces.getNamespaceURI(prefix);
+ }
+
+ public CharArray getNamespaceURI(int index) {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw illegalState("Not a start or end element");
+ return _namespaces._namespaces[index];
+ }
+
+ public NamespaceContext getNamespaceContext() {
+ return _namespaces;
+ }
+
+ public CharArray getNamespaceURI() {
+ return _namespaces.getNamespaceURINullAllowed(getPrefix());
+ }
+
+ public CharArray getPrefix() {
+ if ((_eventType != XMLStreamConstants.START_ELEMENT)
+ && (_eventType != XMLStreamConstants.END_ELEMENT))
+ throw illegalState("Not a start or end element");
+ if (_prefixSep < 0)
+ return null;
+ int offset = _qName.offset();
+ CharArray prefix = newSeq(offset, _prefixSep - offset);
+ return prefix;
+ }
+
+ public CharArray getPIData() {
+ if (_eventType != XMLStreamConstants.PROCESSING_INSTRUCTION)
+ throw illegalState("Not a processing instruction");
+ int offset = _text.indexOf(' ') + _text.offset() + 1;
+ CharArray piData = newSeq(offset, _text.length() - offset);
+ return piData;
+ }
+
+ public CharArray getPITarget() {
+ if (_eventType != XMLStreamConstants.PROCESSING_INSTRUCTION)
+ throw illegalState("Not a processing instruction");
+ CharArray piTarget = newSeq(_text.offset(),
+ _text.indexOf(' ') + _text.offset());
+ return piTarget;
+ }
+
+ public CharArray getText() {
+ if ((_eventType != XMLStreamConstants.CHARACTERS)
+ && (_eventType != XMLStreamConstants.COMMENT)
+ && (_eventType != XMLStreamConstants.DTD))
+ throw illegalState("Not a text event");
+ return _text;
+ }
+
+ public char[] getTextCharacters() {
+ return getText().array();
+ }
+
+ public int getTextCharacters(int sourceStart, char[] target,
+ int targetStart, int length) throws XMLStreamException {
+ CharArray text = getText();
+ int copyLength = Math.min(length, text.length());
+ System.arraycopy(text.array(), sourceStart + text.offset(), target,
+ targetStart, copyLength);
+ return copyLength;
+ }
+
+ public int getTextLength() {
+ return getText().length();
+ }
+
+ public int getTextStart() {
+ return getText().offset();
+ }
+
+ public CharArray getVersion() {
+ return readPrologAttribute(VERSION);
+ }
+
+ private static final CharArray VERSION = new CharArray("version");
+
+ public boolean isStandalone() {
+ CharArray standalone = readPrologAttribute(STANDALONE);
+ return (standalone != null) ? standalone.equals("no") : true;
+ }
+
+ public boolean standaloneSet() {
+ return readPrologAttribute(STANDALONE) != null;
+ }
+
+ private static final CharArray STANDALONE = new CharArray("standalone");
+
+ public boolean hasName() {
+ return (_eventType == XMLStreamConstants.START_ELEMENT)
+ || (_eventType == XMLStreamConstants.END_ELEMENT);
+ }
+
+ public boolean hasNext() throws XMLStreamException {
+ return _eventType != XMLStreamConstants.END_DOCUMENT;
+ }
+
+ public boolean hasText() {
+ return ((_eventType == XMLStreamConstants.CHARACTERS)
+ || (_eventType == XMLStreamConstants.COMMENT) || (_eventType == XMLStreamConstants.DTD))
+ && (_text.length() > 0);
+ }
+
+ public boolean isAttributeSpecified(int index) {
+ if (_eventType != XMLStreamConstants.START_ELEMENT)
+ throw new IllegalStateException("Not a start element");
+ return _attributes.getValue(index) != null;
+ }
+
+ public boolean isCharacters() {
+ return _eventType == XMLStreamConstants.CHARACTERS;
+ }
+
+ public boolean isEndElement() {
+ return _eventType == XMLStreamConstants.END_ELEMENT;
+ }
+
+ public boolean isStartElement() {
+ return _eventType == XMLStreamConstants.START_ELEMENT;
+ }
+
+ public boolean isWhiteSpace() {
+ if (isCharacters()) {
+ char[] chars = _text.array();
+ for (int i = _text.offset(), end = _text.offset() + _text.length(); i < end;) {
+ if (!isWhiteSpace(chars[i++]))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // Whitespaces according to XML 1.1 Specification.
+ private static boolean isWhiteSpace(char c) {
+ return (c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA);
+ }
+
+ public int nextTag() throws XMLStreamException {
+ int eventType = next();
+ while (eventType == XMLStreamConstants.COMMENT
+ || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
+ || eventType == XMLStreamConstants.DTD
+ || (eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace())) {
+ eventType = next();
+ }
+ if (eventType != XMLStreamConstants.START_ELEMENT
+ && eventType != XMLStreamConstants.END_ELEMENT)
+ throw new XMLStreamException("Tag expected (but found "
+ + NAMES_OF_EVENTS[_eventType] + ")");
+ return eventType;
+ }
+
+ private IllegalStateException illegalState(String msg) {
+ return new IllegalStateException(msg + " ("
+ + NAMES_OF_EVENTS[_eventType] + ")");
+ }
+
+ private String detectEncoding(InputStream input) throws XMLStreamException {
+ // Autodetect encoding (see http://en.wikipedia.org/wiki/UTF-16)
+ int byte0;
+ try {
+ byte0 = input.read();
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ if (byte0 == -1)
+ throw new XMLStreamException("Premature End-Of-File");
+ if (byte0 == '<') { // UTF-8 or compatible encoding.
+ _readBuffer[_startOffset++] = '<';
+ return "UTF-8";
+ } else {
+ int byte1;
+ try {
+ byte1 = input.read();
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ if (byte1 == -1)
+ throw new XMLStreamException("Premature End-Of-File");
+ if ((byte0 == 0) && (byte1 == '<')) { // UTF-16 BIG ENDIAN
+ _readBuffer[_startOffset++] = '<';
+ return "UTF-16BE";
+ } else if ((byte0 == '<') && (byte1 == 0)) { // UTF-16 LITTLE ENDIAN
+ _readBuffer[_startOffset++] = '<';
+ return "UTF-16LE";
+ } else if ((byte0 == 0xFF) && (byte1 == 0xFE)) { // BOM for UTF-16 LITTLE ENDIAN
+ return "UTF-16";
+ } else if ((byte0 == 0xFE) && (byte1 == 0xFF)) { // BOM for UTF-16 BIG ENDIAN
+ return "UTF-16";
+ } else { // Encoding unknown (or no prolog) assumes UTF-8
+ _readBuffer[_startOffset++] = (char) byte0;
+ _readBuffer[_startOffset++] = (char) byte1;
+ return "UTF-8";
+ }
+ }
+ }
+
+ private final CharArray readPrologAttribute(CharSequence name) {
+ if (_prolog == null)
+ return null;
+ final int READ_EQUAL = 0;
+ final int READ_QUOTE = 1;
+ final int VALUE_SIMPLE_QUOTE = 2;
+ final int VALUE_DOUBLE_QUOTE = 3;
+
+ int i = _prolog.indexOf(name);
+ if (i >= 0) {
+ i += _prolog.offset();
+ int maxIndex = _prolog.offset() + _prolog.length();
+ i += name.length();
+ int state = READ_EQUAL;
+ int valueOffset = 0;
+ while (i < maxIndex) {
+ char c = _prolog.array()[i++];
+ switch (state) {
+ case READ_EQUAL:
+ if (c == '=') {
+ state = READ_QUOTE;
+ }
+ break;
+ case READ_QUOTE:
+ if (c == '"') {
+ state = VALUE_DOUBLE_QUOTE;
+ valueOffset = i;
+ } else if (c == '\'') {
+ state = VALUE_SIMPLE_QUOTE;
+ valueOffset = i;
+ }
+ break;
+ case VALUE_SIMPLE_QUOTE:
+ if (c == '\'')
+ return newSeq(valueOffset, i - valueOffset - 1);
+ break;
+ case VALUE_DOUBLE_QUOTE:
+ if (c == '"')
+ return newSeq(valueOffset, i - valueOffset - 1);
+ break;
+ }
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
[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)
Posted by ss...@apache.org.
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 > 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) >= 1E7) || (abs(f) < 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 > 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
[07/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/AtomicSortedMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/AtomicSortedMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/AtomicSortedMapImpl.java
new file mode 100644
index 0000000..c26c500
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/AtomicSortedMapImpl.java
@@ -0,0 +1,82 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import javolution.util.internal.map.AtomicMapImpl;
+import javolution.util.service.SortedMapService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * An atomic view over a sorted map (copy-on-write).
+ */
+public class AtomicSortedMapImpl<K, V> extends AtomicMapImpl<K, V> implements SortedMapService<K,V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public AtomicSortedMapImpl(SortedMapService<K, V> target) {
+ super(target);
+ }
+
+ @Override
+ public Comparator<? super K> comparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public SortedSetService<Map.Entry<K, V>> entrySet() {
+ return new SubSortedMapImpl<K,V>(this, null, null).entrySet();
+ }
+
+
+ @Override
+ public K firstKey() {
+ return targetView().firstKey();
+ }
+
+
+ @Override
+ public SortedMapService<K, V> headMap(K toKey) {
+ return new SubSortedMapImpl<K,V>(this, null, toKey);
+ }
+
+ @Override
+ public SortedSetService<K> keySet() {
+ return new SubSortedMapImpl<K,V>(this, null, null).keySet();
+ }
+
+ @Override
+ public K lastKey() {
+ return targetView().lastKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedMapService<K, V>[] split(int n, boolean updateable) {
+ return new SortedMapService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public SortedMapService<K, V> subMap(K fromKey, K toKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, toKey);
+ }
+
+ @Override
+ public SortedMapService<K, V> tailMap(K fromKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, null);
+ }
+
+ @Override
+ protected SortedMapService<K,V> targetView() {
+ return (SortedMapService<K,V>) super.targetView();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/FastSortedMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/FastSortedMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/FastSortedMapImpl.java
new file mode 100644
index 0000000..111bc1d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/FastSortedMapImpl.java
@@ -0,0 +1,115 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.util.Iterator;
+
+import javolution.util.function.Equality;
+import javolution.util.internal.table.sorted.FastSortedTableImpl;
+
+/**
+ * A map view over a sorted table of entries.
+ */
+public class FastSortedMapImpl<K, V> extends SortedMapView<K,V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ private FastSortedTableImpl<Entry<K,V>> entries
+ = new FastSortedTableImpl<Entry<K,V>>(new EntryComparator());
+ private final Equality<? super K> keyComparator;
+ private final Equality<? super V> valueComparator;
+
+ public FastSortedMapImpl(final Equality<? super K> keyComparator,
+ final Equality<? super V> valueComparator) {
+ super(null);
+ this.keyComparator = keyComparator;
+ this.valueComparator = valueComparator;
+ }
+
+ @Override
+ public void clear() {
+ entries.clear();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsKey(Object key) {
+ return entries.contains(new MapEntryImpl<K,V>((K)key, null));
+ }
+
+ @Override
+ public K firstKey() {
+ return entries.getFirst().getKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(Object key) {
+ int i = entries.indexOf(new MapEntryImpl<K,V>((K)key, null));
+ return (i >= 0) ? entries.get(i).getValue() : null;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return entries.isEmpty();
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return entries.iterator();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return keyComparator;
+ }
+
+ @Override
+ public K lastKey() {
+ return entries.getLast().getKey();
+ }
+
+ @Override
+ public V put(K key, V value) {
+ MapEntryImpl<K,V> entry = new MapEntryImpl<K,V>(key, value);
+ int i = entries.positionOf(entry);
+ if (i < size()) {
+ Entry<K,V> e = entries.get(i);
+ if (keyComparator().areEqual(key, e.getKey())) { // Entry exists.
+ V previous = e.getValue();
+ e.setValue(value);
+ return previous;
+ }
+ }
+ entries.add(i, entry);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V remove(Object key) {
+ int i = entries.indexOf(new MapEntryImpl<K,V>((K)key, null));
+ if (i < 0) return null;
+ Entry<K,V> e = entries.get(i);
+ V previous = e.getValue();
+ entries.remove(i);
+ return previous;
+ }
+
+ @Override
+ public int size() {
+ return entries.size();
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return valueComparator;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/MapEntryImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/MapEntryImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/MapEntryImpl.java
new file mode 100644
index 0000000..5693a43
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/MapEntryImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * The sorted map entry implementation (serializable).
+ */
+public final class MapEntryImpl<K, V> implements Map.Entry<K, V>, Serializable {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ K key;
+ V value;
+
+ public MapEntryImpl(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public K getKey() {
+ return key;
+ }
+
+ @Override
+ public V getValue() {
+ return value;
+ }
+
+ @Override
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ @Override
+ public String toString() {
+ return key + "=" + value;
+ }
+
+ }
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SharedSortedMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SharedSortedMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SharedSortedMapImpl.java
new file mode 100644
index 0000000..fecc094
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SharedSortedMapImpl.java
@@ -0,0 +1,107 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import javolution.util.internal.ReadWriteLockImpl;
+import javolution.util.internal.map.SharedMapImpl;
+import javolution.util.service.SortedMapService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * A shared view over a sorted map.
+ */
+public class SharedSortedMapImpl<K, V> extends SharedMapImpl<K, V> implements SortedMapService<K,V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SharedSortedMapImpl(SortedMapService<K, V> target) {
+ super(target);
+ }
+
+ public SharedSortedMapImpl(SortedMapService<K, V> target, ReadWriteLockImpl lock) {
+ super(target, lock);
+ }
+
+ @Override
+ public Comparator<? super K> comparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public SortedSetService<Map.Entry<K, V>> entrySet() {
+ return new SubSortedMapImpl<K,V>(this, null, null).entrySet();
+ }
+
+
+ @Override
+ public K firstKey() {
+ lock.readLock.lock();
+ try {
+ return target().firstKey();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+
+ @Override
+ public SortedMapService<K, V> headMap(K toKey) {
+ return new SubSortedMapImpl<K,V>(this, null, toKey);
+ }
+
+ @Override
+ public SortedSetService<K> keySet() {
+ return new SubSortedMapImpl<K,V>(this, null, null).keySet();
+ }
+
+ @Override
+ public K lastKey() {
+ lock.readLock.lock();
+ try {
+ return target().lastKey();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedMapService<K,V>[] split(int n, boolean updateable) {
+ SortedMapService<K,V>[] tmp;
+ lock.readLock.lock();
+ try {
+ tmp = target().split(n, updateable);
+ } finally {
+ lock.readLock.unlock();
+ }
+ SortedMapService<K,V>[] result = new SortedMapService[tmp.length];
+ for (int i = 0; i < tmp.length; i++) {
+ result[i] = new SharedSortedMapImpl<K,V>(tmp[i], lock); // Shares the same locks.
+ }
+ return result;
+ }
+
+ @Override
+ public SortedMapService<K, V> subMap(K fromKey, K toKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, toKey);
+ }
+
+ @Override
+ public SortedMapService<K, V> tailMap(K fromKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, null);
+ }
+
+ @Override
+ protected SortedMapService<K,V> target() {
+ return (SortedMapService<K,V>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SortedMapView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SortedMapView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SortedMapView.java
new file mode 100644
index 0000000..bb51d56
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SortedMapView.java
@@ -0,0 +1,163 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import javolution.util.internal.map.MapView;
+import javolution.util.internal.set.sorted.SubSortedSetImpl;
+import javolution.util.service.SortedMapService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * Sorted map view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ * When possible sub-classes should forward to the actual target for the methods
+ * isEmpty, size and clear rather than using the default implementation.
+ */
+public abstract class SortedMapView<K,V> extends MapView<K,V> implements SortedMapService<K,V> {
+
+ /** Entry Set View */
+ protected class EntrySortedSet extends EntrySet implements SortedSetService<Entry<K,V>> {
+ private static final long serialVersionUID = SortedMapView.serialVersionUID;
+
+ @Override
+ public Entry<K, V> first() {
+ K key = SortedMapView.this.firstKey();
+ V value = SortedMapView.this.get(key);
+ return new MapEntryImpl<K,V>(key, value);
+ }
+
+ @Override
+ public SortedSetService<Entry<K, V>> headSet(Entry<K, V> toElement) {
+ return new SubSortedSetImpl<Entry<K, V>>(this, null, toElement);
+ }
+
+ @Override
+ public java.util.Map.Entry<K, V> last() {
+ K key = SortedMapView.this.lastKey();
+ V value = SortedMapView.this.get(key);
+ return new MapEntryImpl<K,V>(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedSetService<Entry<K, V>>[] split(int n, boolean updateable) {
+ return new SortedSetService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public SortedSetService<java.util.Map.Entry<K, V>> subSet(
+ Entry<K, V> fromElement,
+ Entry<K, V> toElement) {
+ return new SubSortedSetImpl<Entry<K, V>>(this, fromElement, toElement);
+ }
+
+ @Override
+ public SortedSetService<Entry<K, V>> tailSet(Entry<K, V> fromElement) {
+ return new SubSortedSetImpl<Entry<K, V>>(this, fromElement, null);
+ }
+
+ }
+
+ /** Entry Key View */
+ protected class KeySortedSet extends KeySet implements SortedSetService<K> {
+ private static final long serialVersionUID = SortedMapView.serialVersionUID;
+
+ @Override
+ public K first() {
+ return SortedMapView.this.firstKey();
+ }
+
+ @Override
+ public SortedSetService<K> headSet(K toElement) {
+ return new SubSortedSetImpl<K>(this, null, toElement);
+ }
+
+ @Override
+ public K last() {
+ return SortedMapView.this.lastKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedSetService<K>[] split(int n, boolean updateable) {
+ return new SortedSetService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public SortedSetService<K> subSet(K fromElement, K toElement) {
+ return new SubSortedSetImpl<K>(this, fromElement, toElement);
+ }
+
+ @Override
+ public SortedSetService<K> tailSet(K fromElement) {
+ return new SubSortedSetImpl<K>(this, fromElement, null);
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public SortedMapView(SortedMapService<K,V> target) {
+ super(target);
+ }
+
+ @Override
+ public Comparator<? super K> comparator() {
+ return keyComparator();
+ }
+
+ @Override
+ public SortedSetService<Map.Entry<K, V>> entrySet() {
+ return new EntrySortedSet();
+ }
+
+ @Override
+ public abstract K firstKey();
+
+ @Override
+ public SortedMapService<K, V> headMap(K toKey) {
+ return new SubSortedMapImpl<K,V>(this, firstKey(), toKey);
+ }
+
+ @Override
+ public SortedSetService<K> keySet() {
+ return new KeySortedSet();
+ }
+
+ @Override
+ public abstract K lastKey();
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedMapService<K, V>[] split(int n, boolean updateable) {
+ return new SortedMapService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public SortedMapService<K, V> subMap(K fromKey, K toKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, toKey);
+ }
+
+ @Override
+ public SortedMapService<K, V> tailMap(K fromKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, lastKey());
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected SortedMapService<K,V> target() {
+ return (SortedMapService<K,V>) super.target();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SubSortedMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SubSortedMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SubSortedMapImpl.java
new file mode 100644
index 0000000..59e4cbd
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/SubSortedMapImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.function.Equality;
+import javolution.util.service.SortedMapService;
+
+/**
+ * A view over a portion of a sorted map.
+ */
+public class SubSortedMapImpl<K, V> extends SortedMapView<K, V> {
+
+ /** Peeking ahead iterator. */
+ private class IteratorImpl implements Iterator<Entry<K, V>> {
+
+ private boolean ahead;
+ private final Equality<? super K> cmp = keyComparator();
+ private Entry<K, V> next;
+ private final Iterator<Entry<K, V>> targetIterator = target()
+ .iterator();
+
+ @Override
+ public boolean hasNext() {
+ if (ahead) return true;
+ while (targetIterator.hasNext()) {
+ next = targetIterator.next();
+ if ((from != null) && (cmp.compare(next.getKey(), from) < 0)) continue;
+ if ((to != null) && (cmp.compare(next.getKey(), to) >= 0)) break;
+ ahead = true;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Entry<K, V> next() {
+ hasNext(); // Moves ahead.
+ ahead = false;
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ targetIterator.remove();
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ private final K from; // Can be null.
+ private final K to; // Can be null.
+
+ public SubSortedMapImpl(SortedMapService<K, V> target, K from, K to) {
+ super(target);
+ if ((from != null) && (to != null)
+ && (keyComparator().compare(from, to) > 0)) throw new IllegalArgumentException(
+ "from: " + from + ", to: " + to); // As per SortedSet contract.
+ this.from = from;
+ this.to = to;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsKey(Object key) {
+ Equality<? super K> cmp = keyComparator();
+ if ((from != null) && (cmp.compare((K) key, from) < 0)) return false;
+ if ((to != null) && (cmp.compare((K) key, to) >= 0)) return false;
+ return target().containsKey(key);
+ }
+
+ @Override
+ public K firstKey() {
+ if (from == null) return target().firstKey();
+ Iterator<Entry<K, V>> it = iterator();
+ if (!it.hasNext()) throw new NoSuchElementException();
+ return it.next().getKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(Object key) {
+ Equality<? super K> cmp = keyComparator();
+ if ((from != null) && (cmp.compare((K) key, from) < 0)) return null;
+ if ((to != null) && (cmp.compare((K) key, to) >= 0)) return null;
+ return target().get(key);
+ }
+
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public Equality<? super K> keyComparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public K lastKey() {
+ if (to == null) return target().lastKey();
+ Iterator<Entry<K, V>> it = iterator();
+ if (!it.hasNext()) throw new NoSuchElementException();
+ Entry<K, V> last = it.next();
+ while (it.hasNext()) {
+ last = it.next();
+ }
+ return last.getKey();
+ }
+
+ @Override
+ public V put(K key, V value) {
+ Equality<? super K> cmp = keyComparator();
+ if ((from != null) && (cmp.compare((K) key, from) < 0)) throw new IllegalArgumentException(
+ "Key: " + key + " outside of this sub-map bounds");
+ if ((to != null) && (cmp.compare((K) key, to) >= 0)) throw new IllegalArgumentException(
+ "Key: " + key + " outside of this sub-map bounds");
+ return target().put(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V remove(Object key) {
+ Equality<? super K> cmp = keyComparator();
+ if ((from != null) && (cmp.compare((K) key, from) < 0)) return null;
+ if ((to != null) && (cmp.compare((K) key, to) >= 0)) return null;
+ return target().remove(key);
+ }
+
+ @Override
+ public Equality<? super V> valueComparator() {
+ return target().valueComparator();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/UnmodifiableSortedMapImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/UnmodifiableSortedMapImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/UnmodifiableSortedMapImpl.java
new file mode 100644
index 0000000..60db2b2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/map/sorted/UnmodifiableSortedMapImpl.java
@@ -0,0 +1,85 @@
+/*
+ * 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.internal.map.sorted;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import javolution.util.internal.map.UnmodifiableMapImpl;
+import javolution.util.service.SortedMapService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * * An unmodifiable view over a map.
+ */
+public class UnmodifiableSortedMapImpl<K, V> extends UnmodifiableMapImpl<K, V> implements SortedMapService<K,V> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableSortedMapImpl(SortedMapService<K, V> target) {
+ super(target);
+ }
+
+ @Override
+ public Comparator<? super K> comparator() {
+ return target().keyComparator();
+ }
+
+ @Override
+ public SortedSetService<Map.Entry<K, V>> entrySet() {
+ return new SubSortedMapImpl<K,V>(this, null, null).entrySet();
+ }
+
+ @Override
+ public K firstKey() {
+ return target().firstKey();
+ }
+
+ @Override
+ public SortedMapService<K, V> headMap(K toKey) {
+ return new SubSortedMapImpl<K,V>(this, null, toKey);
+ }
+
+ @Override
+ public SortedSetService<K> keySet() {
+ return new SubSortedMapImpl<K,V>(this, null, null).keySet();
+ }
+
+ @Override
+ public K lastKey() {
+ return target().lastKey();
+ }
+
+ @Override
+ public SortedMapService<K, V> subMap(K fromKey, K toKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, toKey);
+ }
+
+
+ @Override
+ public SortedMapService<K, V> tailMap(K fromKey) {
+ return new SubSortedMapImpl<K,V>(this, fromKey, null);
+ }
+
+ @Override
+ protected SortedMapService<K,V> target() {
+ return (SortedMapService<K,V>) super.target();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedMapService<K,V>[] split(int n, boolean updateable) {
+ SortedMapService<K,V>[] subTargets = target().split(n, updateable);
+ SortedMapService<K,V>[] result = new SortedMapService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new UnmodifiableSortedMapImpl<K,V>(subTargets[i]);
+ }
+ return result;
+ }
+ }
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/AtomicSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/AtomicSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/AtomicSetImpl.java
new file mode 100644
index 0000000..7a94b53
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/AtomicSetImpl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.internal.set;
+
+import javolution.util.internal.collection.AtomicCollectionImpl;
+import javolution.util.service.SetService;
+
+/**
+ * An atomic view over a set allowing concurrent access and sequential updates.
+ */
+public class AtomicSetImpl<E> extends AtomicCollectionImpl<E> implements
+ SetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public AtomicSetImpl(SetService<E> target) {
+ super(target);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SetService<E>[] split(int n, boolean updateable) {
+ return new SetService[] { this }; // Split not supported.
+ }
+ }
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/FilteredSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/FilteredSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/FilteredSetImpl.java
new file mode 100644
index 0000000..78759da
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/FilteredSetImpl.java
@@ -0,0 +1,43 @@
+/*
+ * 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.internal.set;
+
+import javolution.util.function.Predicate;
+import javolution.util.internal.collection.FilteredCollectionImpl;
+import javolution.util.service.SetService;
+
+/**
+ * A filtered view over a set.
+ */
+public class FilteredSetImpl<E> extends FilteredCollectionImpl<E> implements
+ SetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public FilteredSetImpl(SetService<E> target, Predicate<? super E> filter) {
+ super(target, filter);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SetService<E>[] split(int n, boolean updateable) {
+ SetService<E>[] subTargets = target().split(n, updateable);
+ SetService<E>[] result = new SetService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new FilteredSetImpl<E>(subTargets[i], filter);
+ }
+ return result;
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected SetService<E> target() {
+ return (SetService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/MappedSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/MappedSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/MappedSetImpl.java
new file mode 100644
index 0000000..83aede0
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/MappedSetImpl.java
@@ -0,0 +1,43 @@
+/*
+ * 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.internal.set;
+
+import javolution.util.function.Function;
+import javolution.util.internal.collection.MappedCollectionImpl;
+import javolution.util.service.SetService;
+
+/**
+ * A mapped view over a set.
+ */
+public abstract class MappedSetImpl<E, R> extends MappedCollectionImpl<E, R>
+ implements SetService<R> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public MappedSetImpl(SetService<E> target,
+ Function<? super E, ? extends R> function) {
+ super(target, function);
+ }
+
+ @Override
+ public abstract boolean add(R r);
+
+ @Override
+ public abstract boolean contains(Object r);
+
+ @Override
+ public abstract boolean remove(Object r);
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SetService<R>[] split(int n, boolean updateable) {
+ return new SetService[] { this }; // Split not supported.
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SetView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SetView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SetView.java
new file mode 100644
index 0000000..a5a81e1
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SetView.java
@@ -0,0 +1,49 @@
+/*
+ * 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.internal.set;
+
+import javolution.util.internal.collection.CollectionView;
+import javolution.util.service.SetService;
+
+/**
+ * Set view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ */
+public abstract class SetView<E> extends CollectionView<E> implements SetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public SetView(SetService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public abstract boolean contains(Object o);
+
+ @Override
+ public abstract boolean remove(Object o);
+
+ @Override
+ public abstract int size();
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SetService<E>[] split(int n, boolean updateable) {
+ return new SetService[] { this }; // Split not supported.
+ }
+
+ @Override
+ protected SetService<E> target() {
+ return (SetService<E>) super.target();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SharedSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SharedSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SharedSetImpl.java
new file mode 100644
index 0000000..1b8e0a9
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/SharedSetImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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.internal.set;
+
+import javolution.util.internal.ReadWriteLockImpl;
+import javolution.util.internal.collection.SharedCollectionImpl;
+import javolution.util.service.SetService;
+
+/**
+ * A shared view over a set allowing concurrent access and sequential updates.
+ */
+public class SharedSetImpl<E> extends SharedCollectionImpl<E> implements
+ SetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SharedSetImpl(SetService<E> target) {
+ super(target);
+ }
+
+ public SharedSetImpl(SetService<E> target, ReadWriteLockImpl lock) {
+ super(target, lock);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SetService<E>[] split(int n, boolean updateable) {
+ SetService<E>[] tmp;
+ lock.readLock.lock();
+ try {
+ tmp = target().split(n, updateable);
+ } finally {
+ lock.readLock.unlock();
+ }
+ SetService<E>[] result = new SetService[tmp.length];
+ for (int i = 0; i < tmp.length; i++) {
+ result[i] = new SharedSetImpl<E>(tmp[i], lock); // Shares the same locks.
+ }
+ return result;
+ }
+
+ @Override
+ protected SetService<E> target() {
+ return (SetService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/UnmodifiableSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/UnmodifiableSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/UnmodifiableSetImpl.java
new file mode 100644
index 0000000..1ff6ff6
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/UnmodifiableSetImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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.internal.set;
+
+import javolution.util.internal.collection.UnmodifiableCollectionImpl;
+import javolution.util.service.SetService;
+
+/**
+ * An unmodifiable view over a set.
+ */
+public class UnmodifiableSetImpl<E> extends UnmodifiableCollectionImpl<E>
+ implements SetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableSetImpl(SetService<E> target) {
+ super(target);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SetService<E>[] split(int n, boolean updateable) {
+ SetService<E>[] subTargets = target().split(n, updateable);
+ SetService<E>[] result = new SetService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new UnmodifiableSetImpl<E>(subTargets[i]);
+ }
+ return result;
+ }
+
+ @Override
+ protected SetService<E> target() {
+ return (SetService<E>) super.target();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/AtomicSortedSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/AtomicSortedSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/AtomicSortedSetImpl.java
new file mode 100644
index 0000000..d47e5d0
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/AtomicSortedSetImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.internal.set.sorted;
+
+import javolution.util.internal.set.AtomicSetImpl;
+import javolution.util.service.SortedSetService;
+
+/**
+ * An atomic view over a sorted set allowing concurrent access and sequential updates.
+ */
+public class AtomicSortedSetImpl<E> extends AtomicSetImpl<E> implements
+ SortedSetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public AtomicSortedSetImpl(SortedSetService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public E first() {
+ return targetView().first();
+ }
+
+ @Override
+ public SortedSetService<E> headSet(E toElement) {
+ return new SubSortedSetImpl<E>(this, null, toElement);
+ }
+
+ @Override
+ public E last() {
+ return targetView().last();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public SortedSetService<E>[] split(int n, boolean updateable) {
+ return new SortedSetService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public SortedSetService<E> subSet(E fromElement, E toElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, toElement);
+ }
+
+ @Override
+ public SortedSetService<E> tailSet(E fromElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, null);
+ }
+
+ @Override
+ protected SortedSetService<E> targetView() {
+ return (SortedSetService<E>) super.targetView();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SharedSortedSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SharedSortedSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SharedSortedSetImpl.java
new file mode 100644
index 0000000..a453b17
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SharedSortedSetImpl.java
@@ -0,0 +1,88 @@
+/*
+ * 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.internal.set.sorted;
+
+import javolution.util.internal.ReadWriteLockImpl;
+import javolution.util.internal.set.SharedSetImpl;
+import javolution.util.service.SetService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * A shared view over a set allowing concurrent access and sequential updates.
+ */
+public class SharedSortedSetImpl<E> extends SharedSetImpl<E> implements
+ SortedSetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SharedSortedSetImpl(SetService<E> target) {
+ super(target);
+ }
+
+ public SharedSortedSetImpl(SortedSetService<E> target, ReadWriteLockImpl lock) {
+ super(target, lock);
+ }
+
+ @Override
+ public E first() {
+ lock.readLock.lock();
+ try {
+ return target().first();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public SortedSetService<E> headSet(E toElement) {
+ return new SubSortedSetImpl<E>(this, null, toElement);
+ }
+
+ @Override
+ public E last() {
+ lock.readLock.lock();
+ try {
+ return target().last();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedSetService<E>[] split(int n, boolean updateable) {
+ SortedSetService<E>[] tmp;
+ lock.readLock.lock();
+ try {
+ tmp = target().split(n, updateable);
+ } finally {
+ lock.readLock.unlock();
+ }
+ SortedSetService<E>[] result = new SortedSetService[tmp.length];
+ for (int i = 0; i < tmp.length; i++) {
+ result[i] = new SharedSortedSetImpl<E>(tmp[i], lock); // Shares the same locks.
+ }
+ return result;
+ }
+
+ @Override
+ public SortedSetService<E> subSet(E fromElement, E toElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, toElement);
+ }
+
+ @Override
+ public SortedSetService<E> tailSet(E fromElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, null);
+ }
+
+ @Override
+ protected SortedSetService<E> target() {
+ return (SortedSetService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SortedSetView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SortedSetView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SortedSetView.java
new file mode 100644
index 0000000..e932eb2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SortedSetView.java
@@ -0,0 +1,60 @@
+/*
+ * 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.internal.set.sorted;
+
+import javolution.util.internal.set.SetView;
+import javolution.util.service.SortedSetService;
+
+/**
+ * Sorted Set view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ */
+public abstract class SortedSetView<E> extends SetView<E> implements SortedSetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public SortedSetView(SortedSetService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public abstract E first();
+
+ @Override
+ public SortedSetService<E> headSet(E toElement) {
+ return new SubSortedSetImpl<E>(this, null, toElement);
+ }
+
+ @Override
+ public abstract E last();
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedSetService<E>[] split(int n, boolean updateable) {
+ return new SortedSetService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public SortedSetService<E> subSet(E fromElement, E toElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, toElement);
+ }
+
+ @Override
+ public SortedSetService<E> tailSet(E fromElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, null);
+ }
+
+ @Override
+ protected SortedSetService<E> target() {
+ return (SortedSetService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SubSortedSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SubSortedSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SubSortedSetImpl.java
new file mode 100644
index 0000000..3673004
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/SubSortedSetImpl.java
@@ -0,0 +1,144 @@
+/*
+ * 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.internal.set.sorted;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * A view over a portion of a sorted set.
+ */
+public class SubSortedSetImpl<E> extends SortedSetView<E> {
+
+ /** Peeking ahead iterator. */
+ private class IteratorImpl implements Iterator<E> {
+
+ private boolean ahead;
+ private final Equality<? super E> cmp = comparator();
+ private E next;
+ private final Iterator<E> targetIterator = target().iterator();
+
+ @Override
+ public boolean hasNext() {
+ if (ahead) return true;
+ while (targetIterator.hasNext()) {
+ next = targetIterator.next();
+ if ((from != null) && (cmp.compare(next, from) < 0)) continue;
+ if ((to != null) && (cmp.compare(next, to) >= 0)) break;
+ ahead = true;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public E next() {
+ hasNext(); // Moves ahead.
+ ahead = false;
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ targetIterator.remove();
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ private final E from; // Can be null.
+ private final E to; // Can be null.
+
+ public SubSortedSetImpl(SortedSetService<E> target, E from, E to) {
+ super(target);
+ if ((from != null) && (to != null)
+ && (comparator().compare(from, to) > 0)) throw new IllegalArgumentException(
+ "from: " + from + ", to: " + to); // As per SortedSet contract.
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ public boolean add(E e) {
+ Equality<? super E> cmp = comparator();
+ if ((from != null) && (cmp.compare(e, from) < 0)) throw new IllegalArgumentException(
+ "Element: " + e + " outside of this sub-set bounds");
+ if ((to != null) && (cmp.compare(e, to) >= 0)) throw new IllegalArgumentException(
+ "Element: " + e + " outside of this sub-set bounds");
+ return target().add(e);
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return ((CollectionService<E>)target()).comparator();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean contains(Object obj) {
+ Equality<? super E> cmp = comparator();
+ if ((from != null) && (cmp.compare((E) obj, from) < 0)) return false;
+ if ((to != null) && (cmp.compare((E) obj, to) >= 0)) return false;
+ return target().contains(obj);
+ }
+
+ @Override
+ public E first() {
+ if (from == null) return target().first();
+ Iterator<E> it = iterator();
+ if (!it.hasNext()) throw new NoSuchElementException();
+ return it.next();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return iterator().hasNext();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public E last() {
+ if (to == null) return target().last();
+ Iterator<E> it = iterator();
+ if (!it.hasNext()) throw new NoSuchElementException();
+ E last = it.next();
+ while (it.hasNext()) {
+ last = it.next();
+ }
+ return last;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean remove(Object obj) {
+ Equality<? super E> cmp = comparator();
+ if ((from != null) && (cmp.compare((E) obj, from) < 0)) return false;
+ if ((to != null) && (cmp.compare((E) obj, to) >= 0)) return false;
+ return target().remove(obj);
+ }
+
+ @Override
+ public int size() { // Unfortunately, no choice other than counting.
+ int count = 0;
+ Iterator<E> it = iterator();
+ while (it.hasNext()) {
+ count++;
+ it.next();
+ }
+ return count;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/UnmodifiableSortedSetImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/UnmodifiableSortedSetImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/UnmodifiableSortedSetImpl.java
new file mode 100644
index 0000000..028e3ed
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/set/sorted/UnmodifiableSortedSetImpl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.internal.set.sorted;
+
+import javolution.util.internal.set.UnmodifiableSetImpl;
+import javolution.util.service.SetService;
+import javolution.util.service.SortedSetService;
+
+/**
+ * An unmodifiable view over a set.
+ */
+public class UnmodifiableSortedSetImpl<E> extends UnmodifiableSetImpl<E>
+ implements SortedSetService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public UnmodifiableSortedSetImpl(SetService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public E first() {
+ return target().first();
+ }
+
+ @Override
+ public SortedSetService<E> headSet(E toElement) {
+ return new SubSortedSetImpl<E>(this, null, toElement);
+ }
+
+ @Override
+ public E last() {
+ return target().last();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public SortedSetService<E>[] split(int n, boolean updateable) {
+ SortedSetService<E>[] subTargets = target().split(n, updateable);
+ SortedSetService<E>[] result = new SortedSetService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new UnmodifiableSortedSetImpl<E>(subTargets[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public SortedSetService<E> subSet(E fromElement, E toElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, toElement);
+ }
+
+ @Override
+ public SortedSetService<E> tailSet(E fromElement) {
+ return new SubSortedSetImpl<E>(this, fromElement, null);
+ }
+
+ @Override
+ protected SortedSetService<E> target() {
+ return (SortedSetService<E>) super.target();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/AtomicTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/AtomicTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/AtomicTableImpl.java
new file mode 100644
index 0000000..056c149
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/AtomicTableImpl.java
@@ -0,0 +1,236 @@
+/*
+ * 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.internal.table;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import javolution.util.internal.collection.AtomicCollectionImpl;
+import javolution.util.service.TableService;
+
+/**
+ * An atomic view over a table.
+ */
+public class AtomicTableImpl<E> extends AtomicCollectionImpl<E> implements
+ TableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public AtomicTableImpl(TableService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public synchronized void add(int index, E element) {
+ target().add(index, element);
+ if (!updateInProgress()) immutable = cloneTarget();
+ }
+
+ @Override
+ public synchronized boolean addAll(int index, Collection<? extends E> c) {
+ boolean changed = target().addAll(index, c);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized void addFirst(E element) {
+ target().addFirst(element);
+ if (!updateInProgress()) immutable = cloneTarget();
+ }
+
+ @Override
+ public synchronized void addLast(E element) {
+ target().addLast(element);
+ if (!updateInProgress()) immutable = cloneTarget();
+ }
+
+ @Override
+ public Iterator<E> descendingIterator() {
+ return new ReversedTableImpl<E>(this).iterator();
+ }
+
+ @Override
+ public E element() {
+ return getFirst();
+ }
+
+ @Override
+ public E get(int index) {
+ return targetView().get(index);
+ }
+
+ @Override
+ public E getFirst() {
+ return targetView().getFirst();
+ }
+
+ @Override
+ public E getLast() {
+ return targetView().getLast();
+ }
+
+ @Override
+ public int indexOf(Object element) {
+ return targetView().indexOf(element);
+ }
+
+ @Override
+ public ListIterator<E> iterator() {
+ return listIterator(0);
+ }
+
+ @Override
+ public int lastIndexOf(Object element) {
+ return targetView().lastIndexOf(element);
+ }
+
+ @Override
+ public ListIterator<E> listIterator() {
+ return listIterator(0);
+ }
+
+ @Override
+ public ListIterator<E> listIterator(int index) {
+ return new TableIteratorImpl<E>(this, index); // Iterator view on this.
+ }
+
+ @Override
+ public boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ @Override
+ public synchronized boolean offerFirst(E e) {
+ boolean changed = target().offerFirst(e);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized boolean offerLast(E e) {
+ boolean changed = target().offerLast(e);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public E peek() {
+ return peekFirst();
+ }
+
+ @Override
+ public E peekFirst() {
+ return targetView().peekFirst();
+ }
+
+ @Override
+ public E peekLast() {
+ return targetView().peekLast();
+ }
+
+ @Override
+ public E poll() {
+ return pollFirst();
+ }
+
+ @Override
+ public synchronized E pollFirst() {
+ E e = target().pollFirst();
+ if ((e != null) && !updateInProgress()) immutable = cloneTarget();
+ return e;
+ }
+
+ @Override
+ public synchronized E pollLast() {
+ E e = target().pollLast();
+ if ((e != null) && !updateInProgress()) immutable = cloneTarget();
+ return e;
+ }
+
+ @Override
+ public E pop() {
+ return removeFirst();
+ }
+
+ @Override
+ public void push(E e) {
+ addFirst(e);
+ }
+
+ @Override
+ public E remove() {
+ return removeFirst();
+ }
+
+ @Override
+ public synchronized E remove(int index) {
+ E e = target().remove(index);
+ if (!updateInProgress()) immutable = cloneTarget();
+ return e;
+ }
+
+ @Override
+ public synchronized E removeFirst() {
+ E e = target().removeFirst();
+ if (!updateInProgress()) immutable = cloneTarget();
+ return e;
+ }
+
+ @Override
+ public synchronized boolean removeFirstOccurrence(Object o) {
+ boolean changed = target().removeFirstOccurrence(o);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized E removeLast() {
+ E e = target().removeLast();
+ if (!updateInProgress()) immutable = cloneTarget();
+ return e;
+ }
+
+ @Override
+ public synchronized boolean removeLastOccurrence(Object o) {
+ boolean changed = target().removeLastOccurrence(o);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized E set(int index, E element) {
+ E e = target().set(index, element);
+ if (!updateInProgress()) immutable = cloneTarget();
+ return e;
+ }
+
+ @Override
+ public TableService<E>[] split(int n, boolean updateable) {
+ return SubTableImpl.splitOf(this, n, false); // Sub-views over this.
+ }
+
+ @Override
+ public TableService<E> subList(int fromIndex, int toIndex) {
+ return new SubTableImpl<E>(this, fromIndex, toIndex); // View on this.
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected TableService<E> target() {
+ return (TableService<E>) super.target();
+ }
+
+ @Override
+ protected TableService<E> targetView() {
+ return (TableService<E>) super.targetView();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FastTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FastTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FastTableImpl.java
new file mode 100644
index 0000000..070da4d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FastTableImpl.java
@@ -0,0 +1,210 @@
+/*
+ * 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.internal.table;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.function.Equality;
+
+/**
+ * The default {@link javolution.util.FastTable FastTable} implementation
+ * based on {@link FractalTableImpl fractal tables}. The memory footprint
+ * is minimal when the table is cleared.
+ */
+public class FastTableImpl<E> extends TableView<E> {
+
+ /** Internal iterator faster than generic TableIteratorImpl. */
+ private class IteratorImpl implements Iterator<E> {
+ private int currentIndex = -1;
+ private int nextIndex;
+
+ @Override
+ public boolean hasNext() {
+ return nextIndex < size;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public E next() {
+ if (nextIndex >= size) throw new NoSuchElementException();
+ currentIndex = nextIndex++;
+ return (E) fractal.get(currentIndex);
+ }
+
+ @Override
+ public void remove() {
+ if (currentIndex < 0) throw new IllegalStateException();
+ FastTableImpl.this.remove(currentIndex);
+ nextIndex--;
+ currentIndex = -1;
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ private transient int capacity; // Actual memory allocated is usually far less than capacity since inner fractal tables can be null.
+ private final Equality<? super E> comparator;
+ private transient FractalTableImpl fractal; // Null if empty (capacity 0)
+ private transient int size;
+
+ public FastTableImpl(Equality<? super E> comparator) {
+ super(null); // Root class.
+ this.comparator = comparator;
+ }
+
+ @Override
+ public boolean add(E element) {
+ addLast(element);
+ return true;
+ }
+
+ @Override
+ public void add(int index, E element) {
+ if ((index < 0) || (index > size)) indexError(index);
+ checkUpsize();
+ if (index >= (size >> 1)) {
+ fractal.shiftRight(element, index, size - index);
+ } else {
+ fractal.shiftLeft(element, index - 1, index);
+ fractal.offset--;
+ }
+ size++;
+ }
+
+ @Override
+ public void addFirst(E element) {
+ checkUpsize();
+ fractal.offset--;
+ fractal.set(0, element);
+ size++;
+ }
+
+ @Override
+ public void addLast(E element) {
+ checkUpsize();
+ fractal.set(size++, element);
+ }
+
+ @Override
+ public void clear() {
+ fractal = null;
+ capacity = 0;
+ size = 0;
+ }
+
+ @Override
+ public FastTableImpl<E> clone() { // Make a copy.
+ FastTableImpl<E> copy = new FastTableImpl<E>(comparator());
+ copy.addAll(this);
+ return copy;
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return comparator;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E get(int index) {
+ if ((index < 0) && (index >= size)) indexError(index);
+ return (E) fractal.get(index);
+ }
+
+ @Override
+ public E getFirst() {
+ if (size == 0) emptyError();
+ return get(0);
+ }
+
+ @Override
+ public E getLast() {
+ if (size == 0) emptyError();
+ return get(size - 1);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E remove(int index) {
+ if ((index < 0) || (index >= size)) indexError(index);
+ E removed = (E) fractal.get(index);
+ if (index >= (size >> 1)) {
+ fractal.shiftLeft(null, size - 1, size - index - 1);
+ } else {
+ fractal.shiftRight(null, 0, index);
+ fractal.offset++;
+ }
+ size--;
+ return removed;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E removeFirst() {
+ if (size == 0) emptyError();
+ E first = (E) fractal.set(0, null);
+ fractal.offset++;
+ size--;
+ return first;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E removeLast() {
+ if (size == 0) emptyError();
+ E last = (E) fractal.set(--size, null);
+ return last;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public E set(int index, E element) {
+ if ((index < 0) && (index >= size)) indexError(index);
+ return (E) fractal.set(index, element);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ private void checkUpsize() {
+ if (size >= capacity) upsize();
+ }
+
+ /** For serialization support */
+ @SuppressWarnings("unchecked")
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject(); // Deserialize comparator.
+ int n = s.readInt();
+ for (int i = 0; i < n; i++)
+ addLast((E) s.readObject());
+ }
+
+ private void upsize() {
+ fractal = (fractal == null) ? new FractalTableImpl() : fractal.upsize();
+ capacity = fractal.capacity();
+ }
+
+ /** For serialization support */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ s.defaultWriteObject(); // Serialize comparator.
+ s.writeInt(size);
+ for (int i = 0; i < size; i++)
+ s.writeObject(fractal.get(i));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FractalTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FractalTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FractalTableImpl.java
new file mode 100644
index 0000000..66f7782
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/FractalTableImpl.java
@@ -0,0 +1,172 @@
+/*
+ * 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.internal.table;
+
+import javolution.lang.MathLib;
+
+/**
+ * A fractal-based table with fast insertion/deletion capabilities regardless
+ * of the collection size. It is based on a fractal structure with self-similar
+ * patterns at any scale (large tables have the same structure as smaller tables
+ * which have similar structure as even smaller tables and so on).
+ */
+final class FractalTableImpl {
+
+ static final int BASE_CAPACITY_MIN = 16;
+ static final int SHIFT = 8;
+ private static final int BASE_CAPACITY_MAX = 1 << SHIFT;
+
+ /** Offset value, it is the index of the first element (modulo data.length). */
+ int offset;
+
+ /** An array of data elements or fractal tables (recursion).
+ Data length varies from 2 to BASE_CAPACITY_MAX */
+ private Object[] data;
+
+ /** The index shift, zero if base table. */
+ private final int shift;
+
+ public FractalTableImpl() {
+ this.shift = 0;
+ data = new Object[BASE_CAPACITY_MIN];
+ }
+
+ public FractalTableImpl(int shift) {
+ this.shift = shift;
+ data = new Object[2];
+ }
+
+ public FractalTableImpl(int shift, Object[] data, int offset) {
+ this.shift = shift;
+ this.data = data;
+ this.offset = offset;
+ }
+
+ public int capacity() {
+ // Reports lower capacity to ensure that there is no fractal holding
+ // wrapping data (head and tail in the same fractal).
+ return (data.length - 1) << shift;
+ }
+
+ public Object get(int index) {
+ Object fractal = data[((index + offset) >> shift) & (data.length - 1)];
+ return (shift == 0) ? fractal : ((FractalTableImpl) fractal).get(index
+ + offset);
+ }
+
+ public Object set(int index, Object element) {
+ int i = ((index + offset) >> shift) & (data.length - 1);
+ if (shift != 0) return F(i).set(index + offset, element);
+ Object previous = data[i];
+ data[i] = element;
+ return previous;
+ }
+
+ /** Shifts the specified elements(]last - length, last] modulo capacity)
+ one position to the left. No shift if length (modulo capacity) is zero. */
+ public void shiftLeft(Object inserted, int last, int length) {
+ int mask = (data.length << shift) - 1;
+ int tail = (last + offset) & mask;
+ int head = (last + offset - length) & mask;
+ if (shift == 0) {
+ int n = tail - head;
+ if (head > tail) { // Wrapping
+ System.arraycopy(data, head + 1, data, head, mask - head);
+ data[mask] = data[0];
+ n = tail;
+ }
+ System.arraycopy(data, tail - n + 1, data, tail - n, n);
+ data[tail] = inserted;
+ } else if ((head <= tail) && ((head >> shift) == (tail >> shift))) { // Shift local to inner table.
+ F(head >> shift).shiftLeft(inserted, tail, length); // (no wrapping).
+ } else {
+ int low = head >> shift;
+ int high = (low != data.length - 1) ? low + 1 : 0;
+ F(low).shiftLeft(F(high).get(0), -1, mask - head);
+ while (high != (tail >> shift)) {
+ low = high;
+ high = (low != data.length - 1) ? low + 1 : 0;
+ F(low).offset++; // Full shift left.
+ F(low).set(-1, F(high).get(0));
+ }
+ F(high).shiftLeft(inserted, tail, tail);
+ }
+ }
+
+ /** Shifts the specified element ([first, first + length[ modulo capacity)
+ one position to the right. No shift if length (modulo capacity) is zero. */
+ public void shiftRight(Object inserted, int first, int length) {
+ int mask = (data.length << shift) - 1;
+ int head = (first + offset) & mask;
+ int tail = (first + offset + length) & mask;
+ if (shift == 0) {
+ int n = tail - head;
+ if (head > tail) { // Wrapping
+ System.arraycopy(data, 0, data, 1, tail);
+ data[0] = data[mask];
+ n = mask - head;
+ }
+ System.arraycopy(data, head, data, head + 1, n);
+ data[head] = inserted;
+ } else if ((head <= tail) && ((head >> shift) == (tail >> shift))) { // Shift local to inner table.
+ F(head >> shift).shiftRight(inserted, head, length); // (no wrapping).
+ } else {
+ int high = tail >> shift;
+ int low = (high != 0) ? high - 1 : data.length - 1;
+ F(high).shiftRight(F(low).get(-1), 0, tail);
+ while (low != (head >> shift)) {
+ high = low;
+ low = (high != 0) ? high - 1 : data.length - 1;
+ F(high).offset--; // Full shift right.
+ F(high).set(0, F(low).get(-1));
+ }
+ F(low).shiftRight(inserted, head, mask - head);
+ }
+ }
+
+ public FractalTableImpl upsize() {
+ if (data.length >= BASE_CAPACITY_MAX) { // Creates outer fractal.
+ FractalTableImpl table = new FractalTableImpl(shift + SHIFT);
+ copyTo(table.F(0));
+ return table;
+ } else {
+ FractalTableImpl table = new FractalTableImpl(shift,
+ new Object[data.length << 1], 0);
+ copyTo(table);
+ return table;
+ }
+ }
+
+ private FractalTableImpl allocate(int i) {
+ FractalTableImpl fractal = new FractalTableImpl(shift - SHIFT,
+ new Object[1 << SHIFT], 0);
+ data[i] = fractal;
+ return fractal;
+ }
+
+ // Copy to the specified table.
+ private void copyTo(FractalTableImpl that) {
+ int n = MathLib.min(this.data.length, that.data.length);
+ offset &= (data.length << shift) - 1; // Makes it positive.
+ int o = offset >> shift;
+ if ((o + n) > data.length) { // Wrapping.
+ int w = (o + n) - data.length;
+ n -= w;
+ System.arraycopy(data, 0, that.data, n, w);
+ }
+ System.arraycopy(data, o, that.data, 0, n);
+ that.offset = offset - (o << shift);
+ }
+
+ private FractalTableImpl F(int i) {
+ FractalTableImpl table = (FractalTableImpl) data[i];
+ return (table != null) ? table : allocate(i);
+ }
+
+}
\ 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/util/internal/table/QuickSort.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/QuickSort.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/QuickSort.java
new file mode 100644
index 0000000..13cf342
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/QuickSort.java
@@ -0,0 +1,75 @@
+/*
+ * 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.internal.table;
+
+import java.util.Comparator;
+
+import javolution.util.service.TableService;
+
+/**
+ * A quick sort utility class.
+ * From Wikipedia Quick Sort - http://en.wikipedia.org/wiki/Quicksort
+ */
+public class QuickSort<E> {
+
+ private final Comparator<? super E> comparator;
+ private final TableService<E> table;
+
+ public QuickSort(TableService<E> table, Comparator<? super E> comparator) {
+ this.table = table;
+ this.comparator = comparator;
+ }
+
+ public void sort() {
+ int size = table.size();
+ if (size > 0) quicksort(0, table.size() - 1);
+ }
+
+ public void sort(int first, int last) {
+ if (first < last) {
+ int pivIndex = partition(first, last);
+ sort(first, (pivIndex - 1));
+ sort((pivIndex + 1), last);
+ }
+ }
+
+ // From Wikipedia Quick Sort - http://en.wikipedia.org/wiki/Quicksort
+ //
+ void quicksort(int first, int last) {
+ int pivIndex = 0;
+ if (first < last) {
+ pivIndex = partition(first, last);
+ quicksort(first, (pivIndex - 1));
+ quicksort((pivIndex + 1), last);
+ }
+ }
+
+ private int partition(int f, int l) {
+ int up, down;
+ E piv = table.get(f);
+ up = f;
+ down = l;
+ do {
+ while (comparator.compare(table.get(up), piv) <= 0 && up < l) {
+ up++;
+ }
+ while (comparator.compare(table.get(down), piv) > 0 && down > f) {
+ down--;
+ }
+ if (up < down) { // Swaps.
+ E temp = table.get(up);
+ table.set(up, table.get(down));
+ table.set(down, temp);
+ }
+ } while (down > up);
+ table.set(f, table.get(down));
+ table.set(down, piv);
+ return down;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/ReversedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/ReversedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/ReversedTableImpl.java
new file mode 100644
index 0000000..3e2de7d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/ReversedTableImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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.internal.table;
+
+import javolution.util.function.Equality;
+import javolution.util.service.TableService;
+
+/**
+ * A reverse view over a table.
+ */
+public class ReversedTableImpl<E> extends TableView<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public ReversedTableImpl(TableService<E> that) {
+ super(that);
+ }
+
+ @Override
+ public boolean add(E e) {
+ target().addFirst(e);
+ return true;
+ }
+
+ @Override
+ public void add(int index, E element) {
+ target().add(size() - index - 1, element);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public E get(int index) {
+ return target().get(size() - index - 1);
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return size() - target().lastIndexOf(o) - 1;
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return size() - target().indexOf(o) - 1;
+ }
+
+ @Override
+ public E remove(int index) {
+ return target().remove(size() - index - 1);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ return target().set(size() - index - 1, element);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SharedTableImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SharedTableImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SharedTableImpl.java
new file mode 100644
index 0000000..bc68a16
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/table/SharedTableImpl.java
@@ -0,0 +1,315 @@
+/*
+ * 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.internal.table;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import javolution.util.internal.ReadWriteLockImpl;
+import javolution.util.internal.collection.SharedCollectionImpl;
+import javolution.util.service.TableService;
+
+/**
+ * A shared view over a table allowing concurrent access and sequential updates.
+ */
+public class SharedTableImpl<E> extends SharedCollectionImpl<E> implements
+ TableService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public SharedTableImpl(TableService<E> target) {
+ super(target);
+ }
+
+ public SharedTableImpl(TableService<E> target, ReadWriteLockImpl lock) {
+ super(target, lock);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ lock.writeLock.lock();
+ try {
+ target().add(index, element);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
+ lock.writeLock.lock();
+ try {
+ return target().addAll(index, c);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public void addFirst(E element) {
+ lock.writeLock.lock();
+ try {
+ target().addFirst(element);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public void addLast(E element) {
+ lock.writeLock.lock();
+ try {
+ target().addLast(element);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public Iterator<E> descendingIterator() {
+ return new ReversedTableImpl<E>(this).iterator(); // View on this.
+ }
+
+ @Override
+ public E element() {
+ return getFirst();
+ }
+
+ @Override
+ public E get(int index) {
+ lock.readLock.lock();
+ try {
+ return target().get(index);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public E getFirst() {
+ lock.readLock.lock();
+ try {
+ return target().getFirst();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public E getLast() {
+ lock.readLock.lock();
+ try {
+ return target().getLast();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public int indexOf(Object element) {
+ lock.readLock.lock();
+ try {
+ return target().indexOf(element);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public ListIterator<E> iterator() {
+ return target().listIterator(0);
+ }
+
+ @Override
+ public int lastIndexOf(Object element) {
+ lock.readLock.lock();
+ try {
+ return target().lastIndexOf(element);
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public ListIterator<E> listIterator() {
+ return target().listIterator(0);
+ }
+
+ @Override
+ public ListIterator<E> listIterator(int index) {
+ return new TableIteratorImpl<E>(this, index); // View on this.
+ }
+
+ @Override
+ public boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ @Override
+ public boolean offerFirst(E e) {
+ lock.writeLock.lock();
+ try {
+ return target().offerFirst(e);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean offerLast(E e) {
+ lock.writeLock.lock();
+ try {
+ return target().offerLast(e);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public E peek() {
+ return peekFirst();
+ }
+
+ @Override
+ public E peekFirst() {
+ lock.readLock.lock();
+ try {
+ return target().peekFirst();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public E peekLast() {
+ lock.readLock.lock();
+ try {
+ return target().peekLast();
+ } finally {
+ lock.readLock.unlock();
+ }
+ }
+
+ @Override
+ public E poll() {
+ return pollFirst();
+ }
+
+ @Override
+ public E pollFirst() {
+ lock.writeLock.lock();
+ try {
+ return target().pollFirst();
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public E pollLast() {
+ lock.writeLock.lock();
+ try {
+ return target().pollLast();
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public E pop() {
+ return removeFirst();
+ }
+
+ @Override
+ public void push(E e) {
+ addFirst(e);
+ }
+
+ @Override
+ public E remove() {
+ return removeFirst();
+ }
+
+ @Override
+ public E remove(int index) {
+ lock.writeLock.lock();
+ try {
+ return target().remove(index);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public E removeFirst() {
+ lock.writeLock.lock();
+ try {
+ return target().removeFirst();
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean removeFirstOccurrence(Object o) {
+ lock.writeLock.lock();
+ try {
+ return target().removeFirstOccurrence(o);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public E removeLast() {
+ lock.writeLock.lock();
+ try {
+ return target().removeLast();
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean removeLastOccurrence(Object o) {
+ lock.writeLock.lock();
+ try {
+ return target().removeLastOccurrence(o);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+
+ @Override
+ public E set(int index, E element) {
+ lock.writeLock.lock();
+ try {
+ return target().set(index, element);
+ } finally {
+ lock.writeLock.unlock();
+ }
+ }
+ @Override
+ public TableService<E>[] split(int n, boolean updateable) {
+ return SubTableImpl.splitOf(this, n, false); // Sub-views over this.
+ }
+
+ @Override
+ public TableService<E> subList(int fromIndex, int toIndex) {
+ return new SubTableImpl<E>(this, fromIndex, toIndex); // View on this.
+ }
+
+ /** Returns the actual target */
+ @Override
+ protected TableService<E> target() {
+ return (TableService<E>) super.target();
+ }
+
+}
\ No newline at end of file
[17/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/internal/SecurityContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/internal/SecurityContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/context/internal/SecurityContextImpl.java
new file mode 100644
index 0000000..2615119
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/internal/SecurityContextImpl.java
@@ -0,0 +1,61 @@
+/*
+ * 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.context.internal;
+
+import javolution.context.SecurityContext;
+import javolution.util.FastTable;
+
+/**
+ * Holds the default implementation of SecurityContext.
+ */
+public final class SecurityContextImpl extends SecurityContext {
+
+ private FastTable<Action> actions = new FastTable<Action>();
+
+ @Override
+ public boolean isGranted(Permission<?> permission) {
+ boolean isGranted = true;
+ for (Action a : actions) {
+ if (a.permission.implies(permission))
+ isGranted = a.grant;
+ }
+ return isGranted;
+ }
+
+ @Override
+ public void grant(Permission<?> permission, Object certificate)
+ throws SecurityException {
+ Action a = new Action();
+ a.grant = true;
+ a.permission = permission;
+ actions.add(a);
+ }
+
+ @Override
+ public void revoke(Permission<?> permission, Object certificate)
+ throws SecurityException {
+ Action a = new Action();
+ a.grant = false;
+ a.permission = permission;
+ actions.add(a);
+ }
+
+ @Override
+ protected SecurityContext inner() {
+ SecurityContextImpl ctx = new SecurityContextImpl();
+ ctx.actions.addAll(actions);
+ return ctx;
+ }
+
+ // Represents the grant/revoke action performed.
+ private static class Action {
+ boolean grant; // Else revoke.
+ Permission<?> permission;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/internal/StorageContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/internal/StorageContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/context/internal/StorageContextImpl.java
new file mode 100644
index 0000000..0f20936
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/internal/StorageContextImpl.java
@@ -0,0 +1,87 @@
+/*
+ * 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.context.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import javolution.context.LogContext;
+import javolution.context.SecurityContext;
+import javolution.context.SecurityContext.Permission;
+import javolution.context.StorageContext;
+
+/**
+ * Holds the default implementation of StorageContext.
+ */
+public final class StorageContextImpl extends StorageContext {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <V extends Serializable> V read(Resource<V> resource)
+ throws SecurityException {
+ SecurityContext.check(new Permission<Resource<V>>(Resource.class,
+ "write", resource));
+ try {
+ File file = new File(FILE_STORAGE_LOCATION.get(),
+ resource.uniqueID());
+ if (file.exists()) {
+ LogContext.debug("Read resource file ", file.getAbsolutePath());
+ } else {
+ LogContext.debug("Resource file ", file.getAbsolutePath(),
+ " does not exist.");
+ return null;
+ }
+
+ FileInputStream fileIn = new FileInputStream(file);
+ ObjectInputStream in = new ObjectInputStream(fileIn);
+ V value = (V) in.readObject();
+ in.close();
+ fileIn.close();
+ return value;
+ } catch (IOException e1) {
+ LogContext.error(e1);
+ } catch (ClassNotFoundException e2) {
+ LogContext.error(e2);
+ }
+ return null;
+
+ }
+
+ @Override
+ public <V extends Serializable> void write(Resource<V> resource, V value)
+ throws SecurityException {
+ SecurityContext.check(new Permission<Resource<V>>(Resource.class,
+ "write", resource));
+ try {
+ File storage = FILE_STORAGE_LOCATION.get();
+ storage.mkdirs();
+ File file = new File(storage, resource.uniqueID());
+ LogContext.debug("Write resource ", file.getAbsolutePath());
+
+ FileOutputStream fileOut = new FileOutputStream(file);
+ ObjectOutputStream out = new ObjectOutputStream(fileOut);
+ out.writeObject(value);
+ out.close();
+ fileOut.close();
+ } catch (IOException error) {
+ LogContext.error(error);
+ }
+ }
+
+ @Override
+ protected StorageContext inner() {
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/context/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/context/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/context/package-info.java
new file mode 100644
index 0000000..af177ae
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/context/package-info.java
@@ -0,0 +1,103 @@
+/**
+<p> Run-time {@link javolution.context.AbstractContext contexts} to facilitate
+ separation of concerns and achieve higher level of performance and flexibility.</p>
+
+<h2><a name="OVERVIEW">Separation of Concerns</a></h2>
+
+ <p> Separation of concerns is an important design principle greatly misunderstood.
+ Most developers think it is limited to modularity and encapsulation or it
+ requires special programming tools (e.g. Aspect programming).</p>
+
+ <p> Separation of concerns is very powerful and easier than it looks.
+ Basically, it could be summarized as the "pass the buck principle".
+ If you don't know what to do with some information, just give it to someone
+ else who might know.</p>
+
+ <p> A frequent example is the catching of exceptions too early (with some logging processing)
+ instead of throwing a checked exception. Unfortunately, they are still plenty of cases
+ where the separation of concerns is not as good as it could be. For example logging!
+ Why low-level code need to know which logging facility to use
+ (e.g. standard logging, Log4J library, OSGi LogService or anything else)?
+ Why logging should have to be based upon the class hierarchy (standard logging)?
+ Why can't we attach some relevant information (such as user id, session number, etc.)
+ to the logging content ? </p>
+
+ <p> Separation of concerns can be addressed through "Aspect Programming",
+ but there is a rather simpler solution <b>"Context Programming"</b>!</p>
+
+ <p> It does not require any particular tool, it basically says that every threads
+ has a {@link javolution.context.AbstractContext context} which can be customized by someone else
+ (the one who knows what to do, when running OSGi it is typically a separate bundle).
+ Then, your code looks a lot cleaner and is way more flexible as you don't have
+ to worry about logging, security, performance etc. in your low level methods.
+[code]
+void myMethod() {
+ ...
+ LogContext.info("Don't know where this is going to be logged to");
+ ...
+}[/code]</p>
+
+ <p> Used properly <i><b>J</b>avolution</i>'s {@link javolution.context.AbstractContext contexts}
+ greatly facilitate the separation of concerns. Contexts are fully
+ integrated with OSGi (they are published services). Applications
+ may dynamically plug-in the "right context" using OSGi mechanisms.
+ For example, the {@link javolution.context.SecurityContext SecurityContext}
+ might only be known at runtime.</p>
+
+ <h2><a name="PREDEFINED">Predefined Contexts:</a></h2>
+ <p> <i><b>J</b>avolution</i> provides several useful runtime contexts:<ul>
+ <li>{@link javolution.context.ConcurrentContext ConcurrentContext}
+ - To take advantage of concurrent algorithms on multi-cores systems.</li>
+ <li>{@link javolution.context.LogContext LogContext}
+ - To log events according to the runtime environment (e.g. {@link org.osgi.service.log.LogService} when running OSGi).</li>
+ <li>{@link javolution.context.LocalContext LocalContext}
+ - To define locally scoped environment settings.</li>
+ <li>{@link javolution.context.SecurityContext SecurityContext}
+ - To address application-level security concerns.</li>
+ <li>{@link javolution.context.StorageContext StorageContext}
+ - To store/retrieve your persistent data/dataset.</li>
+ <li>{@link javolution.context.FormatContext FormatContext}
+ - For plugable objects parsing/formatting. Such as {@link javolution.text.TextContext TextContext} for plain text,
+ or {@link javolution.xml.XMLContext XMLContext} for XML serialization/deserialization.</li>
+ <li>{@link javolution.context.StorageContext StorageContext}
+ - To store/retrieve your persistent data/dataset.</li>
+ <li>...add your own !</li>
+ </ul>
+ </p>
+
+<h2><a name="FAQ">FAQ:</a></h2>
+<ol>
+ <a name="FAQ-1"></a>
+ <li><b>In my application I create new threads on-the-fly and I would like them to inherit
+ the current context environment. How can I do that?</b>
+ <p> Context is automatically inherited when performing concurrent executions using
+ {@link javolution.context.ConcurrentContext ConcurrentContext}. If you create
+ new threads yourself you can easily setup their context as shown below.</p>
+[code]
+//Spawns a new thread inheriting the context of the current thread.
+MyThread myThread = new MyThread();
+myThread.inherited = AbstractContext.current();
+myThread.start();
+ ...
+class MyThread extends Thread {
+ AbstractContext inherited;
+ public void run() {
+ AbstractContext.inherit(inherited); // Sets current context.
+ ...
+ }
+}[/code]
+<p></p>
+ </li>
+
+ <a name="FAQ-2"></a>
+ <li><b>Is it possible to configure the context of all running threads (global configuration) ?</b>
+ <p> Yes by publishing an OSGi implementation of the customized context
+ (published context services are the default contexts of all running threads).
+ Otherwise, you can only configure a context that you have entered (for obvious safety reasons).</p>
+<p></p>
+ </li>
+ </ol>
+
+*/
+package javolution.context;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/doc-files/overview.html
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/doc-files/overview.html b/commons/marmotta-commons/src/ext/java/javolution/doc-files/overview.html
new file mode 100644
index 0000000..a1ac049
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/doc-files/overview.html
@@ -0,0 +1,149 @@
+<BODY>
+<H2><B><I><SPAN CLASS="style0">J</SPAN><SPAN CLASS="style1">avolution</I></B></SPAN> - Java<SUP>TM</SUP> Solution for Real-Time and Embedded Systems.</H2>
+
+<a name="license"></a>
+<h3><b>License:</b></h3>
+<p> Permission to use, copy, modify, and distribute this software is freely granted,
+ provided that copyright notices are preserved (the full license text can be found
+ <a href="http://javolution.org/LICENSE.txt">here</a>).</p>
+<p> <b><i>Javolution</i></b>'s users are encouraged to show their support with the
+ <a href="http://javolution.org"><img src="http://javolution.org/src/site/css/img/javolution.png"></a> button.</p>
+
+<a name="overview"></a>
+<h3><b>Overview:</b></h3>
+Although Java<sup>TM</sup> has been very successful on the server-side; It has few shortcomings limiting
+its adoption for others domains such as real-time, embedded or high-performance applications.
+For these, the <b><i>Javolution</i></b> library provides important "pieces" missing
+from the Java<sup>TM</sup> core library and making the Java<sup>TM</sup> platform even more attractive.
+
+<a name="usage"></a>
+<h3><b>Usage:</b></h3>
+
+<p><b><i>Javolution</i></b> can be used as a standard OSGi bundle.</p>
+
+<div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">
+<span style="color: #7F0055; font-weight: bold">import</span> org.osgi.framework.*;
+<span style="color: #7F0055; font-weight: bold">import</span> org.osgi.util.tracker.ServiceTracker;
+<span style="color: #7F0055; font-weight: bold">public</span> <span style="color: #7F0055; font-weight: bold">class</span> MyActivator <span style="color: #7F0055; font-weight: bold">implements</span> BundleActivator {
+ ServiceTracker<XMLInputFactory, XMLInputFactory> tracker;
+ <span style="color: #7F0055; font-weight: bold">public</span> <span style="color: #7F0055; font-weight: bold">void</span> start(BundleContext bc) <span style="color: #7F0055; font-weight: bold">throws</span> Exception {
+ tracker = <span style="color: #7F0055; font-weight: bold">new</span> ServiceTracker<>(bc, XMLInputFactory.<span style="color: #7F0055; font-weight: bold">class</span>, null);
+ tracker.open();
+ parse();
+ }
+ <span style="color: #7F0055; font-weight: bold">public</span> <span style="color: #7F0055; font-weight: bold">void</span> stop(BundleContext bc) <span style="color: #7F0055; font-weight: bold">throws</span> Exception {
+ tracker.close();
+ }
+ <span style="color: #7F0055; font-weight: bold">public</span> <span style="color: #7F0055; font-weight: bold">void</span> parse() <span style="color: #7F0055; font-weight: bold">throws</span> XMLStreamException {
+ XMLInputFactory factory = tracker.getService();
+ factory.setProperty(XMLInputFactory.IS_COALESCING, true); <span style="color: #3F7F5F">// Configures.</span>
+
+ <span style="color: #3F7F5F">// Instantiates a new reader.</span>
+ String xml = <span style="color: #2a00ff">"<test>This is a test</test>"</span>;
+ CharSequenceReader in = <span style="color: #7F0055; font-weight: bold">new</span> CharSequenceReader().setInput(xml);
+ XMLStreamReader reader = factory.createXMLStreamReader(in);
+
+ <span style="color: #3F7F5F">// Parses XML.</span>
+ <span style="color: #7F0055; font-weight: bold">while</span> (reader.hasNext()) {
+ <span style="color: #7F0055; font-weight: bold">int</span> eventType = reader.next();
+ <span style="color: #7F0055; font-weight: bold">if</span> (eventType == XMLStreamConstants.CHARACTERS) {
+ System.out.println(reader.getText());
+ }
+ }
+
+ <span style="color: #3F7F5F">// Closes the reader which may be recycled back to the factory.</span>
+ reader.close();
+ }
+}
+</pre></div>
+
+<p> Or as a standard Java library (does not require OSGi runtime).</p>
+
+<div style="background: #ffffff; overflow:auto;width:auto;color:black;background:white;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">
+<span style="color: #7F0055; font-weight: bold">import</span> javolution.osgi.internal.OSGiServices;
+<span style="color: #7F0055; font-weight: bold">public</span> <span style="color: #7F0055; font-weight: bold">class</span> Main {
+ <span style="color: #7F0055; font-weight: bold">public</span> <span style="color: #7F0055; font-weight: bold">static</span> <span style="color: #7F0055; font-weight: bold">void</span> main(String[] args) <span style="color: #7F0055; font-weight: bold">throws</span> XMLStreamException {
+ XMLInputFactory factory = OSGiServices.getXMLInputFactory();
+ factory.setProperty(XMLInputFactory.IS_COALESCING, true); <span style="color: #3F7F5F">// Configures.</span>
+
+ <span style="color: #3F7F5F">// Instantiates a reader.</span>
+ String xml = <span style="color: #2a00ff">"<test>This is a test</test>"</span>;
+ CharSequenceReader in = <span style="color: #7F0055; font-weight: bold">new</span> CharSequenceReader().setInput(xml);
+ XMLStreamReader reader = factory.createXMLStreamReader(in);
+
+ <span style="color: #3F7F5F">// Parses XML.</span>
+ <span style="color: #7F0055; font-weight: bold">while</span> (reader.hasNext()) {
+ <span style="color: #7F0055; font-weight: bold">int</span> eventType = reader.next();
+ <span style="color: #7F0055; font-weight: bold">if</span> (eventType == XMLStreamConstants.CHARACTERS) {
+ System.out.println(reader.getText());
+ }
+ }
+
+ <span style="color: #3F7F5F">// Closes the reader which may be recycled back to the factory.</span>
+ reader.close();
+ }
+}
+</pre></div>
+<a name="services"></a>
+<h3><b>Services:</b></h3>
+<p><b><i>Javolution</i></b> publishes the following OSGi services.</p>
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 1000px;">
+ <tbody>
+ <tr>
+ <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">Published Service</span></td>
+ <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">Description</span></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.xml.stream.XMLInputFactory}</td>
+ <td style="vertical-align: top;">StAX-like version of javax.xml.stream.XMLInputFactory avoiding {@code String} allocations.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.xml.stream.XMLOutputFactory}</td>
+ <td style="vertical-align: top;">StAX-like version of javax.xml.stream.XMLOutputFactory using {@code CharSequence} instead of {@code String}</td>
+ </tr>
+ </tbody>
+</table>
+<p> These services can be accessed through the standard OSGi registry
+ or using {@code javolution.osgi.internal.OSGiServices} when running outside OSGi.</p>
+<p><b><i>Javolution</i></b> listen to the following OSGi services.</p>
+<table cellpadding="2" cellspacing="2" border="1" style="text-align: left; width: 1000px;">
+ <tbody>
+ <tr>
+ <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">Subscribed Service</span></td>
+ <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">Description</span></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@code org.osgi.service.log.LogService}</td>
+ <td style="vertical-align: top;">OSGi service to log messages.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.context.LogContext}</td>
+ <td style="vertical-align: top;">Service to support asynchronous logging.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.context.ConcurrentContext}</td>
+ <td style="vertical-align: top;">Service to support concurrent executions.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.context.LocalContext}</td>
+ <td style="vertical-align: top;">Service to support locally scoped settings.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.context.SecurityContext}</td>
+ <td style="vertical-align: top;">Service granting security authorizations.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.context.StorageContext}</td>
+ <td style="vertical-align: top;">Service to store/retrieve persistent data/dataset.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.text.TextContext}</td>
+ <td style="vertical-align: top;">Service to support text parsing/formatting.</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;">{@link javolution.xml.XMLContext}</td>
+ <td style="vertical-align: top;">Service to support XML serialization/deserialization.</td>
+ </tr>
+ </tbody>
+</table>
+</BODY>
\ 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/io/AppendableWriter.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/AppendableWriter.java b/commons/marmotta-commons/src/ext/java/javolution/io/AppendableWriter.java
new file mode 100644
index 0000000..84e6f7f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/AppendableWriter.java
@@ -0,0 +1,163 @@
+/*
+ * 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.io;
+
+import java.io.IOException;
+import java.io.Writer;
+import javolution.text.Text;
+
+/**
+ * <p> This class allows any <code>Appendable</code> to be used as
+ * a writer.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.8, May 8, 2006
+ */
+public final class AppendableWriter extends Writer {
+
+ /**
+ * Holds the current appendable output or <code>null</code> if closed.
+ */
+ private Appendable _output;
+
+ /**
+ * Creates a new appendable writer for which the appendable output
+ * is not set.
+ *
+ * @see #setOutput(Appendable)
+ */
+ public AppendableWriter() {}
+
+ /**
+ * Sets the appendable output being written to.
+ * For example:[code]
+ * Writer writer = new AppendableWriter().setOutput(new TextBuilder());
+ * [/code]
+ *
+ * @param output the appendable written to.
+ * @return this writer.
+ * @throws IllegalStateException if this writer is being reused and
+ * it has not been {@link #close closed} or {@link #reset reset}.
+ */
+ public AppendableWriter setOutput(Appendable output) {
+ if (_output != null)
+ throw new IllegalStateException("Writer not closed or reset");
+ _output = output;
+ return this;
+ }
+
+ /**
+ * Writes a single character.
+ *
+ * @param c <code>char</code> the character to be written.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(char c) throws IOException {
+ if (_output == null)
+ throw new IOException("Writer closed");
+ _output.append(c);
+ }
+
+ /**
+ * Writes the 16 low-order bits of the given integer value;
+ * the 16 high-order bits are ignored.
+ *
+ * @param c the value of the character to be written.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(int c) throws IOException {
+ if (_output == null)
+ throw new IOException("Writer closed");
+ _output.append((char) c);
+ }
+
+ /**
+ * Writes a portion of an array of characters.
+ *
+ * @param cbuf the array of characters.
+ * @param off the offset from which to start writing characters.
+ * @param len the number of characters to write.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(char cbuf[], int off, int len) throws IOException {
+ if (_output == null)
+ throw new IOException("Writer closed");
+ _tmpBuffer = cbuf;
+ _output.append(_tmpBufferAsCharSequence, off, off + len);
+ _tmpBuffer = null; // Removes temporary references.
+ }
+
+ private char[] _tmpBuffer;
+
+ private final CharSequence _tmpBufferAsCharSequence = new CharSequence() {
+ public int length() {
+ return _tmpBuffer.length;
+ }
+
+ public char charAt(int index) {
+ return _tmpBuffer[index];
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ /**
+ * Writes a portion of a string.
+ *
+ * @param str a String.
+ * @param off the offset from which to start writing characters.
+ * @param len the number of characters to write.
+ * @throws IOException if an I/O error occurs
+ */
+ public void write(String str, int off, int len) throws IOException {
+ if (_output == null)
+ throw new IOException("Writer closed");
+ Object obj = str;
+ if (obj instanceof CharSequence) {
+ _output.append((CharSequence) obj);
+ } else {
+ _output.append(Text.valueOf(str));
+ }
+ }
+
+ /**
+ * Writes the specified character sequence.
+ *
+ * @param csq the character sequence.
+ * @throws IOException if an I/O error occurs
+ */
+ public void write(CharSequence csq) throws IOException {
+ if (_output == null)
+ throw new IOException("Writer closed");
+ _output.append(csq);
+ }
+
+ /**
+ * Flushes the stream.
+ */
+ public void flush() {
+ // Do nothing (no buffer).
+ }
+
+ /**
+ * Closes and {@link #reset resets} this writer for reuse.
+ */
+ public void close() {
+ if (_output != null) {
+ reset();
+ }
+ }
+
+ public void reset() {
+ _output = null;
+ _tmpBuffer = null;
+ }
+}
\ 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/io/CharSequenceReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/CharSequenceReader.java b/commons/marmotta-commons/src/ext/java/javolution/io/CharSequenceReader.java
new file mode 100644
index 0000000..9dd0da2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/CharSequenceReader.java
@@ -0,0 +1,156 @@
+/*
+ * 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.io;
+
+import java.io.IOException;
+import java.io.Reader;
+import javolution.lang.MathLib;
+import javolution.text.CharArray;
+import javolution.text.Text;
+import javolution.text.TextBuilder;
+
+/**
+ * <p> This class allows any <code>CharSequence</code> to be used as
+ * a reader.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.8, May 8, 2004
+ */
+public final class CharSequenceReader extends Reader {
+
+ /**
+ * Holds the character sequence input.
+ */
+ private CharSequence _input;
+
+ /**
+ * Holds the current index into the character sequence.
+ */
+ private int _index;
+
+ /**
+ * Creates a new character sequence reader for which the character
+ * sequence input is not set.
+ *
+ * @see #setInput
+ */
+ public CharSequenceReader() {}
+
+ /**
+ * Sets the character sequence to use for reading.
+ *
+ * @param charSequence the character sequence to be read.
+ * @return this reader.
+ * @throws IllegalStateException if this reader is being reused and
+ * it has not been {@link #close closed} or {@link #reset reset}.
+ */
+ public CharSequenceReader setInput(CharSequence charSequence) {
+ if (_input != null)
+ throw new IllegalStateException("Reader not closed or reset");
+ _input = charSequence;
+ return this;
+ }
+
+ /**
+ * Indicates if this stream is ready to be read.
+ *
+ * @return <code>true</code> if this reader has remaining characters to
+ * read; <code>false</code> otherwise.
+ * @throws IOException if an I/O error occurs.
+ */
+ public boolean ready() throws IOException {
+ if (_input == null)
+ throw new IOException("Reader closed");
+ return true;
+ }
+
+ /**
+ * Closes and {@link #reset resets} this reader for reuse.
+ */
+ public void close() {
+ if (_input != null) {
+ reset();
+ }
+ }
+
+ /**
+ * Reads a single character. This method does not block, <code>-1</code>
+ * is returned if the end of the character sequence input has been reached.
+ *
+ * @return the 31-bits Unicode of the character read, or -1 if there is
+ * no more remaining bytes to be read.
+ * @throws IOException if an I/O error occurs (e.g. incomplete
+ * character sequence being read).
+ */
+ public int read() throws IOException {
+ if (_input == null)
+ throw new IOException("Reader closed");
+ return (_index < _input.length()) ? _input.charAt(_index++) : -1;
+ }
+
+ /**
+ * Reads characters into a portion of an array. This method does not
+ * block.
+ *
+ * @param cbuf the destination buffer.
+ * @param off the offset at which to start storing characters.
+ * @param len the maximum number of characters to read
+ * @return the number of characters read, or -1 if there is no more
+ * character to be read.
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read(char cbuf[], int off, int len) throws IOException {
+ if (_input == null)
+ throw new IOException("Reader closed");
+ final int inputLength = _input.length();
+ if (_index >= inputLength)
+ return -1;
+ final int count = MathLib.min(inputLength - _index, len);
+ final Object csq = _input;
+ if (csq instanceof String) {
+ String str = (String) csq;
+ str.getChars(_index, _index + count, cbuf, off);
+ } else if (csq instanceof Text) {
+ Text txt = (Text) csq;
+ txt.getChars(_index, _index + count, cbuf, off);
+ } else if (csq instanceof TextBuilder) {
+ TextBuilder tb = (TextBuilder) csq;
+ tb.getChars(_index, _index + count, cbuf, off);
+ } else if (csq instanceof CharArray) {
+ CharArray ca = (CharArray) csq;
+ System.arraycopy(ca.array(), _index + ca.offset(), cbuf, off, count);
+ } else { // Generic CharSequence.
+ for (int i = off, n = off + count, j = _index; i < n;) {
+ cbuf[i++] = _input.charAt(j++);
+ }
+ }
+ _index += count;
+ return count;
+ }
+
+ /**
+ * Reads characters into the specified appendable. This method does not
+ * block.
+ *
+ * @param dest the destination buffer.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void read(Appendable dest) throws IOException {
+ if (_input == null)
+ throw new IOException("Reader closed");
+ dest.append(_input);
+ }
+
+ @Override
+ public void reset() {
+ _index = 0;
+ _input = null;
+ }
+
+}
\ No newline at end of file
[13/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/test/Perfometer.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/test/Perfometer.java b/commons/marmotta-commons/src/ext/java/javolution/test/Perfometer.java
new file mode 100644
index 0000000..bd9707d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/test/Perfometer.java
@@ -0,0 +1,271 @@
+/*
+ * 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.test;
+
+import javolution.context.LogContext;
+import javolution.lang.Configurable;
+import javolution.lang.MathLib;
+import javolution.text.TextBuilder;
+import javolution.util.FastTable;
+
+/**
+ * <p> Utility class to measure the worst case execution time and average
+ * execution time with high precision. Here an example measuring the
+ * worst case execution time of {@link java.util.List#add(int, Object)}
+ * for diverse list implementations.</p>
+ * [code]
+ * Perfometer<Class<? extends List>> insertPerf = new Perfometer<>("java.util.List#add(int, Object)") {
+ * List<Object> list;
+ * Random random;
+ * protected void initialize() throws Exception {
+ * list = getInput().newInstance();
+ * random = new Random(-1); // Use seed to ensure same execution path.
+ * }
+ * protected void run(boolean measure) {
+ * Object obj = new Object();
+ * int i = random.nextInt(list.size() + 1);
+ * if (measure) list.add(i, obj);
+ * }
+ * protected void validate() { // Optional.
+ * assert list.size() == getNbrOfIterations();
+ * }
+ * }
+ * ...
+ * public void testExecutionTime() {
+ * insertPerf.measure(java.util.ArrayList.class, 10000).print();
+ * insertPerf.measure(java.util.LinkedList.class, 10000).print();
+ * insertPerf.measure(javolution.util.FastTable.class, 10000).print();
+ * }
+ * ...
+ * > [INFO] java.util.List#add(int, Object) (10000) for java.util.ArrayList: 590.21450 ns (avg), 8443.0000 ns (wcet#9369)
+ * > [INFO] java.util.List#add(int, Object) (10000) for java.util.LinkedList: 4849.8313 ns (avg), 26536.000 ns (wcet#9863)
+ * > [INFO] java.util.List#add(int, Object) (10000) for javolution.util.FastTable: 217.26300 ns (avg), 534.00000 ns (wcet#8864)
+ * [/code]
+ *
+ * @param <T> the perfometer input type.
+ */
+public abstract class Perfometer<T> {
+
+ /**
+ * Hold the measurement duration in milliseconds (default 1000 ms).
+ */
+ public static final Configurable<Integer> DURATION_MS = new Configurable<Integer>() {
+
+ @Override
+ public String getName() { // Requires since there are multiple configurable fields.
+ return this.getClass().getEnclosingClass().getName()
+ + "#DURATION_MS";
+ }
+
+ @Override
+ protected Integer getDefault() {
+ return 1000;
+ }
+
+ };
+ /**
+ * Indicates if perfometer measurements should be skipped (
+ * e.g. {@code -Djavolution.test.Perfometer#SKIP=true} to skip
+ * performance measurements).
+ * When skipped, {@link #measure} and {@link #print} don't do anything.
+ */
+ public static final Configurable<Boolean> SKIP = new Configurable<Boolean>() {
+
+ @Override
+ public String getName() { // Requires since there are multiple configurable fields.
+ return this.getClass().getEnclosingClass().getName() + "#SKIP";
+ }
+
+ @Override
+ protected Boolean getDefault() {
+ return false;
+ }
+ };
+
+ private final String description;
+ private T input;
+ private long[] times; // Nano-Seconds.
+
+ /**
+ * Creates a perfometer having the specified description.
+ *
+ * @param description the description of the code being measured.
+ */
+ public Perfometer(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Returns the average execution time in seconds.
+ */
+ public double getAvgTimeInSeconds() {
+ if (times == null) return Double.NaN;
+ long sum = 0;
+ for (long time : times) {
+ sum += time;
+ }
+ return sum / 1e9 / times.length;
+ }
+
+ /**
+ * Returns this perfometer description.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns this perfometer current inputs.
+ */
+ public T getInput() {
+ return input;
+ }
+
+ /**
+ * Returns this perfometer current number of iterations performed.
+ */
+ public int getNbrOfIterations() {
+ return (times != null) ? times.length : 0;
+ }
+
+ /**
+ * Returns the execution times in seconds.
+ */
+ public double[] getTimesInSeconds() {
+ if (times == null) return new double[0];
+ double[] timesSec = new double[times.length];
+ for (int i=0; i < times.length; i++) {
+ timesSec[i] = times[i] / 1e9;
+ }
+ return timesSec;
+ }
+
+ /**
+ * Measures the worst case execution time and average execution time.
+ *
+ * @param input the test input.
+ * @param nbrOfIterations the number of iterations performed on which
+ * the average will be calculated.
+ */
+ public Perfometer<T> measure(T input, int nbrOfIterations) {
+ if (SKIP.get()) return this; // Skip.
+ this.input = input;
+ this.times = new long[nbrOfIterations];
+ long[] calibrations = longArray(nbrOfIterations, Long.MAX_VALUE);
+ long[] measures = longArray(nbrOfIterations, Long.MAX_VALUE);
+ try {
+ long exitTime = System.currentTimeMillis() + DURATION_MS.get();
+ do {
+ // Calibration.
+ initialize();
+ for (int i = 0; i < nbrOfIterations; i++) {
+ long start = System.nanoTime();
+ run(false);
+ long time = System.nanoTime() - start;
+ calibrations[i] = MathLib.min(calibrations[i], time);
+ }
+ // Measurement.
+ initialize();
+ for (int i = 0; i < nbrOfIterations; i++) {
+ long start = System.nanoTime();
+ run(true);
+ long time = System.nanoTime() - start;
+ measures[i] = MathLib.min(measures[i], time);
+ }
+ } while (System.currentTimeMillis() < exitTime);
+ for (int i = 0; i < nbrOfIterations; i++) {
+ times[i] = measures[i] - calibrations[i];
+ }
+ return this;
+ } catch (Exception error) {
+ throw new RuntimeException("Perfometer Exception", error);
+ }
+ }
+
+ /**
+ * Outputs the result.
+ */
+ public void print() {
+ if (Perfometer.SKIP.get()) return;
+ TextBuilder txt = new TextBuilder();
+ txt.append(description).append(" (").append(getNbrOfIterations())
+ .append(") for ").append(input).append(": ");
+ while (txt.length() < 80)
+ txt.append(' ');
+ txt.append(getAvgTimeInSeconds() * 1E9, 8, false, true); // Nano-Seconds.
+ txt.append(" ns (avg), ");
+ txt.append(getWCETinSeconds() * 1E9, 8, false, true); // Nano-Seconds.
+ txt.append(" ns (wcet#").append(getWorstCaseNumber()).append(")");
+ LogContext.info(txt);
+ }
+
+ /**
+ * Outputs the measurements in nanoseconds.
+ */
+ public void printDetails() {
+ if (Perfometer.SKIP.get()) return;
+ FastTable<Long> measurements = new FastTable<Long>();
+ for (long time : times)
+ measurements.add(time);
+ LogContext.debug(measurements);
+ }
+
+ /**
+ * Returns the worst case execution time in seconds.
+ */
+ public double getWCETinSeconds() {
+ if (times == null) return Double.NaN;
+ long wcet = 0;
+ for (long time : times) {
+ if (time > wcet) wcet = time;
+ }
+ return wcet / 1e9;
+ }
+
+ /**
+ * Returns the iteration number having the slowest execution time.
+ */
+ public int getWorstCaseNumber() {
+ if (times == null) return -1;
+ long wcet = 0;
+ int j = -1;
+ for (int i=0; i < times.length; i++) {
+ if (times[i] > wcet) {
+ wcet = times[i];
+ j = i;
+ }
+ }
+ return j;
+ }
+
+ /**
+ * Performs the initialization.
+ */
+ protected abstract void initialize() throws Exception;
+
+ /**
+ * Runs the code being benchmarked.
+ *
+ * @param measure {@code false} when calibration is performed;
+ * {@code true} otherwise.
+ */
+ protected abstract void run(boolean measure) throws Exception;
+
+ /**
+ * Validates the final result (after all iterations are completed).
+ */
+ protected void validate() {}
+
+ private long[] longArray(int length, long initialValue) {
+ long[] array = new long[length];
+ for (int i = 0; i < length; i++)
+ array[i] = initialValue;
+ return array;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/test/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/test/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/test/package-info.java
new file mode 100644
index 0000000..be22b58
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/test/package-info.java
@@ -0,0 +1,5 @@
+/**
+<p> Testing tools for validation and performance.</p>
+ */
+package javolution.test;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/text/CharArray.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/CharArray.java b/commons/marmotta-commons/src/ext/java/javolution/text/CharArray.java
new file mode 100644
index 0000000..320bd00
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/CharArray.java
@@ -0,0 +1,393 @@
+/*
+ * 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.util.function.Equalities;
+
+/**
+ * <p> A {@link CharSequence} backed up by a <code>char</code> array.
+ * Instances of this class are
+ * typically used/reused to provide <code>CharSequence</code> views
+ * over existing character buffers.</p>
+ *
+ * <p> Instances of this classes have the following properties:<ul>
+ *
+ * <li> They support equality or lexical comparison with any
+ * <code>CharSequence</code> (e.g. <code>String</code>).</li>
+ *
+ * <li> They have the same hashcode than <code>String</code> and can be
+ * used to retrieve data from maps for which the keys are
+ * <code>String</code> instances.</li>
+ *
+ * <li> They support fast conversions to primitive types
+ * (e.g. {@link #toBoolean() Boolean}, {@link #toInt int}).</li>
+ *
+ * </ul></p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.3, January 10, 2007
+ */
+public final class CharArray implements CharSequence, Comparable<CharSequence> {
+
+ /**
+ * Holds the character array.
+ */
+ private char[] _array;
+
+ /**
+ * Holds the index of the first character.
+ */
+ private int _offset;
+
+ /**
+ * Holds the length of char sequence.
+ */
+ private int _length;
+
+ /**
+ * Default constructor (empty character array).
+ */
+ public CharArray() {
+ _array = NO_CHAR;
+ }
+
+ private static final char[] NO_CHAR = new char[0];
+
+ /**
+ * Creates a character array of specified default capacity.
+ *
+ * @param capacity the backing array default capacity.
+ */
+ public CharArray(int capacity) {
+ _array = new char[capacity];
+ }
+
+ /**
+ * Creates a character array from the specified String.
+ *
+ * @param string the string source.
+ */
+ public CharArray(String string) {
+ _array = string.toCharArray();
+ _length = string.length();
+ }
+
+ /**
+ * Returns the underlying array.
+ *
+ * @return the underlying array.
+ */
+ public char[] array() {
+ return _array;
+ }
+
+ /**
+ * Returns the length of this character sequence.
+ *
+ * @return the number of characters (16-bits Unicode).
+ */
+ public int length() {
+ return _length;
+ }
+
+ /**
+ * Returns the offset of the first character in the underlying array.
+ *
+ * @return the offset of the first character.
+ */
+ public int offset() {
+ return _offset;
+ }
+
+ /**
+ * Sets the underlying array of this CharArray.
+ *
+ * @param offset the new offset.
+ * @param array the new underlying array.
+ * @param length the new length.
+ * @return <code>this</code>
+ */
+ public CharArray setArray(char[] array, int offset, int length) {
+ _array = array;
+ _offset = offset;
+ _length = length;
+ return this;
+ }
+
+ /**
+ * Returns the index within this character sequence of the first occurrence
+ * of the specified characters sequence searching forward.
+ *
+ * @param csq a character sequence searched for.
+ * @return the index of the specified character sequence in the range
+ * <code>[0, length()[</code>
+ * or <code>-1</code> if the character sequence is not found.
+ */
+ public final int indexOf(java.lang.CharSequence csq) {
+ final char c = csq.charAt(0);
+ final int csqLength = csq.length();
+ for (int i = _offset, end = _offset + _length - csqLength + 1; i < end; i++) {
+ if (_array[i] == c) { // Potential match.
+ boolean match = true;
+ for (int j = 1; j < csqLength; j++) {
+ if (_array[i + j] != csq.charAt(j)) {
+ match = false;
+ break;
+ }
+ }
+ if (match) { return i - _offset; }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index within this character sequence of the first occurrence
+ * of the specified character searching forward.
+ *
+ * @param c the character to search for.
+ * @return the indext of the specified character in the range
+ * <code>[0, length()[</code>
+ * or <code>-1</code> if the character is not found.
+ */
+ public final int indexOf(char c) {
+ for (int i = _offset, end = _offset + _length; i < end; i++) {
+ if (_array[i] == c)
+ return i - _offset;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the <code>String</code> corresponding to this character
+ * sequence. The <code>String</code> returned is always allocated on the
+ * heap and can safely be referenced elsewhere.
+ *
+ * @return the <code>java.lang.String</code> for this character sequence.
+ */
+ @Override
+ public String toString() {
+ return new String(_array, _offset, _length);
+ }
+
+ /**
+ * Returns the hash code for this {@link CharArray}.
+ *
+ * <p> Note: Returns the same hashCode as <code>java.lang.String</code>
+ * (consistent with {@link #equals})</p>
+ * @return the hash code value.
+ */
+ @Override
+ public int hashCode() {
+ int h = 0;
+ for (int i = 0, j = _offset; i < _length; i++) {
+ h = 31 * h + _array[j++];
+ }
+ return h;
+ }
+
+ /**
+ * Compares this character sequence against the specified object
+ * (<code>String</code> or <code>CharSequence</code>).
+ *
+ * @param that the object to compare with.
+ * @return <code>true</code> if both objects represent the same sequence;
+ * <code>false</code> otherwise.
+ */
+ @Override
+ public boolean equals(Object that) {
+ if (that instanceof String) {
+ return equals((String) that);
+ } else if (that instanceof CharArray) {
+ return equals((CharArray) that);
+ } else if (that instanceof java.lang.CharSequence) {
+ return equals((java.lang.CharSequence) that);
+ } else {
+ return false;
+ }
+ }
+
+ // Do not make public or String instances may not use equals(String)
+ private boolean equals(java.lang.CharSequence chars) {
+ if (chars == null)
+ return false;
+ if (this._length != chars.length())
+ return false;
+ for (int i = _length, j = _offset + _length; --i >= 0;) {
+ if (_array[--j] != chars.charAt(i))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares this character array against the specified {@link CharArray}.
+ *
+ * @param that the character array to compare with.
+ * @return <code>true</code> if both objects represent the same sequence;
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(CharArray that) {
+ if (this == that)
+ return true;
+ if (that == null)
+ return false;
+ if (this._length != that._length)
+ return false;
+ final char[] thatArray = that._array;
+ for (int i = that._offset + _length, j = _offset + _length; --j >= _offset;) {
+ if (_array[j] != thatArray[--i])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares this character array against the specified String.
+ * In case of equality, the CharArray keeps a reference to the
+ * String for future comparisons.
+ *
+ * @param str the string to compare with.
+ * @return <code>true</code> if both objects represent the same sequence;
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(String str) {
+ if (str == null)
+ return false;
+ if (_length != str.length())
+ return false;
+ for (int i = _length, j = _offset + _length; --i >= 0;) {
+ if (_array[--j] != str.charAt(i))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares this character array with the specified character
+ * sequence lexicographically.
+ *
+ * @param seq the character sequence to be compared.
+ * @return <code>{@link Equalities#LEXICAL}.compare(this, seq)</code>
+ * @throws ClassCastException if the specifed object is not a
+ * <code>CharSequence</code>.
+ */
+ public int compareTo(CharSequence seq) {
+ return Equalities.LEXICAL.compare(this, seq);
+ }
+
+ /**
+ * Returns the <code>boolean</code> represented by this character array.
+ *
+ * @return the corresponding <code>boolean</code> value.
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>boolean</code>.
+ */
+ public boolean toBoolean() {
+ return TypeFormat.parseBoolean(this);
+ }
+
+ /**
+ * Returns the decimal <code>int</code> represented by this character array.
+ *
+ * @return <code>toInt(10)</code>
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>int</code>.
+ */
+ public int toInt() {
+ return TypeFormat.parseInt(this);
+ }
+
+ /**
+ * Returns the <code>int</code> represented by this character array
+ * in the specified radix.
+ *
+ * @param radix the radix (e.g. <code>16</code> for hexadecimal).
+ * @return the corresponding <code>int</code> value.
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>int</code>.
+ */
+ public int toInt(int radix) {
+ return TypeFormat.parseInt(this, radix);
+ }
+
+ /**
+ * Returns the decimal <code>long</code> represented by this character
+ * array.
+ *
+ * @return the corresponding <code>long</code> value.
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>long</code>.
+ */
+ public long toLong() {
+ return TypeFormat.parseLong(this);
+ }
+
+ /**
+ * Returns the decimal <code>long</code> represented by this character
+ * array in the specified radix.
+ *
+ * @param radix the radix (e.g. <code>16</code> for hexadecimal).
+ * @return the corresponding <code>long</code> value.
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>long</code>.
+ */
+ public long toLong(int radix) {
+ return TypeFormat.parseLong(this, radix);
+ }
+
+ /**
+ * Returns the <code>float</code> represented by this character array.
+ *
+ * @return the corresponding <code>float</code> value.
+ * @return <code>TypeFormat.parseFloat(this)</code>
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>float</code>.
+ */
+ public float toFloat() {
+ return TypeFormat.parseFloat(this);
+ }
+
+ /**
+ * Returns the <code>double</code> represented by this character array.
+ *
+ * @return the corresponding <code>double</code> value.
+ * @throws NumberFormatException if this character sequence
+ * does not contain a parsable <code>double</code>.
+ */
+ public double toDouble() {
+ return TypeFormat.parseDouble(this);
+ }
+
+ // Implements CharSequence
+ public char charAt(int index) {
+ if ((index < 0) || (index >= _length))
+ throw new IndexOutOfBoundsException("index: " + index);
+ return _array[_offset + index];
+ }
+
+ // Implements CharSequence
+ public java.lang.CharSequence subSequence(int start, int end) {
+ if ((start < 0) || (end < 0) || (start > end) || (end > this.length()))
+ throw new IndexOutOfBoundsException();
+ CharArray chars = new CharArray();
+ chars._array = _array;
+ chars._offset = _offset + start;
+ chars._length = end - start;
+ return chars;
+ }
+
+ // Implements CharSequence
+ public void getChars(int start, int end, char dest[], int destPos) {
+ if ((start < 0) || (end < 0) || (start > end) || (end > _length))
+ throw new IndexOutOfBoundsException();
+ System.arraycopy(_array, start + _offset, dest, destPos, end - start);
+ }
+
+}
\ 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/CharSet.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/CharSet.java b/commons/marmotta-commons/src/ext/java/javolution/text/CharSet.java
new file mode 100644
index 0000000..414d758
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/CharSet.java
@@ -0,0 +1,327 @@
+/*
+ * 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.lang.Immutable;
+import javolution.lang.MathLib;
+
+/**
+ * <p> A set of characters (typically used for parsing purpose where it is
+ * significantly faster than regular expressions for simple patterns).
+ * For example:
+ * [code]
+ * // Integration with Text.
+ * Text number;
+ * int exponentIndex = num.indexOfAny(CharSet.valueOf('e', 'E'));
+ *
+ * // Integration with TextFormat.
+ * public List<Integer> parse(CharSequence csq, Cursor cursor) {
+ * FastTable<Integer> numbers = FastTable.newInstance();
+ * while (cursor.skip(CharSet.WHITESPACES, csq)) {
+ * numbers.add(TypeFormat.parseInt(csq, cursor));
+ * }
+ * return numbers;
+ * } [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.7, January 1, 2006
+ */
+public final class CharSet implements Immutable<CharSet> {
+
+ /**
+ * Represents an empty character set.
+ */
+ public static final CharSet EMPTY = new CharSet(new long[0]);
+
+ /**
+ * Represents white spaces characters according to Java
+ * (see {@link Character#isWhitespace(char)}).
+ */
+ public static final CharSet WHITESPACES = CharSet.valueOf(new char[] { 0x9,
+ 0xA, 0xB, 0xC, 0xD, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x1680, 0x180E,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2008,
+ 0x2009, 0x200A, 0x200B, 0x2028, 0x2029, 0x205F, 0x3000 });
+
+ /**
+ * Represents spaces characters according to Java
+ * (see {@link Character#isSpaceChar(char)}).
+ */
+ public static final CharSet SPACES = CharSet.valueOf(new char[] { 0x20,
+ 0xA0, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004,
+ 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x2028,
+ 0x2029, 0x202F, 0x205F, 0x3000 });
+
+ /**
+ * Represents ISO control characters according to Java
+ * (see {@link Character#isISOControl(char)}).
+ */
+ public static final CharSet ISO_CONTROLS = CharSet.valueOf(new char[] {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC,
+ 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x7F, 0x80, 0x81,
+ 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F });
+
+ /**
+ * Holds the containment mapping.
+ */
+ private final long[] _mapping;
+
+ /**
+ * Creates a character set with the specified mapping.
+ *
+ * @param mapping the character set mapping.
+ */
+ private CharSet(long[] mapping) {
+ _mapping = mapping;
+ }
+
+ /**
+ * Returns the character set holding the specified characters.
+ *
+ * @param chars the characters contained by this character set.
+ * @return the corresponding character set.
+ */
+ public static CharSet valueOf(char... chars) {
+ int maxChar = 0;
+ for (int i = chars.length; --i >= 0;) {
+ if (chars[i] > maxChar) {
+ maxChar = chars[i];
+ }
+ }
+ CharSet charSet = new CharSet(new long[(maxChar >> 6) + 1]);
+ for (int i = chars.length; --i >= 0;) {
+ char c = chars[i];
+ charSet._mapping[c >> 6] |= 1L << (c & 63);
+ }
+ return charSet;
+ }
+
+ /**
+ * Returns the character set holding the characters in the specified
+ * range.
+ *
+ * @param first the first character.
+ * @param last the last character.
+ * @return the corresponding character set.
+ * @throws IllegalArgumentException if <code>first > last</code>
+ */
+ public static CharSet rangeOf(char first, char last) {
+ if (first > last)
+ throw new IllegalArgumentException(
+ "first should be less or equal to last");
+ CharSet charSet = new CharSet(new long[(last >> 6) + 1]);
+ for (char c = first; c <= last; c++) {
+ charSet._mapping[c >> 6] |= 1L << (c & 63);
+ }
+ return charSet;
+
+ }
+
+ /**
+ * Indicates if the specified character is contained by this character set.
+ *
+ * @param c the character to test.
+ * @return <code>true</code> if this character set contains the specified
+ * character; <code>false</code> otherwise.
+ */
+ public boolean contains(char c) {
+ final int i = c >> 6;
+ return i < _mapping.length ? (_mapping[i] & (1L << (c & 63))) != 0
+ : false;
+ }
+
+ /**
+ * Equivalent to
+ * {@link #indexIn(java.lang.CharSequence, int) indexIn(csq, 0)}
+ *
+ * @param csq the character sequence to be searched.
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int indexIn(CharSequence csq) {
+ return indexIn(csq, 0);
+ }
+
+ /**
+ * Returns the first index in the specified character sequence of
+ * one of the character of this set.
+ *
+ * @param csq the character sequence to be searched.
+ * @param fromIndex the index to search from.
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int indexIn(CharSequence csq, int fromIndex) {
+ for (int i = fromIndex, n = csq.length(); i < n; i++) {
+ if (contains(csq.charAt(i)))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Equivalent to {@link #indexIn(char[], int) indexIn(chars, 0)}
+ *
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int indexIn(char[] chars) {
+ return indexIn(chars, 0);
+ }
+
+ /**
+ * Returns the first index in the specified character array of
+ * one of the character of this set.
+ *
+ * @param chars the character array to be searched.
+ * @param fromIndex the index to search from.
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int indexIn(char[] chars, int fromIndex) {
+ for (int i = fromIndex, n = chars.length; i < n; i++) {
+ if (contains(chars[i]))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Equivalent to
+ * {@link #lastIndexIn(java.lang.CharSequence, int)
+ * lastIndexIn(csq, csq.length()-1)}
+ *
+ * @param csq the character sequence to be searched.
+ * @return the last index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int lastIndexIn(CharSequence csq) {
+ return lastIndexIn(csq, csq.length() - 1);
+ }
+
+ /**
+ * Returns the last index in the specified character sequence of
+ * one of the character of this set.
+ *
+ * @param csq the character sequence to be searched.
+ * @param fromIndex the index to search from (backward).
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int lastIndexIn(CharSequence csq, int fromIndex) {
+ for (int i = fromIndex; i >= 0; --i) {
+ if (contains(csq.charAt(i)))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Equivalent to {@link #lastIndexIn(char[], int)
+ * lastIndexIn(chars, chars.length-1)}
+ *
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int lastIndexIn(char[] chars) {
+ return lastIndexIn(chars, chars.length - 1);
+ }
+
+ /**
+ * Returns the last index in the specified character array of
+ * one of the character of this set.
+ *
+ * @param chars the character array to be searched.
+ * @param fromIndex the index to search from (backward).
+ * @return the index in the specified character sequence or
+ * <code>-1</code> if none found.
+ */
+ public int lastIndexIn(char[] chars, int fromIndex) {
+ for (int i = fromIndex; i >= 0; i--) {
+ if (contains(chars[i]))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the character set containing the characters from this
+ * character set plus the characters from the character set specified.
+ *
+ * @param that the set containing the characters to be added.
+ * @return <code>this + that</code>
+ */
+ public CharSet plus(CharSet that) {
+ if (that._mapping.length > this._mapping.length)
+ return that.plus(this);
+ CharSet result = this.copy();
+ for (int i = that._mapping.length; --i >= 0;) {
+ result._mapping[i] |= that._mapping[i];
+ }
+ return result;
+ }
+
+ /**
+ * Returns the character set containing the characters from this
+ * character minus the characters from the character set specified.
+ *
+ * @param that the set containing the character to be removed.
+ * @return <code>this - that</code>
+ */
+ public CharSet minus(CharSet that) {
+ CharSet result = this.copy();
+ for (int i = MathLib.min(this._mapping.length, that._mapping.length); --i >= 0;) {
+ result._mapping[i] &= ~that._mapping[i];
+ }
+ return result;
+ }
+
+ /**
+ * Returns the textual representation of this character set.
+ *
+ * @return the textual representation.
+ */
+ @Override
+ public String toString() {
+ TextBuilder tb = new TextBuilder();
+ tb.append('{');
+ int length = _mapping.length << 6;
+ for (int i = 0; i < length; i++) {
+ if (this.contains((char) i)) {
+ if (tb.length() > 1) {
+ tb.append(',');
+ tb.append(' ');
+ }
+ tb.append('\'');
+ tb.append((char) i);
+ tb.append('\'');
+ }
+ }
+ tb.append('}');
+ return tb.toString();
+ }
+
+ /**
+ * Returns a copy of this character set.
+ */
+ private CharSet copy() {
+ CharSet charSet = new CharSet(new long[this._mapping.length]);
+ for (int i = _mapping.length; --i >= 0;) {
+ charSet._mapping[i] = _mapping[i];
+ }
+ return charSet;
+ }
+
+ @Override
+ public CharSet 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/Cursor.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/Cursor.java b/commons/marmotta-commons/src/ext/java/javolution/text/Cursor.java
new file mode 100644
index 0000000..b27a9b4
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/Cursor.java
@@ -0,0 +1,397 @@
+/*
+ * 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;
+
+/**
+ * <p> A parsing cursor over the characters read. Cursor
+ * allows for token iterations over any {@link CharSequence}.
+ * [code]
+ * String str = "this is a test";
+ * Cursor cursor = new Cursor();
+ * for (CharSequence token; (token=cursor.nextToken(str, ' '))!= null;)
+ * System.out.println(token);
+ * [/code]
+ * Prints the following output:<pre>
+ * this
+ * is
+ * a
+ * test</pre>
+ * Cursors are typically used with {@link TextFormat} instances.
+ * [code]
+ * // Parses decimal number (e.g. "xxx.xxxxxExx" or "NaN")
+ * public Decimal parse(CharSequence csq, Cursor cursor) throws IllegalArgumentException {
+ * TextFormat<LargeInteger> largeIntegerFormat = TextContext.getFormat(LargeInteger.class);
+ * if (cursor.skip("NaN", csq))
+ * return Decimal.NaN;
+ * LargeInteger significand = LargeIntegerFormat.parse(csq, cursor);
+ * LargeInteger fraction = cursor.skip('.', csq) ? largeIntegerFormat.parse(csq, cursor) : LargeInteger.ZERO;
+ * int exponent = cursor.skip(CharSet.valueOf('E', 'e'), csq) ? TypeFormat.parseInt(csq, cursor) : 0;
+ * int fractionDigits = fraction.digitLength();
+ * return Decimal.valueOf(significand.E(fractionDigits).plus(fraction), exponent - fractionDigits);
+ * }
+ * [/code]
+ * </p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.4, November 19, 2009
+ */
+public class Cursor {
+
+ /**
+ * Holds the index.
+ */
+ private int index;
+
+ /**
+ * Default constructor.
+ */
+ public Cursor() {}
+
+ /**
+ * Returns this cursor index.
+ *
+ * @return the index of the next character to parse.
+ */
+ public final int getIndex() {
+ return index;
+ }
+
+ /**
+ * Sets the cursor current index.
+ *
+ * @param i the index of the next character to parse.
+ */
+ public final void setIndex(int i) {
+ index = i;
+ }
+
+ /**
+ * Indicates if this cursor points to the end of the specified
+ * character sequence.
+ *
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>getIndex() >= csq.length()</code>
+ */
+ public final boolean atEnd(CharSequence csq) {
+ return index >= csq.length();
+ }
+
+ /**
+ * Indicates if this cursor points to the specified character in the
+ * specified character sequence.
+ *
+ * @param c the character to test.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>csq.charAt(this.getIndex()) == c</code>
+ */
+ public final boolean at(char c, CharSequence csq) {
+ return index < csq.length() ? csq.charAt(index) == c : false;
+ }
+
+ /**
+ * Indicates if this cursor points to any of the specified character in the
+ * specified character sequence.
+ *
+ * @param charSet any of the character to test.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>csq.charAt(this.getIndex()) == c</code>
+ */
+ public final boolean at(CharSet charSet, CharSequence csq) {
+ return index < csq.length() ? charSet.contains(csq.charAt(index))
+ : false;
+ }
+
+ /**
+ * Indicates if this cursor points to the specified characters in the
+ * specified sequence.
+ *
+ * @param str the characters to test.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>true</code> if this cursor points to the specified
+ * characters; <code>false</code> otherwise.
+ */
+ public final boolean at(String str, CharSequence csq) {
+ int i = index;
+ int length = csq.length();
+ for (int j = 0; j < str.length();) {
+ if ((i >= length) || (str.charAt(j++) != csq.charAt(i++)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the current character at this cursor position.
+ *
+ * @param csq the character sequence iterated by this cursor.
+ * @return the current character this cursor points to.
+ * @throws IndexOutOfBoundsException if {@link #atEnd this.atEnd(csq)}
+ */
+ public final char currentChar(CharSequence csq) {
+ return csq.charAt(index);
+ }
+
+ /**
+ * Returns the next character at this cursor position.The cursor
+ * position is incremented by one.
+ *
+ * @param csq the character sequence iterated by this cursor.
+ * @return the next character this cursor points to.
+ * @throws IndexOutOfBoundsException if {@link #atEnd this.atEnd(csq)}
+ */
+ public final char nextChar(CharSequence csq) {
+ return csq.charAt(index++);
+ }
+
+ /**
+ * Moves this cursor forward until it points to a character
+ * different from the specified character.
+ *
+ * @param c the character to skip.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>true</code> if this cursor has skipped at least one
+ * character;<code>false</code> otherwise (e.g. end of sequence
+ * reached).
+ */
+ public final boolean skipAny(char c, CharSequence csq) {
+ int i = index;
+ int n = csq.length();
+ for (; (i < n) && (csq.charAt(i) == c); i++) {}
+ if (i == index)
+ return false; // Cursor did not moved.
+ index = i;
+ return true;
+ }
+
+ /**
+ * Moves this cursor forward until it points to a character
+ * different from any of the character in the specified set.
+ * For example: [code]
+ * // Reads numbers separated by tabulations or spaces.
+ * FastTable<Integer> numbers = new FastTable<Integer>();
+ * while (cursor.skipAny(CharSet.SPACE_OR_TAB, csq)) {
+ * numbers.add(TypeFormat.parseInt(csq, cursor));
+ * }[/code]
+ *
+ * @param charSet the character to skip.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>true</code> if this cursor has skipped at least one
+ * character;<code>false</code> otherwise (e.g. end of sequence
+ * reached).
+ */
+ public final boolean skipAny(CharSet charSet, CharSequence csq) {
+ int i = index;
+ int n = csq.length();
+ for (; (i < n) && charSet.contains(csq.charAt(i)); i++) {}
+ if (i == index)
+ return false; // Cursor did not moved.
+ index = i;
+ return true;
+ }
+
+ /**
+ * Moves this cursor forward only if at the specified character.
+ * This method is equivalent to:
+ * [code]
+ * if (at(c, csq))
+ * increment();
+ * [/code]
+ *
+ * @param c the character to skip.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>true</code> if this cursor has skipped the specified
+ * character;<code>false</code> otherwise.
+ */
+ public final boolean skip(char c, CharSequence csq) {
+ if (this.at(c, csq)) {
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Moves this cursor forward only if at any of the specified character.
+ * This method is equivalent to:
+ * [code]
+ * if (at(charSet, csq))
+ * increment();
+ * [/code]
+ *
+ * @param charSet holding the characters to skip.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>true</code> if this cursor has skipped any the specified
+ * character;<code>false</code> otherwise.
+ */
+ public final boolean skip(CharSet charSet, CharSequence csq) {
+ if (this.at(charSet, csq)) {
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Moves this cursor forward only if at the specified string.
+ * This method is equivalent to:
+ * [code]
+ * if (at(str, csq))
+ * increment(str.length());
+ * [/code]
+ *
+ * @param str the string to skip.
+ * @param csq the character sequence iterated by this cursor.
+ * @return <code>true</code> if this cursor has skipped the specified
+ * string;<code>false</code> otherwise (e.g. end of sequence
+ * reached).
+ */
+ public final boolean skip(String str, CharSequence csq) {
+ if (this.at(str, csq)) {
+ index += str.length();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the subsequence from the specified cursor position not holding
+ * the specified character. For example:[code]
+ * CharSequence csq = "This is a test";
+ * for (CharSequence token; (token=cursor.nextToken(csq, ' '))!= null;) {
+ * System.out.println(token); // Prints one word at a time.
+ * }[/code]
+ *
+ * @param csq the character sequence iterated by this cursor.
+ * @param c the character being skipped.
+ * @return the subsequence not holding the specified character or
+ * <code>null</code> if none.
+ */
+ public final CharSequence nextToken(CharSequence csq, char c) {
+ int n = csq.length();
+ for (int i = index; i < n; i++) {
+ if (csq.charAt(i) != c) {
+ int j = i;
+ for (; (++j < n) && (csq.charAt(j) != c);) {
+ // Loop until j at the end of sequence or at specified character.
+ }
+ index = j;
+ return csq.subSequence(i, j);
+ }
+ }
+ index = n;
+ return null;
+ }
+
+ /**
+ * Returns the subsequence from the specified cursor position not holding
+ * any of the characters specified. For example:[code]
+ * CharSequence csq = "This is a test";
+ * for (CharSequence token; (token=cursor.nextToken(csq, CharSet.WHITESPACE))!= null;) {
+ * System.out.println(token); // Prints one word at a time.
+ * }[/code]
+ *
+ * @param csq the character sequence iterated by this cursor.
+ * @param charSet the characters being skipped.
+ * @return the subsequence not holding the specified character or
+ * <code>null</code> if none.
+ */
+ public final CharSequence nextToken(CharSequence csq, CharSet charSet) {
+ int n = csq.length();
+ for (int i = index; i < n; i++) {
+ if (!charSet.contains(csq.charAt(i))) {
+ int j = i;
+ for (; (++j < n) && !charSet.contains(csq.charAt(j));) {
+ // Loop until j at the end of sequence or at specified characters.
+ }
+ index = j;
+ return csq.subSequence(i, j);
+ }
+ }
+ index = n;
+ return null;
+ }
+
+ /**
+ * Returns the head of the specified character sequence until
+ * this cursor position.
+ *
+ * @return the corresponding sub-sequence.
+ */
+ public final CharSequence head(CharSequence csq) {
+ return csq.subSequence(0, index);
+ }
+
+ /**
+ * Returns the tail of the specified character sequence starting at
+ * this cursor position.
+ *
+ * @return the corresponding sub-sequence.
+ */
+ public final CharSequence tail(CharSequence csq) {
+ return csq.subSequence(index, csq.length());
+ }
+
+ /**
+ * Increments the cursor index by one.
+ *
+ * @return <code>this</code>
+ */
+ public final Cursor increment() {
+ return increment(1);
+ }
+
+ /**
+ * Increments the cursor index by the specified value.
+ *
+ * @param i the increment value.
+ * @return <code>this</code>
+ */
+ public final Cursor increment(int i) {
+ index += i;
+ return this;
+ }
+
+ /**
+ * Returns the string representation of this cursor.
+ *
+ * @return the index value as a string.
+ */
+ @Override
+ public String toString() {
+ return "Cursor: " + index;
+ }
+
+ /**
+ * Indicates if this cursor is equals to the specified object.
+ *
+ * @return <code>true</code> if the specified object is a cursor
+ * at the same index; <code>false</code> otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj instanceof Cursor))
+ return false;
+ return index == ((Cursor) obj).index;
+ }
+
+ /**
+ * Returns the hash code for this cursor.
+ *
+ * @return the hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ return index;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/text/DefaultTextFormat.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/text/DefaultTextFormat.java b/commons/marmotta-commons/src/ext/java/javolution/text/DefaultTextFormat.java
new file mode 100644
index 0000000..98cdc87
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/text/DefaultTextFormat.java
@@ -0,0 +1,60 @@
+/*
+ * 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.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * <p> Specifies the default text format of a class (for parsing/formatting).
+ * The default format is typically used by the {@link Object#toString()}
+ * method and can be locally overridden in the scope of a
+ * {@link javolution.text.TextContext TextContext}.</p>
+ *
+ * [code]
+ * @DefaultTextFormat(Complex.Cartesian.class)
+ * public class Complex {
+ * public String toString() { // Uses the default format unless locally overridden.
+ * return TextContext.toString(this);
+ * }
+ * public static Complex valueOf(CharSequence csq) {
+ * return TextContext.parse(csq, Complex.class);
+ * }
+ * public static class Cartesian extends TextFormat<Complex> { ... }
+ * public static class Polar extends TextFormat<Complex> { ... }
+ * }
+ * ...
+ * TextContext ctx = TextContext.enter(); // Enters a local textual context.
+ * try {
+ * ctx.setFormat(Complex.class, new Complex.Polar()); // Configure the local context.
+ * System.out.println(complexMatrix); // Displays complex numbers in polar coordinates.
+ * } finally {
+ * ctx.exit(); // Exits local context (reverts to previous Cartesian format).
+ * }[/code]
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+@Documented
+@Inherited
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DefaultTextFormat {
+
+ /**
+ * Returns the default text format of the annotated class.
+ */
+ Class<? extends TextFormat<?>> value();
+
+}
[09/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/Index.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/Index.java b/commons/marmotta-commons/src/ext/java/javolution/util/Index.java
new file mode 100644
index 0000000..e63df1f
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/Index.java
@@ -0,0 +1,262 @@
+/*
+ * 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 java.io.IOException;
+import java.io.ObjectStreamException;
+
+import javolution.lang.Configurable;
+import javolution.lang.MathLib;
+import javolution.lang.Realtime;
+import javolution.lang.ValueType;
+import javolution.text.Cursor;
+import javolution.text.DefaultTextFormat;
+import javolution.text.TextContext;
+import javolution.text.TextFormat;
+import javolution.text.TypeFormat;
+
+/**
+ * <p> A non-negative number representing a position in an arrangement.
+ * For example:
+ * [code]
+ * class SparseVector<F> {
+ * FastMap<Index, F> elements = new FastMap<Index, F>();
+ * ...
+ * }[/code]</p>
+
+ * <p> Index performance is on-par with the primitive {@code int} type
+ * for small values and similar to {@link Integer} instances for large
+ * values. Small indexes have no adverse effect on the garbage collector
+ * and have fast {@link #equals(Object) equals} method due to their unicity.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.1, July 26, 2007
+ */
+@Realtime
+@DefaultTextFormat(Index.Decimal.class)
+public final class Index extends Number implements Comparable<Index>,
+ ValueType<Index> {
+
+ /**
+ * Default text format for indices (decimal value representation).
+ */
+ public static class Decimal extends TextFormat<Index> {
+
+ @Override
+ public Appendable format(Index obj, Appendable dest) throws IOException {
+ return TypeFormat.format(obj.intValue(), dest);
+ }
+
+ @Override
+ public Index parse(CharSequence csq, Cursor cursor)
+ throws IllegalArgumentException {
+ return Index.valueOf(TypeFormat.parseInt(csq, cursor));
+ }
+
+ }
+
+ /**
+ * Holds the number of unique preallocated instances (default {@code 1024}).
+ * This number is configurable, for example with
+ * {@code -Djavolution.util.Index#UNIQUE=0} there is no unique instance.
+ */
+ public static final Configurable<Integer> UNIQUE = new Configurable<Integer>() {
+
+ @Override
+ protected Integer getDefault() {
+ return 1024;
+ }
+
+ @Override
+ protected Integer initialized(Integer value) {
+ return MathLib.min(value, 65536); // Hard-limiting
+ }
+
+ @Override
+ protected Integer reconfigured(Integer oldCount, Integer newCount) {
+ throw new UnsupportedOperationException(
+ "Unicity reconfiguration not supported.");
+ }
+ };
+
+ /**
+ * Holds the index zero (value <code>0</code>).
+ */
+ public static final Index ZERO = new Index(0);
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ private static final Index[] INSTANCES = new Index[UNIQUE.get()];
+ static {
+ INSTANCES[0] = ZERO;
+ for (int i = 1; i < INSTANCES.length; i++) {
+ INSTANCES[i] = new Index(i);
+ }
+ }
+
+ /**
+ * Returns the index for the specified {@code int} non-negative
+ * value (returns a preallocated instance if the specified value is
+ * small).
+ *
+ * @param value the index value.
+ * @return the corresponding index.
+ * @throws IndexOutOfBoundsException if <code>value < 0</code>
+ */
+ public static Index valueOf(int value) {
+ return (value < INSTANCES.length) ? INSTANCES[value] : new Index(value);
+ }
+
+ /**
+ * Holds the index value.
+ */
+ private final int value;
+
+ /**
+ * Creates an index having the specified value.
+ */
+ private Index(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Compares this index with the specified index for order. Returns a
+ * negative integer, zero, or a positive integer as this index is less
+ * than, equal to, or greater than the specified index.
+ *
+ * @param that the index to be compared.
+ * @return a negative integer, zero, or a positive integer as this index
+ * is less than, equal to, or greater than the specified index.
+ */
+ public int compareTo(Index that) {
+ return this.value - that.value;
+ }
+
+ /**
+ * Compares this index with the specified integer value for order. Returns a
+ * negative integer, zero, or a positive integer as this index is less
+ * than, equal to, or greater than the specified value.
+ *
+ * @param value the value to be compared.
+ * @return a negative integer, zero, or a positive integer as this index
+ * is less than, equal to, or greater than the specified value.
+ */
+ public int compareTo(int value) {
+ return this.value - value;
+ }
+
+ /**
+ * Returns a copy of this index or <code>this</code> if the indexes
+ * is small (in permanent memory) in order to maintain unicity.
+ */
+ public Index copy() {
+ return value < INSTANCES.length ? this : new Index(value);
+ }
+
+ /**
+ * Returns the index value as <code>double</code>.
+ *
+ * @return the index value.
+ */
+ public double doubleValue() {
+ return (double) value;
+ }
+
+ /**
+ * Indicates if this index is equals to the one specified (for small
+ * indices this method is equivalent to <code>==</code>).
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return (this.value < INSTANCES.length) ? (this == obj)
+ : ((obj instanceof Index) ? (((Index) obj).value == value)
+ : false);
+ }
+
+ /**
+ * Returns the index value as <code>float</code>.
+ *
+ * @return the index value.
+ */
+ public float floatValue() {
+ return (float) value;
+ }
+
+ /**
+ * Returns the hash code for this index.
+ */
+ @Override
+ public int hashCode() {
+ return value;
+ }
+
+ /**
+ * Returns the index value as <code>int</code>.
+ *
+ * @return the index value.
+ */
+ public int intValue() {
+ return value;
+ }
+
+ /**
+ * Indicates if this index is zero.
+ *
+ * @return {@code this == ZERO}
+ */
+ public boolean isZero() {
+ return this == ZERO;
+ }
+
+ /**
+ * Returns the index value as <code>long</code>.
+ *
+ * @return the index value.
+ */
+ public long longValue() {
+ return value;
+ }
+
+ /**
+ * Returns the index after this one.
+ */
+ public Index next() {
+ return Index.valueOf(value + 1);
+ }
+
+ /**
+ * Returns the index before this one.
+ *
+ * @throws IndexOutOfBoundsException if (this == Index.ZERO)
+ */
+ public Index previous() {
+ return Index.valueOf(value - 1);
+ }
+
+ /**
+ * Ensures index unicity during deserialization.
+ */
+ protected final Object readResolve() throws ObjectStreamException {
+ return Index.valueOf(value);
+ }
+
+ /**
+ * Returns the {@link String} representation of this index.
+ *
+ * @return {@code TextContext.getFormat(Index.class).format(this)}
+ */
+ @Override
+ public String toString() {
+ return TextContext.getFormat(Index.class).format(this);
+ }
+
+ @Override
+ public Index 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/util/doc-files/FastTable-WCET.png
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/FastTable-WCET.png b/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/FastTable-WCET.png
new file mode 100644
index 0000000..68b19c1
Binary files /dev/null and b/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/FastTable-WCET.png differ
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/architecture.png
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/architecture.png b/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/architecture.png
new file mode 100644
index 0000000..a3b4ed9
Binary files /dev/null and b/commons/marmotta-commons/src/ext/java/javolution/util/doc-files/architecture.png differ
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/function/Consumer.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Consumer.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Consumer.java
new file mode 100644
index 0000000..9c03869
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Consumer.java
@@ -0,0 +1,29 @@
+/*
+ * 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.function;
+
+/**
+ * <p> A special type of function which does not return anything.</p>
+ *
+ * <p> Note: In future version this interface may derive from
+ * {@code Function<P, Void>}.</p>
+ *
+ * @param <T> The type of input parameter to accept.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface Consumer<T> {
+
+ /**
+ * Accepts an input value.
+ */
+ void accept(T param);
+
+}
\ 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/util/function/Equalities.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Equalities.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Equalities.java
new file mode 100644
index 0000000..75e1441
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Equalities.java
@@ -0,0 +1,79 @@
+package javolution.util.function;
+
+import javolution.lang.Parallelizable;
+import javolution.lang.Realtime;
+import javolution.util.internal.comparator.ArrayComparatorImpl;
+import javolution.util.internal.comparator.IdentityComparatorImpl;
+import javolution.util.internal.comparator.LexicalCaseInsensitiveComparatorImpl;
+import javolution.util.internal.comparator.LexicalComparatorImpl;
+import javolution.util.internal.comparator.LexicalFastComparatorImpl;
+import javolution.util.internal.comparator.StandardComparatorImpl;
+
+import static javolution.lang.Realtime.Limit.*;
+
+/**
+ * <p> A set of useful equalities comparators.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class Equalities {
+
+ /**
+ * A standard object comparator (based on the object hashCode and equals
+ * methods). Comparisons either use the object natural order (which
+ * should be consistent with equals) or an empirical method
+ * (if the object does not implement {@link Comparable}).
+ *
+ */
+ @Parallelizable
+ @Realtime(limit = UNKNOWN)
+ public static final Equality<Object> STANDARD = new StandardComparatorImpl<Object>();
+
+ /**
+ * A comparator for which instances are only equals to themselves.
+ * For comparisons an empirical method consistent with equals ({@code == })
+ * is used.
+ */
+ @Parallelizable
+ @Realtime(limit = CONSTANT)
+ public static final Equality<Object> IDENTITY = new IdentityComparatorImpl<Object>();
+
+ /**
+ * A content array comparator. If the content of an array is also
+ * an array (multi-dimensional arrays), that same comparator is used
+ * for equality and comparison (recursive). The {@link #STANDARD standard}
+ * comparator is used for non-array elements.
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static final Equality<Object> ARRAY = new ArrayComparatorImpl();
+
+ /**
+ * A lexicographic comparator for any {@link CharSequence}.
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static final Equality<CharSequence> LEXICAL = new LexicalComparatorImpl();
+
+ /**
+ * A case insensitive lexicographic comparator for any {@link CharSequence}.
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static final Equality<CharSequence> LEXICAL_CASE_INSENSITIVE = new LexicalCaseInsensitiveComparatorImpl();
+
+ /**
+ * An optimized lexical comparator for any {@link CharSequence} taking
+ * a sample of few characters instead of the whole character sequence to
+ * calculate the hash code (still equality comparison checks all characters).
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static final Equality<CharSequence> LEXICAL_FAST = new LexicalFastComparatorImpl();
+
+ /**
+ * Utility class (private constructor).
+ */
+ private Equalities() {}
+}
\ 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/util/function/Equality.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Equality.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Equality.java
new file mode 100644
index 0000000..1d7e8dc
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Equality.java
@@ -0,0 +1,77 @@
+/*
+ * 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.function;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * <p> A comparator to be used for element equality as well as for
+ * ordering. Implementing classes should ensure that:
+ * <ul>
+ * <li> The {@link #compare compare} function is consistent with
+ * {@link #areEqual equals}. If two objects {@link #compare compare}
+ * to {@code 0} then they are {@link #areEqual equals} and the
+ * the reciprocal is true (this ensures that sorted collections/maps
+ * do not break the general contract of their parent class based on
+ * object equal).</li>
+ * <li> The {@link #hashCodeOf hashcode} function is consistent with
+ * {@link #areEqual equals}: If two objects are equals, they have
+ * the same hashcode (the reciprocal is not true).</li>
+ * <li> The {@code null} value is supported (even for
+ * {@link #compare comparisons}) and the {@link #hashCodeOf(Object)
+ * hashcode} value of {@code null} is {@code 0}.</li>
+ * </ul>
+ * </p>
+ *
+ * @param <T> the type of objects that may be compared for equality or order.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see Equalities
+ */
+public interface Equality<T> extends Comparator<T>, Serializable {
+
+ /**
+ * Returns the hash code for the specified object (consistent with
+ * {@link #areEqual}). Two objects considered {@link #areEqual equal} have
+ * the same hash code. The hash code of <code>null</code> is always
+ * <code>0</code>.
+ *
+ * @param object the object to return the hashcode for.
+ * @return the hashcode for the specified object.
+ */
+ int hashCodeOf(T object);
+
+ /**
+ * Indicates if the specified objects can be considered equal.
+ * This methods is equivalent to {@code (compare(o1, o2) == 0)} but
+ * usually faster.
+ *
+ * @param left the first object (or <code>null</code>).
+ * @param right the second object (or <code>null</code>).
+ * @return <code>true</code> if both objects are considered equal;
+ * <code>false</code> otherwise.
+ */
+ boolean areEqual(T left, T right);
+
+ /**
+ * Compares the specified objects for order. Returns a negative integer,
+ * zero, or a positive integer as the first argument is less than, possibly
+ * equal to, or greater than the second. Implementation classes should
+ * ensure that comparisons with {@code null} is supported.
+ *
+ * @param left the first object.
+ * @param right the second object.
+ * @return a negative integer, zero, or a positive integer as the first
+ * argument is less than, possibly equal to, or greater than the second.
+ */
+ int compare(T left, T right);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/function/Function.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Function.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Function.java
new file mode 100644
index 0000000..35471de
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Function.java
@@ -0,0 +1,33 @@
+/*
+ * 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.function;
+
+
+/**
+ * <p> A function that perform some operation and returns the result of
+ * that operation.</p>
+ *
+ * @param <T> the type of the input parameter of the apply operation.
+ * @param <R> the type of the result of the apply operation.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see <a href="http://en.wikipedia.org/wiki/Function_(computer_science)">Wikipedia: Function<a>
+ */
+public interface Function<T, R> {
+
+ /**
+ * Returns the result of applying this function to the specified parameter.
+ *
+ * @param param the parameter object on which the function is performed.
+ * @return the result of the function.
+ */
+ R apply(T param);
+
+}
\ 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/util/function/Iteration.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Iteration.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Iteration.java
new file mode 100644
index 0000000..8d870ce
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Iteration.java
@@ -0,0 +1,32 @@
+/*
+ * 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.function;
+
+import java.util.Iterator;
+
+/**
+ * <p> A function iterating over a collection.</p>
+ *
+ * <p> Except for {@link Mutable} instances, iterations are not
+ * allowed to modify the collection iterated.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface Iteration<E> {
+
+ public interface Mutable<E> extends Iteration<E> {}
+ public interface Sequential<E> extends Iteration<E> {}
+
+ /**
+ * Runs the iteration using the specified iterator.
+ */
+ void run(Iterator<E> it);
+
+ }
\ 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/util/function/MultiVariable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/MultiVariable.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/MultiVariable.java
new file mode 100644
index 0000000..c38f4d8
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/MultiVariable.java
@@ -0,0 +1,54 @@
+/*
+ * 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.function;
+
+/**
+ * <p> An object holding multiple variables; typically used to create
+ * {@link Function multi-parameters functions}.</p>
+ *
+ * <p> Multi-variables may represent an unbounded number of variables.
+ * [code]
+ * MultiVariable<Double, MultiVariable<Integer, Boolean>> tertiaryVariable
+ * = new MultiVariable(2.3, new MultiVariable(57, true));
+ * [/code].</p>
+ *
+ * @param <L> the type of the variable on the left.
+ * @param <R> the type of the variable on the right.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public class MultiVariable<L, R> {
+
+ private final L left;
+ private final R right;
+
+ /**
+ * Returns a multi-variable holding the specified objects (possibly
+ * multi-variables themselves).
+ */
+ public MultiVariable(L left, R right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ /**
+ * Returns the variable on the left.
+ */
+ public L getLeft() {
+ return left;
+ }
+
+ /**
+ * Returns the variable on the right.
+ */
+ public R getRight() {
+ return right;
+ }
+}
\ 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/util/function/Predicate.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Predicate.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Predicate.java
new file mode 100644
index 0000000..e2c5803
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Predicate.java
@@ -0,0 +1,32 @@
+/*
+ * 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.function;
+
+/**
+ * <p> A function which states or affirms the attribute or quality of something.</p>
+ *
+ * <p> Note: In future version this interface may derive from
+ * {@code Function<P, Boolean>}.</p>
+
+ * @param <T> The type of input object to test.
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/Predicate_(mathematical_logic)">
+ * Wikipedia: Predicate<a>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface Predicate<T> {
+
+ /**
+ * Tests the specified value.
+ */
+ boolean test(T param);
+
+}
\ 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/util/function/Reducer.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Reducer.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Reducer.java
new file mode 100644
index 0000000..73b3e44
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Reducer.java
@@ -0,0 +1,26 @@
+/*
+ * 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.function;
+
+import java.util.Collection;
+
+
+/**
+ * <p> An operator upon multiple elements of a collection yielding a result
+ * of that collection type.</p>
+ *
+ * @param <E> The type of elements in the collection operated upon.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see Reducers
+ */
+public interface Reducer<E> extends Consumer<Collection<E>>, Supplier<E> {
+
+}
\ 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/util/function/Reducers.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Reducers.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Reducers.java
new file mode 100644
index 0000000..8705e12
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Reducers.java
@@ -0,0 +1,229 @@
+/*
+ * 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.function;
+
+import static javolution.lang.Realtime.Limit.LINEAR;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javolution.lang.Parallelizable;
+import javolution.lang.Realtime;
+import javolution.util.FastCollection;
+
+/**
+ * <p> A set of useful {@link Reducer reducers} of collection elements.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @see FastCollection#reduce(Reducer)
+ */
+public class Reducers {
+
+ // Utility class, no default constructor.
+ private Reducers() {}
+
+ /**
+ * Returns any non-null element of the specified type.
+ * This reducer stops iterating as soon as an element with the matching
+ * type is found.
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static <E> Reducer<E> any(Class<? extends E> type) {
+ return new AnyReducer<E>(type);
+ }
+
+ private static class AnyReducer<E> implements Reducer<E> {
+ private final Class<? extends E> type;
+ private volatile E found;
+
+ public AnyReducer(Class<? extends E> type) {
+ this.type = type;
+ }
+
+ @Override
+ public void accept(Collection<E> param) {
+ Iterator<E> it = param.iterator();
+ while (it.hasNext() && (found == null)) {
+ E e = it.next();
+ if (type.isInstance(e)) {
+ found = e;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public E get() {
+ return found;
+ }
+ }
+
+ /**
+ * Returns the greatest element of a collection according to the
+ * specified comparator (returns {@code null} if the collection is empty).
+ */
+ @Parallelizable(mutexFree = true, comment = "Internal use of AtomicReference")
+ @Realtime(limit = LINEAR)
+ public static <E> Reducer<E> max(Comparator<? super E> comparator) {
+ return new MaxReducer<E>(comparator);
+ }
+
+ private static class MaxReducer<E> implements Reducer<E> {
+ private final Comparator<? super E> cmp;
+ private final AtomicReference<E> max = new AtomicReference<E>(null);
+
+ public MaxReducer(Comparator<? super E> cmp) {
+ this.cmp = cmp;
+ }
+
+ @Override
+ public void accept(Collection<E> param) {
+ Iterator<E> it = param.iterator();
+ while (it.hasNext()) {
+ E e = it.next();
+ E read = max.get();
+ while ((read == null) || (cmp.compare(e, read) > 0)) {
+ if (max.compareAndSet(read, e)) break;
+ read = max.get();
+ }
+ }
+ }
+
+ @Override
+ public E get() {
+ return max.get();
+ }
+ }
+
+ /**
+ * Returns the smallest element of a collection according to the collection
+ * comparator (returns {@code null} if the collection is empty).
+ */
+ @Parallelizable(mutexFree = true, comment = "Internal use of AtomicReference")
+ @Realtime(limit = LINEAR)
+ public static <E> Reducer<E> min(Comparator<? super E> comparator) {
+ return new MinReducer<E>(comparator);
+ }
+
+ private static class MinReducer<E> implements Reducer<E> {
+ private final Comparator<? super E> cmp;
+ private final AtomicReference<E> min = new AtomicReference<E>(null);
+
+ public MinReducer(Comparator<? super E> cmp) {
+ this.cmp = cmp;
+ }
+
+ @Override
+ public void accept(Collection<E> param) {
+ Iterator<E> it = param.iterator();
+ while (it.hasNext()) {
+ E e = it.next();
+ E read = min.get();
+ while ((read == null) || (cmp.compare(e, read) < 0)) {
+ if (min.compareAndSet(read, e)) break;
+ read = min.get();
+ }
+ }
+ }
+
+ @Override
+ public E get() {
+ return min.get();
+ }
+ }
+
+ /**
+ * Conditional 'and' operator (returns {@code true} if the collection is
+ * empty). This operator stops iterating as soon as a {@code false} value
+ * is found.
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static Reducer<Boolean> and() {
+ return new AndReducer();
+ }
+
+ private static class AndReducer implements Reducer<Boolean> {
+ volatile boolean result = true;
+
+ @Override
+ public void accept(Collection<Boolean> param) {
+ Iterator<Boolean> it = param.iterator();
+ while (result && it.hasNext()) {
+ if (!it.next()) result = false;
+ }
+ }
+
+ @Override
+ public Boolean get() {
+ return result;
+ }
+ }
+
+ /**
+ * Conditional 'or' operator (returns {@code false} if the collection is
+ * empty). This operator stops iterating as soon as a {@code true} value
+ * is found.
+ */
+ @Parallelizable
+ @Realtime(limit = LINEAR)
+ public static Reducer<Boolean> or() {
+ return new OrReducer();
+ }
+
+ private static class OrReducer implements Reducer<Boolean> {
+ volatile boolean result = false;
+
+ @Override
+ public void accept(Collection<Boolean> param) {
+ Iterator<Boolean> it = param.iterator();
+ while (!result && it.hasNext()) {
+ if (!it.next()) result = true;
+ }
+ }
+
+ @Override
+ public Boolean get() {
+ return result;
+ }
+ }
+
+ /**
+ * Returns the sum of the specified integers value (returns {@code 0}
+ * if the collection is empty).
+ */
+ @Parallelizable(comment = "Internal use of AtomicInteger")
+ @Realtime(limit = LINEAR)
+ public static Reducer<Integer> sum() {
+ return new SumReducer();
+ }
+
+ private static class SumReducer implements Reducer<Integer> {
+ private final AtomicInteger sum = new AtomicInteger(0);
+
+ @Override
+ public void accept(Collection<Integer> param) {
+ Iterator<Integer> it = param.iterator();
+ while (it.hasNext()) {
+ sum.getAndAdd(it.next().intValue());
+ }
+ }
+
+ @Override
+ public Integer get() {
+ return sum.get();
+ }
+ }
+
+}
\ 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/util/function/Splittable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Splittable.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Splittable.java
new file mode 100644
index 0000000..4ad3d5d
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Splittable.java
@@ -0,0 +1,53 @@
+/*
+ * 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.function;
+
+
+/**
+ * An object which can be divided in distinct parts and on which the same
+ * action may be performed on the parts rather than the whole.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface Splittable<T> {
+
+ /**
+ * Executes a read-only action on the specified part of this object.
+ *
+ * @param action the read-only action.
+ * @param part this object or a part of it.
+ * @throws UnsupportedOperationException if the action tries to update the
+ * specified part.
+ */
+ void perform(Consumer<T> action, T part);
+
+ /**
+ * Returns {@code n} distinct parts of this object.
+ * This method may return an array of size less than {@code n}
+ * (e.g. an array of size one if this object cannot split).
+ *
+ * @param n the number of parts.
+ * @param threadsafe {@code true} if the returned parts can be updated
+ * concurrently; {@code false} otherwise.
+ * @return the distinct parts (or views) for this object.
+ * @throws IllegalArgumentException if {@code n < 1}
+ */
+ T[] split(int n, boolean threadsafe);
+
+ /**
+ * Executes an update action on the specified part of this object.
+ * Any change to the part is reflected in the whole (this object).
+ *
+ * @param action the action authorized to update this object part.
+ * @param part this object or a part of it.
+ */
+ void update(Consumer<T> action, T part);
+
+}
\ 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/util/function/Supplier.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/Supplier.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/Supplier.java
new file mode 100644
index 0000000..984549a
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/Supplier.java
@@ -0,0 +1,30 @@
+/*
+ * 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.function;
+
+/**
+ * <p> A function which does not take any argument and returns instances
+ * of a particular class.</p>
+ *
+ * <p> Note: In future version this interface may derive from
+ * {@code Function<Void, R>}.</p>
+ *
+ * @param <T> The type of result this supplier returns.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public interface Supplier<T> {
+
+ /**
+ * Returns an object.
+ */
+ T get();
+
+}
\ 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/util/function/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/function/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/util/function/package-info.java
new file mode 100644
index 0000000..4501ea9
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/function/package-info.java
@@ -0,0 +1,25 @@
+/**
+<p> Basic functions for lambda expressions and method references.</p>
+ Most often, functions do not have a state and can be called concurrently,
+ as indicated by the annotation {@link javolution.lang.Parallelizable Parallelizable}.</p>
+
+<p> Functions may take an arbitrary number of arguments through the use of
+ {@link javolution.util.function.MultiVariable multi-variables}
+ or no argument at all using the standard {@link java.lang.Void} class.
+[code]
+// Function populating a list of integer and returning void.
+Function<MultiVariable<List<Integer>, Integer>, Void> fill = new Function<>() {
+ public Void apply(MultiVariable<List<Integer>, Integer> params) {
+ List<Integer> list = params.getLeft();
+ for (int i = 0, n = params.getRight(); i < n; i++) {
+ list.add(i);
+ }
+ return null;
+ }
+};
+FastTable<Integer> list = new FastTable<Integer>();
+fill.apply(new MultiVariable(list, 100)); // Populates with numbers [0 .. 100[
+[/code]</p>
+ */
+package javolution.util.function;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/ReadWriteLockImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/ReadWriteLockImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/ReadWriteLockImpl.java
new file mode 100644
index 0000000..e4a464e
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/ReadWriteLockImpl.java
@@ -0,0 +1,138 @@
+/*
+ * 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.internal;
+
+import java.io.Serializable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+
+/**
+ * Simple and efficient read/write lock implementation giving
+ * preferences to writers. Acquiring a write lock then a read lock is
+ * supported. Writers may acquire a read lock after having the write lock
+ * but the reverse would result in deadlock.
+ */
+public final class ReadWriteLockImpl implements ReadWriteLock, Serializable {
+
+ /** Read-Lock Implementation. */
+ public final class ReadLock implements Lock, Serializable {
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ @Override
+ public void lock() {
+ try {
+ lockInterruptibly();
+ } catch (java.lang.InterruptedException e) {}
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ synchronized (ReadWriteLockImpl.this) {
+ if (writerThread == Thread.currentThread()) return; // Current thread has the writer lock.
+ while ((writerThread != null) || (waitingWriters != 0)) {
+ ReadWriteLockImpl.this.wait();
+ }
+ givenLocks++;
+ }
+ }
+
+ @Override
+ public Condition newCondition() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean tryLock() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean tryLock(long time, TimeUnit unit)
+ throws InterruptedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unlock() {
+ synchronized (ReadWriteLockImpl.this) {
+ if (writerThread == Thread.currentThread()) return; // Itself is the writing thread.
+ assert (givenLocks > 0);
+ givenLocks--;
+ ReadWriteLockImpl.this.notifyAll();
+ }
+ }
+ }
+
+ /** Write-Lock Implementation. */
+ public final class WriteLock implements Lock, Serializable {
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ @Override
+ public void lock() {
+ try {
+ lockInterruptibly();
+ } catch (java.lang.InterruptedException e) {}
+ }
+
+ @Override
+ public void lockInterruptibly() throws InterruptedException {
+ synchronized (ReadWriteLockImpl.this) {
+ waitingWriters++;
+ while (givenLocks != 0) {
+ ReadWriteLockImpl.this.wait();
+ }
+ waitingWriters--;
+ writerThread = Thread.currentThread();
+ }
+ }
+
+ @Override
+ public Condition newCondition() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean tryLock() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean tryLock(long time, TimeUnit unit)
+ throws InterruptedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unlock() {
+ synchronized (ReadWriteLockImpl.this) {
+ writerThread = null;
+ ReadWriteLockImpl.this.notifyAll();
+ }
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ public final ReadLock readLock = new ReadLock();
+ public final WriteLock writeLock = new WriteLock();
+ private transient int givenLocks;
+ private transient int waitingWriters;
+ private transient Thread writerThread;
+
+ @Override
+ public ReadLock readLock() {
+ return readLock;
+ }
+
+ @Override
+ public WriteLock writeLock() {
+ return writeLock;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetIteratorImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetIteratorImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetIteratorImpl.java
new file mode 100644
index 0000000..d5cadc9
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetIteratorImpl.java
@@ -0,0 +1,51 @@
+/*
+ * 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.internal.bitset;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javolution.util.Index;
+import javolution.util.service.BitSetService;
+
+/**
+ * An iterator over a bit set.
+ */
+public final class BitSetIteratorImpl implements Iterator<Index> {
+
+ private final BitSetService that;
+
+ private int nextIndex;
+
+ private int currentIndex = -1;
+
+ public BitSetIteratorImpl(BitSetService that, int index) {
+ this.that = that;
+ this.nextIndex = that.nextSetBit(index);
+ }
+
+ public boolean hasNext() {
+ return (nextIndex >= 0);
+ }
+
+ public Index next() {
+ if (nextIndex < 0)
+ throw new NoSuchElementException();
+ currentIndex = nextIndex;
+ nextIndex = that.nextSetBit(nextIndex + 1);
+ return Index.valueOf(currentIndex);
+ }
+
+ public void remove() {
+ if (currentIndex < 0)
+ throw new IllegalStateException();
+ that.clear(currentIndex);
+ currentIndex = -1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetServiceImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetServiceImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetServiceImpl.java
new file mode 100644
index 0000000..77c8c0c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/bitset/BitSetServiceImpl.java
@@ -0,0 +1,373 @@
+/*
+ * 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.internal.bitset;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import javolution.lang.MathLib;
+import javolution.util.Index;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.internal.set.SetView;
+import javolution.util.service.BitSetService;
+
+/**
+ * A table of indices implemented using packed bits (long[]).
+ */
+public class BitSetServiceImpl extends SetView<Index> implements BitSetService, Serializable {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ /** Holds the bits (64 bits per long), trimmed. */
+ private long[] bits;
+
+ /** Creates a bit set (256 bits). */
+ public BitSetServiceImpl() {
+ super(null); // Root.
+ bits = new long[4];
+ }
+
+ @Override
+ public boolean add(Index index) {
+ return !getAndSet(index.intValue(), true);
+ }
+
+ @Override
+ public void and(BitSetService that) {
+ long[] thatBits = that.toLongArray();
+ int n = MathLib.min(this.bits.length, thatBits.length);
+ for (int i = 0; i < n; i++) {
+ this.bits[i] &= thatBits[i];
+ }
+ for (int i = n; i < bits.length; i++) {
+ this.bits[i] = 0L;
+ }
+ trim();
+ }
+
+ @Override
+ public void andNot(BitSetService that) {
+ long[] thatBits = that.toLongArray();
+ int n = MathLib.min(this.bits.length, thatBits.length);
+ for (int i = 0; i < n; i++) {
+ this.bits[i] &= ~thatBits[i];
+ }
+ trim();
+ }
+
+ @Override
+ public int cardinality() {
+ int sum = 0;
+ for (int i = 0; i < bits.length; i++) {
+ sum += MathLib.bitCount(bits[i]);
+ }
+ return sum;
+ }
+
+ @Override
+ public void clear() {
+ bits = new long[0];
+ }
+
+ @Override
+ public void clear(int bitIndex) {
+ int longIndex = bitIndex >> 6;
+ if (longIndex >= bits.length)
+ return;
+ bits[longIndex] &= ~(1L << bitIndex);
+ trim();
+ }
+
+ @Override
+ public void clear(int fromIndex, int toIndex) {
+ if ((fromIndex < 0) || (toIndex < fromIndex))
+ throw new IndexOutOfBoundsException();
+ int i = fromIndex >>> 6;
+ if (i >= bits.length)
+ return; // Ensures that i < _length
+ int j = toIndex >>> 6;
+ if (i == j) {
+ bits[i] &= ((1L << fromIndex) - 1) | (-1L << toIndex);
+ return;
+ }
+ bits[i] &= (1L << fromIndex) - 1;
+ if (j < bits.length) {
+ bits[j] &= -1L << toIndex;
+ }
+ for (int k = i + 1; (k < j) && (k < bits.length); k++) {
+ bits[k] = 0;
+ }
+ trim();
+ }
+
+ @Override
+ public Equality<? super Index> comparator() {
+ return Equalities.IDENTITY;
+ }
+
+ @Override
+ public boolean contains(Object index) {
+ return get(((Index)index).intValue());
+ }
+
+ @Override
+ public void flip(int bitIndex) {
+ int i = bitIndex >> 6;
+ ensureCapacity(i + 1);
+ bits[i] ^= 1L << bitIndex;
+ trim();
+ }
+
+ @Override
+ public void flip(int fromIndex, int toIndex) {
+ if ((fromIndex < 0) || (toIndex < fromIndex))
+ throw new IndexOutOfBoundsException();
+ int i = fromIndex >>> 6;
+ int j = toIndex >>> 6;
+ ensureCapacity(j + 1);
+ if (i == j) {
+ bits[i] ^= (-1L << fromIndex) & ((1L << toIndex) - 1);
+ return;
+ }
+ bits[i] ^= -1L << fromIndex;
+ bits[j] ^= (1L << toIndex) - 1;
+ for (int k = i + 1; k < j; k++) {
+ bits[k] ^= -1;
+ }
+ trim();
+ }
+
+ @Override
+ public boolean get(int bitIndex) {
+ int i = bitIndex >> 6;
+ return (i >= bits.length) ? false : (bits[i] & (1L << bitIndex)) != 0;
+ }
+
+ @Override
+ public BitSetServiceImpl get(int fromIndex, int toIndex) {
+ if (fromIndex < 0 || fromIndex > toIndex)
+ throw new IndexOutOfBoundsException();
+ BitSetServiceImpl bitSet = new BitSetServiceImpl();
+ int length = MathLib.min(bits.length, (toIndex >>> 6) + 1);
+ bitSet.bits = new long[length];
+ System.arraycopy(bits, 0, bitSet.bits, 0, length);
+ bitSet.clear(0, fromIndex);
+ bitSet.clear(toIndex, length << 6);
+ return bitSet;
+ }
+
+ /** Sets the specified bit, returns <code>true</code> if previously set. */
+ @Override
+ public boolean getAndSet(int bitIndex, boolean value) {
+ int i = bitIndex >> 6;
+ ensureCapacity(i + 1);
+ boolean previous = (bits[i] & (1L << bitIndex)) != 0;
+ if (value) {
+ bits[i] |= 1L << bitIndex;
+ } else {
+ bits[i] &= ~(1L << bitIndex);
+ }
+ trim();
+ return previous;
+ }
+
+ @Override
+ public boolean intersects(BitSetService that) {
+ long[] thatBits = that.toLongArray();
+ int i = MathLib.min(this.bits.length, thatBits.length);
+ while (--i >= 0) {
+ if ((bits[i] & thatBits[i]) != 0) return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Iterator<Index> iterator() {
+ return new BitSetIteratorImpl(this, 0);
+ }
+
+ @Override
+ public int length() {
+ if (bits.length == 0) return 0;
+ return (bits.length << 6) - MathLib.numberOfLeadingZeros(bits[bits.length -1]);
+ }
+
+ @Override
+ public int nextClearBit(int fromIndex) {
+ int offset = fromIndex >> 6;
+ long mask = 1L << fromIndex;
+ while (offset < bits.length) {
+ long h = bits[offset];
+ do {
+ if ((h & mask) == 0) { return fromIndex; }
+ mask <<= 1;
+ fromIndex++;
+ } while (mask != 0);
+ mask = 1;
+ offset++;
+ }
+ return fromIndex;
+ }
+
+ @Override
+ public int nextSetBit(int fromIndex) {
+ int offset = fromIndex >> 6;
+ long mask = 1L << fromIndex;
+ while (offset < bits.length) {
+ long h = bits[offset];
+ do {
+ if ((h & mask) != 0)
+ return fromIndex;
+ mask <<= 1;
+ fromIndex++;
+ } while (mask != 0);
+ mask = 1;
+ offset++;
+ }
+ return -1;
+ }
+
+ @Override
+ public void or(BitSetService that) {
+ long[] thatBits = (that instanceof BitSetServiceImpl) ? ((BitSetServiceImpl) that).bits
+ : that.toLongArray();
+ ensureCapacity(thatBits.length);
+ for (int i = thatBits.length; --i >= 0;) {
+ bits[i] |= thatBits[i];
+ }
+ trim();
+ }
+
+ @Override
+ public int previousClearBit(int fromIndex) {
+ int offset = fromIndex >> 6;
+ long mask = 1L << fromIndex;
+ while (offset >= 0) {
+ long h = bits[offset];
+ do {
+ if ((h & mask) == 0)
+ return fromIndex;
+ mask >>= 1;
+ fromIndex--;
+ } while (mask != 0);
+ mask = 1L << 63;
+ offset--;
+ }
+ return -1;
+ }
+
+ @Override
+ public int previousSetBit(int fromIndex) {
+ int offset = fromIndex >> 6;
+ long mask = 1L << fromIndex;
+ while (offset >= 0) {
+ long h = bits[offset];
+ do {
+ if ((h & mask) != 0)
+ return fromIndex;
+ mask >>= 1;
+ fromIndex--;
+ } while (mask != 0);
+ mask = 1L << 63;
+ offset--;
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean remove(Object index) {
+ return getAndSet(((Index)index).intValue(), false);
+ }
+
+ @Override
+ public void set(int bitIndex) {
+ int i = bitIndex >> 6;
+ ensureCapacity(i + 1);
+ bits[i] |= 1L << bitIndex;
+ }
+
+ @Override
+ public void set(int bitIndex, boolean value) {
+ if (value) {
+ set(bitIndex);
+ } else {
+ clear(bitIndex);
+ }
+ }
+
+ @Override
+ public void set(int fromIndex, int toIndex) {
+ int i = fromIndex >>> 6;
+ int j = toIndex >>> 6;
+ ensureCapacity(j + 1);
+ if (i == j) {
+ bits[i] |= (-1L << fromIndex) & ((1L << toIndex) - 1);
+ return;
+ }
+ bits[i] |= -1L << fromIndex;
+ bits[j] |= (1L << toIndex) - 1;
+ for (int k = i + 1; k < j; k++) {
+ bits[k] = -1;
+ }
+ }
+
+ @Override
+ public void set(int fromIndex, int toIndex, boolean value) {
+ if (value) {
+ set(fromIndex, toIndex);
+ } else {
+ clear(fromIndex, toIndex);
+ }
+ }
+
+ @Override
+ public int size() {
+ return cardinality();
+ }
+
+ @Override
+ public long[] toLongArray() {
+ return bits;
+ }
+
+ @Override
+ public void xor(BitSetService that) {
+ long[] thatBits = (that instanceof BitSetServiceImpl) ? ((BitSetServiceImpl) that).bits
+ : that.toLongArray();
+ ensureCapacity(thatBits.length);
+ for (int i = thatBits.length; --i >= 0;) {
+ bits[i] ^= thatBits[i];
+ }
+ trim();
+ }
+
+ // Checks capacity.
+ private void ensureCapacity(int capacity) {
+ if (bits.length < capacity) resize(capacity);
+ }
+
+ // Resize.
+ private void resize(int min) {
+ int newLength = bits.length * 2;
+ while (newLength < min) newLength *= 2;
+ long[] tmp = new long[newLength];
+ System.arraycopy(bits, 0, tmp, 0, bits.length);
+ bits = tmp;
+ }
+
+ /**
+ * Removes the tails words if cleared.
+ */
+ private void trim() {
+ int n = bits.length;
+ while ((--n >= 0) && (bits[n] == 0L)) {}
+ if (++n < bits.length) ensureCapacity(n);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/AtomicCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/AtomicCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/AtomicCollectionImpl.java
new file mode 100644
index 0000000..9773743
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/AtomicCollectionImpl.java
@@ -0,0 +1,194 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * An atomic view over a collection (copy-on-write).
+ */
+public class AtomicCollectionImpl<E> extends CollectionView<E> {
+
+ /** Thread-Safe Iterator. */
+ private class IteratorImpl implements Iterator<E> {
+ private E current;
+ private final Iterator<E> targetIterator;
+
+ public IteratorImpl() {
+ targetIterator = targetView().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public E next() {
+ current = targetIterator.next();
+ return current;
+ }
+
+ @Override
+ public void remove() {
+ if (current == null) throw new IllegalStateException();
+ AtomicCollectionImpl.this.remove(current);
+ current = null;
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected volatile CollectionService<E> immutable; // The copy used by readers.
+ protected transient Thread updatingThread; // The thread executing an update.
+
+ public AtomicCollectionImpl(CollectionService<E> target) {
+ super(target);
+ this.immutable = cloneTarget();
+ }
+
+ @Override
+ public synchronized boolean add(E element) {
+ boolean changed = target().add(element);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized boolean addAll(Collection<? extends E> c) {
+ boolean changed = target().addAll(c);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized void clear() {
+ clear();
+ if (!updateInProgress()) {
+ immutable = cloneTarget();
+ }
+ }
+
+ @Override
+ public synchronized AtomicCollectionImpl<E> clone() { // Synchronized required since working with real target.
+ AtomicCollectionImpl<E> copy = (AtomicCollectionImpl<E>) super.clone();
+ copy.updatingThread = null;
+ return copy;
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return immutable.comparator();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return targetView().contains(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return targetView().containsAll(c);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return targetView().equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return targetView().hashCode();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return targetView().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public synchronized boolean remove(Object o) {
+ boolean changed = target().remove(o);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized boolean removeAll(Collection<?> c) {
+ boolean changed = target().removeAll(c);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public synchronized boolean retainAll(Collection<?> c) {
+ boolean changed = target().retainAll(c);
+ if (changed && !updateInProgress()) immutable = cloneTarget();
+ return changed;
+ }
+
+ @Override
+ public int size() {
+ return targetView().size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return targetView().toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return targetView().toArray(a);
+ }
+
+ @Override
+ public synchronized void update(Consumer<CollectionService<E>> action,
+ CollectionService<E> view) {
+ updatingThread = Thread.currentThread(); // Update in progress.
+ try {
+ target().update(action, view); // No copy performed.
+ } finally {
+ updatingThread = null;
+ immutable = cloneTarget(); // One single copy !
+ }
+ }
+
+ /** Returns a clone copy of target. */
+ protected CollectionService<E> cloneTarget() {
+ try {
+ return target().clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Cannot happen since target is Cloneable.");
+ }
+ }
+
+ /** Returns either the immutable target or the actual target if updating
+ * thread. */
+ protected CollectionService<E> targetView() {
+ return ((updatingThread == null) || (updatingThread != Thread.currentThread()))
+ ? immutable : target();
+ }
+
+ /** Indicates if the current thread is doing an atomic update. */
+ protected final boolean updateInProgress() {
+ return updatingThread == Thread.currentThread();
+
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/CollectionView.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/CollectionView.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/CollectionView.java
new file mode 100644
index 0000000..c077ad7
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/CollectionView.java
@@ -0,0 +1,268 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javolution.util.FastCollection;
+import javolution.util.function.Consumer;
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * Collection view implementation; can be used as root class for implementations
+ * if target is {@code null}.
+ * When possible sub-classes should forward to the actual target for the methods
+ * clear, remove, contains, size and isEmpty rather than using the default
+ * implementation.
+ */
+public abstract class CollectionView<E> extends FastCollection<E> implements CollectionService<E> {
+//public abstract class CollectionView<E> implements CollectionService<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ private CollectionService<E> target;
+
+ /**
+ * The view constructor or root class constructor if target is {@code null}.
+ */
+ public CollectionView(CollectionService<E> target) {
+ this.target = target;
+ }
+
+ @Override
+ public abstract boolean add(E element);
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ boolean changed = false;
+ Iterator<? extends E> it = c.iterator();
+ while (it.hasNext()) {
+ if (add(it.next())) changed = true;
+ }
+ return changed;
+ }
+
+ @Override
+ public void clear() {
+ Iterator<? extends E> it = iterator();
+ while (it.hasNext()) {
+ it.next();
+ it.remove();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public CollectionView<E> clone() {
+ try {
+ CollectionView<E> copy = (CollectionView<E>) super.clone();
+ if (target != null) { // Not a root class.
+ copy.target = target.clone();
+ }
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ throw new Error("Should not happen since target is cloneable");
+ }
+ }
+
+ @Override
+ public abstract Equality<? super E> comparator();
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean contains(Object obj) {
+ Iterator<? extends E> it = iterator();
+ Equality<Object> cmp = (Equality<Object>) comparator();
+ while (it.hasNext()) {
+ if (cmp.areEqual(obj, it.next())) return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ for (Object e : c) {
+ if (!contains(e)) return false;
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object o) {
+ // Follow Collection.equals specification if this comparator is standard.
+ if (this == o) return true;
+ // Check comparators consistency.
+ if (o instanceof CollectionService) {
+ if (!comparator().equals(((CollectionService<E>) o).comparator())) return false; // Different comparators.
+ } else {
+ if (!comparator().equals(Equalities.STANDARD)) return false;
+ }
+ // Collection.equals contract.
+ if (this instanceof Set) {
+ if (!(o instanceof Set)) return false;
+ Set<E> set = (Set<E>) o;
+ return (size() == set.size()) && containsAll(set);
+ } else if (this instanceof List) {
+ if (!(o instanceof List)) return false;
+ List<E> list = (List<E>) o;
+ if (size() != list.size()) return false; // Short-cut.
+ Equality<? super E> cmp = comparator();
+ Iterator<E> it1 = this.iterator();
+ Iterator<E> it2 = list.iterator();
+ while (it1.hasNext()) {
+ if (!it2.hasNext()) return false;
+ if (!cmp.areEqual(it1.next(), it2.next())) return false;
+ }
+ if (it2.hasNext()) return false;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ // Follow Collection.equals specification if this comparator is standard.
+ Equality<? super E> cmp = comparator();
+ Iterator<E> it = this.iterator();
+ int hash = 0;
+ if (this instanceof Set) {
+ while (it.hasNext()) {
+ hash += cmp.hashCodeOf(it.next());
+ }
+ } else if (this instanceof List) {
+ while (it.hasNext()) {
+ hash += 31 * hash + cmp.hashCodeOf(it.next());
+ }
+ } else {
+ hash = super.hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return !iterator().hasNext();
+ }
+
+ @Override
+ public abstract Iterator<E> iterator();
+
+ @Override
+ public void perform(Consumer<CollectionService<E>> action, CollectionService<E> view) {
+ if (target == null) {
+ action.accept(view);
+ } else {
+ target.perform(action, view);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean remove(Object obj) {
+ Iterator<? extends E> it = iterator();
+ Equality<Object> cmp = (Equality<Object>) comparator();
+ while (it.hasNext()) {
+ if (cmp.areEqual(obj, it.next())) {
+ it.remove();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ boolean changed = false;
+ Iterator<? extends E> it = iterator();
+ while (it.hasNext()) {
+ if (c.contains(it.next())) {
+ it.remove();
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ boolean changed = false;
+ Iterator<? extends E> it = iterator();
+ while (it.hasNext()) {
+ if (!c.contains(it.next())) {
+ it.remove();
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public int size() {
+ int count = 0;
+ Iterator<? extends E> it = iterator();
+ while (it.hasNext()) {
+ count++;
+ it.next();
+ }
+ return count;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public CollectionService<E>[] split(int n, boolean updateable) {
+ return new CollectionService[] { this }; // Split not supported.
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toArray(new Object[size()]);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T[] toArray(T[] a) {
+ final int size = size();
+ final T[] result = (size <= a.length) ? a
+ : (T[]) java.lang.reflect.Array.newInstance(a.getClass()
+ .getComponentType(), size);
+ int i = 0;
+ Iterator<E> it = iterator();
+ while (it.hasNext()) {
+ result[i++] = (T) it.next();
+ }
+ if (result.length > size) {
+ result[size] = null; // As per Collection contract.
+ }
+ return result;
+ }
+
+ @Override
+ public void update(Consumer<CollectionService<E>> action, CollectionService<E> view) {
+ if (target == null) {
+ action.accept(view);
+ } else {
+ target.perform(action, view);
+ }
+ }
+
+ protected CollectionService<E> service() {
+ return this;
+ }
+
+ /** Returns the actual target */
+ protected CollectionService<E> target() {
+ return target;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/DistinctCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/DistinctCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/DistinctCollectionImpl.java
new file mode 100644
index 0000000..713dc5b
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/DistinctCollectionImpl.java
@@ -0,0 +1,102 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.util.FastSet;
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * A view which does not iterate twice over the same elements.
+ */
+public class DistinctCollectionImpl<E> extends CollectionView<E> {
+
+ /** Peeking ahead iterator. */
+ private class IteratorImpl implements Iterator<E> {
+
+ private boolean ahead;
+ private final FastSet<E> iterated = new FastSet<E>(comparator());
+ private E next;
+ private final Iterator<E> targetIterator = target().iterator();
+
+ @Override
+ public boolean hasNext() {
+ if (ahead) return true;
+ while (targetIterator.hasNext()) {
+ next = targetIterator.next();
+ if (!iterated.contains(next)) {
+ ahead = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public E next() {
+ hasNext(); // Moves ahead.
+ ahead = false;
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ targetIterator.remove();
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public DistinctCollectionImpl(CollectionService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean add(E element) {
+ if (target().contains(element)) return false;
+ return target().add(element);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return target().contains(o);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public boolean remove(Object o) { // Remove all instances.
+ boolean changed = false;
+ while (true) {
+ if (!remove(o)) return changed;
+ changed = true;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/FilteredCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/FilteredCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/FilteredCollectionImpl.java
new file mode 100644
index 0000000..8f1574c
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/FilteredCollectionImpl.java
@@ -0,0 +1,111 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.util.function.Equality;
+import javolution.util.function.Predicate;
+import javolution.util.service.CollectionService;
+
+/**
+ * A filtered view over a collection.
+ */
+public class FilteredCollectionImpl<E> extends CollectionView<E> {
+
+ /** Peeking ahead iterator. */
+ private class IteratorImpl implements Iterator<E> {
+
+ private boolean ahead; // Indicates if the iterator is ahead (on next element)
+ private final Predicate<? super E> filter;
+ private E next;
+ private final Iterator<E> targetIterator;
+
+ public IteratorImpl(Predicate<? super E> filter) {
+ this.filter = filter;
+ targetIterator = target().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (ahead) return true;
+ while (targetIterator.hasNext()) {
+ next = targetIterator.next();
+ if (filter.test(next)) {
+ ahead = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public E next() {
+ hasNext(); // Moves ahead.
+ ahead = false;
+ return next;
+ }
+
+ @Override
+ public void remove() {
+ targetIterator.remove();
+ }
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected final Predicate<? super E> filter;
+
+ public FilteredCollectionImpl(CollectionService<E> target,
+ Predicate<? super E> filter) {
+ super(target);
+ this.filter = filter;
+ }
+
+ @Override
+ public boolean add(E element) {
+ if (!filter.test(element)) return false;
+ return target().add(element);
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean contains(Object o) {
+ if (!filter.test((E) o)) return false;
+ return target().contains(o);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new IteratorImpl(filter);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean remove(Object o) {
+ if (!filter.test((E) o)) return false;
+ return target().remove(o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public CollectionService<E>[] split(int n, boolean updateable) {
+ CollectionService<E>[] subTargets = target().split(n, updateable);
+ CollectionService<E>[] result = new CollectionService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new FilteredCollectionImpl<E>(subTargets[i], filter);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/MappedCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/MappedCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/MappedCollectionImpl.java
new file mode 100644
index 0000000..425b7b8
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/MappedCollectionImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.util.function.Equalities;
+import javolution.util.function.Equality;
+import javolution.util.function.Function;
+import javolution.util.service.CollectionService;
+
+/**
+ * A mapped view over a collection.
+ */
+public class MappedCollectionImpl<E, R> extends CollectionView<R> {
+
+ /** Mapping iterator. */
+ private class IteratorImpl implements Iterator<R> {
+ private final Iterator<E> targetIterator;
+
+ @SuppressWarnings("unchecked")
+ public IteratorImpl() {
+ targetIterator = (Iterator<E>) target().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return targetIterator.hasNext();
+ }
+
+ @Override
+ public R next() {
+ return function.apply(targetIterator.next());
+ }
+
+ @Override
+ public void remove() {
+ targetIterator.remove();
+ }
+
+ }
+
+ private static final long serialVersionUID = 0x600L; // Version.
+ protected final Function<? super E, ? extends R> function;
+
+ @SuppressWarnings("unchecked")
+ public MappedCollectionImpl(CollectionService<E> target,
+ Function<? super E, ? extends R> function) {
+ super((CollectionService<R>) target); // Beware target is of type <E>
+ this.function = function;
+ }
+
+ @Override
+ public boolean add(R element) {
+ throw new UnsupportedOperationException(
+ "New elements cannot be added to mapped views");
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super R> comparator() {
+ return Equalities.STANDARD;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<R> iterator() {
+ return new IteratorImpl();
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public CollectionService<R>[] split(int n, boolean updateable) {
+ CollectionService<E>[] subTargets = (CollectionService<E>[]) target().split(n, updateable);
+ CollectionService<R>[] result = new CollectionService[subTargets.length];
+ for (int i = 0; i < subTargets.length; i++) {
+ result[i] = new MappedCollectionImpl<E, R>(subTargets[i], function);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ParallelCollectionImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ParallelCollectionImpl.java b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ParallelCollectionImpl.java
new file mode 100644
index 0000000..8056aed
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/util/internal/collection/ParallelCollectionImpl.java
@@ -0,0 +1,120 @@
+/*
+ * 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.internal.collection;
+
+import java.util.Iterator;
+
+import javolution.context.ConcurrentContext;
+import javolution.util.function.Consumer;
+import javolution.util.function.Equality;
+import javolution.util.service.CollectionService;
+
+/**
+ * A parallel view over a collection.
+ */
+public class ParallelCollectionImpl<E> extends CollectionView<E> {
+
+ private static final long serialVersionUID = 0x600L; // Version.
+
+ public ParallelCollectionImpl(CollectionService<E> target) {
+ super(target);
+ }
+
+ @Override
+ public boolean add(E e) {
+ return target().add(e);
+ }
+
+ @Override
+ public void clear() {
+ target().clear();
+ }
+
+ @Override
+ public Equality<? super E> comparator() {
+ return target().comparator();
+ }
+
+ @Override
+ public boolean contains(Object obj) {
+ return target().contains(obj);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return target().isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return target().iterator();
+ }
+
+ @Override
+ public void perform(final Consumer<CollectionService<E>> action,
+ CollectionService<E> view) {
+ ConcurrentContext ctx = ConcurrentContext.enter();
+ try {
+ int concurrency = ctx.getConcurrency();
+ CollectionService<E>[] subViews = view.split(concurrency + 1, false);
+ for (int i = 1; i < subViews.length; i++) {
+ final CollectionService<E> subView = subViews[i];
+ ctx.execute(new Runnable() {
+ @Override
+ public void run() {
+ target().perform(action, subView);
+ }
+ });
+ }
+ target().perform(action, subViews[0]); // This thread works too !
+ } finally {
+ // Any exception raised during parallel iterations will be re-raised here.
+ ctx.exit();
+ }
+ }
+
+ @Override
+ public boolean remove(Object obj) {
+ return target().remove(obj);
+ }
+
+ @Override
+ public int size() {
+ return target().size();
+ }
+
+ @Override
+ public CollectionService<E>[] split(int n, boolean threadsafe) {
+ return target().split(n, threadsafe); // Forwards.
+ }
+
+ @Override
+ public void update(final Consumer<CollectionService<E>> action,
+ CollectionService<E> view) {
+ ConcurrentContext ctx = ConcurrentContext.enter();
+ try {
+ int concurrency = ctx.getConcurrency();
+ CollectionService<E>[] subViews = view.split(concurrency + 1, true);
+ for (int i = 1; i < subViews.length; i++) {
+ final CollectionService<E> subView = subViews[i];
+ ctx.execute(new Runnable() {
+ @Override
+ public void run() {
+ target().update(action, subView);
+ }
+ });
+ }
+ target().perform(action, subViews[0]); // This thread works too !
+ } finally {
+ // Any exception raised during parallel iterations will be re-raised here.
+ ctx.exit();
+ }
+ }
+
+}
[15/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)
Posted by ss...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamReader.java b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamReader.java
new file mode 100644
index 0000000..61fa4fb
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamReader.java
@@ -0,0 +1,316 @@
+/*
+ * 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.io;
+
+import java.io.CharConversionException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * <p> A UTF-8 stream reader.</p>
+ *
+ * <p> This reader supports surrogate <code>char</code> pairs (representing
+ * characters in the range [U+10000 .. U+10FFFF]). It can also be used
+ * to read characters unicodes (31 bits) directly
+ * (ref. {@link #read()}).</p>
+ *
+ * <p> Each invocation of one of the <code>read()</code> methods may cause one
+ * or more bytes to be read from the underlying byte-input stream.
+ * To enable the efficient conversion of bytes to characters, more bytes may
+ * be read ahead from the underlying stream than are necessary to satisfy
+ * the current read operation.</p>
+ *
+ * <p> Instances of this class can be reused for different input streams
+ * and can be part of a higher level component (e.g. parser) in order
+ * to avoid dynamic buffer allocation when the input source changes.
+ * Also wrapping using a <code>java.io.BufferedReader</code> is unnescessary
+ * as instances of this class embed their own data buffers.</p>
+ *
+ * <p> Note: This reader is unsynchronized and does not test if the UTF-8
+ * encoding is well-formed (e.g. UTF-8 sequences longer than
+ * necessary to encode a character).</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 2.0, December 9, 2004
+ * @see UTF8StreamWriter
+ */
+public final class UTF8StreamReader extends Reader {
+
+ /**
+ * Holds the current input stream or <code>null</code> if closed.
+ */
+ private InputStream _inputStream;
+
+ /**
+ * Holds the start index.
+ */
+ private int _start;
+
+ /**
+ * Holds the end index.
+ */
+ private int _end;
+
+ /**
+ * Holds the bytes buffer.
+ */
+ private final byte[] _bytes;
+
+ /**
+ * Creates a UTF-8 reader having a byte buffer of moderate capacity (2048).
+ */
+ public UTF8StreamReader() {
+ _bytes = new byte[2048];
+ }
+
+ /**
+ * Creates a UTF-8 reader having a byte buffer of specified capacity.
+ *
+ * @param capacity the capacity of the byte buffer.
+ */
+ public UTF8StreamReader(int capacity) {
+ _bytes = new byte[capacity];
+ }
+
+ /**
+ * Sets the input stream to use for reading until this reader is closed.
+ * For example:[code]
+ * Reader reader = new UTF8StreamReader().setInput(inStream);
+ * [/code] is equivalent but reads twice as fast as [code]
+ * Reader reader = new java.io.InputStreamReader(inStream, "UTF-8");
+ * [/code]
+ *
+ * @param inStream the input stream.
+ * @return this UTF-8 reader.
+ * @throws IllegalStateException if this reader is being reused and
+ * it has not been {@link #close closed} or {@link #reset reset}.
+ */
+ public UTF8StreamReader setInput(InputStream inStream) {
+ if (_inputStream != null)
+ throw new IllegalStateException("Reader not closed or reset");
+ _inputStream = inStream;
+ return this;
+ }
+
+ /**
+ * Indicates if this stream is ready to be read.
+ *
+ * @return <code>true</code> if the next read() is guaranteed not to block
+ * for input; <code>false</code> otherwise.
+ * @throws IOException if an I/O error occurs.
+ */
+ public boolean ready() throws IOException {
+ if (_inputStream == null)
+ throw new IOException("Stream closed");
+ return ((_end - _start) > 0) || (_inputStream.available() != 0);
+ }
+
+ /**
+ * Closes and {@link #reset resets} this reader for reuse.
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ public void close() throws IOException {
+ if (_inputStream != null) {
+ _inputStream.close();
+ reset();
+ }
+ }
+
+ /**
+ * Reads a single character. This method will block until a character is
+ * available, an I/O error occurs or the end of the stream is reached.
+ *
+ * @return the 31-bits Unicode of the character read, or -1 if the end of
+ * the stream has been reached.
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read() throws IOException {
+ byte b = _bytes[_start];
+ return ((b >= 0) && (_start++ < _end)) ? b : read2();
+ }
+
+ // Reads one full character, blocks if necessary.
+ private int read2() throws IOException {
+ if (_start < _end) {
+ byte b = _bytes[_start++];
+
+ // Decodes UTF-8.
+ if ((b >= 0) && (_moreBytes == 0)) {
+ // 0xxxxxxx
+ return b;
+ } else if (((b & 0xc0) == 0x80) && (_moreBytes != 0)) {
+ // 10xxxxxx (continuation byte)
+ _code = (_code << 6) | (b & 0x3f); // Adds 6 bits to code.
+ if (--_moreBytes == 0) {
+ return _code;
+ } else {
+ return read2();
+ }
+ } else if (((b & 0xe0) == 0xc0) && (_moreBytes == 0)) {
+ // 110xxxxx
+ _code = b & 0x1f;
+ _moreBytes = 1;
+ return read2();
+ } else if (((b & 0xf0) == 0xe0) && (_moreBytes == 0)) {
+ // 1110xxxx
+ _code = b & 0x0f;
+ _moreBytes = 2;
+ return read2();
+ } else if (((b & 0xf8) == 0xf0) && (_moreBytes == 0)) {
+ // 11110xxx
+ _code = b & 0x07;
+ _moreBytes = 3;
+ return read2();
+ } else if (((b & 0xfc) == 0xf8) && (_moreBytes == 0)) {
+ // 111110xx
+ _code = b & 0x03;
+ _moreBytes = 4;
+ return read2();
+ } else if (((b & 0xfe) == 0xfc) && (_moreBytes == 0)) {
+ // 1111110x
+ _code = b & 0x01;
+ _moreBytes = 5;
+ return read2();
+ } else {
+ throw new CharConversionException("Invalid UTF-8 Encoding");
+ }
+ } else { // No more bytes in buffer.
+ if (_inputStream == null)
+ throw new IOException("No input stream or stream closed");
+ _start = 0;
+ _end = _inputStream.read(_bytes, 0, _bytes.length);
+ if (_end > 0) {
+ return read2(); // Continues.
+ } else { // Done.
+ if (_moreBytes == 0) {
+ return -1;
+ } else { // Incomplete sequence.
+ throw new CharConversionException(
+ "Unexpected end of stream");
+ }
+ }
+ }
+ }
+
+ private int _code;
+
+ private int _moreBytes;
+
+ /**
+ * Reads characters into a portion of an array. This method will block
+ * until some input is available, an I/O error occurs or the end of
+ * the stream is reached.
+ *
+ * <p> Note: Characters between U+10000 and U+10FFFF are represented
+ * by surrogate pairs (two <code>char</code>).</p>
+ *
+ * @param cbuf the destination buffer.
+ * @param off the offset at which to start storing characters.
+ * @param len the maximum number of characters to read
+ * @return the number of characters read, or -1 if the end of the
+ * stream has been reached
+ * @throws IOException if an I/O error occurs.
+ */
+ public int read(char cbuf[], int off, int len) throws IOException {
+ if (_inputStream == null)
+ throw new IOException("No input stream or stream closed");
+ if (_start >= _end) { // Fills buffer.
+ _start = 0;
+ _end = _inputStream.read(_bytes, 0, _bytes.length);
+ if (_end <= 0) { // Done.
+ return _end;
+ }
+ }
+ final int off_plus_len = off + len;
+ for (int i = off; i < off_plus_len;) {
+ // assert(_start < _end)
+ byte b = _bytes[_start];
+ if ((b >= 0) && (++_start < _end)) {
+ cbuf[i++] = (char) b; // Most common case.
+ } else if (b < 0) {
+ if (i < off_plus_len - 1) { // Up to two 'char' can be read.
+ int code = read2();
+ if (code < 0x10000) {
+ cbuf[i++] = (char) code;
+ } else if (code <= 0x10ffff) { // Surrogates.
+ cbuf[i++] = (char) (((code - 0x10000) >> 10) + 0xd800);
+ cbuf[i++] = (char) (((code - 0x10000) & 0x3ff) + 0xdc00);
+ } else {
+ throw new CharConversionException("Cannot convert U+"
+ + Integer.toHexString(code)
+ + " to char (code greater than U+10FFFF)");
+ }
+ if (_start < _end) {
+ continue;
+ }
+ }
+ return i - off;
+ } else { // End of buffer (_start >= _end).
+ cbuf[i++] = (char) b;
+ return i - off;
+ }
+ }
+ return len;
+ }
+
+ /**
+ * Reads characters into the specified appendable. This method will block
+ * until the end of the stream is reached.
+ *
+ * @param dest the destination buffer.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void read(Appendable dest) throws IOException {
+ if (_inputStream == null)
+ throw new IOException("No input stream or stream closed");
+ while (true) {
+ if (_start >= _end) { // Fills buffer.
+ _start = 0;
+ _end = _inputStream.read(_bytes, 0, _bytes.length);
+ if (_end <= 0) { // Done.
+ break;
+ }
+ }
+ byte b = _bytes[_start];
+ if (b >= 0) {
+ dest.append((char) b); // Most common case.
+ _start++;
+ } else {
+ int code = read2();
+ if (code < 0x10000) {
+ dest.append((char) code);
+ } else if (code <= 0x10ffff) { // Surrogates.
+ dest.append((char) (((code - 0x10000) >> 10) + 0xd800));
+ dest.append((char) (((code - 0x10000) & 0x3ff) + 0xdc00));
+ } else {
+ throw new CharConversionException("Cannot convert U+"
+ + Integer.toHexString(code)
+ + " to char (code greater than U+10FFFF)");
+ }
+ }
+ }
+ }
+
+ public void reset() {
+ _code = 0;
+ _end = 0;
+ _inputStream = null;
+ _moreBytes = 0;
+ _start = 0;
+ }
+
+ /**
+ * @deprecated Replaced by {@link #setInput(InputStream)}
+ */
+ public UTF8StreamReader setInputStream(InputStream inStream) {
+ return this.setInput(inStream);
+ }
+}
\ 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/io/UTF8StreamWriter.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamWriter.java b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamWriter.java
new file mode 100644
index 0000000..a5872e3
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/UTF8StreamWriter.java
@@ -0,0 +1,338 @@
+/*
+ * 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.io;
+
+import java.io.CharConversionException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * <p> A UTF-8 stream writer.</p>
+ *
+ * <p> This writer supports surrogate <code>char</code> pairs (representing
+ * characters in the range [U+10000 .. U+10FFFF]). It can also be used
+ * to write characters from their unicodes (31 bits) directly
+ * (ref. {@link #write(int)}).</p>
+ *
+ * <p> Instances of this class can be reused for different output streams
+ * and can be part of a higher level component (e.g. serializer) in order
+ * to avoid dynamic buffer allocation when the destination output changes.
+ * Also wrapping using a <code>java.io.BufferedWriter</code> is unnescessary
+ * as instances of this class embed their own data buffers.</p>
+ *
+ * <p> Note: This writer is unsynchronized and always produces well-formed
+ * UTF-8 sequences.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 2.0, December 9, 2004
+ */
+public final class UTF8StreamWriter extends Writer {
+
+ /**
+ * Holds the current output stream or <code>null</code> if closed.
+ */
+ private OutputStream _outputStream;
+
+ /**
+ * Holds the bytes' buffer.
+ */
+ private final byte[] _bytes;
+
+ /**
+ * Holds the bytes buffer index.
+ */
+ private int _index;
+
+ /**
+ * Creates a UTF-8 writer having a byte buffer of moderate capacity (2048).
+ */
+ public UTF8StreamWriter() {
+ _bytes = new byte[2048];
+ }
+
+ /**
+ * Creates a UTF-8 writer having a byte buffer of specified capacity.
+ *
+ * @param capacity the capacity of the byte buffer.
+ */
+ public UTF8StreamWriter(int capacity) {
+ _bytes = new byte[capacity];
+ }
+
+ /**
+ * Sets the output stream to use for writing until this writer is closed.
+ * For example:[code]
+ * Writer writer = new UTF8StreamWriter().setOutputStream(out);
+ * [/code] is equivalent but writes faster than [code]
+ * Writer writer = new java.io.OutputStreamWriter(out, "UTF-8");
+ * [/code]
+ *
+ * @param out the output stream.
+ * @return this UTF-8 writer.
+ * @throws IllegalStateException if this writer is being reused and
+ * it has not been {@link #close closed} or {@link #reset reset}.
+ */
+ public UTF8StreamWriter setOutput(OutputStream out) {
+ if (_outputStream != null)
+ throw new IllegalStateException("Writer not closed or reset");
+ _outputStream = out;
+ return this;
+ }
+
+ /**
+ * Writes a single character. This method supports 16-bits
+ * character surrogates.
+ *
+ * @param c <code>char</code> the character to be written (possibly
+ * a surrogate).
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(char c) throws IOException {
+ if ((c < 0xd800) || (c > 0xdfff)) {
+ write((int) c);
+ } else if (c < 0xdc00) { // High surrogate.
+ _highSurrogate = c;
+ } else { // Low surrogate.
+ int code = ((_highSurrogate - 0xd800) << 10) + (c - 0xdc00)
+ + 0x10000;
+ write(code);
+ }
+ }
+
+ private char _highSurrogate;
+
+ /**
+ * Writes a character given its 31-bits Unicode.
+ *
+ * @param code the 31 bits Unicode of the character to be written.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(int code) throws IOException {
+ if ((code & 0xffffff80) == 0) {
+ _bytes[_index] = (byte) code;
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else { // Writes more than one byte.
+ write2(code);
+ }
+ }
+
+ private void write2(int c) throws IOException {
+ if ((c & 0xfffff800) == 0) { // 2 bytes.
+ _bytes[_index] = (byte) (0xc0 | (c >> 6));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | (c & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else if ((c & 0xffff0000) == 0) { // 3 bytes.
+ _bytes[_index] = (byte) (0xe0 | (c >> 12));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 6) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | (c & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else if ((c & 0xff200000) == 0) { // 4 bytes.
+ _bytes[_index] = (byte) (0xf0 | (c >> 18));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 12) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 6) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | (c & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else if ((c & 0xf4000000) == 0) { // 5 bytes.
+ _bytes[_index] = (byte) (0xf8 | (c >> 24));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 18) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 12) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 6) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | (c & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else if ((c & 0x80000000) == 0) { // 6 bytes.
+ _bytes[_index] = (byte) (0xfc | (c >> 30));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 24) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 18) & 0x3f));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 12) & 0x3F));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | ((c >> 6) & 0x3F));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ _bytes[_index] = (byte) (0x80 | (c & 0x3F));
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else {
+ throw new CharConversionException("Illegal character U+"
+ + Integer.toHexString(c));
+ }
+ }
+
+ /**
+ * Writes a portion of an array of characters.
+ *
+ * @param cbuf the array of characters.
+ * @param off the offset from which to start writing characters.
+ * @param len the number of characters to write.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void write(char cbuf[], int off, int len) throws IOException {
+ final int off_plus_len = off + len;
+ for (int i = off; i < off_plus_len;) {
+ char c = cbuf[i++];
+ if (c < 0x80) {
+ _bytes[_index] = (byte) c;
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else {
+ write(c);
+ }
+ }
+ }
+
+ /**
+ * Writes a portion of a string.
+ *
+ * @param str a String.
+ * @param off the offset from which to start writing characters.
+ * @param len the number of characters to write.
+ * @throws IOException if an I/O error occurs
+ */
+ public void write(String str, int off, int len) throws IOException {
+ final int off_plus_len = off + len;
+ for (int i = off; i < off_plus_len;) {
+ char c = str.charAt(i++);
+ if (c < 0x80) {
+ _bytes[_index] = (byte) c;
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else {
+ write(c);
+ }
+ }
+ }
+
+ /**
+ * Writes the specified character sequence.
+ *
+ * @param csq the character sequence.
+ * @throws IOException if an I/O error occurs
+ */
+ public void write(CharSequence csq) throws IOException {
+ final int length = csq.length();
+ for (int i = 0; i < length;) {
+ char c = csq.charAt(i++);
+ if (c < 0x80) {
+ _bytes[_index] = (byte) c;
+ if (++_index >= _bytes.length) {
+ flushBuffer();
+ }
+ } else {
+ write(c);
+ }
+ }
+ }
+
+ /**
+ * Flushes the stream. If the stream has saved any characters from the
+ * various write() methods in a buffer, write them immediately to their
+ * intended destination. Then, if that destination is another character or
+ * byte stream, flush it. Thus one flush() invocation will flush all the
+ * buffers in a chain of Writers and OutputStreams.
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ public void flush() throws IOException {
+ flushBuffer();
+ _outputStream.flush();
+ }
+
+ /**
+ * Closes and {@link #reset resets} this writer for reuse.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ public void close() throws IOException {
+ if (_outputStream != null) {
+ flushBuffer();
+ _outputStream.close();
+ reset();
+ }
+ }
+
+ /**
+ * Flushes the internal bytes buffer.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ private void flushBuffer() throws IOException {
+ if (_outputStream == null)
+ throw new IOException("Stream closed");
+ _outputStream.write(_bytes, 0, _index);
+ _index = 0;
+ }
+
+ public void reset() {
+ _highSurrogate = 0;
+ _index = 0;
+ _outputStream = null;
+ }
+
+ /**
+ * @deprecated Replaced by {@link #setOutput(OutputStream)}
+ */
+ public UTF8StreamWriter setOutputStream(OutputStream out) {
+ return this.setOutput(out);
+ }
+}
\ 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/io/Union.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/Union.java b/commons/marmotta-commons/src/ext/java/javolution/io/Union.java
new file mode 100644
index 0000000..e8ae270
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/Union.java
@@ -0,0 +1,54 @@
+/*
+ * 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.io;
+
+/**
+ * <p> Equivalent to <code>C/C++ union</code>; this class works in the same
+ * way as {@link Struct} (sub-class) except that all members are mapped
+ * to the same location in memory.</p>
+ * <p> Here is an example of C union:
+ * [code]
+ * union Number {
+ * int asInt;
+ * float asFloat;
+ * char asString[12];
+ * };[/code]</p>
+ * <p> And its Java equivalent:
+ * [code]
+ * public class Number extends Union {
+ * Signed32 asInt = new Signed32();
+ * Float32 asFloat = new Float32();
+ * Utf8String asString = new Utf8String(12);
+ * }[/code]</p>
+ * <p> As for any {@link Struct}, fields are directly accessible:
+ * [code]
+ * Number num = new Number();
+ * num.asInt.set(23);
+ * num.asString.set("23"); // Null terminated (C compatible)
+ * float f = num.asFloat.get();[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, October 4, 2004
+ */
+public abstract class Union extends Struct {
+
+ /**
+ * Default constructor.
+ */
+ public Union() {}
+
+ /**
+ * Returns <code>true</code>.
+ *
+ * @return <code>true</code>
+ */
+ public final boolean isUnion() {
+ return true;
+ }
+}
\ 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/io/package-info.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/io/package-info.java b/commons/marmotta-commons/src/ext/java/javolution/io/package-info.java
new file mode 100644
index 0000000..6e000ae
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/io/package-info.java
@@ -0,0 +1,7 @@
+/**
+<p> Utility classes for input and output such as
+ {@link javolution.io.Struct Struct} and {@link javolution.io.Union Union}
+ for direct interoperability with C/C++.</p>
+ */
+package javolution.io;
+
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/lang/Configurable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/Configurable.java b/commons/marmotta-commons/src/ext/java/javolution/lang/Configurable.java
new file mode 100644
index 0000000..394c60e
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/Configurable.java
@@ -0,0 +1,283 @@
+/*
+ * 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.lang;
+
+import java.lang.reflect.Field;
+
+import javolution.context.LogContext;
+import javolution.context.SecurityContext;
+import javolution.context.SecurityContext.Permission;
+import javolution.osgi.internal.OSGiServices;
+import javolution.text.DefaultTextFormat;
+import javolution.text.TextContext;
+
+/**
+ * <p> An element which is configurable without presupposing how the
+ * configuration is done.</p>
+ *
+ * <p> Does your class need to know or has to assume that the configuration is
+ * coming from system properties ??</p>
+ *
+ * <p> The response is obviously NO !</p>
+ *
+ * <p> Let's compare the following examples:
+ * [code]
+ * class Document {
+ * private static final Font FONT
+ * = Font.decode(System.getProperty("pkg.Document#FONT") != null ?
+ * System.getProperty("FONT") : "Arial-BOLD-18");
+ * }[/code]</p>
+ *
+ * <p>With the following:
+ * [code]
+ * class Document {
+ * public static final Configurable<Font> FONT = new Configurable<Font>() {
+ * @Override
+ * protected Font getDefault() {
+ * new Font("Arial", Font.BOLD, 18);
+ * }
+ * };
+ * }[/code]</p>
+ *
+ * <p> Not only the second example is cleaner, but the actual configuration
+ * data can come from anywhere, from system properties (default),
+ * OSGi Configuration Admin service, another bundle, etc.
+ * Low level code does not need to know.</p>
+ *
+ * <p> Configurables may perform any logic upon initialization or
+ * update. Users are notified of configuration events through
+ * the OSGi {@link Configurable.Listener} service.
+ * [code]
+ * class Index {
+ * // Holds the number of unique preallocated instances (default {@code 1024}).
+ * public static final Configurable<Integer> UNIQUE = new Configurable<Integer>() {
+ * @Override
+ * protected Integer getDefault() {
+ * return 1024;
+ * }
+ * @Override
+ * protected Integer initialized(Integer value) {
+ * return MathLib.min(value, 65536); // Hard-limiting
+ * }
+ * @Override
+ * protected Integer reconfigured(Integer oldCount, Integer newCount) {
+ * throw new UnsupportedOperationException("Unicity reconfiguration not supported.");
+ * }
+ * }
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+public abstract class Configurable<T> {
+
+ /**
+ * Services to be published by any one interested in being informed of
+ * configurable changes.
+ */
+ public interface Listener {
+
+ /**
+ * Receives notification that a configurable has been initialized..
+ *
+ * @param configurable the configurable instance being initialized.
+ * @param value the initial value.
+ */
+ <T> void configurableInitialized(Configurable<T> configurable, T value);
+
+ /**
+ * Receives notification that a configurable has been updated.
+ *
+ * @param configurable the configurable instance being updated.
+ * @param oldValue the previous value.
+ * @param newValue the updated value.
+ */
+ <T> void configurableReconfigured(Configurable<T> configurable,
+ T oldValue, T newValue);
+
+ }
+
+ /**
+ * Holds the general permission to reconfigure configurable instances
+ * (action <code>"reconfigure"</code>).
+ * Whether or not that permission is granted depends on the current
+ * {@link SecurityContext}. It is possible that the general permission
+ * to reconfigure a configurable is granted but revoked for a specific
+ * instance. Also, the general permission to reconfigure a configurable
+ * may be revoked but granted only for a specific instance.
+ */
+ public static Permission<Configurable<?>> RECONFIGURE_PERMISSION = new Permission<Configurable<?>>(
+ Configurable.class, "reconfigure");
+
+ /**
+ * Holds the configurable name.
+ */
+ private String name;
+
+ /**
+ * Holds the reconfigure permission.
+ */
+ private final Permission<Configurable<T>> reconfigurePermission;
+
+ /**
+ * Holds the configurable value.
+ */
+ private volatile T value;
+
+ /**
+ * Creates a new configurable. If a system property exist for this
+ * configurable's {@link #getName() name}, then
+ * the {@link #parse parsed} value of the property supersedes the
+ * {@link #getDefault() default} value of this configurable.
+ * For example, running the JVM with
+ * the option {@code -Djavolution.context.ConcurrentContext#CONCURRENCY=0}
+ * disables concurrency support.
+ */
+ public Configurable() {
+ reconfigurePermission = new Permission<Configurable<T>>(
+ Configurable.class, "reconfigure", this);
+ String name = getName();
+ T defaultValue = getDefault();
+ if (name != null) {
+ try { // Checks system properties.
+ String property = System.getProperty(name);
+ if (property != null) {
+ defaultValue = parse(property); // Supersedes.
+ LogContext.debug(name, ", System Properties Value: ",
+ defaultValue);
+ }
+ } catch (SecurityException securityError) {
+ // Ok, current runtime does not allow system properties access.
+ }
+ }
+ this.name = name;
+ this.value = initialized(defaultValue);
+ Object[] listeners = OSGiServices.getConfigurableListeners();
+ for (Object listener : listeners) {
+ ((Listener) listener).configurableInitialized(this, this.value);
+ }
+ }
+
+ /**
+ * Returns this configurable value.
+ */
+ public T get() {
+ return value;
+ }
+
+ /**
+ * Returns this configurable name. By convention, the name of the
+ * configurable is the name of the static field holding the
+ * configurable (e.g. "javolution.context.ConcurrentContext#CONCURRENCY").
+ * This method should be overridden if the enclosing class needs to be
+ * impervious to obfuscation or if the enclosing class defines multiple
+ * configurable fields.
+ *
+ * @throws UnsupportedOperationException if the enclosing class has
+ * multiple configurable static fields.
+ */
+ public String getName() {
+ if (name != null)
+ return name; // Already set.
+ Class<?> thisClass = this.getClass();
+ Class<?> enclosingClass = thisClass.getEnclosingClass();
+ String fieldName = null;
+ for (Field field : enclosingClass.getFields()) {
+ if (field.getType().isAssignableFrom(thisClass)) {
+ if (fieldName != null) // Indistinguishable field types.
+ throw new UnsupportedOperationException(
+ "Multiple configurables static fields in the same class" +
+ "requires the Configurable.getName() method to be overriden.");
+ fieldName = field.getName();
+ }
+ }
+ return (fieldName != null) ? enclosingClass.getName() + "#" + fieldName
+ : null;
+ }
+
+ /**
+ * Returns the permission to configure this instance.
+ */
+ public Permission<Configurable<T>> getReconfigurePermission() {
+ return reconfigurePermission;
+ }
+
+ /**
+ * Reconfigures this instance with the specified value if authorized
+ * by the {@link SecurityContext}. This method returns the actual new
+ * value which may be different from the requested new value
+ * (see {@link #reconfigured(Object, Object)}).
+ *
+ * @param newValue the requested new value.
+ * @return the actual new value.
+ * @throws SecurityException if the permission to reconfigure this
+ * configurable is not granted.
+ * @throws UnsupportedOperationException if this configurable does not
+ * support dynamic reconfiguration.
+ */
+ public T reconfigure(T newValue) {
+ SecurityContext.check(reconfigurePermission);
+ synchronized (this) {
+ T oldValue = this.value;
+ this.value = reconfigured(oldValue, newValue);
+ Object[] listeners = OSGiServices.getConfigurableListeners();
+ for (Object listener : listeners) {
+ ((Listener) listener).configurableReconfigured(this, oldValue,
+ this.value);
+ }
+ return this.value;
+ }
+ }
+
+ /**
+ * Returns this configurable default value (always different from
+ * {@code null}).
+ */
+ protected abstract T getDefault();
+
+ /**
+ * This methods is called when the configurable is initialized.
+ * Developers may override this method to perform
+ * any initialization logic (e.g. input validation).
+ *
+ * @param value the requested value for this configurable.
+ * @return the actual value of this configurable.
+ */
+ protected T initialized(T value) {
+ return value;
+ }
+
+ /**
+ * Parses the specified text to return the corresponding value.
+ * This method is used to initialize this configurable from
+ * system properties. The default implementation uses the
+ * {@link TextContext} to retrieve the text format
+ * (based on the {@link DefaultTextFormat} class annotation).
+ */
+ @SuppressWarnings("unchecked")
+ protected T parse(String str) {
+ Class<? extends T> type = (Class<? extends T>) getDefault().getClass();
+ return TextContext.getFormat(type).parse(str);
+ }
+
+ /**
+ * This methods is called when the configurable is reconfigured.
+ * Developers may override this method to perform
+ * any reconfiguration logic (e.g. hard limiting values).
+ *
+ * @param oldValue the old value.
+ * @param newValue the requested new value.
+ * @return the actual new value of this configurable.
+ * @throws UnsupportedOperationException if this configurable does not
+ * support dynamic reconfiguration.
+ */
+ protected T reconfigured(T oldValue, T newValue) {
+ return newValue;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/lang/Immutable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/Immutable.java b/commons/marmotta-commons/src/ext/java/javolution/lang/Immutable.java
new file mode 100644
index 0000000..9b60984
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/Immutable.java
@@ -0,0 +1,45 @@
+/*
+ * 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.lang;
+
+/**
+ * <p> An object capable of returning a {@link #value value} not subject or
+ * susceptible of change or variation. For example, {@code Immutable<List>}
+ * has a {@code List} value which is guaranteed to be constant (not modifiable
+ * by anybody). Classes implementing this interface do not need themselves to
+ * be unmodifiable. If the value and the class are the same, the
+ * {@link ValueType} sub-interface can be implemented.
+ * [code]
+ * class Polygon extends Shape implements ValueType<Shape> { // extends Immutable<Shape>
+ * private List<Point2D> vertices;
+ * public Polygon(Immutable<List<Point2D>> vertices) { // Immutable<List> has a constant List value.
+ * this.vertices = vertices.value(); // No defensive copying required (vertices.value() is certified constant).
+ * }
+ * public Polygon value() { return this; } // As per ValueType contract.
+ * }[/code]</p>
+ * <p> {@link javolution.util.FastCollection FastCollection/FastMap} have
+ * direct support for immutable.
+ * [code]
+ * Polygon triangle = new Polygon(new FastTable<Point2D>().addAll(p1, p2, p3).toImmutable());[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ * @param <T> The type of the immutable constant value.
+ * @see <a href="http://en.wikipedia.org/wiki/Immutable_object">
+ * Wikipedia: Immutable Object<a>
+ * @see javolution.util.FastCollection#toImmutable
+ */
+public interface Immutable<T> {
+
+ /**
+ * Returns the constant value held by this object.
+ */
+ T value();
+
+}
\ 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/lang/Initializer.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/lang/Initializer.java b/commons/marmotta-commons/src/ext/java/javolution/lang/Initializer.java
new file mode 100644
index 0000000..81f2823
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/lang/Initializer.java
@@ -0,0 +1,149 @@
+/*
+ * 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.lang;
+
+import java.util.Vector;
+import javolution.context.LogContext;
+
+/**
+ * <p> An initializer for all classes loaded by any given class loader.</p>
+ *
+ * <p> Initialization of classes at startup (or during bundle activation)
+ * ensures a significantly improved worst case execution time especially
+ * if the classes has {@link Configurable configuration logic} to be
+ * executed then.</p>
+ *
+ * <p> Javolution activator initialize {@link Realtime} classes when started.
+ * When running outside OSGi the method
+ * {@code javolution.osgi.internal.OSGiServices.initializeRealtimeClasses()}
+ * can be used to that effect..</p>
+ *
+ * <p> Class loading can be performed in a lazy manner and therefore some parts
+ * of the class loading process may be done on first use rather than at
+ * load time. Javolution bundle activator ensure that <b>all</b> its classes
+ * are initialized at start up.
+ * The following code illustrates how this can be done for any bundle.
+ * [code]
+ * public class MyActivator implements BundleActivator {
+ * public void start(BundleContext bc) throws Exception {
+ * Initializer initializer = new Initializer(MyActivator.class.getClassLoader());
+ * initializer.loadClass(com.foo.internal.UnreferencedClass.class);
+ * // Load explicitly classes not directly or indirectly referenced.
+ * ...
+ * initializer.initializeLoadedClasses(); // Recursive loading/initialization.
+ * ... // Continue activation
+ * }
+ * }[/code]</p>
+ *
+ * <p> This utility use reflection to find the classes loaded and may not be
+ * supported on all platforms.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.1, July 26, 2007
+ */
+public class Initializer {
+
+ /**
+ * Indicates if the class being initialized should be logged
+ * (default {@code false}).
+ */
+ public static final Configurable<Boolean> SHOW_INITIALIZED = new Configurable<Boolean>() {
+ @Override
+ protected Boolean getDefault() {
+ return false;
+ }
+ };
+
+ /** The class loader for this initializer */
+ private final ClassLoader classLoader;
+
+ /**
+ * Creates an initializer for the specified class loader.
+ */
+ public Initializer(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Returns the classes loaded by the class loader of this initializer or
+ * <code>null</code> if not supported by the platform.
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?>[] loadedClasses() {
+ Class<?> cls = classLoader.getClass();
+ while (cls != java.lang.ClassLoader.class) {
+ cls = cls.getSuperclass();
+ }
+ try {
+ java.lang.reflect.Field fldClasses = cls
+ .getDeclaredField("classes");
+ fldClasses.setAccessible(true);
+ Vector<Class<?>> list = (Vector<Class<?>>) fldClasses
+ .get(classLoader);
+ Class<?>[] classes = new Class<?>[list.size()];
+ for (int i = 0; i < classes.length; i++) {
+ classes[i] = list.get(i);
+ }
+ return classes;
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ /**
+ * Loads the specified class (does not perform any initialization).
+ * This method is typically used to load unreferenced classes.
+ */
+ public void loadClass(Class<?> cls) {
+ try {
+ classLoader.loadClass(cls.getName());
+ } catch (ClassNotFoundException e) {
+ LogContext.debug("Class " + cls + " not found.");
+ }
+ }
+
+ /**
+ * Initializes all the loaded classes. If the initialization leads to more
+ * classes being loaded, these classes are initialized as well
+ * (recursive process).
+ *
+ * @return {@code true} if initialization has been performed successfully;
+ * {@code false} otherwise.
+ */
+ public boolean initializeLoadedClasses() {
+ boolean isInitializationSuccessful = true;
+ int nbrClassesInitialized = 0;
+ while (true) {
+ Class<?>[] classes = loadedClasses();
+ if (classes == null) {
+ LogContext
+ .debug("Automatic class initialization not supported.");
+ return false;
+ }
+ if (nbrClassesInitialized >= classes.length)
+ break; // Done.
+ for (int i = nbrClassesInitialized; i < classes.length; i++) {
+ Class<?> cls = classes[i];
+ try {
+ if (SHOW_INITIALIZED.get())
+ LogContext.debug("Initialize ", cls.getName());
+ Class.forName(cls.getName(), true, classLoader);
+ } catch (ClassNotFoundException ex) {
+ isInitializationSuccessful = false;
+ LogContext.error(ex); // Should never happen.
+ }
+ }
+ nbrClassesInitialized = classes.length;
+ }
+ LogContext.debug("Initialization of ", nbrClassesInitialized,
+ " classes loaded by ", classLoader);
+ return isInitializationSuccessful;
+ }
+
+}
\ No newline at end of file