DATAES-628 - Adapt mappers to Document API.

This commit is contained in:
Mark Paluch 2019-08-12 15:59:19 +02:00 committed by Peter-Josef Meisch
parent 29ecd484c5
commit 7a612f3ba8
8 changed files with 175 additions and 167 deletions

View File

@ -17,11 +17,11 @@ package org.springframework.data.elasticsearch.core;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.core.geo.CustomGeoModule; import org.springframework.data.elasticsearch.core.geo.CustomGeoModule;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
@ -44,6 +44,7 @@ import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
* @author Petar Tahchiev * @author Petar Tahchiev
* @author Oliver Gierke * @author Oliver Gierke
* @author Christoph Strobl * @author Christoph Strobl
* @author Mark Paluch
*/ */
public class DefaultEntityMapper implements EntityMapper { public class DefaultEntityMapper implements EntityMapper {
@ -51,7 +52,7 @@ public class DefaultEntityMapper implements EntityMapper {
/** /**
* Creates a new {@link DefaultEntityMapper} using the given {@link MappingContext}. * Creates a new {@link DefaultEntityMapper} using the given {@link MappingContext}.
* *
* @param context must not be {@literal null}. * @param context must not be {@literal null}.
*/ */
public DefaultEntityMapper( public DefaultEntityMapper(
@ -74,7 +75,8 @@ public class DefaultEntityMapper implements EntityMapper {
*/ */
@Override @Override
public String mapToString(Object object) throws IOException { public String mapToString(Object object) throws IOException {
return objectMapper.writeValueAsString(object); return objectMapper
.writeValueAsString(object instanceof Document ? new LinkedHashMap<>((Document) object) : object);
} }
/* /*
@ -82,10 +84,10 @@ public class DefaultEntityMapper implements EntityMapper {
* @see org.springframework.data.elasticsearch.core.EntityMapper#mapObject(java.lang.Object) * @see org.springframework.data.elasticsearch.core.EntityMapper#mapObject(java.lang.Object)
*/ */
@Override @Override
public Map<String, Object> mapObject(Object source) { public Document mapObject(Object source) {
try { try {
return objectMapper.readValue(mapToString(source), HashMap.class); return objectMapper.readValue(mapToString(source), Document.class);
} catch (IOException e) { } catch (IOException e) {
throw new MappingException(e.getMessage(), e); throw new MappingException(e.getMessage(), e);
} }
@ -105,8 +107,7 @@ public class DefaultEntityMapper implements EntityMapper {
* @see org.springframework.data.elasticsearch.core.EntityMapper#readObject(java.util.Map, java.lang.Class) * @see org.springframework.data.elasticsearch.core.EntityMapper#readObject(java.util.Map, java.lang.Class)
*/ */
@Override @Override
public <T> T readObject (Map<String, Object> source, Class<T> targetType) { public <T> T readObject(Document source, Class<T> targetType) {
try { try {
return mapToObject(mapToString(source), targetType); return mapToObject(mapToString(source), targetType);
} catch (IOException e) { } catch (IOException e) {
@ -126,7 +127,7 @@ public class DefaultEntityMapper implements EntityMapper {
/** /**
* Creates a new {@link SpringDataElasticsearchModule} using the given {@link MappingContext}. * Creates a new {@link SpringDataElasticsearchModule} using the given {@link MappingContext}.
* *
* @param context must not be {@literal null}. * @param context must not be {@literal null}.
*/ */
public SpringDataElasticsearchModule( public SpringDataElasticsearchModule(
@ -156,7 +157,7 @@ public class DefaultEntityMapper implements EntityMapper {
this.context = context; this.context = context;
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see com.fasterxml.jackson.databind.ser.BeanSerializerModifier#changeProperties(com.fasterxml.jackson.databind.SerializationConfig, com.fasterxml.jackson.databind.BeanDescription, java.util.List) * @see com.fasterxml.jackson.databind.ser.BeanSerializerModifier#changeProperties(com.fasterxml.jackson.databind.SerializationConfig, com.fasterxml.jackson.databind.BeanDescription, java.util.List)
*/ */

View File

@ -15,11 +15,7 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.GetResponse;
@ -45,11 +41,6 @@ import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor; import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
/** /**
* @author Artur Konczak * @author Artur Konczak
@ -105,13 +96,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
List<T> results = new ArrayList<>(); List<T> results = new ArrayList<>();
for (SearchHit hit : response.getHits()) { for (SearchHit hit : response.getHits()) {
if (hit != null) { if (hit != null) {
T result = null; T result = mapSearchHit(hit, clazz);
String hitSourceAsString = hit.getSourceAsString();
if (!StringUtils.isEmpty(hitSourceAsString)) {
result = mapEntity(hitSourceAsString, clazz);
} else {
result = mapEntity(hit.getFields().values(), clazz);
}
setPersistentEntityId(result, hit.getId(), clazz); setPersistentEntityId(result, hit.getId(), clazz);
setPersistentEntityVersion(result, hit.getVersion(), clazz); setPersistentEntityVersion(result, hit.getVersion(), clazz);
@ -149,38 +134,14 @@ public class DefaultResultMapper extends AbstractResultMapper {
} }
} }
private <T> T mapEntity(Collection<DocumentField> values, Class<T> clazz) {
return mapEntity(buildJSONFromFields(values), clazz);
}
private String buildJSONFromFields(Collection<DocumentField> values) {
JsonFactory nodeFactory = new JsonFactory();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = nodeFactory.createGenerator(stream, JsonEncoding.UTF8);
generator.writeStartObject();
for (DocumentField value : values) {
if (value.getValues().size() > 1) {
generator.writeArrayFieldStart(value.getName());
for (Object val : value.getValues()) {
generator.writeObject(val);
}
generator.writeEndArray();
} else {
generator.writeObjectField(value.getName(), value.getValue());
}
}
generator.writeEndObject();
generator.flush();
return new String(stream.toByteArray(), Charset.forName("UTF-8"));
} catch (IOException e) {
return null;
}
}
@Override @Override
public <T> T mapResult(GetResponse response, Class<T> clazz) { public <T> T mapResult(GetResponse response, Class<T> clazz) {
T result = mapEntity(response.getSourceAsString(), clazz);
if (!response.isExists()) {
return null;
}
T result = mapDocument(DocumentAdapters.from(response), clazz);
if (result != null) { if (result != null) {
setPersistentEntityId(result, response.getId(), clazz); setPersistentEntityId(result, response.getId(), clazz);
setPersistentEntityVersion(result, response.getVersion(), clazz); setPersistentEntityVersion(result, response.getVersion(), clazz);
@ -193,7 +154,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
for (MultiGetItemResponse response : responses.getResponses()) { for (MultiGetItemResponse response : responses.getResponses()) {
if (!response.isFailed() && response.getResponse().isExists()) { if (!response.isFailed() && response.getResponse().isExists()) {
T result = mapEntity(response.getResponse().getSourceAsString(), clazz); T result = mapResult(response.getResponse(), clazz);
setPersistentEntityId(result, response.getResponse().getId(), clazz); setPersistentEntityId(result, response.getResponse().getId(), clazz);
setPersistentEntityVersion(result, response.getResponse().getVersion(), clazz); setPersistentEntityVersion(result, response.getResponse().getVersion(), clazz);
list.add(result); list.add(result);

View File

@ -15,8 +15,6 @@
*/ */
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.io.IOException; import java.io.IOException;
@ -34,6 +32,8 @@ import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.convert.EntityInstantiators; import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.convert.EntityReader; import org.springframework.data.convert.EntityReader;
import org.springframework.data.convert.EntityWriter; import org.springframework.data.convert.EntityWriter;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.SearchDocument;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions; import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchTypeMapper; import org.springframework.data.elasticsearch.core.convert.ElasticsearchTypeMapper;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
@ -52,6 +52,8 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
/** /**
* Elasticsearch specific {@link EntityReader} & {@link EntityWriter} implementation based on domain type * Elasticsearch specific {@link EntityReader} & {@link EntityWriter} implementation based on domain type
@ -59,12 +61,12 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* *
* @author Christoph Strobl * @author Christoph Strobl
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Mark Paluch
* @since 3.2 * @since 3.2
*/ */
public class ElasticsearchEntityMapper implements public class ElasticsearchEntityMapper
EntityConverter<ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty, Object, Map<String, Object>>, implements EntityConverter<ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty, Object, Document>,
EntityWriter<Object, Map<String, Object>>, EntityReader<Object, Map<String, Object>>, InitializingBean, EntityWriter<Object, Document>, EntityReader<Object, Document>, InitializingBean, EntityMapper {
EntityMapper {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext; private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private final GenericConversionService conversionService; private final GenericConversionService conversionService;
@ -134,14 +136,14 @@ public class ElasticsearchEntityMapper implements
// --> READ // --> READ
@Override @Override
public <T> T readObject(Map<String, Object> source, Class<T> targetType) { public <T> T readObject(Document source, Class<T> targetType) {
return read(targetType, source); return read(targetType, source);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
@Nullable @Nullable
public <R> R read(Class<R> type, Map<String, Object> source) { public <R> R read(Class<R> type, Document source) {
return doRead(source, ClassTypeInformation.from((Class<R>) ClassUtils.getUserClass(type))); return doRead(source, ClassTypeInformation.from((Class<R>) ClassUtils.getUserClass(type)));
} }
@ -320,16 +322,16 @@ public class ElasticsearchEntityMapper implements
// --> WRITE // --> WRITE
@Override @Override
public Map<String, Object> mapObject(Object source) { public Document mapObject(Object source) {
LinkedHashMap<String, Object> target = new LinkedHashMap<>(); Document target = Document.create();
write(source, target); write(source, target);
return target; return target;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void write(@Nullable Object source, Map<String, Object> sink) { public void write(@Nullable Object source, Document sink) {
if (source == null) { if (source == null) {
return; return;
@ -351,8 +353,7 @@ public class ElasticsearchEntityMapper implements
doWrite(source, sink, type); doWrite(source, sink, type);
} }
protected void doWrite(@Nullable Object source, Map<String, Object> sink, protected void doWrite(@Nullable Object source, Document sink, @Nullable TypeInformation<? extends Object> typeHint) {
@Nullable TypeInformation<? extends Object> typeHint) {
if (source == null) { if (source == null) {
return; return;
@ -382,7 +383,7 @@ public class ElasticsearchEntityMapper implements
writeEntity(entity, source, sink, null); writeEntity(entity, source, sink, null);
} }
protected void writeEntity(ElasticsearchPersistentEntity<?> entity, Object source, Map<String, Object> sink, protected void writeEntity(ElasticsearchPersistentEntity<?> entity, Object source, Document sink,
@Nullable TypeInformation containingStructure) { @Nullable TypeInformation containingStructure) {
PersistentPropertyAccessor<?> accessor = entity.getPropertyAccessor(source); PersistentPropertyAccessor<?> accessor = entity.getPropertyAccessor(source);
@ -391,11 +392,11 @@ public class ElasticsearchEntityMapper implements
typeMapper.writeType(source.getClass(), sink); typeMapper.writeType(source.getClass(), sink);
} }
writeProperties(entity, accessor, sink); writeProperties(entity, accessor, new MapValueAccessor(sink));
} }
protected void writeProperties(ElasticsearchPersistentEntity<?> entity, PersistentPropertyAccessor<?> accessor, protected void writeProperties(ElasticsearchPersistentEntity<?> entity, PersistentPropertyAccessor<?> accessor,
Map<String, Object> sink) { MapValueAccessor sink) {
for (ElasticsearchPersistentProperty property : entity) { for (ElasticsearchPersistentProperty property : entity) {
@ -412,19 +413,19 @@ public class ElasticsearchEntityMapper implements
if (!isSimpleType(value)) { if (!isSimpleType(value)) {
writeProperty(property, value, sink); writeProperty(property, value, sink);
} else { } else {
sink.put(property.getFieldName(), getWriteSimpleValue(value)); sink.set(property, getWriteSimpleValue(value));
} }
} }
} }
protected void writeProperty(ElasticsearchPersistentProperty property, Object value, Map<String, Object> sink) { protected void writeProperty(ElasticsearchPersistentProperty property, Object value, MapValueAccessor sink) {
Optional<Class<?>> customWriteTarget = conversions.getCustomWriteTarget(value.getClass()); Optional<Class<?>> customWriteTarget = conversions.getCustomWriteTarget(value.getClass());
if (customWriteTarget.isPresent()) { if (customWriteTarget.isPresent()) {
Class<?> writeTarget = customWriteTarget.get(); Class<?> writeTarget = customWriteTarget.get();
sink.put(property.getFieldName(), conversionService.convert(value, writeTarget)); sink.set(property, conversionService.convert(value, writeTarget));
return; return;
} }
@ -442,7 +443,7 @@ public class ElasticsearchEntityMapper implements
} }
} }
sink.put(property.getFieldName(), getWriteComplexValue(property, typeHint, value)); sink.set(property, getWriteComplexValue(property, typeHint, value));
} }
protected Object getWriteSimpleValue(Object value) { protected Object getWriteSimpleValue(Object value) {
@ -479,7 +480,8 @@ public class ElasticsearchEntityMapper implements
} }
private Object writeEntity(Object value, ElasticsearchPersistentProperty property, TypeInformation<?> typeHint) { private Object writeEntity(Object value, ElasticsearchPersistentProperty property, TypeInformation<?> typeHint) {
Map<String, Object> target = new LinkedHashMap<>();
Document target = Document.create();
writeEntity(mappingContext.getRequiredPersistentEntity(value.getClass()), value, target, writeEntity(mappingContext.getRequiredPersistentEntity(value.getClass()), value, target,
property.getTypeInformation()); property.getTypeInformation());
return target; return target;
@ -549,15 +551,15 @@ public class ElasticsearchEntityMapper implements
@Override @Override
public String mapToString(Object source) throws IOException { public String mapToString(Object source) throws IOException {
Map<String, Object> sink = new LinkedHashMap<>(); Document sink = Document.create();
write(source, sink); write(source, sink);
return objectWriter.writeValueAsString(sink); return objectWriter.writeValueAsString(new LinkedHashMap<>(sink));
} }
@Override @Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException { public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
return read(clazz, objectReader.readValue(source)); return read(clazz, Document.from(objectReader.readValue(source)));
} }
// --> PRIVATE HELPERS // --> PRIVATE HELPERS
@ -669,6 +671,18 @@ public class ElasticsearchEntityMapper implements
public Object get(ElasticsearchPersistentProperty property) { public Object get(ElasticsearchPersistentProperty property) {
if (property.isIdProperty() && ((Document) target).hasId()) {
return ((Document) target).getId();
}
if (property.isVersionProperty() && ((Document) target).hasVersion()) {
return ((Document) target).getVersion();
}
if (property.isScoreProperty()) {
return ((SearchDocument) target).getScore();
}
String fieldName = property.getFieldName(); String fieldName = property.getFieldName();
if (!fieldName.contains(".")) { if (!fieldName.contains(".")) {
@ -691,6 +705,19 @@ public class ElasticsearchEntityMapper implements
return result; return result;
} }
public void set(ElasticsearchPersistentProperty property, Object value) {
if (property.isIdProperty()) {
((Document) target).setId((String) value);
}
if (property.isVersionProperty()) {
((Document) target).setVersion((Long) value);
}
target.put(property.getFieldName(), value);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Map<String, Object> getAsMap(Object result) { private Map<String, Object> getAsMap(Object result) {

View File

@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import org.springframework.data.elasticsearch.Document;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
@ -27,6 +28,7 @@ import org.springframework.lang.Nullable;
* @author Rizwan Idrees * @author Rizwan Idrees
* @author Mohsin Husen * @author Mohsin Husen
* @author Christoph Strobl * @author Christoph Strobl
* @author Mark Paluch
*/ */
public interface EntityMapper { public interface EntityMapper {
@ -41,7 +43,7 @@ public interface EntityMapper {
* @return never {@literal null} * @return never {@literal null}
* @since 3.2 * @since 3.2
*/ */
Map<String, Object> mapObject(Object source); Document mapObject(Object source);
/** /**
* Map the given {@link Map} into an instance of the {@literal targetType}. * Map the given {@link Map} into an instance of the {@literal targetType}.
@ -53,5 +55,5 @@ public interface EntityMapper {
* @since 3.2 * @since 3.2
*/ */
@Nullable @Nullable
<T> T readObject(Map<String, Object> source, Class<T> targetType); <T> T readObject(Document source, Class<T> targetType);
} }

View File

@ -16,10 +16,11 @@
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.ElasticsearchException; import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
@ -34,6 +35,7 @@ import org.springframework.util.StringUtils;
* @author Mohsin Husen * @author Mohsin Husen
* @author Artur Konczak * @author Artur Konczak
* @author Christoph Strobl * @author Christoph Strobl
* @author Mark Paluch
*/ */
public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper { public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper {
@ -50,6 +52,7 @@ public interface ResultsMapper extends SearchResultMapper, GetResultMapper, Mult
} }
@Nullable @Nullable
@Deprecated
default <T> T mapEntity(String source, Class<T> clazz) { default <T> T mapEntity(String source, Class<T> clazz) {
if (StringUtils.isEmpty(source)) { if (StringUtils.isEmpty(source)) {
@ -63,27 +66,18 @@ public interface ResultsMapper extends SearchResultMapper, GetResultMapper, Mult
} }
/** /**
* Map a single {@link GetResult} to an instance of the given type. * Map a single {@link Document} to an instance of the given type.
* *
* @param getResult must not be {@literal null}. * @param document must not be {@literal null}.
* @param type must not be {@literal null}. * @param type must not be {@literal null}.
* @param <T> * @param <T>
* @return can be {@literal null} if the {@link GetResult#isSourceEmpty() is empty}. * @return can be {@literal null} if the {@link Document#isEmpty() is empty}.
* @since 3.2 * @since 4.0
*/ */
@Nullable @Nullable
default <T> T mapGetResult(GetResult getResult, Class<T> type) { default <T> T mapDocument(Document document, Class<T> type) {
if (getResult.isSourceEmpty()) { Object mappedResult = getEntityMapper().readObject(document, type);
return null;
}
Map<String, Object> source = getResult.getSource();
if (!source.containsKey("id") || source.get("id") == null) {
source.put("id", getResult.getId());
}
Object mappedResult = getEntityMapper().readObject(source, type);
if (mappedResult == null) { if (mappedResult == null) {
return (T) null; return (T) null;
@ -96,6 +90,20 @@ public interface ResultsMapper extends SearchResultMapper, GetResultMapper, Mult
return type.cast(mappedResult); return type.cast(mappedResult);
} }
/**
* Map a single {@link GetResult} to an instance of the given type.
*
* @param getResult must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null} if the {@link GetResult#isSourceEmpty() is empty}.
* @since 3.2
*/
@Nullable
default <T> T mapGetResult(GetResult getResult, Class<T> type) {
return mapDocument(DocumentAdapters.from(getResult), type);
}
/** /**
* Map a single {@link SearchHit} to an instance of the given type. * Map a single {@link SearchHit} to an instance of the given type.
* *
@ -107,26 +115,6 @@ public interface ResultsMapper extends SearchResultMapper, GetResultMapper, Mult
*/ */
@Nullable @Nullable
default <T> T mapSearchHit(SearchHit searchHit, Class<T> type) { default <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
return mapDocument(DocumentAdapters.from(searchHit), type);
if (!searchHit.hasSource()) {
return null;
}
Map<String, Object> source = searchHit.getSourceAsMap();
if (!source.containsKey("id") || source.get("id") == null) {
source.put("id", searchHit.getId());
}
Object mappedResult = getEntityMapper().readObject(source, type);
if (mappedResult == null) {
return null;
}
if (type.isInterface()) {
return getProjectionFactory().createProjection(type, mappedResult);
}
return type.cast(mappedResult);
} }
} }

View File

@ -16,11 +16,13 @@
package org.springframework.data.elasticsearch.core; package org.springframework.data.elasticsearch.core;
import java.io.IOException; import java.io.IOException;
import java.util.Map;
import org.springframework.data.elasticsearch.Document;
/** /**
* @author Artur Konczak * @author Artur Konczak
* @author Mohsin Husen * @author Mohsin Husen
* @author Mark Paluch
*/ */
public class CustomEntityMapper implements EntityMapper { public class CustomEntityMapper implements EntityMapper {
@ -41,12 +43,12 @@ public class CustomEntityMapper implements EntityMapper {
} }
@Override @Override
public Map<String, Object> mapObject(Object source) { public Document mapObject(Object source) {
return null; return null;
} }
@Override @Override
public <T> T readObject(Map<String, Object> source, Class<T> targetType) { public <T> T readObject(Document source, Class<T> targetType) {
return null; return null;
} }
} }

View File

@ -30,6 +30,7 @@ import java.lang.Object;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -38,6 +39,7 @@ import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse; import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.document.DocumentField; import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.SearchHits;
@ -172,7 +174,14 @@ public class DefaultResultMapperTests {
// given // given
GetResponse response = mock(GetResponse.class); GetResponse response = mock(GetResponse.class);
when(response.getSourceAsString()).thenReturn(createJsonCar("Ford", "Grat")); when(response.isExists()).thenReturn(true);
Map<String, Object> sourceAsMap = new HashMap<>();
sourceAsMap.put("name", "Ford");
sourceAsMap.put("model", "Grat");
when(response.getSourceAsMap()).thenReturn(sourceAsMap);
when(response.getSourceAsBytesRef()).thenReturn(new BytesArray(" "));
// when // when
Car result = resultMapper.mapResult(response, Car.class); Car result = resultMapper.mapResult(response, Car.class);
@ -188,7 +197,9 @@ public class DefaultResultMapperTests {
public void setsIdentifierOnImmutableType() { public void setsIdentifierOnImmutableType() {
GetResponse response = mock(GetResponse.class); GetResponse response = mock(GetResponse.class);
when(response.isExists()).thenReturn(true);
when(response.getSourceAsString()).thenReturn("{}"); when(response.getSourceAsString()).thenReturn("{}");
when(response.getSourceAsBytesRef()).thenReturn(new BytesArray("{}"));
when(response.getId()).thenReturn("identifier"); when(response.getId()).thenReturn("identifier");
ImmutableEntity result = resultMapper.mapResult(response, ImmutableEntity.class); ImmutableEntity result = resultMapper.mapResult(response, ImmutableEntity.class);
@ -201,6 +212,7 @@ public class DefaultResultMapperTests {
public void setsVersionFromGetResponse() { public void setsVersionFromGetResponse() {
GetResponse response = mock(GetResponse.class); GetResponse response = mock(GetResponse.class);
when(response.isExists()).thenReturn(true);
when(response.getSourceAsString()).thenReturn("{}"); when(response.getSourceAsString()).thenReturn("{}");
when(response.getVersion()).thenReturn(1234L); when(response.getVersion()).thenReturn(1234L);
@ -214,12 +226,16 @@ public class DefaultResultMapperTests {
public void setsVersionFromMultiGetResponse() { public void setsVersionFromMultiGetResponse() {
GetResponse response1 = mock(GetResponse.class); GetResponse response1 = mock(GetResponse.class);
when(response1.isExists()).thenReturn(true);
when(response1.getSourceAsString()).thenReturn("{}"); when(response1.getSourceAsString()).thenReturn("{}");
when(response1.getSourceAsBytesRef()).thenReturn(new BytesArray("{}"));
when(response1.isExists()).thenReturn(true); when(response1.isExists()).thenReturn(true);
when(response1.getVersion()).thenReturn(1234L); when(response1.getVersion()).thenReturn(1234L);
GetResponse response2 = mock(GetResponse.class); GetResponse response2 = mock(GetResponse.class);
when(response2.isExists()).thenReturn(true);
when(response2.getSourceAsString()).thenReturn("{}"); when(response2.getSourceAsString()).thenReturn("{}");
when(response2.getSourceAsBytesRef()).thenReturn(new BytesArray("{}"));
when(response2.isExists()).thenReturn(true); when(response2.isExists()).thenReturn(true);
when(response2.getVersion()).thenReturn(5678L); when(response2.getVersion()).thenReturn(5678L);
@ -239,11 +255,11 @@ public class DefaultResultMapperTests {
public void setsVersionFromSearchResponse() { public void setsVersionFromSearchResponse() {
SearchHit hit1 = mock(SearchHit.class); SearchHit hit1 = mock(SearchHit.class);
when(hit1.getSourceAsString()).thenReturn("{}"); when(hit1.getSourceRef()).thenReturn(new BytesArray("{}"));
when(hit1.getVersion()).thenReturn(1234L); when(hit1.getVersion()).thenReturn(1234L);
SearchHit hit2 = mock(SearchHit.class); SearchHit hit2 = mock(SearchHit.class);
when(hit2.getSourceAsString()).thenReturn("{}"); when(hit2.getSourceRef()).thenReturn(new BytesArray("{}"));
when(hit2.getVersion()).thenReturn(5678L); when(hit2.getVersion()).thenReturn(5678L);
SearchHits searchHits = mock(SearchHits.class); SearchHits searchHits = mock(SearchHits.class);
@ -272,7 +288,13 @@ public class DefaultResultMapperTests {
private SearchHit createCarHit(String name, String model) { private SearchHit createCarHit(String name, String model) {
SearchHit hit = mock(SearchHit.class); SearchHit hit = mock(SearchHit.class);
when(hit.getSourceAsString()).thenReturn(createJsonCar(name, model)); String json = createJsonCar(name, model);
when(hit.getSourceAsString()).thenReturn(json);
when(hit.getSourceRef()).thenReturn(new BytesArray(json));
Map<String, Object> map = new LinkedHashMap<>();
map.put("name", name);
map.put("model", model);
when(hit.getSourceAsMap()).thenReturn(map);
return hit; return hit;
} }
@ -281,6 +303,7 @@ public class DefaultResultMapperTests {
SearchHit hit = mock(SearchHit.class); SearchHit hit = mock(SearchHit.class);
when(hit.getSourceAsString()).thenReturn(null); when(hit.getSourceAsString()).thenReturn(null);
when(hit.getFields()).thenReturn(createCarFields(name, model)); when(hit.getFields()).thenReturn(createCarFields(name, model));
when(hit.iterator()).thenReturn(createCarFields(name, model).values().iterator());
return hit; return hit;
} }

View File

@ -47,7 +47,7 @@ import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.TypeAlias; import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.convert.ReadingConverter; import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter; import org.springframework.data.convert.WritingConverter;
import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.annotations.GeoPointField; import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions; import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
import org.springframework.data.elasticsearch.core.geo.GeoPoint; import org.springframework.data.elasticsearch.core.geo.GeoPoint;
@ -58,7 +58,10 @@ import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon; import org.springframework.data.geo.Polygon;
/** /**
* Unit tests for {@link ElasticsearchEntityMapper}.
*
* @author Christoph Strobl * @author Christoph Strobl
* @author Mark Paluch
*/ */
public class ElasticsearchEntityMapperUnitTests { public class ElasticsearchEntityMapperUnitTests {
@ -79,16 +82,16 @@ public class ElasticsearchEntityMapperUnitTests {
Address observatoryRoad; Address observatoryRoad;
Place bigBunsCafe; Place bigBunsCafe;
Map<String, Object> sarahAsMap; Document sarahAsMap;
Map<String, Object> t800AsMap; Document t800AsMap;
Map<String, Object> kyleAsMap; Document kyleAsMap;
Map<String, Object> gratiotAveAsMap; Document gratiotAveAsMap;
Map<String, Object> locationAsMap; Document locationAsMap;
Map<String, Object> gunAsMap; Document gunAsMap;
Map<String, Object> grenadeAsMap; Document grenadeAsMap;
Map<String, Object> rifleAsMap; Document rifleAsMap;
Map<String, Object> shotGunAsMap; Document shotGunAsMap;
Map<String, Object> bigBunsCafeAsMap; Document bigBunsCafeAsMap;
@Before @Before
public void init() { public void init() {
@ -117,7 +120,7 @@ public class ElasticsearchEntityMapperUnitTests {
t800.name = "T-800"; t800.name = "T-800";
t800.gender = Gender.MACHINE; t800.gender = Gender.MACHINE;
t800AsMap = new LinkedHashMap<>(); t800AsMap = Document.create();
t800AsMap.put("id", "t800"); t800AsMap.put("id", "t800");
t800AsMap.put("name", "T-800"); t800AsMap.put("name", "T-800");
t800AsMap.put("gender", "MACHINE"); t800AsMap.put("gender", "MACHINE");
@ -134,27 +137,27 @@ public class ElasticsearchEntityMapperUnitTests {
bigBunsCafe.street = "15 South Fremont Avenue"; bigBunsCafe.street = "15 South Fremont Avenue";
bigBunsCafe.location = new Point(34.0945637D, -118.1545845D); bigBunsCafe.location = new Point(34.0945637D, -118.1545845D);
sarahAsMap = new LinkedHashMap<>(); sarahAsMap = Document.create();
sarahAsMap.put("id", "sarah"); sarahAsMap.put("id", "sarah");
sarahAsMap.put("name", "Sarah Connor"); sarahAsMap.put("name", "Sarah Connor");
sarahAsMap.put("gender", "MAN"); sarahAsMap.put("gender", "MAN");
sarahAsMap.put("_class", "org.springframework.data.elasticsearch.core.ElasticsearchEntityMapperUnitTests$Person"); sarahAsMap.put("_class", "org.springframework.data.elasticsearch.core.ElasticsearchEntityMapperUnitTests$Person");
kyleAsMap = new LinkedHashMap<>(); kyleAsMap = Document.create();
kyleAsMap.put("id", "kyle"); kyleAsMap.put("id", "kyle");
kyleAsMap.put("gender", "MAN"); kyleAsMap.put("gender", "MAN");
kyleAsMap.put("name", "Kyle Reese"); kyleAsMap.put("name", "Kyle Reese");
locationAsMap = new LinkedHashMap<>(); locationAsMap = Document.create();
locationAsMap.put("lat", 34.118347D); locationAsMap.put("lat", 34.118347D);
locationAsMap.put("lon", -118.3026284D); locationAsMap.put("lon", -118.3026284D);
gratiotAveAsMap = new LinkedHashMap<>(); gratiotAveAsMap = Document.create();
gratiotAveAsMap.put("city", "Los Angeles"); gratiotAveAsMap.put("city", "Los Angeles");
gratiotAveAsMap.put("street", "2800 East Observatory Road"); gratiotAveAsMap.put("street", "2800 East Observatory Road");
gratiotAveAsMap.put("location", locationAsMap); gratiotAveAsMap.put("location", locationAsMap);
bigBunsCafeAsMap = new LinkedHashMap<>(); bigBunsCafeAsMap = Document.create();
bigBunsCafeAsMap.put("name", "Big Buns Cafe"); bigBunsCafeAsMap.put("name", "Big Buns Cafe");
bigBunsCafeAsMap.put("city", "Los Angeles"); bigBunsCafeAsMap.put("city", "Los Angeles");
bigBunsCafeAsMap.put("street", "15 South Fremont Avenue"); bigBunsCafeAsMap.put("street", "15 South Fremont Avenue");
@ -164,22 +167,22 @@ public class ElasticsearchEntityMapperUnitTests {
bigBunsCafeAsMap.put("_class", bigBunsCafeAsMap.put("_class",
"org.springframework.data.elasticsearch.core.ElasticsearchEntityMapperUnitTests$Place"); "org.springframework.data.elasticsearch.core.ElasticsearchEntityMapperUnitTests$Place");
gunAsMap = new LinkedHashMap<>(); gunAsMap = Document.create();
gunAsMap.put("label", "Glock 19"); gunAsMap.put("label", "Glock 19");
gunAsMap.put("shotsPerMagazine", 33); gunAsMap.put("shotsPerMagazine", 33);
gunAsMap.put("_class", Gun.class.getName()); gunAsMap.put("_class", Gun.class.getName());
grenadeAsMap = new LinkedHashMap<>(); grenadeAsMap = Document.create();
grenadeAsMap.put("label", "40 mm"); grenadeAsMap.put("label", "40 mm");
grenadeAsMap.put("_class", Grenade.class.getName()); grenadeAsMap.put("_class", Grenade.class.getName());
rifleAsMap = new LinkedHashMap<>(); rifleAsMap = Document.create();
rifleAsMap.put("label", "AR-18 Assault Rifle"); rifleAsMap.put("label", "AR-18 Assault Rifle");
rifleAsMap.put("weight", 3.17D); rifleAsMap.put("weight", 3.17D);
rifleAsMap.put("maxShotsPerMagazine", 40); rifleAsMap.put("maxShotsPerMagazine", 40);
rifleAsMap.put("_class", "rifle"); rifleAsMap.put("_class", "rifle");
shotGunAsMap = new LinkedHashMap<>(); shotGunAsMap = Document.create();
shotGunAsMap.put("model", "Ithaca 37 Pump Shotgun"); shotGunAsMap.put("model", "Ithaca 37 Pump Shotgun");
shotGunAsMap.put("_class", ShotGun.class.getName()); shotGunAsMap.put("_class", ShotGun.class.getName());
} }
@ -255,7 +258,7 @@ public class ElasticsearchEntityMapperUnitTests {
person.gender = Gender.MAN; person.gender = Gender.MAN;
person.address = observatoryRoad; person.address = observatoryRoad;
LinkedHashMap<String, Object> sink = writeToMap(person); Map<String, Object> sink = writeToMap(person);
assertThat(sink.get("address")).isEqualTo(gratiotAveAsMap); assertThat(sink.get("address")).isEqualTo(gratiotAveAsMap);
} }
@ -269,7 +272,7 @@ public class ElasticsearchEntityMapperUnitTests {
sarahConnor.coWorkers = Arrays.asList(kyleReese, ginger); sarahConnor.coWorkers = Arrays.asList(kyleReese, ginger);
LinkedHashMap<String, Object> target = writeToMap(sarahConnor); Map<String, Object> target = writeToMap(sarahConnor);
assertThat((List) target.get("coWorkers")).hasSize(2).contains(kyleAsMap); assertThat((List) target.get("coWorkers")).hasSize(2).contains(kyleAsMap);
} }
@ -281,7 +284,7 @@ public class ElasticsearchEntityMapperUnitTests {
sarahConnor.inventoryList = Arrays.asList(gun, grenade); sarahConnor.inventoryList = Arrays.asList(gun, grenade);
LinkedHashMap<String, Object> target = writeToMap(sarahConnor); Map<String, Object> target = writeToMap(sarahConnor);
assertThat((List) target.get("inventoryList")).containsExactly(gunAsMap, grenadeAsMap); assertThat((List) target.get("inventoryList")).containsExactly(gunAsMap, grenadeAsMap);
} }
@ -319,7 +322,7 @@ public class ElasticsearchEntityMapperUnitTests {
sarahConnor.shippingAddresses = new LinkedHashMap<>(); sarahConnor.shippingAddresses = new LinkedHashMap<>();
sarahConnor.shippingAddresses.put("home", observatoryRoad); sarahConnor.shippingAddresses.put("home", observatoryRoad);
LinkedHashMap<String, Object> target = writeToMap(sarahConnor); Map<String, Object> target = writeToMap(sarahConnor);
assertThat(target.get("shippingAddresses")).isInstanceOf(Map.class); assertThat(target.get("shippingAddresses")).isInstanceOf(Map.class);
assertThat(target.get("shippingAddresses")).isEqualTo(Collections.singletonMap("home", gratiotAveAsMap)); assertThat(target.get("shippingAddresses")).isEqualTo(Collections.singletonMap("home", gratiotAveAsMap));
} }
@ -331,7 +334,7 @@ public class ElasticsearchEntityMapperUnitTests {
sarahConnor.inventoryMap.put("glock19", gun); sarahConnor.inventoryMap.put("glock19", gun);
sarahConnor.inventoryMap.put("40 mm grenade", grenade); sarahConnor.inventoryMap.put("40 mm grenade", grenade);
LinkedHashMap<String, Object> target = writeToMap(sarahConnor); Map<String, Object> target = writeToMap(sarahConnor);
assertThat(target.get("inventoryMap")).isInstanceOf(Map.class); assertThat(target.get("inventoryMap")).isInstanceOf(Map.class);
assertThat((Map) target.get("inventoryMap")).containsEntry("glock19", gunAsMap).containsEntry("40 mm grenade", assertThat((Map) target.get("inventoryMap")).containsEntry("glock19", gunAsMap).containsEntry("40 mm grenade",
grenadeAsMap); grenadeAsMap);
@ -365,7 +368,7 @@ public class ElasticsearchEntityMapperUnitTests {
skynet.objectList.add(t800); skynet.objectList.add(t800);
skynet.objectList.add(gun); skynet.objectList.add(gun);
LinkedHashMap<String, Object> target = writeToMap(skynet); Map<String, Object> target = writeToMap(skynet);
assertThat((List<Object>) target.get("objectList")).containsExactly(t800AsMap, gunAsMap); assertThat((List<Object>) target.get("objectList")).containsExactly(t800AsMap, gunAsMap);
} }
@ -373,7 +376,7 @@ public class ElasticsearchEntityMapperUnitTests {
@Test // DATAES-530 @Test // DATAES-530
public void readGenericList() { public void readGenericList() {
LinkedHashMap<String, Object> source = new LinkedHashMap<>(); Document source = Document.create();
source.put("objectList", Arrays.asList(t800AsMap, gunAsMap)); source.put("objectList", Arrays.asList(t800AsMap, gunAsMap));
Skynet target = entityMapper.read(Skynet.class, source); Skynet target = entityMapper.read(Skynet.class, source);
@ -388,7 +391,7 @@ public class ElasticsearchEntityMapperUnitTests {
skynet.objectList = new ArrayList<>(); skynet.objectList = new ArrayList<>();
skynet.objectList.add(Arrays.asList(t800, gun)); skynet.objectList.add(Arrays.asList(t800, gun));
LinkedHashMap<String, Object> target = writeToMap(skynet); Map<String, Object> target = writeToMap(skynet);
assertThat((List<Object>) target.get("objectList")).containsExactly(Arrays.asList(t800AsMap, gunAsMap)); assertThat((List<Object>) target.get("objectList")).containsExactly(Arrays.asList(t800AsMap, gunAsMap));
} }
@ -396,7 +399,7 @@ public class ElasticsearchEntityMapperUnitTests {
@Test // DATAES-530 @Test // DATAES-530
public void readGenericListList() { public void readGenericListList() {
LinkedHashMap<String, Object> source = new LinkedHashMap<>(); Document source = Document.create();
source.put("objectList", Arrays.asList(Arrays.asList(t800AsMap, gunAsMap))); source.put("objectList", Arrays.asList(Arrays.asList(t800AsMap, gunAsMap)));
Skynet target = entityMapper.read(Skynet.class, source); Skynet target = entityMapper.read(Skynet.class, source);
@ -412,7 +415,7 @@ public class ElasticsearchEntityMapperUnitTests {
skynet.objectMap.put("gun", gun); skynet.objectMap.put("gun", gun);
skynet.objectMap.put("grenade", grenade); skynet.objectMap.put("grenade", grenade);
LinkedHashMap<String, Object> target = writeToMap(skynet); Map<String, Object> target = writeToMap(skynet);
assertThat((Map<String, Object>) target.get("objectMap")).containsEntry("gun", gunAsMap).containsEntry("grenade", assertThat((Map<String, Object>) target.get("objectMap")).containsEntry("gun", gunAsMap).containsEntry("grenade",
grenadeAsMap); grenadeAsMap);
@ -421,7 +424,7 @@ public class ElasticsearchEntityMapperUnitTests {
@Test // DATAES-530 @Test // DATAES-530
public void readGenericMap() { public void readGenericMap() {
LinkedHashMap<String, Object> source = new LinkedHashMap<>(); Document source = Document.create();
source.put("objectMap", Collections.singletonMap("glock19", gunAsMap)); source.put("objectMap", Collections.singletonMap("glock19", gunAsMap));
Skynet target = entityMapper.read(Skynet.class, source); Skynet target = entityMapper.read(Skynet.class, source);
@ -436,7 +439,7 @@ public class ElasticsearchEntityMapperUnitTests {
skynet.objectMap = new LinkedHashMap<>(); skynet.objectMap = new LinkedHashMap<>();
skynet.objectMap.put("inventory", Collections.singletonMap("glock19", gun)); skynet.objectMap.put("inventory", Collections.singletonMap("glock19", gun));
LinkedHashMap<String, Object> target = writeToMap(skynet); Map<String, Object> target = writeToMap(skynet);
assertThat((Map<String, Object>) target.get("objectMap")).containsEntry("inventory", assertThat((Map<String, Object>) target.get("objectMap")).containsEntry("inventory",
Collections.singletonMap("glock19", gunAsMap)); Collections.singletonMap("glock19", gunAsMap));
@ -445,7 +448,7 @@ public class ElasticsearchEntityMapperUnitTests {
@Test // DATAES-530 @Test // DATAES-530
public void readGenericMapMap() { public void readGenericMapMap() {
LinkedHashMap<String, Object> source = new LinkedHashMap<>(); Document source = Document.create();
source.put("objectMap", Collections.singletonMap("inventory", Collections.singletonMap("glock19", gunAsMap))); source.put("objectMap", Collections.singletonMap("inventory", Collections.singletonMap("glock19", gunAsMap)));
Skynet target = entityMapper.read(Skynet.class, source); Skynet target = entityMapper.read(Skynet.class, source);
@ -466,7 +469,7 @@ public class ElasticsearchEntityMapperUnitTests {
@Test // DATAES-530 @Test // DATAES-530
public void readsNestedObjectEntity() { public void readsNestedObjectEntity() {
LinkedHashMap<String, Object> source = new LinkedHashMap<>(); Document source = Document.create();
source.put("object", t800AsMap); source.put("object", t800AsMap);
Skynet target = entityMapper.read(Skynet.class, source); Skynet target = entityMapper.read(Skynet.class, source);
@ -483,7 +486,7 @@ public class ElasticsearchEntityMapperUnitTests {
public void writesNestedAliased() { public void writesNestedAliased() {
t800.inventoryList = Collections.singletonList(rifle); t800.inventoryList = Collections.singletonList(rifle);
LinkedHashMap<String, Object> target = writeToMap(t800); Map<String, Object> target = writeToMap(t800);
assertThat((List) target.get("inventoryList")).contains(rifleAsMap); assertThat((List) target.get("inventoryList")).contains(rifleAsMap);
} }
@ -516,7 +519,7 @@ public class ElasticsearchEntityMapperUnitTests {
sarahConnor.address = bigBunsCafe; sarahConnor.address = bigBunsCafe;
LinkedHashMap<String, Object> target = writeToMap(sarahConnor); Map<String, Object> target = writeToMap(sarahConnor);
assertThat(target.get("address")).isEqualTo(bigBunsCafeAsMap); assertThat(target.get("address")).isEqualTo(bigBunsCafeAsMap);
} }
@ -535,9 +538,9 @@ public class ElasticsearchEntityMapperUnitTests {
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY()); return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
} }
private LinkedHashMap<String, Object> writeToMap(Object source) { private Map<String, Object> writeToMap(Object source) {
LinkedHashMap<String, Object> sink = new LinkedHashMap<>(); Document sink = Document.create();
entityMapper.write(source, sink); entityMapper.write(source, sink);
return sink; return sink;
} }
@ -696,7 +699,8 @@ public class ElasticsearchEntityMapperUnitTests {
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Builder @Builder
@Document(indexName = "test-index-geo-core-entity-mapper", type = "geo-test-index", shards = 1, replicas = 0, @org.springframework.data.elasticsearch.annotations.Document(indexName = "test-index-geo-core-entity-mapper",
type = "geo-test-index", shards = 1, replicas = 0,
refreshInterval = "-1") refreshInterval = "-1")
static class GeoEntity { static class GeoEntity {