gora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lewi...@apache.org
Subject [1/5] gora git commit: GORA-437 implement couchdb datastore , added a new store for gora as gora-couchdb , added javadocs , bugfixed
Date Tue, 23 Aug 2016 22:06:50 GMT
Repository: gora
Updated Branches:
  refs/heads/master 228991175 -> 72ce897f9


GORA-437 implement couchdb datastore
,added a new store for gora as gora-couchdb
,added javadocs
,bugfixed


Project: http://git-wip-us.apache.org/repos/asf/gora/repo
Commit: http://git-wip-us.apache.org/repos/asf/gora/commit/d6c820b2
Tree: http://git-wip-us.apache.org/repos/asf/gora/tree/d6c820b2
Diff: http://git-wip-us.apache.org/repos/asf/gora/diff/d6c820b2

Branch: refs/heads/master
Commit: d6c820b227ee1eea298126414e2e133096f7698a
Parents: 4192c87
Author: cihad guzel <cguzelg@gmail.com>
Authored: Thu May 19 10:16:34 2016 +0300
Committer: cihad guzel <cguzelg@gmail.com>
Committed: Sun Aug 21 22:56:02 2016 +0300

----------------------------------------------------------------------
 gora-couchdb/pom.xml                            | 229 +++++++
 .../apache/gora/couchdb/query/CouchDBQuery.java |  43 ++
 .../gora/couchdb/query/CouchDBResult.java       |  90 +++
 .../gora/couchdb/store/CouchDBMapping.java      |  56 ++
 .../couchdb/store/CouchDBMappingBuilder.java    | 106 ++++
 .../gora/couchdb/store/CouchDBParameters.java   |  82 +++
 .../apache/gora/couchdb/store/CouchDBStore.java | 628 +++++++++++++++++++
 .../util/CouchDBObjectMapperFactory.java        |  69 ++
 .../src/test/conf/gora-couchdb-mapping.xml      |  47 ++
 gora-couchdb/src/test/conf/gora.properties      |  19 +
 .../gora/couchdb/GoraCouchDBTestDriver.java     |  78 +++
 .../org/apache/gora/couchdb/package-info.java   |  21 +
 pom.xml                                         |   7 +
 13 files changed, 1475 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/pom.xml
----------------------------------------------------------------------
diff --git a/gora-couchdb/pom.xml b/gora-couchdb/pom.xml
new file mode 100644
index 0000000..69307a6
--- /dev/null
+++ b/gora-couchdb/pom.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.gora</groupId>
+    <artifactId>gora</artifactId>
+    <version>0.7-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+  <artifactId>gora-couchdb</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Apache Gora :: CouchDB</name>
+  <url>http://gora.apache.org</url>
+  <description>The Apache Gora open source framework provides an in-memory data model and 
+    persistence for big data. Gora supports persisting to column stores, key value stores, 
+    document stores and RDBMSs, and analyzing the data with extensive Apache Hadoop MapReduce 
+    support.</description>
+  <inceptionYear>2010</inceptionYear>
+  <organization>
+    <name>The Apache Software Foundation</name>
+    <url>http://www.apache.org/</url>
+  </organization>
+  <issueManagement>
+    <system>JIRA</system>
+    <url>https://issues.apache.org/jira/browse/GORA</url>
+  </issueManagement>
+  <ciManagement>
+    <system>Jenkins</system>
+    <url>https://builds.apache.org/job/Gora-trunk/</url>
+  </ciManagement>
+
+  <properties>
+    <osgi.import>*</osgi.import>
+    <osgi.export>org.apache.gora.couchdb*;version="${project.version}";-noimport:=true</osgi.export>
+  </properties>
+
+  <profiles>
+    <profile>
+      <id>couchdb-with-test</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <version>2.4.2</version>
+            <configuration>
+              <skipTests>false</skipTests>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+  <build>
+    <directory>target</directory>
+    <outputDirectory>target/classes</outputDirectory>
+    <finalName>${project.artifactId}-${project.version}</finalName>
+    <testOutputDirectory>target/test-classes</testOutputDirectory>
+    <testSourceDirectory>src/test/java</testSourceDirectory>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testResources>
+      <testResource>
+        <directory>${project.basedir}/src/test/conf</directory>
+        <includes>
+          <include>**/*</include>
+        </includes>
+      </testResource>
+    </testResources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.4.2</version>
+        <configuration>
+          <skipTests>true</skipTests>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>${build-helper-maven-plugin.version}</version>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>src/examples/java</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <repositories>
+    <repository>
+      <id>clojars.org</id>
+      <url>http://clojars.org/repo</url>
+    </repository>
+  </repositories>
+
+  <dependencies>
+    <!-- Gora Internal Dependencies -->
+    <dependency>
+      <groupId>org.apache.gora</groupId>
+      <artifactId>gora-core</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.gora</groupId>
+      <artifactId>gora-core</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.apache.gora</groupId>
+      <artifactId>gora-core</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- END of Gora Internal Dependencies -->
+
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-client</artifactId>
+      <scope>compile</scope>
+      <optional>true</optional>
+    </dependency>
+
+    <!-- Apache CouchDB java client -->
+    <dependency>
+      <groupId>org.ektorp</groupId>
+      <artifactId>org.ektorp</artifactId>
+      <version>1.4.2</version>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.apache.avro</groupId>
+      <artifactId>avro</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <!-- Misc Dependencies -->
+    <dependency>
+      <groupId>org.jdom</groupId>
+      <artifactId>jdom</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <!-- Logging Dependencies -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>runtime</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>javax.jms</groupId>
+          <artifactId>jms</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <!-- END of Logging Dependencies -->
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-minicluster</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- END of Testing Dependencies -->
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBQuery.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBQuery.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBQuery.java
new file mode 100644
index 0000000..69319c3
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBQuery.java
@@ -0,0 +1,43 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.query;
+
+import org.apache.gora.couchdb.store.CouchDBStore;
+import org.apache.gora.persistency.impl.PersistentBase;
+import org.apache.gora.query.Query;
+import org.apache.gora.query.impl.QueryBase;
+import org.apache.gora.store.DataStore;
+
+/**
+ * CouchDB specific implementation of the {@link Query} interface.
+ */
+public class CouchDBQuery<K, T extends PersistentBase> extends QueryBase<K, T> {
+
+  final CouchDBStore store;
+
+  /**
+   * Constructor for the query
+   *
+   * @param dataStore Data store used
+   *
+   */
+  public CouchDBQuery(DataStore<K, T> dataStore) {
+    super(dataStore);
+    store = (CouchDBStore) dataStore;
+  }
+}

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBResult.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBResult.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBResult.java
new file mode 100644
index 0000000..7d43682
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/query/CouchDBResult.java
@@ -0,0 +1,90 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.query;
+
+import org.apache.gora.couchdb.store.CouchDBStore;
+import org.apache.gora.persistency.Persistent;
+import org.apache.gora.query.Query;
+import org.apache.gora.query.impl.ResultBase;
+import org.apache.gora.store.DataStore;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CouchDB specific implementation of the {@link org.apache.gora.query.Result}
+ * interface.
+ */
+public class CouchDBResult<K, T extends Persistent> extends ResultBase<K, T> {
+
+  /**
+   * Result set containing query results
+   */
+  private List<Map> result;
+
+  protected CouchDBStore dataStore;
+  int position = 0;
+
+  /**
+   * Constructor for the result set
+   *
+   * @param dataStore Data store used
+   * @param query     Query used
+   * @param result    Result obtained from querying
+   */
+  public CouchDBResult(DataStore<K, T> dataStore, Query<K, T> query, List<Map> result) {
+    super(dataStore, query);
+    this.result = result;
+    this.dataStore = (CouchDBStore) dataStore;
+  }
+
+  /**
+   * Gets the next item
+   */
+  @Override
+  protected boolean nextInner() throws IOException {
+    if (result == null || result.size() <= 0 || position >= result.size()) {
+      return false;
+    }
+    key = (K) result.get(position).get("_id");
+    persistent = (T) dataStore.newInstance(result.get(position++), query.getFields());
+    return persistent != null;
+  }
+
+  /**
+   * Gets the items reading progress
+   */
+  @Override
+  public float getProgress() throws IOException, InterruptedException {
+    if (result != null && result.size() > 0) {
+      return (float) position / (float) result.size();
+    } else {
+      return 0;
+    }
+  }
+
+  /**
+   * Result set containing query results
+   *
+   * @return Result set containing query results
+   */
+  public List<Map> getResultData() {
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMapping.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMapping.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMapping.java
new file mode 100644
index 0000000..502cb24
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMapping.java
@@ -0,0 +1,56 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.store;
+
+import org.jdom.Element;
+
+import java.util.List;
+
+/**
+ * Mapping definitions for CouchDB.
+ */
+public class CouchDBMapping {
+
+  /**
+   * Name of the database this mapping is linked to
+   */
+  public String databaseName;
+
+  /**
+   * CouchDB document description
+   */
+  public List<Element> fields;
+
+  /**
+   * Name of the database this mapping is linked to
+   *
+   * @return name as String
+   */
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
+  /**
+   * Setter for the name of the database
+   *
+   * @param databaseName name of the database
+   */
+  public void setDatabaseName(String databaseName) {
+    this.databaseName = databaseName;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMappingBuilder.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMappingBuilder.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMappingBuilder.java
new file mode 100644
index 0000000..715add6
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBMappingBuilder.java
@@ -0,0 +1,106 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.store;
+
+import org.apache.gora.persistency.impl.PersistentBase;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * A builder for creating the mapper.
+ */
+public class CouchDBMappingBuilder<K, T extends PersistentBase> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CouchDBMappingBuilder.class);
+
+  // Class description
+  private static final String TAG_CLASS = "class";
+  private static final String TAG_FIELD = "field";
+  private static final String ATT_KEYCLASS = "keyClass";
+  private static final String ATT_DOCUMENT = "document";
+
+  // Document description
+  private static final String ATT_NAME = "name";
+
+  /**
+   * Mapping instance being built
+   */
+  private final CouchDBMapping mapping;
+
+  private final CouchDBStore<K, T> dataStore;
+
+  /**
+   * Constructor for builder to create the mapper.
+   *
+   * @param store
+   */
+  public CouchDBMappingBuilder(final CouchDBStore<K, T> store) {
+    this.dataStore = store;
+    this.mapping = new CouchDBMapping();
+  }
+
+  /**
+   * Return the built mapping if it is in a legal state
+   */
+  public CouchDBMapping build() {
+    if (mapping.getDatabaseName() == null) {
+      LOG.error("A collection is not specified");
+      throw new IllegalStateException("A collection is not specified");
+    }
+    return mapping;
+  }
+
+  /**
+   * Load the {@link org.apache.gora.couchdb.store.CouchDBMapping} from a file
+   * passed in parameter.
+   *
+   * @param filename path to the file holding the mapping
+   * @throws java.io.IOException
+   */
+  protected void readMapping(String filename) throws IOException {
+    try {
+      final Class<T> persistentClass = dataStore.getPersistentClass();
+      final Class<K> keyClass = dataStore.getKeyClass();
+
+      final SAXBuilder saxBuilder = new SAXBuilder();
+      final InputStream is = getClass().getClassLoader().getResourceAsStream(filename);
+
+      final Element root = saxBuilder.build(is).getRootElement();
+      final List<Element> classElements = root.getChildren(TAG_CLASS);
+
+      for (Element classElement : classElements) {
+        if (classElement.getAttributeValue(ATT_NAME).equals(persistentClass.getName()) &&
+            classElement.getAttributeValue(ATT_KEYCLASS).equals(keyClass.getName())) {
+          mapping
+              .setDatabaseName(dataStore.getSchemaName(classElement.getAttributeValue(ATT_DOCUMENT), persistentClass));
+          mapping.fields = classElement.getChildren(TAG_FIELD);
+          break;
+        }
+      }
+    } catch (Exception ex) {
+      CouchDBStore.LOG.error(ex.getMessage(), ex);
+      throw new IOException(ex);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBParameters.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBParameters.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBParameters.java
new file mode 100644
index 0000000..d73f430
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBParameters.java
@@ -0,0 +1,82 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.store;
+
+import java.util.Properties;
+
+/**
+ * Configuration properties
+ */
+public class CouchDBParameters {
+
+  /**
+   * Property pointing to the host where the server is running
+   */
+  public static final String PROP_COUCHDB_SERVER = "gora.datastore.couchdb.server";
+
+  /**
+   * Property pointing to the port where the server is running
+   */
+  public static final String PROP_COUCHDB_PORT = "gora.datastore.couchdb.port";
+
+  private final String server;
+  private final String port;
+
+  /**
+   *
+   *  Initializing for configuration properties
+   *
+   * @param server      server domain or ip for couchDB connection
+   * @param port        port for couchDB connection
+   */
+  private CouchDBParameters(String server, String port) {
+    this.server = server;
+    this.port = port;
+  }
+
+  /**
+   * Get server domain
+   *
+   * @return
+   */
+  public String getServer() {
+    return server;
+  }
+
+  /**
+   * Get server port
+   *
+   * @return
+   */
+  public int getPort() {
+    return Integer.parseInt(port);
+  }
+
+  /**
+   * load configuration values
+   *
+   * @param properties
+   * @return
+   */
+  public static CouchDBParameters load(Properties properties) {
+    String couchDBServer = properties.getProperty(PROP_COUCHDB_SERVER);
+    String couchDBPort = properties.getProperty(PROP_COUCHDB_PORT);
+
+    return new CouchDBParameters(couchDBServer, couchDBPort);
+  }
+}

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBStore.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBStore.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBStore.java
new file mode 100644
index 0000000..5ca8af7
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/store/CouchDBStore.java
@@ -0,0 +1,628 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.store;
+
+import com.google.common.primitives.Ints;
+import org.apache.avro.Schema;
+import org.apache.avro.Schema.Field;
+import org.apache.avro.util.Utf8;
+import org.apache.commons.lang.StringUtils;
+import org.apache.gora.couchdb.query.CouchDBQuery;
+import org.apache.gora.couchdb.query.CouchDBResult;
+import org.apache.gora.couchdb.util.CouchDBObjectMapperFactory;
+import org.apache.gora.persistency.impl.BeanFactoryImpl;
+import org.apache.gora.persistency.impl.DirtyListWrapper;
+import org.apache.gora.persistency.impl.DirtyMapWrapper;
+import org.apache.gora.persistency.impl.PersistentBase;
+import org.apache.gora.query.PartitionQuery;
+import org.apache.gora.query.Query;
+import org.apache.gora.query.Result;
+import org.apache.gora.query.impl.PartitionQueryImpl;
+import org.apache.gora.store.DataStoreFactory;
+import org.apache.gora.store.impl.DataStoreBase;
+import org.apache.gora.util.AvroUtils;
+import org.apache.gora.util.ClassLoadingUtils;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.CouchDbInstance;
+import org.ektorp.ViewQuery;
+import org.ektorp.http.HttpClient;
+import org.ektorp.http.StdHttpClient;
+import org.ektorp.impl.ObjectMapperFactory;
+import org.ektorp.impl.StdCouchDbConnector;
+import org.ektorp.impl.StdCouchDbInstance;
+import org.ektorp.support.CouchDbDocument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * Implementation of a CouchDB data store to be used by gora.
+ *
+ * @param <K> class to be used for the key
+ * @param <T> class to be persisted within the store
+ */
+public class CouchDBStore<K, T extends PersistentBase> extends DataStoreBase<K, T> {
+
+  /**
+   * Logging implementation
+   */
+  protected static final Logger LOG = LoggerFactory.getLogger(CouchDBStore.class);
+
+  /**
+   * The default file name value to be used for obtaining the CouchDB object field mapping's
+   */
+  public static final String DEFAULT_MAPPING_FILE = "gora-couchdb-mapping.xml";
+
+  /**
+   * for bulk document operations
+   */
+  private final List<Object> bulkDocs = new ArrayList<>();
+
+  /**
+   * Mapping definition for CouchDB
+   */
+  private CouchDBMapping mapping;
+
+  /**
+   * The standard implementation of the CouchDbInstance interface. This interface provides methods for
+   * managing databases on the connected CouchDb instance.
+   * StdCouchDbInstance is thread-safe.
+   */
+  private CouchDbInstance dbInstance;
+
+  /**
+   * The standard implementation of the CouchDbConnector interface. This interface provides methods for
+   * manipulating documents within a specific database.
+   * StdCouchDbConnector is thread-safe.
+   */
+  private CouchDbConnector db;
+
+  /**
+   * Initialize the data store by reading the credentials, setting the client's properties up and
+   * reading the mapping file. Initialize is called when then the call to
+   * {@link org.apache.gora.store.DataStoreFactory#createDataStore} is made.
+   *
+   * @param keyClass
+   * @param persistentClass
+   * @param properties
+   */
+  @Override
+  public void initialize(Class<K> keyClass, Class<T> persistentClass, Properties properties) {
+    LOG.debug("Initializing CouchDB store");
+    super.initialize(keyClass, persistentClass, properties);
+
+    final CouchDBParameters params = CouchDBParameters.load(properties);
+
+    try {
+      final String mappingFile = DataStoreFactory.getMappingFile(properties, this, DEFAULT_MAPPING_FILE);
+      final HttpClient httpClient = new StdHttpClient.Builder()
+          .url("http://" + params.getServer() + ":" + params.getPort())
+          .build();
+
+      dbInstance = new StdCouchDbInstance(httpClient);
+
+      final CouchDBMappingBuilder<K, T> builder = new CouchDBMappingBuilder<>(this);
+      LOG.debug("Initializing CouchDB store with mapping {}.", new Object[] { mappingFile });
+      builder.readMapping(mappingFile);
+      mapping = builder.build();
+
+      final ObjectMapperFactory myObjectMapperFactory = new CouchDBObjectMapperFactory();
+      myObjectMapperFactory.createObjectMapper().addMixInAnnotations(persistentClass, CouchDbDocument.class);
+
+      db = new StdCouchDbConnector(mapping.getDatabaseName(), dbInstance, myObjectMapperFactory);
+      db.createDatabaseIfNotExists();
+
+    } catch (IOException e) {
+      LOG.error("Error while initializing CouchDB store: {}", new Object[] { e.getMessage() });
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * In CouchDB, Schemas are referred to as database name.
+   *
+   * @return databasename
+   */
+  @Override
+  public String getSchemaName() {
+    return mapping.getDatabaseName();
+  }
+
+  /**
+   * In CouchDB, Schemas are referred to as database name.
+   *
+   * @param mappingSchemaName the name of the schema as read from the mapping file
+   * @param persistentClass   persistent class
+   * @return database name
+   */
+  @Override
+  public String getSchemaName(final String mappingSchemaName, final Class<?> persistentClass) {
+    return super.getSchemaName(mappingSchemaName, persistentClass);
+  }
+
+  /**
+   * Create a new database in CouchDB if necessary.
+   */
+  @Override
+  public void createSchema() {
+    if (schemaExists()) {
+      return;
+    }
+    dbInstance.createDatabase(mapping.getDatabaseName());
+  }
+
+  /**
+   * Drop the database.
+   */
+  @Override
+  public void deleteSchema() {
+    if (schemaExists()) {
+      dbInstance.deleteDatabase(mapping.getDatabaseName());
+    }
+  }
+
+  /**
+   * Check if the database already exists or should be created.
+   */
+  @Override
+  public boolean schemaExists() {
+    return dbInstance.checkIfDbExists(mapping.getDatabaseName());
+  }
+
+  /**
+   * Retrieve an entry from the store with only selected fields.
+   *
+   * @param key    identifier of the document in the database
+   * @param fields list of fields to be loaded from the database
+   */
+  @Override
+  public T get(final K key, final String[] fields) {
+
+    final Map result;
+    try {
+      result = db.get(Map.class, key.toString());
+      return newInstance(result, getFieldsToQuery(fields));
+    } catch (Exception e) {
+      LOG.info(e.getMessage(), e);
+      return null;
+    }
+  }
+
+  /**
+   * Persist an object into the store.
+   *
+   * @param key identifier of the object in the store
+   * @param obj the object to be inserted
+   */
+  @Override
+  public void put(K key, T obj) {
+    final Map<String, Object> buffer = Collections.synchronizedMap(new LinkedHashMap<String, Object>());
+    buffer.put("_id", key);
+
+    Schema schema = obj.getSchema();
+
+    List<Field> fields = schema.getFields();
+    for (int i = 0; i < fields.size(); i++) {
+      if (!obj.isDirty(i)) {
+        continue;
+      }
+      Field field = fields.get(i);
+      Object fieldValue = obj.get(field.pos());
+
+      Schema fieldSchema = field.schema();
+
+      // check if field has a nested structure (array, map, record or union)
+      fieldValue = toDBObject(fieldSchema, fieldValue);
+      buffer.put(field.name(), fieldValue);
+    }
+    bulkDocs.add(buffer);
+
+  }
+
+  private Map<String, Object> mapToCouchDB(final Object fieldValue) {
+    final Map<String, Object> newMap = new LinkedHashMap<>();
+    final Map<?, ?> fieldMap = (Map<?, ?>) fieldValue;
+    if (fieldValue == null) {
+      return null;
+    }
+    for (Object key : fieldMap.keySet()) {
+      newMap.put(key.toString(), fieldMap.get(key).toString());
+    }
+    return newMap;
+  }
+
+  private List<Object> listToCouchDB(final Schema fieldSchema, final Object fieldValue) {
+    final List<Object> list = new LinkedList<>();
+    for (Object obj : (List<Object>) fieldValue) {
+      list.add(toDBObject(fieldSchema.getElementType(), obj));
+    }
+    return list;
+  }
+
+  private Map<String, Object> recordToCouchDB(final Schema fieldSchema, final Object fieldValue) {
+    final PersistentBase persistent = (PersistentBase) fieldValue;
+    final Map<String, Object> newMap = new LinkedHashMap<>();
+
+    if (persistent != null) {
+      for (Field member : fieldSchema.getFields()) {
+        Schema memberSchema = member.schema();
+        Object memberValue = persistent.get(member.pos());
+        newMap.put(member.name(), toDBObject(memberSchema, memberValue));
+      }
+      return newMap;
+    }
+    return null;
+  }
+
+  private String bytesToCouchDB(final Object fieldValue) {
+    return new String(((ByteBuffer) fieldValue).array(), StandardCharsets.UTF_8);
+  }
+
+  private Object unionToCouchDB(final Schema fieldSchema, final Object fieldValue) {
+    Schema.Type type0 = fieldSchema.getTypes().get(0).getType();
+    Schema.Type type1 = fieldSchema.getTypes().get(1).getType();
+
+    // Check if types are different and there's a "null", like ["null","type"]
+    // or ["type","null"]
+    if (!type0.equals(type1)
+        && (type0.equals(Schema.Type.NULL) || type1.equals(Schema.Type.NULL))) {
+      Schema innerSchema = fieldSchema.getTypes().get(1);
+      LOG.debug("Transform value to DBObject (UNION), schemaType:{}, type1:{}",
+          new Object[] { innerSchema.getType(), type1 });
+
+      // Deserialize as if schema was ["type"]
+      return toDBObject(innerSchema, fieldValue);
+    } else {
+      throw new IllegalStateException(
+          "CouchDBStore doesn't support 3 types union field yet. Please update your mapping");
+    }
+  }
+
+  private Object toDBObject(final Schema fieldSchema, final Object fieldValue) {
+
+    final Object result;
+
+    switch (fieldSchema.getType()) {
+    case MAP:
+      result = mapToCouchDB(fieldValue);
+      break;
+    case ARRAY:
+      result = listToCouchDB(fieldSchema, fieldValue);
+      break;
+    case RECORD:
+      result = recordToCouchDB(fieldSchema, fieldValue);
+      break;
+    case BYTES:
+      result = bytesToCouchDB(fieldValue);
+      break;
+    case ENUM:
+    case STRING:
+      result = fieldValue.toString();
+      break;
+    case UNION:
+      result = unionToCouchDB(fieldSchema, fieldValue);
+      break;
+    default:
+      result = fieldValue;
+      break;
+    }
+    return result;
+  }
+
+  /**
+   * Deletes the object with the given key
+   *
+   * @param key the key of the object
+   * @return whether the object was successfully deleted
+   */
+  @Override
+  public boolean delete(K key) {
+    if (key == null) {
+      deleteSchema();
+      createSchema();
+      return true;
+    }
+    final String keyString = key.toString();
+    final Map<String, Object> referenceData = db.get(Map.class, keyString);
+    return StringUtils.isNotEmpty(db.delete(keyString, referenceData.get("_rev").toString()));
+  }
+
+  /**
+   * Deletes all the objects matching the query.
+   * See also the note on <a href="#visibility">visibility</a>.
+   *
+   * @param query matching records to this query will be deleted
+   * @return number of deleted records
+   */
+  @Override
+  public long deleteByQuery(Query<K, T> query) {
+
+    final K key = query.getKey();
+    final K startKey = query.getStartKey();
+    final K endKey = query.getEndKey();
+
+    if (key == null && startKey == null && endKey == null) {
+      deleteSchema();
+      createSchema();
+      return -1;
+    } else {
+      final ViewQuery viewQuery = new ViewQuery()
+          .allDocs()
+          .includeDocs(true)
+          .key(key)
+          .startKey(startKey)
+          .endKey(endKey);
+
+      final List<Map> result = db.queryView(viewQuery, Map.class);
+      final Map<String, List<String>> revisionsToPurge = new HashMap<>();
+
+      for (Map map : result) {
+        final List<String> revisions = new ArrayList<>();
+        String keyString = map.get("_id").toString();
+        String rev = map.get("_rev").toString();
+        revisions.add(rev);
+        revisionsToPurge.put(keyString, revisions);
+      }
+      return db.purge(revisionsToPurge).getPurged().size();
+    }
+  }
+
+  /**
+   * Create a new {@link Query} to query the datastore.
+   */
+  @Override
+  public Query<K, T> newQuery() {
+    CouchDBQuery<K, T> query = new CouchDBQuery<>(this);
+    query.setFields(getFieldsToQuery(null));
+    return query;
+  }
+
+  /**
+   * Execute the query and return the result.
+   */
+  @Override
+  public Result<K, T> execute(Query<K, T> query) {
+    query.setFields(getFieldsToQuery(query.getFields()));
+    final ViewQuery viewQuery = new ViewQuery()
+        .allDocs()
+        .includeDocs(true)
+        .startKey(query.getStartKey())
+        .endKey(query.getEndKey())
+        .limit(Ints.checkedCast(query.getLimit())); //FIXME GORA have long value but ektorp client use integer
+
+    CouchDBResult<K, T> couchDBResult = new CouchDBResult<>(this, query, db.queryView(viewQuery, Map.class));
+
+    return couchDBResult;
+  }
+
+  @Override
+  public List<PartitionQuery<K, T>> getPartitions(Query<K, T> query) throws IOException {
+
+    final List<PartitionQuery<K, T>> list = new ArrayList<>();
+    final PartitionQueryImpl<K, T> pqi = new PartitionQueryImpl<>(query);
+
+    pqi.setConf(getConf());
+    list.add(pqi);
+    return list;
+  }
+
+  /**
+   * Creates a new Persistent instance with the values in 'result' for the fields listed.
+   *
+   * @param result result from the query to the database
+   * @param fields the list of fields to be mapped to the persistence class instance
+   * @return a persistence class instance which content was deserialized
+   * @throws IOException
+   */
+  public T newInstance(Map<String, Object> result, String[] fields) throws IOException {
+    if (result == null)
+      return null;
+
+    T persistent = newPersistent();
+
+    // Populate each field
+    for (String fieldName : fields) {
+      if (result.get(fieldName) == null) {
+        continue;
+      }
+      final Field field = fieldMap.get(fieldName);
+      final Schema fieldSchema = field.schema();
+
+      LOG.debug("Load from DBObject (MAIN), field:{}, schemaType:{}, docField:{}",
+          new Object[] { field.name(), fieldSchema.getType(), fieldName });
+
+      final Object resultObj = fromDBObject(fieldSchema, field, fieldName, result);
+      persistent.put(field.pos(), resultObj);
+      persistent.setDirty(field.pos());
+    }
+
+    persistent.clearDirty();
+    return persistent;
+
+  }
+
+  private Object fromCouchDBRecord(final Schema fieldSchema, final String docf, final Object value) {
+
+    final Object innerValue = ((Map) value).get(docf);
+    if (innerValue == null) {
+      return null;
+    }
+
+    Class<?> clazz = null;
+    try {
+      clazz = ClassLoadingUtils.loadClass(fieldSchema.getFullName());
+    } catch (ClassNotFoundException e) {
+      LOG.debug(e.getMessage());
+    }
+
+    final PersistentBase record = (PersistentBase) new BeanFactoryImpl(keyClass, clazz).newPersistent();
+
+    for (Field recField : fieldSchema.getFields()) {
+      Schema innerSchema = recField.schema();
+
+      record.put(recField.pos(), fromDBObject(innerSchema, recField, recField.name(), innerValue));
+    }
+    return record;
+  }
+
+  private Object fromCouchDBMap(final Schema fieldSchema, final Field field, final String docf, final Object value) {
+
+    final Map<String, Object> map = (Map<String, Object>) ((Map<String, Object>) value).get(docf);
+    final Map<Utf8, Object> rmap = new HashMap<>();
+
+    if (map == null) {
+      return new DirtyMapWrapper(rmap);
+    }
+
+    for (Map.Entry<String, Object> e : map.entrySet()) {
+      Schema innerSchema = fieldSchema.getValueType();
+      ;
+      Object o = fromDBObject(innerSchema, field, e.getKey(), e.getValue());
+      rmap.put(new Utf8(e.getKey()), o);
+    }
+    return new DirtyMapWrapper<>(rmap);
+  }
+
+  private Object fromCouchDBUnion(final Schema fieldSchema, final Field field, final String docf, final Object value) {
+
+    Object result;// schema [type0, type1]
+    Schema.Type type0 = fieldSchema.getTypes().get(0).getType();
+    Schema.Type type1 = fieldSchema.getTypes().get(1).getType();
+
+    // Check if types are different and there's a "null", like ["null","type"]
+    // or ["type","null"]
+    if (!type0.equals(type1)
+        && (type0.equals(Schema.Type.NULL) || type1.equals(Schema.Type.NULL))) {
+      Schema innerSchema = fieldSchema.getTypes().get(1);
+      LOG.debug(
+          "Load from DBObject (UNION), schemaType:{}, docField:{}, storeType:{}",
+          new Object[] { innerSchema.getType(), docf });
+      // Deserialize as if schema was ["type"]
+      result = fromDBObject(innerSchema, field, docf, value);
+    } else {
+      throw new IllegalStateException(
+          "CouchDBStore doesn't support 3 types union field yet. Please update your mapping");
+    }
+    return result;
+  }
+
+  private Object fromCouchDBList(final Schema fieldSchema, final Field field, final String docf, final Object value) {
+    final List<Object> list = (List<Object>) ((Map<String, Object>) value).get(docf);
+    final List<Object> rlist = new ArrayList<>();
+
+    if (list == null) {
+      return new DirtyListWrapper(rlist);
+    }
+
+    for (Object item : list) {
+
+      Object o = fromDBObject(fieldSchema.getElementType(), field, "item", item);
+      rlist.add(o);
+    }
+    return new DirtyListWrapper<>(rlist);
+  }
+
+  private Object fromCouchDBEnum(final Schema fieldSchema, final String docf, final Object value) {
+    final Object result;
+    if (value instanceof Map) {
+      result = AvroUtils.getEnumValue(fieldSchema, (String) ((Map) value).get(docf));
+    } else {
+      result = AvroUtils.getEnumValue(fieldSchema, (String) value);
+    }
+    return result;
+  }
+
+  private Object fromCouchDBBytes(final String docf, final Object value) {
+    final byte[] array;
+    if (value instanceof Map) {
+      array = ((String) ((Map) value).get(docf)).getBytes(StandardCharsets.UTF_8);
+    } else {
+      array = ((String) value).getBytes(StandardCharsets.UTF_8);
+    }
+    return ByteBuffer.wrap(array);
+  }
+
+  private Object fromCouchDBString(final String docf, final Object value) {
+    final Object result;
+
+    if (value instanceof Map) {
+      result = new Utf8((String) ((Map) value).get(docf));
+    } else {
+      result = new Utf8((String) value);
+    }
+
+    return result;
+  }
+
+  private Object fromDBObject(final Schema fieldSchema, final Field field, final String docf, final Object value) {
+    if (value == null) {
+      return null;
+    }
+
+    final Object result;
+
+    switch (fieldSchema.getType()) {
+    case MAP:
+      result = fromCouchDBMap(fieldSchema, field, docf, value);
+      break;
+    case ARRAY:
+      result = fromCouchDBList(fieldSchema, field, docf, value);
+      break;
+    case RECORD:
+      result = fromCouchDBRecord(fieldSchema, docf, value);
+      break;
+    case UNION:
+      result = fromCouchDBUnion(fieldSchema, field, docf, value);
+      break;
+    case ENUM:
+      result = fromCouchDBEnum(fieldSchema, docf, value);
+      break;
+    case BYTES:
+      result = fromCouchDBBytes(docf, value);
+      break;
+    case STRING:
+      result = fromCouchDBString(docf, value);
+      break;
+    case LONG:
+    case DOUBLE:
+    case INT:
+      result = ((Map) value).get(docf);
+      break;
+    default:
+      result = value;
+    }
+    return result;
+  }
+
+  @Override
+  public void flush() {
+    db.executeBulk(bulkDocs);
+    bulkDocs.clear();
+    db.flushBulkBuffer();
+  }
+
+  @Override
+  public void close() {
+    flush();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/main/java/org/apache/gora/couchdb/util/CouchDBObjectMapperFactory.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/main/java/org/apache/gora/couchdb/util/CouchDBObjectMapperFactory.java b/gora-couchdb/src/main/java/org/apache/gora/couchdb/util/CouchDBObjectMapperFactory.java
new file mode 100644
index 0000000..1e447d9
--- /dev/null
+++ b/gora-couchdb/src/main/java/org/apache/gora/couchdb/util/CouchDBObjectMapperFactory.java
@@ -0,0 +1,69 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.ektorp.CouchDbConnector;
+import org.ektorp.impl.ObjectMapperFactory;
+import org.ektorp.impl.jackson.EktorpJacksonModule;
+
+/**
+ *
+ */
+public class CouchDBObjectMapperFactory implements ObjectMapperFactory {
+
+  private ObjectMapper instance;
+  private boolean writeDatesAsTimestamps = false;
+
+  /**
+   * Create a object mapper instance
+   * @return
+   */
+  public synchronized ObjectMapper createObjectMapper() {
+    if (instance == null) {
+      instance = new ObjectMapper();
+      applyDefaultConfiguration(instance);
+    }
+    return instance;
+  }
+
+  /**
+   * Create a object mapper object via couchdb connector
+   *
+   * @param connector
+   * @return
+   */
+  public synchronized ObjectMapper createObjectMapper(CouchDbConnector connector) {
+    this.createObjectMapper();
+    instance.registerModule(new EktorpJacksonModule(connector, instance));
+    return instance;
+  }
+
+  /**
+   * Apply default configuration
+   *
+   * @param om a object mapper object
+   */
+  private void applyDefaultConfiguration(ObjectMapper om) {
+    om.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, this.writeDatesAsTimestamps);
+    om.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/test/conf/gora-couchdb-mapping.xml
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/test/conf/gora-couchdb-mapping.xml b/gora-couchdb/src/test/conf/gora-couchdb-mapping.xml
new file mode 100644
index 0000000..e2e7672
--- /dev/null
+++ b/gora-couchdb/src/test/conf/gora-couchdb-mapping.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   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.
+-->
+
+<gora-otd>
+
+  <class name="org.apache.gora.examples.generated.Employee" keyClass="java.lang.String" table="Employee">
+    <field name="name"/>
+    <field name="dateOfBirth"/>
+    <field name="ssn"/>
+    <field name="salary"/>
+    <field name="boss"/>
+    <field name="webpage"/>
+  </class>
+
+  <class name="org.apache.gora.examples.generated.WebPage" keyClass="java.lang.String" table="WebPage">
+    <field name="url"/>
+    <field name="content"/>
+    <field name="parsedContent"/>
+    <field name="outlinks"/>
+    <field name="headers"/>
+    <field name="metadata"/>
+    <field name="byteData"/>
+    <field name="stringData"/>
+  </class>
+
+
+  <class name="org.apache.gora.examples.generated.TokenDatum" keyClass="java.lang.String">
+    <field name="count"/>
+  </class>
+
+</gora-otd>

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/test/conf/gora.properties
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/test/conf/gora.properties b/gora-couchdb/src/test/conf/gora.properties
new file mode 100644
index 0000000..4bcf6c7
--- /dev/null
+++ b/gora-couchdb/src/test/conf/gora.properties
@@ -0,0 +1,19 @@
+# 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.
+
+gora.datastore.default=org.apache.gora.couchdb.store.CouchDBStore
+gora.datastore.couchdb.server=localhost
+gora.datastore.couchdb.port=5984
+gora.datastore.mapping.file=gora-couchdb-mapping.xml
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/test/java/org/apache/gora/couchdb/GoraCouchDBTestDriver.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/test/java/org/apache/gora/couchdb/GoraCouchDBTestDriver.java b/gora-couchdb/src/test/java/org/apache/gora/couchdb/GoraCouchDBTestDriver.java
new file mode 100644
index 0000000..bb48c83
--- /dev/null
+++ b/gora-couchdb/src/test/java/org/apache/gora/couchdb/GoraCouchDBTestDriver.java
@@ -0,0 +1,78 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.gora.couchdb;
+
+import org.apache.gora.GoraTestDriver;
+import org.apache.gora.couchdb.store.CouchDBParameters;
+import org.apache.gora.couchdb.store.CouchDBStore;
+import org.apache.gora.persistency.Persistent;
+import org.apache.gora.store.DataStore;
+import org.apache.gora.store.DataStoreFactory;
+import org.apache.gora.util.GoraException;
+import org.testcontainers.containers.GenericContainer;
+
+import java.util.Properties;
+
+/**
+ * Helper class for third party tests using gora-couchdb backend.
+ * @see GoraTestDriver for test specifics.
+ * This driver is the base for all test cases that require an CouchDB server.
+ * In this case we use docker container. A docker container is run before tests
+ * and it is stopped after tests.
+ *
+ */
+public class GoraCouchDBTestDriver extends GoraTestDriver {
+
+  private final GenericContainer couchdbContainer;
+  private Properties properties = DataStoreFactory.createProps();
+
+  /**
+   * Default constructor
+   */
+  public GoraCouchDBTestDriver(GenericContainer couchdbContainer) {
+    super(CouchDBStore.class);
+    this.couchdbContainer = couchdbContainer;
+  }
+
+  @Override
+  public void setUpClass() throws Exception {
+    properties.put(CouchDBParameters.PROP_COUCHDB_PORT, couchdbContainer.getMappedPort(5984).toString());
+  }
+
+  /**
+   * Instantiate a new {@link DataStore}. Uses 'null' schema.
+   *
+   * @param keyClass The key class.
+   * @param persistentClass The value class.
+   * @return A new store instance.
+   * @throws GoraException
+   */
+  @Override
+  public <K, T extends Persistent> DataStore<K, T> createDataStore(Class<K> keyClass, Class<T> persistentClass)
+      throws GoraException {
+
+    final DataStore<K, T> dataStore = DataStoreFactory
+        .createDataStore((Class<? extends DataStore<K, T>>) dataStoreClass, keyClass, persistentClass, conf,
+            properties);
+    dataStores.add(dataStore);
+    log.info("Datastore for {} was added.", persistentClass);
+    return dataStore;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/gora-couchdb/src/test/java/org/apache/gora/couchdb/package-info.java
----------------------------------------------------------------------
diff --git a/gora-couchdb/src/test/java/org/apache/gora/couchdb/package-info.java b/gora-couchdb/src/test/java/org/apache/gora/couchdb/package-info.java
new file mode 100644
index 0000000..ae4cd6c
--- /dev/null
+++ b/gora-couchdb/src/test/java/org/apache/gora/couchdb/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+/**
+ * Tests for <code>gora-couchdb</code> including
+ * the test driver for {@link org.apache.gora.couchdb.store.TestCouchDBStore}
+ */
+package org.apache.gora.couchdb;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/gora/blob/d6c820b2/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 5221fd1..e705894 100644
--- a/pom.xml
+++ b/pom.xml
@@ -666,6 +666,7 @@
     <module>gora-jcache</module>
     <!-- module>gora-lucene</module -->
     <module>gora-dynamodb</module>
+    <module>gora-couchdb</module>
     <!--module>gora-sql</module -->
     <module>gora-maven-plugin</module>
     <module>gora-mongodb</module>
@@ -830,6 +831,12 @@
 
       <dependency>
         <groupId>org.apache.gora</groupId>
+        <artifactId>gora-couchdb</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.apache.gora</groupId>
         <artifactId>gora-jcache</artifactId>
         <version>${project.version}</version>
       </dependency>


Mime
View raw message