DATAKV-105 - Polish implementation after recent addition of features.
Remove obsolete method hasKeyspace() from KeyValueAdapter. Transition from List to Iterable for find methods in KeyValueTemplate. We now offer a plug able KeySpace resolution by providing a KeySpaceResolver via the KeyValueMappingContext. By default an AnnotationBasedKeySpaceResolver will be used to examine the type for @KeySpace. In case of non explicit keySpace we fall back to using the class' fully-qualified name as the default key space. Key space resolution is now fixed on resolving @KeySpace on a given PersistentEntity. In case no annotation key space can be found we by default fall back to a class name based key space. It is possible to configure the fallback via the MappingContext. Refactored names & visibility of types required for tests. Removed shortcut for returning results not having an explicit key space, since we now can no longer rely on the type name strategy dividing non explicit types into separate key spaces. Original pull request: #11.
This commit is contained in:
committed by
Oliver Gierke
parent
02759f58ea
commit
f19a6c0faf
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.keyvalue;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* Custom composed {@link Persistent} annotation using {@link KeySpace} on name attribute.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
public @interface CustomKeySpaceAnnotation {
|
||||
|
||||
@KeySpace
|
||||
String name() default "";
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.keyvalue;
|
||||
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* Class that inherits its {@link KeySpace} from a super class annotated with a custom {@link CustomKeySpaceAnnotation} annotation.
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class SubclassOfTypeWithCustomComposedKeySpaceAnnotation extends TypeWithCustomComposedKeySpaceAnnotation {
|
||||
|
||||
public SubclassOfTypeWithCustomComposedKeySpaceAnnotation(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.keyvalue;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A {@link Persistent} type with {@link CustomKeySpaceAnnotation}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@CustomKeySpaceAnnotation(name = "aliased")
|
||||
public class TypeWithCustomComposedKeySpaceAnnotation {
|
||||
|
||||
@Id String id;
|
||||
String name;
|
||||
|
||||
public TypeWithCustomComposedKeySpaceAnnotation(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.id);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof TypeWithCustomComposedKeySpaceAnnotation)) {
|
||||
return false;
|
||||
}
|
||||
TypeWithCustomComposedKeySpaceAnnotation other = (TypeWithCustomComposedKeySpaceAnnotation) obj;
|
||||
if (!ObjectUtils.nullSafeEquals(this.id, other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(this.name, other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.keyvalue;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* A {@link Persistent} type with explict {@link KeySpace}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@KeySpace("rhaegar")
|
||||
public class TypeWithDirectKeySpaceAnnotation {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.keyvalue;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* A type inheriting {@link Persistent} from {@link TypeAlias} not having a {@link KeySpace} defined.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@TypeAlias("foo")
|
||||
public class TypeWithInhteritedPersistentAnnotationNotHavingKeySpace {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.keyvalue;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* A {@link Persistent} class without a defined {@link KeySpace}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Persistent
|
||||
public class TypeWithPersistentAnnotationNotHavingKeySpace {
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.data.keyvalue.core;
|
||||
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.*;
|
||||
import static org.hamcrest.collection.IsEmptyCollection.*;
|
||||
import static org.hamcrest.collection.IsEmptyIterable.*;
|
||||
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.*;
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.hamcrest.core.IsNull.*;
|
||||
@@ -191,7 +191,7 @@ public class KeyValueTemplateTests {
|
||||
operations.insert("2", FOO_TWO);
|
||||
operations.insert("3", FOO_THREE);
|
||||
|
||||
assertThat(operations.findInRange(5, 5, Foo.class), empty());
|
||||
assertThat(operations.findInRange(5, 5, Foo.class), emptyIterable());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,10 +22,6 @@ import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -42,9 +38,8 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
import org.springframework.data.keyvalue.TypeWithCustomComposedKeySpaceAnnotation;
|
||||
import org.springframework.data.keyvalue.SubclassOfTypeWithCustomComposedKeySpaceAnnotation;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.DeleteEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.DropKeyspaceEvent;
|
||||
@@ -66,8 +61,8 @@ public class KeyValueTemplateUnitTests {
|
||||
|
||||
private static final Foo FOO_ONE = new Foo("one");
|
||||
private static final Foo FOO_TWO = new Foo("two");
|
||||
private static final ClassWithTypeAlias ALIASED = new ClassWithTypeAlias("super");
|
||||
private static final SubclassOfAliasedType SUBCLASS_OF_ALIASED = new SubclassOfAliasedType("sub");
|
||||
private static final TypeWithCustomComposedKeySpaceAnnotation ALIASED = new TypeWithCustomComposedKeySpaceAnnotation("super");
|
||||
private static final SubclassOfTypeWithCustomComposedKeySpaceAnnotation SUBCLASS_OF_ALIASED = new SubclassOfTypeWithCustomComposedKeySpaceAnnotation("sub");
|
||||
|
||||
private static final KeyValueQuery<String> STRING_QUERY = new KeyValueQuery<String>("foo == 'two'");
|
||||
|
||||
@@ -683,7 +678,7 @@ public class KeyValueTemplateUnitTests {
|
||||
|
||||
}
|
||||
|
||||
static class Bar {
|
||||
class Bar {
|
||||
|
||||
String bar;
|
||||
|
||||
@@ -753,94 +748,4 @@ public class KeyValueTemplateUnitTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExplicitKeySpace(name = "aliased")
|
||||
static class ClassWithTypeAlias {
|
||||
|
||||
@Id String id;
|
||||
String name;
|
||||
|
||||
public ClassWithTypeAlias(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.id);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof ClassWithTypeAlias)) {
|
||||
return false;
|
||||
}
|
||||
ClassWithTypeAlias other = (ClassWithTypeAlias) obj;
|
||||
if (!ObjectUtils.nullSafeEquals(this.id, other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(this.name, other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class SubclassOfAliasedType extends ClassWithTypeAlias {
|
||||
|
||||
public SubclassOfAliasedType(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Persistent
|
||||
static class EntityWithPersistentAnnotation {
|
||||
|
||||
}
|
||||
|
||||
@TypeAlias("foo")
|
||||
static class AliasedEntity {
|
||||
|
||||
}
|
||||
|
||||
@KeySpace("rhaegar")
|
||||
static class ClassWithDirectKeySpaceAnnotation {
|
||||
|
||||
}
|
||||
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
private static @interface ExplicitKeySpace {
|
||||
|
||||
@KeySpace
|
||||
String name() default "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,39 +13,45 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.keyvalue.core;
|
||||
package org.springframework.data.keyvalue.core.mapping;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.keyvalue.core.KeySpaceUtils.*;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.keyvalue.TypeWithDirectKeySpaceAnnotation;
|
||||
import org.springframework.data.keyvalue.TypeWithInhteritedPersistentAnnotationNotHavingKeySpace;
|
||||
import org.springframework.data.keyvalue.TypeWithPersistentAnnotationNotHavingKeySpace;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
import org.springframework.data.keyvalue.core.KeyValueTemplateUnitTests.AliasedEntity;
|
||||
import org.springframework.data.keyvalue.core.KeyValueTemplateUnitTests.ClassWithDirectKeySpaceAnnotation;
|
||||
import org.springframework.data.keyvalue.core.KeyValueTemplateUnitTests.EntityWithPersistentAnnotation;
|
||||
import org.springframework.data.keyvalue.core.KeyValueTemplateUnitTests.Foo;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link KeySpaceUtils}.
|
||||
* Unit tests for {@link AnnotationBasedKeySpaceResolver}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class KeySpaceUtilsUnitTests {
|
||||
public class AnnotationBasedKeySpaceResolverUnitTests {
|
||||
|
||||
private AnnotationBasedKeySpaceResolver resolver;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
resolver = AnnotationBasedKeySpaceResolver.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-525
|
||||
*/
|
||||
@Test
|
||||
public void shouldResolveKeySpaceDefaultValueCorrectly() {
|
||||
assertThat(getKeySpace(EntityWithDefaultKeySpace.class), is((Object) "daenerys"));
|
||||
assertThat(resolver.resolveKeySpace(EntityWithDefaultKeySpace.class), is("daenerys"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,31 +59,31 @@ public class KeySpaceUtilsUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void shouldResolveKeySpaceCorrectly() {
|
||||
assertThat(getKeySpace(EntityWithSetKeySpace.class), is((Object) "viserys"));
|
||||
assertThat(resolver.resolveKeySpace(EntityWithSetKeySpace.class), is("viserys"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-525
|
||||
* @see DATAKV-105
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnNullWhenNoKeySpaceFoundOnComposedPersistentAnnotation() {
|
||||
assertThat(getKeySpace(AliasedEntity.class), nullValue());
|
||||
assertThat(resolver.resolveKeySpace(TypeWithInhteritedPersistentAnnotationNotHavingKeySpace.class), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-525
|
||||
* @see DATAKV-105
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnNullWhenPersistentIsFoundOnNonComposedAnnotation() {
|
||||
assertThat(getKeySpace(EntityWithPersistentAnnotation.class), nullValue());
|
||||
assertThat(resolver.resolveKeySpace(TypeWithPersistentAnnotationNotHavingKeySpace.class), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-525
|
||||
* @see DATAKV-105
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnNullWhenPersistentIsNotFound() {
|
||||
assertThat(getKeySpace(Foo.class), nullValue());
|
||||
assertThat(resolver.resolveKeySpace(TypeWithoutKeySpace.class), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +91,7 @@ public class KeySpaceUtilsUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void shouldResolveInheritedKeySpaceCorrectly() {
|
||||
assertThat(getKeySpace(EntityWithInheritedKeySpace.class), is((Object) "viserys"));
|
||||
assertThat(resolver.resolveKeySpace(EntityWithInheritedKeySpace.class), is("viserys"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +99,7 @@ public class KeySpaceUtilsUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void shouldResolveDirectKeySpaceAnnotationCorrectly() {
|
||||
assertThat(getKeySpace(ClassWithDirectKeySpaceAnnotation.class), is((Object) "rhaegar"));
|
||||
assertThat(resolver.resolveKeySpace(TypeWithDirectKeySpaceAnnotation.class), is("rhaegar"));
|
||||
}
|
||||
|
||||
@PersistentAnnotationWithExplicitKeySpace
|
||||
@@ -121,12 +127,9 @@ public class KeySpaceUtilsUnitTests {
|
||||
String lastnamne() default "targaryen";
|
||||
}
|
||||
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
static @interface ExplicitKeySpace {
|
||||
static class TypeWithoutKeySpace {
|
||||
|
||||
String foo;
|
||||
|
||||
@KeySpace
|
||||
String name() default "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user