.. highlight:: java

.. _java-dev-guide:

#####################
Java Developers Guide
#####################

*******
Preface
*******

Overview
========

This guide provides information about how to use the rasdaman database
management system. The booklet explains usage of rasj, the rasdaman Java
API.

Follow the instructions in this guide as you develop your application
which makes use of rasdaman services. Explanations detail how, from
within a Java program, to create databases, collections, and instances;
how to retrieve from databases; how to manipulate and delete instances
within databases; how to influence physical storage parameters; how to
do transaction handling and other administrative tasks.

Audience
========

The information in this manual is intended for application developers.

Rasdaman Documentation Set
==========================

This manual should be read in conjunction with the complete rasdaman
documentation set which this guide is part of. The documentation set in
its completeness covers all important infor­mat­ion needed to work with
the rasdaman system, such as programming and query access to databases,
guidance to utilities such as *raswct*, release notes, and additional
information on the rasdaman wiki.

The rasdaman Documentation Set consists of the following docu­ments:

-  Installation and Administration Guide
-  Query Language Guide
-  C++ Developer's Guide
-  Java Developer's Guide
-  raswct Developer's Guide
-  the rasdaman wiki, accessible at `www.rasdaman.org <http://www.rasdaman.org>`_


************
Introduction
************

See the corresponding :ref:`introduction` Section in the *rasdaman Query Language
Guide*.

***********
Terminology
***********

See the corresponding :ref:`terminology` Section in the *rasdaman Query Language
Guide*.


********************
Application Examples
********************

Overview
========

This section contains an example of using the rasdaman Java API. The
intention is, for the advanced programmer, to quickly get an overview on
the programming style to be observed.

The source code can be found (slightly extended) in subdirectory
``$RMANHOME/share/rasdaman/examples/java`` of the rasdaman distribution directory.

For details on the operational semantics of the rasdaman data model the
reader is strongly encouraged to study the *rasdaman Query Language
Guide*.

Application Program Example Code
================================

::

    import rasj.*;
    import rasj.odmg.*;
    import org.odmg.*;
    import java.util.*;

    /** Example Java program for computing the avg cell value
     * for each n-D 8-bit grey image in a given collection.
     * set the server name with -server, the database name with -database,
     * the collection name with -collection,
     * the port number with -port, the user login with -user,
     * the password with -passwd
     */
    public class AvgCell {
        public static void main(String[] args) {
            String server = "localhost";
            String base = "RASBASE";
            String coll = "mr";
            String port = "7001";
            String user = "rasguest";
            String passwd = "rasguest";

            double sum;

            for (int i = args.length - 1; i >= 0; i--) {
                //System.out.println(args[i]);
                if (args[i].equals("-server")) {
                    server = args[i + 1];
                }
                if (args[i].equals("-database")) {
                    base = args[i + 1];
                }
                if (args[i].equals("-collection")) {
                    coll = args[i + 1];
                }
                if (args[i].equals("-port")) {
                    port = args[i + 1];
                }
                if (args[i].equals("-user")) {
                    user = args[i + 1];
                }
                if (args[i].equals("-passwd")) {
                    passwd = args[i + 1];
                }
            }
            //System.out.println(server+base+coll+port+user+passwd);

            DBag resultBag = null;
            RasGMArray result = null;
            Transaction myTa = null;
            Database myDb = null;
            OQLQuery myQu = null;

            try {
                Implementation myApp = new RasImplementation(
                                            "http://" + server + ":" + port);
                ((RasImplementation)myApp).setUserIdentification(user, passwd);
                myDb = myApp.newDatabase();

                System.out.println("Opening database ...");
                myDb.open(base, Database.OPEN_READ_ONLY);

                System.out.println("Starting transaction ...");
                myTa = myApp.newTransaction();
                myTa.begin();

                System.out.println("Retrieving MDDs ...");
                myQu = myApp.newOQLQuery();
                myQu.create("select img from " + coll + " as img");
                resultBag = (DBag)myQu.execute();
                if (resultBag != null) {
                    Iterator iter = resultBag.iterator();
                    while (iter.hasNext()) {
                        result = (RasGMArray)iter.next();
                        System.out.println(result);
                        if (result.getTypeLength() != 1) {
                            System.out.println("skipping image because"
                                    + " of non-int cell type");
                        } else {
                            byte[] pixelfield = result.getArray();
                            sum = 0.0;
                            long size = result.getArraySize();
                            for (int i = 0; i < size; i++) {
                                sum += pixelfield[i];
                            }
                            System.out.println("Avarage over " + size + " pixels is "
                                    + ((sum / size) + 128));
                        }

                    }
                    System.out.println("All results");
                }

                System.out.println("Committing transaction ...");
                myTa.commit();

                System.out.println("Closing database ...");
                myDb.close();

            } catch (org.odmg.ODMGException e) {
                System.out.println("An exception has occurred: " + e.getMessage());
                System.out.println("Try to abort the transaction ...");
                if (myTa != null) {
                    myTa.abort();
                }

                try {
                    System.out.println("Try to close the database ...");
                    if (myDb != null) {
                        myDb.close();
                    }
                } catch (org.odmg.ODMGException exp) {
                    System.err.println("Could not close the database: "
                            + exp.getMessage());
                }
            }
            System.out.println("Done.");
        }
    }

.. note::
    This sample program makes use of the ``mr`` collection provided with the
    rasdaman distribution package. See the rasdaman *Installation and
    Administration Guide* to learn on how to create this collection as part
    of the demonstration database.

****
rasj
****

Overview
========

The rasj package contains the API for Java-based access to the rasdaman
database system. It relies on the ODMG standard
which it implements to the extent that is necessary for raster data management.

The overall rasj package is subdivided into two packages, ``rasj`` and
``org.odmg``. The ``org.odmg`` sub-package (see :ref:`sec-odmg`) implements the
general ODMG specifications while the ``rasj`` sub-package implements
rasdaman specific features.

.. _sec-rasj-hierarchy:

Class Hierarchy
===============

.. note::
    All class hierarchies are generated from the rasj javadoc,
    which can be built in the ``java/`` directory with
    ::

        mvn javadoc:javadoc

    This generates a ``javadoc`` folder in the build directory
    (``build/java/target/site/apidocs/rasj``). Then, a commandline tool named ``w3m``
    is used to dump the tree structure in HTML format of a package to text in console, example:
    ::

        w3m -dump build/java/target/site/apidocs/rasj/package-tree.html


The ``rasj`` class hierarchy has the following structure.

.. code-block:: text

  * java.lang.Object
      * rasj.RasFastScale (implements rasj.global.RasGlobalDefs)
      * rasj.RasImplementation (implements org.odmg.Implementation)
      * rasj.RasMInterval
      * rasj.odmg.RasObject (implements rasj.global.RasGlobalDefs)
          * rasj.RasGMArray (implements rasj.global.RasGlobalDefs)
              * rasj.RasMArrayByte
              * rasj.RasMArrayDouble
              * rasj.RasMArrayFloat
              * rasj.RasMArrayInteger
              * rasj.RasMArrayLong
              * rasj.RasMArrayShort
      * rasj.RasPoint
      * rasj.RasSInterval
      * rasj.RasStorageLayout
      * rasj.RasStructure
      * rasj.RasType
          * rasj.RasBaseType
              * rasj.RasPrimitiveType (implements rasj.global.RasGlobalDefs)
              * rasj.RasStructureType
          * rasj.RasCollectionType
          * rasj.RasMArrayType
          * rasj.RasMIntervalType
          * rasj.RasOIDType
          * rasj.RasPointType
          * rasj.RasSIntervalType
      * java.lang.Throwable (implements java.io.Serializable)
          * java.lang.Exception
              * org.odmg.ODMGException
                  * org.odmg.QueryException
                      * org.odmg.QueryInvalidException
                          * rasj.RasQueryExecutionFailedException
              * rasj.RasException
                  * rasj.RasDimensionMismatchException
                  * rasj.RasIndexOutOfBoundsException
                  * rasj.RasResultIsNoCellException
                  * rasj.RasResultIsNoIntervalException
                  * rasj.RasStreamInputOverflowException
                  * rasj.RasTypeInvalidException
              * java.lang.RuntimeException
                  * org.odmg.ODMGRuntimeException
                      * rasj.RasConnectionFailedException
                  * rasj.RasRuntimeException
                      * rasj.RasClientInternalException
                      * rasj.RasIllegalULongValueException
                      * rasj.RasIllegalUShortValueException
                      * rasj.RasInvalidNameException
                      * rasj.RasTypeNotSupportedException
                      * rasj.RasTypeUnknownException


Interface Hierarchy
===================

The complete rasj interface hierarchy has the following structure.

.. code-block:: text

  * org.odmg.Implementation
      * rasj.RasImplementationInterface

.. _sec-odmg:

****
ODMG
****

Overview
========

The ODMG classes implement classes defined in the ODMG standard
providing functionality such as database open and close, transactions,
querying, and unique identifiers, i.e., OIDs.

Don't Use ``DArray``!

ODMG defines an interface ``DArray`` which also is part of the ODMG
sub-package provided with the rasdaman distribution. These implement
only 1-D arrays; most important, however, ``DArray`` is ***not compatible***
with rasdaman arrays. Therefore, ***do not use*** class ``DArray`` as a
rasdaman array, but use class ``RasGMArray`` (and its subclasses) instead.

\...But Do Use ``Dbag``!

Queries return multi-sets as results. A *bag* or *multi-set* contains an
arbitrary number of elements; like a set (and unlike a list), no
particular sequence is defined, and like a list (and unlike a set), the
same elements can occur multiply. The query result type, therefore, is
``DBag``. See also :ref:`sec-storage-layout`.

.. _sec-odmg-hierarchy:

Class Hierarchy
===============

The complete ``org.odmg`` class hierarchy has the following structure.

.. code-block:: text

  * java.lang.Object
      * java.lang.Throwable (implements java.io.Serializable)
          * java.lang.Exception
              * org.odmg.ODMGException
                  * org.odmg.DatabaseNotFoundException
                  * org.odmg.DatabaseOpenException
                  * org.odmg.ObjectNameNotFoundException
                  * org.odmg.ObjectNameNotUniqueException
                  * org.odmg.QueryException
                      * org.odmg.QueryInvalidException
                      * org.odmg.QueryParameterCountInvalidException
                      * org.odmg.QueryParameterTypeInvalidException
              * java.lang.RuntimeException
                  * org.odmg.ODMGRuntimeException
                      * org.odmg.ClassNotPersistenceCapableException
                      * org.odmg.DatabaseClosedException
                      * org.odmg.DatabaseIsReadOnlyException
                      * org.odmg.LockNotGrantedException
                      * org.odmg.NotImplementedException
                      * org.odmg.ObjectDeletedException
                      * org.odmg.ObjectNotPersistentException
                      * org.odmg.TransactionAbortedException
                      * org.odmg.TransactionInProgressException
                      * org.odmg.TransactionNotInProgressException


Interface Hierarchy
===================

This is the ``org.odmg`` interface hierarchy:

.. code-block:: text

  * org.odmg.Database
  * org.odmg.Implementation
  * java.lang.Iterable<T>
      * java.util.Collection<E>
          * org.odmg.DCollection
              * org.odmg.DArray (also extends java.util.List<E>)
              * org.odmg.DBag
              * org.odmg.DList (also extends java.util.List<E>)
              * org.odmg.DSet (also extends java.util.Set<E>)
          * java.util.List<E>
              * org.odmg.DArray (also extends org.odmg.DCollection)
              * org.odmg.DList (also extends org.odmg.DCollection)
          * java.util.Set<E>
              * org.odmg.DSet (also extends org.odmg.DCollection)
  * java.util.Map<K,V>
      * org.odmg.DMap
  * org.odmg.OQLQuery
  * org.odmg.Transaction


How To Use
==========

The following code piece demonstrates a typical retrieval situation: a
database is opened with username and password, a transaction is started, and then a query is
executed against that database. ::

    Transaction myTa = null;
    Database myDb = null;
    OQLQuery myQu = null;
    DBag resultSet = null;
    RasGMArray result = null;

    Implementation myApp = new RasImplementation("http://" + server + port );
    ((RasImplementation)myApp).setUserIdentification(user, passwd);
    myDb = myApp.newDatabase();
    myDb.open( database, Database.OPEN_READ_ONLY );

    myTa = myApp.newTransaction();
    myTa.begin();

    myQu = myApp.newOQLQuery();
    myQu.create( "select mr from mr" );
    resultSet = (DBag) myQu.execute();

    // ...result set processing...

    myTa.commit();
    myDb.close();

**Database Login**

The database name and the address of a running server manager must be
indicated. Further optional parameters and their defaults are:

-  login (default: ``"rasguest"``)

-  password (default: ``"rasguest"``)

**Multiple ODMG Implementations**

It is well possible to use several implementations - for example, from
different vendors - of the ODMG classes simultaneously. Like rasj, other
ODMG packages will provide an ``Implementation`` class in their ``org.odmg``
package. Instantiating one ``Implementation`` for each pack­age is the only
prerequisite to be done. The resulting code might look like the
following (incomplete) example fragment where two different
implementation classes are assumed, ``RasImplementation`` and
``Implementation2``; note that transactions for different implement­ations
are independent from each other. ::

    Transaction myTa1 = null;
    Database myDb1 = null;

    Transaction myTa2 = null;
    Database myDb2 = null;

    Implementation rasApp1 = new RasImplementation( "http://" + server1 + ":" + port1 );
    ((RasImplementation)rasApp1).setUserIdentification(user, passwd);
    myDb1 = myApp1.newDatabase();
    myDb1.open( rasbase, Database.OPEN_READ_ONLY );
    MyTa1 = myApp1.newTransaction();
    myTa1.begin();

    Implementation2 myApp2 = new Implementation2( "http://" + server2 + ":" + port2 );
    ((RasImplementation)myApp2).setUserIdentification(user, passwd);
    myDb2 = myApp2.newDatabase();
    myDb2.open( database2, Database.OPEN_READ_ONLY );
    MyTa2 = myApp2.newTransaction();
    myTa2.begin();

    // ...now access both databases...

    myTa1.commit();
    myDb1.close();

    myTa2.commit();
    myDb2.close();

**ODMG Functions Available**

rasj does not implement ODMG fully (this would go beyond its purpose),
rather it contains those functions necessary for rasdaman database
access. When using the HTML hypertext documentation, clicking through
the org.odmg package ultimately gets you to the rasdaman classes which
implement the corresponding ODMG class. There, methods not available are
marked as such.

**Further Information**

Details on how to process the query result can be found in :ref:`sec-storage-layout`.
The example code makes use of the demonstration database whose set-up
routines are part of the distribution package; find more on this topic
in the rasdaman *Installation and Administration Guide*.

********************
Points and Intervals
********************

Overview
========

Point and interval handling is needed for indexing arrays, such as
in­dication of array boundaries. To this end, classes ``RasPoint``,
``RasS­Interval``, and ``RasMInterval`` for n-dimensional points, 1-D
("single-") intervals, and n-dimensional ("multi-") intervals resp. are
provided.

**Value Ranges and Consistency Constraints**

All points, 1-D and n-D intervals can span negative values as well.
Furthermore, intervals can have any integer value as lower bound. This
is in contrast to most programming languages where usually the lower
bound is fixed to 0.

However, intervals obviously need to match some consistency criteria to
be valid. Foremostly, in a 1-D interval (class ``RasSInterval``) as well as
in an n-D interval (class ``RasMInterval``) the lower bound must not be
higher than the upper bound.

Further, operations between intervals of any type must yield a valid
interval again. Consider the union of two 1-D intervals ``s1`` and ``s2``, ::

    s1.unionWith( s2 )

Intervals ``s1`` and ``s2`` must be overlap or at least be adjacent, otherwise
the resulting interval would contain a hole (mathematically speaking, it
would not be simply connected). As such situations are not allowed for
intervals in rasdaman, corresponding exceptions will be thrown by rasj.

If nevertheless two intervals should be merged which are apart from each
other, then operation ``closureWith()`` can be used. It will "fill" the gap
between the intervals so that a valid result interval comes out.

The HTML manual lists each possible situation. It is recommended to
study this for getting an understanding of all valid and invalid
interval combinations.

Class Hierarchy
===============

.. code-block:: text

  * java.lang.Object
      * rasj.RasPoint
      * rasj.RasSInterval
      * rasj.RasMInterval

.. note::
    Class ``java.lang.Object`` obviously has further subclasses, not just the
    one shown here.

How To Use
==========

Here are some sample code fragments showing usage of the point and
interval classes:

**RasPoint**

::

    // (1) point instantiation using string constructor:
    RasPoint p1 = new RasPoint( "[ 3, 7 ]" );
    // (2) point instantiation using numerical constructor:
    RasPoint p2 = new RasPoint( 5, 0 );

    // get point dimension:
    int d = p2.dimension();

    // test if points are equal:
    boolean b = p1.equals( p2 );

**RasSInterval**

::

    // create a 1-D intervals (100,200) and (-150,400), resp.:
    RasSInterval s1 = new RasSInterval( 100, 200 );
    RasSInterval s2 = new RasSInterval( "-150:400" );
    // no "[" and "]" !

    // get upper bound of interval:
    long hiBound = s2.high();
    // get lower bound of interval:
    long loBound = s2.low();

    // test if interval intersects with another interval
    // (the return value shows the kind of intersection)
    int j = s1.intersectsWith( s2 );

**RasMInterval**

::

    // create new 2-D interval, set bounds to (-1,1) and (3,7):
    RasMInterval m1 = new RasMInterval( "[ -1:1, 3:7 ]" );
    // create a 4-D interval, leaving open array bounds for now:
    RasMInterval m2 = new RasMInterval( 4 );

    // get number of cells:
    long noOfCells = m1.cellCount();


***********************
Multidimensional Arrays
***********************

Overview
========

Instances of ``RasGMArray`` and its subclasses represent multidimensional
arrays. To handle arrays with different base types and geometries, the
"implements" relation of Java is used. With this approach, greyscale
images, RGB images etc. can all be treated as subclasses of the general
array class ``RasGMArray``.

Currently supported are types for integer arrays (e.g., grayscale
images) of various cell size, as well as types for floating-point arrays
with single and double precision. All of them allow arrays of any
dimension and extent per dimension.

Class Hierarchy

.. code-block:: text

  * rasj.odmg.RasObject (implements rasj.global.RasGlobalDefs)
      * rasj.RasGMArray (implements rasj.global.RasGlobalDefs)
          * rasj.RasMArrayByte
          * rasj.RasMArrayDouble
          * rasj.RasMArrayFloat
          * rasj.RasMArrayInteger
          * rasj.RasMArrayLong
          * rasj.RasMArrayShort

How To Use
==========

A few code fragments will show appropriate usage of the array classes.
To keep it brief and to the spot, we omit declarations and other
standard steps; these can be looked up in the previous, complete coding
examples.

**Note: Current restriction**

Queries can contain formal parameters, denoted by ``$1``, ``$2``, etc. (see
*Query Language Guide* for details). In the current rasj
implem­ent­at­ion, only one MDD object can be bound per query (however,
it is possible to bind several scalar values). This limitation will be
overcome in future releases.

**Example 1: compute summary data from array**

The following code example retrieves all MDD objects from a sample
collection and, fore each object, computes the average cell value. As a
safeguard, averaging is carried out only in case of integer cells (i.e.,
greyscale pixels).

::

    myQu = myApp.newOQLQuery();
    myQu.create( "select mr from mr" );
    DBag resultSet = (DBag) myQu.execute();
    if (resultSet != null)
    {
        Iterator iter = resultSet.iterator();
        while (iter.hasNext())
        {
            result = (RasGMArray) iter.next();
            if(result.getTypeLength() != 1)
                System.out.println("skipping image because of non-int cell type" );
            else
            {
                byte[] pixelfield = result.getArray();
                double sum = 0.0;
                long size = result.getArraySize();
                for(int i=0; i<size; i++)
                sum += pixelfield[i];
                System.out.println( "Average over " + size +
                " pixels is " +
                ((sum/size)+128) );
            }
        }
    }

**Example 2: set up array object in main memory**

The following code fragment instantiates a ``RasGMArray`` object as a 2-D
greyscale image and fills it with values using the normal Java means:

::

    // create 2-D MDD with cell length 1, i.e., type "byte":
    RasGMArray myMDD = new RasGMArray(new RasMInterval( "[1:400,1:400]"), 1 );
    // byte container for array data, matching in size:
    byte[] mydata = new byte[160000];

    // initialize array as all-black with two grey stripes:
    for(int y=0; y<400; y++)
    {
        for(int x=0; x<400; x++)
        {
            if((x>99 && x<151) || (x>299 && x<351))
                mydata[y*399+x]=100;
            else
                mydata[y*399+x]=0;
        }
    }

    // now insert byte array into MDD object
    // (sets only the pointer, no copying takes place!):
    myMDD.setArray(mydata);

As for the last line containing the import of array data into the MDD
object, observe the following: There are specific get/set
functions for the various supported array types, e.g., ``getIntArray()``.
While the ``setArray()`` and ``getArray()`` methods always will work, they will
require data type conversion if the actual array cell type is not
"byte". Therefore, it is most efficient to always use that operation
which respects the actual array data type.

The following code fragment instantiates a ``RasGMArray`` object as a 2-D
greyscale image and fills it with values using the normal Java means:

**Example 3: insert new array object into database**

This example generates a new greyscale image collection named test in
the database and inserts an image into this database collection.

Note that a new query object has to be generated for each query. It is
not sufficient to just change the query string in the query object!

::

    // set up query object for collection creation:
    myQu.create( "create collection test GreySet" );
    // set the object type name (used for server type checking):
    myMDD.setObjectTypeName( "GreyImage" );
    // finally, execute "create collection" statement:
    myQu.execute();

    // now create the insert statement:
    myQu.create( "insert into test values $1" );
    // let the server generate a new OID for the object to be
    // inserted, and remember this OID locally:
    myNewOID = myApp.getObjectId( myMDD );
    // bind the MDD value which substitutes formal parameter $1:
    myQu.bind( myMDD );
    // ...and ship the complete statement to the server:
    myQu.execute();


rasdaman Cell Types
===================

The set of cell base types known to rasdaman encompasses the usual
numeric types. Below find the table of types known, and the necessary
information to map them to Java types.

Null values, i.e., values of cells which have not been assigned a value
yet, always are the numerical zero value of the corresponding type. This
extends in the obvious way to composite cells.

+----------------------+--------------+------------------------------------+
| Rasdaman             | Length       | Description                        |
+----------------------+--------------+------------------------------------+
| ``octet``            | 8 bit        | signed integer                     |
+----------------------+--------------+------------------------------------+
| ``char``             | 8 bit        | unsigned integer                   |
+----------------------+--------------+------------------------------------+
| ``short``            | 16 bit       | signed integer                     |
+----------------------+--------------+------------------------------------+
| ``unsigned short``   | 16 bit       | unsigned integer                   |
+----------------------+--------------+------------------------------------+
| ``long``             | 32 bit       | signed integer                     |
+----------------------+--------------+------------------------------------+
| ``unsigned long``    | 32 bit       | unsigned integer                   |
+----------------------+--------------+------------------------------------+
| ``float``            | 32 bit       | single precision floating point    |
+----------------------+--------------+------------------------------------+
| ``double``           | 64 bit       | double precision floating point    |
+----------------------+--------------+------------------------------------+
| ``boolean``          | 1 bit [1]_   | true (nonzero value)               |
|                      |              | false (zero value)                 |
+----------------------+--------------+------------------------------------+

rasdaman Types vs. Java Types
=============================

Java types do not 1:1 correspond to rasdaman types. This is due to the
fact that the Java type system in some aspects is different from what
the ODMG Standard prescribes. Below find the most important caveats.

**Long Integer**

Long integer values in rasdaman always have 4 bytes, in accordance with
the ODMG standard. The corresponding rasdaman types are ``Ras_Long`` and
``Ras_ULong``.

In rasj, the array type to be used for 4-byte integers is
``RasMArrayInteger`` which matches with the Java ``int`` type occupying 4 bytes.

Mind that the Java type ``long`` represents 8 byte quantities. If an MDD
object is passed to the database through rasj, a overflow test takes
place on each integer value. An exception is thrown on overflow.

**Unsigned Integers**

Special care should be taken with unsigned integers, as Java does not
support this. For example, for cells of type ``Ras_UShort`` (2 bytes) the
array type ``RasMArrayInteger`` (4 bytes) must be used to collate values,
according to the ODMG standard.

.. _sec-storage-layout:

**************
Storage Layout
**************

Overview
========

At insertion time of an MDD object, several database-internal storage
parameters can be set to affect the way the object is stored in the
database. A ``RasStorageLayout`` object, attached to a ``RasGMArray`` MDD
object, will guide storage of this MDD object when passed to the server
through ``RasOQLQuery.execute()``.

Class Hierarchy
===============

.. code-block:: text

  * java.lang.Object
      * rasj.RasStorageLayout

How To Use
==========

The following code fragment shows how to associate a storage layout
object with an MDD object; the storage layout will be evaluated at
insertion time of the MDD into the database. ::

    // create 2-D MDD with cell length 1, i.e., type byte:
    RasGMArray myMDD =
    new RasGMArray(new RasMInterval( "[1:400,1:400]" ), 1 );

    // assume that there is some byte array prepared, insert it:
    myMDD.setArray( mydata );

    // set image type name
    myMDD.setObjectTypeName("GreyImage");

    // add storage layout object:
    RasStorageLayout myLayout = new RasStorageLayout();

    // now you can set either TileSize or TileDomain; to this
    // end, continue with Alternative 1 or 2, as described below

**Alternative 1: set tile size**

Having prepared the object as described above, now the tiling strategy
can be set. Experience tells that a good size for tiles is 4 MB,
but bear in mind that the optimal size for tiles depends on
the actual user behaviour as well as various system parameters. ::

    // define size of tiles as 128,000 bytes:
    myLayout.setTileSize( 128000 );
    myMDD.setStorageLayout( myLayout );

**Alternative 2: set domain shape**

As an alternative to setting the overall tile size, the domain can be
prescribed. This is more exact, as it allows to define not only size,
but also the extent per dimension. For example, if it is known from the
user access patterns there are ten times as much vertical slices
requested than are horizontal ones, then it may be a good strategy to
define tiles with a vertical:horizontal ratio of 10 to 1. ::

    // define tiles with spatial extent [1:1000,1:100]:
    myLayout.setTileDomain("[1:1000,1:100]");
    myMDD.setStorageLayout( myLayout );

.. note::
    rasdaman also allows to set the storage and compression format, as well
    as client/server transfer format. However, currently the interface
    controlling these parameters is only available via the C++ interface,
    not yet via Java. In future versions format and compression control will
    be available via Java, too.

***********************
Collections and Queries
***********************

Overview
========

**Bag versus Set**

Queries return multi-sets as results. The corresponding query result
type is ``DBag``.

A *bag* or *multi-set* is a collection of elements similar to sets an
lists; like a set (and unlike a list), no particular sequence is
defined, and like a list (and unlike a set), the same elements can occur
multiply. While ``{1,2,3}`` is an example for a set, ``[1,2,2,3]`` is a bag
example; ``[1,2,3]`` denotes the same bag as ``[3,2,1]``, because sequence is
irrelevant in a bag.

Let us clarify the difference with an example. A query which returns the
object identifiers (OIDs) of some database objects, such as

.. code-block:: rasql

    select oid(a)
    from a

never will contain duplicates, as OIDs are unique by definition On the
other hand, requesting summary information on MDD objects may well lead
to duplicates; for example, in a query like this:

.. code-block:: rasql

    select avg_cells(a)
    from a

several objects may share the same maximum or average cell value. In the
latter case, it obviously is crucial to obtain duplicates also.
Therefore, the query result always is ``DBag``, which forms a particular
subclass of the general class ``DCollection``.

Nevertheless, we will use the term result set sometimes, as it is just
common database speak.

**Important Hint**

Use ``org.odmg.DBag``, do *not* use ``rasj.odmg.RasBag``!

Class Hierarchy
===============

.. code-block:: text

  * java.lang.Iterable<T>
      * java.util.Collection<E>
          * org.odmg.DCollection
              * org.odmg.DArray (also extends java.util.List<E>)
              * org.odmg.DBag
              * org.odmg.DList (also extends java.util.List<E>)
              * org.odmg.DSet (also extends java.util.Set<E>)
          * java.util.List<E>
              * org.odmg.DArray (also extends org.odmg.DCollection)
              * org.odmg.DList (also extends org.odmg.DCollection)
          * java.util.Set<E>
              * org.odmg.DSet (also extends org.odmg.DCollection)


How To Use
==========

The following code piece demonstrates how to use object sets in the
typical case of querying the database and piecewise processing the
result set: ::

    OQLQuery myQu = myApp.newOQLQuery();
    myQu.create( "select mr from mr" );
    DBag resultSet = (DBag) myQu.execute();
    if (resultSet != null)
    {
        Iterator iter = resultSet.iterator();
        while ( iter.hasNext() )
        {
            RasGMArray result = (RasGMArray) iter.next();
            // ...here now process result...
        }
    }

Synchronous query execution

When a query is sent to the rasdaman server it will be executed in
completeness - a running query cannot be aborted [2]_. Care should be
taken therefore not to start queries requir­ing resources beyond the
capability of the server hardware and soft­ware environment, as the
rasdaman service may be blocked for an indefinite time period.

Query Result Type
=================

Database collections satisfy some criterion of homogeneity; this common
property is expressed through the underlying type definition. Likewise,
a collection returned as a query result has such an underlying common
type definition. However, as queries dynamically describe and
instantiate structures, this may not always adhere to some type existing
in the database - sometimes the structure is new, so a type structure
has to be generated "on the fly". While such a type does not have a
name, its structure is well defined through the query itself.

This dynamic typing is predefined in the ODMG standard to which rasj
adheres, so further information can be obtained there.

To access cells from arrays in query result bags, accessor functions are
provided, such as ``getObject()``, ``getInteger()``. These functions are
super­vised by the type checking mechanism, hence using a function on an
in appropriate type will cause an exception of type ``ClassCast­Exception``.

Generally speaking, it is up to the application to know the result type
structure of the query it has sent to the server.

****
OIDs
****

Overview
========

The class ``RasOID`` manages object identifiers (OIDs) for persistent MDD
and collections.

Class Hierarchy
===============

.. code-block:: text

  * java.lang.Object
      * rasj.odmg.RasOID


.. note::
    Class ``java.lang.Object`` obviously has further subclasses, not just the
    one shown here.

How To Use
==========

The following code fragment prints the OID for each object in a query
result set. ::

    myQu = myApp.newOQLQuery();
    myQu.create( "select mr from mr" );
    DBag resultSet = (DBag) myQu.execute();
    if (resultSet != null)
    {
        Iterator iter = resultSet.iterator();
        while ( iter.hasNext() )
        {
            RasGMArray result = (RasGMArray) iter.next();
            System.out.println( "<"
            + result.getOID().getSystemName() + "|"
            + result.getOID().getBaseName() + "|"
            + result.getOID().getLocalOID() + " >" );
            // last statement is equivalent to:
            // System.out.println( getObjectId( result ) );
        }
    }

***************
Type Management
***************

Overview
========

rasdaman allows to define new types during runtime of the system. This
is in contrast to programming languages where type structures are fixed
at compilation time. rasdaman, therefore, offers separate mechanisms to
maintain database types; these are provided through the ``RasType`` class
and its subclasses. For each structure relevant in dealing with
persistent (i.e., database stored) entities, a corresponding type class
is provided.

.. note::
    Right now, rasj does not allow to create and manipulate persistent types
    in the database; methods provided mainly serve to inquire the result
    type of a query for a maximum of code flexibility. Database type
    manipulation can be done through rasql queries, for more details
    see :ref:`sec-rasql-typedef`.

Class Hierarchy
===============

.. code-block:: text

  * java.lang.Object
      * rasj.RasType
          * rasj.RasBaseType
              * rasj.RasPrimitiveType (implements rasj.global.RasGlobalDefs)
              * rasj.RasStructureType
          * rasj.RasCollectionType
          * rasj.RasMArrayType
          * rasj.RasMIntervalType
          * rasj.RasOIDType
          * rasj.RasPointType
          * rasj.RasSIntervalType


How To Use
==========

The following code piece demonstrates how the type structure given by
some ``RasType`` object can be evaluated and printed in a user-friendly
form. ::

    // instantiate a sample MDD type object:
    RasType rType = RasType.getAnyType( "marray <char, 1>" );

    // Now let's forget again that we know rType, let's analyse.
    // Check if the type object is some MDD type:
    if (rType.getClass().getName().equals("rasj.RasMArrayType"))
    {
        // yes, it is an MDD; is it structured or simple?
        if (rType.isStructType())
        {
            // yes, structured:
            System.out.println( "Structured base type is: " +
            rType.getBaseType() );
        }
        else
        {
            // no, atomic:
            System.out.println( "Atomic base type is: " +
            rType.getBaseType() );
        }
    }
    else
    {
        // no, not an MDD at all.
        System.out.println(
        "type object doesn't describe an MArray." );
    }


**********
Exceptions
**********

Overview
========

Exceptions serve to handle deviations from the desired flow of
operation. Several exceptions can be thrown by rasj classes; as a
general rule, all exceptions are subclassed from the general Java
exception class ``java.lang.Exception``. Exceptions are further grouped into
four main classes

-  ``org.odmg.Exception``
-  ``java.lang.Runtime­Exception``
-  ``rasj.RasException``
-  ``rasj.RasRuntimeException.``

See the HTML documentation for details on the exception class hierarchy.

Class Hierarchy (pruned)
========================

.. code-block:: text

  * java.lang.Object
      * java.lang.Throwable (implements java.io.Serializable)
          * java.lang.Exception
              * org.odmg.ODMGException
              * rasj.RasException
              * java.lang.RuntimeException
                  * org.odmg.ODMGRuntimeException
                  * rasj.RasRuntimeException


.. note::
    All classes have further subclasses See :ref:`sec-rasj-hierarchy` and
    :ref:`sec-odmg-hierarchy` for more information.

Handling Exceptions in the Client
=================================

Catching an exception can be done, for example, as shown below.
Obviously there are several ways doing this - however, a few rules
should be obeyed:

-  Granularity of exception catching depends on the overall program
   structure and purpose. For example, for data insertion one may want
   to build not just one large transaction, but several smaller units
   which, in case of failure, can be rerun with less time expenditure.

-  Don't forget to clean up program state during exception recovery -
   think of closing (aborting? committing?) transactions, closing the
   database, etc.

**Sample exception handling code**

The following code piece demonstrates simple exception handling. The
whole database access code is wrapped into a try statement. In case of
an exception, the corresponding catch statement attempts to abort the
transaction (if any is open) and to close the database. If in the course
of these actions another exception occurs (for example, because the
communication line has broken down), an error message is generated and
the program terminates. ::

    try
    {
        Implementation myApp = new RasImplementation( "http://" + server + port );
        ((RasImplementation)myApp).setUserIdentification(user, passwd);
        myDb = myApp.newDatabase();
        myDb.open(base, Database.OPEN_READ_ONLY);
        myTa = myApp.newTransaction();
        myTa.begin();
        // here do some work with the database
        myTa.commit();
        myDb.close();
    }
    catch ( java.lang.Exception e ) // catch any error
    {
        System.out.println( e.getMessage() );
        try
        {
            if(myTa != null)
                myTa.abort();
            if(myDb != null)
                myDb.close();
        }
        catch ( org.odmg.ODMGException exp ) // catch an abort
                                             // or close error
        {
            System.err.println( "Cannot commit/close: " + exp.getMessage());
        }
    }

Exceptions in the Class rasj.RasException
=========================================

The following exceptions are rasj specific:

**RasDimensionMismatchException**

The dimensions of the two operand objects do not match.

**RasIndexOutOfBoundsException**

The specified index is not within the bounds of the array indexed.

**RasResultIsNoCellException**

The operation result is no cell, but an array cell is expected at this
position. This happens, e.g., if the cast operator for casting to the
base type of class ``RasGMarray`` is invoked on an object which is not
'zero-dimensional'.

**RasResultIsNoIntervalException**

The result is no interval, but an interval is expected at this position.

**RasStreamInputOverflowException**

An initialization overflow occured. This happens, e.g., if the stream
input operator is invoked more often than the object has dimensions.

**RasTypeInvalidException**

Access method does not fit base type.

Exceptions in the Class ``org.odmg.QueryInvalidException``
==========================================================

**RasQueryExecutionFailedException**

This exception extends ``ODMGQueryInvalidException`` by offering direct
access to the rasdaman error number and the line, column and token in
the query string that produced the error.

Exceptions in the Class ``org.odmg.ODMGRuntimeException``
=========================================================

**RasConnectionFailedException**

This exception is raised when the connection to the server fails.

Exceptions in the Class ``rasj.RasRuntimeException``
====================================================

**RasClientInternalException**

This runtime exception indicates an internal error on client side which
cannot be solved by the user. In case of such an event, send a
report to your dealer containing the complete error message and a
precise description of the actions that lead to this exception.

**RasTypeNotSupportedException**

This exception is raised when the base type of a query result is not
supported by the current version of the rasj package.

**RasTypeUnknownException**

This exception is raised when the base type of a query result is unknown
on client-side.

**RasInvalidNameException**

This exception is thrown if an object name contains invalid characters.

**RasIllegalULongValueException**

Thrown if a RasMArrayLong is trying to be sent to the
server where one or more cell values are out of the range of 32-bit
unsigned integers.

**RasIllegalUShortValueException**

Thrown if a RasMArrayShort is trying to be sent to the
server where one or more cell values are out of the range of 16-bit
unsigned integers.


********************************************
Compilation and Execution of Client Programs
********************************************

Compiling Code Using rasj
=========================

**Environment Variables**

The ``CLASSPATH`` variable - which is used by the Java compiler to locate
packages used - must be extended with the path for the rasj directory of
the rasdaman distribution. This can be done, e.g., with the following
command:

.. code-block:: shell

    export CLASSPATH=$RMANHOME/lib/rasj.jar;$CLASSPATH

Alternatively, the ``-classpath`` or ``-cp`` option of ``javac`` can be used to explicitly
make known the package locations to the Java compiler.

Further, the JDK class directory must be contained in ``CLASSPATH``, and the
JDK binaries directory must be contained in the ``PATH`` variable.

Java sources making use of the rasj package are compiled and run as
usual. For example, a source file ``Lookup.java`` containing class ``Lookup``
would be compiled as

.. code-block:: shell

    javac Lookup.java

Running it as an application would be done through this command line
statement:

.. code-block:: shell

    java Lookup

**Sample Programs**

Several sample Java programs are provided as part of the rasdaman
distribution; they are located in the ``$RMANHOME/share/rasdaman/examples/java`` directory of the
distribution.

**Web Servlets and Applications**

rasj allows to build applications written in Java which can be web servlets
as well as applications. See petascope for example :ref:`sec_geo-services-guide`.

**Notes**

Remember the uppercase/lowercase distinction of Java!

For all classes with package definitions - such as ``rasj.RasGMArray`` - the
package name must be prefixed.

Java Version Compatibility Statement
====================================

rasj has been successfully tested with JDK versions 1.7+.

HTTP communication
==================

rasj internally uses HTTP to communicate with the rasdaman server. By
selecting individual URLs and ports in the database open statement (see
:ref:`sec-odmg`), safe database access across firewalls is possible.

Copyright Note
==============

rasj contains code for password encoding based on MD5.

Provision of this code is done in accordance with the GNU *Library
General Public License* (see `www.gnu.org <http://www.gnu.org>`_).

Legal Note
==========

Note that under some legislations usage and/or distribution of
crypto­graphy code may be prohibited by law. If you have obtained the
above­mentioned library in or from a region under such a legislation,
whatever you do with it is fully under your own responsibility. 
Inform rasdaman GmbH about the source where you have it obtained from so
that we can take action against any violator.


******************
HTML Documentation
******************

The implementation is described in extensive documentation integ­rated
with the source code from which a set of HTML files. This documentation
can be used with any Web browser. The entry point for the complete
documentation pages, including the rasj part, is ``doc/index.html`` in the
rasdaman distribution directory (see :ref:`sec-rasdaman-architecture`).

**ODMG Class Availability**

Note that the ``org.odmg`` package is taken verbatim from the ODMG standard.
rasdaman interface classes are derived as implementations of the
standard classes. However, only those classes have been implemented
which are necessary for rasdaman. If in doubt, the ``Implementation``
section should be consulted where unavailable items are marked (due to
copyright restrictions, the ODMG text must remain unchanged).

.. [1]
   memory usage is one byte per pixel

.. [2]
   This has nothing to do with transactions - after each completion of a
   query, the embracing transaction can be aborted indeed.
