diff --git a/solr/core/src/test/org/apache/solr/util/TestUtils.java b/solr/core/src/test/org/apache/solr/util/TestUtils.java index 78659d7b7ca..0423fbf57ba 100644 --- a/solr/core/src/test/org/apache/solr/util/TestUtils.java +++ b/solr/core/src/test/org/apache/solr/util/TestUtils.java @@ -201,6 +201,29 @@ public class TestUtils extends SolrTestCaseJ4 { assertEquals( "v1" ,Utils.getObjectByPath(m, true, "/a/d[0]/k1")); assertEquals( "v2" ,Utils.getObjectByPath(m, true, "/a/d[1]/k2")); } + public void testSetObjectByPath(){ + String json = "{\n" + + " 'authorization':{\n" + + " 'class':'solr.RuleBasedAuthorizationPlugin',\n" + + " 'user-role':{\n" + + " 'solr':'admin',\n" + + " 'harry':'admin'},\n" + + " 'permissions':[{\n" + + " 'name':'security-edit',\n" + + " 'role':['admin']},\n" + + " {\n" + + " 'name':'x-update',\n" + + " 'collection':'x',\n" + + " 'path':'/update/*',\n" + + " 'role':'dev'}],\n" + + " '':{'v':4}}}"; + Map m = (Map) fromJSONString(json); + Utils.setObjectByPath(m,"authorization/permissions[1]/role","guest"); + Utils.setObjectByPath(m,"authorization/permissions[0]/role[-1]","dev"); + assertEquals("guest", Utils.getObjectByPath(m,true,"authorization/permissions[1]/role")); + assertEquals("dev", Utils.getObjectByPath(m,true,"authorization/permissions[0]/role[1]")); + + } public void testUtilsJSPath(){ diff --git a/solr/solrj/src/java/org/apache/solr/common/util/Utils.java b/solr/solrj/src/java/org/apache/solr/common/util/Utils.java index fbfc4a120e7..3be565c90ad 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/Utils.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/Utils.java @@ -213,13 +213,72 @@ public class Utils { } public static Object getObjectByPath(Object root, boolean onlyPrimitive, String hierarchy) { - if(root == null) return null; - if(!isMapLike(root)) throw new RuntimeException("must be a Map or NamedList"); List parts = StrUtils.splitSmart(hierarchy, '/'); if (parts.get(0).isEmpty()) parts.remove(0); return getObjectByPath(root, onlyPrimitive, parts); } + public static boolean setObjectByPath(Object root, String hierarchy, Object value) { + List parts = StrUtils.splitSmart(hierarchy, '/'); + if (parts.get(0).isEmpty()) parts.remove(0); + return setObjectByPath(root, parts, value); + } + + public static boolean setObjectByPath(Object root, List hierarchy, Object value) { + if (root == null) return false; + if (!isMapLike(root)) throw new RuntimeException("must be a Map or NamedList"); + Object obj = root; + for (int i = 0; i < hierarchy.size(); i++) { + int idx = -2; //-1 means append to list, -2 means not found + String s = hierarchy.get(i); + if (s.endsWith("]")) { + Matcher matcher = ARRAY_ELEMENT_INDEX.matcher(s); + if (matcher.find()) { + s = matcher.group(1); + idx = Integer.parseInt(matcher.group(2)); + } + } + if (i < hierarchy.size() - 1) { + Object o = getVal(obj, s); + if (o == null) return false; + if (idx > -1) { + List l = (List) o; + o = idx < l.size() ? l.get(idx) : null; + } + if (!isMapLike(o)) return false; + obj = o; + } else { + if (idx == -2) { + if (obj instanceof NamedList) { + NamedList namedList = (NamedList) obj; + int location = namedList.indexOf(s, 0); + if (location == -1) namedList.add(s, value); + else namedList.setVal(location, value); + } else if (obj instanceof Map) { + ((Map) obj).put(s, value); + } + return true; + } else { + Object v = getVal(obj, s); + if (v instanceof List) { + List list = (List) v; + if (idx == -1) { + list.add(value); + } else { + if (idx < list.size()) list.set(idx, value); + else return false; + } + return true; + } else { + return false; + } + } + } + } + + return false; + + } public static Object getObjectByPath(Object root, boolean onlyPrimitive, List hierarchy) { @@ -326,7 +385,7 @@ public class Utils { } public static final Pattern ARRAY_ELEMENT_INDEX = Pattern - .compile("(\\S*?)\\[(\\d+)\\]"); + .compile("(\\S*?)\\[([-]?\\d+)\\]"); public static SpecProvider getSpec(final String name) { return () -> {