@@ -96,7 +96,7 @@ public String toString() {
9696
9797 public static class Defaults {
9898 public static final boolean ENABLED = true ;
99- public static final Optional <Subobjects > SUBOBJECTS = Optional . empty ( );
99+ public static final Explicit <Subobjects > SUBOBJECTS = Explicit . implicit ( Subobjects . ENABLED );
100100 public static final Explicit <Boolean > STORE_ARRAY_SOURCE = Explicit .IMPLICIT_FALSE ;
101101 public static final Dynamic DYNAMIC = Dynamic .TRUE ;
102102 }
@@ -133,13 +133,17 @@ static Dynamic getRootDynamic(MappingLookup mappingLookup) {
133133 }
134134
135135 public static class Builder extends Mapper .Builder {
136- protected Optional <Subobjects > subobjects ;
136+ protected Explicit <Subobjects > subobjects ;
137137 protected Explicit <Boolean > enabled = Explicit .IMPLICIT_TRUE ;
138138 protected Optional <SourceKeepMode > sourceKeepMode = Optional .empty ();
139139 protected Dynamic dynamic ;
140140 protected final List <Mapper .Builder > mappersBuilders = new ArrayList <>();
141141
142- public Builder (String name , Optional <Subobjects > subobjects ) {
142+ public Builder (String name ) {
143+ this (name , Defaults .SUBOBJECTS );
144+ }
145+
146+ public Builder (String name , Explicit <Subobjects > subobjects ) {
143147 super (name );
144148 this .subobjects = subobjects ;
145149 }
@@ -184,7 +188,7 @@ public Mapper build(MapperBuilderContext context) {
184188 public final void addDynamic (String name , String prefix , Mapper mapper , DocumentParserContext context ) {
185189 // If the mapper to add has no dots, or the current object mapper has subobjects set to false,
186190 // we just add it as it is for sure a leaf mapper
187- if (name .contains ("." ) == false || ( subobjects .isPresent () && ( subobjects . get () == Subobjects .DISABLED )) ) {
191+ if (name .contains ("." ) == false || subobjects .value () == Subobjects .DISABLED ) {
188192 add (name , mapper );
189193 } else {
190194 // We strip off the first object path of the mapper name, load or create
@@ -198,7 +202,7 @@ public final void addDynamic(String name, String prefix, Mapper mapper, Document
198202 if (parentBuilder != null ) {
199203 parentBuilder .addDynamic (name .substring (firstDotIndex + 1 ), immediateChildFullName , mapper , context );
200204 add (parentBuilder );
201- } else if (subobjects .isPresent () && subobjects . get () == Subobjects .AUTO ) {
205+ } else if (subobjects .value () == Subobjects .AUTO ) {
202206 // No matching parent object was found, the mapper is added as a leaf - similar to subobjects false.
203207 add (name , mapper );
204208 } else {
@@ -236,7 +240,7 @@ protected final Map<String, Mapper> buildMappers(MapperBuilderContext mapperBuil
236240 // mix of object notation and dot notation.
237241 mapper = existing .merge (mapper , MapperMergeContext .from (mapperBuilderContext , Long .MAX_VALUE ));
238242 }
239- if (subobjects .isPresent () && subobjects . get () == Subobjects .DISABLED && mapper instanceof ObjectMapper objectMapper ) {
243+ if (subobjects .value () == Subobjects .DISABLED && mapper instanceof ObjectMapper objectMapper ) {
240244 // We're parsing a mapping that has set `subobjects: false` but has defined sub-objects
241245 objectMapper .asFlattenedFieldMappers (mapperBuilderContext ).forEach (m -> mappers .put (m .leafName (), m ));
242246 } else {
@@ -279,7 +283,7 @@ public boolean supportsVersion(IndexVersion indexCreatedVersion) {
279283 public Mapper .Builder parse (String name , Map <String , Object > node , MappingParserContext parserContext )
280284 throws MapperParsingException {
281285 parserContext .incrementMappingObjectDepth (); // throws MapperParsingException if depth limit is exceeded
282- Optional <Subobjects > subobjects = parseSubobjects (node );
286+ Explicit <Subobjects > subobjects = parseSubobjects (node );
283287 Builder builder = new Builder (name , subobjects );
284288 parseObjectFields (node , parserContext , builder );
285289 parserContext .decrementMappingObjectDepth ();
@@ -344,10 +348,10 @@ protected static boolean parseObjectOrDocumentTypeProperties(
344348 return false ;
345349 }
346350
347- protected static Optional <Subobjects > parseSubobjects (Map <String , Object > node ) {
351+ protected static Explicit <Subobjects > parseSubobjects (Map <String , Object > node ) {
348352 Object subobjectsNode = node .remove ("subobjects" );
349353 if (subobjectsNode != null ) {
350- return Optional .of (Subobjects .from (subobjectsNode ));
354+ return Explicit .of (Subobjects .from (subobjectsNode ));
351355 }
352356 return Defaults .SUBOBJECTS ;
353357 }
@@ -384,9 +388,7 @@ protected static void parseProperties(Builder objBuilder, Map<String, Object> pr
384388 }
385389 }
386390
387- if (objBuilder .subobjects .isPresent ()
388- && objBuilder .subobjects .get () == Subobjects .DISABLED
389- && type .equals (NestedObjectMapper .CONTENT_TYPE )) {
391+ if (objBuilder .subobjects .value () == Subobjects .DISABLED && type .equals (NestedObjectMapper .CONTENT_TYPE )) {
390392 throw new MapperParsingException (
391393 "Tried to add nested object ["
392394 + fieldName
@@ -408,7 +410,7 @@ protected static void parseProperties(Builder objBuilder, Map<String, Object> pr
408410 );
409411 }
410412 Mapper .Builder fieldBuilder ;
411- if (objBuilder .subobjects .isPresent () && objBuilder . subobjects . get () != Subobjects .ENABLED ) {
413+ if (objBuilder .subobjects .value () != Subobjects .ENABLED ) {
412414 fieldBuilder = typeParser .parse (fieldName , propNode , parserContext );
413415 } else {
414416 String [] fieldNameParts = fieldName .split ("\\ ." );
@@ -456,7 +458,7 @@ private static void validateFieldName(String fieldName, IndexVersion indexCreate
456458 private final String fullPath ;
457459
458460 protected final Explicit <Boolean > enabled ;
459- protected final Optional <Subobjects > subobjects ;
461+ protected final Explicit <Subobjects > subobjects ;
460462 protected final Optional <SourceKeepMode > sourceKeepMode ;
461463 protected final Dynamic dynamic ;
462464
@@ -466,7 +468,7 @@ private static void validateFieldName(String fieldName, IndexVersion indexCreate
466468 String name ,
467469 String fullPath ,
468470 Explicit <Boolean > enabled ,
469- Optional <Subobjects > subobjects ,
471+ Explicit <Subobjects > subobjects ,
470472 Optional <SourceKeepMode > sourceKeepMode ,
471473 Dynamic dynamic ,
472474 Map <String , Mapper > mappers
@@ -484,9 +486,7 @@ private static void validateFieldName(String fieldName, IndexVersion indexCreate
484486 } else {
485487 this .mappers = Map .copyOf (mappers );
486488 }
487- assert subobjects .isEmpty ()
488- || subobjects .get () != Subobjects .DISABLED
489- || this .mappers .values ().stream ().noneMatch (m -> m instanceof ObjectMapper )
489+ assert subobjects .value () != Subobjects .DISABLED || this .mappers .values ().stream ().noneMatch (m -> m instanceof ObjectMapper )
490490 : "When subobjects is false, mappers must not contain an ObjectMapper" ;
491491 }
492492
@@ -540,7 +540,7 @@ public final Dynamic dynamic() {
540540 }
541541
542542 public final Subobjects subobjects () {
543- return subobjects .orElse ( Subobjects . ENABLED );
543+ return subobjects .value ( );
544544 }
545545
546546 public final Optional <SourceKeepMode > sourceKeepMode () {
@@ -581,7 +581,7 @@ public ObjectMapper merge(Mapper mergeWith, MapperMergeContext parentMergeContex
581581
582582 protected record MergeResult (
583583 Explicit <Boolean > enabled ,
584- Optional <Subobjects > subObjects ,
584+ Explicit <Subobjects > subObjects ,
585585 Optional <SourceKeepMode > sourceKeepMode ,
586586 Dynamic dynamic ,
587587 Map <String , Mapper > mappers
@@ -602,8 +602,8 @@ static MergeResult build(ObjectMapper existing, ObjectMapper mergeWithObject, Ma
602602 } else {
603603 enabled = existing .enabled ;
604604 }
605- final Optional <Subobjects > subObjects ;
606- if (mergeWithObject .subobjects .isPresent ()) {
605+ final Explicit <Subobjects > subObjects ;
606+ if (mergeWithObject .subobjects .explicit ()) {
607607 if (reason == MergeReason .INDEX_TEMPLATE ) {
608608 subObjects = mergeWithObject .subobjects ;
609609 } else if (existing .subobjects () != mergeWithObject .subobjects ()) {
@@ -650,13 +650,11 @@ private static Map<String, Mapper> buildMergedMappers(
650650 ObjectMapper existing ,
651651 ObjectMapper mergeWithObject ,
652652 MapperMergeContext objectMergeContext ,
653- Optional <Subobjects > subobjects
653+ Explicit <Subobjects > subobjects
654654 ) {
655655 Map <String , Mapper > mergedMappers = new HashMap <>();
656656 for (Mapper childOfExistingMapper : existing .mappers .values ()) {
657- if (subobjects .isPresent ()
658- && subobjects .get () == Subobjects .DISABLED
659- && childOfExistingMapper instanceof ObjectMapper objectMapper ) {
657+ if (subobjects .value () == Subobjects .DISABLED && childOfExistingMapper instanceof ObjectMapper objectMapper ) {
660658 // An existing mapping with sub-objects is merged with a mapping that has set `subobjects: false`
661659 objectMapper .asFlattenedFieldMappers (objectMergeContext .getMapperBuilderContext ())
662660 .forEach (m -> mergedMappers .put (m .leafName (), m ));
@@ -667,9 +665,7 @@ private static Map<String, Mapper> buildMergedMappers(
667665 for (Mapper mergeWithMapper : mergeWithObject ) {
668666 Mapper mergeIntoMapper = mergedMappers .get (mergeWithMapper .leafName ());
669667 if (mergeIntoMapper == null ) {
670- if (subobjects .isPresent ()
671- && subobjects .get () == Subobjects .DISABLED
672- && mergeWithMapper instanceof ObjectMapper objectMapper ) {
668+ if (subobjects .value () == Subobjects .DISABLED && mergeWithMapper instanceof ObjectMapper objectMapper ) {
673669 // An existing mapping that has set `subobjects: false` is merged with a mapping with sub-objects.
674670 List <FieldMapper > flattenedMappers = objectMapper .asFlattenedFieldMappers (
675671 objectMergeContext .getMapperBuilderContext ()
@@ -691,7 +687,7 @@ private static Map<String, Mapper> buildMergedMappers(
691687 putMergedMapper (mergedMappers , truncateObjectMapper (objectMergeContext , om ));
692688 }
693689 } else if (mergeIntoMapper instanceof ObjectMapper objectMapper ) {
694- assert subobjects .isEmpty () || subobjects .get () != Subobjects .DISABLED
690+ assert subobjects .explicit () == false || subobjects .value () != Subobjects .DISABLED
695691 : "existing object mappers are supposed to be flattened if subobjects is false" ;
696692 putMergedMapper (mergedMappers , objectMapper .merge (mergeWithMapper , objectMergeContext ));
697693 } else {
@@ -803,7 +799,7 @@ private void ensureFlattenable(MapperBuilderContext context, ContentPath path) {
803799 if (isEnabled () == false ) {
804800 throwAutoFlatteningException (path , "the value of [enabled] is [false]" );
805801 }
806- if (subobjects .isPresent () && subobjects .get () == Subobjects .ENABLED ) {
802+ if (subobjects .explicit () && subobjects .value () == Subobjects .ENABLED ) {
807803 throwAutoFlatteningException (path , "the value of [subobjects] is [true]" );
808804 }
809805 }
@@ -838,8 +834,8 @@ void toXContent(XContentBuilder builder, Params params, ToXContent custom) throw
838834 if (isEnabled () != Defaults .ENABLED ) {
839835 builder .field ("enabled" , enabled .value ());
840836 }
841- if (subobjects .isPresent ()) {
842- builder .field ("subobjects" , subobjects .get ().printedValue );
837+ if (subobjects .explicit ()) {
838+ builder .field ("subobjects" , subobjects .value ().printedValue );
843839 }
844840 if (sourceKeepMode .isPresent ()) {
845841 builder .field ("synthetic_source_keep" , sourceKeepMode .get ());
0 commit comments