Move PdxInstance identifier/identity resolution logic from JsonCacheDataImporterExporter to PdxInstanceWrapper.
This commit is contained in:
@@ -51,6 +51,7 @@ public class PdxInstanceWrapper implements PdxInstance, Sendable {
|
||||
public static final String AT_TYPE_FIELD_NAME = "@type";
|
||||
public static final String CLASS_NAME_PROPERTY = "className";
|
||||
public static final String ID_FIELD_NAME = "id";
|
||||
protected static final String NO_FIELD_NAME = "";
|
||||
|
||||
protected static final String ARRAY_BEGIN = "[";
|
||||
protected static final String ARRAY_END = "]";
|
||||
@@ -202,14 +203,6 @@ public class PdxInstanceWrapper implements PdxInstance, Sendable {
|
||||
return getDelegate().isEnum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdentityField(String fieldName) {
|
||||
return getDelegate().isIdentityField(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -226,10 +219,123 @@ public class PdxInstanceWrapper implements PdxInstance, Sendable {
|
||||
return getDelegate().getFieldNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the {@link Object identifier} for, or {@link PdxInstance#isIdentityField(String) identity} of,
|
||||
* this {@link PdxInstance}.
|
||||
*
|
||||
* @return the {@link Object identifier} for this {@link PdxInstance}; never {@literal null}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see #isIdentityField(String)
|
||||
* @see #getField(String)
|
||||
* @see #getFieldNames()
|
||||
* @see #getId()
|
||||
*/
|
||||
public Object getIdentifier() {
|
||||
|
||||
Optional<String> identityFieldName = nullSafeList(getFieldNames()).stream()
|
||||
.filter(this::hasText)
|
||||
.filter(this::isIdentityField)
|
||||
.findFirst();
|
||||
|
||||
return identityFieldName
|
||||
.map(this::getField)
|
||||
.orElseGet(this::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field name} called {@literal id} on this {@link PdxInstance}
|
||||
* and returns its {@link Object value} as the {@link Object identifier} for,
|
||||
* or {@link PdxInstance#isIdentityField(String) identity} of, this {@link PdxInstance}.
|
||||
*
|
||||
* @return the {@link Object value} of the {@literal id} {@link String field} on this {@link PdxInstance}.
|
||||
* @throws IllegalStateException if this {@link PdxInstance} does not have an id.
|
||||
* @see #getAtIdentifier()
|
||||
* @see #getField(String)
|
||||
* @see #hasField(String)
|
||||
*/
|
||||
protected Object getId() {
|
||||
|
||||
return hasField(ID_FIELD_NAME)
|
||||
? getField(ID_FIELD_NAME)
|
||||
: getAtIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field} declared by the {@literal @identifier} metadata {@link String field}
|
||||
* on this {@link PdxInstance} and returns the {@link Object value} of this {@link String field}
|
||||
* as the {@link Object identifier} for, or {@link PdxInstance#isIdentityField(String) identity} of,
|
||||
* this {@link PdxInstance}.
|
||||
*
|
||||
* @return the {@link Object value} of the {@link String field} declared in the {@literal @identifier} metadata
|
||||
* {@link String field} on this {@link PdxInstance}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
protected Object getAtIdentifier() {
|
||||
|
||||
return Optional.of(AT_IDENTIFIER_FIELD_NAME)
|
||||
.filter(this::hasField)
|
||||
.map(this::getField)
|
||||
.map(String::valueOf)
|
||||
.filter(this::hasField)
|
||||
.map(this::getField)
|
||||
.orElseThrow(() -> new IllegalStateException(String.format("PdxInstance for type [%1$s] has no %2$s",
|
||||
getClassName(), resolveMessageForIdentifierError(this))));
|
||||
}
|
||||
|
||||
private String resolveMessageForIdentifierError(PdxInstance pdxInstance) {
|
||||
|
||||
String message = "declared identifier";
|
||||
|
||||
if (pdxInstance.hasField(ID_FIELD_NAME)) {
|
||||
message = "id";
|
||||
}
|
||||
else if (pdxInstance.hasField(AT_IDENTIFIER_FIELD_NAME)) {
|
||||
|
||||
Object atIdentifierFieldValue = pdxInstance.getField(AT_IDENTIFIER_FIELD_NAME);
|
||||
|
||||
String resolvedIdentifierFieldName = Objects.nonNull(atIdentifierFieldValue)
|
||||
? atIdentifierFieldValue.toString().trim()
|
||||
: NO_FIELD_NAME;
|
||||
|
||||
boolean identifierFieldNameWasDeclaredAndIsValid = pdxInstance.hasField(resolvedIdentifierFieldName);
|
||||
|
||||
Object identifier = identifierFieldNameWasDeclaredAndIsValid
|
||||
? pdxInstance.getField(resolvedIdentifierFieldName)
|
||||
: null;
|
||||
|
||||
String ifMessage = "value [%s] for field [%s] declared in [%s]";
|
||||
String elseMessage = "field [%s] declared in [%s]";
|
||||
|
||||
message = identifierFieldNameWasDeclaredAndIsValid
|
||||
? String.format(ifMessage, identifier, resolvedIdentifierFieldName, AT_IDENTIFIER_FIELD_NAME)
|
||||
: String.format(elseMessage, resolvedIdentifierFieldName, AT_IDENTIFIER_FIELD_NAME);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdentityField(String fieldName) {
|
||||
return getDelegate().isIdentityField(fieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Materializes an {@link Object} from the PDX bytes described by this {@link PdxInstance}.
|
||||
*
|
||||
* If these PDX bytes describe an {@link Object} parsed from JSON, then the JSON is reconstructed from
|
||||
* this {@link PdxInstance} and mapped to an instance of the {@link Class type} identified by
|
||||
* the {@literal @type} metadata PDX {@link String field} using Jackson's {@link ObjectMapper}.
|
||||
*
|
||||
* @return an {@link Object} constructed from the PDX bytes described by this {@link PdxInstance}.
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see java.lang.Object
|
||||
* @see #getObjectMapper()
|
||||
*/
|
||||
@Override
|
||||
public Object getObject() {
|
||||
|
||||
return getObjectMapper()
|
||||
@@ -247,7 +353,7 @@ public class PdxInstanceWrapper implements PdxInstance, Sendable {
|
||||
return objectMapper.readValue(json, type);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
// TODO Add log statement
|
||||
// TODO Log Throwable?
|
||||
return null;
|
||||
}
|
||||
})
|
||||
@@ -370,6 +476,10 @@ public class PdxInstanceWrapper implements PdxInstance, Sendable {
|
||||
return String.format(FIELD_TYPE_VALUE, fieldName, nullSafeType(fieldValue), fieldValue);
|
||||
}
|
||||
|
||||
private boolean hasText(String value) {
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private boolean isArray(Object value) {
|
||||
return Objects.nonNull(value) && value.getClass().isArray();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
@@ -34,6 +35,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -264,6 +266,315 @@ public class PdxInstanceWrapperUnitTests {
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingAnIdentity() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Arrays.asList("age", "id", "name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(true).when(mockPdxInstance).isIdentityField(eq("id"));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq("id"));
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
assertThat(wrapper.getIdentifier()).isEqualTo(42);
|
||||
|
||||
verify(wrapper, never()).getId();
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("id"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("id"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(null).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(69).when(wrapper).getId();
|
||||
|
||||
assertThat(wrapper.getIdentifier()).isEqualTo(69);
|
||||
|
||||
verify(wrapper, times(1)).getId();
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, never()).isIdentityField(anyString());
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoIdentityFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Arrays.asList("", "age", null, "name", " ")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(any());
|
||||
doReturn(99).when(wrapper).getId();
|
||||
|
||||
assertThat(wrapper.getIdentifier()).isEqualTo(99);
|
||||
|
||||
verify(wrapper, times(1)).getId();
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(isNull());
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(""));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(" "));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getIdentifierFromPdxInstanceWithNoIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Collections.singletonList("name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(anyString());
|
||||
doThrow(new IllegalStateException("NO ID")).when(wrapper).getId();
|
||||
|
||||
try {
|
||||
wrapper.getIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("NO ID");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verify(wrapper, times(1)).getId();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceHavingIdField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
|
||||
assertThat(wrapper.getId()).isEqualTo(42);
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(wrapper, never()).getAtIdentifier();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceHavingIdFieldWithNoValueReturnsNull() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(null).when(mockPdxInstance).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
|
||||
assertThat(wrapper.getId()).isNull();
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(wrapper, never()).getAtIdentifier();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceWithNoIdFieldCallsGetAtIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(false).when(mockPdxInstance).hasField(any());
|
||||
doReturn(99).when(wrapper).getAtIdentifier();
|
||||
|
||||
assertThat(wrapper.getId()).isEqualTo(99);
|
||||
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(wrapper, times(1)).getAtIdentifier();
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAtIdentifierFromPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq("isbn"));
|
||||
doReturn("isbn").when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn("123456789").when(mockPdxInstance).getField(eq("isbn"));
|
||||
|
||||
assertThat(wrapper.getAtIdentifier()).isEqualTo("123456789");
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq("isbn"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("isbn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithNoDeclaredIdentity() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Account.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(false).when(mockPdxInstance).hasField(any());
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no declared identifier",
|
||||
Account.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Account.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no id",
|
||||
Account.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(any());
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithValidAtIdentifierAndIdentifierFieldButNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Person.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq("ssn"));
|
||||
doReturn("ssn").when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(null).when(mockPdxInstance).getField(eq("ssn"));
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
String expectedMessage = "PdxInstance for type [%s] has no value [null] for field [ssn] declared in [%s]";
|
||||
|
||||
assertThat(expected).hasMessage(expectedMessage, Person.class.getName(),
|
||||
PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2)).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).hasField(eq("ssn"));
|
||||
verify(mockPdxInstance, times(2)).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).getField(eq("ssn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithAtIdentifierReferringToInvalidIdentifierField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
PdxInstanceWrapper wrapper = spy(new PdxInstanceWrapper(mockPdxInstance));
|
||||
|
||||
doReturn(Person.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq("ssn"));
|
||||
doReturn("ssn").when(mockPdxInstance).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
|
||||
try {
|
||||
wrapper.getAtIdentifier();
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no field [ssn] declared in [%s]",
|
||||
Person.class.getName(), PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2)).hasField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq(PdxInstanceWrapper.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).hasField(eq("ssn"));
|
||||
verify(mockPdxInstance, times(2)).getField(eq(PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(eq("ssn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectReturnsObject() throws JsonProcessingException {
|
||||
|
||||
@@ -481,6 +792,8 @@ public class PdxInstanceWrapperUnitTests {
|
||||
String getName();
|
||||
}
|
||||
|
||||
interface Person { }
|
||||
|
||||
interface SendablePdxInstance extends PdxInstance, Sendable { }
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.geode.data.json;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
@@ -25,7 +23,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
@@ -42,6 +39,7 @@ import org.springframework.geode.data.CacheDataImporter;
|
||||
import org.springframework.geode.data.json.converter.AbstractObjectArrayToJsonConverter;
|
||||
import org.springframework.geode.data.json.converter.JsonToPdxArrayConverter;
|
||||
import org.springframework.geode.data.json.converter.support.JacksonJsonToPdxConverter;
|
||||
import org.springframework.geode.pdx.ObjectPdxInstanceAdapter;
|
||||
import org.springframework.geode.pdx.PdxInstanceWrapper;
|
||||
import org.springframework.geode.util.CacheUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
@@ -81,11 +79,8 @@ public class JsonCacheDataImporterExporter extends AbstractCacheDataImporterExpo
|
||||
private static final int CONTENT_PREVIEW_LENGTH = 50;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 32768;
|
||||
|
||||
protected static final String AT_IDENTIFIER_FIELD_NAME = PdxInstanceWrapper.AT_IDENTIFIER_FIELD_NAME;
|
||||
protected static final String CLASSPATH_RESOURCE_PREFIX = ResourceLoader.CLASSPATH_URL_PREFIX;
|
||||
protected static final String FILESYSTEM_RESOURCE_PREFIX = "file://";
|
||||
protected static final String ID_FIELD_NAME = PdxInstanceWrapper.ID_FIELD_NAME;
|
||||
protected static final String NO_FIELD_NAME = "";
|
||||
protected static final String RESOURCE_NAME_PATTERN = "data-%s.json";
|
||||
|
||||
private JsonToPdxArrayConverter jsonToPdxArrayConverter = newJsonToPdxArrayConverter();
|
||||
@@ -182,7 +177,7 @@ public class JsonCacheDataImporterExporter extends AbstractCacheDataImporterExpo
|
||||
.map(this::toPdx)
|
||||
.map(Arrays::stream)
|
||||
.ifPresent(pdxInstances -> pdxInstances.forEach(pdxInstance ->
|
||||
region.put(getIdentifier(pdxInstance), postProcess(pdxInstance))));
|
||||
region.put(resolveKey(pdxInstance), resolveValue(pdxInstance))));
|
||||
|
||||
return region;
|
||||
}
|
||||
@@ -223,107 +218,6 @@ public class JsonCacheDataImporterExporter extends AbstractCacheDataImporterExpo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the {@link Object identifier} (a.k.a. {@link PdxInstance#isIdentityField(String) identity})
|
||||
* for the given {@link PdxInstance}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to evaluate; must not be {@literal null}.
|
||||
* @return the {@link Object identifier} for the given {@link PdxInstance}; never {@literal null}.
|
||||
* @throws IllegalArgumentException if {@link PdxInstance} is {@literal null}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #getId(PdxInstance)
|
||||
*/
|
||||
protected @NonNull Object getIdentifier(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
Assert.notNull(pdxInstance, "PdxInstance must not be null");
|
||||
|
||||
Optional<String> idFieldName = CollectionUtils.nullSafeList(pdxInstance.getFieldNames()).stream()
|
||||
.filter(StringUtils::hasText)
|
||||
.filter(pdxInstance::isIdentityField)
|
||||
.findFirst();
|
||||
|
||||
return idFieldName
|
||||
.map(pdxInstance::getField)
|
||||
.orElseGet(() -> getId(pdxInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field name} called {@literal id} on the given {@link PdxInstance}
|
||||
* and returns its {@link Object value} as the {@link Object identifier} for the {@link PdxInstance}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to evaluate; must not be {@literal null}.
|
||||
* @return the {@link Object value} of the {@literal id} {@link String field} on the {@link PdxInstance}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #getAtIdentifier(PdxInstance)
|
||||
*/
|
||||
protected @NonNull Object getId(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
Assert.notNull(pdxInstance, "PdxInstance must not be null");
|
||||
|
||||
return Optional.of(pdxInstance)
|
||||
.filter(it -> it.hasField(ID_FIELD_NAME))
|
||||
.map(it -> it.getField(ID_FIELD_NAME))
|
||||
.orElseGet(() -> getAtIdentifier(pdxInstance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a PDX {@link String field} declared by the {@literal @identifier} metadata {@link String field}
|
||||
* on the given {@link PdxInstance} and returns the {@link Object value} of this {@link String field}
|
||||
* as the {@link Object identifier} for the {@link PdxInstance}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to evaluate; most not be {@literal null}.
|
||||
* @return the {@link Object value} of the {@link String field} declared in the {@literal @identifier} metadata
|
||||
* {@link String field} on the {@link PdxInstance}.
|
||||
* @throws IllegalArgumentException if {@link PdxInstance} is {@literal null}.
|
||||
* @throws IllegalStateException if the {@link PdxInstance} does not have an id.
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
protected @NonNull Object getAtIdentifier(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
Assert.notNull(pdxInstance, "PdxInstance must not be null");
|
||||
|
||||
return Optional.of(pdxInstance)
|
||||
.filter(pdx -> pdx.hasField(AT_IDENTIFIER_FIELD_NAME))
|
||||
.map(pdx -> pdx.getField(AT_IDENTIFIER_FIELD_NAME))
|
||||
.map(String::valueOf)
|
||||
.filter(pdxInstance::hasField)
|
||||
.map(pdxInstance::getField)
|
||||
.orElseThrow(() -> newIllegalStateException(String.format("PdxInstance for type [%1$s] has no %2$s",
|
||||
pdxInstance.getClassName(), resolveMessageForIdentifierError(pdxInstance))));
|
||||
}
|
||||
|
||||
private @NonNull String resolveMessageForIdentifierError(@NonNull PdxInstance pdxInstance) {
|
||||
|
||||
String message = "declared identifier";
|
||||
|
||||
if (pdxInstance.hasField(ID_FIELD_NAME)) {
|
||||
message = "id";
|
||||
}
|
||||
else if (pdxInstance.hasField(AT_IDENTIFIER_FIELD_NAME)) {
|
||||
|
||||
Object atIdentifierFieldValue = pdxInstance.getField(AT_IDENTIFIER_FIELD_NAME);
|
||||
|
||||
String resolvedIdentifierFieldName = Objects.nonNull(atIdentifierFieldValue)
|
||||
? atIdentifierFieldValue.toString().trim()
|
||||
: NO_FIELD_NAME;
|
||||
|
||||
boolean identifierFieldNameWasDeclaredAndIsValid = pdxInstance.hasField(resolvedIdentifierFieldName);
|
||||
|
||||
Object identifier = identifierFieldNameWasDeclaredAndIsValid
|
||||
? pdxInstance.getField(resolvedIdentifierFieldName)
|
||||
: null;
|
||||
|
||||
message = identifierFieldNameWasDeclaredAndIsValid
|
||||
? String.format("value [%s] for field [%s] declared in [%s]", identifier, resolvedIdentifierFieldName,
|
||||
AT_IDENTIFIER_FIELD_NAME)
|
||||
: String.format("field [%s] declared in [%s]", resolvedIdentifierFieldName, AT_IDENTIFIER_FIELD_NAME);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a computed JSON {@link Resource} containing JSON data to be loaded into the given {@link Region}.
|
||||
*
|
||||
@@ -372,6 +266,41 @@ public class JsonCacheDataImporterExporter extends AbstractCacheDataImporterExpo
|
||||
return pdxInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link Object key} used to map the given {@link PdxInstance} as the {@link Object value}
|
||||
* for the {@link Region.Entry entry} stored in the {@link Region}.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} used to resolve the {@link Object key}.
|
||||
* @return the resolved {@link Object key}.
|
||||
* @see org.springframework.geode.pdx.PdxInstanceWrapper#getIdentifier()
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
*/
|
||||
protected @NonNull Object resolveKey(@NonNull PdxInstance pdxInstance) {
|
||||
return PdxInstanceWrapper.from(pdxInstance).getIdentifier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link Object value} to store in the {@link Region} from the given {@link PdxInstance}.
|
||||
*
|
||||
* If the given {@link PdxInstance} is an instance of {@link PdxInstanceWrapper} then this method will return
|
||||
* the underlying, {@link PdxInstanceWrapper#getDelegate() delegate} {@link PdxInstance}.
|
||||
*
|
||||
* If the given {@link PdxInstance} is an instance of {@link ObjectPdxInstanceAdapter} then this method will return
|
||||
* the underlying, {@link ObjectPdxInstanceAdapter#getObject() Object}.
|
||||
*
|
||||
* Otherwise, the given {@link PdxInstance} is returned.
|
||||
*
|
||||
* @param pdxInstance {@link PdxInstance} to unwrap.
|
||||
* @return the resolved {@link Object value}.
|
||||
* @see org.springframework.geode.pdx.ObjectPdxInstanceAdapter#unwrap(PdxInstance)
|
||||
* @see org.springframework.geode.pdx.PdxInstanceWrapper#unwrap(PdxInstance)
|
||||
* @see org.apache.geode.pdx.PdxInstance
|
||||
* @see #postProcess(PdxInstance)
|
||||
*/
|
||||
protected @Nullable Object resolveValue(@Nullable PdxInstance pdxInstance) {
|
||||
return ObjectPdxInstanceAdapter.unwrap(PdxInstanceWrapper.unwrap(postProcess(pdxInstance)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link Object values} contained in the {@link Region} to {@link String JSON}.
|
||||
*
|
||||
|
||||
@@ -37,8 +37,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -56,9 +54,6 @@ import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.geode.data.json.converter.JsonToPdxArrayConverter;
|
||||
|
||||
import example.app.crm.model.Customer;
|
||||
import example.app.pos.model.LineItem;
|
||||
|
||||
/**
|
||||
* Unit Tests for {@link JsonCacheDataImporterExporter}.
|
||||
*
|
||||
@@ -229,8 +224,8 @@ public class JsonCacheDataImporterExporterUnitTests {
|
||||
doReturn(true).when(mockResource).exists();
|
||||
doReturn(json).when(this.importer).getContent(eq(mockResource));
|
||||
doReturn(ArrayUtils.asArray(mockPdxInstanceOne, mockPdxInstanceTwo)).when(this.importer).toPdx(eq(json));
|
||||
doReturn(1).when(this.importer).getIdentifier(eq(mockPdxInstanceOne));
|
||||
doReturn(2).when(this.importer).getIdentifier(eq(mockPdxInstanceTwo));
|
||||
doReturn(1).when(this.importer).resolveKey(eq(mockPdxInstanceOne));
|
||||
doReturn(2).when(this.importer).resolveKey(eq(mockPdxInstanceTwo));
|
||||
|
||||
assertThat(this.importer.doImportInto(mockRegion)).isEqualTo(mockRegion);
|
||||
|
||||
@@ -238,10 +233,12 @@ public class JsonCacheDataImporterExporterUnitTests {
|
||||
.getResource(eq(mockRegion), eq(JsonCacheDataImporterExporter.CLASSPATH_RESOURCE_PREFIX));
|
||||
verify(this.importer, times(1)).getContent(eq(mockResource));
|
||||
verify(this.importer, times(1)).toPdx(eq(json));
|
||||
verify(this.importer, times(1)).resolveKey(eq(mockPdxInstanceOne));
|
||||
verify(this.importer, times(1)).postProcess(eq(mockPdxInstanceOne));
|
||||
verify(this.importer, times(1)).getIdentifier(eq(mockPdxInstanceOne));
|
||||
verify(this.importer, times(1)).resolveValue(eq(mockPdxInstanceOne));
|
||||
verify(this.importer, times(1)).resolveKey(eq(mockPdxInstanceTwo));
|
||||
verify(this.importer, times(1)).postProcess(eq(mockPdxInstanceTwo));
|
||||
verify(this.importer, times(1)).getIdentifier(eq(mockPdxInstanceTwo));
|
||||
verify(this.importer, times(1)).resolveValue(eq(mockPdxInstanceTwo));
|
||||
verify(mockResource, times(1)).exists();
|
||||
verify(mockRegion, times(1)).put(eq(1), eq(mockPdxInstanceOne));
|
||||
verify(mockRegion, times(1)).put(eq(2), eq(mockPdxInstanceTwo));
|
||||
@@ -411,345 +408,6 @@ public class JsonCacheDataImporterExporterUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingIdentity() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Arrays.asList("age", "id", "name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(true).when(mockPdxInstance).isIdentityField(eq("id"));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq("id"));
|
||||
|
||||
assertThat(this.importer.getIdentifier(mockPdxInstance)).isEqualTo(42);
|
||||
|
||||
verify(this.importer, never()).getId(any(PdxInstance.class));
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("id"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(null).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(69).when(this.importer).getId(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.getIdentifier(mockPdxInstance)).isEqualTo(69);
|
||||
|
||||
verify(this.importer, times(1)).getId(eq(mockPdxInstance));
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, never()).isIdentityField(anyString());
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdentifierFromPdxInstanceHavingNoIdentityFields() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Arrays.asList("", "age", null, "name", " ")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(any());
|
||||
doReturn(99).when(this.importer).getId(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.getIdentifier(mockPdxInstance)).isEqualTo(99);
|
||||
|
||||
verify(this.importer, times(1)).getId(eq(mockPdxInstance));
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("age"));
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).isIdentityField(isNull());
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(""));
|
||||
verify(mockPdxInstance, never()).isIdentityField(eq(" "));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getIdentifierFromPdxInstanceWithNoIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Collections.singletonList("name")).when(mockPdxInstance).getFieldNames();
|
||||
doReturn(false).when(mockPdxInstance).isIdentityField(anyString());
|
||||
doThrow(new IllegalStateException("NO ID")).when(this.importer).getId(eq(mockPdxInstance));
|
||||
|
||||
try {
|
||||
this.importer.getIdentifier(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("NO ID");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getFieldNames();
|
||||
verify(mockPdxInstance, times(1)).isIdentityField(eq("name"));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getIdentifierFromNullPdxInstance() {
|
||||
|
||||
try {
|
||||
this.importer.getIdentifier(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceHavingIdField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(42).when(mockPdxInstance).getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
|
||||
assertThat(this.importer.getId(mockPdxInstance)).isEqualTo(42);
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(this.importer, never()).getAtIdentifier(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceHavingIdFieldWithNoValueCallsGetAtIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(null).when(mockPdxInstance).getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(69).when(this.importer).getAtIdentifier(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.getId(mockPdxInstance)).isEqualTo(69);
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(this.importer, times(1)).getAtIdentifier(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIdFromPdxInstanceWithNoIdFieldCallsGetAtIdentifier() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(false).when(mockPdxInstance).hasField(any());
|
||||
doReturn(99).when(this.importer).getAtIdentifier(eq(mockPdxInstance));
|
||||
|
||||
assertThat(this.importer.getId(mockPdxInstance)).isEqualTo(99);
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(this.importer, times(1)).getAtIdentifier(eq(mockPdxInstance));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getIdFromNullPdxInstance() {
|
||||
|
||||
try {
|
||||
this.importer.getId(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAtIdentifierFromPdxInstance() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(true).when(mockPdxInstance)
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq("isbn"));
|
||||
doReturn("isbn").when(mockPdxInstance)
|
||||
.getField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn("123456789").when(mockPdxInstance).getField(eq("isbn"));
|
||||
|
||||
assertThat(this.importer.getAtIdentifier(mockPdxInstance)).isEqualTo("123456789");
|
||||
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.getField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1)).hasField(eq("isbn"));
|
||||
verify(mockPdxInstance, times(1)).getField(eq("isbn"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getAtIdentifierWithNullPdxInstance() {
|
||||
|
||||
try {
|
||||
this.importer.getAtIdentifier(null);
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance must not be null");
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithNoDeclaredIdentity() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(LineItem.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(false).when(mockPdxInstance).hasField(any());
|
||||
|
||||
try {
|
||||
this.importer.getAtIdentifier(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no declared identifier",
|
||||
LineItem.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(LineItem.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
|
||||
try {
|
||||
this.importer.getAtIdentifier(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected).hasMessage("PdxInstance for type [%s] has no id",
|
||||
LineItem.class.getName());
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(any());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithValidAtIdentifierAndIdentifierFieldButNoId() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Customer.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance)
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance)
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(true).when(mockPdxInstance).hasField(eq("ssn"));
|
||||
doReturn("ssn").when(mockPdxInstance)
|
||||
.getField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(null).when(mockPdxInstance).getField(eq("ssn"));
|
||||
|
||||
try {
|
||||
this.importer.getAtIdentifier(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("PdxInstance for type [%s] has no value [null] for field [ssn] declared in [%s]",
|
||||
Customer.class.getName(), JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).hasField(eq("ssn"));
|
||||
verify(mockPdxInstance, times(2))
|
||||
.getField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).getField(eq("ssn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void getAtIdentifierFromPdxInstanceWithAtIdentifierReferringToInvalidIdentifierField() {
|
||||
|
||||
PdxInstance mockPdxInstance = mock(PdxInstance.class);
|
||||
|
||||
doReturn(Customer.class.getName()).when(mockPdxInstance).getClassName();
|
||||
doReturn(true).when(mockPdxInstance)
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance)
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
doReturn(false).when(mockPdxInstance).hasField(eq("ssn"));
|
||||
doReturn("ssn").when(mockPdxInstance)
|
||||
.getField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
|
||||
try {
|
||||
this.importer.getAtIdentifier(mockPdxInstance);
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
|
||||
assertThat(expected)
|
||||
.hasMessage("PdxInstance for type [%s] has no field [ssn] declared in [%s]",
|
||||
Customer.class.getName(), JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME);
|
||||
assertThat(expected).hasNoCause();
|
||||
|
||||
throw expected;
|
||||
}
|
||||
finally {
|
||||
verify(mockPdxInstance, times(1)).getClassName();
|
||||
verify(mockPdxInstance, times(2))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(1))
|
||||
.hasField(eq(JsonCacheDataImporterExporter.ID_FIELD_NAME));
|
||||
verify(mockPdxInstance, times(2)).hasField(eq("ssn"));
|
||||
verify(mockPdxInstance, times(2))
|
||||
.getField(eq(JsonCacheDataImporterExporter.AT_IDENTIFIER_FIELD_NAME));
|
||||
verify(mockPdxInstance, never()).getField(eq("ssn"));
|
||||
verifyNoMoreInteractions(mockPdxInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceFromRegionAndResourcePrefix() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user