/*
* Copyright 2012 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.gemfire.mapping;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.annotation.Region;
import org.springframework.data.mapping.IdentifierAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.util.ClassTypeInformation;
/**
* Unit tests for {@link GemfirePersistentEntity}.
*
* @author Oliver Gierke
* @author John Blum
* @author Gregory Green
* @see org.junit.Rule
* @see org.junit.Test
* @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity
*/
public class GemfirePersistentEntityUnitTests {
@Rule
public ExpectedException exception = ExpectedException.none();
private GemfireMappingContext mappingContext = new GemfireMappingContext();
protected IdentifierAccessor getIdentifierAccessor(Object domainObject) {
return getMappingContextPersistentEntity(domainObject).getIdentifierAccessor(domainObject);
}
@SuppressWarnings("unchecked")
protected <T> GemfirePersistentEntity<T> getMappingContextPersistentEntity(Object domainObject) {
return this.<T>getMappingContextPersistentEntity((Class<T>) domainObject.getClass());
}
@SuppressWarnings("unchecked")
protected <T> GemfirePersistentEntity<T> getMappingContextPersistentEntity(Class<T> type) {
return (GemfirePersistentEntity<T>) this.mappingContext.getPersistentEntity(type).orElseThrow(
() -> newIllegalStateException("Unable to resolve PersistentEntity for type [%s]", type));
}
protected <T> GemfirePersistentEntity<T> newPersistentEntity(Class<T> type) {
return new GemfirePersistentEntity<>(ClassTypeInformation.from(type));
}
@Test
public void defaultsRegionNameForNonRegionAnnotatedEntityToClassName() {
assertThat(newPersistentEntity(NonRegionAnnotatedEntity.class).getRegionName())
.isEqualTo(NonRegionAnnotatedEntity.class.getSimpleName());
}
@Test
public void defaultsRegionNameForUnnamedRegionAnnotatedEntityToClassName() {
assertThat(newPersistentEntity(UnnamedRegionAnnotatedEntity.class).getRegionName())
.isEqualTo(UnnamedRegionAnnotatedEntity.class.getSimpleName());
}
@Test
public void returnsGivenNameForNamedRegionAnnotatedEntityAsRegionName() {
assertThat(newPersistentEntity(NamedRegionAnnotatedEntity.class).getRegionName()).isEqualTo("Foo");
}
@Test
@SuppressWarnings("unchecked")
public void bigDecimalPersistentPropertyIsNotAnEntity() {
GemfirePersistentEntity<ExampleDomainObject> entity =
getMappingContextPersistentEntity(ExampleDomainObject.class);
assertThat(entity).isNotNull();
assertThat(entity.getRegionName()).isEqualTo("Example");
Optional<GemfirePersistentProperty> currency = entity.getPersistentProperty("currency");
assertThat(currency.isPresent()).isTrue();
assertThat(currency.get().isEntity()).isFalse();
}
@Test
@SuppressWarnings("unchecked")
public void bigIntegerPersistentPropertyIsNotAnEntity() {
GemfirePersistentEntity<ExampleDomainObject> entity =
getMappingContextPersistentEntity(ExampleDomainObject.class);
assertThat(entity).isNotNull();
assertThat(entity.getRegionName()).isEqualTo("Example");
Optional<GemfirePersistentProperty> bigNumber = entity.getPersistentProperty("bigNumber");
assertThat(bigNumber.isPresent()).isTrue();
assertThat(bigNumber.get().isEntity()).isFalse();
}
/**
* <a href="https://jira.spring.io/browse/SGF-582">SGF-582</a>
*/
@Test
public void identifierForNonIdAnnotatedEntityWithNoIdFieldOrPropertyIsNull() {
IdentifierAccessor identifierAccessor = getIdentifierAccessor(new NonRegionAnnotatedEntity());
assertThat(identifierAccessor.getIdentifier().orElse(null)).isNull();
}
/**
* <a href="https://jira.spring.io/browse/SGF-582">SGF-582</a>
*/
@Test
public void identifierForNonIdAnnotatedEntityWithIdFieldIsNotNull() {
IdentifierAccessor identifierAccessor = getIdentifierAccessor(new NonIdAnnotatedIdFieldEntity());
assertThat(identifierAccessor.getIdentifier().orElse(null)).isEqualTo(123L);
}
/**
* <a href="https://jira.spring.io/browse/SGF-582">SGF-582</a>
*/
@Test
public void identifierForNonIdAnnotatedEntityWithIdPropertyIsNotNull() {
IdentifierAccessor identifierAccessor = getIdentifierAccessor(new NonIdAnnotatedIdGetterEntity());
assertThat(identifierAccessor.getIdentifier().orElse(null)).isEqualTo(456L);
}
@Test
public void identifierForIdAnnotatedFieldAndPropertyEntityShouldNotConflict() {
IdentifierAccessor identifierAccessor = getIdentifierAccessor(new IdAnnotatedFieldAndPropertyEntity());
assertThat(identifierAccessor.getIdentifier().orElse(null)).isEqualTo(1L);
}
@Test
public void identifierForAmbiguousIdAnnotatedFieldAndIdAnnotatedPropertyEntityThrowsMappingException() {
AmbiguousIdAnnotatedFieldAndIdAnnotatedPropertyEntity entity
= new AmbiguousIdAnnotatedFieldAndIdAnnotatedPropertyEntity();
String expectedMessage = String.format("Attempt to add explicit id property [ssn] but already have id property [id] registered as explicit;"
+ " Please check your object [%s] mapping configuration", entity.getClass().getName());
exception.expect(MappingException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage(expectedMessage);
getIdentifierAccessor(new AmbiguousIdAnnotatedFieldAndIdAnnotatedPropertyEntity());
}
@SuppressWarnings("unused")
static class AmbiguousIdAnnotatedFieldAndIdAnnotatedPropertyEntity {
@Id
private Long id = 1L;
@Id
public String getSsn() {
return "123456789";
}
}
static class IdAnnotatedFieldAndPropertyEntity {
@Id
private Long id = 1L;
@Id
public Long getId() {
return this.id;
}
}
static class NonIdAnnotatedIdFieldEntity {
private Long id = 123L;
}
static class NonIdAnnotatedIdGetterEntity {
public Long getId() {
return 456L;
}
}
static class NonRegionAnnotatedEntity {
}
@Region("Foo")
static class NamedRegionAnnotatedEntity {
}
@Region
static class UnnamedRegionAnnotatedEntity {
}
@Region("Example")
@SuppressWarnings("unused")
static class ExampleDomainObject {
private BigDecimal currency;
private BigInteger bigNumber;
public BigDecimal getCurrency() {
return currency;
}
public BigInteger getBigNumber() {
return bigNumber;
}
}
}