You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2013/04/11 00:36:20 UTC

svn commit: r1466720 - in /lucene/dev/trunk: lucene/analysis/common/src/java/org/apache/lucene/analysis/util/ solr/core/src/java/org/apache/solr/schema/ solr/core/src/test-files/solr/collection1/conf/ solr/core/src/test/org/apache/solr/rest/schema/ sol...

Author: sarowe
Date: Wed Apr 10 22:36:19 2013
New Revision: 1466720

URL: http://svn.apache.org/r1466720
Log:
SOLR-4658:
- Fix class name shortening issues, for SimilarityFactory's, FieldType's, and analysis factories: persisted class names' original forms are preserved in both shortened form (e.g. 'solr.TextField') and fully qualified form (e.g. 'org.apache.solr.schema.TextField')
- luceneMatchVersion on analysis factories is now persisted only when explicitly specified in the original; previously the default value was persisted when it was absent in the original
- Add MockTokenFilterFactory

Added:
    lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-class-name-shortening-on-serialization.xml   (with props)
    lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest-lucene-match-version.xml   (with props)
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java   (with props)
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java   (with props)
    lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/analysis/MockTokenFilterFactory.java   (with props)
Modified:
    lucene/dev/trunk/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AbstractAnalysisFactory.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java

Modified: lucene/dev/trunk/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AbstractAnalysisFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AbstractAnalysisFactory.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AbstractAnalysisFactory.java (original)
+++ lucene/dev/trunk/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/AbstractAnalysisFactory.java Wed Apr 10 22:36:19 2013
@@ -51,20 +51,24 @@ import java.util.regex.PatternSyntaxExce
  * </ol>
  */
 public abstract class AbstractAnalysisFactory {
+  public static final String LUCENE_MATCH_VERSION_PARAM = "luceneMatchVersion";
 
   /** The original args, before any processing */
   private final Map<String,String> originalArgs;
 
   /** the luceneVersion arg */
   protected final Version luceneMatchVersion;
+  /** whether the luceneMatchVersion arg is explicitly specified in the serialized schema */
+  private boolean isExplicitLuceneMatchVersion = false;
 
   /**
    * Initialize this factory via a set of key-value pairs.
    */
   protected AbstractAnalysisFactory(Map<String,String> args) {
     originalArgs = Collections.unmodifiableMap(new HashMap<String,String>(args));
-    String version = get(args, "luceneMatchVersion");
+    String version = get(args, LUCENE_MATCH_VERSION_PARAM);
     luceneMatchVersion = version == null ? null : Version.parseLeniently(version);
+    args.remove(CLASS_NAME);  // consume the class arg
   }
   
   public final Map<String,String> getOriginalArgs() {
@@ -299,4 +303,28 @@ public abstract class AbstractAnalysisFa
 
     return result;
   }
+
+  private static final String CLASS_NAME = "class";
+  
+  /**
+   * @return the string used to specify the concrete class name in a serialized representation: the class arg.  
+   *         If the concrete class name was not specified via a class arg, returns {@code getClass().getName()}.
+   */ 
+  public String getClassArg() {
+    if (null != originalArgs) {
+      String className = originalArgs.get(CLASS_NAME);
+      if (null != className) {
+        return className;
+      }
+    }
+    return getClass().getName();
+  }
+
+  public boolean isExplicitLuceneMatchVersion() {
+    return isExplicitLuceneMatchVersion;
+  }
+
+  public void setExplicitLuceneMatchVersion(boolean isExplicitLuceneMatchVersion) {
+    this.isExplicitLuceneMatchVersion = isExplicitLuceneMatchVersion;
+  }
 }

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/AbstractSubTypeFieldType.java Wed Apr 10 22:36:19 2013
@@ -49,6 +49,7 @@ public abstract class AbstractSubTypeFie
 
   @Override
   protected void init(IndexSchema schema, Map<String, String> args) {
+    super.init(schema, args);
     this.schema = schema;
     //it's not a first class citizen for the IndexSchema
     SolrParams p = new MapSolrParams(args);

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldType.java Wed Apr 10 22:36:19 2013
@@ -26,8 +26,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+
+import static org.apache.lucene.analysis.util.AbstractAnalysisFactory.LUCENE_MATCH_VERSION_PARAM; 
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Tokenizer;
@@ -95,7 +95,6 @@ public abstract class FieldType extends 
   private boolean isExplicitQueryAnalyzer;
   private boolean isExplicitAnalyzer;
 
-
   /** Returns true if fields of this type should be tokenized */
   public boolean isTokenized() {
     return (properties & TOKENIZED) != 0;
@@ -152,6 +151,7 @@ public abstract class FieldType extends 
 
     this.args = Collections.unmodifiableMap(args);
     Map<String,String> initArgs = new HashMap<String,String>(args);
+    initArgs.remove(CLASS_NAME); // consume the class arg 
 
     trueProperties = FieldProperties.parseProperties(initArgs,true,false);
     falseProperties = FieldProperties.parseProperties(initArgs,false,false);
@@ -413,7 +413,21 @@ public abstract class FieldType extends 
     return isExplicitAnalyzer;
   }
 
-    /**
+  /**
+   * @return the string used to specify the concrete class name in a serialized representation: the class arg.  
+   *         If the concrete class name was not specified via a class arg, returns {@code getClass().getName()}.
+   */
+  public String getClassArg() {
+    if (null != args) {
+      String className = args.get(CLASS_NAME);
+      if (null != className) {
+        return className;
+      }
+    }
+    return getClass().getName();
+  }
+
+  /**
    * Default analyzer for types that only produce 1 verbatim token...
    * A maximum size of chars to be read must be specified
    */
@@ -752,12 +766,14 @@ public abstract class FieldType extends 
   public SimpleOrderedMap<Object> getNamedPropertyValues(boolean showDefaults) {
     SimpleOrderedMap<Object> namedPropertyValues = new SimpleOrderedMap<Object>();
     namedPropertyValues.add(TYPE_NAME, getTypeName());
-    namedPropertyValues.add(CLASS_NAME, getShortName(getClass().getName()));
+    namedPropertyValues.add(CLASS_NAME, getClassArg());
     if (showDefaults) {
       Map<String,String> fieldTypeArgs = getNonFieldPropertyArgs();
       if (null != fieldTypeArgs) {
         for (String key : fieldTypeArgs.keySet()) {
-          namedPropertyValues.add(key, fieldTypeArgs.get(key));
+        if ( ! CLASS_NAME.equals(key) && ! TYPE_NAME.equals(key)) {
+            namedPropertyValues.add(key, fieldTypeArgs.get(key));
+          }
         }
       }
       if (this instanceof TextField) {
@@ -790,7 +806,7 @@ public abstract class FieldType extends 
       for (String key : args.keySet()) {
         if (fieldProperties.contains(key)) {
           namedPropertyValues.add(key, StrUtils.parseBool(args.get(key)));
-        } else {
+        } else if ( ! CLASS_NAME.equals(key) && ! TYPE_NAME.equals(key)) {
           namedPropertyValues.add(key, args.get(key));
         }
       }
@@ -846,11 +862,19 @@ public abstract class FieldType extends 
         List<SimpleOrderedMap<Object>> charFilterProps = new ArrayList<SimpleOrderedMap<Object>>();
         for (CharFilterFactory charFilterFactory : charFilterFactories) {
           SimpleOrderedMap<Object> props = new SimpleOrderedMap<Object>();
-          props.add(CLASS_NAME, getShortName(charFilterFactory.getClass().getName()));
+          props.add(CLASS_NAME, charFilterFactory.getClassArg());
           factoryArgs = charFilterFactory.getOriginalArgs();
           if (null != factoryArgs) {
             for (String key : factoryArgs.keySet()) {
-              props.add(key, factoryArgs.get(key));
+              if ( ! CLASS_NAME.equals(key)) {
+                if (LUCENE_MATCH_VERSION_PARAM.equals(key)) {
+                  if (charFilterFactory.isExplicitLuceneMatchVersion()) {
+                    props.add(key, factoryArgs.get(key));
+                  }
+                } else {
+                   props.add(key, factoryArgs.get(key));
+                }
+              }
             }
           }
           charFilterProps.add(props);
@@ -860,11 +884,19 @@ public abstract class FieldType extends 
 
       SimpleOrderedMap<Object> tokenizerProps = new SimpleOrderedMap<Object>();
       TokenizerFactory tokenizerFactory = tokenizerChain.getTokenizerFactory();
-      tokenizerProps.add(CLASS_NAME, getShortName(tokenizerFactory.getClass().getName()));
+      tokenizerProps.add(CLASS_NAME, tokenizerFactory.getClassArg());
       factoryArgs = tokenizerFactory.getOriginalArgs();
       if (null != factoryArgs) {
         for (String key : factoryArgs.keySet()) {
-          tokenizerProps.add(key, factoryArgs.get(key));
+          if ( ! CLASS_NAME.equals(key)) {
+            if (LUCENE_MATCH_VERSION_PARAM.equals(key)) {
+              if (tokenizerFactory.isExplicitLuceneMatchVersion()) {
+                tokenizerProps.add(key, factoryArgs.get(key));
+              }
+            } else {
+              tokenizerProps.add(key, factoryArgs.get(key));
+            }
+          }
         }
       }
       analyzerProps.add(TOKENIZER, tokenizerProps);
@@ -874,11 +906,19 @@ public abstract class FieldType extends 
         List<SimpleOrderedMap<Object>> filterProps = new ArrayList<SimpleOrderedMap<Object>>();
         for (TokenFilterFactory filterFactory : filterFactories) {
           SimpleOrderedMap<Object> props = new SimpleOrderedMap<Object>();
-          props.add(CLASS_NAME, getShortName(filterFactory.getClass().getName()));
+          props.add(CLASS_NAME, filterFactory.getClassArg());
           factoryArgs = filterFactory.getOriginalArgs();
           if (null != factoryArgs) {
             for (String key : factoryArgs.keySet()) {
-              props.add(key, factoryArgs.get(key));
+              if ( ! CLASS_NAME.equals(key)) {
+                if (LUCENE_MATCH_VERSION_PARAM.equals(key)) {
+                  if (filterFactory.isExplicitLuceneMatchVersion()) {
+                    props.add(key, factoryArgs.get(key));
+                  }
+                } else {
+                  props.add(key, factoryArgs.get(key));
+                }
+              }
             }
           }
           filterProps.add(props);
@@ -890,12 +930,4 @@ public abstract class FieldType extends 
     }
     return analyzerProps;
   }
-  
-  private static final Pattern SHORTENABLE_PACKAGE_PATTERN 
-      = Pattern.compile("org\\.apache\\.(?:lucene\\.analysis(?=.).*|solr\\.(?:analysis|schema))\\.([^.]+)$");
-
-  private static String getShortName(String fullyQualifiedName) {
-    Matcher matcher = SHORTENABLE_PACKAGE_PATTERN.matcher(fullyQualifiedName);
-    return matcher.matches() ? "solr." + matcher.group(1) : fullyQualifiedName;
-  }
 }

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/FieldTypePluginLoader.java Wed Apr 10 22:36:19 2013
@@ -137,11 +137,10 @@ public final class FieldTypePluginLoader
   @Override
   protected void init(FieldType plugin, Node node) throws Exception {
 
-    Map<String,String> params = DOMUtil.toMapExcept( node.getAttributes(), 
-                                                     "name","class" );
-    plugin.setArgs(schema, params );
+    Map<String,String> params = DOMUtil.toMapExcept( node.getAttributes(), "name");
+    plugin.setArgs(schema, params);
   }
-  
+
   @Override
   protected FieldType register(String name, 
                                FieldType plugin) throws Exception {
@@ -301,10 +300,12 @@ public final class FieldTypePluginLoader
 
       @Override
       protected CharFilterFactory create(SolrResourceLoader loader, String name, String className, Node node) throws Exception {
-        final Map<String,String> params = DOMUtil.toMapExcept(node.getAttributes(),"class");
+        final Map<String,String> params = DOMUtil.toMap(node.getAttributes());
         String configuredVersion = params.remove(LUCENE_MATCH_VERSION_PARAM);
         params.put(LUCENE_MATCH_VERSION_PARAM, parseConfiguredVersion(configuredVersion, CharFilterFactory.class.getSimpleName()).toString());
-        return loader.newInstance(className, CharFilterFactory.class, getDefaultPackages(), new Class[] { Map.class }, new Object[] { params });
+        CharFilterFactory factory = loader.newInstance(className, CharFilterFactory.class, getDefaultPackages(), new Class[] { Map.class }, new Object[] { params });
+        factory.setExplicitLuceneMatchVersion(null != configuredVersion);
+        return factory;
       }
 
       @Override
@@ -335,10 +336,12 @@ public final class FieldTypePluginLoader
       
       @Override
       protected TokenizerFactory create(SolrResourceLoader loader, String name, String className, Node node) throws Exception {
-        final Map<String,String> params = DOMUtil.toMapExcept(node.getAttributes(),"class");
+        final Map<String,String> params = DOMUtil.toMap(node.getAttributes());
         String configuredVersion = params.remove(LUCENE_MATCH_VERSION_PARAM);
         params.put(LUCENE_MATCH_VERSION_PARAM, parseConfiguredVersion(configuredVersion, TokenizerFactory.class.getSimpleName()).toString());
-        return loader.newInstance(className, TokenizerFactory.class, getDefaultPackages(), new Class[] { Map.class }, new Object[] { params });
+        TokenizerFactory factory = loader.newInstance(className, TokenizerFactory.class, getDefaultPackages(), new Class[] { Map.class }, new Object[] { params });
+        factory.setExplicitLuceneMatchVersion(null != configuredVersion);
+        return factory;
       }
       
       @Override
@@ -373,10 +376,13 @@ public final class FieldTypePluginLoader
     {
       @Override
       protected TokenFilterFactory create(SolrResourceLoader loader, String name, String className, Node node) throws Exception {
-        final Map<String,String> params = DOMUtil.toMapExcept(node.getAttributes(),"class");
+        final Map<String,String> params = DOMUtil.toMap(node.getAttributes());
         String configuredVersion = params.remove(LUCENE_MATCH_VERSION_PARAM);
         params.put(LUCENE_MATCH_VERSION_PARAM, parseConfiguredVersion(configuredVersion, TokenFilterFactory.class.getSimpleName()).toString());
-        return loader.newInstance(className, TokenFilterFactory.class, getDefaultPackages(), new Class[] { Map.class }, new Object[] { params });
+        TokenFilterFactory factory = loader.newInstance
+            (className, TokenFilterFactory.class, getDefaultPackages(), new Class[] { Map.class }, new Object[] { params });
+        factory.setExplicitLuceneMatchVersion(null != configuredVersion);
+        return factory;
       }
       
       @Override

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/IndexSchema.java Wed Apr 10 22:36:19 2013
@@ -890,10 +890,13 @@ public class IndexSchema {
       return null;
     } else {
       SimilarityFactory similarityFactory;
-      final Object obj = loader.newInstance(((Element) node).getAttribute("class"), Object.class, "search.similarities.");
+      final String classArg = ((Element) node).getAttribute(SimilarityFactory.CLASS_NAME);
+      final Object obj = loader.newInstance(classArg, Object.class, "search.similarities.");
       if (obj instanceof SimilarityFactory) {
         // configure a factory, get a similarity back
-        SolrParams params = SolrParams.toSolrParams(DOMUtil.childNodesToNamedList(node));
+        final NamedList<Object> namedList = DOMUtil.childNodesToNamedList(node);
+        namedList.add(SimilarityFactory.CLASS_NAME, classArg);
+        SolrParams params = SolrParams.toSolrParams(namedList);
         similarityFactory = (SimilarityFactory)obj;
         similarityFactory.init(params);
       } else {

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/SimilarityFactory.java Wed Apr 10 22:36:19 2013
@@ -40,7 +40,6 @@ import java.util.Iterator;
  */
 public abstract class SimilarityFactory {
   public static final String CLASS_NAME = "class";
-  private static final String SOLR_SIMILARITIES_PACKAGE = "org.apache.solr.search.similarities"; 
   
   protected SolrParams params;
 
@@ -52,25 +51,38 @@ public abstract class SimilarityFactory 
 
   /** Returns a serializable description of this similarity(factory) */
   public SimpleOrderedMap<Object> getNamedPropertyValues() {
-    String className = getClass().getName();
-    if (className.startsWith("org.apache.solr.schema.IndexSchema$")) {
-      // If this class is just a no-params wrapper around a similarity class, use the similarity class
-      className = getSimilarity().getClass().getName();
-    } else {
-      // Only shorten factory names
-      if (className.startsWith(SOLR_SIMILARITIES_PACKAGE + ".")) {
-        className = className.replace(SOLR_SIMILARITIES_PACKAGE, "solr");
-      }
-    }
     SimpleOrderedMap<Object> props = new SimpleOrderedMap<Object>();
-    props.add(CLASS_NAME, className);
+    props.add(CLASS_NAME, getClassArg());
     if (null != params) {
       Iterator<String> iter = params.getParameterNamesIterator();
       while (iter.hasNext()) {
         String key = iter.next();
-        props.add(key, params.get(key));
+        if ( ! CLASS_NAME.equals(key)) {
+          props.add(key, params.get(key));
+        }
       }
     }
     return props;
   }
+
+  /**
+   * @return the string used to specify the concrete class name in a serialized representation: the class arg.  
+   *         If the concrete class name was not specified via a class arg, returns {@code getClass().getName()},
+   *         unless this class is the anonymous similarity wrapper produced in {@link IndexSchema}, in which
+   *         case the {@code getSimilarity().getClass().getName()} is returned.
+   */
+  public String getClassArg() {
+    if (null != params) {
+      String className = params.get(CLASS_NAME);
+      if (null != className) {
+        return className;
+      }
+    }
+    String className = getClass().getName(); 
+    if (className.startsWith("org.apache.solr.schema.IndexSchema$")) {
+      // If this class is just a no-params wrapper around a similarity class, use the similarity class
+      className = getSimilarity().getClass().getName();
+    }
+    return className; 
+  }
 }

Added: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-class-name-shortening-on-serialization.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-class-name-shortening-on-serialization.xml?rev=1466720&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-class-name-shortening-on-serialization.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-class-name-shortening-on-serialization.xml Wed Apr 10 22:36:19 2013
@@ -0,0 +1,43 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<schema name="test-class-name-shortening-on-serialization" version="1.5">
+  <types>
+    <fieldtype name="fullClassNames" class="org.apache.solr.schema.TextField">
+      <analyzer>
+        <charFilter class="org.apache.solr.analysis.MockCharFilterFactory" remainder="0"/>
+        <tokenizer class="org.apache.solr.analysis.MockTokenizerFactory"/>
+        <filter class="org.apache.solr.analysis.MockTokenFilterFactory" stopset="empty"/>
+      </analyzer>
+      <similarity class="org.apache.lucene.misc.SweetSpotSimilarity"/>
+    </fieldtype>
+    <fieldtype name="shortenedClassNames" class="solr.TextField">
+      <analyzer>
+        <charFilter class="solr.MockCharFilterFactory" remainder="0"/>
+        <tokenizer class="solr.MockTokenizerFactory"/>
+        <filter class="solr.MockTokenFilterFactory" stopset="empty"/>
+      </analyzer>
+      <similarity class="solr.SweetSpotSimilarityFactory"/>
+    </fieldtype>
+    <fieldtype name="string" class="solr.StrField" sortMissingLast="true"/>
+  </types>
+  <fields>
+    <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
+    <field name="signatureField" type="string" indexed="true" stored="false"/>
+  </fields>
+  <similarity class="solr.SchemaSimilarityFactory"/>
+</schema>

Added: lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest-lucene-match-version.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest-lucene-match-version.xml?rev=1466720&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest-lucene-match-version.xml (added)
+++ lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-rest-lucene-match-version.xml Wed Apr 10 22:36:19 2013
@@ -0,0 +1,40 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<schema name="test-class-name-shortening-on-serialization" version="1.5">
+  <types>
+    <fieldtype name="explicitLuceneMatchVersions" class="org.apache.solr.schema.TextField">
+      <analyzer>
+        <charFilter class="org.apache.solr.analysis.MockCharFilterFactory" luceneMatchVersion="LUCENE_40" remainder="0"/>
+        <tokenizer class="org.apache.solr.analysis.MockTokenizerFactory" luceneMatchVersion="LUCENE_40" />
+        <filter class="org.apache.solr.analysis.MockTokenFilterFactory" luceneMatchVersion="LUCENE_40" stopset="empty"/>
+      </analyzer>
+    </fieldtype>
+    <fieldtype name="noLuceneMatchVersions" class="org.apache.solr.schema.TextField">
+      <analyzer>
+        <charFilter class="org.apache.solr.analysis.MockCharFilterFactory" remainder="0"/>
+        <tokenizer class="org.apache.solr.analysis.MockTokenizerFactory" />
+        <filter class="org.apache.solr.analysis.MockTokenFilterFactory" stopset="empty"/>
+      </analyzer>
+    </fieldtype>
+    <fieldtype name="string" class="solr.StrField" sortMissingLast="true"/>
+  </types>
+  <fields>
+    <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
+    <field name="signatureField" type="string" indexed="true" stored="false"/>
+  </fields>
+</schema>

Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java?rev=1466720&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java Wed Apr 10 22:36:19 2013
@@ -0,0 +1,70 @@
+package org.apache.solr.rest.schema;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.solr.util.RestTestBase;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.restlet.ext.servlet.ServerServlet;
+
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+
+public class TestClassNameShortening extends RestTestBase {
+
+  @BeforeClass
+  public static void init() throws Exception {
+    final SortedMap<ServletHolder,String> extraServlets = new TreeMap<ServletHolder,String>();
+    final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
+    solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
+    extraServlets.put(solrRestApi, "/schema/*");  // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
+
+    createJettyAndHarness(TEST_HOME(), "solrconfig-minimal.xml", "schema-class-name-shortening-on-serialization.xml", 
+                          "/solr", true, extraServlets);
+  }
+
+  @Test
+  public void testClassNamesNotShortened() throws Exception {
+    assertQ("/schema/fieldtypes/fullClassNames?indent=on&wt=xml&showDefaults=true",
+            "count(/response/lst[@name='fieldType']) = 1",
+            "/response/lst[@name='fieldType']/str[@name='class'] = 'org.apache.solr.schema.TextField'",
+            "//arr[@name='charFilters']/lst/str[@name='class'] = 'org.apache.solr.analysis.MockCharFilterFactory'",
+            "//lst[@name='tokenizer']/str[@name='class'] = 'org.apache.solr.analysis.MockTokenizerFactory'",
+            "//arr[@name='filters']/lst/str[@name='class'] = 'org.apache.solr.analysis.MockTokenFilterFactory'",
+            "/response/lst[@name='fieldType']/lst[@name='similarity']/str[@name='class'] = 'org.apache.lucene.misc.SweetSpotSimilarity'");
+  }
+
+  @Test
+  public void testShortenedGlobalSimilarityStaysShortened() throws Exception {
+    assertQ("/schema/similarity?indent=on&wt=xml",
+            "count(/response/lst[@name='similarity']) = 1",
+            "/response/lst[@name='similarity']/str[@name='class'][.='solr.SchemaSimilarityFactory']");
+  }
+
+  @Test
+  public void testShortenedClassNamesStayShortened() throws Exception {
+    assertQ("/schema/fieldtypes/shortenedClassNames?indent=on&wt=xml&showDefaults=true",
+            "count(/response/lst[@name='fieldType']) = 1",
+            "/response/lst[@name='fieldType']/str[@name='class'] = 'solr.TextField'",
+            "//arr[@name='charFilters']/lst/str[@name='class'] = 'solr.MockCharFilterFactory'",
+            "//lst[@name='tokenizer']/str[@name='class'] = 'solr.MockTokenizerFactory'",
+            "//arr[@name='filters']/lst/str[@name='class'] = 'solr.MockTokenFilterFactory'",
+            "/response/lst[@name='fieldType']/lst[@name='similarity']/str[@name='class'] = 'solr.SweetSpotSimilarityFactory'");
+  }
+}

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java?rev=1466720&r1=1466719&r2=1466720&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java Wed Apr 10 22:36:19 2013
@@ -24,7 +24,7 @@ public class TestSchemaSimilarityResourc
   public void testGetSchemaSimilarity() throws Exception {
     assertQ("/schema/similarity?indent=on&wt=xml",
             "count(/response/lst[@name='similarity']) = 1",
-            "/response/lst[@name='similarity']/str[@name='class'][.='solr.DefaultSimilarityFactory']");
+            "/response/lst[@name='similarity']/str[@name='class'][.='org.apache.solr.search.similarities.DefaultSimilarityFactory']");
   }
 }
 

Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java?rev=1466720&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/rest/schema/TestSerializedLuceneMatchVersion.java Wed Apr 10 22:36:19 2013
@@ -0,0 +1,72 @@
+package org.apache.solr.rest.schema;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.solr.util.RestTestBase;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.restlet.ext.servlet.ServerServlet;
+
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+
+public class TestSerializedLuceneMatchVersion extends RestTestBase {
+
+  @BeforeClass
+  public static void init() throws Exception {
+    final SortedMap<ServletHolder,String> extraServlets = new TreeMap<ServletHolder,String>();
+    final ServletHolder solrRestApi = new ServletHolder("SolrRestApi", ServerServlet.class);
+    solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrRestApi");
+    extraServlets.put(solrRestApi, "/schema/*");  // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
+
+    createJettyAndHarness(TEST_HOME(), "solrconfig-minimal.xml", "schema-rest-lucene-match-version.xml",
+                          "/solr", true, extraServlets);
+  }
+
+  @Test
+  public void testExplicitLuceneMatchVersions() throws Exception {
+    assertQ("/schema/fieldtypes/explicitLuceneMatchVersions?indent=on&wt=xml&showDefaults=true",
+            "count(/response/lst[@name='fieldType']) = 1",
+        
+            "//lst[str[@name='class'][.='org.apache.solr.analysis.MockCharFilterFactory']]"
+           +"     [str[@name='luceneMatchVersion'][.='LUCENE_40']]",
+        
+            "//lst[str[@name='class'][.='org.apache.solr.analysis.MockTokenizerFactory']]"
+           +"     [str[@name='luceneMatchVersion'][.='LUCENE_40']]",
+        
+            "//lst[str[@name='class'][.='org.apache.solr.analysis.MockTokenFilterFactory']]"
+           +"     [str[@name='luceneMatchVersion'][.='LUCENE_40']]");
+  }
+
+  @Test
+  public void testNoLuceneMatchVersions() throws Exception {
+    assertQ("/schema/fieldtypes/noLuceneMatchVersions?indent=on&wt=xml&showDefaults=true",
+            "count(/response/lst[@name='fieldType']) = 1",
+
+            "//lst[str[@name='class'][.='org.apache.solr.analysis.MockCharFilterFactory']]"
+           +"     [not(./str[@name='luceneMatchVersion'])]",
+
+            "//lst[str[@name='class'][.='org.apache.solr.analysis.MockTokenizerFactory']]"
+           +"     [not(./str[@name='luceneMatchVersion'])]",
+        
+            "//lst[str[@name='class'][.='org.apache.solr.analysis.MockTokenFilterFactory']]"
+           +"     [not(./str[@name='luceneMatchVersion'])]");
+  }
+  
+}

Added: lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/analysis/MockTokenFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/analysis/MockTokenFilterFactory.java?rev=1466720&view=auto
==============================================================================
--- lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/analysis/MockTokenFilterFactory.java (added)
+++ lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/analysis/MockTokenFilterFactory.java Wed Apr 10 22:36:19 2013
@@ -0,0 +1,67 @@
+package org.apache.solr.analysis;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.lucene.analysis.MockTokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.util.TokenFilterFactory;
+import org.apache.lucene.util.automaton.CharacterRunAutomaton;
+import org.apache.lucene.util.automaton.RegExp;
+
+/**
+ * Factory for {@link MockTokenFilter} for testing purposes.
+ */
+public class MockTokenFilterFactory extends TokenFilterFactory {
+  final CharacterRunAutomaton filter;
+  final boolean enablePositionIncrements;
+
+  /** Creates a new MockTokenizerFactory */
+  public MockTokenFilterFactory(Map<String, String> args) {
+    super(args);
+    String stopset = get(args, "stopset", Arrays.asList("english", "empty"), null, false);
+    String stopregex = get(args, "stopregex");
+    if (null != stopset) {
+      if (null != stopregex) {
+        throw new IllegalArgumentException("Parameters stopset and stopregex cannot both be specified.");
+      }
+      if ("english".equalsIgnoreCase(stopset)) {
+        filter = MockTokenFilter.ENGLISH_STOPSET;
+      } else { // must be "empty"
+        filter = MockTokenFilter.EMPTY_STOPSET;
+      }
+    } else if (null != stopregex) {
+      RegExp regex = new RegExp(stopregex);
+      filter = new CharacterRunAutomaton(regex.toAutomaton());
+    } else {
+      throw new IllegalArgumentException
+          ("Configuration Error: either the 'stopset' or the 'stopregex' parameter must be specified.");
+    }
+    enablePositionIncrements = getBoolean(args, "enablePositionIncrements", true);
+    if (!args.isEmpty()) {
+      throw new IllegalArgumentException("Unknown parameters: " + args);
+    }
+  }
+
+  @Override
+  public MockTokenFilter create(TokenStream stream) {
+    return new MockTokenFilter(stream, filter);
+  }
+}
\ No newline at end of file