Skip to content

Commit

Permalink
DATAES-568 - Polishing.
Browse files Browse the repository at this point in the history
Add package-info and nullability annotations to org.springframework.data.elasticsearch.core.mapping.
Extract method to avoid excessive nesting.

Add ticket references/convert old references to test methods. Move test models to inner classes. Use static imports for JSON Assert. Formatting.

Original pull request: #281.
  • Loading branch information
mp911de committed May 6, 2019
1 parent 66b77ec commit 01cda35
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 338 deletions.
Expand Up @@ -89,6 +89,7 @@
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
Expand All @@ -108,7 +109,21 @@
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.core.query.AliasQuery;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.GetQuery;
import org.springframework.data.elasticsearch.core.query.IndexBoost;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.ScriptField;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.core.query.SourceFilter;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.util.CloseableIterator;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
Expand Down Expand Up @@ -224,7 +239,7 @@ public <T> boolean putMapping(Class<T> clazz) {
}
try {
MappingBuilder mappingBuilder = new MappingBuilder(elasticsearchConverter);
return putMapping(clazz, mappingBuilder.buildMapping(clazz));
return putMapping(clazz, mappingBuilder.buildPropertyMapping(clazz));
} catch (Exception e) {
throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
}
Expand Down Expand Up @@ -497,8 +512,7 @@ public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultM
@Override
public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) {
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz,
resultsMapper);
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz, resultsMapper);
}

@Override
Expand All @@ -509,8 +523,7 @@ public <T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz) {
@Override
public <T> CloseableIterator<T> stream(SearchQuery query, final Class<T> clazz, final SearchResultMapper mapper) {
final long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz, mapper), clazz,
mapper);
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz, mapper), clazz, mapper);
}

private <T> CloseableIterator<T> doStream(final long scrollTimeInMillis, final ScrolledPage<T> page,
Expand Down Expand Up @@ -1453,8 +1466,7 @@ List<AliasMetaData> convertAliasResponse(String aliasResponse) {
node = node.findValue("aliases");

Map<String, AliasData> aliasData = mapper.readValue(mapper.writeValueAsString(node),
new TypeReference<Map<String, AliasData>>() {
});
new TypeReference<Map<String, AliasData>>() {});

Iterable<Map.Entry<String, AliasData>> aliasIter = aliasData.entrySet();
List<AliasMetaData> aliasMetaDataList = new ArrayList<AliasMetaData>();
Expand Down
Expand Up @@ -206,7 +206,7 @@ public <T> boolean putMapping(Class<T> clazz) {
}
try {
MappingBuilder mappingBuilder = new MappingBuilder(elasticsearchConverter);
return putMapping(clazz, mappingBuilder.buildMapping(clazz));
return putMapping(clazz, mappingBuilder.buildPropertyMapping(clazz));
} catch (Exception e) {
throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
}
Expand Down
Expand Up @@ -27,16 +27,25 @@
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.core.io.ClassPathResource;
import org.springframework.data.annotation.Transient;
import org.springframework.data.elasticsearch.annotations.*;
import org.springframework.data.elasticsearch.annotations.CompletionContext;
import org.springframework.data.elasticsearch.annotations.CompletionField;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.DynamicTemplates;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.annotations.InnerField;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.core.completion.Completion;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
Expand All @@ -61,34 +70,33 @@
*/
class MappingBuilder {

public static final String FIELD_DATA = "fielddata";
public static final String FIELD_STORE = "store";
public static final String FIELD_TYPE = "type";
public static final String FIELD_INDEX = "index";
public static final String FIELD_FORMAT = "format";
public static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
public static final String FIELD_INDEX_ANALYZER = "analyzer";
public static final String FIELD_NORMALIZER = "normalizer";
public static final String FIELD_PROPERTIES = "properties";
public static final String FIELD_PARENT = "_parent";
public static final String FIELD_COPY_TO = "copy_to";
public static final String FIELD_CONTEXT_NAME = "name";
public static final String FIELD_CONTEXT_TYPE = "type";
public static final String FIELD_CONTEXT_PRECISION = "precision";
public static final String FIELD_DYNAMIC_TEMPLATES = "dynamic_templates";

public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators";
public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
public static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
public static final String COMPLETION_CONTEXTS = "contexts";

public static final String TYPE_VALUE_KEYWORD = "keyword";
public static final String TYPE_VALUE_GEO_POINT = "geo_point";
public static final String TYPE_VALUE_COMPLETION = "completion";
public static final String TYPE_VALUE_GEO_HASH_PREFIX = "geohash_prefix";
public static final String TYPE_VALUE_GEO_HASH_PRECISION = "geohash_precision";
private static final String FIELD_DATA = "fielddata";
private static final String FIELD_STORE = "store";
private static final String FIELD_TYPE = "type";
private static final String FIELD_INDEX = "index";
private static final String FIELD_FORMAT = "format";
private static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
private static final String FIELD_INDEX_ANALYZER = "analyzer";
private static final String FIELD_NORMALIZER = "normalizer";
private static final String FIELD_PROPERTIES = "properties";
private static final String FIELD_PARENT = "_parent";
private static final String FIELD_COPY_TO = "copy_to";
private static final String FIELD_CONTEXT_NAME = "name";
private static final String FIELD_CONTEXT_TYPE = "type";
private static final String FIELD_CONTEXT_PRECISION = "precision";
private static final String FIELD_DYNAMIC_TEMPLATES = "dynamic_templates";

private static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators";
private static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
private static final String COMPLETION_MAX_INPUT_LENGTH = "max_input_length";
private static final String COMPLETION_CONTEXTS = "contexts";

private static final String TYPE_VALUE_KEYWORD = "keyword";
private static final String TYPE_VALUE_GEO_POINT = "geo_point";
private static final String TYPE_VALUE_COMPLETION = "completion";

private static final Logger logger = LoggerFactory.getLogger(ElasticsearchRestTemplate.class);
private static SimpleTypeHolder SIMPLE_TYPE_HOLDER = SimpleTypeHolder.DEFAULT;

private final ElasticsearchConverter elasticsearchConverter;

MappingBuilder(ElasticsearchConverter elasticsearchConverter) {
Expand All @@ -101,7 +109,7 @@ class MappingBuilder {
* @return JSON string
* @throws IOException
*/
String buildMapping(Class<?> clazz) throws IOException {
String buildPropertyMapping(Class<?> clazz) throws IOException {

ElasticsearchPersistentEntity<?> entity = elasticsearchConverter.getMappingContext()
.getRequiredPersistentEntity(clazz);
Expand Down Expand Up @@ -157,70 +165,76 @@ private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersisten
return;
}

if (property.isAnnotationPresent(Mapping.class)) {
buildPropertyMapping(builder, isRootObject, property);
} catch (IOException e) {
logger.warn("error mapping property with name {}", property.getName(), e);
}
});
}

String mappingPath = property.getRequiredAnnotation(Mapping.class).mappingPath();
if (!StringUtils.isEmpty(mappingPath)) {
if (writeNestedProperties) {
builder.endObject().endObject();
}
}

ClassPathResource mappings = new ClassPathResource(mappingPath);
if (mappings.exists()) {
builder.rawField(property.getFieldName(), mappings.getInputStream(), XContentType.JSON);
return;
}
}
}
private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject,
ElasticsearchPersistentProperty property) throws IOException {

boolean isGeoPointProperty = isGeoPointProperty(property);
boolean isCompletionProperty = isCompletionProperty(property);
boolean isNestedOrObjectProperty = isNestedOrObjectProperty(property);
if (property.isAnnotationPresent(Mapping.class)) {

Field fieldAnnotation = property.findAnnotation(Field.class);
if (!isGeoPointProperty && !isCompletionProperty && property.isEntity() && hasRelevantAnnotation(property)) {
String mappingPath = property.getRequiredAnnotation(Mapping.class).mappingPath();
if (!StringUtils.isEmpty(mappingPath)) {

if (fieldAnnotation == null) {
return;
}
ClassPathResource mappings = new ClassPathResource(mappingPath);
if (mappings.exists()) {
builder.rawField(property.getFieldName(), mappings.getInputStream(), XContentType.JSON);
return;
}
}
}

Iterator<? extends TypeInformation<?>> iterator = property.getPersistentEntityTypes().iterator();
ElasticsearchPersistentEntity<?> persistentEntity = iterator.hasNext()
? elasticsearchConverter.getMappingContext().getPersistentEntity(iterator.next())
: null;
boolean isGeoPointProperty = isGeoPointProperty(property);
boolean isCompletionProperty = isCompletionProperty(property);
boolean isNestedOrObjectProperty = isNestedOrObjectProperty(property);

mapEntity(builder, persistentEntity, false, property.getFieldName(), isNestedOrObjectProperty,
fieldAnnotation.type(), fieldAnnotation);
Field fieldAnnotation = property.findAnnotation(Field.class);
if (!isGeoPointProperty && !isCompletionProperty && property.isEntity() && hasRelevantAnnotation(property)) {

if (isNestedOrObjectProperty) {
return;
}
}
if (fieldAnnotation == null) {
return;
}

MultiField multiField = property.findAnnotation(MultiField.class);
Iterator<? extends TypeInformation<?>> iterator = property.getPersistentEntityTypes().iterator();
ElasticsearchPersistentEntity<?> persistentEntity = iterator.hasNext()
? elasticsearchConverter.getMappingContext().getPersistentEntity(iterator.next())
: null;

if (isGeoPointProperty) {
applyGeoPointFieldMapping(builder, property);
return;
}
mapEntity(builder, persistentEntity, false, property.getFieldName(), isNestedOrObjectProperty,
fieldAnnotation.type(), fieldAnnotation);

if (isCompletionProperty) {
CompletionField completionField = property.findAnnotation(CompletionField.class);
applyCompletionFieldMapping(builder, property, completionField);
}
if (isNestedOrObjectProperty) {
return;
}
}

if (isRootObject && fieldAnnotation != null && property.isIdProperty()) {
applyDefaultIdFieldMapping(builder, property);
} else if (multiField != null) {
addMultiFieldMapping(builder, property, multiField, isNestedOrObjectProperty);
} else if (fieldAnnotation != null) {
addSingleFieldMapping(builder, property, fieldAnnotation, isNestedOrObjectProperty);
}
} catch (IOException e) {
logger.warn("error mapping property with name {}", property.getName(), e);
}
});
MultiField multiField = property.findAnnotation(MultiField.class);

if (isGeoPointProperty) {
applyGeoPointFieldMapping(builder, property);
return;
}

if (writeNestedProperties) {
builder.endObject().endObject();
if (isCompletionProperty) {
CompletionField completionField = property.findAnnotation(CompletionField.class);
applyCompletionFieldMapping(builder, property, completionField);
}

if (isRootObject && fieldAnnotation != null && property.isIdProperty()) {
applyDefaultIdFieldMapping(builder, property);
} else if (multiField != null) {
addMultiFieldMapping(builder, property, multiField, isNestedOrObjectProperty);
} else if (fieldAnnotation != null) {
addSingleFieldMapping(builder, property, fieldAnnotation, isNestedOrObjectProperty);
}
}

Expand Down Expand Up @@ -321,6 +335,7 @@ private void addMultiFieldMapping(XContentBuilder builder, ElasticsearchPersiste

private void addFieldMappingParameters(XContentBuilder builder, Object annotation, boolean nestedOrObjectField)
throws IOException {

boolean index = true;
boolean store = false;
boolean fielddata = false;
Expand Down
Expand Up @@ -22,6 +22,7 @@
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;

/**
* SimpleElasticsearchMappingContext
Expand All @@ -30,10 +31,11 @@
* @author Mohsin Husen
* @author Mark Paluch
*/
public class SimpleElasticsearchMappingContext extends
AbstractMappingContext<SimpleElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> implements ApplicationContextAware {
public class SimpleElasticsearchMappingContext
extends AbstractMappingContext<SimpleElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty>
implements ApplicationContextAware {

private ApplicationContext context;
private @Nullable ApplicationContext context;

@Override
protected <T> SimpleElasticsearchPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
Expand Down

0 comments on commit 01cda35

Please sign in to comment.