This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 22c37b3c7fd SOLR-17600: MapSerializable p2: Migrate Core config 
classes (#4464)
22c37b3c7fd is described below

commit 22c37b3c7fd185ac349980787a96d04565c23231
Author: Ivan Šarić <[email protected]>
AuthorDate: Thu Jun 11 19:22:30 2026 +0200

    SOLR-17600: MapSerializable p2: Migrate Core config classes (#4464)
    
    MapSerializable is deprecated; stop using it in some places.
---
 .../solr/api/NodeConfigClusterPluginsSource.java   |   3 +-
 .../java/org/apache/solr/core/ConfigOverlay.java   |  12 +-
 .../src/java/org/apache/solr/core/PluginInfo.java  |  50 +++++---
 .../java/org/apache/solr/core/RequestParams.java   |  26 ++--
 .../src/java/org/apache/solr/core/SolrConfig.java  | 134 +++++++++++----------
 .../apache/solr/filestore/ClusterFileStore.java    |   3 +-
 .../org/apache/solr/handler/SolrConfigHandler.java |   5 +-
 .../java/org/apache/solr/schema/IndexSchema.java   |  23 ++--
 .../java/org/apache/solr/search/CacheConfig.java   |  12 +-
 .../org/apache/solr/update/IndexFingerprint.java   |  25 ++--
 .../org/apache/solr/update/SolrIndexConfig.java    |  39 +++---
 .../api/NodeConfigClusterPluginsSourceTest.java    |   5 +-
 .../test/org/apache/solr/core/CacheConfigTest.java |   8 +-
 .../src/test/org/apache/solr/core/TestConfig.java  |   6 +-
 .../apache/solr/update/SolrIndexConfigTest.java    |  12 +-
 15 files changed, 188 insertions(+), 175 deletions(-)

diff --git 
a/solr/core/src/java/org/apache/solr/api/NodeConfigClusterPluginsSource.java 
b/solr/core/src/java/org/apache/solr/api/NodeConfigClusterPluginsSource.java
index 4282cce69b2..360ef8c3e96 100644
--- a/solr/core/src/java/org/apache/solr/api/NodeConfigClusterPluginsSource.java
+++ b/solr/core/src/java/org/apache/solr/api/NodeConfigClusterPluginsSource.java
@@ -79,8 +79,7 @@ public class NodeConfigClusterPluginsSource implements 
ClusterPluginsSource {
         pluginMap.put("class", p.className);
 
         if (p.initArgs.size() > 0) {
-          Map<String, Object> config = p.initArgs.toMap(new HashMap<>());
-          pluginMap.put("config", config);
+          pluginMap.put("config", p.initArgs.asMap(0));
         }
 
         pluginInfos.put(pluginName, pluginMap);
diff --git a/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java 
b/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
index 480df900f83..9898d5efeac 100644
--- a/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
+++ b/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
@@ -18,12 +18,13 @@ package org.apache.solr.core;
 
 import static org.apache.solr.common.util.Utils.toJSONString;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.util.StrUtils;
@@ -33,7 +34,7 @@ import org.apache.solr.common.util.Utils;
  * This class encapsulates the config overlay json file. It is immutable and 
any edit operations
  * performed on this gives a new copy of the object with the changed value
  */
-public class ConfigOverlay implements MapSerializable {
+public class ConfigOverlay implements MapWriter {
   private final int version;
   private final Map<String, Object> data;
   private Map<String, Object> props;
@@ -233,10 +234,9 @@ public class ConfigOverlay implements MapSerializable {
   }
 
   @Override
-  public Map<String, Object> toMap(Map<String, Object> map) {
-    map.put(ZNODEVER, version);
-    map.putAll(data);
-    return map;
+  public void writeMap(EntryWriter ew) throws IOException {
+    ew.put(ZNODEVER, version);
+    data.forEach(ew::putNoEx);
   }
 
   @SuppressWarnings({"unchecked"})
diff --git a/solr/core/src/java/org/apache/solr/core/PluginInfo.java 
b/solr/core/src/java/org/apache/solr/core/PluginInfo.java
index 1cd80713b44..1b5e501e423 100644
--- a/solr/core/src/java/org/apache/solr/core/PluginInfo.java
+++ b/solr/core/src/java/org/apache/solr/core/PluginInfo.java
@@ -23,19 +23,20 @@ import static 
org.apache.solr.common.params.CoreAdminParams.NAME;
 import static org.apache.solr.schema.FieldType.CLASS_NAME;
 
 import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import org.apache.solr.common.ConfigNode;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.util.DOMConfigNode;
 import org.w3c.dom.Node;
 
 /** An Object which represents a Plugin of any type */
-public class PluginInfo implements MapSerializable {
+public class PluginInfo implements MapWriter {
   public final String name, className, type, pkgName;
   public final ClassName cName;
   public final NamedList<Object> initArgs;
@@ -193,26 +194,35 @@ public class PluginInfo implements MapSerializable {
 
   @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
-  public Map<String, Object> toMap(Map<String, Object> map) {
-    map.putAll(attributes);
-    Map m = map;
-    if (initArgs != null) m.putAll(initArgs.asMap(3));
-    if (children != null) {
-      for (PluginInfo child : children) {
-        Object old = m.get(child.name);
-        if (old == null) {
-          m.put(child.name, child.toMap(new LinkedHashMap<>()));
-        } else if (old instanceof List list) {
-          list.add(child.toMap(new LinkedHashMap<>()));
-        } else {
-          ArrayList l = new ArrayList();
-          l.add(old);
-          l.add(child.toMap(new LinkedHashMap<>()));
-          m.put(child.name, l);
-        }
+  public void writeMap(EntryWriter ew) throws IOException {
+    // Direct forEach(ew::putNoEx) does not work: attributes is declared 
Map<String, String> but
+    // the PluginInfo(String, Map<String, Object>) constructor assigns it via 
raw types, so values
+    // may not be Strings. The bridge method generated for forEach would CCE 
on non-String values.
+    new NamedList<>(attributes).writeMap(ew);
+    if (initArgs != null) {
+      initArgs.asMap(3).forEach((k, v) -> ew.putNoEx((String) k, v));
+    }
+    if (children == null || children.isEmpty()) {
+      return;
+    }
+
+    Map<String, Object> childrenGrouped = new LinkedHashMap<>();
+    for (PluginInfo child : children) {
+      Object old = childrenGrouped.get(child.name);
+      if (old == null) {
+        childrenGrouped.put(child.name, child);
+      } else if (old instanceof List list) {
+        list.add(child);
+      } else {
+        List<Object> l = new ArrayList<>();
+        l.add(old);
+        l.add(child);
+        childrenGrouped.put(child.name, l);
       }
     }
-    return m;
+    for (Map.Entry<String, Object> entry : childrenGrouped.entrySet()) {
+      ew.put(entry.getKey(), entry.getValue());
+    }
   }
 
   /**
diff --git a/solr/core/src/java/org/apache/solr/core/RequestParams.java 
b/solr/core/src/java/org/apache/solr/core/RequestParams.java
index 469b107e9af..b1c80bf3836 100644
--- a/solr/core/src/java/org/apache/solr/core/RequestParams.java
+++ b/solr/core/src/java/org/apache/solr/core/RequestParams.java
@@ -24,7 +24,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import org.apache.solr.cloud.ZkSolrResourceLoader;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.SolrZkClient;
 import org.apache.solr.common.params.MultiMapSolrParams;
@@ -38,7 +38,7 @@ import org.slf4j.LoggerFactory;
  * The class encapsulates the request time parameters . This is immutable and 
any changes performed
  * returns a copy of the Object with the changed values
  */
-public class RequestParams implements MapSerializable {
+public class RequestParams implements MapWriter {
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   private final Map<String, Object> data;
@@ -112,8 +112,9 @@ public class RequestParams implements MapSerializable {
   }
 
   @Override
-  public Map<String, Object> toMap(Map<String, Object> map) {
-    return getMapWithVersion(data, znodeVersion);
+  public void writeMap(EntryWriter ew) throws IOException {
+    ew.put(ConfigOverlay.ZNODEVER, znodeVersion);
+    data.forEach(ew::putNoEx);
   }
 
   public static Map<String, Object> getMapWithVersion(Map<String, Object> 
data, int znodeVersion) {
@@ -129,7 +130,9 @@ public class RequestParams implements MapSerializable {
     Map p = (Map) deepCopy.get(NAME);
     if (p == null) deepCopy.put(NAME, p = new LinkedHashMap<>());
     if (paramSet == null) p.remove(name);
-    else p.put(name, paramSet.toMap(new LinkedHashMap<>()));
+    else {
+      p.put(name, Utils.convertToMap(paramSet, new LinkedHashMap<>()));
+    }
     return new RequestParams(deepCopy, znodeVersion);
   }
 
@@ -207,7 +210,7 @@ public class RequestParams implements MapSerializable {
   public static final String INVARIANTS = "_invariants_";
 
   @SuppressWarnings({"unchecked"})
-  public static class ParamSet implements MapSerializable {
+  public static class ParamSet implements MapWriter {
     private final Map<String, Object> defaults, appends, invariants;
     Map<String, VersionedParams> paramsMap;
     public final Map<String, Long> meta;
@@ -234,12 +237,11 @@ public class RequestParams implements MapSerializable {
     }
 
     @Override
-    public Map<String, Object> toMap(Map<String, Object> result) {
-      result.putAll(defaults);
-      if (appends != null) result.put(APPENDS, appends);
-      if (invariants != null) result.put(INVARIANTS, invariants);
-      if (meta != null) result.put("", meta);
-      return result;
+    public void writeMap(EntryWriter ew) throws IOException {
+      defaults.forEach(ew::putNoEx);
+      if (appends != null) ew.put(APPENDS, appends);
+      if (invariants != null) ew.put(INVARIANTS, invariants);
+      if (meta != null) ew.put("", meta);
     }
 
     @SuppressWarnings({"rawtypes"})
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java 
b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index 1bbe7a9f807..b5358755d1f 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -59,7 +59,7 @@ import 
org.apache.solr.client.solrj.io.stream.expr.Expressible;
 import org.apache.solr.cloud.RecoveryStrategy;
 import org.apache.solr.cloud.ZkSolrResourceLoader;
 import org.apache.solr.common.ConfigNode;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.util.IOUtils;
@@ -96,7 +96,7 @@ import org.slf4j.LoggerFactory;
  * Provides a static reference to a Config object modeling the main 
configuration data for a Solr
  * core -- typically found in "solrconfig.xml".
  */
-public class SolrConfig implements MapSerializable {
+public class SolrConfig implements MapWriter {
 
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
@@ -685,23 +685,17 @@ public class SolrConfig implements MapSerializable {
     return httpCachingConfig;
   }
 
-  public static class HttpCachingConfig implements MapSerializable {
+  public static class HttpCachingConfig implements MapWriter {
 
     /** For extracting Expires "ttl" from <cacheControl> config */
     private static final Pattern MAX_AGE = 
Pattern.compile("\\bmax-age=(\\d+)");
 
     @Override
-    public Map<String, Object> toMap(Map<String, Object> map) {
-      // Could have nulls
-      return Utils.makeMap(
-          "never304",
-          never304,
-          "etagSeed",
-          etagSeed,
-          "lastModFrom",
-          lastModFrom.name().toLowerCase(Locale.ROOT),
-          "cacheControl",
-          cacheControlHeader);
+    public void writeMap(EntryWriter ew) throws IOException {
+      ew.put("never304", never304)
+          .put("etagSeed", etagSeed)
+          .put("lastModFrom", lastModFrom.name().toLowerCase(Locale.ROOT))
+          .put("cacheControl", cacheControlHeader);
     }
 
     public enum LastModFrom {
@@ -783,7 +777,7 @@ public class SolrConfig implements MapSerializable {
     }
   }
 
-  public static class UpdateHandlerInfo implements MapSerializable {
+  public static class UpdateHandlerInfo implements MapWriter {
     public final String className;
     public final int autoCommmitMaxDocs,
         autoCommmitMaxTime,
@@ -842,19 +836,18 @@ public class SolrConfig implements MapSerializable {
     }
 
     @Override
-    public Map<String, Object> toMap(Map<String, Object> map) {
-      map.put("commitWithin", Map.of("softCommit", commitWithinSoftCommit));
-      map.put(
+    public void writeMap(EntryWriter ew) throws IOException {
+      ew.put("commitWithin", Map.of("softCommit", commitWithinSoftCommit));
+      ew.put(
           "autoCommit",
           Map.of(
               "maxDocs", autoCommmitMaxDocs,
               "maxTime", autoCommmitMaxTime,
               "openSearcher", openSearcher));
-      map.put(
+      ew.put(
           "autoSoftCommit",
           Map.of("maxDocs", autoSoftCommmitMaxDocs, "maxTime", 
autoSoftCommmitMaxTime));
-      map.put("commitPollInterval", commitPollInterval);
-      return map;
+      ew.put("commitPollInterval", commitPollInterval);
     }
   }
 
@@ -952,20 +945,34 @@ public class SolrConfig implements MapSerializable {
   }
 
   @Override
-  public Map<String, Object> toMap(Map<String, Object> result) {
-    if (znodeVersion > -1) result.put(ZNODEVER, znodeVersion);
-    if (luceneMatchVersion != null)
-      result.put(IndexSchema.LUCENE_MATCH_VERSION_PARAM, 
luceneMatchVersion.toString());
-    result.put("updateHandler", getUpdateHandlerInfo());
-    Map<String, Object> m = new LinkedHashMap<>();
-    result.put("query", m);
-    m.put("useFilterForSortedQuery", useFilterForSortedQuery);
-    m.put("queryResultWindowSize", queryResultWindowSize);
-    m.put("queryResultMaxDocsCached", queryResultMaxDocsCached);
-    m.put("enableLazyFieldLoading", enableLazyFieldLoading);
-    m.put("maxBooleanClauses", booleanQueryMaxClauseCount);
-    m.put(MIN_PREFIX_QUERY_TERM_LENGTH, prefixQueryMinPrefixLength);
+  public void writeMap(EntryWriter ew) throws IOException {
+    if (znodeVersion > -1) {
+      ew.put(ZNODEVER, znodeVersion);
+    }
+    if (luceneMatchVersion != null) {
+      ew.put(IndexSchema.LUCENE_MATCH_VERSION_PARAM, 
luceneMatchVersion.toString());
+    }
 
+    ew.put("updateHandler", getUpdateHandlerInfo());
+    ew.put(
+        "query",
+        (MapWriter)
+            m -> {
+              m.put("useFilterForSortedQuery", useFilterForSortedQuery);
+              m.put("queryResultWindowSize", queryResultWindowSize);
+              m.put("queryResultMaxDocsCached", queryResultMaxDocsCached);
+              m.put("enableLazyFieldLoading", enableLazyFieldLoading);
+              m.put("maxBooleanClauses", booleanQueryMaxClauseCount);
+              m.put(MIN_PREFIX_QUERY_TERM_LENGTH, prefixQueryMinPrefixLength);
+
+              addCacheConfig(
+                  m,
+                  filterCacheConfig,
+                  queryResultCacheConfig,
+                  documentCacheConfig,
+                  fieldValueCacheConfig,
+                  featureVectorCacheConfig);
+            });
     for (SolrPluginInfo plugin : plugins) {
       List<PluginInfo> infos = getPluginInfos(plugin.clazz.getName());
       if (infos == null || infos.isEmpty()) continue;
@@ -982,45 +989,46 @@ public class SolrConfig implements MapSerializable {
             overlay.getNamedPlugins(plugin.tag).entrySet()) {
           items.put(e.getKey(), e.getValue());
         }
-        result.put(tag, items);
+        ew.put(
+            tag,
+            (MapWriter)
+                m -> {
+                  for (Map.Entry<String, Object> item : items.entrySet()) {
+                    m.put(item.getKey(), item.getValue());
+                  }
+                });
       } else {
         if (plugin.options.contains(MULTI_OK)) {
-          ArrayList<MapSerializable> l = new ArrayList<>();
-          for (PluginInfo info : infos) l.add(info);
-          result.put(tag, l);
+          ew.put(tag, infos);
         } else {
-          result.put(tag, infos.get(0));
+          ew.put(tag, infos.getFirst());
         }
       }
     }
 
-    addCacheConfig(
-        m,
-        filterCacheConfig,
-        queryResultCacheConfig,
-        documentCacheConfig,
-        fieldValueCacheConfig,
-        featureVectorCacheConfig);
-    m = new LinkedHashMap<>();
-    result.put("requestDispatcher", m);
-    if (httpCachingConfig != null) m.put("httpCaching", httpCachingConfig);
-    m.put(
-        "requestParsers",
-        Map.of(
-            "multipartUploadLimitKB",
-            multipartUploadLimitKB,
-            "formUploadLimitKB",
-            formUploadLimitKB));
-    if (indexConfig != null) result.put("indexConfig", indexConfig);
-
-    // TODO there is more to add
-
-    return result;
+    ew.put(
+        "requestDispatcher",
+        (MapWriter)
+            m -> {
+              if (httpCachingConfig != null) m.put("httpCaching", 
httpCachingConfig);
+              m.put(
+                  "requestParsers",
+                  Map.of(
+                      "multipartUploadLimitKB",
+                      multipartUploadLimitKB,
+                      "formUploadLimitKB",
+                      formUploadLimitKB));
+            });
+    if (indexConfig != null) ew.put("indexConfig", indexConfig);
   }
 
-  private void addCacheConfig(Map<String, Object> queryMap, CacheConfig... 
cache) {
+  private void addCacheConfig(EntryWriter queryMap, CacheConfig... cache) 
throws IOException {
     if (cache == null) return;
-    for (CacheConfig config : cache) if (config != null) 
queryMap.put(config.getNodeName(), config);
+    for (CacheConfig cc : cache) {
+      if (cc != null) {
+        queryMap.put(cc.getNodeName(), cc);
+      }
+    }
   }
 
   public Properties getSubstituteProperties() {
diff --git a/solr/core/src/java/org/apache/solr/filestore/ClusterFileStore.java 
b/solr/core/src/java/org/apache/solr/filestore/ClusterFileStore.java
index bcd4e562053..80ea2066e65 100644
--- a/solr/core/src/java/org/apache/solr/filestore/ClusterFileStore.java
+++ b/solr/core/src/java/org/apache/solr/filestore/ClusterFileStore.java
@@ -46,6 +46,7 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.common.util.SuppressForbidden;
+import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.jersey.PermissionName;
@@ -269,7 +270,7 @@ public class ClusterFileStore extends JerseyResource 
implements ClusterFileStore
     entryMetadata.size = size;
     entryMetadata.timestamp = timestamp;
     if (details.getMetaData() != null) {
-      details.getMetaData().toMap(entryMetadata.unknownProperties());
+      Utils.convertToMap(details.getMetaData(), 
entryMetadata.unknownProperties());
     }
 
     return entryMetadata;
diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java 
b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
index 975bd79d65b..c9e528e2455 100644
--- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
@@ -336,7 +336,8 @@ public class SolrConfigHandler extends RequestHandlerBase
     private Map<String, Object> getConfigDetails(String componentType, 
SolrQueryRequest req) {
       String componentName = componentType == null ? null : 
req.getParams().get("componentName");
       boolean showParams = req.getParams().getBool("expandParams", false);
-      Map<String, Object> map = this.req.getCore().getSolrConfig().toMap(new 
LinkedHashMap<>());
+      Map<String, Object> map =
+          Utils.convertToMap(this.req.getCore().getSolrConfig(), new 
LinkedHashMap<>());
       if (componentType != null && 
!SolrRequestHandler.TYPE.equals(componentType)) return map;
 
       @SuppressWarnings({"unchecked"})
@@ -369,7 +370,7 @@ public class SolrConfigHandler extends RequestHandlerBase
       if (plugin instanceof Map) {
         pluginInfo = (Map) plugin;
       } else if (plugin instanceof PluginInfo) {
-        pluginInfo = ((PluginInfo) plugin).toMap(new LinkedHashMap<>());
+        pluginInfo = Utils.convertToMap((PluginInfo) plugin, new 
LinkedHashMap<>());
       }
       String useParams = (String) pluginInfo.get(USEPARAM);
       String useParamsInReq = req.getOriginalParams().get(USEPARAM);
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java 
b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index ff81ecc84b3..05b362f95b6 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -27,7 +27,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
@@ -56,7 +55,7 @@ import org.apache.lucene.util.ResourceLoaderAware;
 import org.apache.lucene.util.Version;
 import org.apache.solr.analysis.TokenizerChain;
 import org.apache.solr.common.ConfigNode;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
@@ -68,7 +67,6 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.Cache;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.Pair;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.ConfigSetService;
 import org.apache.solr.core.SolrCore;
@@ -1557,7 +1555,7 @@ public class IndexSchema {
     return getNamedPropertyValues(null, new MapSolrParams(Map.of()));
   }
 
-  public static class SchemaProps implements MapSerializable {
+  public static class SchemaProps implements MapWriter {
     private static final String SOURCE_FIELD_LIST = IndexSchema.SOURCE + "." + 
CommonParams.FL;
     private static final String DESTINATION_FIELD_LIST =
         IndexSchema.DESTINATION + "." + CommonParams.FL;
@@ -1683,12 +1681,13 @@ public class IndexSchema {
     }
 
     @Override
-    public Map<String, Object> toMap(Map<String, Object> map) {
-      return Stream.of(Handler.values())
-          .filter(it -> name == null || it.nameLower.equals(name))
-          .map(it -> new Pair<>(it.realName, it.fun.apply(this)))
-          .filter(it -> it.second() != null)
-          .collect(Collectors.toMap(Pair::first, Pair::second, (v1, v2) -> v2, 
LinkedHashMap::new));
+    public void writeMap(EntryWriter ew) throws IOException {
+      for (Handler it : Handler.values()) {
+        if (name == null || it.nameLower.equals(name)) {
+          Object val = it.fun.apply(this);
+          if (val != null) ew.put(it.realName, val);
+        }
+      }
     }
   }
 
@@ -1699,7 +1698,9 @@ public class IndexSchema {
                   SchemaProps.Handler::getNameLower, 
SchemaProps.Handler::getRealName));
 
   public Map<String, Object> getNamedPropertyValues(String name, SolrParams 
params) {
-    return new SchemaProps(name, params, this).toMap(new LinkedHashMap<>());
+    // Must remain a SimpleOrderedMap (with SOM-valued entries preserved) — 
SchemaXmlWriter casts
+    // nested values to SimpleOrderedMap when persisting managed schemas.
+    return new SimpleOrderedMap<>(new SchemaProps(name, params, this));
   }
 
   /**
diff --git a/solr/core/src/java/org/apache/solr/search/CacheConfig.java 
b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
index c253f48fa41..71b24ed4c79 100644
--- a/solr/core/src/java/org/apache/solr/search/CacheConfig.java
+++ b/solr/core/src/java/org/apache/solr/search/CacheConfig.java
@@ -18,6 +18,7 @@ package org.apache.solr.search;
 
 import static org.apache.solr.common.params.CommonParams.NAME;
 
+import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -25,7 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.function.Supplier;
 import org.apache.solr.common.ConfigNode;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.util.CollectionUtil;
 import org.apache.solr.core.PluginInfo;
 import org.apache.solr.core.SolrConfig;
@@ -37,7 +38,7 @@ import org.slf4j.LoggerFactory;
  * Contains the knowledge of how cache config is stored in the solrconfig.xml 
file, and implements a
  * factory to create caches.
  */
-public class CacheConfig implements MapSerializable {
+public class CacheConfig implements MapWriter {
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   private String nodeName;
@@ -175,9 +176,10 @@ public class CacheConfig implements MapSerializable {
   }
 
   @Override
-  public Map<String, Object> toMap(Map<String, Object> argsMap) {
-    // TODO: Should not create new HashMap?
-    return new HashMap<>(args);
+  public void writeMap(EntryWriter ew) throws IOException {
+    for (Map.Entry<String, String> entry : args.entrySet()) {
+      ew.put(entry.getKey(), entry.getValue());
+    }
   }
 
   public String getNodeName() {
diff --git a/solr/core/src/java/org/apache/solr/update/IndexFingerprint.java 
b/solr/core/src/java/org/apache/solr/update/IndexFingerprint.java
index 8a62ce299b1..1323c9eb083 100644
--- a/solr/core/src/java/org/apache/solr/update/IndexFingerprint.java
+++ b/solr/core/src/java/org/apache/solr/update/IndexFingerprint.java
@@ -19,17 +19,17 @@ package org.apache.solr.update;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.util.Bits;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.Hash;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.SolrIndexSearcher;
@@ -41,7 +41,7 @@ import org.slf4j.LoggerFactory;
 /**
  * @lucene.internal
  */
-public class IndexFingerprint implements MapSerializable {
+public class IndexFingerprint implements MapWriter {
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   private long maxVersionSpecified;
@@ -177,15 +177,14 @@ public class IndexFingerprint implements MapSerializable {
   }
 
   @Override
-  public Map<String, Object> toMap(Map<String, Object> map) {
-    map.put("maxVersionSpecified", maxVersionSpecified);
-    map.put("maxVersionEncountered", maxVersionEncountered);
-    map.put("maxInHash", maxInHash);
-    map.put("versionsHash", versionsHash);
-    map.put("numVersions", numVersions);
-    map.put("numDocs", numDocs);
-    map.put("maxDoc", maxDoc);
-    return map;
+  public void writeMap(EntryWriter ew) throws IOException {
+    ew.put("maxVersionSpecified", maxVersionSpecified)
+        .put("maxVersionEncountered", maxVersionEncountered)
+        .put("maxInHash", maxInHash)
+        .put("versionsHash", versionsHash)
+        .put("numVersions", numVersions)
+        .put("numDocs", numDocs)
+        .put("maxDoc", maxDoc);
   }
 
   private static long getLong(Map<String, Object> m, String key, long def) {
@@ -218,7 +217,7 @@ public class IndexFingerprint implements MapSerializable {
 
   @Override
   public String toString() {
-    return toMap(new LinkedHashMap<>()).toString();
+    return new SimpleOrderedMap<>(this).toString();
   }
 
   @Override
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java 
b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
index 30e7687eda2..8c672962846 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
@@ -32,7 +32,7 @@ import org.apache.lucene.index.MergeScheduler;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.util.InfoStream;
 import org.apache.solr.common.ConfigNode;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SuppressForbidden;
 import org.apache.solr.core.DirectoryFactory;
@@ -53,7 +53,7 @@ import org.slf4j.LoggerFactory;
  * This config object encapsulates IndexWriter config params, defined in the 
&lt;indexConfig&gt;
  * section of solrconfig.xml
  */
-public class SolrIndexConfig implements MapSerializable {
+public class SolrIndexConfig implements MapWriter {
   private static final Logger log = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   private static final String NO_SUB_PACKAGES[] = new String[0];
@@ -195,28 +195,19 @@ public class SolrIndexConfig implements MapSerializable {
   }
 
   @Override
-  public Map<String, Object> toMap(Map<String, Object> map) {
-    map.put("useCompoundFile", useCompoundFile);
-    map.put("maxBufferedDocs", maxBufferedDocs);
-    map.put("ramBufferSizeMB", ramBufferSizeMB);
-    map.put("ramPerThreadHardLimitMB", ramPerThreadHardLimitMB);
-    map.put("maxCommitMergeWaitTime", maxCommitMergeWaitMillis);
-    map.put("writeLockTimeout", writeLockTimeout);
-    map.put("lockType", lockType);
-    map.put("infoStreamEnabled", infoStream != InfoStream.NO_OUTPUT);
-    if (mergeSchedulerInfo != null) {
-      map.put("mergeScheduler", mergeSchedulerInfo);
-    }
-    if (metricsInfo != null) {
-      map.put("metrics", metricsInfo);
-    }
-    if (mergePolicyFactoryInfo != null) {
-      map.put("mergePolicyFactory", mergePolicyFactoryInfo);
-    }
-    if (mergedSegmentWarmerInfo != null) {
-      map.put("mergedSegmentWarmer", mergedSegmentWarmerInfo);
-    }
-    return map;
+  public void writeMap(EntryWriter ew) throws IOException {
+    ew.put("useCompoundFile", useCompoundFile)
+        .put("maxBufferedDocs", maxBufferedDocs)
+        .put("ramBufferSizeMB", ramBufferSizeMB)
+        .put("ramPerThreadHardLimitMB", ramPerThreadHardLimitMB)
+        .put("maxCommitMergeWaitTime", maxCommitMergeWaitMillis)
+        .put("writeLockTimeout", writeLockTimeout)
+        .put("lockType", lockType)
+        .put("infoStreamEnabled", infoStream != InfoStream.NO_OUTPUT)
+        .putIfNotNull("mergeScheduler", mergeSchedulerInfo)
+        .putIfNotNull("metrics", metricsInfo)
+        .putIfNotNull("mergePolicyFactory", mergePolicyFactoryInfo)
+        .putIfNotNull("mergedSegmentWarmer", mergedSegmentWarmerInfo);
   }
 
   private PluginInfo getPluginInfo(ConfigNode node, PluginInfo def) {
diff --git 
a/solr/core/src/test/org/apache/solr/api/NodeConfigClusterPluginsSourceTest.java
 
b/solr/core/src/test/org/apache/solr/api/NodeConfigClusterPluginsSourceTest.java
index 0ad8666c527..d7489660f20 100644
--- 
a/solr/core/src/test/org/apache/solr/api/NodeConfigClusterPluginsSourceTest.java
+++ 
b/solr/core/src/test/org/apache/solr/api/NodeConfigClusterPluginsSourceTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.solr.api;
 
-import java.util.HashMap;
 import java.util.Map;
 import org.apache.solr.client.solrj.RemoteSolrException;
 import org.apache.solr.client.solrj.request.V2Request;
@@ -29,6 +28,7 @@ import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.annotation.JsonProperty;
 import org.apache.solr.common.util.ReflectMapWriter;
+import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.CoreContainer;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -89,8 +89,7 @@ public class NodeConfigClusterPluginsSourceTest extends 
SolrCloudTestCase {
         apiInfo.getInfo().klass);
     MapWriter config = apiInfo.getInfo().config;
     assertNotNull("config should be set for " + SingletonWithConfig.NAME, 
config);
-    Map<String, Object> configMap = new HashMap<>();
-    config.toMap(configMap);
+    Map<String, Object> configMap = new SimpleOrderedMap<>(config);
     assertEquals("incorrect config val for cfgInt parameter", CFG_VAL, 
configMap.get("cfgInt"));
   }
 
diff --git a/solr/core/src/test/org/apache/solr/core/CacheConfigTest.java 
b/solr/core/src/test/org/apache/solr/core/CacheConfigTest.java
index f8825a7f108..8eb503dbaf7 100644
--- a/solr/core/src/test/org/apache/solr/core/CacheConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/core/CacheConfigTest.java
@@ -20,7 +20,6 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Map;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -28,6 +27,7 @@ import javax.xml.parsers.ParserConfigurationException;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.ConfigNode;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.search.CacheConfig;
 import org.apache.solr.util.DOMConfigNode;
 import org.junit.Before;
@@ -91,7 +91,7 @@ public class CacheConfigTest extends SolrTestCaseJ4 {
     final CacheConfig cacheConfig =
         CacheConfig.getConfig(mockSolrConfig, domConfigNode, 
XPATH_DOCUMENT_CACHE);
     assertNotNull(cacheConfig);
-    final Map<String, Object> args = cacheConfig.toMap(new HashMap<>());
+    final Map<String, Object> args = new SimpleOrderedMap<>(cacheConfig);
     assertNotNull(args);
     assertEquals("99", args.get("initialSize"));
     assertEquals("999", args.get("size"));
@@ -119,7 +119,7 @@ public class CacheConfigTest extends SolrTestCaseJ4 {
     final CacheConfig cacheConfig =
         CacheConfig.getConfig(mockSolrConfig, domConfigNode, 
XPATH_DOCUMENT_CACHE);
     assertNotNull(cacheConfig);
-    final Map<String, Object> args = cacheConfig.toMap(new HashMap<>());
+    final Map<String, Object> args = new SimpleOrderedMap<>(cacheConfig);
     assertNotNull(args);
     assertEquals(overlaidSize, args.get("size"));
   }
@@ -146,7 +146,7 @@ public class CacheConfigTest extends SolrTestCaseJ4 {
     final CacheConfig cacheConfig =
         CacheConfig.getConfig(mockSolrConfig, overlayConfigNode, 
XPATH_QUERY_RESULT_CACHE);
     assertNotNull(cacheConfig);
-    final Map<String, Object> args = cacheConfig.toMap(new HashMap<>());
+    final Map<String, Object> args = new SimpleOrderedMap<>(cacheConfig);
     assertNotNull(args);
     assertEquals("99", args.get("initialSize"));
     assertEquals("queryResultCache", cacheConfig.getNodeName());
diff --git a/solr/core/src/test/org/apache/solr/core/TestConfig.java 
b/solr/core/src/test/org/apache/solr/core/TestConfig.java
index 0ba42bb156d..a856090e54d 100644
--- a/solr/core/src/test/org/apache/solr/core/TestConfig.java
+++ b/solr/core/src/test/org/apache/solr/core/TestConfig.java
@@ -17,13 +17,13 @@
 package org.apache.solr.core;
 
 import java.io.InputStream;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import org.apache.lucene.index.ConcurrentMergeScheduler;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.TieredMergePolicy;
 import org.apache.lucene.util.InfoStream;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.IndexSchemaFactory;
 import org.apache.solr.update.SolrIndexConfig;
@@ -160,10 +160,10 @@ public class TestConfig extends SolrTestCaseJ4 {
 
     assertNull("non-null mergedSegmentWarmer", iwc.getMergedSegmentWarmer());
 
-    final int numDefaultsMapped = sic.toMap(new LinkedHashMap<>()).size();
+    final int numDefaultsMapped = new SimpleOrderedMap<>(sic).size();
     assertEquals(
         "numDefaultsTested vs. numDefaultsMapped+numNullDefaults ="
-            + sic.toMap(new LinkedHashMap<>()).keySet(),
+            + new SimpleOrderedMap<>(sic).keySet(),
         numDefaultsTested,
         numDefaultsMapped + numNullDefaults);
   }
diff --git a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java 
b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
index 78d45b2c49e..2b94e57434f 100644
--- a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
@@ -17,7 +17,6 @@
 package org.apache.solr.update;
 
 import java.nio.file.Path;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import org.apache.lucene.index.ConcurrentMergeScheduler;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -29,8 +28,9 @@ import 
org.apache.lucene.sandbox.index.MergeOnFlushMergePolicy;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.common.MapSerializable;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.TestMergePolicyConfig;
@@ -253,7 +253,7 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
     }
     assertNotNull(solrIndexConfig.mergeSchedulerInfo);
 
-    Map<String, Object> m = solrIndexConfig.toMap(new LinkedHashMap<>());
+    Map<String, Object> m = new SimpleOrderedMap<>(solrIndexConfig);
     int mSizeExpected = 0;
 
     ++mSizeExpected;
@@ -292,12 +292,12 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
     }
 
     ++mSizeExpected;
-    assertTrue(m.get("mergeScheduler") instanceof MapSerializable);
+    assertTrue(m.get("mergeScheduler") instanceof MapWriter);
     ++mSizeExpected;
-    assertTrue(m.get("mergePolicyFactory") instanceof MapSerializable);
+    assertTrue(m.get("mergePolicyFactory") instanceof MapWriter);
     if 
(solrConfigFileName.equals(solrConfigFileNameWarmerRandomMergePolicyFactory)) {
       ++mSizeExpected;
-      assertTrue(m.get("mergedSegmentWarmer") instanceof MapSerializable);
+      assertTrue(m.get("mergedSegmentWarmer") instanceof MapWriter);
     } else {
       assertNull(m.get("mergedSegmentWarmer"));
     }


Reply via email to