![JAR search and dependency download from the Maven repository](/logo.png)
org.opensearch.index.mapper.Mapping Maven / Gradle / Ivy
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.index.mapper;
import org.opensearch.Version;
import org.opensearch.common.Strings;
import org.opensearch.common.xcontent.ToXContent;
import org.opensearch.common.xcontent.ToXContentFragment;
import org.opensearch.common.xcontent.XContentBuilder;
import org.opensearch.common.xcontent.XContentFactory;
import org.opensearch.common.xcontent.XContentHelper;
import org.opensearch.index.mapper.MapperService.MergeReason;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
/**
* Wrapper around everything that defines a mapping, without references to
* utility classes like MapperService, ...
*/
public final class Mapping implements ToXContentFragment {
final Version indexCreated;
final RootObjectMapper root;
final MetadataFieldMapper[] metadataMappers;
final Map, MetadataFieldMapper> metadataMappersMap;
final Map metadataMappersByName;
final Map meta;
public Mapping(
Version indexCreated,
RootObjectMapper rootObjectMapper,
MetadataFieldMapper[] metadataMappers,
Map meta
) {
this.indexCreated = indexCreated;
this.metadataMappers = metadataMappers;
Map, MetadataFieldMapper> metadataMappersMap = new HashMap<>();
Map metadataMappersByName = new HashMap<>();
for (MetadataFieldMapper metadataMapper : metadataMappers) {
metadataMappersMap.put(metadataMapper.getClass(), metadataMapper);
metadataMappersByName.put(metadataMapper.name(), metadataMapper);
}
this.root = rootObjectMapper;
// keep root mappers sorted for consistent serialization
Arrays.sort(metadataMappers, new Comparator() {
@Override
public int compare(Mapper o1, Mapper o2) {
return o1.name().compareTo(o2.name());
}
});
this.metadataMappersMap = unmodifiableMap(metadataMappersMap);
this.metadataMappersByName = unmodifiableMap(metadataMappersByName);
this.meta = meta;
}
/** Return the root object mapper. */
public RootObjectMapper root() {
return root;
}
public void validate(MappingLookup mappers) {
for (MetadataFieldMapper metadataFieldMapper : metadataMappers) {
metadataFieldMapper.validate(mappers);
}
root.validate(mappers);
}
/**
* Generate a mapping update for the given root object mapper.
*/
public Mapping mappingUpdate(Mapper rootObjectMapper) {
return new Mapping(indexCreated, (RootObjectMapper) rootObjectMapper, metadataMappers, meta);
}
/** Get the root mapper with the given class. */
@SuppressWarnings("unchecked")
public T metadataMapper(Class clazz) {
return (T) metadataMappersMap.get(clazz);
}
/**
* Merges a new mapping into the existing one.
*
* @param mergeWith the new mapping to merge into this one.
* @param reason the reason this merge was initiated.
* @return the resulting merged mapping.
*/
public Mapping merge(Mapping mergeWith, MergeReason reason) {
RootObjectMapper mergedRoot = root.merge(mergeWith.root, reason);
// When merging metadata fields as part of applying an index template, new field definitions
// completely overwrite existing ones instead of being merged. This behavior matches how we
// merge leaf fields in the 'properties' section of the mapping.
Map, MetadataFieldMapper> mergedMetadataMappers = new HashMap<>(metadataMappersMap);
for (MetadataFieldMapper metaMergeWith : mergeWith.metadataMappers) {
MetadataFieldMapper mergeInto = mergedMetadataMappers.get(metaMergeWith.getClass());
MetadataFieldMapper merged;
if (mergeInto == null || reason == MergeReason.INDEX_TEMPLATE) {
merged = metaMergeWith;
} else {
merged = (MetadataFieldMapper) mergeInto.merge(metaMergeWith);
}
mergedMetadataMappers.put(merged.getClass(), merged);
}
// If we are merging the _meta object as part of applying an index template, then the new object
// is deep-merged into the existing one to allow individual keys to be added or overwritten. For
// standard mapping updates, the new _meta object completely replaces the old one.
Map mergedMeta;
if (mergeWith.meta == null) {
mergedMeta = meta;
} else if (meta == null || reason != MergeReason.INDEX_TEMPLATE) {
mergedMeta = mergeWith.meta;
} else {
mergedMeta = new HashMap<>(mergeWith.meta);
XContentHelper.mergeDefaults(mergedMeta, meta);
}
return new Mapping(indexCreated, mergedRoot, mergedMetadataMappers.values().toArray(new MetadataFieldMapper[0]), mergedMeta);
}
public MetadataFieldMapper getMetadataMapper(String mapperName) {
return metadataMappersByName.get(mapperName);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
root.toXContent(builder, params, new ToXContent() {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (meta != null) {
builder.field("_meta", meta);
}
for (Mapper mapper : metadataMappers) {
mapper.toXContent(builder, params);
}
return builder;
}
});
return builder;
}
@Override
public String toString() {
try {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
toXContent(builder, new ToXContent.MapParams(emptyMap()));
return Strings.toString(builder.endObject());
} catch (IOException bogus) {
throw new UncheckedIOException(bogus);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy