You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2014/01/20 12:56:10 UTC
svn commit: r1559670 - in /lucene/dev/branches/lucene5376/lucene:
analysis/common/src/java/org/apache/lucene/analysis/charfilter/
analysis/common/src/java/org/apache/lucene/analysis/pattern/
server/src/java/org/apache/lucene/server/handlers/ server/src...
Author: mikemccand
Date: Mon Jan 20 11:56:10 2014
New Revision: 1559670
URL: http://svn.apache.org/r1559670
Log:
LUCENE-5376: get 'file-like resources' working with char filters, fix nocommits, tests, clean up the analysis factory code
Modified:
lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/MappingCharFilterFactory.java
lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/pattern/PatternReplaceCharFilterFactory.java
lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/handlers/RegisterFieldHandler.java
lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/OrType.java
lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/Request.java
lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/ServerBaseTestCase.java
lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/TestAnalysis.java
Modified: lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/MappingCharFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/MappingCharFilterFactory.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/MappingCharFilterFactory.java (original)
+++ lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/charfilter/MappingCharFilterFactory.java Mon Jan 20 11:56:10 2014
@@ -55,7 +55,7 @@ public class MappingCharFilterFactory ex
super(args);
mapping = get(args, "mapping");
if (!args.isEmpty()) {
- throw new IllegalArgumentException("Unknown parameters: " + args);
+ throw new IllegalArgumentException("Unknown parameters: " + args + "; valid parameters: mapping, luceneMatchVersion, class");
}
}
@@ -94,30 +94,32 @@ public class MappingCharFilterFactory ex
}
// "source" => "target"
- static Pattern p = Pattern.compile( "\"(.*)\"\\s*=>\\s*\"(.*)\"\\s*$" );
+ static Pattern p = Pattern.compile("\"(.*)\"\\s*=>\\s*\"(.*)\"\\s*$");
- protected void parseRules( List<String> rules, NormalizeCharMap.Builder builder ){
- for( String rule : rules ){
- Matcher m = p.matcher( rule );
- if( !m.find() )
- throw new IllegalArgumentException("Invalid Mapping Rule : [" + rule + "], file = " + mapping);
- builder.add( parseString( m.group( 1 ) ), parseString( m.group( 2 ) ) );
+ protected void parseRules(List<String> rules, NormalizeCharMap.Builder builder) {
+ for(String rule : rules) {
+ Matcher m = p.matcher(rule);
+ if (m.find() == false) {
+ throw new IllegalArgumentException("Invalid Mapping Rule \"" + rule + "\" (file=\"" + mapping + "\"); should be form \"xxx\" => \"yyy\"");
+ }
+ builder.add(parseString(m.group(1)), parseString(m.group(2)));
}
}
char[] out = new char[256];
- protected String parseString( String s ){
+ protected String parseString(String s) {
int readPos = 0;
int len = s.length();
int writePos = 0;
- while( readPos < len ){
- char c = s.charAt( readPos++ );
- if( c == '\\' ){
- if( readPos >= len )
+ while (readPos < len) {
+ char c = s.charAt(readPos++);
+ if (c == '\\') {
+ if (readPos >= len) {
throw new IllegalArgumentException("Invalid escaped char in [" + s + "]");
- c = s.charAt( readPos++ );
- switch( c ) {
+ }
+ c = s.charAt(readPos++);
+ switch(c) {
case '\\' : c = '\\'; break;
case '"' : c = '"'; break;
case 'n' : c = '\n'; break;
@@ -126,16 +128,17 @@ public class MappingCharFilterFactory ex
case 'b' : c = '\b'; break;
case 'f' : c = '\f'; break;
case 'u' :
- if( readPos + 3 >= len )
+ if (readPos + 3 >= len) {
throw new IllegalArgumentException("Invalid escaped char in [" + s + "]");
- c = (char)Integer.parseInt( s.substring( readPos, readPos + 4 ), 16 );
+ }
+ c = (char) Integer.parseInt(s.substring(readPos, readPos + 4 ), 16);
readPos += 4;
break;
}
}
out[writePos++] = c;
}
- return new String( out, 0, writePos );
+ return new String(out, 0, writePos);
}
@Override
Modified: lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/pattern/PatternReplaceCharFilterFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/pattern/PatternReplaceCharFilterFactory.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/pattern/PatternReplaceCharFilterFactory.java (original)
+++ lucene/dev/branches/lucene5376/lucene/analysis/common/src/java/org/apache/lucene/analysis/pattern/PatternReplaceCharFilterFactory.java Mon Jan 20 11:56:10 2014
@@ -47,7 +47,7 @@ public class PatternReplaceCharFilterFac
pattern = getPattern(args, "pattern");
replacement = get(args, "replacement", "");
if (!args.isEmpty()) {
- throw new IllegalArgumentException("Unknown parameters: " + args);
+ throw new IllegalArgumentException("Unknown parameters: " + args + "; valid parameters: pattern, replacement, luceneMatchVersion, class");
}
}
Modified: lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/handlers/RegisterFieldHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/handlers/RegisterFieldHandler.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/handlers/RegisterFieldHandler.java (original)
+++ lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/handlers/RegisterFieldHandler.java Mon Jan 20 11:56:10 2014
@@ -726,16 +726,17 @@ public class RegisterFieldHandler extend
return words;
}
- static TokenizerFactory buildICUTokenizerFactory(JSONObject params) {
+ final static Pattern COMMENTS_PATTERN = Pattern.compile("#.*$", Pattern.MULTILINE);
+
+ static TokenizerFactory buildICUTokenizerFactory(Request sub) {
boolean cjkAsWords;
final BreakIterator breakers[];
- if (params != null) {
+ if (sub != null) {
+ Request icuRequest = new Request(sub, ICU_TOKENIZER_TYPE);
- // nocommit don't pass null, null:
- Request icuRequest = new Request(null, null, params, ICU_TOKENIZER_TYPE);
cjkAsWords = icuRequest.getBoolean("cjkAsWords");
if (icuRequest.hasParam("rules")) {
@@ -813,57 +814,41 @@ public class RegisterFieldHandler extend
};
}
- final static Pattern COMMENTS_PATTERN = Pattern.compile("#.*$", Pattern.MULTILINE);
-
- static Analyzer buildCustomAnalyzer(IndexState state, Version matchVersion, Request chain) throws IOException {
-
- // nocommit what is MultiTermAwareComponent?
-
- // nocommit charFilters
-
+ private static List<CharFilterFactory> parseCharFilters(IndexState state, Version matchVersion, Request chain) throws IOException {
List<CharFilterFactory> charFilters;
-
if (chain.hasParam("charFilters")) {
charFilters = new ArrayList<CharFilterFactory>();
for(Object o : chain.getList("charFilters")) {
+ String paramName = "charFilters[" + charFilters.size() + "]";
Request sub;
String className;
if (o instanceof String) {
className = (String) o;
sub = null;
} else {
- if ((o instanceof Request) == false) {
- // nocommit make sure test hits this
- chain.failWrongClass("charFilters", "each char filter must be string or struct", o);
- }
+ // The type already validated this:
+ assert o instanceof Request;
sub = (Request) o;
className = sub.getString("class");
}
- Map<String,String> factoryArgs = new HashMap<String,String>();
- // nocommit how to allow the SPI name and separately
- // also a fully qualified class name ...
- factoryArgs.put("class", className);
- factoryArgs.put("luceneMatchVersion", matchVersion.toString());
- if (sub != null) {
- for(Map.Entry<String,Object> ent : sub.getRawParams().entrySet()) {
- factoryArgs.put(ent.getKey(), ent.getValue().toString());
- }
- sub.clearParams();
- }
+ TwoThings<Map<String,String>,ResourceLoader> things = parseArgsAndResources(state,
+ className,
+ matchVersion,
+ sub);
CharFilterFactory factory;
try {
- factory = CharFilterFactory.forName(className, factoryArgs);
+ factory = CharFilterFactory.forName(className, things.a);
} catch (IllegalArgumentException iae) {
- chain.fail("charFilters[" + charFilters.size() + "]", "failed to create CharFilterFactory for class \"" + className + "\": " + iae, iae);
+ chain.fail(paramName, "failed to create CharFilterFactory for class \"" + className + "\": " + iae, iae);
+
// Dead code but compiler disagrees:
factory = null;
}
if (factory instanceof ResourceLoaderAware) {
- // nocommit also do RAM wrapping resource loader here:
- ((ResourceLoaderAware) factory).inform(state.resourceLoader);
+ ((ResourceLoaderAware) factory).inform(things.b);
}
charFilters.add(factory);
@@ -872,44 +857,124 @@ public class RegisterFieldHandler extend
charFilters = null;
}
+ return charFilters;
+ }
+
+ private static final class TwoThings<A,B> {
+ public final A a;
+ public final B b;
+
+ public TwoThings(A a, B b) {
+ this.a = a;
+ this.b = b;
+ }
+ };
+
+ /** Parses the arguments for an analysis factory
+ * component, but also detects any argument name of the
+ * form xxxFileContents and puts its value into a "fake"
+ * (RAM) file, leaving xxx referring to that file. This
+ * way any existing component expecting to load a
+ * resource from a "file" will (hacky) work. */
+ private static TwoThings<Map<String,String>,ResourceLoader> parseArgsAndResources(IndexState state,
+ String className,
+ Version matchVersion,
+ Request sub) {
+
+ Map<String,String> factoryArgs = new HashMap<String,String>();
+
+ // nocommit how to allow the SPI name and separately
+ // also a fully qualified class name ...
+ factoryArgs.put("class", className);
+ factoryArgs.put("luceneMatchVersion", matchVersion.toString());
+
+ ResourceLoader resources = state.resourceLoader;
+ RAMResourceLoaderWrapper ramResources = null;
+
+ if (sub != null) {
+ for(Map.Entry<String,Object> ent : sub.getRawParams().entrySet()) {
+ String argName = ent.getKey();
+ Object argValue = ent.getValue();
+
+ // Messy / impedance mismatch: allow
+ // components that expect files for things
+ // like stopword lists, keywords, to come in
+ // as inlined string values. We "hijack" any
+ // argument name ending in FileContents and
+ // make a RAM file out of it:
+ String argString;
+
+ if (argName.endsWith("FileContents")) {
+ if (ramResources == null) {
+ ramResources = new RAMResourceLoaderWrapper(resources);
+ resources = ramResources;
+ }
+
+ String value;
+ if (argValue instanceof String) {
+ value = (String) argValue;
+ } else if (argValue instanceof JSONArray) {
+ // Each element in the array is mapped to
+ // one line in the file
+ StringBuilder b = new StringBuilder();
+ for(Object v : (JSONArray) argValue) {
+ if ((v instanceof String) == false) {
+ sub.failWrongClass(argName, "array must contain strings", v);
+ }
+ b.append((String) v);
+ b.append('\n');
+ }
+ value = b.toString();
+ } else {
+ sub.failWrongClass(argName, "must be a String or Array", argValue);
+
+ // Dead code but compiler disagrees:
+ value = null;
+ }
+
+ argName = argName.substring(0, argName.length()-12);
+ ramResources.add(argName, value);
+ argString = argName;
+ } else {
+ argString = argValue.toString();
+ }
+
+ factoryArgs.put(argName, argString);
+ }
+
+ // Clear all bindings from the incoming request,
+ // so that they are not seen as unused by the
+ // server. If any params are really unused, the
+ // analysis factory should throw its own
+ // IllegalArgumentException:
+ sub.clearParams();
+ }
+
+ return new TwoThings<Map<String,String>,ResourceLoader>(factoryArgs, resources);
+ }
+
+ static TokenizerFactory parseTokenizer(IndexState state, Version matchVersion, Request chain) throws IOException {
// Build TokenizerFactory:
String className;
- JSONObject t;
+ Request sub;
if (chain.isString("tokenizer")) {
className = chain.getString("tokenizer");
- t = null;
+ sub = null;
} else {
- Object o = chain.getAndRemoveRaw("tokenizer");
- if ((o instanceof JSONObject) == false) {
- chain.fail("tokenizer", "must be string or struct; got: " + o.getClass());
- }
- t = (JSONObject) o;
-
- o = t.get("class");
- if ((o instanceof String) == false) {
- chain.fail("tokenizer", "class must be string; got: " + o.getClass());
- }
-
- className = (String) o;
+ sub = chain.getStruct("tokenizer");
+
+ className = sub.getString("class");
}
TokenizerFactory tokenizerFactory;
if (className.toLowerCase(Locale.ROOT).equals("icu")) {
- tokenizerFactory = buildICUTokenizerFactory(t);
+ tokenizerFactory = buildICUTokenizerFactory(sub);
} else {
- Map<String,String> factoryArgs = new HashMap<String,String>();
- // nocommit how to allow the SPI name and separately
- // also a fully qualified class name ...
- factoryArgs.put("class", className);
- factoryArgs.put("luceneMatchVersion", matchVersion.toString());
- if (t != null) {
- for(Map.Entry<String,Object> ent : t.entrySet()) {
- factoryArgs.put(ent.getKey(), ent.getValue().toString());
- }
- }
+
+ TwoThings<Map<String,String>,ResourceLoader> things = parseArgsAndResources(state, className, matchVersion, sub);
try {
- tokenizerFactory = TokenizerFactory.forName(className, factoryArgs);
+ tokenizerFactory = TokenizerFactory.forName(className, things.a);
} catch (IllegalArgumentException iae) {
chain.fail("tokenizer", "failed to create TokenizerFactory for class \"" + className + "\": " + iae, iae);
@@ -918,27 +983,31 @@ public class RegisterFieldHandler extend
}
if (tokenizerFactory instanceof ResourceLoaderAware) {
- // nocommit also do RAM wrapping resource loader here:
- ((ResourceLoaderAware) tokenizerFactory).inform(state.resourceLoader);
+ // nocommit need test case that requires a
+ // xxxFileContents to a Tokenizer
+ ((ResourceLoaderAware) tokenizerFactory).inform(things.b);
}
}
+ return tokenizerFactory;
+ }
+
+ static List<TokenFilterFactory> parseTokenFilters(IndexState state, Version matchVersion, Request chain) throws IOException {
+
// Build TokenFilters
List<TokenFilterFactory> tokenFilterFactories;
if (chain.hasParam("tokenFilters")) {
tokenFilterFactories = new ArrayList<TokenFilterFactory>();
for(Object o : chain.getList("tokenFilters")) {
String paramName = "tokenFilters[" + tokenFilterFactories.size() + "]";
-
+ String className;
Request sub;
if (o instanceof String) {
className = (String) o;
sub = null;
} else {
- if ((o instanceof Request) == false) {
- // nocommit make sure test hits this
- chain.fail(paramName, "each filter must be string or struct; got: " + o.getClass());
- }
+ // The type already validated this:
+ assert o instanceof Request;
sub = (Request) o;
className = sub.getString("class");
@@ -952,75 +1021,10 @@ public class RegisterFieldHandler extend
}
tokenFilterFactory = buildSynonymFilterFactory(state, new Request(chain, paramName, sub.getRawParams(), SYNONYM_FILTER_TYPE));
} else {
-
- Map<String,String> factoryArgs = new HashMap<String,String>();
-
- // nocommit how to allow the SPI name and separately
- // also a fully qualified class name ...
- factoryArgs.put("class", className);
- factoryArgs.put("luceneMatchVersion", matchVersion.toString());
-
- ResourceLoader resources = state.resourceLoader;
- RAMResourceLoaderWrapper ramResources = null;
-
- if (sub != null) {
- for(Map.Entry<String,Object> ent : sub.getRawParams().entrySet()) {
- String argName = ent.getKey();
- Object argValue = ent.getValue();
-
- // Messy: allow components that expect files for
- // things like stopword lists, keywords, to come
- // in as inlined string values. We "hijack" any
- // argument name ending in FileContents and make a RAM
- // file out of it:
- String argString;
-
- if (argName.endsWith("FileContents")) {
- if (ramResources == null) {
- ramResources = new RAMResourceLoaderWrapper(resources);
- resources = ramResources;
- }
-
- String value;
- if (argValue instanceof String) {
- value = (String) argValue;
- } else if (argValue instanceof JSONArray) {
- StringBuilder b = new StringBuilder();
- for(Object v : (JSONArray) argValue) {
- if ((v instanceof String) == false) {
- sub.fail(argName, "array must contain strings; got: " + v.getClass().getSimpleName());
- }
- b.append((String) v);
- b.append('\n');
- }
- value = b.toString();
- } else {
- sub.fail(argName, "must be a String or JSONArray; got: " + argValue.getClass().getSimpleName());
-
- // Dead code but compiler disagrees:
- value = null;
- }
-
- argName = argName.substring(0, argName.length()-12);
- ramResources.add(argName, value);
- argString = argName;
- } else {
- argString = argValue.toString();
- }
-
- factoryArgs.put(argName, argString);
- }
-
- // Clear all bindings from the incoming request,
- // so that they are not seen as unused by the
- // server. If any params are really unused, the
- // analysis factory should throw its own
- // IllegalArgumentException:
- sub.clearParams();
- }
-
+ TwoThings<Map<String,String>,ResourceLoader> things = parseArgsAndResources(state, className, matchVersion, sub);
+
try {
- tokenFilterFactory = TokenFilterFactory.forName(className, factoryArgs);
+ tokenFilterFactory = TokenFilterFactory.forName(className, things.a);
} catch (IllegalArgumentException iae) {
chain.fail("tokenizer", "failed to create TokenFilterFactory for class \"" + className + "\": " + iae, iae);
@@ -1029,7 +1033,7 @@ public class RegisterFieldHandler extend
}
if (tokenFilterFactory instanceof ResourceLoaderAware) {
- ((ResourceLoaderAware) tokenFilterFactory).inform(resources);
+ ((ResourceLoaderAware) tokenFilterFactory).inform(things.b);
}
}
@@ -1039,8 +1043,16 @@ public class RegisterFieldHandler extend
tokenFilterFactories = null;
}
- return new CustomAnalyzer(charFilters,
- tokenizerFactory, tokenFilterFactories,
+ return tokenFilterFactories;
+ }
+
+ static Analyzer buildCustomAnalyzer(IndexState state, Version matchVersion, Request chain) throws IOException {
+
+ // nocommit what is MultiTermAwareComponent?
+
+ return new CustomAnalyzer(parseCharFilters(state, matchVersion, chain),
+ parseTokenizer(state, matchVersion, chain),
+ parseTokenFilters(state, matchVersion, chain),
chain.getInt("positionIncrementGap"),
chain.getInt("offsetGap"));
}
@@ -1048,7 +1060,7 @@ public class RegisterFieldHandler extend
private static SynonymMap parseSynonyms(List<Object> syns, Analyzer a) {
try {
// nocommit this is awkward! I just want to use Parser's
- // analyze utility method...
+ // analyze utility method... if the Parser could just take the JSONObject...
SynonymMap.Parser parser = new SynonymMap.Parser(true, a) {
@Override
public void parse(Reader in) throws IOException {
@@ -1081,9 +1093,8 @@ public class RegisterFieldHandler extend
}
/** An analyzer based on the custom charFilter, tokenizer,
- * tokenFilters chains specified when the field was
- * registered. */
-
+ * tokenFilters factory chains specified when the field
+ * was registered. */
private static class CustomAnalyzer extends Analyzer {
private final int posIncGap;
private final int offsetGap;
Modified: lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/OrType.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/OrType.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/OrType.java (original)
+++ lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/OrType.java Mon Jan 20 11:56:10 2014
@@ -43,9 +43,9 @@ public class OrType extends Type {
if (i != 0) {
sb.append(", ");
}
- sb.append(types[i]);
+ sb.append(types[i].getClass().getSimpleName());
}
- sb.append(", but got " + o.getClass());
+ sb.append(", but got " + o.getClass().getSimpleName());
throw new IllegalArgumentException(sb.toString());
}
Modified: lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/Request.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/Request.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/Request.java (original)
+++ lucene/dev/branches/lucene5376/lucene/server/src/java/org/apache/lucene/server/params/Request.java Mon Jan 20 11:56:10 2014
@@ -56,7 +56,7 @@ public class Request {
* reporting. */
private final String name;
- /** Sole constructor. */
+ /** Creates this. */
public Request(Request parent, String name, JSONObject params, StructType type) {
this.params = params;
this.type = type;
@@ -64,6 +64,15 @@ public class Request {
this.name = name;
}
+ /** Creates Request from another Request, changing the
+ * struct type. */
+ public Request(Request other, StructType type) {
+ this.params = other.params;
+ this.type = type;
+ this.parent = other.parent;
+ this.name = other.name;
+ }
+
/** Clears all parameters. */
public void clearParams() {
params.clear();
@@ -420,6 +429,9 @@ public class Request {
if (pType instanceof WrapType) {
pType = ((WrapType) pType).getWrappedType();
}
+ if (pType instanceof StructType == false) {
+ pType = findStructType(pType);
+ }
assert pType instanceof StructType: "name \"" + name + "\" is not StructType: got " + type;
Object v = params.get(name);
@@ -472,6 +484,13 @@ public class Request {
}
}
}
+ } else if (t instanceof OrType) {
+ OrType ot = (OrType) t;
+ for(Type t2 : ot.types) {
+ if (t2 instanceof StructType) {
+ return (StructType) t2;
+ }
+ }
}
return null;
@@ -535,7 +554,7 @@ public class Request {
try {
((ListType) p.type).subType.validate(o);
} catch (IllegalArgumentException iae) {
- fail(name, iae.getMessage(), iae);
+ fail(name + "[" + idx + "]", iae.getMessage(), iae);
}
}
subs.add(o);
Modified: lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/ServerBaseTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/ServerBaseTestCase.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/ServerBaseTestCase.java (original)
+++ lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/ServerBaseTestCase.java Mon Jan 20 11:56:10 2014
@@ -505,13 +505,19 @@ public abstract class ServerBaseTestCase
return sb.toString();
}
- protected void assertFailsWith(String command, String args, String fragment) throws Exception {
+ /** Sends the command + args, expecting a failure such
+ * that all fragments occur in the failure message
+ * string. Use this to verify a failure case is hitting
+ * the right error messages back to the user. */
+ protected void assertFailsWith(String command, String args, String... fragments) throws Exception {
try {
send(command, args);
fail("did not hit expected exception");
} catch (IOException ioe) {
- if (ioe.getMessage().contains(fragment) == false) {
- fail("expected: " + fragment + "\nactual: \"" + ioe.getMessage());
+ for(String fragment : fragments) {
+ if (ioe.getMessage().contains(fragment) == false) {
+ fail("expected: " + fragment + "\nactual: \"" + ioe.getMessage());
+ }
}
}
}
Modified: lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/TestAnalysis.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/TestAnalysis.java?rev=1559670&r1=1559669&r2=1559670&view=diff
==============================================================================
--- lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/TestAnalysis.java (original)
+++ lucene/dev/branches/lucene5376/lucene/server/src/test/org/apache/lucene/server/TestAnalysis.java Mon Jan 20 11:56:10 2014
@@ -94,6 +94,32 @@ public class TestAnalysis extends Server
assertEquals("the dogs go", justTokens());
}
+ public void testBadCharFilterSpec() throws Exception {
+ assertFailsWith("analyze",
+ "{text: abc, analyzer: {charFilters: [17], tokenizer: Whitespace}}",
+ "analyze > analyzer > charFilters[0]: expected one of StringType, StructType, but got Integer");
+ }
+
+ public void testNonExistentCharFilter() throws Exception {
+ assertFailsWith("analyze",
+ "{text: abc, analyzer: {charFilters: [Bad], tokenizer: Whitespace}}",
+ "analyze > analyzer > charFilters[0]",
+ "A SPI class of type org.apache.lucene.analysis.util.CharFilterFactory with name 'Bad' does not exist");
+ }
+
+ public void testPatternReplaceCharFilter() throws Exception {
+ send("analyze",
+ "{text: foo bar, analyzer: {charFilters: [{class: PatternReplace, pattern: foo, replacement: bar}], tokenizer: Whitespace}}");
+ assertEquals("bar bar", justTokens());
+ }
+
+ /** Exercises the xxxFileContents hack, for a char filter */
+ public void testMappingCharFilter() throws Exception {
+ send("analyze",
+ "{text: foo bar, analyzer: {charFilters: [{class: Mapping, mappingFileContents: '\"bar\" => \"foo\"'}], tokenizer: Whitespace}}");
+ assertEquals("foo foo", justTokens());
+ }
+
public void testPositionIncrementGap() throws Exception {
curIndexName = "posinc";
_TestUtil.rmDir(new File("posinc"));