|
18 | 18 | */ |
19 | 19 | package org.elasticsearch.client.indices; |
20 | 20 |
|
21 | | -import org.elasticsearch.ElasticsearchParseException; |
22 | 21 | import org.elasticsearch.cluster.metadata.AliasMetaData; |
23 | 22 | import org.elasticsearch.cluster.metadata.IndexMetaData; |
24 | 23 | import org.elasticsearch.cluster.metadata.MappingMetaData; |
25 | 24 | import org.elasticsearch.common.Nullable; |
| 25 | +import org.elasticsearch.common.ParseField; |
26 | 26 | import org.elasticsearch.common.collect.ImmutableOpenMap; |
27 | 27 | import org.elasticsearch.common.settings.Settings; |
28 | | -import org.elasticsearch.common.util.set.Sets; |
| 28 | +import org.elasticsearch.common.xcontent.ConstructingObjectParser; |
29 | 29 | import org.elasticsearch.common.xcontent.XContentParser; |
30 | 30 | import org.elasticsearch.index.mapper.MapperService; |
31 | 31 |
|
32 | 32 | import java.io.IOException; |
33 | | -import java.util.ArrayList; |
34 | | -import java.util.Collections; |
| 33 | +import java.util.AbstractMap; |
35 | 34 | import java.util.List; |
36 | 35 | import java.util.Map; |
37 | 36 | import java.util.Objects; |
38 | | -import java.util.Set; |
| 37 | +import java.util.stream.Collectors; |
| 38 | + |
| 39 | +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; |
39 | 40 |
|
40 | 41 | public class IndexTemplateMetaData { |
41 | 42 |
|
| 43 | + @SuppressWarnings("unchecked") |
| 44 | + private static final ConstructingObjectParser<IndexTemplateMetaData, String> PARSER = new ConstructingObjectParser<>( |
| 45 | + "IndexTemplateMetaData", true, (a, name) -> { |
| 46 | + List<Map.Entry<String, AliasMetaData>> alias = (List<Map.Entry<String, AliasMetaData>>) a[5]; |
| 47 | + ImmutableOpenMap<String, AliasMetaData> aliasMap = |
| 48 | + new ImmutableOpenMap.Builder<String, AliasMetaData>() |
| 49 | + .putAll(alias.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))) |
| 50 | + .build(); |
| 51 | + return new IndexTemplateMetaData( |
| 52 | + name, |
| 53 | + (Integer) a[0], |
| 54 | + (Integer) a[1], |
| 55 | + (List<String>) a[2], |
| 56 | + (Settings) a[3], |
| 57 | + (MappingMetaData) a[4], |
| 58 | + aliasMap); |
| 59 | + }); |
| 60 | + |
| 61 | + static { |
| 62 | + PARSER.declareInt(optionalConstructorArg(), new ParseField("order")); |
| 63 | + PARSER.declareInt(optionalConstructorArg(), new ParseField("version")); |
| 64 | + PARSER.declareStringArray(optionalConstructorArg(), new ParseField("index_patterns")); |
| 65 | + PARSER.declareObject(optionalConstructorArg(), (p, c) -> { |
| 66 | + Settings.Builder templateSettingsBuilder = Settings.builder(); |
| 67 | + templateSettingsBuilder.put(Settings.fromXContent(p)); |
| 68 | + templateSettingsBuilder.normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX); |
| 69 | + return templateSettingsBuilder.build(); |
| 70 | + }, new ParseField("settings")); |
| 71 | + PARSER.declareObject(optionalConstructorArg(), (p, c) -> { |
| 72 | + Map<String, Object> mapping = p.map(); |
| 73 | + if (mapping.isEmpty()) { |
| 74 | + return null; |
| 75 | + } |
| 76 | + return new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, mapping); |
| 77 | + }, new ParseField("mappings")); |
| 78 | + PARSER.declareNamedObjects(optionalConstructorArg(), |
| 79 | + (p, c, name) -> new AbstractMap.SimpleEntry<>(name, AliasMetaData.Builder.fromXContent(p)), new ParseField("aliases")); |
| 80 | + } |
42 | 81 |
|
43 | 82 | private final String name; |
44 | 83 |
|
@@ -125,28 +164,23 @@ public static Builder builder(String name) { |
125 | 164 | public boolean equals(Object o) { |
126 | 165 | if (this == o) return true; |
127 | 166 | if (o == null || getClass() != o.getClass()) return false; |
128 | | - |
129 | 167 | IndexTemplateMetaData that = (IndexTemplateMetaData) o; |
130 | | - |
131 | | - if (order != that.order) return false; |
132 | | - if (!Objects.equals(mappings, that.mappings)) return false; |
133 | | - if (!name.equals(that.name)) return false; |
134 | | - if (!settings.equals(that.settings)) return false; |
135 | | - if (!patterns.equals(that.patterns)) return false; |
136 | | - |
137 | | - return Objects.equals(version, that.version); |
| 168 | + return order == that.order && |
| 169 | + Objects.equals(name, that.name) && |
| 170 | + Objects.equals(version, that.version) && |
| 171 | + Objects.equals(patterns, that.patterns) && |
| 172 | + Objects.equals(settings, that.settings) && |
| 173 | + Objects.equals(mappings, that.mappings) && |
| 174 | + Objects.equals(aliases, that.aliases); |
138 | 175 | } |
139 | 176 |
|
140 | 177 | @Override |
141 | 178 | public int hashCode() { |
142 | | - return Objects.hash(name, order, version, patterns, settings, mappings); |
| 179 | + return Objects.hash(name, order, version, patterns, settings, mappings, aliases); |
143 | 180 | } |
144 | 181 |
|
145 | 182 | public static class Builder { |
146 | 183 |
|
147 | | - private static final Set<String> VALID_FIELDS = Sets.newHashSet( |
148 | | - "template", "order", "mappings", "settings", "index_patterns", "aliases", "version"); |
149 | | - |
150 | 184 | private String name; |
151 | 185 |
|
152 | 186 | private int order; |
@@ -193,7 +227,6 @@ public Builder patterns(List<String> indexPatterns) { |
193 | 227 | return this; |
194 | 228 | } |
195 | 229 |
|
196 | | - |
197 | 230 | public Builder settings(Settings.Builder settings) { |
198 | 231 | this.settings = settings.build(); |
199 | 232 | return this; |
@@ -225,76 +258,7 @@ public IndexTemplateMetaData build() { |
225 | 258 |
|
226 | 259 |
|
227 | 260 | public static IndexTemplateMetaData fromXContent(XContentParser parser, String templateName) throws IOException { |
228 | | - Builder builder = new Builder(templateName); |
229 | | - |
230 | | - String currentFieldName = skipTemplateName(parser); |
231 | | - XContentParser.Token token; |
232 | | - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { |
233 | | - if (token == XContentParser.Token.FIELD_NAME) { |
234 | | - currentFieldName = parser.currentName(); |
235 | | - } else if (token == XContentParser.Token.START_OBJECT) { |
236 | | - if ("settings".equals(currentFieldName)) { |
237 | | - Settings.Builder templateSettingsBuilder = Settings.builder(); |
238 | | - templateSettingsBuilder.put(Settings.fromXContent(parser)); |
239 | | - templateSettingsBuilder.normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX); |
240 | | - builder.settings(templateSettingsBuilder.build()); |
241 | | - } else if ("mappings".equals(currentFieldName)) { |
242 | | - Map<String, Object> mapping = parser.map(); |
243 | | - if (mapping.isEmpty() == false) { |
244 | | - MappingMetaData md = new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, mapping); |
245 | | - builder.mapping(md); |
246 | | - } |
247 | | - } else if ("aliases".equals(currentFieldName)) { |
248 | | - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { |
249 | | - builder.putAlias(AliasMetaData.Builder.fromXContent(parser)); |
250 | | - } |
251 | | - } else { |
252 | | - throw new ElasticsearchParseException("unknown key [{}] for index template", currentFieldName); |
253 | | - } |
254 | | - } else if (token == XContentParser.Token.START_ARRAY) { |
255 | | - if ("mappings".equals(currentFieldName)) { |
256 | | - // The server-side IndexTemplateMetaData has toXContent impl that can return mappings |
257 | | - // in an array but also a comment saying this never happens with typeless APIs. |
258 | | - throw new ElasticsearchParseException("Invalid response format - " |
259 | | - + "mappings are not expected to be returned in an array", currentFieldName); |
260 | | - } else if ("index_patterns".equals(currentFieldName)) { |
261 | | - List<String> index_patterns = new ArrayList<>(); |
262 | | - while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { |
263 | | - index_patterns.add(parser.text()); |
264 | | - } |
265 | | - builder.patterns(index_patterns); |
266 | | - } |
267 | | - } else if (token.isValue()) { |
268 | | - // Prior to 5.1.0, elasticsearch only supported a single index pattern called `template` (#21009) |
269 | | - if("template".equals(currentFieldName)) { |
270 | | - builder.patterns(Collections.singletonList(parser.text())); |
271 | | - } else if ("order".equals(currentFieldName)) { |
272 | | - builder.order(parser.intValue()); |
273 | | - } else if ("version".equals(currentFieldName)) { |
274 | | - builder.version(parser.intValue()); |
275 | | - } |
276 | | - } |
277 | | - } |
278 | | - return builder.build(); |
279 | | - } |
280 | | - |
281 | | - private static String skipTemplateName(XContentParser parser) throws IOException { |
282 | | - XContentParser.Token token = parser.nextToken(); |
283 | | - if (token == XContentParser.Token.START_OBJECT) { |
284 | | - token = parser.nextToken(); |
285 | | - if (token == XContentParser.Token.FIELD_NAME) { |
286 | | - String currentFieldName = parser.currentName(); |
287 | | - if (VALID_FIELDS.contains(currentFieldName)) { |
288 | | - return currentFieldName; |
289 | | - } else { |
290 | | - // we just hit the template name, which should be ignored and we move on |
291 | | - parser.nextToken(); |
292 | | - } |
293 | | - } |
294 | | - } |
295 | | - |
296 | | - return null; |
| 261 | + return PARSER.parse(parser, templateName); |
297 | 262 | } |
298 | 263 | } |
299 | | - |
300 | 264 | } |
0 commit comments