dsmiley commented on code in PR #3027:
URL: https://github.com/apache/solr/pull/3027#discussion_r1912371099


##########
solr/core/src/java/org/apache/solr/core/PluginInfo.java:
##########
@@ -100,39 +100,23 @@ public String toString() {
     }
   }
 
+  /** From XML. */
   public PluginInfo(ConfigNode node, String err, boolean requireName, boolean 
requireClass) {
     type = node.name();
-    name =
-        node.requiredStrAttr(
-            NAME,
-            requireName
-                ? () -> new RuntimeException(err + ": missing mandatory 
attribute 'name'")
-                : null);
+    name = requireName ? node.attrRequired(NAME, err) : node.attr(NAME);
     cName =
-        parseClassName(
-            node.requiredStrAttr(
-                CLASS_NAME,
-                requireClass
-                    ? () -> new RuntimeException(err + ": missing mandatory 
attribute 'class'")
-                    : null));
+        parseClassName(requireClass ? node.attrRequired(CLASS_NAME, err) : 
node.attr(CLASS_NAME));
     className = cName.className;
     pkgName = cName.pkg;
-    initArgs = DOMUtil.childNodesToNamedList(node);
+    initArgs = node.childNodesToNamedList();
     attributes = node.attributes();
     children = loadSubPlugins(node);
     isFromSolrConfig = true;
   }
 
-  public PluginInfo(Node node, String err, boolean requireName, boolean 
requireClass) {
-    type = node.getNodeName();
-    name = DOMUtil.getAttr(node, NAME, requireName ? err : null);
-    cName = parseClassName(DOMUtil.getAttr(node, CLASS_NAME, requireClass ? 
err : null));
-    className = cName.className;
-    pkgName = cName.pkg;
-    initArgs = DOMUtil.childNodesToNamedList(node);
-    attributes = unmodifiableMap(DOMUtil.toMap(node.getAttributes()));
-    children = loadSubPlugins(node);
-    isFromSolrConfig = true;
+  @VisibleForTesting
+  PluginInfo(Node node, String err, boolean requireName, boolean requireClass) 
{

Review Comment:
   Don't truly need this but it's a convenience constructor for one test.
   It's crazy PluginInfo had duplicated code for Node vs ConfigNode -- no need.



##########
solr/solrj/src/java/org/apache/solr/common/ConfigNode.java:
##########
@@ -39,39 +39,53 @@
 public interface ConfigNode {
   ThreadLocal<Function<String, String>> SUBSTITUTES = new ThreadLocal<>();
 
-  /** Name of the tag */
+  /** Name of the tag/element. */
   String name();
 
-  /** Attributes */
+  /** Attributes of this node. Immutable shared instance. Not null. */
   Map<String, String> attributes();
 
+  /** Mutable copy of {@link #attributes()}, excluding {@code exclusions} 
keys. */
+  default Map<String, String> attributesExcept(String... exclusions) {
+    assert exclusions.length < 5 : "non-performant exclusion list";
+    final var attributes = attributes();
+    Map<String, String> args = CollectionUtil.newHashMap(attributes.size());
+    attributes.forEach(
+        (k, v) -> {
+          for (String ex : exclusions) if (ex.equals(k)) return;
+          args.put(k, v);
+        });
+    return args;
+  }
+
   /** Child by name */
   default ConfigNode child(String name) {
-    return child(null, name);
+    return child(name, null);
   }
 
   /**
    * Child by name or return an empty node if null. If there are multiple 
values, it returns the
    * first element. This never returns a null.
    */
   default ConfigNode get(String name) {
-    ConfigNode child = child(null, name);
+    ConfigNode child = child(name, null);
     return child == null ? EMPTY : child;
   }
 
   default ConfigNode get(String name, Predicate<ConfigNode> test) {
-    List<ConfigNode> children = getAll(test, name);
+    List<ConfigNode> children = getAll(Set.of(name), test);
     if (children.isEmpty()) return EMPTY;
     return children.get(0);
   }
 
+  // @VisibleForTesting  Helps writing tests
   default ConfigNode get(String name, int idx) {
-    List<ConfigNode> children = getAll(null, name);
+    List<ConfigNode> children = getAll(name);
     if (idx < children.size()) return children.get(idx);
     return EMPTY;
   }
 
-  default ConfigNode child(String name, Supplier<RuntimeException> err) {
+  default ConfigNode childRequired(String name, Supplier<RuntimeException> 
err) {

Review Comment:
   I want "required" in the name to better differentiate the overloads



##########
solr/core/src/java/org/apache/solr/util/DOMConfigNode.java:
##########
@@ -30,7 +30,11 @@
 public class DOMConfigNode implements ConfigNode {
 
   private final Node node;
-  Map<String, String> attrs;
+  private Map<String, String> attrs; // lazy populated
+
+  public DOMConfigNode(Node node) {

Review Comment:
   constructor was misplaced



##########
solr/core/src/java/org/apache/solr/util/DataConfigNode.java:
##########
@@ -94,9 +94,13 @@ public List<ConfigNode> getAll(String name) {
   }
 
   @Override
-  public List<ConfigNode> getAll(Predicate<ConfigNode> test, Set<String> 
matchNames) {
+  public List<ConfigNode> getAll(Set<String> names, Predicate<ConfigNode> 
test) {

Review Comment:
   name/names should go first in these methods.  More logical / good taste.



##########
solr/solrj/src/java/org/apache/solr/common/ConfigNode.java:
##########
@@ -135,34 +156,24 @@ default ConfigNode child(Predicate<ConfigNode> test, 
String name) {
   /**
    * Iterate through child nodes with the names and return all the matching 
children
    *
-   * @param nodeNames names of tags to be returned
-   * @param test check for the nodes to be returned
+   * @param names names of tags/elements to be returned. Null means all nodes.
+   * @param test check for the nodes to be returned. Null means all nodes.
    */
-  default List<ConfigNode> getAll(Predicate<ConfigNode> test, String... 
nodeNames) {
-    return getAll(
-        test, nodeNames == null ? Collections.emptySet() : new 
HashSet<>(Arrays.asList(nodeNames)));
-  }
-
-  /**
-   * Iterate through child nodes with the names and return all the matching 
children
-   *
-   * @param matchNames names of tags to be returned
-   * @param test check for the nodes to be returned
-   */
-  default List<ConfigNode> getAll(Predicate<ConfigNode> test, Set<String> 
matchNames) {
+  default List<ConfigNode> getAll(Set<String> names, Predicate<ConfigNode> 
test) {
+    assert names == null || !names.isEmpty() : "Intended to pass null?";
     List<ConfigNode> result = new ArrayList<>();
     forEachChild(
         it -> {
-          if (matchNames != null && !matchNames.isEmpty() && 
!matchNames.contains(it.name()))

Review Comment:
   no longer using empty as a reasonable param



##########
solr/solrj/src/java/org/apache/solr/common/util/DOMUtil.java:
##########


Review Comment:
   I don't think it makes sense for DOMUtil to refer to ConfigNode; the latter 
is a higher level concept.  The methods in here referring to it were itching to 
be instance methods on ConfigNode, which is much more natural for callers.  I 
don't see why ConfigNode & implementations are doing in SolrJ; there are too 
many things in SolrJ that don't belong there.
   
   This is mostly what precipitated the substance of this PR.
   
   I didn't rename methods in DOMUtil based on the naming choices in ConfigNode 
(e.g. toMap -> attributes, ...) but maybe should be for consistency?  I'm more 
inclined to let it be.  DOMUtil doesn't have many callers anymore.  The code 
there is ancient.



##########
solr/solrj/src/java/org/apache/solr/common/ConfigNode.java:
##########
@@ -39,39 +39,53 @@
 public interface ConfigNode {
   ThreadLocal<Function<String, String>> SUBSTITUTES = new ThreadLocal<>();
 
-  /** Name of the tag */
+  /** Name of the tag/element. */
   String name();
 
-  /** Attributes */
+  /** Attributes of this node. Immutable shared instance. Not null. */
   Map<String, String> attributes();
 
+  /** Mutable copy of {@link #attributes()}, excluding {@code exclusions} 
keys. */
+  default Map<String, String> attributesExcept(String... exclusions) {

Review Comment:
   formerly was DOMUtil.toMapExcept.  This is a better name and needed 
documentation.  I also added a check for a reasonable number of exclusions, and 
also pre-initialize the result map size.



##########
solr/core/src/java/org/apache/solr/util/DataConfigNode.java:
##########
@@ -94,9 +94,13 @@ public List<ConfigNode> getAll(String name) {
   }
 
   @Override
-  public List<ConfigNode> getAll(Predicate<ConfigNode> test, Set<String> 
matchNames) {
+  public List<ConfigNode> getAll(Set<String> names, Predicate<ConfigNode> 
test) {
+    if (names == null) {
+      return ConfigNode.super.getAll(names, test);
+    }

Review Comment:
   this actually fixes a bug since this overriding code doesn't handle null 
names, and an empty names was weird so I made that basically disallowed.



##########
solr/solrj/src/java/org/apache/solr/common/ConfigNode.java:
##########
@@ -135,34 +156,24 @@ default ConfigNode child(Predicate<ConfigNode> test, 
String name) {
   /**
    * Iterate through child nodes with the names and return all the matching 
children
    *
-   * @param nodeNames names of tags to be returned
-   * @param test check for the nodes to be returned
+   * @param names names of tags/elements to be returned. Null means all nodes.
+   * @param test check for the nodes to be returned. Null means all nodes.
    */
-  default List<ConfigNode> getAll(Predicate<ConfigNode> test, String... 
nodeNames) {

Review Comment:
   Didn't need this one



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org
For additional commands, e-mail: issues-h...@solr.apache.org

Reply via email to