12
12
import org .elasticsearch .common .compress .CompressedXContent ;
13
13
import org .elasticsearch .common .xcontent .XContentHelper ;
14
14
import org .elasticsearch .common .xcontent .XContentType ;
15
- import org .elasticsearch .index .IndexSettings ;
16
- import org .elasticsearch .index .analysis .IndexAnalyzers ;
17
15
18
16
import java .util .Collections ;
19
17
import java .util .HashMap ;
22
20
import java .util .function .Function ;
23
21
import java .util .function .Supplier ;
24
22
25
- public class DocumentMapperParser {
26
- private final IndexSettings indexSettings ;
27
- private final IndexAnalyzers indexAnalyzers ;
28
- private final Function <String , String > documentTypeResolver ;
29
- private final DocumentParser documentParser ;
30
- private final Supplier <Map <Class <? extends MetadataFieldMapper >, MetadataFieldMapper >> metadataMappersSupplier ;
23
+ /**
24
+ * Parser for {@link Mapping} provided in {@link CompressedXContent} format
25
+ */
26
+ public final class MappingParser {
31
27
private final Supplier <Mapper .TypeParser .ParserContext > parserContextSupplier ;
32
28
private final RootObjectMapper .TypeParser rootObjectTypeParser = new RootObjectMapper .TypeParser ();
33
- private final Map <String , MetadataFieldMapper .TypeParser > rootTypeParsers ;
29
+ private final Supplier <Map <Class <? extends MetadataFieldMapper >, MetadataFieldMapper >> metadataMappersSupplier ;
30
+ private final Map <String , MetadataFieldMapper .TypeParser > metadataMapperParsers ;
31
+ private final Function <String , String > documentTypeResolver ;
34
32
35
- DocumentMapperParser (IndexSettings indexSettings ,
36
- IndexAnalyzers indexAnalyzers ,
37
- Function <String , String > documentTypeResolver ,
38
- DocumentParser documentParser ,
39
- Supplier <Map <Class <? extends MetadataFieldMapper >, MetadataFieldMapper >> metadataMappersSupplier ,
40
- Supplier <Mapper .TypeParser .ParserContext > parserContextSupplier ,
41
- Map <String , MetadataFieldMapper .TypeParser > metadataMapperParsers ) {
42
- this .indexSettings = indexSettings ;
43
- this .indexAnalyzers = indexAnalyzers ;
44
- this .documentTypeResolver = documentTypeResolver ;
45
- this .documentParser = documentParser ;
46
- this .metadataMappersSupplier = metadataMappersSupplier ;
33
+ MappingParser (Supplier <Mapper .TypeParser .ParserContext > parserContextSupplier ,
34
+ Map <String , MetadataFieldMapper .TypeParser > metadataMapperParsers ,
35
+ Supplier <Map <Class <? extends MetadataFieldMapper >, MetadataFieldMapper >> metadataMappersSupplier ,
36
+ Function <String , String > documentTypeResolver ) {
47
37
this .parserContextSupplier = parserContextSupplier ;
48
- this .rootTypeParsers = metadataMapperParsers ;
38
+ this .metadataMapperParsers = metadataMapperParsers ;
39
+ this .metadataMappersSupplier = metadataMappersSupplier ;
40
+ this .documentTypeResolver = documentTypeResolver ;
41
+ }
42
+
43
+ /**
44
+ * Verify that there are no remaining fields in the provided map that contained mapped fields
45
+ *
46
+ * @param fieldName the name of the field that is being parsed
47
+ * @param fieldNodeMap the map of fields
48
+ */
49
+ public static void checkNoRemainingFields (String fieldName , Map <?, ?> fieldNodeMap ) {
50
+ checkNoRemainingFields (fieldNodeMap , "Mapping definition for [" + fieldName + "] has unsupported parameters: " );
51
+ }
52
+
53
+ /**
54
+ * Verify that there are no remaining fields in the provided map that contained mapped fields
55
+ *
56
+ * @param fieldNodeMap the map of fields
57
+ * @param message the error message to be returned in case the provided map contains one or more fields
58
+ */
59
+ public static void checkNoRemainingFields (Map <?, ?> fieldNodeMap , String message ) {
60
+ if (fieldNodeMap .isEmpty () == false ) {
61
+ throw new MapperParsingException (message + getRemainingFields (fieldNodeMap ));
62
+ }
63
+ }
64
+
65
+ private static String getRemainingFields (Map <?, ?> map ) {
66
+ StringBuilder remainingFields = new StringBuilder ();
67
+ for (Object key : map .keySet ()) {
68
+ remainingFields .append (" [" ).append (key ).append (" : " ).append (map .get (key )).append ("]" );
69
+ }
70
+ return remainingFields .toString ();
49
71
}
50
72
51
73
@ SuppressWarnings ("unchecked" )
52
- DocumentMapper parse (@ Nullable String type , CompressedXContent source ) throws MapperParsingException {
74
+ Mapping parse (@ Nullable String type , CompressedXContent source ) throws MapperParsingException {
53
75
Map <String , Object > mapping = null ;
54
76
if (source != null ) {
55
77
mapping = XContentHelper .convertToMap (source .compressedReference (), true , XContentType .JSON ).v2 ();
@@ -65,82 +87,68 @@ DocumentMapper parse(@Nullable String type, CompressedXContent source) throws Ma
65
87
}
66
88
}
67
89
}
90
+ if (type == null ) {
91
+ throw new MapperParsingException ("Failed to derive type" );
92
+ }
68
93
if (mapping == null ) {
69
94
mapping = new HashMap <>();
70
95
}
71
96
return parse (type , mapping );
72
97
}
73
98
74
- @ SuppressWarnings ({"unchecked" })
75
- private DocumentMapper parse (String type , Map <String , Object > mapping ) throws MapperParsingException {
76
- if (type == null ) {
77
- throw new MapperParsingException ("Failed to derive type" );
78
- }
79
-
99
+ private Mapping parse (String type , Map <String , Object > mapping ) throws MapperParsingException {
100
+ ContentPath contentPath = new ContentPath (1 );
80
101
Mapper .TypeParser .ParserContext parserContext = parserContextSupplier .get ();
81
- // parse RootObjectMapper
82
- RootObjectMapper .Builder root = (RootObjectMapper .Builder ) rootObjectTypeParser .parse (type , mapping , parserContext );
83
- DocumentMapper .Builder docBuilder = new DocumentMapper .Builder (root , indexSettings , indexAnalyzers , documentParser ,
84
- metadataMappersSupplier .get ());
102
+ RootObjectMapper rootObjectMapper = rootObjectTypeParser .parse (type , mapping , parserContext ).build (contentPath );
103
+
104
+ Map <Class <? extends MetadataFieldMapper >, MetadataFieldMapper > metadataMappers = metadataMappersSupplier .get ();
105
+ Map <String , Object > meta = null ;
106
+
85
107
Iterator <Map .Entry <String , Object >> iterator = mapping .entrySet ().iterator ();
86
- // parse DocumentMapper
87
- while (iterator .hasNext ()) {
108
+ while (iterator .hasNext ()) {
88
109
Map .Entry <String , Object > entry = iterator .next ();
89
110
String fieldName = entry .getKey ();
90
111
Object fieldNode = entry .getValue ();
91
112
92
- MetadataFieldMapper .TypeParser typeParser = rootTypeParsers .get (fieldName );
113
+ MetadataFieldMapper .TypeParser typeParser = metadataMapperParsers .get (fieldName );
93
114
if (typeParser != null ) {
94
115
iterator .remove ();
95
116
if (false == fieldNode instanceof Map ) {
96
117
throw new IllegalArgumentException ("[_parent] must be an object containing [type]" );
97
118
}
119
+ @ SuppressWarnings ("unchecked" )
98
120
Map <String , Object > fieldNodeMap = (Map <String , Object >) fieldNode ;
99
- docBuilder .put (typeParser .parse (fieldName , fieldNodeMap , parserContext ));
121
+ MetadataFieldMapper metadataFieldMapper = typeParser .parse (fieldName , fieldNodeMap , parserContext ).build (contentPath );
122
+ metadataMappers .put (metadataFieldMapper .getClass (), metadataFieldMapper );
100
123
fieldNodeMap .remove ("type" );
101
124
checkNoRemainingFields (fieldName , fieldNodeMap );
102
125
}
103
126
}
104
127
105
- Map <String , Object > meta = (Map <String , Object >) mapping .remove ("_meta" );
106
- if (meta != null ) {
128
+ @ SuppressWarnings ("unchecked" )
129
+ Map <String , Object > removed = (Map <String , Object >) mapping .remove ("_meta" );
130
+ if (removed != null ) {
107
131
/*
108
132
* It may not be required to copy meta here to maintain immutability but the cost is pretty low here.
109
133
*
110
- * Note: this copy can not be replaced by Map#copyOf because we rely on consistent serialization order since we do byte-level
111
- * checks on the mapping between what we receive from the master and what we have locally. As Map#copyOf is not necessarily
112
- * the same underlying map implementation, we could end up with a different iteration order. For reference, see
113
- * MapperService#assertSerializtion and GitHub issues #10302 and #10318.
134
+ * Note: this copy can not be replaced by Map#copyOf because we rely on consistent serialization order since we do
135
+ * byte-level checks on the mapping between what we receive from the master and what we have locally. As Map#copyOf
136
+ * is not necessarily the same underlying map implementation, we could end up with a different iteration order.
137
+ * For reference, see MapperService#assertSerializtion and GitHub issues #10302 and #10318.
114
138
*
115
139
* Do not change this to Map#copyOf or any other method of copying meta that could change the iteration order.
116
140
*
117
141
* TODO:
118
142
* - this should almost surely be a copy as a LinkedHashMap to have the ordering guarantees that we are relying on
119
- * - investigate the above note about whether or not we really need to be copying here, the ideal outcome would be to not
143
+ * - investigate the above note about whether or not we need to be copying here, the ideal outcome would be to not
120
144
*/
121
- docBuilder . meta ( Collections .unmodifiableMap (new HashMap <>(meta ) ));
145
+ meta = Collections .unmodifiableMap (new HashMap <>(removed ));
122
146
}
123
-
124
147
checkNoRemainingFields (mapping , "Root mapping definition has unsupported parameters: " );
125
148
126
- return docBuilder .build ();
127
- }
128
-
129
- public static void checkNoRemainingFields (String fieldName , Map <?, ?> fieldNodeMap ) {
130
- checkNoRemainingFields (fieldNodeMap , "Mapping definition for [" + fieldName + "] has unsupported parameters: " );
131
- }
132
-
133
- public static void checkNoRemainingFields (Map <?, ?> fieldNodeMap , String message ) {
134
- if (fieldNodeMap .isEmpty () == false ) {
135
- throw new MapperParsingException (message + getRemainingFields (fieldNodeMap ));
136
- }
137
- }
138
-
139
- private static String getRemainingFields (Map <?, ?> map ) {
140
- StringBuilder remainingFields = new StringBuilder ();
141
- for (Object key : map .keySet ()) {
142
- remainingFields .append (" [" ).append (key ).append (" : " ).append (map .get (key )).append ("]" );
143
- }
144
- return remainingFields .toString ();
149
+ return new Mapping (
150
+ rootObjectMapper ,
151
+ metadataMappers .values ().toArray (new MetadataFieldMapper [0 ]),
152
+ meta );
145
153
}
146
154
}
0 commit comments