diff --git a/.gitignore b/.gitignore
index 32858aad3..fef573878 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,6 @@
-*.class
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
-*.jar
-*.war
-*.ear
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
+/.classpath
+/.project
+/.settings
+/target
+/.idea
+/*.iml
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 000000000..52e46447f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,254 @@
+
+ 4.0.0
+
+ com.arangodb
+ arangodb-java-driver
+ 3.1.0-SNAPSHOT
+ 2016
+ jar
+
+ arangodb-java-driver
+ ArangoDB Java Driver
+ http://maven.apache.org
+
+
+
+ Apache License 2.0
+ http://www.apache.org/licenses/LICENSE-2.0
+ repo
+
+
+
+
+ UTF-8
+ 1.7.13
+ 1.1.3
+ 1.3
+ 4.12
+
+
+
+
+ a-brandt
+ a-brandt
+ https://github.com/a-brandt
+
+
+ mpv1989
+ Mark
+ https://github.com/mpv1989
+
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.5
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ 84aff6e87e214c
+ false
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.4.1
+
+
+ assembly
+ package
+
+ single
+
+
+
+
+
+ ${project.artifactId}-${project.version}-standalone
+
+ false
+ false
+
+ jar-with-dependencies
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.2
+
+ 1.8
+ 1.8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.7
+
+ UTF-8
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.4
+
+
+
+ jar
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.9.1
+
+
+ attach-javadocs
+
+ jar
+
+
+ ${javadoc.opts}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+ false
+ 10
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.5
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ ch.qos.logback
+ logback-classic
+ provided
+
+
+ junit
+ junit
+ test
+
+
+ org.hamcrest
+ hamcrest-all
+ test
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j-api.version}
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback-classic.version}
+
+
+ junit
+ junit
+ ${junit.version}
+
+
+ org.hamcrest
+ hamcrest-all
+ ${hamcrest-all.version}
+
+
+
+
+
+ https://github.com/arangodb/arangodb-java-driver2
+ scm:git:git://github.com/arangodb/arangodb-java-driver2.git
+ scm:git:git://github.com/arangodb/arangodb-java-driver2.git
+
+
+
+ ArangoDB GmbH
+ https://www.arangodb.com
+
+
+
diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java
new file mode 100644
index 000000000..55677b023
--- /dev/null
+++ b/src/main/java/com/arangodb/ArangoDB.java
@@ -0,0 +1,68 @@
+package com.arangodb;
+
+import java.util.Optional;
+
+import com.arangodb.internal.Constants;
+import com.arangodb.model.DB;
+import com.arangodb.model.DBCreate;
+import com.arangodb.model.DBDelete;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class ArangoDB {
+
+ public static class Builder {
+
+ private Optional host = Optional.empty();
+ private Optional port = Optional.empty();
+ private Optional user = Optional.empty();
+ private Optional password = Optional.empty();
+
+ public ArangoDB build() {
+ return new ArangoDB(this);
+ }
+
+ public Builder host(final String url) {
+ this.host = Optional.ofNullable(url);
+ return this;
+ }
+
+ public Builder port(final int port) {
+ this.port = Optional.of(port);
+ return this;
+ }
+
+ public Builder user(final String user) {
+ this.user = Optional.ofNullable(user);
+ return this;
+ }
+
+ public Builder password(final String password) {
+ this.password = Optional.ofNullable(password);
+ return this;
+ }
+
+ }
+
+ private ArangoDB(final Builder builder) {
+ }
+
+ public DBCreate dbCreate(final String name) {
+ return new DBCreate(this, name);
+ }
+
+ public DBDelete dbDelete(final String name) {
+ return new DBDelete(this, name);
+ }
+
+ public DB db() {
+ return db(Constants.SYSTEM_COLLECTION);
+ }
+
+ public DB db(final String name) {
+ return new DB(this, name);
+ }
+
+}
diff --git a/src/main/java/com/arangodb/ArangoException.java b/src/main/java/com/arangodb/ArangoException.java
new file mode 100644
index 000000000..fe0c11b0f
--- /dev/null
+++ b/src/main/java/com/arangodb/ArangoException.java
@@ -0,0 +1,13 @@
+package com.arangodb;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class ArangoException extends Exception {
+
+ public ArangoException(final Exception e) {
+ super(e);
+ }
+
+}
diff --git a/src/main/java/com/arangodb/entity/CollectionEntity.java b/src/main/java/com/arangodb/entity/CollectionEntity.java
new file mode 100644
index 000000000..e7de851b3
--- /dev/null
+++ b/src/main/java/com/arangodb/entity/CollectionEntity.java
@@ -0,0 +1,9 @@
+package com.arangodb.entity;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class CollectionEntity {
+
+}
diff --git a/src/main/java/com/arangodb/internal/Connection.java b/src/main/java/com/arangodb/internal/Connection.java
new file mode 100644
index 000000000..df1cf4294
--- /dev/null
+++ b/src/main/java/com/arangodb/internal/Connection.java
@@ -0,0 +1,9 @@
+package com.arangodb.internal;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class Connection {
+
+}
diff --git a/src/main/java/com/arangodb/internal/Constants.java b/src/main/java/com/arangodb/internal/Constants.java
new file mode 100644
index 000000000..106bbb20f
--- /dev/null
+++ b/src/main/java/com/arangodb/internal/Constants.java
@@ -0,0 +1,14 @@
+package com.arangodb.internal;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class Constants {
+
+ public static final String SYSTEM_COLLECTION = "_system";
+ public static final String DEFAULT_HOST = "127.0.0.1";
+ public static final int DEFAULT_PORT = 8529;
+ public static final String DEFAULT_PROPERTY_FILE = "/arangodb.properties";
+
+}
diff --git a/src/main/java/com/arangodb/model/CollectionCreate.java b/src/main/java/com/arangodb/model/CollectionCreate.java
new file mode 100644
index 000000000..319014fbe
--- /dev/null
+++ b/src/main/java/com/arangodb/model/CollectionCreate.java
@@ -0,0 +1,37 @@
+package com.arangodb.model;
+
+import java.util.Optional;
+import java.util.concurrent.Future;
+
+import com.arangodb.entity.CollectionEntity;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class CollectionCreate implements Executeable {
+
+ private final DB db;
+ private final String name;
+ private final Options options;
+
+ public static class Options {
+ private Optional waitForSync = Optional.empty();
+
+ public Options waitForSync(final Boolean waitForSync) {
+ this.waitForSync = Optional.of(waitForSync);
+ return this;
+ }
+ }
+
+ protected CollectionCreate(final DB db, final String name, final Options options) {
+ this.db = db;
+ this.name = name;
+ this.options = options;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+}
diff --git a/src/main/java/com/arangodb/model/CollectionDelete.java b/src/main/java/com/arangodb/model/CollectionDelete.java
new file mode 100644
index 000000000..9208e158e
--- /dev/null
+++ b/src/main/java/com/arangodb/model/CollectionDelete.java
@@ -0,0 +1,24 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class CollectionDelete implements Executeable {
+
+ private final DB db;
+ private final String name;
+
+ protected CollectionDelete(final DB db, final String name) {
+ this.db = db;
+ this.name = name;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DB.java b/src/main/java/com/arangodb/model/DB.java
new file mode 100644
index 000000000..b6af33274
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DB.java
@@ -0,0 +1,39 @@
+package com.arangodb.model;
+
+import com.arangodb.ArangoDB;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class DB {
+
+ private final ArangoDB arangoDB;
+ private final String name;
+
+ public DB(final ArangoDB arangoDB, final String name) {
+ this.arangoDB = arangoDB;
+ this.name = name;
+ }
+
+ protected ArangoDB arangoDB() {
+ return arangoDB;
+ }
+
+ protected String name() {
+ return name;
+ }
+
+ public DBCollection collection(final String name) {
+ return new DBCollection(this, name);
+ }
+
+ public CollectionCreate collectionCreate(final String name, final CollectionCreate.Options options) {
+ return new CollectionCreate(this, name, options);
+ }
+
+ public CollectionDelete collectionDelete(final String name) {
+ return new CollectionDelete(this, name);
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DBCollection.java b/src/main/java/com/arangodb/model/DBCollection.java
new file mode 100644
index 000000000..a37465d12
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DBCollection.java
@@ -0,0 +1,45 @@
+package com.arangodb.model;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class DBCollection {
+
+ private final DB db;
+ private final String name;
+
+ protected DBCollection(final DB db, final String name) {
+ this.db = db;
+ this.name = name;
+ }
+
+ protected DB db() {
+ return db;
+ }
+
+ protected String name() {
+ return name;
+ }
+
+ public DocumentCreate documentCreate(final T value, final DocumentCreate.Options options) {
+ return new DocumentCreate<>(this, value, options);
+ }
+
+ public DocumentRead documentRead(final String key, final Class type, final DocumentRead.Options options) {
+ return new DocumentRead<>(this, key, type, options);
+ }
+
+ public DocumentUpdate documentUpdate(final String key, final T value, final DocumentUpdate.Options options) {
+ return new DocumentUpdate<>(this, key, value, options);
+ }
+
+ public DocumentDelete documentDelete(final String key, final DocumentDelete.Options options) {
+ return new DocumentDelete(this, key, options);
+ }
+
+ public DocumentReadAll documentReadAll() {
+ return new DocumentReadAll(this);
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DBCreate.java b/src/main/java/com/arangodb/model/DBCreate.java
new file mode 100644
index 000000000..59b4ecdce
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DBCreate.java
@@ -0,0 +1,26 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+import com.arangodb.ArangoDB;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class DBCreate implements Executeable {
+
+ private final ArangoDB arangoDB;
+ private final String name;
+
+ public DBCreate(final ArangoDB arangoDB, final String name) {
+ this.arangoDB = arangoDB;
+ this.name = name;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DBDelete.java b/src/main/java/com/arangodb/model/DBDelete.java
new file mode 100644
index 000000000..bc30b6198
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DBDelete.java
@@ -0,0 +1,26 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+import com.arangodb.ArangoDB;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class DBDelete implements Executeable {
+
+ private final ArangoDB arangoDB;
+ private final String name;
+
+ public DBDelete(final ArangoDB arangoDB, final String name) {
+ this.arangoDB = arangoDB;
+ this.name = name;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DocumentCreate.java b/src/main/java/com/arangodb/model/DocumentCreate.java
new file mode 100644
index 000000000..dcbb37f73
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DocumentCreate.java
@@ -0,0 +1,31 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Mark - mark at arangodb.com
+ * @param
+ *
+ */
+public class DocumentCreate implements Executeable {
+
+ private final DBCollection dbCollection;
+ private final T value;
+ private final Options options;
+
+ public static class Options {
+
+ }
+
+ protected DocumentCreate(final DBCollection dbCollection, final T value, final Options options) {
+ this.dbCollection = dbCollection;
+ this.value = value;
+ this.options = options;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DocumentDelete.java b/src/main/java/com/arangodb/model/DocumentDelete.java
new file mode 100644
index 000000000..04558c47a
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DocumentDelete.java
@@ -0,0 +1,29 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class DocumentDelete implements Executeable {
+
+ private final DBCollection dbCollection;
+ private final String key;
+ private final Options options;
+
+ public static class Options {
+
+ }
+
+ protected DocumentDelete(final DBCollection dbCollection, final String key, final Options options) {
+ this.dbCollection = dbCollection;
+ this.key = key;
+ this.options = options;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+}
diff --git a/src/main/java/com/arangodb/model/DocumentRead.java b/src/main/java/com/arangodb/model/DocumentRead.java
new file mode 100644
index 000000000..fe9096856
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DocumentRead.java
@@ -0,0 +1,32 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Mark - mark at arangodb.com
+ * @param
+ *
+ */
+public class DocumentRead implements Executeable {
+
+ private final DBCollection dbCollection;
+ private final String key;
+ private final Class type;
+ private final Options options;
+
+ public static class Options {
+
+ }
+
+ public DocumentRead(final DBCollection dbCollection, final String key, final Class type, final Options options) {
+ this.dbCollection = dbCollection;
+ this.key = key;
+ this.type = type;
+ this.options = options;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+}
diff --git a/src/main/java/com/arangodb/model/DocumentReadAll.java b/src/main/java/com/arangodb/model/DocumentReadAll.java
new file mode 100644
index 000000000..1ce165c21
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DocumentReadAll.java
@@ -0,0 +1,23 @@
+package com.arangodb.model;
+
+import java.util.Collection;
+import java.util.concurrent.Future;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class DocumentReadAll implements Executeable> {
+
+ private final DBCollection dbCollection;
+
+ protected DocumentReadAll(final DBCollection dbCollection) {
+ this.dbCollection = dbCollection;
+ }
+
+ @Override
+ public Future> execute(final ExecuteCallback> callback) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/arangodb/model/DocumentUpdate.java b/src/main/java/com/arangodb/model/DocumentUpdate.java
new file mode 100644
index 000000000..b9c2f742a
--- /dev/null
+++ b/src/main/java/com/arangodb/model/DocumentUpdate.java
@@ -0,0 +1,32 @@
+package com.arangodb.model;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Mark - mark at arangodb.com
+ * @param
+ *
+ */
+public class DocumentUpdate implements Executeable {
+
+ private final DBCollection dbCollection;
+ private final String key;
+ private final T value;
+ private final Options options;
+
+ public static class Options {
+
+ }
+
+ protected DocumentUpdate(final DBCollection dbCollection, final String key, final T value, final Options options) {
+ this.dbCollection = dbCollection;
+ this.key = key;
+ this.value = value;
+ this.options = options;
+ }
+
+ @Override
+ public Future execute(final ExecuteCallback callback) {
+ return null;
+ }
+}
diff --git a/src/main/java/com/arangodb/model/ExecuteCallback.java b/src/main/java/com/arangodb/model/ExecuteCallback.java
new file mode 100644
index 000000000..f86e09a2b
--- /dev/null
+++ b/src/main/java/com/arangodb/model/ExecuteCallback.java
@@ -0,0 +1,11 @@
+package com.arangodb.model;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public interface ExecuteCallback {
+
+ void process(ExecuteResult result);
+
+}
diff --git a/src/main/java/com/arangodb/model/ExecuteResult.java b/src/main/java/com/arangodb/model/ExecuteResult.java
new file mode 100644
index 000000000..84673c464
--- /dev/null
+++ b/src/main/java/com/arangodb/model/ExecuteResult.java
@@ -0,0 +1,21 @@
+package com.arangodb.model;
+
+import java.util.Optional;
+
+import com.arangodb.ArangoException;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public interface ExecuteResult {
+
+ default boolean isSuccess() {
+ return getResult().isPresent();
+ }
+
+ Optional getException();
+
+ Optional getResult();
+
+}
diff --git a/src/main/java/com/arangodb/model/Executeable.java b/src/main/java/com/arangodb/model/Executeable.java
new file mode 100644
index 000000000..1a5e53e9c
--- /dev/null
+++ b/src/main/java/com/arangodb/model/Executeable.java
@@ -0,0 +1,24 @@
+package com.arangodb.model;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import com.arangodb.ArangoException;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public interface Executeable {
+
+ default T execute() throws ArangoException {
+ try {
+ return execute(null).get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new ArangoException(e);
+ }
+ }
+
+ Future execute(final ExecuteCallback callback);
+
+}
diff --git a/src/main/java/com/arangodb/util/MapBuilder.java b/src/main/java/com/arangodb/util/MapBuilder.java
new file mode 100644
index 000000000..084f797a4
--- /dev/null
+++ b/src/main/java/com/arangodb/util/MapBuilder.java
@@ -0,0 +1,38 @@
+package com.arangodb.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author Mark - mark at arangodb.com
+ *
+ */
+public class MapBuilder {
+
+ private final boolean ignoreValue;
+ private final LinkedHashMap map;
+
+ public MapBuilder() {
+ this(true);
+ }
+
+ public MapBuilder(final boolean ignoreValue) {
+ this.ignoreValue = ignoreValue;
+ map = new LinkedHashMap<>();
+ }
+
+ public MapBuilder put(final String key, final Object value) {
+ return put(key, value, false);
+ }
+
+ public MapBuilder put(final String key, final Object value, final boolean toString) {
+ if (!this.ignoreValue || (key != null && value != null)) {
+ map.put(key, toString ? value.toString() : value);
+ }
+ return this;
+ }
+
+ public Map get() {
+ return map;
+ }
+}
diff --git a/src/main/java/com/arangodb/velocypack/ArrayIterator.java b/src/main/java/com/arangodb/velocypack/ArrayIterator.java
new file mode 100644
index 000000000..2137b2bbd
--- /dev/null
+++ b/src/main/java/com/arangodb/velocypack/ArrayIterator.java
@@ -0,0 +1,35 @@
+package com.arangodb.velocypack;
+
+import java.util.NoSuchElementException;
+
+import com.arangodb.velocypack.exception.VPackValueTypeException;
+
+/**
+ * @author Mark - mark@arangodb.com
+ *
+ */
+public class ArrayIterator extends SliceIterator {
+
+ /**
+ * @param slice
+ * @throws VPackValueTypeException
+ */
+ public ArrayIterator(final VPackSlice slice) throws VPackValueTypeException {
+ super(slice);
+ if (!slice.isArray()) {
+ throw new VPackValueTypeException(ValueType.ARRAY);
+ }
+ }
+
+ @Override
+ public VPackSlice next() {
+ final VPackSlice next;
+ if (hasNext()) {
+ next = slice.get((int) position++);
+ } else {
+ throw new NoSuchElementException();
+ }
+ return next;
+ }
+
+}
diff --git a/src/main/java/com/arangodb/velocypack/ObjectIterator.java b/src/main/java/com/arangodb/velocypack/ObjectIterator.java
new file mode 100644
index 000000000..9bdda2665
--- /dev/null
+++ b/src/main/java/com/arangodb/velocypack/ObjectIterator.java
@@ -0,0 +1,47 @@
+package com.arangodb.velocypack;
+
+import java.util.NoSuchElementException;
+
+import com.arangodb.velocypack.exception.VPackValueTypeException;
+
+/**
+ * @author Mark - mark@arangodb.com
+ *
+ */
+public class ObjectIterator extends SliceIterator {
+
+ /**
+ * @param slice
+ * @throws VPackValueTypeException
+ */
+ public ObjectIterator(final VPackSlice slice) throws VPackValueTypeException {
+ super(slice);
+ if (!slice.isObject()) {
+ throw new VPackValueTypeException(ValueType.OBJECT);
+ }
+ if (size > 0) {
+ final byte head = slice.head();
+ if (head == 0x14) {
+ current = slice.keyAt(0).getStart();
+ } else {
+ current = slice.getStart() + slice.findDataOffset();
+ }
+ }
+ }
+
+ @Override
+ public VPackSlice next() {
+ if (position++ > 0) {
+ if (position <= size && current != 0) {
+ // skip over key
+ current += getCurrent().getByteSize();
+ // skip over value
+ current += getCurrent().getByteSize();
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ return getCurrent();
+ }
+
+}
diff --git a/src/main/java/com/arangodb/velocypack/SliceIterator.java b/src/main/java/com/arangodb/velocypack/SliceIterator.java
new file mode 100644
index 000000000..e3d573483
--- /dev/null
+++ b/src/main/java/com/arangodb/velocypack/SliceIterator.java
@@ -0,0 +1,38 @@
+package com.arangodb.velocypack;
+
+import java.util.Iterator;
+
+import com.arangodb.velocypack.exception.VPackValueTypeException;
+
+/**
+ * @author Mark - mark@arangodb.com
+ *
+ */
+public abstract class SliceIterator implements Iterator {
+
+ protected final VPackSlice slice;
+ protected final long size;
+ protected long position;
+ protected long current;
+
+ protected SliceIterator(final VPackSlice slice) throws VPackValueTypeException {
+ super();
+ this.slice = slice;
+ size = slice.getLength();
+ position = 0;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return position < size;
+ }
+
+ protected VPackSlice getCurrent() {
+ return new VPackSlice(slice.getVpack(), (int) current);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/com/arangodb/velocypack/VPack.java b/src/main/java/com/arangodb/velocypack/VPack.java
new file mode 100644
index 000000000..b27feac3f
--- /dev/null
+++ b/src/main/java/com/arangodb/velocypack/VPack.java
@@ -0,0 +1,544 @@
+package com.arangodb.velocypack;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.arangodb.velocypack.VPackBuilder.BuilderOptions;
+import com.arangodb.velocypack.exception.VPackException;
+import com.arangodb.velocypack.exception.VPackParserException;
+import com.arangodb.velocypack.internal.VPackCache;
+import com.arangodb.velocypack.internal.VPackCache.FieldInfo;
+import com.arangodb.velocypack.internal.VPackDeserializers;
+import com.arangodb.velocypack.internal.VPackInstanceCreators;
+import com.arangodb.velocypack.internal.VPackKeyMapAdapters;
+import com.arangodb.velocypack.internal.VPackOptionsImpl;
+import com.arangodb.velocypack.internal.VPackSerializers;
+
+/**
+ * @author Mark - mark@arangodb.com
+ *
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class VPack {
+
+ public static interface VPackOptions extends BuilderOptions {
+ boolean isSerializeNullValues();
+
+ void setSerializeNullValues(boolean serializeNullValues);
+ }
+
+ private static final String ATTR_KEY = "key";
+ private static final String ATTR_VALUE = "value";
+
+ private final Map, VPackSerializer>> serializers;
+ private final Map, VPackDeserializer>> deserializers;
+ private final Map, VPackInstanceCreator>> instanceCreators;
+ private final Map, VPackKeyMapAdapter>> keyMapAdapters;
+ private final VPackOptions options;
+
+ private final VPackCache cache;
+ private final VPackSerializationContext serializationContext;
+ private final VPackDeserializationContext deserializationContext;
+
+ public VPack() {
+ this(new VPackOptionsImpl());
+ }
+
+ public VPack(final VPackOptions options) {
+ super();
+ this.options = options;
+ serializers = new HashMap, VPackSerializer>>();
+ deserializers = new HashMap, VPackDeserializer>>();
+ instanceCreators = new HashMap, VPackInstanceCreator>>();
+ keyMapAdapters = new HashMap, VPackKeyMapAdapter>>();
+ cache = new VPackCache();
+ serializationContext = new VPackSerializationContext() {
+ @Override
+ public void serialize(final VPackBuilder builder, final String attribute, final Object entity)
+ throws VPackParserException {
+ VPack.this.serialize(attribute, entity, builder, new HashMap());
+ }
+
+ @Override
+ public void serialize(
+ final VPackBuilder builder,
+ final String attribute,
+ final Map, ?> entity,
+ final Class> keyType) throws VPackParserException {
+ VPack.this.serialize(attribute, entity, keyType, builder, new HashMap());
+ }
+
+ };
+ deserializationContext = new VPackDeserializationContext() {
+ @Override
+ public T deserialize(final VPackSlice vpack, final Class type) throws VPackParserException {
+ return VPack.this.deserialize(vpack, type);
+ }
+
+ @Override
+ public , C> T deserialize(
+ final VPackSlice vpack,
+ final Class type,
+ final Class contentType) throws VPackParserException {
+ return VPack.this.deserialize(vpack, type, contentType);
+ }
+
+ @Override
+ public , K, C> T deserialize(
+ final VPackSlice vpack,
+ final Class type,
+ final Class keyType,
+ final Class contentType) throws VPackParserException {
+ return VPack.this.deserialize(vpack, type, keyType, contentType);
+ }
+ };
+ instanceCreators.put(Collection.class, VPackInstanceCreators.COLLECTION);
+ instanceCreators.put(List.class, VPackInstanceCreators.LIST);
+ instanceCreators.put(Set.class, VPackInstanceCreators.SET);
+ instanceCreators.put(Map.class, VPackInstanceCreators.MAP);
+
+ serializers.put(String.class, VPackSerializers.STRING);
+ serializers.put(Boolean.class, VPackSerializers.BOOLEAN);
+ serializers.put(boolean.class, VPackSerializers.BOOLEAN);
+ serializers.put(Integer.class, VPackSerializers.INTEGER);
+ serializers.put(int.class, VPackSerializers.INTEGER);
+ serializers.put(Long.class, VPackSerializers.LONG);
+ serializers.put(long.class, VPackSerializers.LONG);
+ serializers.put(Short.class, VPackSerializers.SHORT);
+ serializers.put(short.class, VPackSerializers.SHORT);
+ serializers.put(Double.class, VPackSerializers.DOUBLE);
+ serializers.put(double.class, VPackSerializers.DOUBLE);
+ serializers.put(Float.class, VPackSerializers.FLOAT);
+ serializers.put(float.class, VPackSerializers.FLOAT);
+ serializers.put(BigInteger.class, VPackSerializers.BIG_INTEGER);
+ serializers.put(BigDecimal.class, VPackSerializers.BIG_DECIMAL);
+ serializers.put(Number.class, VPackSerializers.NUMBER);
+ serializers.put(Character.class, VPackSerializers.CHARACTER);
+ serializers.put(char.class, VPackSerializers.CHARACTER);
+
+ deserializers.put(String.class, VPackDeserializers.STRING);
+ deserializers.put(Boolean.class, VPackDeserializers.BOOLEAN);
+ deserializers.put(boolean.class, VPackDeserializers.BOOLEAN);
+ deserializers.put(Integer.class, VPackDeserializers.INTEGER);
+ deserializers.put(int.class, VPackDeserializers.INTEGER);
+ deserializers.put(Long.class, VPackDeserializers.LONG);
+ deserializers.put(long.class, VPackDeserializers.LONG);
+ deserializers.put(Short.class, VPackDeserializers.SHORT);
+ deserializers.put(short.class, VPackDeserializers.SHORT);
+ deserializers.put(Double.class, VPackDeserializers.DOUBLE);
+ deserializers.put(double.class, VPackDeserializers.DOUBLE);
+ deserializers.put(Float.class, VPackDeserializers.FLOAT);
+ deserializers.put(float.class, VPackDeserializers.FLOAT);
+ deserializers.put(BigInteger.class, VPackDeserializers.BIG_INTEGER);
+ deserializers.put(BigDecimal.class, VPackDeserializers.BIG_DECIMAL);
+ deserializers.put(Number.class, VPackDeserializers.NUMBER);
+ deserializers.put(Character.class, VPackDeserializers.CHARACTER);
+ deserializers.put(char.class, VPackDeserializers.CHARACTER);
+
+ keyMapAdapters.put(String.class, VPackKeyMapAdapters.STRING);
+ keyMapAdapters.put(Boolean.class, VPackKeyMapAdapters.BOOLEAN);
+ keyMapAdapters.put(Integer.class, VPackKeyMapAdapters.INTEGER);
+ keyMapAdapters.put(Long.class, VPackKeyMapAdapters.LONG);
+ keyMapAdapters.put(Short.class, VPackKeyMapAdapters.SHORT);
+ keyMapAdapters.put(Double.class, VPackKeyMapAdapters.DOUBLE);
+ keyMapAdapters.put(Float.class, VPackKeyMapAdapters.FLOAT);
+ keyMapAdapters.put(BigInteger.class, VPackKeyMapAdapters.BIG_INTEGER);
+ keyMapAdapters.put(BigDecimal.class, VPackKeyMapAdapters.BIG_DECIMAL);
+ keyMapAdapters.put(Number.class, VPackKeyMapAdapters.NUMBER);
+ keyMapAdapters.put(Character.class, VPackKeyMapAdapters.CHARACTER);
+ }
+
+ public VPackOptions getOptions() {
+ return options;
+ }
+
+ public VPack registerSerializer(final Class clazz, final VPackSerializer serializer) {
+ serializers.put(clazz, serializer);
+ return this;
+ }
+
+ public VPack registerDeserializer(final Class clazz, final VPackDeserializer deserializer) {
+ deserializers.put(clazz, deserializer);
+ return this;
+ }
+
+ public VPack regitserInstanceCreator(final Class clazz, final VPackInstanceCreator creator) {
+ instanceCreators.put(clazz, creator);
+ return this;
+ }
+
+ public T deserialize(final VPackSlice vpack, final Class type) throws VPackParserException {
+ final T entity;
+ try {
+ entity = (T) getValue(vpack, type, null);
+ } catch (final Exception e) {
+ throw new VPackParserException(e);
+ }
+ return entity;
+ }
+
+ public , C> T deserialize(
+ final VPackSlice vpack,
+ final Class type,
+ final Class contentType) throws VPackParserException {
+ final T entity;
+ try {
+ entity = (T) deserializeCollection(vpack, type, contentType);
+ } catch (final Exception e) {
+ throw new VPackParserException(e);
+ }
+ return entity;
+ }
+
+ public , K, C> T deserialize(
+ final VPackSlice vpack,
+ final Class type,
+ final Class keyType,
+ final Class contentType) throws VPackParserException {
+ final T entity;
+ try {
+ entity = (T) deserializeMap(vpack, type, keyType, contentType);
+ } catch (final Exception e) {
+ throw new VPackParserException(e);
+ }
+ return entity;
+ }
+
+ private T deserializeObject(final VPackSlice vpack, final Class type) throws InstantiationException,
+ IllegalAccessException, NoSuchMethodException, InvocationTargetException, VPackException {
+ final T entity;
+ final VPackDeserializer> deserializer = deserializers.get(type);
+ if (deserializer != null) {
+ entity = ((VPackDeserializer) deserializer).deserialize(vpack, deserializationContext);
+ } else {
+ entity = createInstance(type);
+ deserializeFields(entity, vpack);
+ }
+ return entity;
+ }
+
+ private T createInstance(final Class type) throws InstantiationException, IllegalAccessException {
+ final T entity;
+ final VPackInstanceCreator> creator = instanceCreators.get(type);
+ if (creator != null) {
+ entity = (T) creator.createInstance();
+ } else {
+ entity = type.newInstance();
+ }
+ return entity;
+ }
+
+ private void deserializeFields(final Object entity, final VPackSlice vpack) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException, InstantiationException, VPackException {
+ final Map fields = cache.getFields(entity.getClass());
+ for (final Iterator iterator = vpack.iterator(); iterator.hasNext();) {
+ final VPackSlice attr = iterator.next();
+ final FieldInfo fieldInfo = fields.get(attr.makeKey().getAsString());
+ if (fieldInfo != null && fieldInfo.isDeserialize()) {
+ deserializeField(attr, entity, fieldInfo);
+ }
+ }
+ }
+
+ private void deserializeField(final VPackSlice vpack, final Object entity, final FieldInfo fieldInfo)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException,
+ VPackException {
+ final VPackSlice attr = new VPackSlice(vpack.getVpack(), vpack.getStart() + vpack.getByteSize());
+ if (!attr.isNone()) {
+ final Object value = getValue(attr, fieldInfo.getType(), fieldInfo);
+ fieldInfo.set(entity, value);
+ }
+ }
+
+ private Object getValue(final VPackSlice vpack, final Class type, final FieldInfo fieldInfo)
+ throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException,
+ VPackException {
+ final Object value;
+ if (vpack.isNull()) {
+ value = null;
+ } else {
+ final VPackDeserializer> deserializer = deserializers.get(type);
+ if (deserializer != null) {
+ value = ((VPackDeserializer