lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From no...@apache.org
Subject lucene-solr:branch_6_0: SOLR-8992: Restore Schema API GET method functionality removed in 6.0
Date Tue, 03 May 2016 11:20:14 GMT
Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6_0 b3cd1ff61 -> f837216b3


SOLR-8992: Restore Schema API GET method functionality removed in 6.0


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f837216b
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f837216b
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f837216b

Branch: refs/heads/branch_6_0
Commit: f837216b3bd06c6e914206562b3c8c4cfdf8c1bd
Parents: b3cd1ff
Author: Noble Paul <noble@apache.org>
Authored: Tue May 3 16:50:00 2016 +0530
Committer: Noble Paul <noble@apache.org>
Committed: Tue May 3 16:50:00 2016 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   2 +
 .../org/apache/solr/handler/SchemaHandler.java  |  46 ++--
 .../apache/solr/response/SchemaXmlWriter.java   |  27 ++-
 .../org/apache/solr/schema/IndexSchema.java     | 209 ++++++++++++++-----
 .../schema/TestCopyFieldCollectionResource.java |  34 +++
 .../TestDynamicFieldCollectionResource.java     |  24 +++
 .../solr/rest/schema/TestFieldResource.java     |   8 +-
 .../solrj/response/schema/SchemaResponse.java   |  64 +++---
 .../org/apache/solr/common/util/NamedList.java  |  69 ++++++
 9 files changed, 368 insertions(+), 115 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 5281829..62eac56 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -26,6 +26,8 @@ Bug Fixes
 
 * SOLR-9016: Fix SolrIdentifierValidator to not allow empty identifiers. (Shai Erera)
 
+* SOLR-8992: Restore Schema API GET method functionality removed in 6.0 (noble, Steve Rowe)
+
 ==================  6.0.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
----------------------------------------------------------------------
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 4279864..5852a76 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;
@@ -46,7 +45,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 {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -55,18 +59,14 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware
{
   private static final Map<String, String> level2;
 
   static {
-    Set<String> 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<String, String> 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);
   }
 
 
@@ -170,9 +170,15 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware
{
           List<String> 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));
-            SimpleOrderedMap<Object> propertyValues = req.getSchema().getNamedPropertyValues(req.getParams());
-            Object o = propertyValues.get(realName);
+            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(fieldName);
             if(parts.size()> 2) {
               String name = parts.get(2);
               if (o instanceof List) {
@@ -181,7 +187,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;
                     }
                   }
@@ -189,7 +195,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;
           }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/core/src/java/org/apache/solr/response/SchemaXmlWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/SchemaXmlWriter.java b/solr/core/src/java/org/apache/solr/response/SchemaXmlWriter.java
index 4ed4d8f..a38fe36 100644
--- a/solr/core/src/java/org/apache/solr/response/SchemaXmlWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/SchemaXmlWriter.java
@@ -78,8 +78,8 @@ public class SchemaXmlWriter extends TextResponseWriter {
       writer.write(MANAGED_SCHEMA_DO_NOT_EDIT_WARNING);
     }
 
-    @SuppressWarnings("unchecked") SimpleOrderedMap<Object> schemaProperties
-        = (SimpleOrderedMap<Object>)rsp.getValues().get(IndexSchema.SCHEMA);
+    @SuppressWarnings("unchecked") Map<String,Object> schemaProperties
+        = (Map<String , Object>)rsp.getValues().get(IndexSchema.SCHEMA);
 
     openStartTag(IndexSchema.SCHEMA);
     writeAttr(IndexSchema.NAME, schemaProperties.get(IndexSchema.NAME).toString());
@@ -87,34 +87,33 @@ public class SchemaXmlWriter extends TextResponseWriter {
     closeStartTag(false);
     incLevel();
 
-    for (int schemaPropNum = 0 ; schemaPropNum < schemaProperties.size() ; ++schemaPropNum)
{
-      String schemaPropName = schemaProperties.getName(schemaPropNum);
+    for (Map.Entry<String, Object> entry : schemaProperties.entrySet()) {
+      String schemaPropName = entry.getKey();
+      Object val = entry.getValue();
       if (schemaPropName.equals(IndexSchema.NAME) || schemaPropName.equals(IndexSchema.VERSION))
{
         continue;
       }
       if (schemaPropName.equals(IndexSchema.UNIQUE_KEY)) {
         openStartTag(IndexSchema.UNIQUE_KEY);
         closeStartTag(false);
-        writer.write(schemaProperties.getVal(schemaPropNum).toString());
+        writer.write(val.toString());
         endTag(IndexSchema.UNIQUE_KEY, false);
       } else if (schemaPropName.equals(IndexSchema.DEFAULT_SEARCH_FIELD)) {
         openStartTag(IndexSchema.DEFAULT_SEARCH_FIELD);
         closeStartTag(false);
-        writer.write(schemaProperties.getVal(schemaPropNum).toString());
+        writer.write(val.toString());
         endTag(IndexSchema.DEFAULT_SEARCH_FIELD, false);
       } else if (schemaPropName.equals(IndexSchema.SOLR_QUERY_PARSER)) {
         openStartTag(IndexSchema.SOLR_QUERY_PARSER);
-        @SuppressWarnings("unchecked") SimpleOrderedMap<Object> solrQueryParserProperties
-            = (SimpleOrderedMap<Object>)schemaProperties.getVal(schemaPropNum);
-        writeAttr(IndexSchema.DEFAULT_OPERATOR, solrQueryParserProperties.get(IndexSchema.DEFAULT_OPERATOR).toString());
+        writeAttr(IndexSchema.DEFAULT_OPERATOR, ((Map<String ,Object>) val).get(IndexSchema.DEFAULT_OPERATOR).toString());
         closeStartTag(true);
       } else if (schemaPropName.equals(IndexSchema.SIMILARITY)) {
-        writeSimilarity((SimpleOrderedMap<Object>) schemaProperties.getVal(schemaPropNum));
+        writeSimilarity((SimpleOrderedMap<Object>) val);
       } else if (schemaPropName.equals(IndexSchema.FIELD_TYPES)) {
-        writeFieldTypes((List<SimpleOrderedMap<Object>>)schemaProperties.getVal(schemaPropNum));
+        writeFieldTypes((List<SimpleOrderedMap<Object>>) val);
       } else if (schemaPropName.equals(IndexSchema.FIELDS)) {
         @SuppressWarnings("unchecked") List<SimpleOrderedMap<Object>> fieldPropertiesList
-            = (List<SimpleOrderedMap<Object>>)schemaProperties.getVal(schemaPropNum);
+            = (List<SimpleOrderedMap<Object>>) val;
         for (SimpleOrderedMap<Object> fieldProperties : fieldPropertiesList) {
           openStartTag(IndexSchema.FIELD);
           for (int fieldPropNum = 0 ; fieldPropNum < fieldProperties.size() ; ++fieldPropNum)
{
@@ -124,7 +123,7 @@ public class SchemaXmlWriter extends TextResponseWriter {
         }
       } else if (schemaPropName.equals(IndexSchema.DYNAMIC_FIELDS)) {
         @SuppressWarnings("unchecked") List<SimpleOrderedMap<Object>> dynamicFieldPropertiesList

-            = (List<SimpleOrderedMap<Object>>)schemaProperties.getVal(schemaPropNum);
+            = (List<SimpleOrderedMap<Object>>) val;
         for (SimpleOrderedMap<Object> dynamicFieldProperties : dynamicFieldPropertiesList)
{
           openStartTag(IndexSchema.DYNAMIC_FIELD);
           for (int dynamicFieldPropNum = 0 ; dynamicFieldPropNum < dynamicFieldProperties.size()
; ++dynamicFieldPropNum) {
@@ -135,7 +134,7 @@ public class SchemaXmlWriter extends TextResponseWriter {
         }
       } else if (schemaPropName.equals(IndexSchema.COPY_FIELDS)) {
         @SuppressWarnings("unchecked") List<SimpleOrderedMap<Object>> copyFieldPropertiesList
-            = (List<SimpleOrderedMap<Object>>)schemaProperties.getVal(schemaPropNum);
+            = (List<SimpleOrderedMap<Object>>) val;
         for (SimpleOrderedMap<Object> copyFieldProperties : copyFieldPropertiesList)
{
           openStartTag(IndexSchema.COPY_FIELD);
           for (int copyFieldPropNum = 0 ; copyFieldPropNum < copyFieldProperties.size()
; ++ copyFieldPropNum) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
----------------------------------------------------------------------
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 4319c3e..9e65332 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -16,14 +16,31 @@
  */
 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 javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.DelegatingAnalyzerWrapper;
@@ -32,19 +49,21 @@ import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexableField;
-import org.apache.lucene.index.IndexableField;
 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;
 import org.apache.solr.common.params.SolrParams;
 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.Config;
+import org.apache.solr.core.MapSerializable;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrResourceLoader;
 import org.apache.solr.request.LocalSolrQueryRequest;
@@ -63,6 +82,7 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
+import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
 import static java.util.Collections.singletonMap;
 
@@ -780,7 +800,7 @@ public class IndexSchema {
    * @param fields The sequence of {@link org.apache.solr.schema.SchemaField}
    */
   public void registerDynamicFields(SchemaField... fields) {
-    List<DynamicField> dynFields = new ArrayList<>(Arrays.asList(dynamicFields));
+    List<DynamicField> dynFields = new ArrayList<>(asList(dynamicFields));
     for (SchemaField field : fields) {
       if (isDuplicateDynField(dynFields, field)) {
         log.debug("dynamic field already exists: dynamic field: [" + field.getName() + "]");
@@ -1352,51 +1372,144 @@ public class IndexSchema {
   /**
    * Get a map of property name -&gt; value for the whole schema.
    */
-  public SimpleOrderedMap<Object> getNamedPropertyValues() {
-    return getNamedPropertyValues(new MapSolrParams(Collections.EMPTY_MAP));
-
-  }
-  public SimpleOrderedMap<Object> getNamedPropertyValues(SolrParams params) {
-    SimpleOrderedMap<Object> topLevel = new SimpleOrderedMap<>();
-    topLevel.add(NAME, getSchemaName());
-    topLevel.add(VERSION, getVersion());
-    if (null != uniqueKeyFieldName) {
-      topLevel.add(UNIQUE_KEY, uniqueKeyFieldName);
-    }
-    if (null != defaultSearchFieldName) {
-      topLevel.add(DEFAULT_SEARCH_FIELD, defaultSearchFieldName);
-    }
-    if (isExplicitQueryParserDefaultOperator) {
-      SimpleOrderedMap<Object> solrQueryParserProperties = new SimpleOrderedMap<>();
-      solrQueryParserProperties.add(DEFAULT_OPERATOR, queryParserDefaultOperator);
-      topLevel.add(SOLR_QUERY_PARSER, solrQueryParserProperties);
-    }
-    if (isExplicitSimilarity) {
-      topLevel.add(SIMILARITY, similarityFactory.getNamedPropertyValues());
-    }
-    List<SimpleOrderedMap<Object>> fieldTypeProperties = new ArrayList<>();
-    SortedMap<String,FieldType> sortedFieldTypes = new TreeMap<>(fieldTypes);
-    for (FieldType fieldType : sortedFieldTypes.values()) {
-      fieldTypeProperties.add(fieldType.getNamedPropertyValues(params.getBool("showDefaults",
false)));
-    }
-    topLevel.add(FIELD_TYPES, fieldTypeProperties);  
-    List<SimpleOrderedMap<Object>> fieldProperties = new ArrayList<>();
-    SortedSet<String> fieldNames = new TreeSet<>(fields.keySet());
-    for (String fieldName : fieldNames) {
-      fieldProperties.add(fields.get(fieldName).getNamedPropertyValues(params.getBool("showDefaults",
false)));
-    }
-    topLevel.add(FIELDS, fieldProperties);
-    List<SimpleOrderedMap<Object>> dynamicFieldProperties = new ArrayList<>();
-    for (IndexSchema.DynamicField dynamicField : dynamicFields) {
-      if ( ! dynamicField.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX)) { // omit internal
polyfields
-        dynamicFieldProperties.add(dynamicField.getPrototype().getNamedPropertyValues(params.getBool("showDefaults",
false)));
+  public Map getNamedPropertyValues() {
+    return getNamedPropertyValues(null, new MapSolrParams(Collections.EMPTY_MAP));
+  }
+
+  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;
+    public final String name;
+    private final SolrParams params;
+    private final IndexSchema schema;
+    boolean showDefaults, includeDynamic;
+    Set<String> requestedFields;
+    private Set<String> requestedSourceFields;
+    private Set<String> requestedDestinationFields;
+
+
+    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),
+      DEFAULT_SEARCH_FIELD(IndexSchema.DEFAULT_SEARCH_FIELD, sp -> sp.schema.defaultSearchFieldName),
+      SOLR_QUERY_PARSER(IndexSchema.SOLR_QUERY_PARSER, sp -> sp.schema.isExplicitQueryParserDefaultOperator
?
+          singletonMap(DEFAULT_OPERATOR, sp.schema.queryParserDefaultOperator) :
+          null),
+      SIMILARITY(IndexSchema.SIMILARITY, sp -> sp.schema.isExplicitSimilarity ?
+          sp.schema.similarityFactory.getNamedPropertyValues() :
+          null),
+      FIELD_TYPES(IndexSchema.FIELD_TYPES, sp -> new TreeMap<>(sp.schema.fieldTypes)
+          .values().stream()
+          .map(it -> it.getNamedPropertyValues(sp.showDefaults))
+          .collect(Collectors.toList())),
+
+      FIELDS(IndexSchema.FIELDS, sp -> {
+        List<SimpleOrderedMap> result = (sp.requestedFields != null ? sp.requestedFields
: new TreeSet<>(sp.schema.fields.keySet()))
+            .stream()
+            .map(sp.schema::getFieldOrNull)
+            .filter(it -> it != null)
+            .filter(it -> sp.includeDynamic || !sp.schema.isDynamicField(it.name))
+            .map(sp::getProperties)
+            .collect(Collectors.toList());
+        if (sp.includeDynamic && sp.requestedFields == null) {
+          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<SchemaProps, Object> fun;
+      public final String realName, nameLower;
+      Handler(String name, Function<SchemaProps, Object> fun) {
+        this.fun = fun;
+        this.realName = name;
+        nameLower = name.toLowerCase(Locale.ROOT);
+
+      }
+      public String getRealName(){
+        return realName;
+      }
+      public String getNameLower(){
+        return nameLower;
+
       }
     }
-    topLevel.add(DYNAMIC_FIELDS, dynamicFieldProperties);
-    topLevel.add(COPY_FIELDS, getCopyFieldProperties(false, null, null));
-    return topLevel;
+
+
+    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);
+
+    }
+    public Collection applyDynamic(){
+      return (Collection) Handler.DYNAMIC_FIELDS.fun.apply(this);
+    }
+
+    private Set<String> readMultiVals(String name) {
+      String flParam = params.get(name);
+      if (null != flParam) {
+        String[] fields = flParam.trim().split("[,\\s]+");
+        if (fields.length > 0)
+          return new LinkedHashSet<>(Stream.of(fields)
+              .filter(it -> !it.trim().isEmpty())
+              .collect(Collectors.toList()));
+
+      }
+
+      return null;
+    }
+
+
+    SimpleOrderedMap getProperties(SchemaField sf) {
+      SimpleOrderedMap<Object> result = sf.getNamedPropertyValues(showDefaults);
+      if (schema.isDynamicField(sf.name)) {
+        String dynamicBase = schema.getDynamicPattern(sf.getName());
+        // Add dynamicBase property if it's different from the field name.
+        if (!sf.getName().equals(dynamicBase)) {
+          result.add("dynamicBase", dynamicBase);
+        }
+      }
+      return result;
+    }
+
+
+    @Override
+    public Map<String, Object> toMap() {
+      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<String,String> nameMapping = Collections.unmodifiableMap(Stream.of(Handler.values())
+        .collect(Collectors.toMap(Handler::getNameLower , Handler::getRealName)));
   }
 
+  public Map<String, Object> getNamedPropertyValues(String name, SolrParams params)
{
+    return new SchemaProps(name, params, this).toMap();
+
+  }
+
+
   /**
    * Returns a list of copyField directives, with optional details and optionally restricting
to those
    * directives that contain the requested source and/or destination field names.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
b/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
index c0f936d..7b39ab3 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
@@ -100,4 +100,38 @@ public class TestCopyFieldCollectionResource extends SolrRestletTestBase
{
 
   }
 
+  @Test
+  public void testRestrictSource() throws Exception {
+    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=title,*_i,*_src_sub_i,src_sub_no_ast_i",
+        "count(/response/arr[@name='copyFields']/lst) = 16", // 4 + 4 + 4 + 4
+        "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='title']) = 4",
+        "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='*_i']) = 4",
+        "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='*_src_sub_i'])
= 4",
+        "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='src_sub_no_ast_i'])
= 4");
+  }
+
+  @Test
+  public void testRestrictDest() throws Exception {
+    assertQ("/schema/copyfields/?indent=on&wt=xml&dest.fl=title,*_s,*_dest_sub_s,dest_sub_no_ast_s",
+        "count(/response/arr[@name='copyFields']/lst) = 16", // 3 + 4 + 4 + 5
+        "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='title']) = 3",
+        "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='*_s']) = 4",
+        "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='*_dest_sub_s'])
= 4",
+        "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='dest_sub_no_ast_s'])
= 5");
+  }
+
+  @Test
+  public void testRestrictSourceAndDest() throws Exception {
+    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=title,*_i&dest.fl=title,dest_sub_no_ast_s",
+        "count(/response/arr[@name='copyFields']/lst) = 3",
+
+        "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title']"
+            + "                                      and str[@name='dest'][.='dest_sub_no_ast_s']]",
+
+        "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
+            + "                                      and str[@name='dest'][.='title']]",
+
+        "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
+            + "                                      and str[@name='dest'][.='dest_sub_no_ast_s']]");
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
index 032bbad..6734ca2 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
@@ -30,10 +30,34 @@ public class TestDynamicFieldCollectionResource extends SolrRestletTestBase
{
   }
 
   @Test
+  public void testGetTwoDynamicFields() throws IOException {
+    assertQ("/schema/dynamicfields?indent=on&wt=xml&fl=*_i,*_s",
+            "count(/response/arr[@name='dynamicFields']/lst/str[@name='name']) = 2",
+            "(/response/arr[@name='dynamicFields']/lst/str[@name='name'])[1] = '*_i'",
+            "(/response/arr[@name='dynamicFields']/lst/str[@name='name'])[2] = '*_s'");
+  }
+
+  @Test
+  public void testNotFoundDynamicFields() throws IOException {
+    assertQ("/schema/dynamicfields?indent=on&wt=xml&fl=*_not_in_there,this_one_isnt_either_*",
+            "count(/response/arr[@name='dynamicFields']) = 1",
+            "count(/response/arr[@name='dynamicfields']/lst/str[@name='name']) = 0");
+  }
+
+  @Test
   public void testJsonGetAllDynamicFields() throws Exception {
     assertJQ("/schema/dynamicfields?indent=on",
              "/dynamicFields/[0]/name=='*_coordinate'",
              "/dynamicFields/[1]/name=='ignored_*'",
              "/dynamicFields/[2]/name=='*_mfacet'");
   }
+
+  @Test
+  public void testJsonGetTwoDynamicFields() throws Exception {
+    assertJQ("/schema/dynamicfields?indent=on&fl=*_i,*_s&wt=xml", // assertJQ will
fix the wt param to be json
+             "/dynamicFields/[0]/name=='*_i'",
+             "/dynamicFields/[1]/name=='*_s'");
+  }
+
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java
----------------------------------------------------------------------
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 627aee0..d296cdb 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,7 +71,13 @@ 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
   public void testGetFieldDontShowDefaults() throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/solrj/src/java/org/apache/solr/client/solrj/response/schema/SchemaResponse.java
----------------------------------------------------------------------
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 0f3b289..088cd60 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<Object> 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<Object> schemaNamedList) {
+  private static String getSchemaName(Map schemaNamedList) {
     return (String) schemaNamedList.get("name");
   }
 
-  private static Float getSchemaVersion(NamedList<Object> schemaNamedList) {
+  private static Float getSchemaVersion(Map schemaNamedList) {
     return (Float) schemaNamedList.get("version");
   }
 
-  private static String getSchemaUniqueKey(NamedList<Object> schemaNamedList) {
+  private static String getSchemaUniqueKey(Map schemaNamedList) {
     return (String) schemaNamedList.get("uniqueKey");
   }
 
-  private static String getDefaultSearchField(NamedList<Object> schemaNamedList) {
+  private static String getDefaultSearchField(Map schemaNamedList) {
     return (String) schemaNamedList.get("defaultSearchField");
   }
 
-  private static Map<String, Object> getSimilarity(NamedList<Object> schemaNamedList)
{
+  private static Map<String, Object> getSimilarity(Map schemaNamedList) {
     NamedList<Object> similarityNamedList = (NamedList<Object>) schemaNamedList.get("similarity");
     Map<String, Object> similarity = null;
     if (similarityNamedList != null) similarity = extractAttributeMap(similarityNamedList);
@@ -171,7 +171,7 @@ public class SchemaResponse extends SolrResponseBase {
   }
 
   @SuppressWarnings("unchecked")
-  private static String getDefaultOperator(NamedList<Object> schemaNamedList) {
+  private static String getDefaultOperator(Map schemaNamedList) {
     String defaultOperator = null;
     NamedList<Object> solrQueryParserProperties = (NamedList<Object>) 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<Map<String, Object>> getFields(NamedList<Object>
schemaNamedList) {
+  private static List<Map<String, Object>> getFields(Map schemaNamedList) {
     List<Map<String, Object>> fieldsAttributes = new LinkedList<>();
     List<NamedList<Object>> fieldsResponse = (List<NamedList<Object>>)
schemaNamedList.get("fields");
     for (NamedList<Object> fieldNamedList : fieldsResponse) {
@@ -192,7 +192,7 @@ public class SchemaResponse extends SolrResponseBase {
   }
 
   @SuppressWarnings("unchecked")
-  private static List<Map<String, Object>> getDynamicFields(NamedList<Object>
schemaNamedList) {
+  private static List<Map<String, Object>> getDynamicFields(Map schemaNamedList)
{
     List<Map<String, Object>> dynamicFieldsAttributes = new LinkedList<>();
     List<NamedList<Object>> dynamicFieldsResponse = (List<NamedList<Object>>)
schemaNamedList.get("dynamicFields");
     for (NamedList<Object> fieldNamedList : dynamicFieldsResponse) {
@@ -205,7 +205,7 @@ public class SchemaResponse extends SolrResponseBase {
   }
 
   @SuppressWarnings("unchecked")
-  private static List<Map<String, Object>> getCopyFields(NamedList<Object>
schemaNamedList) {
+  private static List<Map<String, Object>> getCopyFields(Map schemaNamedList)
{
     List<Map<String, Object>> copyFieldsAttributes = new LinkedList<>();
     List<NamedList<Object>> copyFieldsResponse = (List<NamedList<Object>>)
schemaNamedList.get("copyFields");
     for (NamedList<Object> copyFieldNamedList : copyFieldsResponse) {
@@ -218,7 +218,7 @@ public class SchemaResponse extends SolrResponseBase {
   }
 
   @SuppressWarnings("unchecked")
-  private static List<FieldTypeDefinition> getFieldTypeDefinitions(NamedList<Object>
schemaNamedList) {
+  private static List<FieldTypeDefinition> getFieldTypeDefinitions(Map schemaNamedList)
{
     List<FieldTypeDefinition> fieldTypeDefinitions = new LinkedList<>();
     List<NamedList<Object>> fieldsResponse = (List<NamedList<Object>>)
schemaNamedList.get("fieldTypes");
     for (NamedList<Object> fieldNamedList : fieldsResponse) {
@@ -230,7 +230,7 @@ public class SchemaResponse extends SolrResponseBase {
   }
 
   @SuppressWarnings("unchecked")
-  private static List<FieldTypeRepresentation> getFieldTypeRepresentations(NamedList<Object>
schemaNamedList) {
+  private static List<FieldTypeRepresentation> getFieldTypeRepresentations(Map schemaNamedList)
{
     List<FieldTypeRepresentation> fieldTypeRepresentations = new LinkedList<>();
     List<NamedList<Object>> fieldsResponse = (List<NamedList<Object>>)
schemaNamedList.get("fieldTypes");
     for (NamedList<Object> fieldNamedList : fieldsResponse) {
@@ -249,8 +249,8 @@ public class SchemaResponse extends SolrResponseBase {
   public void setResponse(NamedList<Object> response) {
     super.setResponse(response);
 
-    NamedList<Object> schemaNamedList = (NamedList<Object>) 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<Object> 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<Object> 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<Object> response) {
       super.setResponse(response);
 
-      fields = SchemaResponse.getFields(response);
+      fields = SchemaResponse.getFields(response.asShallowMap());
     }
 
     public List<Map<String, Object>> getFields() {
@@ -369,7 +369,7 @@ public class SchemaResponse extends SolrResponseBase {
     public void setResponse(NamedList<Object> response) {
       super.setResponse(response);
 
-      dynamicFields = SchemaResponse.getDynamicFields(response);
+      dynamicFields = SchemaResponse.getDynamicFields(response.asMap(3));
     }
 
     public List<Map<String, Object>> getDynamicFields() {
@@ -388,7 +388,7 @@ public class SchemaResponse extends SolrResponseBase {
     public void setResponse(NamedList<Object> 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<Object> response) {
       super.setResponse(response);
 
-      similarity = SchemaResponse.getSimilarity(response);
+      similarity = SchemaResponse.getSimilarity(response.asShallowMap());
     }
 
     public Map<String, Object> getSimilarity() {
@@ -446,7 +446,7 @@ public class SchemaResponse extends SolrResponseBase {
     public void setResponse(NamedList<Object> response) {
       super.setResponse(response);
 
-      copyFields = SchemaResponse.getCopyFields(response);
+      copyFields = SchemaResponse.getCopyFields(response.asShallowMap());
     }
 
     public List<Map<String, Object>> getCopyFields() {
@@ -486,7 +486,7 @@ public class SchemaResponse extends SolrResponseBase {
     public void setResponse(NamedList<Object> response) {
       super.setResponse(response);
 
-      fieldTypes = SchemaResponse.getFieldTypeRepresentations(response);
+      fieldTypes = SchemaResponse.getFieldTypeRepresentations(response.asShallowMap());
     }
 
     public List<FieldTypeRepresentation> getFieldTypes() {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f837216b/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java
----------------------------------------------------------------------
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 3ca750d..dd5afe7 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<T> implements Cloneable, Serializable, Iterable<Map.Entry
     return new NamedList<>( Collections.unmodifiableList(copy.nvPairs));
   }
 
+  public Map<String,T> asShallowMap() {
+    return new Map<String, T>() {
+      @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<String> 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<Entry<String,T>> 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<size();i++){


Mime
View raw message