From f19a6c0fafdbf1fa5e441f87d9da76933359e61d Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 13 May 2015 13:43:25 +0200 Subject: [PATCH] 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. --- src/main/asciidoc/key-value-repositories.adoc | 45 +++++--- .../core/ClassNameKeySpaceResolver.java | 41 +++++++ .../core/ForwardingCloseableIterator.java | 12 ++ .../data/keyvalue/core/KeySpaceResolver.java | 33 ++++++ .../data/keyvalue/core/KeyValueAdapter.java | 10 +- .../data/keyvalue/core/KeyValueTemplate.java | 71 ++++-------- .../AnnotationBasedKeySpaceResolver.java} | 40 ++++--- .../BasicKeyValuePersistentEntity.java | 59 ++++++++++ .../mapping/KeyValuePersistentEntity.java | 32 ++++++ .../context/KeyValueMappingContext.java | 42 +++++-- .../data/map/MapKeyValueAdapter.java | 13 --- .../keyvalue/CustomKeySpaceAnnotation.java | 38 +++++++ ...eWithCustomComposedKeySpaceAnnotation.java | 30 +++++ ...eWithCustomComposedKeySpaceAnnotation.java | 83 ++++++++++++++ .../TypeWithDirectKeySpaceAnnotation.java | 29 +++++ ...PersistentAnnotationNotHavingKeySpace.java | 30 +++++ ...PersistentAnnotationNotHavingKeySpace.java | 29 +++++ .../keyvalue/core/KeyValueTemplateTests.java | 4 +- .../core/KeyValueTemplateUnitTests.java | 105 +----------------- ...tationBasedKeySpaceResolverUnitTests.java} | 51 +++++---- .../KeyValueMappingContextUnitTests.java | 31 ++++++ 21 files changed, 598 insertions(+), 230 deletions(-) create mode 100644 src/main/java/org/springframework/data/keyvalue/core/ClassNameKeySpaceResolver.java create mode 100644 src/main/java/org/springframework/data/keyvalue/core/KeySpaceResolver.java rename src/main/java/org/springframework/data/keyvalue/core/{KeySpaceUtils.java => mapping/AnnotationBasedKeySpaceResolver.java} (93%) create mode 100644 src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java create mode 100644 src/main/java/org/springframework/data/keyvalue/core/mapping/KeyValuePersistentEntity.java create mode 100644 src/test/java/org/springframework/data/keyvalue/CustomKeySpaceAnnotation.java create mode 100644 src/test/java/org/springframework/data/keyvalue/SubclassOfTypeWithCustomComposedKeySpaceAnnotation.java create mode 100644 src/test/java/org/springframework/data/keyvalue/TypeWithCustomComposedKeySpaceAnnotation.java create mode 100644 src/test/java/org/springframework/data/keyvalue/TypeWithDirectKeySpaceAnnotation.java create mode 100644 src/test/java/org/springframework/data/keyvalue/TypeWithInhteritedPersistentAnnotationNotHavingKeySpace.java create mode 100644 src/test/java/org/springframework/data/keyvalue/TypeWithPersistentAnnotationNotHavingKeySpace.java rename src/test/java/org/springframework/data/keyvalue/core/{KeySpaceUtilsUnitTests.java => mapping/AnnotationBasedKeySpaceResolverUnitTests.java} (62%) create mode 100644 src/test/java/ort/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContextUnitTests.java diff --git a/src/main/asciidoc/key-value-repositories.adoc b/src/main/asciidoc/key-value-repositories.adoc index 38b5ca0..464da93 100644 --- a/src/main/asciidoc/key-value-repositories.adoc +++ b/src/main/asciidoc/key-value-repositories.adoc @@ -14,17 +14,17 @@ The Key/Value abstraction within Spring Data Commons requires an `Adapter` shiel ---- interface KeyValueOperations { - T insert(T objectToInsert); <1> + T insert(T objectToInsert); <1> - void update(Object objectToUpdate); <2> + void update(Object objectToUpdate); <2> - void delete(Class type); <3> + void delete(Class type); <3> - T findById(Serializable id, Class type); <4> + T findById(Serializable id, Class type); <4> - List findAllOf(Class type); <5> + Iterable findAllOf(Class type); <5> - List find(KeyValueQuery query, Class type); <6> + Iterable find(KeyValueQuery query, Class type); <6> //... more functionality omitted. @@ -44,7 +44,7 @@ In its very basic shape the `KeyValueTemplate` uses a `MapAdaper` wrapping a `Co NOTE: The used `KeyValueAdapter` does the heavy lifting when it comes to storing and retrieving data. The data structure used will influence performance and/or multi threading behavior. -One may choose to use a different type or preinitialize the adapter with some values, and can do so using `MapKeyValueAdapterFactory`. +One may choose to use a different type or preinitialize the adapter with some values, and can do so using various constructors on `MapKeyValueAdapter`. [source, java] ---- @@ -55,13 +55,7 @@ public KeyValueOperations keyValueTemplate() { @Bean public KeyValueAdapter keyValueAdapter() { - - MapKeyValueAdapterFactory factory = new MapKeyValueAdapterFactory(); - factory.setMapType(ConcurrentSkipListMap.class); - factory.setInitialValuesForKeyspace("lennister", singletonMap("1", "tyrion")); - factory.setInitialValuesForKeyspace("stark", singletonMap("1", "sansa")); - - return factory.getAdapter(); + return new MapKeyValueAdapter(ConcurrentHashMap.class); } ---- @@ -91,6 +85,29 @@ template.findAllOf(User.class); <2> <1> Returns all entities for keyspace "persons". <2> Returns only elements of type `User` stored in keyspace "persons". +[[key-value.keyspaces-custom]] +=== Custom KeySpace Annotation + +It is possible to compose own `KeySpace` annotations for a more domain centric usage by annotating one of the attibutes with `@KeySpace`. + +NOTE: The composed annotation needs to inherit `@Persistent`. + +[source, java] +---- +@Persistent +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +static @interface CacheCentricAnnotation { + + @KeySpace String cacheRegion() default ""; +} + +@CacheCentricAnnotation(cacheRegion = "customers") +class Customer { + //... +} +---- + [[key-value.template-query]] == Querying diff --git a/src/main/java/org/springframework/data/keyvalue/core/ClassNameKeySpaceResolver.java b/src/main/java/org/springframework/data/keyvalue/core/ClassNameKeySpaceResolver.java new file mode 100644 index 0000000..631e555 --- /dev/null +++ b/src/main/java/org/springframework/data/keyvalue/core/ClassNameKeySpaceResolver.java @@ -0,0 +1,41 @@ +/* + * 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.core; + +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; + +/** + * Most trivial implementation of {@link KeySpaceResolver} returning the {@link Class#getName()}. + * + * @author Christoph Strobl + */ +public enum ClassNameKeySpaceResolver implements KeySpaceResolver { + + INSTANCE; + + /* + * (non-Javadoc) + * @see org.springframework.data.keyvalue.core.KeySpaceResolver#resolveKeySpace(java.lang.Class) + */ + @Override + public String resolveKeySpace(Class type) { + + Assert.notNull(type, "Type must not be null!"); + return ClassUtils.getUserClass(type).getName(); + } + +} diff --git a/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java b/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java index 924ed9d..efd8393 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java +++ b/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java @@ -53,16 +53,28 @@ public class ForwardingCloseableIterator implements CloseableIterator next() { return delegate.next(); } + /* + * (non-Javadoc) + * @see org.springframework.data.util.CloseableIterator#close() + */ @Override public void close() { if (closeHandler != null) { diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeySpaceResolver.java b/src/main/java/org/springframework/data/keyvalue/core/KeySpaceResolver.java new file mode 100644 index 0000000..0287071 --- /dev/null +++ b/src/main/java/org/springframework/data/keyvalue/core/KeySpaceResolver.java @@ -0,0 +1,33 @@ +/* + * 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.core; + +/** + * {@link KeySpaceResolver} determines the {@literal keyspace} a given type is assigned to. A keyspace in this context + * is a specific region/collection/grouping of elements sharing a common keyrange.
+ * + * @author Christoph Strobl + */ +public interface KeySpaceResolver { + + /** + * Determine the {@literal keySpace} to use for a given type. + * + * @param type must not be {@literal null}. + * @return + */ + String resolveKeySpace(Class type); +} diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java index 8903417..1f47f18 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java @@ -76,7 +76,7 @@ public interface KeyValueAdapter extends DisposableBean { Iterable getAllOf(Serializable keyspace); /** - * Returns a {@link KeyValueIterator} that iterates over all entries. + * Returns a {@link KeyValueIterator} that iterates over all entries. * * @param keyspace * @return @@ -119,12 +119,4 @@ public interface KeyValueAdapter extends DisposableBean { * @return */ long count(KeyValueQuery query, Serializable keyspace); - - /** - * Check if values from the given keyspace are contained in the underlying key-value store. - * - * @param keyspace - * @return true if {@literal keyspace} already present in adapter. - */ - boolean hasKeyspace(Serializable keyspace); } diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java index 7218053..f56d44a 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueTemplate.java @@ -15,15 +15,12 @@ */ package org.springframework.data.keyvalue.core; -import static org.springframework.data.keyvalue.core.KeySpaceUtils.*; - import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -35,6 +32,8 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.domain.Sort; import org.springframework.data.keyvalue.core.event.KeyValueEvent; +import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity; +import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty; import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext; import org.springframework.data.keyvalue.core.query.KeyValueQuery; import org.springframework.data.mapping.PersistentEntity; @@ -43,7 +42,6 @@ import org.springframework.data.mapping.context.MappingContext; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; /** * Basic implementation of {@link KeyValueOperations}. @@ -57,8 +55,8 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA private static final PersistenceExceptionTranslator DEFAULT_PERSISTENCE_EXCEPTION_TRANSLATOR = new KeyValuePersistenceExceptionTranslator(); private final KeyValueAdapter adapter; - private final ConcurrentHashMap, String> keySpaceCache = new ConcurrentHashMap, String>(); - private final MappingContext>, ? extends PersistentProperty> mappingContext; + + private final MappingContext, ? extends KeyValuePersistentProperty> mappingContext; private final IdentifierGenerator identifierGenerator; private ApplicationEventPublisher eventPublisher; private final Set eventTypesToPublish = new HashSet(4); @@ -80,10 +78,8 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA * @param adapter must not be {@literal null}. * @param mappingContext must not be {@literal null}. */ - @SuppressWarnings("rawtypes") - public KeyValueTemplate( - KeyValueAdapter adapter, - MappingContext, ? extends PersistentProperty> mappingContext) { + public KeyValueTemplate(KeyValueAdapter adapter, + MappingContext, ? extends KeyValuePersistentProperty> mappingContext) { Assert.notNull(adapter, "Adapter must not be null!"); Assert.notNull(mappingContext, "MappingContext must not be null!"); @@ -192,20 +188,20 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA * @see org.springframework.data.keyvalue.core.KeyValueOperations#findAllOf(java.lang.Class) */ @Override - public List findAll(final Class type) { + public Iterable findAll(final Class type) { Assert.notNull(type, "Type to fetch must not be null!"); - return execute(new KeyValueCallback>() { + return execute(new KeyValueCallback>() { @SuppressWarnings("unchecked") @Override - public List doInKeyValue(KeyValueAdapter adapter) { + public Iterable doInKeyValue(KeyValueAdapter adapter) { Iterable values = adapter.getAllOf(resolveKeySpace(type)); - if (getKeySpace(type) == null) { - return new ArrayList(IterableConverter.toList((Iterable) values)); + if (values == null) { + return Collections.emptySet(); } ArrayList filtered = new ArrayList(); @@ -242,7 +238,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA Object result = adapter.get(id, keyspace); - if (result == null || getKeySpace(type) == null || typeCheck(type, result)) { + if (result == null || typeCheck(type, result)) { return (T) result; } @@ -355,18 +351,17 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA * @see org.springframework.data.keyvalue.core.KeyValueOperations#find(org.springframework.data.keyvalue.core.query.KeyValueQuery, java.lang.Class) */ @Override - public List find(final KeyValueQuery query, final Class type) { + public Iterable find(final KeyValueQuery query, final Class type) { - return execute(new KeyValueCallback>() { + return execute(new KeyValueCallback>() { @SuppressWarnings("unchecked") @Override - public List doInKeyValue(KeyValueAdapter adapter) { + public Iterable doInKeyValue(KeyValueAdapter adapter) { Iterable result = adapter.find(query, resolveKeySpace(type)); - - if (getKeySpace(type) == null) { - return new ArrayList(IterableConverter.toList((Iterable) result)); + if (result == null) { + return Collections.emptySet(); } List filtered = new ArrayList(); @@ -388,7 +383,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA */ @SuppressWarnings("rawtypes") @Override - public List findAll(Sort sort, Class type) { + public Iterable findAll(Sort sort, Class type) { return find(new KeyValueQuery(sort), type); } @@ -398,7 +393,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA */ @SuppressWarnings("rawtypes") @Override - public List findInRange(int offset, int rows, Class type) { + public Iterable findInRange(int offset, int rows, Class type) { return find(new KeyValueQuery().skip(offset).limit(rows), type); } @@ -408,7 +403,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA */ @SuppressWarnings("rawtypes") @Override - public List findInRange(int offset, int rows, Sort sort, Class type) { + public Iterable findInRange(int offset, int rows, Sort sort, Class type) { return find(new KeyValueQuery(sort).skip(offset).limit(rows), type); } @@ -480,29 +475,8 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA } } - protected String resolveKeySpace(Class type) { - - Class userClass = ClassUtils.getUserClass(type); - - String potentialKeySpace = keySpaceCache.get(userClass); - - if (potentialKeySpace != null) { - return potentialKeySpace; - } - - String keySpaceString = null; - Object keySpace = getKeySpace(type); - - if (keySpace != null) { - keySpaceString = keySpace.toString(); - } - - if (!StringUtils.hasText(keySpaceString)) { - keySpaceString = userClass.getName(); - } - - keySpaceCache.put(userClass, keySpaceString); - return keySpaceString; + private String resolveKeySpace(Class type) { + return this.mappingContext.getPersistentEntity(type).getKeySpace(); } private static boolean typeCheck(Class requiredType, Object candidate) { @@ -525,4 +499,5 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA eventPublisher.publishEvent(event); } } + } diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeySpaceUtils.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java similarity index 93% rename from src/main/java/org/springframework/data/keyvalue/core/KeySpaceUtils.java rename to src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java index c71944c..4a8004b 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeySpaceUtils.java +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * 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. @@ -13,7 +13,7 @@ * 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 java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -26,24 +26,39 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.style.ToStringCreator; import org.springframework.data.annotation.Persistent; import org.springframework.data.keyvalue.annotation.KeySpace; -import org.springframework.data.keyvalue.core.KeySpaceUtils.MetaAnnotationUtils.AnnotationDescriptor; +import org.springframework.data.keyvalue.core.KeySpaceResolver; +import org.springframework.data.keyvalue.core.mapping.AnnotationBasedKeySpaceResolver.MetaAnnotationUtils.AnnotationDescriptor; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** + * {@link AnnotationBasedKeySpaceResolver} looks up {@link Persistent} and checks for presence of either meta or direct + * usage of {@link KeySpace}. If non found it will default the keyspace to {@link Class#getName()}. + * * @author Christoph Strobl * @author Oliver Gierke */ -abstract class KeySpaceUtils { +enum AnnotationBasedKeySpaceResolver implements KeySpaceResolver { - private KeySpaceUtils() {} + INSTANCE; - /** - * Looks up {@link Persistent} when used as meta annotation to find the {@link KeySpace} attribute. - * - * @return + /* + * (non-Javadoc) + * @see org.springframework.data.keyvalue.core.KeySpaceResolver#resolveKeySpace(java.lang.Class) */ - public static Object getKeySpace(Class type) { + @Override + public String resolveKeySpace(Class type) { + + Assert.notNull(type, "Type for keyspace for null!"); + + Class userClass = ClassUtils.getUserClass(type); + Object keySpace = getKeySpace(userClass); + + return keySpace != null ? keySpace.toString() : null; + } + + private Object getKeySpace(Class type) { KeySpace keyspace = AnnotationUtils.findAnnotation(type, KeySpace.class); @@ -51,8 +66,7 @@ abstract class KeySpaceUtils { return AnnotationUtils.getValue(keyspace); } - AnnotationDescriptor descriptor = KeySpaceUtils.MetaAnnotationUtils.findAnnotationDescriptor(type, - Persistent.class); + AnnotationDescriptor descriptor = MetaAnnotationUtils.findAnnotationDescriptor(type, Persistent.class); if (descriptor != null && descriptor.getComposedAnnotation() != null) { @@ -392,6 +406,6 @@ abstract class KeySpaceUtils { } } } - } + } diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java new file mode 100644 index 0000000..ddeaf27 --- /dev/null +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/BasicKeyValuePersistentEntity.java @@ -0,0 +1,59 @@ +/* + * 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.core.mapping; + +import org.springframework.data.keyvalue.core.KeySpaceResolver; +import org.springframework.data.mapping.model.BasicPersistentEntity; +import org.springframework.data.util.TypeInformation; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * {@link KeyValuePersistentEntity} implementation that adds specific meta-data such as the {@literal keySpace}.. + * + * @author Christoph Strobl + * @param + */ +public class BasicKeyValuePersistentEntity extends BasicPersistentEntity implements + KeyValuePersistentEntity { + + private final String keyspace; + + /** + * @param information must not be {@literal null}. + * @param keySpaceResolver must not be {@literal null}. + */ + public BasicKeyValuePersistentEntity(TypeInformation information, KeySpaceResolver fallbackKeySpaceResolver) { + + super(information); + + Assert.notNull(fallbackKeySpaceResolver, "FallbackKeySpaceResolver must not be null!"); + + String resolvedKeySpace = AnnotationBasedKeySpaceResolver.INSTANCE.resolveKeySpace(information.getType()); + this.keyspace = StringUtils.hasText(resolvedKeySpace) ? resolvedKeySpace : fallbackKeySpaceResolver + .resolveKeySpace(information.getType()); + + } + + /* + * (non-Javadoc) + * @see org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity#getKeySpace() + */ + @Override + public String getKeySpace() { + return this.keyspace; + } +} diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/KeyValuePersistentEntity.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/KeyValuePersistentEntity.java new file mode 100644 index 0000000..abd3bc5 --- /dev/null +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/KeyValuePersistentEntity.java @@ -0,0 +1,32 @@ +/* + * 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.core.mapping; + +import org.springframework.data.mapping.model.MutablePersistentEntity; + +/** + * @author Christoph Strobl + * @param + */ +public interface KeyValuePersistentEntity extends MutablePersistentEntity { + + /** + * Get the {@literal keySpace} a given entity assigns to. + * + * @return never {@literal null}. + */ + String getKeySpace(); +} diff --git a/src/main/java/org/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContext.java b/src/main/java/org/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContext.java index 4f9ab84..33cd91b 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContext.java +++ b/src/main/java/org/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-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. @@ -18,26 +18,54 @@ package org.springframework.data.keyvalue.core.mapping.context; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; +import org.springframework.data.keyvalue.core.ClassNameKeySpaceResolver; +import org.springframework.data.keyvalue.core.KeySpaceResolver; +import org.springframework.data.keyvalue.core.mapping.BasicKeyValuePersistentEntity; +import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity; import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty; import org.springframework.data.mapping.context.AbstractMappingContext; -import org.springframework.data.mapping.model.BasicPersistentEntity; +import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.util.TypeInformation; +import org.springframework.util.Assert; /** + * Default implementation of a {@link MappingContext} using {@link KeyValuePersistentEntity} and + * {@link KeyValuePersistentProperty} as primary abstractions. + * * @author Christoph Strobl */ public class KeyValueMappingContext extends - AbstractMappingContext, KeyValuePersistentProperty> { + AbstractMappingContext, KeyValuePersistentProperty> { + + private final KeySpaceResolver fallbackKeySpaceResolver; + + /** + * Creates new {@link KeyValueMappingContext} using an {@link ClassNameKeySpaceResolver} for {@literal keyspace} + * resolution. + */ + public KeyValueMappingContext() { + this(ClassNameKeySpaceResolver.INSTANCE); + } + + /** + * Creates new {@link KeyValueMappingContext} using given {@link KeySpaceResolver} + * + * @param keySpaceResolver must not be {@literal null}. + */ + public KeyValueMappingContext(KeySpaceResolver fallbackKeySpaceResolver) { + + Assert.notNull(fallbackKeySpaceResolver, "FallbackKeySpaceResolver must not be null!"); + this.fallbackKeySpaceResolver = fallbackKeySpaceResolver; + } /* * (non-Javadoc) * @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation) */ @Override - protected BasicPersistentEntity createPersistentEntity( - TypeInformation typeInformation) { - return new BasicPersistentEntity(typeInformation); + protected KeyValuePersistentEntity createPersistentEntity(TypeInformation typeInformation) { + return new BasicKeyValuePersistentEntity(typeInformation, fallbackKeySpaceResolver); } /* @@ -46,7 +74,7 @@ public class KeyValueMappingContext extends */ @Override protected KeyValuePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, - BasicPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { + KeyValuePersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { return new KeyValuePersistentProperty(field, descriptor, owner, simpleTypeHolder); } } diff --git a/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java b/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java index 38012c9..bf18e0a 100644 --- a/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java @@ -17,9 +17,7 @@ package org.springframework.data.map; import java.io.Serializable; import java.util.Collection; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.springframework.core.CollectionFactory; @@ -163,17 +161,6 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter { getKeySpaceMap(keyspace).clear(); } - /* - * (non-Javadoc) - * @see org.springframework.data.keyvalue.core.KeyValueAdapter#hasKeyspace(java.io.Serializable) - */ - @Override - public boolean hasKeyspace(Serializable keyspace) { - - Assert.notNull(keyspace, "Collection must not be null for lookup."); - return store.containsKey(keyspace); - } - /* * (non-Javadoc) * @see org.springframework.data.keyvalue.core.KeyValueAdapter#clear() diff --git a/src/test/java/org/springframework/data/keyvalue/CustomKeySpaceAnnotation.java b/src/test/java/org/springframework/data/keyvalue/CustomKeySpaceAnnotation.java new file mode 100644 index 0000000..3cdc121 --- /dev/null +++ b/src/test/java/org/springframework/data/keyvalue/CustomKeySpaceAnnotation.java @@ -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 ""; +} diff --git a/src/test/java/org/springframework/data/keyvalue/SubclassOfTypeWithCustomComposedKeySpaceAnnotation.java b/src/test/java/org/springframework/data/keyvalue/SubclassOfTypeWithCustomComposedKeySpaceAnnotation.java new file mode 100644 index 0000000..67e507c --- /dev/null +++ b/src/test/java/org/springframework/data/keyvalue/SubclassOfTypeWithCustomComposedKeySpaceAnnotation.java @@ -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); + } + +} diff --git a/src/test/java/org/springframework/data/keyvalue/TypeWithCustomComposedKeySpaceAnnotation.java b/src/test/java/org/springframework/data/keyvalue/TypeWithCustomComposedKeySpaceAnnotation.java new file mode 100644 index 0000000..0887983 --- /dev/null +++ b/src/test/java/org/springframework/data/keyvalue/TypeWithCustomComposedKeySpaceAnnotation.java @@ -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; + } + +} diff --git a/src/test/java/org/springframework/data/keyvalue/TypeWithDirectKeySpaceAnnotation.java b/src/test/java/org/springframework/data/keyvalue/TypeWithDirectKeySpaceAnnotation.java new file mode 100644 index 0000000..6ec08fd --- /dev/null +++ b/src/test/java/org/springframework/data/keyvalue/TypeWithDirectKeySpaceAnnotation.java @@ -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 { + +} diff --git a/src/test/java/org/springframework/data/keyvalue/TypeWithInhteritedPersistentAnnotationNotHavingKeySpace.java b/src/test/java/org/springframework/data/keyvalue/TypeWithInhteritedPersistentAnnotationNotHavingKeySpace.java new file mode 100644 index 0000000..4c592e2 --- /dev/null +++ b/src/test/java/org/springframework/data/keyvalue/TypeWithInhteritedPersistentAnnotationNotHavingKeySpace.java @@ -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 { + +} diff --git a/src/test/java/org/springframework/data/keyvalue/TypeWithPersistentAnnotationNotHavingKeySpace.java b/src/test/java/org/springframework/data/keyvalue/TypeWithPersistentAnnotationNotHavingKeySpace.java new file mode 100644 index 0000000..69ab0b3 --- /dev/null +++ b/src/test/java/org/springframework/data/keyvalue/TypeWithPersistentAnnotationNotHavingKeySpace.java @@ -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 { + +} diff --git a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java index d359f71..4c02131 100644 --- a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java +++ b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateTests.java @@ -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()); } /** diff --git a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java index 80e183c..189f338 100644 --- a/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/keyvalue/core/KeyValueTemplateUnitTests.java @@ -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_QUERY = new KeyValueQuery("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 ""; - } } diff --git a/src/test/java/org/springframework/data/keyvalue/core/KeySpaceUtilsUnitTests.java b/src/test/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolverUnitTests.java similarity index 62% rename from src/test/java/org/springframework/data/keyvalue/core/KeySpaceUtilsUnitTests.java rename to src/test/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolverUnitTests.java index ccbe4ea..2d4dd41 100644 --- a/src/test/java/org/springframework/data/keyvalue/core/KeySpaceUtilsUnitTests.java +++ b/src/test/java/org/springframework/data/keyvalue/core/mapping/AnnotationBasedKeySpaceResolverUnitTests.java @@ -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 ""; } } diff --git a/src/test/java/ort/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContextUnitTests.java b/src/test/java/ort/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContextUnitTests.java new file mode 100644 index 0000000..0267f5f --- /dev/null +++ b/src/test/java/ort/springframework/data/keyvalue/core/mapping/context/KeyValueMappingContextUnitTests.java @@ -0,0 +1,31 @@ +/* + * 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 ort.springframework.data.keyvalue.core.mapping.context; + +import org.junit.Test; +import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext; + +public class KeyValueMappingContextUnitTests { + + /** + * @see DATAKV-105 + */ + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionWhenKeySpaceResolverIsNull() { + new KeyValueMappingContext(null); + } + +}