You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2023/03/01 19:20:12 UTC
[couchdb] 07/07: WIP the great shuffle
This is an automated email from the ASF dual-hosted git repository.
rnewson pushed a commit to branch import-nouveau-great-shuffle-wip
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit aaa4ed6185825d92fe481b3220661665eff15cd0
Author: Robert Newson <rn...@apache.org>
AuthorDate: Wed Mar 1 19:19:41 2023 +0000
WIP the great shuffle
---
.../couchdb/nouveau/api/document/DoubleField.java | 77 -----------
.../apache/couchdb/nouveau/api/document/Field.java | 47 -------
.../nouveau/api/document/StoredDoubleField.java | 41 ------
.../couchdb/nouveau/api/document/StringField.java | 74 -----------
.../couchdb/nouveau/api/document/TextField.java | 74 -----------
.../apache/couchdb/nouveau/core/LuceneBundle.java | 9 --
.../nouveau/api/DocumentUpdateRequestTest.java | 65 ---------
java/nouveau/{api => base}/pom.xml | 4 +-
.../couchdb/nouveau/IndexManagerFactory.java} | 65 +++++----
.../nouveau/NouveauApplicationConfiguration.java} | 28 ++--
.../java/org/apache/couchdb/nouveau/api/After.java | 0
.../apache/couchdb/nouveau/api/AnalyzeRequest.java | 0
.../couchdb/nouveau/api/AnalyzeResponse.java | 0
.../couchdb/nouveau/api/DocumentDeleteRequest.java | 22 ---
.../couchdb/nouveau/api/DocumentUpdateRequest.java | 44 +-----
.../apache/couchdb/nouveau/api/DoubleRange.java | 0
.../couchdb/nouveau/api/IndexDefinition.java | 0
.../org/apache/couchdb/nouveau/api/IndexInfo.java | 14 +-
.../java/org/apache/couchdb/nouveau/api/Range.java | 0
.../org/apache/couchdb/nouveau/api/SearchHit.java | 10 +-
.../apache/couchdb/nouveau/api/SearchRequest.java | 0
.../apache/couchdb/nouveau/api/SearchResults.java | 8 +-
.../org/apache/couchdb/nouveau/core/IOUtils.java | 0
.../org/apache/couchdb/nouveau/core/Index.java | 10 +-
.../apache/couchdb/nouveau/core/IndexLoader.java} | 14 +-
.../apache/couchdb/nouveau/core/IndexManager.java | 47 +++----
.../nouveau/core/UpdatesOutOfOrderException.java | 0
.../nouveau/core/ser/AfterDeserializer.java | 0
.../couchdb/nouveau/core/ser/AfterSerializer.java | 0
.../nouveau/resources/BaseAnalyzeResource.java} | 24 +---
.../nouveau/resources/BaseIndexResource.java} | 41 +++---
.../couchdb/nouveau/api/SearchRequestTest.java | 0
.../resources/fixtures/DocumentUpdateRequest.json | 0
.../src/test/resources/fixtures/SearchRequest.json | 0
java/nouveau/lucene4/pom.xml | 4 +-
.../couchdb/nouveau/core/lucene4/Dummy4.java | 25 ----
.../core/lucene4/IndexableFieldDeserializer.java | 30 -----
.../couchdb/nouveau/core/lucene4/Lucene4.java | 99 --------------
.../nouveau/core/lucene4/Lucene4Bundle.java | 25 ----
.../nouveau/core/lucene4/Lucene4Module.java | 15 ---
.../lucene4/core/IndexableFieldDeserializer.java | 78 +++++++++++
.../lucene4/core/IndexableFieldSerializer.java | 59 ++++++++
.../core}/Lucene4AnalyzerFactory.java | 4 +-
.../nouveau/lucene4/core/Lucene4Bundle.java | 45 +++++++
.../lucene4 => lucene4/core}/Lucene4Index.java | 78 +++--------
.../nouveau/lucene4/core/Lucene4Module.java | 35 +++++
.../core}/Lucene4QueryParser.java | 2 +-
.../core}/ParallelSearcherFactory.java | 2 +-
.../lucene4 => lucene4/core}/PerFieldAnalyzer.java | 2 +-
.../nouveau/lucene4/core/QueryDeserializer.java | 41 ++++++
.../{core/lucene4 => lucene4/core}/Utils.java | 6 +-
.../nouveau/lucene4/resources/AnalyzeResource.java | 62 +++++++++
.../nouveau/lucene4/resources/IndexResource.java | 68 ++++++++++
.../core}/Lucene4AnalyzerFactoryTest.java | 2 +-
java/nouveau/lucene9/pom.xml | 4 +-
java/nouveau/pom.xml | 2 +-
java/nouveau/server/nouveau.yaml | 9 +-
java/nouveau/server/pom.xml | 4 +-
.../apache/couchdb/nouveau/NouveauApplication.java | 78 ++---------
.../couchdb/nouveau/health/AnalyzeHealthCheck.java | 45 -------
.../nouveau/health/IndexManagerHealthCheck.java | 52 --------
.../apache/couchdb/nouveau/IntegrationTest.java | 137 -------------------
.../couchdb/nouveau/core/IndexManagerTest.java | 76 -----------
.../nouveau/core/ser/SerializationTest.java | 148 ---------------------
share/server/nouveau.js | 9 +-
65 files changed, 567 insertions(+), 1397 deletions(-)
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java
deleted file mode 100644
index 11f662233..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/DoubleField.java
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import javax.validation.constraints.NotNull;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonInclude.Include;
-
-import io.dropwizard.jackson.JsonSnakeCase;
-
-@JsonSnakeCase
-@JsonInclude(value=Include.NON_DEFAULT)
-public final class DoubleField extends Field {
-
- private final double value;
-
- private final boolean store;
-
- private final boolean facet;
-
- private final boolean sortable;
-
- @JsonCreator
- public DoubleField(
- @NotNull @JsonProperty("name") final String name,
- @NotNull @JsonProperty("value") final double value,
- @JsonProperty("store") final boolean store,
- @JsonProperty("facet") final boolean facet,
- @JsonProperty("sortable") final boolean sortable) {
- super(name);
- this.value = value;
- this.store = store;
- this.facet = facet;
- this.sortable = sortable;
- }
-
- @JsonProperty
- public double getValue() {
- return value;
- }
-
- @JsonProperty
- public boolean isStore() {
- return store;
- }
-
- @JsonProperty
- public boolean isFacet() {
- return facet;
- }
-
- @JsonProperty
- public boolean isSortable() {
- return sortable;
- }
-
- @Override
- public String toString() {
- return "DoubleField [name=" + name + ", value=" + value + ", store=" + store + ", facet=" + facet + ", sortable=" + sortable
- + "]";
- }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java
deleted file mode 100644
index 2fc90b29e..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/Field.java
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-
-import io.dropwizard.jackson.JsonSnakeCase;
-
-@JsonSnakeCase
-@JsonTypeInfo(
- use = JsonTypeInfo.Id.NAME,
- include = JsonTypeInfo.As.PROPERTY,
- property = "@type")
-@JsonSubTypes({
- @JsonSubTypes.Type(value = DoubleField.class, name = "double"),
- @JsonSubTypes.Type(value = StoredDoubleField.class, name = "stored_double"),
- @JsonSubTypes.Type(value = StoredStringField.class, name = "stored_string"),
- @JsonSubTypes.Type(value = StringField.class, name = "string"),
- @JsonSubTypes.Type(value = TextField.class, name = "text"),
-})
-public abstract class Field {
-
- protected final String name;
-
- protected Field(final String name) {
- this.name = name;
- }
-
- @JsonProperty
- public String getName() {
- return name;
- }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java
deleted file mode 100644
index b880f1742..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredDoubleField.java
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import javax.validation.constraints.NotNull;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public final class StoredDoubleField extends Field {
-
- private final double value;
-
- @JsonCreator
- public StoredDoubleField(@NotNull @JsonProperty("name") final String name, @NotNull @JsonProperty("value") final double value) {
- super(name);
- this.value = value;
- }
-
- @JsonProperty
- public double getValue() {
- return value;
- }
-
- @Override
- public String toString() {
- return "StoredDoubleField [value=" + value + "]";
- }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java
deleted file mode 100644
index d03a6f38a..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StringField.java
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import javax.validation.constraints.NotNull;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonInclude.Include;
-
-@JsonInclude(value=Include.NON_DEFAULT)
-public final class StringField extends Field {
-
- private final String value;
-
- private final boolean store;
-
- private final boolean facet;
-
- private final boolean sortable;
-
- @JsonCreator
- public StringField(
- @NotNull @JsonProperty("name") final String name,
- @NotNull @JsonProperty("value") final String value,
- @JsonProperty("store") final boolean store,
- @JsonProperty("facet") final boolean facet,
- @JsonProperty("sortable") final boolean sortable) {
- super(name);
- this.value = value;
- this.store = store;
- this.facet = facet;
- this.sortable = sortable;
- }
-
- @JsonProperty
- public String getValue() {
- return value;
- }
-
- @JsonProperty
- public boolean isStore() {
- return store;
- }
-
- @JsonProperty
- public boolean isFacet() {
- return facet;
- }
-
- @JsonProperty
- public boolean isSortable() {
- return sortable;
- }
-
- @Override
- public String toString() {
- return "StringField [name=" + name + ", value=" + value + ", store=" + store + ", facet=" + facet + ", sortable=" + sortable
- + "]";
- }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java
deleted file mode 100644
index 0c8903c77..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/TextField.java
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api.document;
-
-import javax.validation.constraints.NotNull;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonInclude.Include;
-
-@JsonInclude(value=Include.NON_DEFAULT)
-public final class TextField extends Field {
-
- private final String value;
-
- private final boolean store;
-
- private final boolean facet;
-
- private final boolean sortable;
-
- @JsonCreator
- public TextField(
- @NotNull @JsonProperty("name") final String name,
- @NotNull @JsonProperty("value") final String value,
- @JsonProperty("store") final boolean store,
- @JsonProperty("facet") final boolean facet,
- @JsonProperty("sortable") final boolean sortable) {
- super(name);
- this.value = value;
- this.store = store;
- this.facet = facet;
- this.sortable = sortable;
- }
-
- @JsonProperty
- public String getValue() {
- return value;
- }
-
- @JsonProperty
- public boolean isStore() {
- return store;
- }
-
- @JsonProperty
- public boolean isFacet() {
- return facet;
- }
-
- @JsonProperty
- public boolean isSortable() {
- return sortable;
- }
-
- @Override
- public String toString() {
- return "TextField [name=" + name + ", value=" + value + ", store=" + store + ", facet=" + facet + ", sortable=" + sortable
- + "]";
- }
-
-}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/LuceneBundle.java b/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/LuceneBundle.java
deleted file mode 100644
index c94e99e56..000000000
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/LuceneBundle.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.apache.couchdb.nouveau.core;
-
-import io.dropwizard.ConfiguredBundle;
-
-public interface LuceneBundle<T> extends ConfiguredBundle<T> {
-
- Lucene getLucene();
-
-}
diff --git a/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java b/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java
deleted file mode 100644
index 1c79f8fe1..000000000
--- a/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequestTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.api;
-
-import static io.dropwizard.testing.FixtureHelpers.fixture;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.couchdb.nouveau.api.document.DoubleField;
-import org.apache.couchdb.nouveau.api.document.Field;
-import org.apache.couchdb.nouveau.api.document.StringField;
-import org.apache.couchdb.nouveau.api.document.TextField;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-public class DocumentUpdateRequestTest {
-
- private static ObjectMapper mapper;
-
- @BeforeAll
- public static void setupMapper() {
- System.err.println("farts");
- mapper = new ObjectMapper();
- }
-
- @Test
- public void testSerialisation() throws Exception {
- DocumentUpdateRequest request = asObject();
- final String expected = mapper.writeValueAsString(
- mapper.readValue(fixture("fixtures/DocumentUpdateRequest.json"), DocumentUpdateRequest.class));
- assertThat(mapper.writeValueAsString(request)).isEqualTo(expected);
- }
-
- @Test
- public void testDeserialisation() throws Exception {
- DocumentUpdateRequest request = asObject();
- assertThat(mapper.readValue(fixture("fixtures/DocumentUpdateRequest.json"), DocumentUpdateRequest.class).toString())
- .isEqualTo(request.toString());
- }
-
- private DocumentUpdateRequest asObject() {
- final List<Field> fields = new ArrayList<Field>();
- fields.add(new StringField("stringfoo", "bar", true, false, false));
- fields.add(new TextField("textfoo", "hello there", true, false, false));
- fields.add(new DoubleField("doublefoo", 12, false, false, false));
- return new DocumentUpdateRequest(12, null, fields);
- }
-
-}
diff --git a/java/nouveau/api/pom.xml b/java/nouveau/base/pom.xml
similarity index 95%
rename from java/nouveau/api/pom.xml
rename to java/nouveau/base/pom.xml
index ed1acd417..a54c844b8 100644
--- a/java/nouveau/api/pom.xml
+++ b/java/nouveau/base/pom.xml
@@ -2,10 +2,10 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.couchdb.nouveau</groupId>
- <artifactId>api</artifactId>
+ <artifactId>base</artifactId>
<name>${project.artifactId}</name>
<version>1.0-SNAPSHOT</version>
- <description>Nouveau API classes</description>
+ <description>Nouveau Base classes</description>
<inceptionYear>2023</inceptionYear>
<parent>
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/IndexManagerFactory.java
similarity index 59%
rename from java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/IndexManagerFactory.java
index 5be8c5a21..3f5c38f9b 100644
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/IndexManagerFactory.java
@@ -13,73 +13,90 @@
package org.apache.couchdb.nouveau;
-import java.net.URL;
import java.nio.file.Path;
-import java.util.Arrays;
+import java.util.concurrent.ScheduledExecutorService;
+import javax.validation.Valid;
import javax.validation.constraints.Min;
-import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
+import org.apache.couchdb.nouveau.core.IndexManager;
+
import com.fasterxml.jackson.annotation.JsonProperty;
-import io.dropwizard.Configuration;
+import io.dropwizard.setup.Environment;
-public class NouveauApplicationConfiguration extends Configuration {
+public final class IndexManagerFactory {
@Min(10)
- private int maxIndexesOpen = -1;
+ private int maxIndexesOpen = 10;
@Min(10)
- private int commitIntervalSeconds = -1;
+ private int commitIntervalSeconds = 10;
@Min(30)
- private int idleSeconds = -1;
+ private int idleSeconds = 30;
+ @Valid
@NotNull
- private Path rootDir = null;
+ private Path rootDir;
@JsonProperty
- public void setMaxIndexesOpen(int maxIndexesOpen) {
- this.maxIndexesOpen = maxIndexesOpen;
- }
-
public int getMaxIndexesOpen() {
return maxIndexesOpen;
}
@JsonProperty
- public void setCommitIntervalSeconds(int commitIntervalSeconds) {
- this.commitIntervalSeconds = commitIntervalSeconds;
+ public void setMaxIndexesOpen(int maxIndexesOpen) {
+ this.maxIndexesOpen = maxIndexesOpen;
}
+ @JsonProperty
public int getCommitIntervalSeconds() {
return commitIntervalSeconds;
}
@JsonProperty
- public void setIdleSeconds(int idleSeconds) {
- this.idleSeconds = idleSeconds;
+ public void setCommitIntervalSeconds(int commitIntervalSeconds) {
+ this.commitIntervalSeconds = commitIntervalSeconds;
}
+ @JsonProperty
public int getIdleSeconds() {
return idleSeconds;
}
@JsonProperty
- public void setRootDir(Path rootDir) {
- this.rootDir = rootDir;
+ public void setIdleSeconds(int idleSeconds) {
+ this.idleSeconds = idleSeconds;
}
+ @JsonProperty
public Path getRootDir() {
return rootDir;
}
- @Override
- public String toString() {
- return "NouveauApplicationConfiguration [maxIndexesOpen=" + maxIndexesOpen + ", commitIntervalSeconds="
- + commitIntervalSeconds + ", idleSeconds=" + idleSeconds + ", rootDir=" + rootDir
- + "]";
+ @JsonProperty
+ public void setRootDir(Path rootDir) {
+ this.rootDir = rootDir;
+ }
+
+ public IndexManager build(final Environment environment) {
+ final ScheduledExecutorService scheduler = environment.lifecycle()
+ .scheduledExecutorService("index-manager-scheduler-%d")
+ .threads(10)
+ .build();
+
+ final IndexManager result = new IndexManager();
+ result.setCommitIntervalSeconds(commitIntervalSeconds);
+ result.setIdleSeconds(idleSeconds);
+ result.setMaxIndexesOpen(maxIndexesOpen);
+ result.setObjectMapper(environment.getObjectMapper());
+ result.setRootDir(rootDir);
+ result.setScheduler(scheduler);
+
+ environment.lifecycle().manage(result);
+ return result;
}
}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
similarity index 56%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
index a93e3fade..11602cdbc 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/document/StoredStringField.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
@@ -11,31 +11,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.api.document;
+package org.apache.couchdb.nouveau;
+import javax.validation.Valid;
import javax.validation.constraints.NotNull;
-import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-public final class StoredStringField extends Field {
+import io.dropwizard.Configuration;
- private String value;
+public class NouveauApplicationConfiguration extends Configuration {
- @JsonCreator
- public StoredStringField(@NotNull @JsonProperty("name") final String name, @NotNull @JsonProperty("value") final String value) {
- super(name);
- this.value = value;
- }
+ @Valid
+ @NotNull
+ private IndexManagerFactory indexManagerFactory;
@JsonProperty
- public String getValue() {
- return value;
+ public IndexManagerFactory getIndexManagerFactory() {
+ return indexManagerFactory;
}
- @Override
- public String toString() {
- return "StoredStringField [value=" + value + "]";
+ @JsonProperty
+ public void setIndexManagerFactory(IndexManagerFactory indexManagerFactory) {
+ this.indexManagerFactory = indexManagerFactory;
}
+
+
}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/After.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/After.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/After.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/After.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeRequest.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeRequest.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeRequest.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeRequest.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeResponse.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeResponse.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeResponse.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/AnalyzeResponse.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DocumentDeleteRequest.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DocumentDeleteRequest.java
similarity index 67%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DocumentDeleteRequest.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DocumentDeleteRequest.java
index f7a4c572b..045aa1944 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DocumentDeleteRequest.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DocumentDeleteRequest.java
@@ -38,28 +38,6 @@ public class DocumentDeleteRequest {
return seq;
}
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (int) (seq ^ (seq >>> 32));
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- DocumentDeleteRequest other = (DocumentDeleteRequest) obj;
- if (seq != other.seq)
- return false;
- return true;
- }
-
@Override
public String toString() {
return "DocumentDeleteRequest [seq=" + seq + "]";
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequest.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequest.java
similarity index 55%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequest.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequest.java
index e5871d68c..2e66fe4e2 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequest.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DocumentUpdateRequest.java
@@ -18,14 +18,12 @@ import java.util.Collection;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
-import org.apache.couchdb.nouveau.api.document.Field;
-
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.jackson.JsonSnakeCase;
@JsonSnakeCase
-public class DocumentUpdateRequest {
+public class DocumentUpdateRequest<T> {
@Min(1)
private long seq;
@@ -33,13 +31,13 @@ public class DocumentUpdateRequest {
private String partition;
@NotEmpty
- private Collection<Field> fields;
+ private Collection<T> fields;
public DocumentUpdateRequest() {
// Jackson deserialization
}
- public DocumentUpdateRequest(long seq, String partition, Collection<Field> fields) {
+ public DocumentUpdateRequest(long seq, String partition, Collection<T> fields) {
this.seq = seq;
this.partition = partition;
this.fields = fields;
@@ -60,44 +58,10 @@ public class DocumentUpdateRequest {
}
@JsonProperty
- public Collection<Field> getFields() {
+ public Collection<T> getFields() {
return fields;
}
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (int) (seq ^ (seq >>> 32));
- result = prime * result + ((partition == null) ? 0 : partition.hashCode());
- result = prime * result + ((fields == null) ? 0 : fields.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- DocumentUpdateRequest other = (DocumentUpdateRequest) obj;
- if (seq != other.seq)
- return false;
- if (partition == null) {
- if (other.partition != null)
- return false;
- } else if (!partition.equals(other.partition))
- return false;
- if (fields == null) {
- if (other.fields != null)
- return false;
- } else if (!fields.equals(other.fields))
- return false;
- return true;
- }
-
@Override
public String toString() {
return "DocumentUpdateRequest [seq=" + seq + ", partition=" + partition + ", fields=" + fields + "]";
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DoubleRange.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DoubleRange.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/DoubleRange.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/DoubleRange.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/IndexDefinition.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/IndexDefinition.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/IndexDefinition.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/IndexDefinition.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/IndexInfo.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/IndexInfo.java
similarity index 80%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/IndexInfo.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/IndexInfo.java
index 2bfa096a6..55e7174ec 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/IndexInfo.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/IndexInfo.java
@@ -13,8 +13,6 @@
package org.apache.couchdb.nouveau.api;
-import javax.validation.constraints.NotNull;
-
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.jackson.JsonSnakeCase;
@@ -22,27 +20,25 @@ import io.dropwizard.jackson.JsonSnakeCase;
@JsonSnakeCase
public class IndexInfo {
- @NotNull
- private Long updateSeq;
+ private long updateSeq;
- @NotNull
- private Integer numDocs;
+ private int numDocs;
public IndexInfo() {
}
- public IndexInfo(final Long updateSeq, final Integer numDocs) {
+ public IndexInfo(final long updateSeq, final int numDocs) {
this.updateSeq = updateSeq;
this.numDocs = numDocs;
}
@JsonProperty
- public Integer getNumDocs() {
+ public int getNumDocs() {
return numDocs;
}
@JsonProperty
- public Long getUpdateSeq() {
+ public long getUpdateSeq() {
return updateSeq;
}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/Range.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/Range.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/Range.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/Range.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
similarity index 87%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
index dbb6c7a28..a667fc7ba 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchHit.java
@@ -18,12 +18,10 @@ import java.util.Collection;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
-import org.apache.couchdb.nouveau.api.document.Field;
-
import io.dropwizard.jackson.JsonSnakeCase;
@JsonSnakeCase
-public class SearchHit {
+public class SearchHit<T> {
@NotEmpty
private String id;
@@ -32,12 +30,12 @@ public class SearchHit {
private After order;
@NotNull
- private Collection<@NotNull Field> fields;
+ private Collection<@NotNull T> fields;
public SearchHit() {
}
- public SearchHit(final String id, final After order, final Collection<Field> fields) {
+ public SearchHit(final String id, final After order, final Collection<T> fields) {
this.id = id;
this.order = order;
this.fields = fields;
@@ -51,7 +49,7 @@ public class SearchHit {
return order;
}
- public Collection<Field> getFields() {
+ public Collection<T> getFields() {
return fields;
}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchRequest.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
similarity index 92%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
index 7e68fe944..157572ee3 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/api/SearchResults.java
@@ -24,7 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.jackson.JsonSnakeCase;
@JsonSnakeCase
-public class SearchResults {
+public class SearchResults<T> {
@Min(0)
private long totalHits;
@@ -33,7 +33,7 @@ public class SearchResults {
private String totalHitsRelation;
@NotNull
- private List<@NotNull SearchHit> hits;
+ private List<@NotNull SearchHit<T>> hits;
private Map<@NotNull String, Map<@NotNull String, Number>> counts;
@@ -59,12 +59,12 @@ public class SearchResults {
this.totalHitsRelation = totalHitsRelation;
}
- public void setHits(final List<SearchHit> hits) {
+ public void setHits(final List<SearchHit<T>> hits) {
this.hits = hits;
}
@JsonProperty
- public List<SearchHit> getHits() {
+ public List<SearchHit<T>> getHits() {
return hits;
}
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/core/IOUtils.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IOUtils.java
similarity index 100%
rename from java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/core/IOUtils.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IOUtils.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/Index.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/Index.java
similarity index 91%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/Index.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/Index.java
index b4ca00928..e037ddc95 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/Index.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/Index.java
@@ -23,7 +23,7 @@ import org.apache.couchdb.nouveau.api.IndexInfo;
import org.apache.couchdb.nouveau.api.SearchRequest;
import org.apache.couchdb.nouveau.api.SearchResults;
-public abstract class Index implements Closeable {
+public abstract class Index<T> implements Closeable {
private long updateSeq;
@@ -45,14 +45,14 @@ public abstract class Index implements Closeable {
protected abstract int doNumDocs() throws IOException;
- public final synchronized void update(final String docId, final DocumentUpdateRequest request) throws IOException {
+ public final synchronized void update(final String docId, final DocumentUpdateRequest<T> request) throws IOException {
assertUpdateSeqIsLower(request.getSeq());
updateLastUsed();
doUpdate(docId, request);
incrementUpdateSeq(request.getSeq());
}
- protected abstract void doUpdate(final String docId, final DocumentUpdateRequest request) throws IOException;
+ protected abstract void doUpdate(final String docId, final DocumentUpdateRequest<T> request) throws IOException;
public final synchronized void delete(final String docId, final DocumentDeleteRequest request) throws IOException {
assertUpdateSeqIsLower(request.getSeq());
@@ -63,12 +63,12 @@ public abstract class Index implements Closeable {
protected abstract void doDelete(final String docId, final DocumentDeleteRequest request) throws IOException;
- public final SearchResults search(final SearchRequest request) throws IOException {
+ public final SearchResults<T> search(final SearchRequest request) throws IOException {
updateLastUsed();
return doSearch(request);
}
- protected abstract SearchResults doSearch(final SearchRequest request) throws IOException;
+ protected abstract SearchResults<T> doSearch(final SearchRequest request) throws IOException;
public final boolean commit() throws IOException {
final long updateSeq;
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/Lucene.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IndexLoader.java
similarity index 65%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/Lucene.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IndexLoader.java
index f98335ae4..8fe2ecc76 100644
--- a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/Lucene.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IndexLoader.java
@@ -15,20 +15,12 @@ package org.apache.couchdb.nouveau.core;
import java.io.IOException;
import java.nio.file.Path;
-import java.util.List;
-
-import javax.ws.rs.WebApplicationException;
import org.apache.couchdb.nouveau.api.IndexDefinition;
-public interface Lucene {
-
- int getMajor();
-
- List<String> analyze(final String analyzer, final String text) throws IOException;
-
- void validate(final IndexDefinition indexDefinition) throws WebApplicationException;
+@FunctionalInterface
+public interface IndexLoader<T> {
- Index open(final Path path, final IndexDefinition indexDefinition) throws IOException;
+ Index<T> apply(final Path path, final IndexDefinition indexDefinition) throws IOException;
}
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
similarity index 90%
rename from java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
index d90fe2e90..8c8ac9c6b 100644
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
@@ -13,6 +13,8 @@
package org.apache.couchdb.nouveau.core;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
@@ -30,8 +32,6 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.stream.Stream;
import javax.ws.rs.WebApplicationException;
@@ -58,12 +58,11 @@ public final class IndexManager implements Managed {
private Path rootDir;
- private Map<Integer, Lucene> lucenes;
-
private ObjectMapper objectMapper;
private ScheduledExecutorService scheduler;
+ @SuppressWarnings("rawtypes")
private Map<String, Index> cache;
private Map<String, Collection<ScheduledFuture<?>>> scheduledFutures;
@@ -72,7 +71,8 @@ public final class IndexManager implements Managed {
// by the hashCode of the index's name.
private ReadWriteLock[] locks;
- public Index acquire(final String name) throws IOException {
+ @SuppressWarnings("rawtypes")
+ public Index acquire(final String name, final IndexLoader loader) throws IOException {
if (!exists(name)) {
throw new WebApplicationException("Index does not exist", Status.NOT_FOUND);
}
@@ -106,9 +106,8 @@ public final class IndexManager implements Managed {
LOGGER.info("opening {}", name);
final Path path = indexPath(name);
- final IndexDefinition indexDefinition = objectMapper.readValue(indexDefinitionPath(name).toFile(),
- IndexDefinition.class);
- final Index newIndex = luceneFor(indexDefinition).open(path, indexDefinition);
+ final IndexDefinition indexDefinition = loadIndexDefinition(name);
+ final Index newIndex = loader.apply(path, indexDefinition);
final Runnable committer = () -> {
try {
@@ -119,7 +118,8 @@ public final class IndexManager implements Managed {
LOGGER.error("I/O exception when committing " + name, e);
}
};
- final ScheduledFuture<?> committerFuture = scheduler.scheduleWithFixedDelay(committer, commitIntervalSeconds, commitIntervalSeconds, SECONDS);
+ final ScheduledFuture<?> committerFuture = scheduler.scheduleWithFixedDelay(committer,
+ commitIntervalSeconds, commitIntervalSeconds, SECONDS);
final Runnable idler = () -> {
if (newIndex.secondsSinceLastUse() >= idleSeconds) {
@@ -131,7 +131,8 @@ public final class IndexManager implements Managed {
}
}
};
- final ScheduledFuture<?> idlerFuture = scheduler.scheduleWithFixedDelay(idler, idleSeconds, idleSeconds, SECONDS);
+ final ScheduledFuture<?> idlerFuture = scheduler.scheduleWithFixedDelay(idler, idleSeconds, idleSeconds,
+ SECONDS);
synchronized (cache) {
cache.put(name, newIndex);
@@ -144,6 +145,7 @@ public final class IndexManager implements Managed {
}
}
+ @SuppressWarnings("rawtypes")
public void release(final String name, final Index index) throws IOException {
writeLock(name).lock();
try {
@@ -168,6 +170,7 @@ public final class IndexManager implements Managed {
}
}
+ @SuppressWarnings("rawtypes")
private void doRelease(final String name, final Index index) throws IOException {
index.decRef();
if (!index.isOpen()) {
@@ -196,7 +199,7 @@ public final class IndexManager implements Managed {
throw new WebApplicationException("Index already exists", Status.EXPECTATION_FAILED);
}
// Validate index definiton
- luceneFor(indexDefinition).validate(indexDefinition);
+ // TODO luceneFor(indexDefinition).validate(indexDefinition);
// Persist definition
final Path path = indexDefinitionPath(name);
@@ -231,6 +234,7 @@ public final class IndexManager implements Managed {
}
}
+ @SuppressWarnings("rawtypes")
private void deleteIndex(final String name) throws IOException {
final Index index;
readLock(name).lock();
@@ -284,10 +288,6 @@ public final class IndexManager implements Managed {
this.rootDir = rootDir;
}
- public void setLucenes(final Map<Integer, Lucene> lucenes) {
- this.lucenes = lucenes;
- }
-
public void setObjectMapper(final ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@@ -297,6 +297,7 @@ public final class IndexManager implements Managed {
}
@Override
+ @SuppressWarnings("rawtypes")
public void start() throws IOException {
final int lockCount = Math.max(1000, maxIndexesOpen / 10);
locks = new ReadWriteLock[lockCount];
@@ -324,7 +325,7 @@ public final class IndexManager implements Managed {
try {
release(evictee.getKey(), evictee.getValue());
} catch (final IOException e) {
- LOGGER.error("error evicting " +evictee.getKey(), e);
+ LOGGER.error("error evicting " + evictee.getKey(), e);
}
}
};
@@ -332,6 +333,7 @@ public final class IndexManager implements Managed {
}
@Override
+ @SuppressWarnings("rawtypes")
public void stop() throws IOException {
synchronized (cache) {
for (final Index index : cache.values()) {
@@ -353,6 +355,10 @@ public final class IndexManager implements Managed {
return indexRootPath(name).resolve("index");
}
+ private IndexDefinition loadIndexDefinition(final String name) throws IOException {
+ return objectMapper.readValue(indexDefinitionPath(name).toFile(), IndexDefinition.class);
+ }
+
private Path indexRootPath(final String name) {
final Path result = rootDir.resolve(name).normalize();
if (result.startsWith(rootDir)) {
@@ -362,13 +368,4 @@ public final class IndexManager implements Managed {
Status.BAD_REQUEST);
}
- private Lucene luceneFor(final IndexDefinition indexDefinition) {
- final int luceneMajor = indexDefinition.getLuceneMajor();
- final Lucene result = lucenes.get(luceneMajor);
- if (result == null) {
- throw new WebApplicationException("Lucene major version " + luceneMajor + " not valid", Status.BAD_REQUEST);
- }
- return result;
- }
-
}
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/UpdatesOutOfOrderException.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/UpdatesOutOfOrderException.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/UpdatesOutOfOrderException.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/UpdatesOutOfOrderException.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterDeserializer.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterDeserializer.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterDeserializer.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterDeserializer.java
diff --git a/java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterSerializer.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterSerializer.java
similarity index 100%
rename from java/nouveau/api/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterSerializer.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/core/ser/AfterSerializer.java
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/resources/BaseAnalyzeResource.java
similarity index 54%
rename from java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/resources/BaseAnalyzeResource.java
index 4b532a8b7..a92a3d20d 100644
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/resources/AnalyzeResource.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/resources/BaseAnalyzeResource.java
@@ -14,45 +14,25 @@
package org.apache.couchdb.nouveau.resources;
import java.io.IOException;
-import java.util.List;
-import java.util.Map;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
-import javax.ws.rs.Path;
import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response.Status;
import org.apache.couchdb.nouveau.api.AnalyzeRequest;
import org.apache.couchdb.nouveau.api.AnalyzeResponse;
-import org.apache.couchdb.nouveau.core.Lucene;
import com.codahale.metrics.annotation.Timed;
-@Path("/analyze")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
-public class AnalyzeResource {
-
- private final Map<Integer, Lucene> lucenes;
-
- public AnalyzeResource(Map<Integer, Lucene> lucenes) {
- this.lucenes = lucenes;
- }
+public abstract class BaseAnalyzeResource {
@POST
@Timed
- public AnalyzeResponse analyzeText(@NotNull @Valid AnalyzeRequest analyzeRequest) throws IOException {
- final Lucene lucene = lucenes.get(analyzeRequest.getLuceneMajor());
- if (lucene == null) {
- throw new WebApplicationException("Lucene major version " + analyzeRequest.getLuceneMajor() + " not valid", Status.BAD_REQUEST);
- }
- final List<String> tokens = lucene.analyze(analyzeRequest.getAnalyzer(), analyzeRequest.getText());
- return new AnalyzeResponse(tokens);
- }
+ public abstract AnalyzeResponse analyzeText(@NotNull @Valid AnalyzeRequest analyzeRequest) throws IOException;
}
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/resources/BaseIndexResource.java
similarity index 65%
rename from java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java
rename to java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/resources/BaseIndexResource.java
index d28ac2266..2b59665f7 100644
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java
+++ b/java/nouveau/base/src/main/java/org/apache/couchdb/nouveau/resources/BaseIndexResource.java
@@ -14,7 +14,6 @@
package org.apache.couchdb.nouveau.resources;
import java.io.IOException;
-import java.util.concurrent.ExecutionException;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@@ -35,26 +34,26 @@ import org.apache.couchdb.nouveau.api.IndexInfo;
import org.apache.couchdb.nouveau.api.SearchRequest;
import org.apache.couchdb.nouveau.api.SearchResults;
import org.apache.couchdb.nouveau.core.Index;
+import org.apache.couchdb.nouveau.core.IndexLoader;
import org.apache.couchdb.nouveau.core.IndexManager;
import com.codahale.metrics.annotation.Timed;
-@Path("/index/{name}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
-public class IndexResource {
+public abstract class BaseIndexResource<T> {
- private final IndexManager indexManager;
+ protected final IndexManager indexManager;
- public IndexResource(final IndexManager indexManager) {
+ protected BaseIndexResource(final IndexManager indexManager) {
this.indexManager = indexManager;
}
@GET
@SuppressWarnings("resource")
- public IndexInfo indexInfo(@PathParam("name") String name)
- throws IOException, InterruptedException, ExecutionException {
- final Index index = indexManager.acquire(name);
+ public final IndexInfo indexInfo(@PathParam("name") String name)
+ throws Exception {
+ final Index<T> index = indexManager.acquire(name, indexLoader());
try {
return index.info();
} finally {
@@ -63,12 +62,12 @@ public class IndexResource {
}
@DELETE
- public void deletePath(@PathParam("name") String path) throws IOException {
+ public final void deletePath(@PathParam("name") String path) throws IOException {
indexManager.deleteAll(path);
}
@PUT
- public void createIndex(@PathParam("name") String name, @NotNull @Valid IndexDefinition indexDefinition)
+ public final void createIndex(@PathParam("name") String name, @NotNull @Valid IndexDefinition indexDefinition)
throws IOException {
indexManager.create(name, indexDefinition);
}
@@ -76,10 +75,10 @@ public class IndexResource {
@DELETE
@Timed
@Path("/doc/{docId}")
- public void deleteDoc(@PathParam("name") String name, @PathParam("docId") String docId,
+ public final void deleteDoc(@PathParam("name") String name, @PathParam("docId") String docId,
@NotNull @Valid final DocumentDeleteRequest request)
- throws IOException, InterruptedException, ExecutionException {
- final Index index = indexManager.acquire(name);
+ throws Exception {
+ final Index<T> index = indexManager.acquire(name, indexLoader());
try {
index.delete(docId, request);
} finally {
@@ -90,10 +89,10 @@ public class IndexResource {
@PUT
@Timed
@Path("/doc/{docId}")
- public void updateDoc(@PathParam("name") String name, @PathParam("docId") String docId,
- @NotNull @Valid final DocumentUpdateRequest request)
- throws IOException, InterruptedException, ExecutionException {
- final Index index = indexManager.acquire(name);
+ public final void updateDoc(@PathParam("name") String name, @PathParam("docId") String docId,
+ @NotNull @Valid final DocumentUpdateRequest<T> request)
+ throws Exception {
+ final Index<T> index = indexManager.acquire(name, indexLoader());
try {
index.update(docId, request);
} finally {
@@ -104,9 +103,9 @@ public class IndexResource {
@POST
@Timed
@Path("/search")
- public SearchResults searchIndex(@PathParam("name") String name, @NotNull @Valid SearchRequest request)
- throws IOException, InterruptedException, ExecutionException {
- final Index index = indexManager.acquire(name);
+ public final SearchResults<T> searchIndex(@PathParam("name") String name, @NotNull @Valid SearchRequest request)
+ throws Exception {
+ final Index index = indexManager.acquire(name, indexLoader());
try {
return index.search(request);
} finally {
@@ -114,4 +113,6 @@ public class IndexResource {
}
}
+ protected abstract IndexLoader<T> indexLoader();
+
}
\ No newline at end of file
diff --git a/java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java b/java/nouveau/base/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java
similarity index 100%
rename from java/nouveau/api/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java
rename to java/nouveau/base/src/test/java/org/apache/couchdb/nouveau/api/SearchRequestTest.java
diff --git a/java/nouveau/api/src/test/resources/fixtures/DocumentUpdateRequest.json b/java/nouveau/base/src/test/resources/fixtures/DocumentUpdateRequest.json
similarity index 100%
rename from java/nouveau/api/src/test/resources/fixtures/DocumentUpdateRequest.json
rename to java/nouveau/base/src/test/resources/fixtures/DocumentUpdateRequest.json
diff --git a/java/nouveau/api/src/test/resources/fixtures/SearchRequest.json b/java/nouveau/base/src/test/resources/fixtures/SearchRequest.json
similarity index 100%
rename from java/nouveau/api/src/test/resources/fixtures/SearchRequest.json
rename to java/nouveau/base/src/test/resources/fixtures/SearchRequest.json
diff --git a/java/nouveau/lucene4/pom.xml b/java/nouveau/lucene4/pom.xml
index 9d51fbd97..75cb27ebc 100644
--- a/java/nouveau/lucene4/pom.xml
+++ b/java/nouveau/lucene4/pom.xml
@@ -20,10 +20,10 @@
<dependencies>
- <!-- API -->
+ <!-- Base -->
<dependency>
<groupId>org.apache.couchdb.nouveau</groupId>
- <artifactId>api</artifactId>
+ <artifactId>base</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Dummy4.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Dummy4.java
deleted file mode 100644
index 2c6c287a2..000000000
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Dummy4.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.apache.couchdb.nouveau.core.lucene4;
-
-import org.apache.lucene.index.IndexableField;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class Dummy4 {
-
- private IndexableField field;
-
- @JsonProperty
- public IndexableField getField() {
- return field;
- }
-
- public void setField(IndexableField field) {
- this.field = field;
- }
-
- @Override
- public String toString() {
- return "Dummy4 [field=" + field + "]";
- }
-
-}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/IndexableFieldDeserializer.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/IndexableFieldDeserializer.java
deleted file mode 100644
index c01d9e554..000000000
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/IndexableFieldDeserializer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.apache.couchdb.nouveau.core.lucene4;
-
-import java.io.IOException;
-
-import org.apache.lucene.document.TextField;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.index.IndexableField;
-
-import com.fasterxml.jackson.core.JacksonException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-public class IndexableFieldDeserializer extends StdDeserializer<IndexableField> {
-
- public IndexableFieldDeserializer() {
- this(null);
- }
-
- public IndexableFieldDeserializer(Class<?> vc) {
- super(vc);
- }
-
- @Override
- public IndexableField deserialize(JsonParser p, DeserializationContext ctxt)
- throws IOException, JacksonException {
- return new TextField("foo4", "bar4", Store.NO);
- }
-
-}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4.java
deleted file mode 100644
index ca7362a31..000000000
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4.java
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.core.lucene4;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response.Status;
-
-import org.apache.couchdb.nouveau.api.IndexDefinition;
-import org.apache.couchdb.nouveau.core.Index;
-import org.apache.couchdb.nouveau.core.Lucene;
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.search.SearcherFactory;
-import org.apache.lucene.search.SearcherManager;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.FSDirectory;
-
-final class Lucene4 implements Lucene {
-
- private SearcherFactory searcherFactory;
-
- public int getMajor() {
- return 4;
- }
-
- public void setExecutor(ExecutorService executor) {
- this.searcherFactory = new ParallelSearcherFactory(executor);
- }
-
- @Override
- public List<String> analyze(String analyzer, String text) throws IOException {
- try {
- return tokenize(Lucene4AnalyzerFactory.newAnalyzer(analyzer), text);
- } catch (IllegalArgumentException e) {
- throw new WebApplicationException(analyzer + " not a valid analyzer",
- Status.BAD_REQUEST);
- }
- }
-
- private List<String> tokenize(final Analyzer analyzer, final String text) throws IOException {
- final List<String> result = new ArrayList<String>(10);
- try (final TokenStream tokenStream = analyzer.tokenStream("default", text)) {
- tokenStream.reset();
- while (tokenStream.incrementToken()) {
- final CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class);
- result.add(term.toString());
- }
- tokenStream.end();
- }
- return result;
- }
-
- @Override
- public void validate(IndexDefinition indexDefinition) throws WebApplicationException {
- Lucene4AnalyzerFactory.fromDefinition(indexDefinition);
- }
-
- @Override
- public Index open(Path path, IndexDefinition indexDefinition) throws IOException {
- final Analyzer analyzer = Lucene4AnalyzerFactory.fromDefinition(indexDefinition);
- final Directory dir = FSDirectory.open(path.toFile());
- final IndexWriterConfig config = new IndexWriterConfig(Utils.LUCENE_VERSION, analyzer);
- config.setUseCompoundFile(false);
- final IndexWriter writer = new IndexWriter(dir, config);
- final long updateSeq = getUpdateSeq(writer);
- final SearcherManager searcherManager = new SearcherManager(writer, true, searcherFactory);
- return new Lucene4Index(analyzer, writer, updateSeq, searcherManager);
- }
-
- private static long getUpdateSeq(final IndexWriter writer) throws IOException {
- final Map<String, String> commitData = writer.getCommitData();
- if (commitData == null) {
- return 0L;
- }
- return Long.parseLong(commitData.getOrDefault("update_seq", "0"));
- }
-
-}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Bundle.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Bundle.java
deleted file mode 100644
index 2976f7057..000000000
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Bundle.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.apache.couchdb.nouveau.core.lucene4;
-
-import org.apache.couchdb.nouveau.core.Lucene;
-import org.apache.couchdb.nouveau.core.LuceneBundle;
-
-import io.dropwizard.setup.Environment;
-
-public final class Lucene4Bundle<Configuration> implements LuceneBundle<Configuration> {
-
- private Lucene4 lucene;
-
- @Override
- public void run(final Configuration configuration, final Environment environment) throws Exception {
- lucene = new Lucene4();
- lucene.setExecutor(environment.lifecycle().executorService("nouveau-lucene4-%d").build());
-
- environment.getObjectMapper().registerModule(new Lucene4Module());
- }
-
- @Override
- public Lucene getLucene() {
- return lucene;
- }
-
-}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Module.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Module.java
deleted file mode 100644
index 4ef2a411e..000000000
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Module.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.apache.couchdb.nouveau.core.lucene4;
-
-import org.apache.lucene.index.IndexableField;
-
-import com.fasterxml.jackson.core.Version;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-public class Lucene4Module extends SimpleModule {
-
- public Lucene4Module() {
- super("lucene4", Version.unknownVersion());
- addDeserializer(IndexableField.class, new IndexableFieldDeserializer());
- }
-
-}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/IndexableFieldDeserializer.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/IndexableFieldDeserializer.java
new file mode 100644
index 000000000..90c5cbaa0
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/IndexableFieldDeserializer.java
@@ -0,0 +1,78 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.core;
+
+import java.io.IOException;
+
+import org.apache.lucene.document.DoubleField;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.util.BytesRef;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+class IndexableFieldDeserializer extends StdDeserializer<IndexableField> {
+
+ IndexableFieldDeserializer() {
+ this(null);
+ }
+
+ IndexableFieldDeserializer(Class<?> vc) {
+ super(vc);
+ }
+
+ @Override
+ public IndexableField deserialize(final JsonParser parser, final DeserializationContext context)
+ throws IOException, JsonProcessingException {
+ JsonNode node = parser.getCodec().readTree(parser);
+
+ final String type = node.get("@type").asText();
+ final String name = node.get("name").asText();
+
+ switch (type) {
+ case "double":
+ return new DoubleField(name, node.get("value").doubleValue(),
+ node.get("stored").asBoolean() ? Store.YES : Store.NO);
+ case "string":
+ return new StringField(name, node.get("value").asText(),
+ node.get("stored").asBoolean() ? Store.YES : Store.NO);
+ case "text":
+ return new TextField(name, node.get("value").asText(),
+ node.get("stored").asBoolean() ? Store.YES : Store.NO);
+ case "stored":
+ if (node.get("value").isDouble()) {
+ return new StoredField(name, node.get("value").asDouble());
+ }
+ if (node.get("value").isTextual()) {
+ final JsonNode value = node.get("value");
+ if (node.has("encoded") && node.get("encoded").asBoolean()) {
+ return new StoredField(name, new BytesRef(value.binaryValue()));
+ } else {
+ return new StoredField(name, value.asText());
+ }
+ }
+ throw new JsonParseException(parser, node.get("value") + " not a valid value for a stored field");
+ }
+ throw new JsonParseException(parser, type + " not a valid type of field");
+ }
+
+}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/IndexableFieldSerializer.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/IndexableFieldSerializer.java
new file mode 100644
index 000000000..a450a7a19
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/IndexableFieldSerializer.java
@@ -0,0 +1,59 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.core;
+
+import java.io.IOException;
+
+import org.apache.lucene.document.StoredField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.util.BytesRef;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+class IndexableFieldSerializer extends StdSerializer<IndexableField> {
+
+ IndexableFieldSerializer() {
+ this(null);
+ }
+
+ IndexableFieldSerializer(Class<IndexableField> vc) {
+ super(vc);
+ }
+
+ @Override
+ public void serialize(final IndexableField field, final JsonGenerator gen, final SerializerProvider provider)
+ throws IOException {
+ if (!(field instanceof StoredField)) {
+ throw new JsonGenerationException(field.getClass() + " not supported", gen);
+ }
+ gen.writeStartObject();
+ gen.writeStringField("@type", "stored");
+ gen.writeStringField("name", field.name());
+ if (field.numericValue() != null) {
+ gen.writeNumberField("value", (double) field.numericValue());
+ } else if (field.stringValue() != null) {
+ gen.writeStringField("value", field.stringValue());
+ } else if (field.binaryValue() != null) {
+ final BytesRef bytesRef = field.binaryValue();
+ gen.writeFieldName("value");
+ gen.writeBinary(bytesRef.bytes, bytesRef.offset, bytesRef.length);
+ gen.writeBooleanField("encoded", true);
+ }
+ gen.writeEndObject();
+ }
+
+}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4AnalyzerFactory.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4AnalyzerFactory.java
similarity index 98%
rename from java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4AnalyzerFactory.java
rename to java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4AnalyzerFactory.java
index 9067608c8..89d102c54 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4AnalyzerFactory.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4AnalyzerFactory.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import java.util.HashMap;
import java.util.Map;
@@ -61,7 +61,7 @@ import org.apache.lucene.analysis.sv.SwedishAnalyzer;
import org.apache.lucene.analysis.th.ThaiAnalyzer;
import org.apache.lucene.analysis.tr.TurkishAnalyzer;
-final class Lucene4AnalyzerFactory {
+public final class Lucene4AnalyzerFactory {
public Lucene4AnalyzerFactory() {
}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Bundle.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Bundle.java
new file mode 100644
index 000000000..2cb7482eb
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Bundle.java
@@ -0,0 +1,45 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.core;
+
+import java.util.concurrent.ExecutorService;
+
+import org.apache.couchdb.nouveau.NouveauApplicationConfiguration;
+import org.apache.couchdb.nouveau.core.IndexManager;
+import org.apache.couchdb.nouveau.lucene4.resources.AnalyzeResource;
+import org.apache.couchdb.nouveau.lucene4.resources.IndexResource;
+import org.apache.lucene.search.SearcherFactory;
+
+import io.dropwizard.ConfiguredBundle;
+import io.dropwizard.setup.Environment;
+
+public final class Lucene4Bundle implements ConfiguredBundle<NouveauApplicationConfiguration> {
+
+ @Override
+ public void run(final NouveauApplicationConfiguration configuration, final Environment environment) throws Exception {
+
+ // Serialization classes
+ environment.getObjectMapper().registerModule(new Lucene4Module());
+
+ // AnalyzeResource
+ environment.jersey().register(new AnalyzeResource());
+
+ // IndexResource
+ final IndexManager indexManager = configuration.getIndexManagerFactory().build(environment);
+ final ExecutorService executorService = environment.lifecycle().executorService("nouveau-lucene4-%d").build();
+ final SearcherFactory searcherFactory = new ParallelSearcherFactory(executorService);
+ environment.jersey().register(new IndexResource(indexManager, searcherFactory));
+ }
+
+}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Index.java
similarity index 79%
rename from java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java
rename to java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Index.java
index d6986c6ef..01918fbb8 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4Index.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Index.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import java.io.IOException;
import java.util.ArrayList;
@@ -34,15 +34,10 @@ import org.apache.couchdb.nouveau.api.DoubleRange;
import org.apache.couchdb.nouveau.api.SearchHit;
import org.apache.couchdb.nouveau.api.SearchRequest;
import org.apache.couchdb.nouveau.api.SearchResults;
-import org.apache.couchdb.nouveau.api.document.DoubleField;
-import org.apache.couchdb.nouveau.api.document.Field;
-import org.apache.couchdb.nouveau.api.document.StoredDoubleField;
-import org.apache.couchdb.nouveau.api.document.StoredStringField;
-import org.apache.couchdb.nouveau.api.document.StringField;
-import org.apache.couchdb.nouveau.api.document.TextField;
import org.apache.couchdb.nouveau.core.Index;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
+import org.apache.lucene.document.StringField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.range.RangeAccumulator;
@@ -73,7 +68,7 @@ import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopFieldCollector;
import org.apache.lucene.util.BytesRef;
-class Lucene4Index extends Index {
+public class Lucene4Index extends Index<IndexableField> {
private static final Sort DEFAULT_SORT = new Sort(SortField.FIELD_SCORE,
new SortField("_id", SortField.Type.STRING));
@@ -84,7 +79,7 @@ class Lucene4Index extends Index {
private final SearcherManager searcherManager;
private volatile boolean isOpen = true;
- Lucene4Index(final Analyzer analyzer, final IndexWriter writer, final long updateSeq,
+ public Lucene4Index(final Analyzer analyzer, final IndexWriter writer, final long updateSeq,
final SearcherManager searcherManager) {
super(updateSeq);
this.analyzer = analyzer;
@@ -98,7 +93,7 @@ class Lucene4Index extends Index {
}
@Override
- public void doUpdate(final String docId, final DocumentUpdateRequest request) throws IOException {
+ public void doUpdate(final String docId, final DocumentUpdateRequest<IndexableField> request) throws IOException {
final Term docIdTerm = docIdTerm(docId);
final Document doc = toDocument(docId, request);
writer.updateDocument(docIdTerm, doc);
@@ -134,7 +129,7 @@ class Lucene4Index extends Index {
}
@Override
- public SearchResults doSearch(final SearchRequest request) throws IOException {
+ public SearchResults<IndexableField> doSearch(final SearchRequest request) throws IOException {
final Query query;
try {
query = newQueryParser().parse(request);
@@ -230,9 +225,9 @@ class Lucene4Index extends Index {
return sortFields[sortFields.length - 1];
}
- private SearchResults toSearchResults(final SearchRequest searchRequest, final IndexSearcher searcher,
+ private SearchResults<IndexableField> toSearchResults(final SearchRequest searchRequest, final IndexSearcher searcher,
TopFieldCollector hitCollector, FacetsCollector countsCollector, FacetsCollector rangesCollector) throws IOException {
- final SearchResults result = new SearchResults();
+ final SearchResults<IndexableField> result = new SearchResults<IndexableField>();
collectHits(searcher, hitCollector.topDocs(), result);
if (searchRequest.hasCounts()) {
result.setCounts(convertFacets(countsCollector));
@@ -243,22 +238,22 @@ class Lucene4Index extends Index {
return result;
}
- private void collectHits(final IndexSearcher searcher, final TopDocs topDocs, final SearchResults searchResults)
+ private void collectHits(final IndexSearcher searcher, final TopDocs topDocs, final SearchResults<IndexableField> searchResults)
throws IOException {
- final List<SearchHit> hits = new ArrayList<SearchHit>(topDocs.scoreDocs.length);
+ final List<SearchHit<IndexableField>> hits = new ArrayList<SearchHit<IndexableField>>(topDocs.scoreDocs.length);
for (final ScoreDoc scoreDoc : topDocs.scoreDocs) {
final Document doc = searcher.doc(scoreDoc.doc);
- final List<Field> fields = new ArrayList<Field>(doc.getFields().size());
+ final List<IndexableField> fields = new ArrayList<IndexableField>(doc.getFields().size());
for (IndexableField field : doc.getFields()) {
if (!field.name().equals("_id")) {
- fields.add(toField(field));
+ fields.add(field);
}
}
final After after = toAfter(((FieldDoc)scoreDoc));
- hits.add(new SearchHit(doc.get("_id"), after, fields));
+ hits.add(new SearchHit<IndexableField>(doc.get("_id"), after, fields));
}
searchResults.setTotalHits(topDocs.totalHits);
@@ -316,63 +311,28 @@ class Lucene4Index extends Index {
return new SortField(m.group(2), type, reverse);
}
- private static Document toDocument(final String docId, final DocumentUpdateRequest request) throws IOException {
+ private static Document toDocument(final String docId, final DocumentUpdateRequest<IndexableField> request) throws IOException {
final Document result = new Document();
// id
- addIndexableFields(result,
- new StringField("_id", docId, true, false, true));
+ result.add(new StringField("_id", docId, Store.YES));
// partition (optional)
if (request.hasPartition()) {
- addIndexableFields(result,
- new StringField("_partition", request.getPartition(), false, false, false));
+ result.add(new StringField("_partition", request.getPartition(), Store.NO));
}
- for (Field field : request.getFields()) {
+ for (IndexableField field : request.getFields()) {
// Underscore-prefix is reserved.
- if (field.getName().startsWith("_")) {
+ if (field.name().startsWith("_")) {
continue;
}
- addIndexableFields(result, field);
+ result.add(field);
}
return result;
}
- private static void addIndexableFields(final Document doc, final Field field) {
- if (field instanceof DoubleField) {
- final DoubleField f = (DoubleField) field;
- doc.add(new org.apache.lucene.document.DoubleField(f.getName(), f.getValue(), f.isStore() ? Store.YES : Store.NO));
- if (f.isFacet()) {
- doc.add(new org.apache.lucene.document.DoubleDocValuesField(f.getName(), f.getValue()));
- }
- } else if (field instanceof StringField) {
- final StringField f = (StringField) field;
- doc.add(new org.apache.lucene.document.StringField(f.getName(), f.getValue(),
- f.isStore() ? Store.YES : Store.NO));
- if (f.isSortable() || f.isFacet()) {
- doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
- }
- } else if (field instanceof TextField) {
- final TextField f = (TextField) field;
- doc.add(new org.apache.lucene.document.TextField(f.getName(), f.getValue(), f.isStore() ? Store.YES : Store.NO));
- if (f.isSortable() || f.isFacet()) {
- doc.add(new org.apache.lucene.document.SortedDocValuesField(f.getName(), new BytesRef(f.getValue())));
- }
- } else {
- throw new WebApplicationException(field.getClass() + " is not valid", Status.BAD_REQUEST);
- }
- }
-
- private static Field toField(final IndexableField field) {
- if (field.numericValue() != null) {
- return new StoredDoubleField(field.name(), (double) field.numericValue());
- } else {
- return new StoredStringField(field.name(), field.stringValue());
- }
- }
-
private FieldDoc toFieldDoc(final After after) {
final Object[] fields = Arrays.copyOf(after.getFields(), after.getFields().length);
for (int i = 0; i < fields.length; i++) {
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Module.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Module.java
new file mode 100644
index 000000000..377f92d11
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4Module.java
@@ -0,0 +1,35 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.core;
+
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.Query;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+public class Lucene4Module extends SimpleModule {
+
+ public Lucene4Module() {
+ super("lucene4", Version.unknownVersion());
+
+ // IndexableField
+ addSerializer(IndexableField.class, new IndexableFieldSerializer());
+ addDeserializer(IndexableField.class, new IndexableFieldDeserializer());
+
+ // Query
+ addDeserializer(Query.class, new QueryDeserializer());
+ }
+
+}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4QueryParser.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4QueryParser.java
similarity index 99%
rename from java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4QueryParser.java
rename to java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4QueryParser.java
index a9554ee5b..3753973a3 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4QueryParser.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4QueryParser.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import java.util.regex.Pattern;
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/ParallelSearcherFactory.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/ParallelSearcherFactory.java
similarity index 95%
rename from java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/ParallelSearcherFactory.java
rename to java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/ParallelSearcherFactory.java
index a8d98ec47..fff84355f 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/ParallelSearcherFactory.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/ParallelSearcherFactory.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/PerFieldAnalyzer.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/PerFieldAnalyzer.java
similarity index 96%
rename from java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/PerFieldAnalyzer.java
rename to java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/PerFieldAnalyzer.java
index 5a6d27b13..1952d9e32 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/PerFieldAnalyzer.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/PerFieldAnalyzer.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import java.util.Map;
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/QueryDeserializer.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/QueryDeserializer.java
new file mode 100644
index 000000000..ca222605c
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/QueryDeserializer.java
@@ -0,0 +1,41 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.core;
+
+import java.io.IOException;
+
+import org.apache.lucene.search.Query;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+class QueryDeserializer extends StdDeserializer<Query> {
+
+ QueryDeserializer() {
+ this(null);
+ }
+
+ QueryDeserializer(Class<?> vc) {
+ super(vc);
+ }
+
+ @Override
+ public Query deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException("Unimplemented method 'deserialize'");
+ }
+
+}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Utils.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Utils.java
similarity index 87%
rename from java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Utils.java
rename to java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Utils.java
index 0f72962f1..2fdc2cf02 100644
--- a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/core/lucene4/Utils.java
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/core/Utils.java
@@ -11,16 +11,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import org.apache.lucene.index.Term;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.NumericUtils;
import org.apache.lucene.util.Version;
-class Utils {
+public class Utils {
- static final Version LUCENE_VERSION = Version.LUCENE_46;
+ public static final Version LUCENE_VERSION = Version.LUCENE_46;
static Term doubleToTerm(String field, Double value) {
var bytesRef = new BytesRef();
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/resources/AnalyzeResource.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/resources/AnalyzeResource.java
new file mode 100644
index 000000000..eeb6e1426
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/resources/AnalyzeResource.java
@@ -0,0 +1,62 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.resources;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.couchdb.nouveau.api.AnalyzeRequest;
+import org.apache.couchdb.nouveau.api.AnalyzeResponse;
+import org.apache.couchdb.nouveau.lucene4.core.Lucene4AnalyzerFactory;
+import org.apache.couchdb.nouveau.resources.BaseAnalyzeResource;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+
+@Path("/4/analyze")
+public class AnalyzeResource extends BaseAnalyzeResource {
+
+ @Override
+ public AnalyzeResponse analyzeText(@NotNull @Valid AnalyzeRequest request) throws IOException {
+ try {
+ final List<String> tokens = tokenize(Lucene4AnalyzerFactory.newAnalyzer(request.getAnalyzer()),
+ request.getText());
+ return new AnalyzeResponse(tokens);
+ } catch (IllegalArgumentException e) {
+ throw new WebApplicationException(request.getAnalyzer() + " not a valid analyzer",
+ Status.BAD_REQUEST);
+ }
+ }
+
+ private List<String> tokenize(final Analyzer analyzer, final String text) throws IOException {
+ final List<String> result = new ArrayList<String>(10);
+ try (final TokenStream tokenStream = analyzer.tokenStream("default", text)) {
+ tokenStream.reset();
+ while (tokenStream.incrementToken()) {
+ final CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class);
+ result.add(term.toString());
+ }
+ tokenStream.end();
+ }
+ return result;
+ }
+
+}
diff --git a/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/resources/IndexResource.java b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/resources/IndexResource.java
new file mode 100644
index 000000000..061b57845
--- /dev/null
+++ b/java/nouveau/lucene4/src/main/java/org/apache/couchdb/nouveau/lucene4/resources/IndexResource.java
@@ -0,0 +1,68 @@
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.couchdb.nouveau.lucene4.resources;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.ws.rs.Path;
+
+import org.apache.couchdb.nouveau.core.IndexLoader;
+import org.apache.couchdb.nouveau.core.IndexManager;
+import org.apache.couchdb.nouveau.lucene4.core.Lucene4AnalyzerFactory;
+import org.apache.couchdb.nouveau.lucene4.core.Lucene4Index;
+import org.apache.couchdb.nouveau.lucene4.core.Utils;
+import org.apache.couchdb.nouveau.resources.BaseIndexResource;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.SearcherFactory;
+import org.apache.lucene.search.SearcherManager;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;;
+
+@Path("/4/index/{name}")
+public class IndexResource extends BaseIndexResource<IndexableField> {
+
+ private final SearcherFactory searcherFactory;
+
+ public IndexResource(final IndexManager indexManager, final SearcherFactory searcherFactory) {
+ super(indexManager);
+ this.searcherFactory = searcherFactory;
+ }
+
+ @Override
+ protected IndexLoader<IndexableField> indexLoader() {
+ return (path, indexDefinition) -> {
+ final Analyzer analyzer = Lucene4AnalyzerFactory.fromDefinition(indexDefinition);
+ final Directory dir = FSDirectory.open(path.toFile());
+ final IndexWriterConfig config = new IndexWriterConfig(Utils.LUCENE_VERSION, analyzer);
+ config.setUseCompoundFile(false);
+ final IndexWriter writer = new IndexWriter(dir, config);
+ final long updateSeq = getUpdateSeq(writer);
+ final SearcherManager searcherManager = new SearcherManager(writer, true, searcherFactory);
+ return new Lucene4Index(analyzer, writer, updateSeq, searcherManager);
+ };
+ }
+
+ private static long getUpdateSeq(final IndexWriter writer) throws IOException {
+ final Map<String, String> commitData = writer.getCommitData();
+ if (commitData == null) {
+ return 0L;
+ }
+ return Long.parseLong(commitData.getOrDefault("update_seq", "0"));
+ }
+
+}
\ No newline at end of file
diff --git a/java/nouveau/lucene4/src/test/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4AnalyzerFactoryTest.java b/java/nouveau/lucene4/src/test/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4AnalyzerFactoryTest.java
similarity index 99%
rename from java/nouveau/lucene4/src/test/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4AnalyzerFactoryTest.java
rename to java/nouveau/lucene4/src/test/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4AnalyzerFactoryTest.java
index 67113d248..3a41189bd 100644
--- a/java/nouveau/lucene4/src/test/java/org/apache/couchdb/nouveau/core/lucene4/Lucene4AnalyzerFactoryTest.java
+++ b/java/nouveau/lucene4/src/test/java/org/apache/couchdb/nouveau/lucene4/core/Lucene4AnalyzerFactoryTest.java
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.couchdb.nouveau.core.lucene4;
+package org.apache.couchdb.nouveau.lucene4.core;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/java/nouveau/lucene9/pom.xml b/java/nouveau/lucene9/pom.xml
index 2094f3985..2903efdf2 100644
--- a/java/nouveau/lucene9/pom.xml
+++ b/java/nouveau/lucene9/pom.xml
@@ -20,10 +20,10 @@
<dependencies>
- <!-- API -->
+ <!-- Base -->
<dependency>
<groupId>org.apache.couchdb.nouveau</groupId>
- <artifactId>api</artifactId>
+ <artifactId>base</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/java/nouveau/pom.xml b/java/nouveau/pom.xml
index f62001d96..5f32aa759 100644
--- a/java/nouveau/pom.xml
+++ b/java/nouveau/pom.xml
@@ -52,7 +52,7 @@
</dependencyManagement>
<modules>
- <module>api</module>
+ <module>base</module>
<module>lucene4</module>
<module>lucene9</module>
<module>server</module>
diff --git a/java/nouveau/server/nouveau.yaml b/java/nouveau/server/nouveau.yaml
index 1dcf51e23..7ccc76737 100644
--- a/java/nouveau/server/nouveau.yaml
+++ b/java/nouveau/server/nouveau.yaml
@@ -1,7 +1,8 @@
-maxIndexesOpen: 100
-commitIntervalSeconds: 30
-idleSeconds: 60
-rootDir: target/indexes
+indexManager:
+ maxIndexesOpen: 100
+ commitIntervalSeconds: 30
+ idleSeconds: 60
+ rootDir: target/indexes
server:
applicationConnectors:
diff --git a/java/nouveau/server/pom.xml b/java/nouveau/server/pom.xml
index 696f8f274..505f4a1da 100644
--- a/java/nouveau/server/pom.xml
+++ b/java/nouveau/server/pom.xml
@@ -28,10 +28,10 @@
<dependencies>
- <!-- API -->
+ <!-- Base -->
<dependency>
<groupId>org.apache.couchdb.nouveau</groupId>
- <artifactId>api</artifactId>
+ <artifactId>base</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java b/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java
index 8357fc4e6..5086bdf4c 100644
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java
+++ b/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java
@@ -16,40 +16,17 @@ package org.apache.couchdb.nouveau;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
import java.util.ServiceLoader;
-import java.util.concurrent.ScheduledExecutorService;
-import org.apache.couchdb.nouveau.core.IndexManager;
-import org.apache.couchdb.nouveau.core.Lucene;
-import org.apache.couchdb.nouveau.core.LuceneBundle;
import org.apache.couchdb.nouveau.core.UpdatesOutOfOrderExceptionMapper;
-import org.apache.couchdb.nouveau.health.AnalyzeHealthCheck;
-import org.apache.couchdb.nouveau.health.IndexManagerHealthCheck;
-import org.apache.couchdb.nouveau.resources.AnalyzeResource;
-import org.apache.couchdb.nouveau.resources.IndexResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.codahale.metrics.MetricRegistry;
-import com.codahale.metrics.jersey2.InstrumentedResourceMethodApplicationListener;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.dropwizard.Application;
-import io.dropwizard.Configuration;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class NouveauApplication extends Application<NouveauApplicationConfiguration> {
- private static final Logger LOGGER = LoggerFactory.getLogger(NouveauApplication.class);
-
- private Collection<LuceneBundle> bundles = new HashSet<LuceneBundle>();
-
public static void main(String[] args) throws Exception {
new NouveauApplication().run(args);
}
@@ -65,14 +42,15 @@ public class NouveauApplication extends Application<NouveauApplicationConfigurat
for (String name : System.getProperties().stringPropertyNames()) {
if (name.startsWith("nouveau.bundle.")) {
try {
- ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL(System.getProperty(name))});
- final ServiceLoader<ConfiguredBundle> bundleLoader = ServiceLoader.load(ConfiguredBundle.class, classLoader);
- for (final ConfiguredBundle<Configuration> bundle : bundleLoader) {
- if (bundle instanceof LuceneBundle) {
- bootstrap.addBundle(bundle);
- bundles.add((LuceneBundle<?>)bundle);
+ ClassLoader classLoader = URLClassLoader
+ .newInstance(new URL[] { new URL(System.getProperty(name)) });
+ final ServiceLoader<ConfiguredBundle> bundleLoader = ServiceLoader.load(ConfiguredBundle.class,
+ classLoader);
+ for (final ConfiguredBundle<NouveauApplicationConfiguration> bundle : bundleLoader) {
+ if (bundle instanceof ConfiguredBundle) {
+ bootstrap.addBundle(bundle);
+ }
}
- }
} catch (final MalformedURLException e) {
throw new Error(e);
}
@@ -82,47 +60,7 @@ public class NouveauApplication extends Application<NouveauApplicationConfigurat
@Override
public void run(NouveauApplicationConfiguration configuration, Environment environment) throws Exception {
- final MetricRegistry metricsRegistry = new MetricRegistry();
- environment.jersey().register(new InstrumentedResourceMethodApplicationListener(metricsRegistry));
-
- final ObjectMapper objectMapper = environment.getObjectMapper();
-
- final Map<Integer, Lucene> lucenes = new HashMap<Integer, Lucene>();
- for (final LuceneBundle bundle : bundles) {
- final Lucene lucene = ((LuceneBundle)bundle).getLucene();
- lucenes.put(lucene.getMajor(), lucene);
- LOGGER.info("Loaded bundle for Lucene {}", lucene.getMajor());
- }
-
- if (lucenes.isEmpty()) {
- throw new IllegalStateException("No Lucene bundles configured");
- }
-
- final ScheduledExecutorService indexManagerScheduler =
- environment.lifecycle()
- .scheduledExecutorService("index-manager-scheduler-%d")
- .threads(10)
- .build();
-
- final IndexManager indexManager = new IndexManager();
- indexManager.setScheduler(indexManagerScheduler);
- indexManager.setRootDir(configuration.getRootDir());
- indexManager.setMaxIndexesOpen(configuration.getMaxIndexesOpen());
- indexManager.setCommitIntervalSeconds(configuration.getCommitIntervalSeconds());
- indexManager.setIdleSeconds(configuration.getIdleSeconds());
- indexManager.setObjectMapper(objectMapper);
- indexManager.setLucenes(lucenes);
- environment.lifecycle().manage(indexManager);
-
environment.jersey().register(new UpdatesOutOfOrderExceptionMapper());
-
- final AnalyzeResource analyzeResource = new AnalyzeResource(lucenes);
- environment.jersey().register(analyzeResource);
- environment.jersey().register(new IndexResource(indexManager));
-
- // health checks
- environment.healthChecks().register("analyzeResource", new AnalyzeHealthCheck(analyzeResource));
- environment.healthChecks().register("indexManager", new IndexManagerHealthCheck(indexManager));
}
}
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/health/AnalyzeHealthCheck.java b/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/health/AnalyzeHealthCheck.java
deleted file mode 100644
index ebe01d4d4..000000000
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/health/AnalyzeHealthCheck.java
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.health;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.couchdb.nouveau.api.AnalyzeRequest;
-import org.apache.couchdb.nouveau.api.AnalyzeResponse;
-import org.apache.couchdb.nouveau.resources.AnalyzeResource;
-import com.codahale.metrics.health.HealthCheck;
-
-public class AnalyzeHealthCheck extends HealthCheck {
-
- private AnalyzeResource analyzeResource;
-
- public AnalyzeHealthCheck(final AnalyzeResource analyzeResource) {
- this.analyzeResource = analyzeResource;
- }
-
- @Override
- protected Result check() throws Exception {
- final AnalyzeRequest request = new AnalyzeRequest(9, "standard", "hello there");
- final AnalyzeResponse response = analyzeResource.analyzeText(request);
- final List<String> expected = Arrays.asList("hello", "there");
- final List<String> actual = response.getTokens();
- if (expected.equals(actual)) {
- return Result.healthy();
- } else {
- return Result.unhealthy("Expected '{}' but got '{}'", expected, actual);
- }
- }
-
-}
diff --git a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/health/IndexManagerHealthCheck.java b/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/health/IndexManagerHealthCheck.java
deleted file mode 100644
index cbf73d505..000000000
--- a/java/nouveau/server/src/main/java/org/apache/couchdb/nouveau/health/IndexManagerHealthCheck.java
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.health;
-
-import java.io.IOException;
-import java.util.Collections;
-
-import org.apache.couchdb.nouveau.api.DocumentUpdateRequest;
-import org.apache.couchdb.nouveau.api.IndexDefinition;
-import org.apache.couchdb.nouveau.core.Index;
-import org.apache.couchdb.nouveau.core.IndexManager;
-
-import com.codahale.metrics.health.HealthCheck;
-
-public class IndexManagerHealthCheck extends HealthCheck {
-
- private IndexManager indexManager;
-
- public IndexManagerHealthCheck(final IndexManager indexManager) {
- this.indexManager = indexManager;
- }
-
- @Override
- protected Result check() throws Exception {
- final String name = "_____test";
- try {
- indexManager.deleteAll(name);
- } catch (IOException e) {
- // Ignored, index might not exist yet.
- }
-
- indexManager.create(name, new IndexDefinition(9, "standard", null));
- final Index index = indexManager.acquire(name);
- final DocumentUpdateRequest request = new DocumentUpdateRequest(1, null, Collections.emptyList());
- index.update("foo", request);
- index.commit();
- index.setDeleteOnClose(true);
- return Result.healthy();
- }
-
-}
diff --git a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java
deleted file mode 100644
index 13f9048e3..000000000
--- a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/IntegrationTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Map;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.couchdb.nouveau.api.After;
-import org.apache.couchdb.nouveau.api.DocumentUpdateRequest;
-import org.apache.couchdb.nouveau.api.DoubleRange;
-import org.apache.couchdb.nouveau.api.IndexDefinition;
-import org.apache.couchdb.nouveau.api.SearchRequest;
-import org.apache.couchdb.nouveau.api.SearchResults;
-import org.apache.couchdb.nouveau.api.document.DoubleField;
-import org.apache.couchdb.nouveau.api.document.StringField;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-import io.dropwizard.testing.junit5.DropwizardAppExtension;
-import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
-
-@ExtendWith(DropwizardExtensionsSupport.class)
-public class IntegrationTest {
-
- static NouveauApplicationConfiguration CONFIG;
- static DropwizardAppExtension<NouveauApplicationConfiguration> APP;
-
- static {
- CONFIG = new NouveauApplicationConfiguration();
- CONFIG.setCommitIntervalSeconds(30);
- CONFIG.setMaxIndexesOpen(10);
- CONFIG.setIdleSeconds(60);
- CONFIG.setRootDir(Path.of("target/indexes"));
-
- // yuck
- final String path =
- String.format("file://%s/.m2/repository/org/apache/couchdb/nouveau/lucene9/1.0-SNAPSHOT/lucene9-1.0-SNAPSHOT-dist.jar",
- System.getProperty("user.home"));
-
- System.setProperty("nouveau.bundle.9", path);
-
- APP = new DropwizardAppExtension<>(NouveauApplication.class, CONFIG);
- }
-
- @Test
- public void indexTest() throws Exception{
- final String url = "http://localhost:" + APP.getLocalPort();
- final String indexName = "foo";
- final IndexDefinition indexDefinition = new IndexDefinition(9, "standard", null);
-
- // Clean up.
- Response response =
- APP.client().target(String.format("%s/index/%s", url, indexName))
- .request()
- .delete();
-
- // Create index.
- response =
- APP.client().target(String.format("%s/index/%s", url, indexName))
- .request()
- .put(Entity.entity(indexDefinition, MediaType.APPLICATION_JSON_TYPE));
-
- assertThat(response).extracting(Response::getStatus)
- .isEqualTo(Response.Status.NO_CONTENT.getStatusCode());
-
- // Populate index
- for (int i = 0; i < 10; i++) {
- final DocumentUpdateRequest docUpdate = new DocumentUpdateRequest(i + 1, null,
- List.of(
- new DoubleField("foo", i, false, false, false),
- new DoubleField("baz", i, false, true, false),
- new StringField("bar", "baz", false, true, false)));
- response =
- APP.client().target(String.format("%s/index/%s/doc/doc%d", url, indexName, i))
- .request()
- .put(Entity.entity(docUpdate, MediaType.APPLICATION_JSON_TYPE));
- assertThat(response).extracting(Response::getStatus)
- .isEqualTo(Response.Status.NO_CONTENT.getStatusCode());
- }
-
- // Search index
- final SearchRequest searchRequest = new SearchRequest();
- searchRequest.setQuery("*:*");
- searchRequest.setLimit(10);
- searchRequest.setCounts(List.of("bar"));
- searchRequest.setRanges(Map.of("baz", List.of(new DoubleRange("0 to 100 inc", 0.0, true, 100.0, true))));
- searchRequest.setTopN(2);
- searchRequest.setAfter(new After(1.0f, new byte[]{'a'}));
-
- response =
- APP.client().target(String.format("%s/index/%s/search", url, indexName))
- .request()
- .post(Entity.entity(searchRequest, MediaType.APPLICATION_JSON_TYPE));
-
- assertThat(response).extracting(Response::getStatus).isEqualTo(Response.Status.OK.getStatusCode());
- final SearchResults results = response.readEntity(SearchResults.class);
- assertThat(results.getTotalHits()).isEqualTo(10);
- assertThat(results.getTotalHitsRelation()).isEqualTo("EQUAL_TO");
- assertThat(results.getCounts().size()).isEqualTo(1);
- assertThat(results.getCounts().get("bar").get("baz")).isEqualTo(10);
- assertThat(results.getRanges().get("baz").get("0 to 100 inc")).isEqualTo(10);
- }
-
- @Test
- public void healthCheckShouldSucceed() throws IOException {
- final Response healthCheckResponse =
- APP.client().target("http://localhost:" + APP.getAdminPort() + "/healthcheck")
- .request()
- .get();
-
- assertThat(healthCheckResponse)
- .extracting(Response::getStatus)
- .isEqualTo(Response.Status.OK.getStatusCode());
- }
-
-}
diff --git a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java
deleted file mode 100644
index 1c247debc..000000000
--- a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/IndexManagerTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.core;
-
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.Path;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-
-import org.apache.couchdb.nouveau.api.IndexDefinition;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.api.io.TempDir;
-
-import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
-
-import static org.mockito.Mockito.*;
-
-@ExtendWith(DropwizardExtensionsSupport.class)
-public class IndexManagerTest {
-
- private static final int LUCENE_MAJOR = 9;
-
- @TempDir
- static Path tempDir;
-
- private IndexManager manager;
-
- private ScheduledExecutorService scheduler;
-
- @BeforeEach
- public void setup() throws Exception {
- scheduler = Executors.newScheduledThreadPool(1);
- manager = new IndexManager();
- manager.setScheduler(scheduler);
- manager.setLucenes(Map.of(LUCENE_MAJOR, mock(Lucene.class)));
- manager.setCommitIntervalSeconds(5);
- manager.setObjectMapper(new ObjectMapper());
- manager.setRootDir(tempDir);
- manager.start();
- }
-
- @AfterEach
- public void cleanup() throws Exception {
- manager.stop();
- scheduler.shutdown();
- }
-
- @Test
- public void testCreate() throws Exception {
- final IndexDefinition def = new IndexDefinition(LUCENE_MAJOR, "standard", null);
- manager.create("foo", def);
- }
-
-}
diff --git a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java b/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java
deleted file mode 100644
index c45cdb758..000000000
--- a/java/nouveau/server/src/test/java/org/apache/couchdb/nouveau/core/ser/SerializationTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.core.ser;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-
-import org.apache.couchdb.nouveau.api.After;
-import org.apache.couchdb.nouveau.api.DoubleRange;
-import org.apache.couchdb.nouveau.api.document.DoubleField;
-import org.apache.couchdb.nouveau.api.document.StoredDoubleField;
-import org.apache.couchdb.nouveau.api.document.StoredStringField;
-import org.apache.couchdb.nouveau.api.document.StringField;
-import org.apache.couchdb.nouveau.api.document.TextField;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class SerializationTest {
-
- private static ObjectMapper mapper;
-
- @BeforeAll
- public static void setupMapper() {
- mapper = new ObjectMapper();
- }
-
- @Test
- public void testSerializeStringFieldStoreYES() throws Exception {
- final String expected = "{\"@type\":\"string\",\"name\":\"foo\",\"value\":\"bar\",\"store\":true}";
- final String actual = mapper.writeValueAsString(new StringField("foo", "bar", true, false, false));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testSerializeStringFieldStoreNO() throws Exception {
- final String expected = "{\"@type\":\"string\",\"name\":\"foo\",\"value\":\"bar\"}";
- final String actual = mapper.writeValueAsString(new StringField("foo", "bar", false, false, false));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testSerializeTextFieldStoreYES() throws Exception {
- final String expected = "{\"@type\":\"text\",\"name\":\"foo\",\"value\":\"bar\",\"store\":true}";
- final String actual = mapper.writeValueAsString(new TextField("foo", "bar", true, false, false));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testSerializeTextFieldStoreNO() throws Exception {
- final String expected = "{\"@type\":\"text\",\"name\":\"foo\",\"value\":\"bar\"}";
- final String actual = mapper.writeValueAsString(new TextField("foo", "bar", false, false, false));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testSerializeDoubleField() throws Exception {
- final String expected = "{\"@type\":\"double\",\"name\":\"foo\",\"value\":12.5}";
- final String actual = mapper.writeValueAsString(new DoubleField("foo", 12.5, false, false, false));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testDeserializeDoubleField1D() throws Exception {
- final String json = "{\"@type\":\"double\",\"name\":\"foo\",\"value\":12.5}";
- final DoubleField field = mapper.readValue(json, DoubleField.class);
- assertEquals("foo", field.getName());
- assertEquals(12.5, field.getValue());
- }
-
- @Test
- public void testSerializeStoredFieldString() throws Exception {
- final String expected = "{\"@type\":\"stored_string\",\"name\":\"foo\",\"value\":\"bar\"}";
- final String actual = mapper.writeValueAsString(new StoredStringField("foo", "bar"));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testSerializeStoredFieldDouble() throws Exception {
- final String expected = "{\"@type\":\"stored_double\",\"name\":\"foo\",\"value\":12.5}";
- final String actual = mapper.writeValueAsString(new StoredDoubleField("foo", 12.5));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testSerializeAfter() throws Exception {
- final After after = new After(
- Float.valueOf(1),
- Double.valueOf(2),
- Integer.valueOf(3),
- Long.valueOf(4),
- "foo",
- new byte[]{'b', 'a', 'r'});
-
- final String expected = "[{\"@type\":\"float\",\"value\":1.0},{\"@type\":\"double\",\"value\":2.0},{\"@type\":\"int\",\"value\":3},{\"@type\":\"long\",\"value\":4},{\"@type\":\"string\",\"value\":\"foo\"},{\"@type\":\"bytes\",\"value\":\"YmFy\"}]";
- final String actual = mapper.writeValueAsString(after);
- assertEquals(expected, actual);
-
- final After after2 = mapper.readValue(expected, After.class);
-
- for (int i = 0; i < after.getFields().length; i++) {
- assertThat(after.getFields()[i].getClass()).isEqualTo(after2.getFields()[i].getClass());
- }
- }
-
- @Test
- public void testSerializeDoubleRange() throws Exception {
- final String expected = "{\"label\":\"foo\",\"min\":12.5,\"max\":52.1,\"min_inclusive\":false,\"max_inclusive\":false}";
- final String actual = mapper.writeValueAsString(new DoubleRange("foo", 12.5, false, 52.1, false));
- assertEquals(expected, actual);
- }
-
- @Test
- public void testDeserializeDoubleRange() throws Exception {
- final String expected = "{\"label\":\"foo\",\"min\":12.5,\"max\":52.1,\"min_inclusive\":false,\"max_inclusive\":false}";
- final DoubleRange actual = mapper.readValue(expected, DoubleRange.class);
- assertEquals("foo", actual.getLabel());
- assertEquals(12.5, actual.getMin());
- assertEquals(false, actual.isMinInclusive());
- assertEquals(52.1, actual.getMax());
- assertEquals(false, actual.isMaxInclusive());
- }
-
- @Test
- public void testDeserializeDoubleRangeDefaults() throws Exception {
- final String expected = "{\"label\":\"foo\",\"min\":12.5,\"max\":52.1}";
- final DoubleRange actual = mapper.readValue(expected, DoubleRange.class);
- assertEquals("foo", actual.getLabel());
- assertEquals(12.5, actual.getMin());
- assertEquals(true, actual.isMinInclusive());
- assertEquals(52.1, actual.getMax());
- assertEquals(true, actual.isMaxInclusive());
- }
-
-}
diff --git a/share/server/nouveau.js b/share/server/nouveau.js
index c7f706324..101ab4632 100644
--- a/share/server/nouveau.js
+++ b/share/server/nouveau.js
@@ -60,10 +60,11 @@ var Nouveau = (function() {
'@type': typeof value == 'string' ? 'string' : 'double',
'name': name,
'value': value,
- 'store': options.store|| false,
+ 'stored': options.store|| false,
'facet': options.facet|| false
});
- } else { // nouveau api
+ } else {
+ // Nouveau API.
var type = arguments[0];
var name = arguments[1];
@@ -85,9 +86,7 @@ var Nouveau = (function() {
'@type': type,
'name': name,
'value': value,
- 'store': options.store|| false,
- 'facet': options.facet|| false,
- 'sortable': options.sortable|| true
+ 'stored': options.store
});
break;
default: