GEODE-3027: add a simple PartitionResolver

The new PartitionResolver is:
org.apache.geode.cache.util.StringPrefixPartitionResolver
It has a default no-arg constructor and can be configured
on a partitioned region as its PartitionResolver.
It requires that the region it is on to use String keys
and that the key contains at least one "|" delimiter.
The portion of the key that precedes the delimiter,
called the prefix, will
be returned from getRoutingObject and used to partition
the data on the region.
For example if the key is "customer#36|item#45" then it would
be partitioned uisng "customer#36".
This resolver does not allow the prefix string to contain a
delimiter.


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

Branch: refs/heads/feature/GEODE-3023
Commit: c8c24dd49e3e87808d43f0b0df796e2c307999eb
Parents: c756d31
Author: Darrel Schneider <[email protected]>
Authored: Mon Jun 5 17:07:46 2017 -0700
Committer: Udo Kohlmeyer <[email protected]>
Committed: Fri Jun 9 13:12:03 2017 -0700

----------------------------------------------------------------------
 .../util/StringPrefixPartitionResolver.java     | 86 ++++++++++++++++++
 .../StringPrefixPartitionResolverJUnitTest.java | 96 ++++++++++++++++++++
 2 files changed, 182 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/c8c24dd4/geode-core/src/main/java/org/apache/geode/cache/util/StringPrefixPartitionResolver.java
----------------------------------------------------------------------
diff --git 
a/geode-core/src/main/java/org/apache/geode/cache/util/StringPrefixPartitionResolver.java
 
b/geode-core/src/main/java/org/apache/geode/cache/util/StringPrefixPartitionResolver.java
new file mode 100644
index 0000000..6a2d037
--- /dev/null
+++ 
b/geode-core/src/main/java/org/apache/geode/cache/util/StringPrefixPartitionResolver.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.util;
+
+import org.apache.geode.cache.EntryOperation;
+import org.apache.geode.cache.PartitionResolver;
+
+/**
+ * This partition resolver requires every key of the partitioned region to be 
an instance of String
+ * and to contain at least one "|" delimiter. The prefix, the substring of the 
key that precedes the
+ * first delimiter, is returned by getRoutingObject.
+ * 
+ * @since Geode 1.2.0
+ */
+public class StringPrefixPartitionResolver implements 
PartitionResolver<String, Object> {
+
+  /**
+   * The default delimiter is "|". Currently this class only uses the default 
delimiter but in a
+   * future release configuring the delimiter may be supported.
+   */
+  public static final String DEFAULT_DELIMITER = "|";
+
+  /**
+   * Creates a prefix resolver with the default delimiter.
+   */
+  public StringPrefixPartitionResolver() {}
+
+  /**
+   * Returns the prefix of the String key that precedes the first "|" in the 
key.
+   * 
+   * @throws ClassCastException if the key is not an instance of String
+   * @throws IllegalArgumentException if the key does not contain at least one 
"|".
+   */
+  @Override
+  public Object getRoutingObject(EntryOperation<String, Object> opDetails) {
+    String key = opDetails.getKey();
+    String delimiter = getDelimiter();
+    int idx = key.indexOf(delimiter);
+    if (idx == -1) {
+      throw new IllegalArgumentException(
+          "The key \"" + key + "\" does not contains the \"" + delimiter + "\" 
delimiter.");
+    }
+    return key.substring(0, idx);
+  }
+
+  @Override
+  public java.lang.String getName() {
+    return getClass().getName();
+  }
+
+  private java.lang.String getDelimiter() {
+    return DEFAULT_DELIMITER;
+  }
+
+  @Override
+  public int hashCode() {
+    return getName().hashCode();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof StringPrefixPartitionResolver)) {
+      return false;
+    }
+    StringPrefixPartitionResolver other = (StringPrefixPartitionResolver) o;
+    return other.getName().equals(getName()) && 
other.getDelimiter().equals(getDelimiter());
+  }
+
+  @Override
+  public void close() {}
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c8c24dd4/geode-core/src/test/java/org/apache/geode/cache/util/StringPrefixPartitionResolverJUnitTest.java
----------------------------------------------------------------------
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/util/StringPrefixPartitionResolverJUnitTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/util/StringPrefixPartitionResolverJUnitTest.java
new file mode 100644
index 0000000..be67f1b
--- /dev/null
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/util/StringPrefixPartitionResolverJUnitTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.util;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.EntryOperation;
+import org.apache.geode.cache.util.StringPrefixPartitionResolver;
+import org.apache.geode.internal.cache.EntryOperationImpl;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class StringPrefixPartitionResolverJUnitTest {
+  static final String DELIMITER = 
StringPrefixPartitionResolver.DEFAULT_DELIMITER;
+
+  @Test
+  public void testGetName() {
+    assertEquals("org.apache.geode.cache.util.StringPrefixPartitionResolver",
+        (new StringPrefixPartitionResolver()).getName());
+  }
+
+  @Test
+  public void testEquals() {
+    StringPrefixPartitionResolver pr1 = new StringPrefixPartitionResolver();
+    assertEquals(true, pr1.equals(pr1));
+    StringPrefixPartitionResolver pr2 = new StringPrefixPartitionResolver();
+    assertEquals(true, pr1.equals(pr2));
+    assertEquals(false, pr1.equals(new Object()));
+  }
+
+  @Test
+  public void testNonStringKey() {
+    Object key = new Object();
+    StringPrefixPartitionResolver pr = new StringPrefixPartitionResolver();
+    assertThatThrownBy(() -> pr.getRoutingObject(createEntryOperation(key)))
+        .isInstanceOf(ClassCastException.class);
+  }
+
+  @Test
+  public void testNoDelimiterKey() {
+    String key = "foobar";
+    StringPrefixPartitionResolver pr = new StringPrefixPartitionResolver();
+    assertThatThrownBy(() -> pr.getRoutingObject(createEntryOperation(key)))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("The key \"foobar\" does not contains the \"" + DELIMITER 
+ "\" delimiter.");
+  }
+
+  @Test
+  public void testEmptyPrefix() {
+    String key = DELIMITER + "foobar";
+    StringPrefixPartitionResolver pr = new StringPrefixPartitionResolver();
+    assertEquals("", pr.getRoutingObject(createEntryOperation(key)));
+  }
+
+  @Test
+  public void testAllPrefix() {
+    String key = "foobar" + DELIMITER;
+    StringPrefixPartitionResolver pr = new StringPrefixPartitionResolver();
+    assertEquals("foobar", pr.getRoutingObject(createEntryOperation(key)));
+  }
+
+  @Test
+  public void testSimpleKey() {
+    String key = "1" + DELIMITER + "2";
+    StringPrefixPartitionResolver pr = new StringPrefixPartitionResolver();
+    assertEquals("1", pr.getRoutingObject(createEntryOperation(key)));
+  }
+
+  @Test
+  public void testMulitPrefix() {
+    String key = "one" + DELIMITER + "two" + DELIMITER + "three";
+    StringPrefixPartitionResolver pr = new StringPrefixPartitionResolver();
+    assertEquals("one", pr.getRoutingObject(createEntryOperation(key)));
+  }
+
+  @SuppressWarnings("unchecked")
+  private EntryOperation<String, Object> createEntryOperation(Object key) {
+    return new EntryOperationImpl(null, null, key, null, null);
+  }
+}

Reply via email to