From 827c670d189f9da56259b541db9b94113d3ca9a0 Mon Sep 17 00:00:00 2001 From: Noble Paul Date: Fri, 22 Apr 2016 11:32:29 +0530 Subject: [PATCH] SOLR-8992: Restore Schema API GET method functionality removed in 6.0 added back another test and fixed test errors --- .../apache/solr/handler/SchemaHandler.java | 44 ++++---- .../org/apache/solr/schema/IndexSchema.java | 105 +++++++++++------- .../solr/rest/schema/TestFieldResource.java | 6 + .../solrj/response/schema/SchemaResponse.java | 64 +++++------ .../apache/solr/common/util/NamedList.java | 69 ++++++++++++ 5 files changed, 194 insertions(+), 94 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java index 4da557d85ef..063c3d4d83c 100644 --- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java @@ -20,20 +20,19 @@ import java.io.IOException; import java.lang.invoke.MethodHandles; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import org.apache.solr.cloud.ZkSolrResourceLoader; import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.MapSolrParams; +import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.ContentStream; import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.StrUtils; +import org.apache.solr.common.util.Utils; import org.apache.solr.core.SolrCore; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; @@ -48,7 +47,12 @@ import org.apache.solr.util.plugin.SolrCoreAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static java.util.Collections.singletonMap; import static org.apache.solr.common.params.CommonParams.JSON; +import static org.apache.solr.schema.IndexSchema.SchemaProps.Handler.COPY_FIELDS; +import static org.apache.solr.schema.IndexSchema.SchemaProps.Handler.DYNAMIC_FIELDS; +import static org.apache.solr.schema.IndexSchema.SchemaProps.Handler.FIELDS; +import static org.apache.solr.schema.IndexSchema.SchemaProps.Handler.FIELD_TYPES; public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware, PermissionNameProvider { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -57,18 +61,14 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware, private static final Map level2; static { - Set s = ImmutableSet.of( - IndexSchema.FIELD_TYPES, - IndexSchema.FIELDS, - IndexSchema.DYNAMIC_FIELDS, - IndexSchema.COPY_FIELDS + Map s = Utils.makeMap( + FIELD_TYPES.nameLower, null, + FIELDS.nameLower, "fl", + DYNAMIC_FIELDS.nameLower, "fl", + COPY_FIELDS.nameLower, null ); - Map m = new HashMap<>(); - for (String s1 : s) { - m.put(s1, s1); - m.put(s1.toLowerCase(Locale.ROOT), s1); - } - level2 = ImmutableMap.copyOf(m); + + level2 = Collections.unmodifiableMap(s); } @@ -184,9 +184,15 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware, List parts = StrUtils.splitSmart(path, '/'); if (parts.get(0).isEmpty()) parts.remove(0); if (parts.size() > 1 && level2.containsKey(parts.get(1))) { - String realName = level2.get(parts.get(1)); + String realName = parts.get(1); + String fieldName = IndexSchema.SchemaProps.nameMapping.get(realName); + + String pathParam = level2.get(realName); + if (parts.size() > 2) { + req.setParams(SolrParams.wrapDefaults(new MapSolrParams(singletonMap(pathParam, parts.get(2))), req.getParams())); + } Map propertyValues = req.getSchema().getNamedPropertyValues(realName, req.getParams()); - Object o = propertyValues.get(realName); + Object o = propertyValues.get(fieldName); if(parts.size()> 2) { String name = parts.get(2); if (o instanceof List) { @@ -195,7 +201,7 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware, if (obj instanceof SimpleOrderedMap) { SimpleOrderedMap simpleOrderedMap = (SimpleOrderedMap) obj; if(name.equals(simpleOrderedMap.get("name"))) { - rsp.add(realName.substring(0, realName.length() - 1), simpleOrderedMap); + rsp.add(fieldName.substring(0, realName.length() - 1), simpleOrderedMap); return; } } @@ -203,7 +209,7 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware, } throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No such path " + path); } else { - rsp.add(realName, o); + rsp.add(fieldName, o); } return; } 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 f71db0aafd2..9e653321c8a 100644 --- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java +++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java @@ -16,19 +16,32 @@ */ package org.apache.solr.schema; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; import java.io.IOException; import java.io.Writer; import java.lang.invoke.MethodHandles; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +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; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import com.google.common.base.Functions; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.DelegatingAnalyzerWrapper; import org.apache.lucene.index.DocValuesType; @@ -40,8 +53,8 @@ import org.apache.lucene.index.MultiFields; import org.apache.lucene.search.similarities.Similarity; import org.apache.lucene.uninverting.UninvertingReader; import org.apache.lucene.util.Version; -import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.SolrException; +import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.MapSolrParams; import org.apache.solr.common.params.ModifiableSolrParams; @@ -1363,10 +1376,10 @@ public class IndexSchema { return getNamedPropertyValues(null, new MapSolrParams(Collections.EMPTY_MAP)); } - static class SchemaProps implements MapSerializable { + public static class SchemaProps implements MapSerializable { private static final String SOURCE_FIELD_LIST = IndexSchema.SOURCE + "." + CommonParams.FL; private static final String DESTINATION_FIELD_LIST = IndexSchema.DESTINATION + "." + CommonParams.FL; - private final String name; + public final String name; private final SolrParams params; private final IndexSchema schema; boolean showDefaults, includeDynamic; @@ -1375,7 +1388,7 @@ public class IndexSchema { private Set requestedDestinationFields; - enum Handler { + public enum Handler { NAME(IndexSchema.NAME, sp -> sp.schema.getSchemaName()), VERSION(IndexSchema.VERSION, sp -> sp.schema.getVersion()), UNIQUE_KEY(IndexSchema.UNIQUE_KEY, sp -> sp.schema.uniqueKeyFieldName), @@ -1391,11 +1404,6 @@ public class IndexSchema { .map(it -> it.getNamedPropertyValues(sp.showDefaults)) .collect(Collectors.toList())), - DYNAMIC_FIELDS(IndexSchema.DYNAMIC_FIELDS, sp -> Stream.of(sp.schema.dynamicFields) - .filter(it -> !it.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX)) - .filter(it -> sp.requestedFields == null || sp.requestedFields.contains(it.getPrototype().getName())) - .map(it -> sp.getProperties(it.getPrototype())) - .collect(Collectors.toList())), FIELDS(IndexSchema.FIELDS, sp -> { List result = (sp.requestedFields != null ? sp.requestedFields : new TreeSet<>(sp.schema.fields.keySet())) .stream() @@ -1405,57 +1413,65 @@ public class IndexSchema { .map(sp::getProperties) .collect(Collectors.toList()); if (sp.includeDynamic && sp.requestedFields == null) { - result.addAll((Collection) Handler.DYNAMIC_FIELDS.fun.apply(sp)); + result.addAll(sp.applyDynamic()); } return result; }), + DYNAMIC_FIELDS(IndexSchema.DYNAMIC_FIELDS, sp -> Stream.of(sp.schema.dynamicFields) + .filter(it -> !it.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX)) + .filter(it -> sp.requestedFields == null || sp.requestedFields.contains(it.getPrototype().getName())) + .map(it -> sp.getProperties(it.getPrototype())) + .collect(Collectors.toList())), COPY_FIELDS(IndexSchema.COPY_FIELDS, sp -> sp.schema.getCopyFieldProperties(false, sp.requestedSourceFields, sp.requestedDestinationFields)); final Function fun; - final String name; + public final String realName, nameLower; Handler(String name, Function fun) { this.fun = fun; - this.name = name; + this.realName = name; + nameLower = name.toLowerCase(Locale.ROOT); + + } + public String getRealName(){ + return realName; + } + public String getNameLower(){ + return nameLower; + } } + SchemaProps(String name, SolrParams params, IndexSchema schema) { this.name = name; this.params = params; this.schema = schema; showDefaults = params.getBool("showDefaults", false); includeDynamic = params.getBool("includeDynamic", false); + requestedSourceFields = readMultiVals(SOURCE_FIELD_LIST); + requestedDestinationFields = readMultiVals(DESTINATION_FIELD_LIST); + requestedFields = readMultiVals(CommonParams.FL); - String sourceFieldListParam = params.get(SOURCE_FIELD_LIST); - if (null != sourceFieldListParam) { - String[] fields = sourceFieldListParam.trim().split("[,\\s]+"); - if (fields.length > 0) { - requestedSourceFields = new HashSet<>(Arrays.asList(fields)); - requestedSourceFields.remove(""); // Remove empty values, if any - } - } - String destinationFieldListParam = params.get(DESTINATION_FIELD_LIST); - if (null != destinationFieldListParam) { - String[] fields = destinationFieldListParam.trim().split("[,\\s]+"); - if (fields.length > 0) { - requestedDestinationFields = new HashSet<>(Arrays.asList(fields)); - requestedDestinationFields.remove(""); // Remove empty values, if any - } - } + } + public Collection applyDynamic(){ + return (Collection) Handler.DYNAMIC_FIELDS.fun.apply(this); + } - String flParam = params.get(CommonParams.FL); + private Set readMultiVals(String name) { + String flParam = params.get(name); if (null != flParam) { String[] fields = flParam.trim().split("[,\\s]+"); if (fields.length > 0) - requestedFields = new LinkedHashSet<>(Stream.of(fields) + return new LinkedHashSet<>(Stream.of(fields) .filter(it -> !it.trim().isEmpty()) .collect(Collectors.toList())); } + return null; } @@ -1474,15 +1490,18 @@ public class IndexSchema { @Override public Map toMap() { - Map topLevel = new LinkedHashMap<>(); - Stream.of(Handler.values()) - .filter(it -> name == null || it.name.equals(name)) - .forEach(it -> { - Object val = it.fun.apply(this); - if (val != null) topLevel.put(it.name, val); - }); - return topLevel; + 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.getValue() != null) + .collect(Collectors.toMap( + Pair::getKey, + Pair::getValue, + (v1, v2) -> v2, + LinkedHashMap::new)); } + public static Map nameMapping = Collections.unmodifiableMap(Stream.of(Handler.values()) + .collect(Collectors.toMap(Handler::getNameLower , Handler::getRealName))); } public Map getNamedPropertyValues(String name, SolrParams params) { diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java index 627aee09e78..d591b9ad026 100644 --- a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java +++ b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java @@ -71,6 +71,12 @@ public class TestFieldResource extends SolrRestletTestBase { "/field/required==false", "/field/tokenized==true"); } + @Test + public void testGetFieldIncludeDynamic() throws Exception { + assertQ("/schema/fields/some_crazy_name_i?indent=on&wt=xml&includeDynamic=true", + "/response/lst[@name='field']/str[@name='name'] = 'some_crazy_name_i'", + "/response/lst[@name='field']/str[@name='dynamicBase'] = '*_i'"); + } @Test diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/schema/SchemaResponse.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/schema/SchemaResponse.java index 0f3b2896430..088cd603a4a 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/response/schema/SchemaResponse.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/schema/SchemaResponse.java @@ -132,38 +132,38 @@ public class SchemaResponse extends SolrResponseBase { } } - private static SchemaRepresentation createSchemaConfiguration(NamedList schemaNamedList) { + private static SchemaRepresentation createSchemaConfiguration(Map schemaObj) { SchemaRepresentation schemaRepresentation = new SchemaRepresentation(); - schemaRepresentation.setName(getSchemaName(schemaNamedList)); - schemaRepresentation.setVersion(getSchemaVersion(schemaNamedList)); - schemaRepresentation.setUniqueKey(getSchemaUniqueKey(schemaNamedList)); - schemaRepresentation.setDefaultSearchField(getDefaultSearchField(schemaNamedList)); - schemaRepresentation.setDefaultOperator(getDefaultOperator(schemaNamedList)); - schemaRepresentation.setSimilarity(getSimilarity(schemaNamedList)); - schemaRepresentation.setFields(getFields(schemaNamedList)); - schemaRepresentation.setDynamicFields(getDynamicFields(schemaNamedList)); - schemaRepresentation.setFieldTypes(getFieldTypeDefinitions(schemaNamedList)); - schemaRepresentation.setCopyFields(getCopyFields(schemaNamedList)); + schemaRepresentation.setName(getSchemaName(schemaObj)); + schemaRepresentation.setVersion(getSchemaVersion(schemaObj)); + schemaRepresentation.setUniqueKey(getSchemaUniqueKey(schemaObj)); + schemaRepresentation.setDefaultSearchField(getDefaultSearchField(schemaObj)); + schemaRepresentation.setDefaultOperator(getDefaultOperator(schemaObj)); + schemaRepresentation.setSimilarity(getSimilarity(schemaObj)); + schemaRepresentation.setFields(getFields(schemaObj)); + schemaRepresentation.setDynamicFields(getDynamicFields(schemaObj)); + schemaRepresentation.setFieldTypes(getFieldTypeDefinitions(schemaObj)); + schemaRepresentation.setCopyFields(getCopyFields(schemaObj)); return schemaRepresentation; } - private static String getSchemaName(NamedList schemaNamedList) { + private static String getSchemaName(Map schemaNamedList) { return (String) schemaNamedList.get("name"); } - private static Float getSchemaVersion(NamedList schemaNamedList) { + private static Float getSchemaVersion(Map schemaNamedList) { return (Float) schemaNamedList.get("version"); } - private static String getSchemaUniqueKey(NamedList schemaNamedList) { + private static String getSchemaUniqueKey(Map schemaNamedList) { return (String) schemaNamedList.get("uniqueKey"); } - private static String getDefaultSearchField(NamedList schemaNamedList) { + private static String getDefaultSearchField(Map schemaNamedList) { return (String) schemaNamedList.get("defaultSearchField"); } - private static Map getSimilarity(NamedList schemaNamedList) { + private static Map getSimilarity(Map schemaNamedList) { NamedList similarityNamedList = (NamedList) schemaNamedList.get("similarity"); Map similarity = null; if (similarityNamedList != null) similarity = extractAttributeMap(similarityNamedList); @@ -171,7 +171,7 @@ public class SchemaResponse extends SolrResponseBase { } @SuppressWarnings("unchecked") - private static String getDefaultOperator(NamedList schemaNamedList) { + private static String getDefaultOperator(Map schemaNamedList) { String defaultOperator = null; NamedList solrQueryParserProperties = (NamedList) schemaNamedList.get("solrQueryParser"); if (solrQueryParserProperties != null) defaultOperator = (String) solrQueryParserProperties.get("defaultOperator"); @@ -179,7 +179,7 @@ public class SchemaResponse extends SolrResponseBase { } @SuppressWarnings("unchecked") - private static List> getFields(NamedList schemaNamedList) { + private static List> getFields(Map schemaNamedList) { List> fieldsAttributes = new LinkedList<>(); List> fieldsResponse = (List>) schemaNamedList.get("fields"); for (NamedList fieldNamedList : fieldsResponse) { @@ -192,7 +192,7 @@ public class SchemaResponse extends SolrResponseBase { } @SuppressWarnings("unchecked") - private static List> getDynamicFields(NamedList schemaNamedList) { + private static List> getDynamicFields(Map schemaNamedList) { List> dynamicFieldsAttributes = new LinkedList<>(); List> dynamicFieldsResponse = (List>) schemaNamedList.get("dynamicFields"); for (NamedList fieldNamedList : dynamicFieldsResponse) { @@ -205,7 +205,7 @@ public class SchemaResponse extends SolrResponseBase { } @SuppressWarnings("unchecked") - private static List> getCopyFields(NamedList schemaNamedList) { + private static List> getCopyFields(Map schemaNamedList) { List> copyFieldsAttributes = new LinkedList<>(); List> copyFieldsResponse = (List>) schemaNamedList.get("copyFields"); for (NamedList copyFieldNamedList : copyFieldsResponse) { @@ -218,7 +218,7 @@ public class SchemaResponse extends SolrResponseBase { } @SuppressWarnings("unchecked") - private static List getFieldTypeDefinitions(NamedList schemaNamedList) { + private static List getFieldTypeDefinitions(Map schemaNamedList) { List fieldTypeDefinitions = new LinkedList<>(); List> fieldsResponse = (List>) schemaNamedList.get("fieldTypes"); for (NamedList fieldNamedList : fieldsResponse) { @@ -230,7 +230,7 @@ public class SchemaResponse extends SolrResponseBase { } @SuppressWarnings("unchecked") - private static List getFieldTypeRepresentations(NamedList schemaNamedList) { + private static List getFieldTypeRepresentations(Map schemaNamedList) { List fieldTypeRepresentations = new LinkedList<>(); List> fieldsResponse = (List>) schemaNamedList.get("fieldTypes"); for (NamedList fieldNamedList : fieldsResponse) { @@ -249,8 +249,8 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - NamedList schemaNamedList = (NamedList) response.get("schema"); - schemaRepresentation = createSchemaConfiguration(schemaNamedList); + Map schemaObj = (Map) response.get("schema"); + schemaRepresentation = createSchemaConfiguration(schemaObj); } public SchemaRepresentation getSchemaRepresentation() { @@ -268,7 +268,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - schemaName = SchemaResponse.getSchemaName(response); + schemaName = SchemaResponse.getSchemaName(response.asShallowMap()); } public String getSchemaName() { @@ -288,7 +288,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - schemaVersion = SchemaResponse.getSchemaVersion(response); + schemaVersion = SchemaResponse.getSchemaVersion(response.asShallowMap()); } public float getSchemaVersion() { @@ -329,7 +329,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - fields = SchemaResponse.getFields(response); + fields = SchemaResponse.getFields(response.asShallowMap()); } public List> getFields() { @@ -369,7 +369,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - dynamicFields = SchemaResponse.getDynamicFields(response); + dynamicFields = SchemaResponse.getDynamicFields(response.asMap(3)); } public List> getDynamicFields() { @@ -388,7 +388,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - uniqueKey = SchemaResponse.getSchemaUniqueKey(response); + uniqueKey = SchemaResponse.getSchemaUniqueKey(response.asShallowMap()); } public String getUniqueKey() { @@ -407,7 +407,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - similarity = SchemaResponse.getSimilarity(response); + similarity = SchemaResponse.getSimilarity(response.asShallowMap()); } public Map getSimilarity() { @@ -446,7 +446,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - copyFields = SchemaResponse.getCopyFields(response); + copyFields = SchemaResponse.getCopyFields(response.asShallowMap()); } public List> getCopyFields() { @@ -486,7 +486,7 @@ public class SchemaResponse extends SolrResponseBase { public void setResponse(NamedList response) { super.setResponse(response); - fieldTypes = SchemaResponse.getFieldTypeRepresentations(response); + fieldTypes = SchemaResponse.getFieldTypeRepresentations(response.asShallowMap()); } public List getFieldTypes() { diff --git a/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java b/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java index 3ca750d4c3f..dd5afe72087 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.solr.common.SolrException; @@ -396,6 +397,74 @@ public class NamedList implements Cloneable, Serializable, Iterable( Collections.unmodifiableList(copy.nvPairs)); } + public Map asShallowMap() { + return new Map() { + @Override + public int size() { + return NamedList.this.size(); + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + public boolean containsKey(Object key) { + return NamedList.this.get((String) key) != null ; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public T get(Object key) { + return NamedList.this.get((String) key); + } + + @Override + public T put(String key, T value) { + NamedList.this.add(key, value); + return null; + } + + @Override + public T remove(Object key) { + return NamedList.this.remove((String) key); + } + + @Override + public void putAll(Map m) { + NamedList.this.addAll(m); + + } + + @Override + public void clear() { + NamedList.this.clear(); + } + + @Override + public Set keySet() { + //TODO implement more efficiently + return NamedList.this.asMap(1).keySet(); + } + + @Override + public Collection values() { + //TODO implement more efficiently + return NamedList.this.asMap(1).values(); + } + + @Override + public Set> entrySet() { + //TODO implement more efficiently + return NamedList.this.asMap(1).entrySet(); + } + }; + } + public Map asMap(int maxDepth) { LinkedHashMap result = new LinkedHashMap(); for(int i=0;i