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 2017/06/23 14:14:42 UTC

[5/6] lucene-solr:master: SOLR-10503, SOLR-10502: Deprecate CurrencyField in favor of new CurrencyFieldType, which works with point fields and provides control over dynamic fields used for the raw amount and currency code sub-fields.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java b/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
index 2d16108..2b6cbf6 100644
--- a/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
+++ b/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
@@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory;
 
 /**
  * <p>
- * Exchange Rates Provider for {@link CurrencyField} capable of fetching &amp; 
+ * Exchange Rates Provider for {@link CurrencyField} and {@link CurrencyFieldType} capable of fetching &amp; 
  * parsing the freely available exchange rates from openexchangerates.org
  * </p>
  * <p>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
index b599272..7d6d162 100644
--- a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
@@ -47,7 +47,7 @@ import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.schema.CurrencyField;
+import org.apache.solr.schema.CurrencyFieldType;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.StrField;
@@ -444,11 +444,11 @@ public abstract class ValueSourceParser implements NamedListInitializedPlugin {
 
         String fieldName = fp.parseArg();
         SchemaField f = fp.getReq().getSchema().getField(fieldName);
-        if (! (f.getType() instanceof CurrencyField)) {
+        if (! (f.getType() instanceof CurrencyFieldType)) {
           throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                                  "Currency function input must be the name of a CurrencyField: " + fieldName);
+                                  "Currency function input must be the name of a CurrencyFieldType: " + fieldName);
         }
-        CurrencyField ft = (CurrencyField) f.getType();
+        CurrencyFieldType ft = (CurrencyFieldType) f.getType();
         String code = fp.hasMoreArguments() ? fp.parseArg() : null;
         return ft.getConvertedValueSource(code, ft.getValueSource(f, fp));
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-amount-suffix.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-amount-suffix.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-amount-suffix.xml
new file mode 100644
index 0000000..bafdb37
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-amount-suffix.xml
@@ -0,0 +1,34 @@
+<?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="bad-schema-currency-ft-amount-suffix" version="1.4">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" multiValued="false"/>
+  
+  <!-- BEGIN BAD STUFF: amountLongSuffix not allowed -->
+  <fieldType name="currency" class="solr.CurrencyField" amountLongSuffix="_l" multiValued="false"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  <field name="money" type="currency" indexed="true" stored="true"/>
+  
+  <dyanmicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-code-suffix.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-code-suffix.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-code-suffix.xml
new file mode 100644
index 0000000..06973f4
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-code-suffix.xml
@@ -0,0 +1,33 @@
+<?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="bad-schema-currency-ft-code-suffix" version="1.4">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  
+  <!-- BEGIN BAD STUFF: codeStrSuffix not allowed -->
+  <fieldType name="currency" class="solr.CurrencyField" codeStrSuffix="_s" multiValued="false"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  <field name="money" type="currency" indexed="true" stored="true"/>
+  
+  <dyanmicField name="*_s" type="string" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-oer-norates.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-oer-norates.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-oer-norates.xml
index 539f503..a1d664c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-oer-norates.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currency-ft-oer-norates.xml
@@ -18,7 +18,7 @@
 
 <schema name="bad-schema-currency-ft-oer-norates" version="1.4">
   <fieldType name="string" class="solr.StrField" multiValued="true"/>
-  <!-- BEGIN BAD STUFF: multiValued -->
+  <!-- BEGIN BAD STUFF: no rates-->
   <fieldType name="currency"
              class="solr.CurrencyField"
              providerClass="solr.OpenExchangeRatesOrgProvider"

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-amount-suffix.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-amount-suffix.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-amount-suffix.xml
new file mode 100644
index 0000000..37b6d20
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-amount-suffix.xml
@@ -0,0 +1,34 @@
+<?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="bad-schema-currencyfieldtype-bogus-amount-suffix" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: bogus amount field suffix -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             amountLongSuffix="_NOT_THERE" codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-code-suffix.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-code-suffix.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-code-suffix.xml
new file mode 100644
index 0000000..7172455
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-bogus-code-suffix.xml
@@ -0,0 +1,35 @@
+<?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="bad-schema-currencyfieldtype-bogus-code-suffix" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: bogus code field suffix -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             amountLongSuffix="_l" codeStrSuffix="_NOT_THERE"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-dynamic-multivalued.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-dynamic-multivalued.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-dynamic-multivalued.xml
new file mode 100644
index 0000000..2fba82a
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-dynamic-multivalued.xml
@@ -0,0 +1,36 @@
+<?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="bad-schema-currencyfieldtype-dynamic-multivalued" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             amountLongSuffix="_l" codeStrSuffix="_s"/>
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <!-- BEGIN BAD STUFF: multiValued="true" -->
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true" multiValued="true"/>
+  <!-- END BAD STUFF -->
+
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-code-in-xml.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-code-in-xml.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-code-in-xml.xml
new file mode 100644
index 0000000..3b5c695
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-code-in-xml.xml
@@ -0,0 +1,41 @@
+<?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="bad-schema-currencyfieldtype-ft-bogus-code-in-xml" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+  
+  <!-- BEGIN BAD STUFF: bad-currency.xml has bogus code-->
+  <fieldType name="currency"
+             class="solr.CurrencyFieldType"
+             defaultCurrency="USD"
+             currencyConfig="bad-currency.xml"
+             multiValued="false"
+             amountLongSuffix="_l" 
+             codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+  
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  <field name="money" type="currency" indexed="true" stored="true"/>
+
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-default-code.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-default-code.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-default-code.xml
new file mode 100644
index 0000000..2748372
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-bogus-default-code.xml
@@ -0,0 +1,41 @@
+<?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="bad-schema-currencyfieldtype-ft-bogus-default-code" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: defaultCurrency -->
+  <fieldType name="currency"
+             class="solr.CurrencyFieldType"
+             defaultCurrency="HOSS"
+             currencyConfig="currency.xml"
+             multiValued="false"
+             amountLongSuffix="_l" 
+             codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+  
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  <field name="money" type="currency" indexed="true" stored="true"/>
+
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-multivalued.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-multivalued.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-multivalued.xml
new file mode 100644
index 0000000..6afcea4
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-multivalued.xml
@@ -0,0 +1,36 @@
+<?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="bad-schema-currencyfieldtype-ft-multivalued" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+  
+  <!-- BEGIN BAD STUFF: multiValued -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="true"
+             amountLongSuffix="_l" codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  <field name="money" type="currency" indexed="true" stored="true"/>
+
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-oer-norates.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-oer-norates.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-oer-norates.xml
new file mode 100644
index 0000000..8d8533d
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-ft-oer-norates.xml
@@ -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="bad-schema-currencyfieldtype-ft-oer-norates" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: no rates -->
+  <fieldType name="currency"
+             class="solr.CurrencyFieldType"
+             providerClass="solr.OpenExchangeRatesOrgProvider"
+             multiValued="false"
+             amountLongSuffix="_l" 
+             codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+  
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  <field name="money" type="currency" indexed="true" stored="true"/>
+
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-amount-suffix.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-amount-suffix.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-amount-suffix.xml
new file mode 100644
index 0000000..77a531d
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-amount-suffix.xml
@@ -0,0 +1,34 @@
+<?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="bad-schema-currencyfieldtype-missing-amount-suffix" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+
+  <!-- BEGIN BAD STUFF: missing amountLongSuffix -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-code-suffix.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-code-suffix.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-code-suffix.xml
new file mode 100644
index 0000000..89c7080
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-missing-code-suffix.xml
@@ -0,0 +1,35 @@
+<?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="bad-schema-currencyfieldtype-missing-code-suffix" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: missing codeStrSuffix -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             amountLongSuffix="_l"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-multivalued.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-multivalued.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-multivalued.xml
new file mode 100644
index 0000000..9e95458
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-multivalued.xml
@@ -0,0 +1,36 @@
+<?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="bad-schema-currencyfieldtype-multivalued" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml"
+             amountLongSuffix="_l" codeStrSuffix="_s"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <!-- BEGIN BAD STUFF: multiValued="true" -->
+  <field name="money" type="currency" indexed="true" stored="true" multiValued="true"/>
+  <!-- END BAD STUFF -->
+
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-amount-ft.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-amount-ft.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-amount-ft.xml
new file mode 100644
index 0000000..5188190
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-amount-ft.xml
@@ -0,0 +1,36 @@
+<?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="bad-schema-currencyfieldtype-wrong-amount-ft" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: code dynamic field type is wrong -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             amountLongSuffix="_s" codeStrSuffix="_s"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <dynamicField name="*_s" type="string" multiValued="false"/>
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-code-ft.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-code-ft.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-code-ft.xml
new file mode 100644
index 0000000..c3eadc1
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-currencyfieldtype-wrong-code-ft.xml
@@ -0,0 +1,35 @@
+<?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="bad-schema-currencyfieldtype-wrong-code-ft" version="1.6">
+  <fieldType name="string" class="solr.StrField" multiValued="true"/>
+  <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+  <!-- BEGIN BAD STUFF: code dynamic field type is wrong -->
+  <fieldType name="currency" class="solr.CurrencyFieldType" currencyConfig="currency.xml" multiValued="false"
+             amountLongSuffix="_l" codeStrSuffix="_l"/>
+  <!-- END BAD STUFF -->
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false"/>
+  
+  <dynamicField name="*_l" type="plong" multiValued="false"/>
+  <dynamicField name="*_c" type="currency" indexed="true" stored="true"/>
+
+  <uniqueKey>id</uniqueKey>
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test-files/solr/collection1/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema.xml b/solr/core/src/test-files/solr/collection1/conf/schema.xml
index 23c1045..4aaef48 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema.xml
@@ -451,6 +451,17 @@
              multiValued="false"
              providerClass="solr.OpenExchangeRatesOrgProvider"
              ratesFileLocation="open-exchange-rates.json"/>
+  <fieldType name="currency_CFT" class="solr.CurrencyFieldType" amountLongSuffix="_l1_ns" codeStrSuffix="_s1"
+             currencyConfig="currency.xml" multiValued="false"/>
+  <fieldType name="mock_currency_CFT" class="solr.CurrencyFieldType" amountLongSuffix="_l1_ns" codeStrSuffix="_s1"
+             providerClass="solr.MockExchangeRateProvider" foo="bar" multiValued="false"/>
+  <fieldType name="oer_currency_CFT"
+             class="solr.CurrencyFieldType"
+             amountLongSuffix="_l1_ns"
+             codeStrSuffix="_s1_ns"
+             multiValued="false"
+             providerClass="solr.OpenExchangeRatesOrgProvider"
+             ratesFileLocation="open-exchange-rates.json"/>
 
   <!-- omitPositions example -->
   <fieldType name="nopositions" class="solr.TextField" omitPositions="true">
@@ -539,6 +550,9 @@
   <field name="amount" type="currency" indexed="true" stored="true" multiValued="false"/>
   <field name="mock_amount" type="mock_currency" indexed="true" stored="true"/>
   <field name="oer_amount" type="oer_currency" indexed="true" stored="true"/>
+  <field name="amount_CFT" type="currency_CFT" indexed="true" stored="true" multiValued="false"/>
+  <field name="mock_amount_CFT" type="mock_currency_CFT" indexed="true" stored="true"/>
+  <field name="oer_amount_CFT" type="oer_currency_CFT" indexed="true" stored="true"/>
 
   <!-- test different combinations of indexed and stored -->
   <field name="bind" type="boolean" indexed="true" stored="false"/>
@@ -652,8 +666,10 @@
 
   <dynamicField name="*_s" type="string" indexed="true" stored="true"/>
   <dynamicField name="*_s1" type="string" indexed="true" stored="true" multiValued="false"/>
+  <dynamicField name="*_s1_ns" type="string" indexed="true" stored="false" multiValued="false"/>
   <dynamicField name="*_l" type="long" indexed="true" stored="true"/>
   <dynamicField name="*_l1" type="long" indexed="true" stored="true" multiValued="false"/>
+  <dynamicField name="*_l1_ns" type="long" indexed="true" stored="false" multiValued="false"/>
   <dynamicField name="*_t" type="text" indexed="true" stored="true"/>
   <dynamicField name="*_b" type="boolean" indexed="true" stored="true"/>
   <dynamicField name="*_b1" type="boolean" indexed="true" stored="true" multiValued="false"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test/org/apache/solr/schema/AbstractCurrencyFieldTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/AbstractCurrencyFieldTest.java b/solr/core/src/test/org/apache/solr/schema/AbstractCurrencyFieldTest.java
deleted file mode 100644
index be719db..0000000
--- a/solr/core/src/test/org/apache/solr/schema/AbstractCurrencyFieldTest.java
+++ /dev/null
@@ -1,426 +0,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.
- */
-package org.apache.solr.schema;
-import java.util.Currency;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-import org.apache.lucene.index.IndexableField;
-import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.util.RTimer;
-import org.junit.Assume;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * Tests currency field type.
- * @see #field
- */
-@Ignore("Abstract base class with test methods")
-public abstract class AbstractCurrencyFieldTest extends SolrTestCaseJ4 {
-
-  /**
-   * "Assumes" that the specified list of currency codes are
-   * supported in this JVM
-   */
-  public static void assumeCurrencySupport(String... codes) {
-    try {
-      // each JDK might have a diff list of supported currencies,
-      // these are the ones needed for this test to work.
-      for (String code : codes) {
-        Currency obj = Currency.getInstance(code);
-        assertNotNull(code, obj);
-      }
-    } catch (IllegalArgumentException e) {
-      Assume.assumeNoException(e);
-    }
-
-  }
-  @BeforeClass
-  public static void beforeClass() throws Exception {
-    assumeCurrencySupport("USD", "EUR", "MXN", "GBP", "JPY", "NOK");
-    initCore("solrconfig.xml", "schema.xml");
-  }
-
-  /** The field name to use in all tests */
-  public abstract String field();
-
-  @Test
-  public void testCurrencySchema() throws Exception {
-    IndexSchema schema = h.getCore().getLatestSchema();
-
-    SchemaField amount = schema.getField(field());
-    assertNotNull(amount);
-    assertTrue(amount.isPolyField());
-
-    SchemaField[] dynFields = schema.getDynamicFieldPrototypes();
-    boolean seenCurrency = false;
-    boolean seenAmount = false;
-
-    for (SchemaField dynField : dynFields) {
-      if (dynField.getName().equals("*" + FieldType.POLY_FIELD_SEPARATOR + CurrencyField.FIELD_SUFFIX_CURRENCY)) {
-        seenCurrency = true;
-      }
-
-      if (dynField.getName().equals("*" + FieldType.POLY_FIELD_SEPARATOR + CurrencyField.FIELD_SUFFIX_AMOUNT_RAW)) {
-        seenAmount = true;
-      }
-    }
-
-    assertTrue("Didn't find the expected currency code dynamic field", seenCurrency);
-    assertTrue("Didn't find the expected value dynamic field", seenAmount);
-  }
-
-  @Test
-  public void testCurrencyFieldType() throws Exception {
-    SolrCore core = h.getCore();
-    IndexSchema schema = core.getLatestSchema();
-    SchemaField amount = schema.getField(field());
-    assertNotNull(amount);
-    assertTrue(field() + " is not a poly field", amount.isPolyField());
-    FieldType tmp = amount.getType();
-    assertTrue(tmp instanceof CurrencyField);
-    String currencyValue = "1.50,EUR";
-    List<IndexableField> fields = amount.createFields(currencyValue);
-    assertEquals(fields.size(), 3);
-
-    // First field is currency code, second is value, third is stored.
-    for (int i = 0; i < 3; i++) {
-      boolean hasValue = fields.get(i).readerValue() != null
-              || fields.get(i).numericValue() != null
-              || fields.get(i).stringValue() != null;
-      assertTrue("Doesn't have a value: " + fields.get(i), hasValue);
-    }
-
-    assertEquals(schema.getFieldTypeByName("string").toExternal(fields.get(2)), "1.50,EUR");
-    
-    // A few tests on the provider directly
-    ExchangeRateProvider p = ((CurrencyField) tmp).getProvider();
-    Set<String> availableCurrencies = p.listAvailableCurrencies();
-    assertEquals(5, availableCurrencies.size());
-    assert(p.reload() == true);
-    assert(p.getExchangeRate("USD", "EUR") == 2.5);
-  }
-
-  @Test
-  public void testMockExchangeRateProvider() throws Exception {
-    SolrCore core = h.getCore();
-    IndexSchema schema = core.getLatestSchema();
-    SchemaField amount = schema.getField("mock_amount");
-
-    // A few tests on the provider directly
-    ExchangeRateProvider p = ((CurrencyField)amount.getType()).getProvider();
-    Set<String> availableCurrencies = p.listAvailableCurrencies();
-    assert(availableCurrencies.size() == 3);
-    assert(p.reload() == true);
-    assert(p.getExchangeRate("USD", "EUR") == 0.8);
-  }
-
-  @Test
-  public void testCurrencyRangeSearch() throws Exception {
-    clearIndex();
-    final int emptyDocs = atLeast(50); // times 2
-    final int negDocs = atLeast(5);
-    
-    assertU(adoc("id", "0", field(), "0,USD")); // 0
-    // lots of docs w/o values
-    for (int i = 100; i <= 100 + emptyDocs; i++) {
-      assertU(adoc("id", "" + i));
-    }
-    // docs with values in ranges we'll query
-    for (int i = 1; i <= 10; i++) {
-      assertU(adoc("id", "" + i, field(), i + ",USD"));
-    }
-    // more docs w/o values
-    for (int i = 500; i <= 500 + emptyDocs; i++) {
-      assertU(adoc("id", "" + i));
-    }
-    // some negative values
-    for (int i = -100; i > -100 - negDocs; i--) {
-      assertU(adoc("id", "" + i, field(), i + ",USD"));
-    }
-    assertU(adoc("id", "40", field(), "0,USD")); // 0
-
-    assertU(commit());
-
-    assertQ(req("fl", "*,score", "q",
-            field()+":[2.00,USD TO 5.00,USD]"),
-            "//*[@numFound='4']");
-
-    assertQ(req("fl", "*,score", "q",
-            field()+":[0.50,USD TO 1.00,USD]"),
-            "//*[@numFound='1']");
-
-    assertQ(req("fl", "*,score", "q",
-            field()+":[24.00,USD TO 25.00,USD]"),
-            "//*[@numFound='0']");
-
-    // "GBP" currency code is 1/2 of a USD dollar, for testing.
-    assertQ(req("fl", "*,score", "q",
-            field()+":[0.50,GBP TO 1.00,GBP]"),
-            "//*[@numFound='2']");
-
-    // "EUR" currency code is 2.5X of a USD dollar, for testing.
-    assertQ(req("fl", "*,score", "q",
-            field()+":[24.00,EUR TO 25.00,EUR]"),
-            "//*[@numFound='1']");
-
-    // Slight asymmetric rate should work.
-    assertQ(req("fl", "*,score", "q",
-            field()+":[24.99,EUR TO 25.01,EUR]"),
-            "//*[@numFound='1']");
-    
-    // Open ended ranges without currency
-    assertQ(req("fl", "*,score", "q",
-            field()+":[* TO *]"),
-            "//*[@numFound='" + (2 + 10 + negDocs) + "']");
-    
-    // Open ended ranges with currency
-    assertQ(req("fl", "*,score", "q",
-            field()+":[*,EUR TO *,EUR]"),
-            "//*[@numFound='" + (2 + 10 + negDocs) + "']");
-
-    // Open ended start range without currency
-    assertQ(req("fl", "*,score", "q",
-            field()+":[* TO 5,USD]"),
-            "//*[@numFound='" + (2 + 5 + negDocs) + "']");
-
-    // Open ended start range with currency (currency for the * won't matter)
-    assertQ(req("fl", "*,score", "q",
-            field()+":[*,USD TO 5,USD]"),
-            "//*[@numFound='" + (2 + 5 + negDocs) + "']");
-
-    // Open ended end range
-    assertQ(req("fl", "*,score", "q",
-            field()+":[3 TO *]"),
-            "//*[@numFound='8']");
-  }
-
-  @Test
-  public void testBogusCurrency() throws Exception {
-    ignoreException("HOSS");
-
-    // bogus currency
-    assertQEx("Expected exception for invalid currency",
-              req("fl", "*,score", "q",
-                  field()+":[3,HOSS TO *]"),
-              400);
-  }
-
-  @Test
-  public void testCurrencyPointQuery() throws Exception {
-    clearIndex();
-    assertU(adoc("id", "" + 1, field(), "10.00,USD"));
-    assertU(adoc("id", "" + 2, field(), "15.00,MXN"));
-    assertU(commit());
-    assertQ(req("fl", "*,score", "q", field()+":10.00,USD"), "//str[@name='id']='1'");
-    assertQ(req("fl", "*,score", "q", field()+":9.99,USD"), "//*[@numFound='0']");
-    assertQ(req("fl", "*,score", "q", field()+":10.01,USD"), "//*[@numFound='0']");
-    assertQ(req("fl", "*,score", "q", field()+":15.00,MXN"), "//str[@name='id']='2'");
-    assertQ(req("fl", "*,score", "q", field()+":7.50,USD"), "//str[@name='id']='2'");
-    assertQ(req("fl", "*,score", "q", field()+":7.49,USD"), "//*[@numFound='0']");
-    assertQ(req("fl", "*,score", "q", field()+":7.51,USD"), "//*[@numFound='0']");
-  }
-
-  @Ignore
-  public void testPerformance() throws Exception {
-    clearIndex();
-
-    Random r = random();
-    int initDocs = 200000;
-
-    for (int i = 1; i <= initDocs; i++) {
-      assertU(adoc("id", "" + i, field(), (r.nextInt(10) + 1.00) + ",USD"));
-      if (i % 1000 == 0)
-        System.out.println(i);
-    }
-
-    assertU(commit());
-    for (int i = 0; i < 1000; i++) {
-      double lower = r.nextInt(10) + 1.00;
-      assertQ(req("fl", "*,score", "q", field()+":[" +  lower + ",USD TO " + (lower + 10.00) + ",USD]"), "//*");
-      assertQ(req("fl", "*,score", "q", field()+":[" +  lower + ",EUR TO " + (lower + 10.00) + ",EUR]"), "//*");
-    }
-
-    for (int j = 0; j < 3; j++) {
-      final RTimer timer = new RTimer();
-      for (int i = 0; i < 1000; i++) {
-        double lower = r.nextInt(10) + 1.00;
-        assertQ(req("fl", "*,score", "q", field()+":[" +  lower + ",USD TO " + (lower + (9.99 - (j * 0.01))) + ",USD]"), "//*");
-      }
-
-      System.out.println(timer.getTime());
-    }
-
-    System.out.println("---");
-
-    for (int j = 0; j < 3; j++) {
-      final RTimer timer = new RTimer();
-      for (int i = 0; i < 1000; i++) {
-        double lower = r.nextInt(10) + 1.00;
-        assertQ(req("fl", "*,score", "q", field()+":[" +  lower + ",EUR TO " + (lower + (9.99 - (j * 0.01))) + ",EUR]"), "//*");
-      }
-
-      System.out.println(timer.getTime());
-    }
-  }
-
-  @Test
-  public void testCurrencySort() throws Exception {
-    clearIndex();
-
-    assertU(adoc("id", "" + 1, field(), "10.00,USD"));
-    assertU(adoc("id", "" + 2, field(), "15.00,EUR"));
-    assertU(adoc("id", "" + 3, field(), "7.00,EUR"));
-    assertU(adoc("id", "" + 4, field(), "6.00,GBP"));
-    assertU(adoc("id", "" + 5, field(), "2.00,GBP"));
-    assertU(commit());
-
-    assertQ(req("fl", "*,score", "q", "*:*", "sort", field()+" desc", "limit", "1"), "//str[@name='id']='4'");
-    assertQ(req("fl", "*,score", "q", "*:*", "sort", field()+" asc", "limit", "1"), "//str[@name='id']='3'");
-  }
-
-  public void testFunctionUsage() throws Exception {
-    clearIndex();
-    for (int i = 1; i <= 8; i++) {
-      // "GBP" currency code is 1/2 of a USD dollar, for testing.
-      assertU(adoc("id", "" + i, field(), (((float)i)/2) + ",GBP"));
-    }
-    for (int i = 9; i <= 11; i++) {
-      assertU(adoc("id", "" + i, field(), i + ",USD"));
-    }
-
-    assertU(commit());
-
-    // direct value source usage, gets "raw" form od default currency
-    // default==USD, so raw==penies
-    assertQ(req("fl", "id,func:field($f)",
-                "f", field(),
-                "q", "id:5"),
-            "//*[@numFound='1']",
-            "//doc/float[@name='func' and .=500]");
-    assertQ(req("fl", "id,func:field($f)",
-                "f", field(),
-                "q", "id:10"),
-            "//*[@numFound='1']",
-            "//doc/float[@name='func' and .=1000]");
-    assertQ(req("fl", "id,score,"+field(), 
-                "q", "{!frange u=500}"+field())
-            ,"//*[@numFound='5']"
-            ,"//str[@name='id']='1'"
-            ,"//str[@name='id']='2'"
-            ,"//str[@name='id']='3'"
-            ,"//str[@name='id']='4'"
-            ,"//str[@name='id']='5'"
-            );
-    assertQ(req("fl", "id,score,"+field(), 
-                "q", "{!frange l=500 u=1000}"+field())
-            ,"//*[@numFound='6']"
-            ,"//str[@name='id']='5'"
-            ,"//str[@name='id']='6'"
-            ,"//str[@name='id']='7'"
-            ,"//str[@name='id']='8'"
-            ,"//str[@name='id']='9'"
-            ,"//str[@name='id']='10'"
-            );
-
-    // use the currency function to convert to default (USD)
-    assertQ(req("fl", "id,func:currency($f)",
-                "f", field(),
-                "q", "id:10"),
-            "//*[@numFound='1']",
-            "//doc/float[@name='func' and .=10]");
-    assertQ(req("fl", "id,func:currency($f)",
-                "f", field(),
-                "q", "id:5"),
-            "//*[@numFound='1']",
-            "//doc/float[@name='func' and .=5]");
-    assertQ(req("fl", "id,score"+field(), 
-                "f", field(),
-                "q", "{!frange u=5}currency($f)")
-            ,"//*[@numFound='5']"
-            ,"//str[@name='id']='1'"
-            ,"//str[@name='id']='2'"
-            ,"//str[@name='id']='3'"
-            ,"//str[@name='id']='4'"
-            ,"//str[@name='id']='5'"
-            );
-    assertQ(req("fl", "id,score"+field(), 
-                "f", field(),
-                "q", "{!frange l=5 u=10}currency($f)")
-            ,"//*[@numFound='6']"
-            ,"//str[@name='id']='5'"
-            ,"//str[@name='id']='6'"
-            ,"//str[@name='id']='7'"
-            ,"//str[@name='id']='8'"
-            ,"//str[@name='id']='9'"
-            ,"//str[@name='id']='10'"
-            );
-    
-    // use the currency function to convert to MXN
-    assertQ(req("fl", "id,func:currency($f,MXN)",
-                "f", field(),
-                "q", "id:5"),
-            "//*[@numFound='1']",
-            "//doc/float[@name='func' and .=10]");
-    assertQ(req("fl", "id,func:currency($f,MXN)",
-                "f", field(),
-                "q", "id:10"),
-            "//*[@numFound='1']",
-            "//doc/float[@name='func' and .=20]");
-    assertQ(req("fl", "*,score,"+field(), 
-                "f", field(),
-                "q", "{!frange u=10}currency($f,MXN)")
-            ,"//*[@numFound='5']"
-            ,"//str[@name='id']='1'"
-            ,"//str[@name='id']='2'"
-            ,"//str[@name='id']='3'"
-            ,"//str[@name='id']='4'"
-            ,"//str[@name='id']='5'"
-            );
-    assertQ(req("fl", "*,score,"+field(), 
-                "f", field(),
-                "q", "{!frange l=10 u=20}currency($f,MXN)")
-            ,"//*[@numFound='6']"
-            ,"//str[@name='id']='5'"
-            ,"//str[@name='id']='6'"
-            ,"//str[@name='id']='7'"
-            ,"//str[@name='id']='8'"
-            ,"//str[@name='id']='9'"
-            ,"//str[@name='id']='10'"
-            );
-
-  }
-
-  @Test
-  public void testMockFieldType() throws Exception {
-    clearIndex();
-
-    assertU(adoc("id", "1", "mock_amount", "1.00,USD"));
-    assertU(adoc("id", "2", "mock_amount", "1.00,EUR"));
-    assertU(adoc("id", "3", "mock_amount", "1.00,NOK"));
-    assertU(commit());
-
-    assertQ(req("fl", "*,score", "q", "mock_amount:5.0,NOK"),   "//*[@numFound='1']", "//str[@name='id']='1'");
-    assertQ(req("fl", "*,score", "q", "mock_amount:1.2,USD"), "//*[@numFound='1']",   "//str[@name='id']='2'");
-    assertQ(req("fl", "*,score", "q", "mock_amount:0.2,USD"), "//*[@numFound='1']",   "//str[@name='id']='3'");
-    assertQ(req("fl", "*,score", "q", "mock_amount:99,USD"),  "//*[@numFound='0']");
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test/org/apache/solr/schema/BadIndexSchemaTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/BadIndexSchemaTest.java b/solr/core/src/test/org/apache/solr/schema/BadIndexSchemaTest.java
index b7d00a9..b9dc1aa 100644
--- a/solr/core/src/test/org/apache/solr/schema/BadIndexSchemaTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/BadIndexSchemaTest.java
@@ -68,14 +68,22 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
     doTest("bad-schema-currency-ft-multivalued.xml", 
            "types can not be multiValued: currency");
     doTest("bad-schema-currency-multivalued.xml", 
-           "Fields can not be multiValued: money");
+           "fields can not be multiValued: money");
     doTest("bad-schema-currency-dynamic-multivalued.xml", 
-           "Fields can not be multiValued: *_c");
+           "fields can not be multiValued: *_c");
+    doTest("bad-schema-currencyfieldtype-ft-multivalued.xml",
+        "types can not be multiValued: currency");
+    doTest("bad-schema-currencyfieldtype-multivalued.xml",
+        "fields can not be multiValued: money");
+    doTest("bad-schema-currencyfieldtype-dynamic-multivalued.xml",
+        "fields can not be multiValued: *_c");
   }
 
   public void testCurrencyOERNoRates() throws Exception {
     doTest("bad-schema-currency-ft-oer-norates.xml", 
            "ratesFileLocation");
+    doTest("bad-schema-currencyfieldtype-ft-oer-norates.xml",
+        "ratesFileLocation");
   }
 
   public void testCurrencyBogusCode() throws Exception {
@@ -83,6 +91,35 @@ public class BadIndexSchemaTest extends AbstractBadConfigTestBase {
            "HOSS");
     doTest("bad-schema-currency-ft-bogus-code-in-xml.xml", 
            "HOSS");
+    doTest("bad-schema-currencyfieldtype-ft-bogus-default-code.xml",
+        "HOSS");
+    doTest("bad-schema-currencyfieldtype-ft-bogus-code-in-xml.xml",
+        "HOSS");
+  }
+  
+  public void testCurrencyDisallowedSuffixParams() throws Exception {
+    doTest("bad-schema-currency-ft-code-suffix.xml", 
+        "Unknown parameter(s)");
+    doTest("bad-schema-currency-ft-amount-suffix.xml",
+        "Unknown parameter(s)");
+  }
+  
+  public void testCurrencyBogusSuffixes() throws Exception {
+    doTest("bad-schema-currencyfieldtype-bogus-code-suffix.xml",
+           "Undefined dynamic field for codeStrSuffix");
+    doTest("bad-schema-currencyfieldtype-bogus-amount-suffix.xml",
+           "Undefined dynamic field for amountLongSuffix");
+    doTest("bad-schema-currencyfieldtype-wrong-code-ft.xml",
+           "Dynamic field for codeStrSuffix=\"_l\" must have type class of (or extending) StrField");
+    doTest("bad-schema-currencyfieldtype-wrong-amount-ft.xml",
+           "Dynamic field for amountLongSuffix=\"_s\" must have type class extending LongValueFieldType");
+  } 
+  
+  public void testCurrencyMissingSuffixes() throws Exception {
+    doTest("bad-schema-currencyfieldtype-missing-code-suffix.xml",
+        "Missing required param codeStrSuffix");
+    doTest("bad-schema-currencyfieldtype-missing-amount-suffix.xml",
+        "Missing required param amountLongSuffix");
   }
 
   public void testPerFieldtypeSimButNoSchemaSimFactory() throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test/org/apache/solr/schema/CurrencyFieldOpenExchangeTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldOpenExchangeTest.java b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldOpenExchangeTest.java
deleted file mode 100644
index fed51eb..0000000
--- a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldOpenExchangeTest.java
+++ /dev/null
@@ -1,27 +0,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.
- */
-package org.apache.solr.schema;
-
-/**
- * Tests currency field type using OpenExchangeRatesOrgProvider.
- */
-public class CurrencyFieldOpenExchangeTest extends AbstractCurrencyFieldTest {
-
-  public String field() {
-    return "oer_amount";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java
new file mode 100644
index 0000000..c2f8f2d
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java
@@ -0,0 +1,494 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.schema;
+
+import java.util.Arrays;
+import java.util.Currency;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+import org.apache.lucene.index.IndexableField;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.util.RTimer;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/** Tests CurrencyField and CurrencyFieldType. */
+public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
+  private final String fieldName;
+  private final Class<? extends ExchangeRateProvider> expectedProviderClass;
+  
+  public CurrencyFieldTypeTest(String fieldName, Class<? extends ExchangeRateProvider> expectedProviderClass) {
+    this.fieldName = fieldName;
+    this.expectedProviderClass = expectedProviderClass;
+  }
+
+  @ParametersFactory
+  public static Iterable<Object[]> parameters() {
+    return Arrays.asList(new Object[][] {
+        {"amount", FileExchangeRateProvider.class},    // CurrencyField
+        {"mock_amount", MockExchangeRateProvider.class},                 // CurrencyField
+        {"oer_amount", OpenExchangeRatesOrgProvider.class},              // CurrencyField
+        {"amount_CFT", FileExchangeRateProvider.class},  // CurrencyFieldType
+        {"mock_amount_CFT", MockExchangeRateProvider.class},               // CurrencyFieldType
+        {"oer_amount_CFT", OpenExchangeRatesOrgProvider.class}             // CurrencyFieldType
+      });
+  }
+  
+  /**
+   * "Assumes" that the specified list of currency codes are
+   * supported in this JVM
+   */
+  public static void assumeCurrencySupport(String... codes) {
+    try {
+      // each JDK might have a diff list of supported currencies,
+      // these are the ones needed for this test to work.
+      for (String code : codes) {
+        Currency obj = Currency.getInstance(code);
+        assertNotNull(code, obj);
+      }
+    } catch (IllegalArgumentException e) {
+      Assume.assumeNoException(e);
+    }
+
+  }
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    assumeCurrencySupport("USD", "EUR", "MXN", "GBP", "JPY", "NOK");
+    initCore("solrconfig.xml", "schema.xml");
+  }
+
+  @Test
+  public void testCurrencySchema() throws Exception {
+    IndexSchema schema = h.getCore().getLatestSchema();
+
+    SchemaField amount = schema.getField(fieldName);
+    assertNotNull(amount);
+    assertTrue(amount.isPolyField());
+
+    CurrencyFieldType type = (CurrencyFieldType)amount.getType();
+    String currencyDynamicField
+        = "*" + (type instanceof CurrencyField ? FieldType.POLY_FIELD_SEPARATOR : "") + type.fieldSuffixCurrency;
+    String amountDynamicField 
+        = "*" + (type instanceof CurrencyField ? FieldType.POLY_FIELD_SEPARATOR : "") + type.fieldSuffixAmountRaw;
+
+    SchemaField[] dynFields = schema.getDynamicFieldPrototypes();
+    boolean seenCurrency = false;
+    boolean seenAmount = false;
+
+    for (SchemaField dynField : dynFields) {
+      if (dynField.getName().equals(amountDynamicField)) {
+        seenAmount = true;
+      }
+
+      if (dynField.getName().equals(currencyDynamicField)) {
+        seenCurrency = true;
+      }
+    }
+
+    assertTrue("Didn't find the expected currency code dynamic field " + currencyDynamicField, seenCurrency);
+    assertTrue("Didn't find the expected value dynamic field " + amountDynamicField, seenAmount);
+  }
+
+  @Test
+  public void testCurrencyFieldType() throws Exception {
+    assumeTrue("This test is only applicable to the XML file based exchange rate provider",
+        expectedProviderClass.equals(FileExchangeRateProvider.class));
+
+    SolrCore core = h.getCore();
+    IndexSchema schema = core.getLatestSchema();
+    SchemaField amount = schema.getField(fieldName);
+    assertNotNull(amount);
+    assertTrue(fieldName + " is not a poly field", amount.isPolyField());
+    FieldType tmp = amount.getType();
+    assertTrue(fieldName + " is not an instance of CurrencyFieldType", tmp instanceof CurrencyFieldType);
+    String currencyValue = "1.50,EUR";
+    List<IndexableField> fields = amount.createFields(currencyValue);
+    assertEquals(fields.size(), 3);
+
+    // First field is currency code, second is value, third is stored.
+    for (int i = 0; i < 3; i++) {
+      boolean hasValue = fields.get(i).readerValue() != null
+              || fields.get(i).numericValue() != null
+              || fields.get(i).stringValue() != null;
+      assertTrue("Doesn't have a value: " + fields.get(i), hasValue);
+    }
+
+    assertEquals(schema.getFieldTypeByName("string").toExternal(fields.get(2)), "1.50,EUR");
+    
+    // A few tests on the provider directly
+    ExchangeRateProvider p = ((CurrencyFieldType)tmp).getProvider();
+    Set<String> availableCurrencies = p.listAvailableCurrencies();
+    assertEquals(5, availableCurrencies.size());
+    assertTrue(p.reload());
+    assertEquals(2.5, p.getExchangeRate("USD", "EUR"), 0.00000000001);
+  }
+
+  @Test
+  public void testMockExchangeRateProvider() throws Exception {
+    assumeTrue("This test is only applicable to the mock exchange rate provider",
+        expectedProviderClass.equals(MockExchangeRateProvider.class));
+    
+    SolrCore core = h.getCore();
+    IndexSchema schema = core.getLatestSchema();
+    SchemaField field = schema.getField(fieldName);
+    FieldType fieldType = field.getType();
+    ExchangeRateProvider provider = ((CurrencyFieldType)fieldType).getProvider();
+
+    // A few tests on the provider directly
+    assertEquals(3, provider.listAvailableCurrencies().size());
+    assertTrue(provider.reload());
+    assertEquals(0.8, provider.getExchangeRate("USD", "EUR"), 0.00000000001);
+  }
+
+  @Test
+  public void testCurrencyRangeSearch() throws Exception {
+    assumeTrue("This test is only applicable to the XML file based exchange rate provider",
+        expectedProviderClass.equals(FileExchangeRateProvider.class));
+    
+    clearIndex();
+    final int emptyDocs = atLeast(50); // times 2
+    final int negDocs = atLeast(5);
+    
+    assertU(adoc("id", "0", fieldName, "0,USD")); // 0
+    // lots of docs w/o values
+    for (int i = 100; i <= 100 + emptyDocs; i++) {
+      assertU(adoc("id", "" + i));
+    }
+    // docs with values in ranges we'll query
+    for (int i = 1; i <= 10; i++) {
+      assertU(adoc("id", "" + i, fieldName, i + ",USD"));
+    }
+    // more docs w/o values
+    for (int i = 500; i <= 500 + emptyDocs; i++) {
+      assertU(adoc("id", "" + i));
+    }
+    // some negative values
+    for (int i = -100; i > -100 - negDocs; i--) {
+      assertU(adoc("id", "" + i, fieldName, i + ",USD"));
+    }
+    assertU(adoc("id", "40", fieldName, "0,USD")); // 0
+
+    assertU(commit());
+
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[2.00,USD TO 5.00,USD]"),
+            "//*[@numFound='4']");
+
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[0.50,USD TO 1.00,USD]"),
+            "//*[@numFound='1']");
+
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[24.00,USD TO 25.00,USD]"),
+            "//*[@numFound='0']");
+
+    // "GBP" currency code is 1/2 of a USD dollar, for testing.
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[0.50,GBP TO 1.00,GBP]"),
+            "//*[@numFound='2']");
+
+    // "EUR" currency code is 2.5X of a USD dollar, for testing.
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[24.00,EUR TO 25.00,EUR]"),
+            "//*[@numFound='1']");
+
+    // Slight asymmetric rate should work.
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[24.99,EUR TO 25.01,EUR]"),
+            "//*[@numFound='1']");
+    
+    // Open ended ranges without currency
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[* TO *]"),
+            "//*[@numFound='" + (2 + 10 + negDocs) + "']");
+    
+    // Open ended ranges with currency
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[*,EUR TO *,EUR]"),
+            "//*[@numFound='" + (2 + 10 + negDocs) + "']");
+
+    // Open ended start range without currency
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[* TO 5,USD]"),
+            "//*[@numFound='" + (2 + 5 + negDocs) + "']");
+
+    // Open ended start range with currency (currency for the * won't matter)
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[*,USD TO 5,USD]"),
+            "//*[@numFound='" + (2 + 5 + negDocs) + "']");
+
+    // Open ended end range
+    assertQ(req("fl", "*,score", "q",
+            fieldName+":[3 TO *]"),
+            "//*[@numFound='8']");
+  }
+
+  @Test
+  public void testBogusCurrency() throws Exception {
+    ignoreException("HOSS");
+
+    // bogus currency
+    assertQEx("Expected exception for invalid currency",
+              req("fl", "*,score", "q",
+                  fieldName+":[3,HOSS TO *]"),
+              400);
+  }
+
+  @Test
+  public void testCurrencyPointQuery() throws Exception {
+    assumeTrue("This test is only applicable to the XML file based exchange rate provider",
+        expectedProviderClass.equals(FileExchangeRateProvider.class));
+
+    clearIndex();
+    assertU(adoc("id", "" + 1, fieldName, "10.00,USD"));
+    assertU(adoc("id", "" + 2, fieldName, "15.00,MXN"));
+    assertU(commit());
+    assertQ(req("fl", "*,score", "q", fieldName+":10.00,USD"), "//str[@name='id']='1'");
+    assertQ(req("fl", "*,score", "q", fieldName+":9.99,USD"), "//*[@numFound='0']");
+    assertQ(req("fl", "*,score", "q", fieldName+":10.01,USD"), "//*[@numFound='0']");
+    assertQ(req("fl", "*,score", "q", fieldName+":15.00,MXN"), "//str[@name='id']='2'");
+    assertQ(req("fl", "*,score", "q", fieldName+":7.50,USD"), "//str[@name='id']='2'");
+    assertQ(req("fl", "*,score", "q", fieldName+":7.49,USD"), "//*[@numFound='0']");
+    assertQ(req("fl", "*,score", "q", fieldName+":7.51,USD"), "//*[@numFound='0']");
+  }
+
+  @Ignore
+  public void testPerformance() throws Exception {
+    clearIndex();
+
+    Random r = random();
+    int initDocs = 200000;
+
+    for (int i = 1; i <= initDocs; i++) {
+      assertU(adoc("id", "" + i, fieldName, (r.nextInt(10) + 1.00) + ",USD"));
+      if (i % 1000 == 0)
+        System.out.println(i);
+    }
+
+    assertU(commit());
+    for (int i = 0; i < 1000; i++) {
+      double lower = r.nextInt(10) + 1.00;
+      assertQ(req("fl", "*,score", "q", fieldName+":[" +  lower + ",USD TO " + (lower + 10.00) + ",USD]"), "//*");
+      assertQ(req("fl", "*,score", "q", fieldName+":[" +  lower + ",EUR TO " + (lower + 10.00) + ",EUR]"), "//*");
+    }
+
+    for (int j = 0; j < 3; j++) {
+      final RTimer timer = new RTimer();
+      for (int i = 0; i < 1000; i++) {
+        double lower = r.nextInt(10) + 1.00;
+        assertQ(req("fl", "*,score", "q", fieldName+":[" +  lower + ",USD TO " + (lower + (9.99 - (j * 0.01))) + ",USD]"), "//*");
+      }
+
+      System.out.println(timer.getTime());
+    }
+
+    System.out.println("---");
+
+    for (int j = 0; j < 3; j++) {
+      final RTimer timer = new RTimer();
+      for (int i = 0; i < 1000; i++) {
+        double lower = r.nextInt(10) + 1.00;
+        assertQ(req("fl", "*,score", "q", fieldName+":[" +  lower + ",EUR TO " + (lower + (9.99 - (j * 0.01))) + ",EUR]"), "//*");
+      }
+
+      System.out.println(timer.getTime());
+    }
+  }
+
+  @Test
+  public void testCurrencySort() throws Exception {
+    assumeTrue("This test is only applicable to the XML file based exchange rate provider",
+        expectedProviderClass.equals(FileExchangeRateProvider.class));
+
+    clearIndex();
+
+    assertU(adoc("id", "" + 1, fieldName, "10.00,USD"));
+    assertU(adoc("id", "" + 2, fieldName, "15.00,EUR"));
+    assertU(adoc("id", "" + 3, fieldName, "7.00,EUR"));
+    assertU(adoc("id", "" + 4, fieldName, "6.00,GBP"));
+    assertU(adoc("id", "" + 5, fieldName, "2.00,GBP"));
+    assertU(commit());
+
+    assertQ(req("fl", "*,score", "q", "*:*", "sort", fieldName+" desc", "limit", "1"), "//str[@name='id']='4'");
+    assertQ(req("fl", "*,score", "q", "*:*", "sort", fieldName+" asc", "limit", "1"), "//str[@name='id']='3'");
+  }
+
+  public void testExpectedProvider() {
+      SolrCore core = h.getCore();
+      IndexSchema schema = core.getLatestSchema();
+      SchemaField field = schema.getField(fieldName);
+      FieldType fieldType = field.getType();
+      ExchangeRateProvider provider = ((CurrencyFieldType)fieldType).getProvider();
+      assertEquals(expectedProviderClass, provider.getClass());
+    }
+  
+  public void testFunctionUsage() throws Exception {
+    assumeTrue("This test is only applicable to the XML file based exchange rate provider",
+        expectedProviderClass.equals(FileExchangeRateProvider.class));
+
+    clearIndex();
+    for (int i = 1; i <= 8; i++) {
+      // "GBP" currency code is 1/2 of a USD dollar, for testing.
+      assertU(adoc("id", "" + i, fieldName, (((float)i)/2) + ",GBP"));
+    }
+    for (int i = 9; i <= 11; i++) {
+      assertU(adoc("id", "" + i, fieldName, i + ",USD"));
+    }
+
+    assertU(commit());
+
+    // direct value source usage, gets "raw" form od default currency
+    // default==USD, so raw==penies
+    assertQ(req("fl", "id,func:field($f)",
+                "f", fieldName,
+                "q", "id:5"),
+            "//*[@numFound='1']",
+            "//doc/float[@name='func' and .=500]");
+    assertQ(req("fl", "id,func:field($f)",
+                "f", fieldName,
+                "q", "id:10"),
+            "//*[@numFound='1']",
+            "//doc/float[@name='func' and .=1000]");
+    assertQ(req("fl", "id,score,"+fieldName, 
+                "q", "{!frange u=500}"+fieldName)
+            ,"//*[@numFound='5']"
+            ,"//str[@name='id']='1'"
+            ,"//str[@name='id']='2'"
+            ,"//str[@name='id']='3'"
+            ,"//str[@name='id']='4'"
+            ,"//str[@name='id']='5'"
+            );
+    assertQ(req("fl", "id,score,"+fieldName, 
+                "q", "{!frange l=500 u=1000}"+fieldName)
+            ,"//*[@numFound='6']"
+            ,"//str[@name='id']='5'"
+            ,"//str[@name='id']='6'"
+            ,"//str[@name='id']='7'"
+            ,"//str[@name='id']='8'"
+            ,"//str[@name='id']='9'"
+            ,"//str[@name='id']='10'"
+            );
+
+    // use the currency function to convert to default (USD)
+    assertQ(req("fl", "id,func:currency($f)",
+                "f", fieldName,
+                "q", "id:10"),
+            "//*[@numFound='1']",
+            "//doc/float[@name='func' and .=10]");
+    assertQ(req("fl", "id,func:currency($f)",
+                "f", fieldName,
+                "q", "id:5"),
+            "//*[@numFound='1']",
+            "//doc/float[@name='func' and .=5]");
+    assertQ(req("fl", "id,score"+fieldName, 
+                "f", fieldName,
+                "q", "{!frange u=5}currency($f)")
+            ,"//*[@numFound='5']"
+            ,"//str[@name='id']='1'"
+            ,"//str[@name='id']='2'"
+            ,"//str[@name='id']='3'"
+            ,"//str[@name='id']='4'"
+            ,"//str[@name='id']='5'"
+            );
+    assertQ(req("fl", "id,score"+fieldName, 
+                "f", fieldName,
+                "q", "{!frange l=5 u=10}currency($f)")
+            ,"//*[@numFound='6']"
+            ,"//str[@name='id']='5'"
+            ,"//str[@name='id']='6'"
+            ,"//str[@name='id']='7'"
+            ,"//str[@name='id']='8'"
+            ,"//str[@name='id']='9'"
+            ,"//str[@name='id']='10'"
+            );
+    
+    // use the currency function to convert to MXN
+    assertQ(req("fl", "id,func:currency($f,MXN)",
+                "f", fieldName,
+                "q", "id:5"),
+            "//*[@numFound='1']",
+            "//doc/float[@name='func' and .=10]");
+    assertQ(req("fl", "id,func:currency($f,MXN)",
+                "f", fieldName,
+                "q", "id:10"),
+            "//*[@numFound='1']",
+            "//doc/float[@name='func' and .=20]");
+    assertQ(req("fl", "*,score,"+fieldName, 
+                "f", fieldName,
+                "q", "{!frange u=10}currency($f,MXN)")
+            ,"//*[@numFound='5']"
+            ,"//str[@name='id']='1'"
+            ,"//str[@name='id']='2'"
+            ,"//str[@name='id']='3'"
+            ,"//str[@name='id']='4'"
+            ,"//str[@name='id']='5'"
+            );
+    assertQ(req("fl", "*,score,"+fieldName, 
+                "f", fieldName,
+                "q", "{!frange l=10 u=20}currency($f,MXN)")
+            ,"//*[@numFound='6']"
+            ,"//str[@name='id']='5'"
+            ,"//str[@name='id']='6'"
+            ,"//str[@name='id']='7'"
+            ,"//str[@name='id']='8'"
+            ,"//str[@name='id']='9'"
+            ,"//str[@name='id']='10'"
+            );
+
+  }
+
+  @Test
+  public void testMockFieldType() throws Exception {
+    assumeTrue("This test is only applicable to the mock exchange rate provider",
+        expectedProviderClass.equals(MockExchangeRateProvider.class));
+
+    clearIndex();
+
+    assertU(adoc("id", "1", fieldName, "1.00,USD"));
+    assertU(adoc("id", "2", fieldName, "1.00,EUR"));
+    assertU(adoc("id", "3", fieldName, "1.00,NOK"));
+    assertU(commit());
+
+    assertQ(req("fl", "*,score", "q", fieldName+":5.0,NOK"),   "//*[@numFound='1']", "//str[@name='id']='1'");
+    assertQ(req("fl", "*,score", "q", fieldName+":1.2,USD"), "//*[@numFound='1']",   "//str[@name='id']='2'");
+    assertQ(req("fl", "*,score", "q", fieldName+":0.2,USD"), "//*[@numFound='1']",   "//str[@name='id']='3'");
+    assertQ(req("fl", "*,score", "q", fieldName+":99,USD"),  "//*[@numFound='0']");
+  }
+
+  @Test
+  public void testAsymmetricPointQuery() throws Exception {
+    assumeTrue("This test is only applicable to the XML file based exchange rate provider",
+        expectedProviderClass.equals(FileExchangeRateProvider.class));
+
+    clearIndex();
+    assertU(adoc("id", "" + 1, fieldName, "10.00,USD"));
+    assertU(adoc("id", "" + 2, fieldName, "15.00,EUR"));
+    assertU(commit());
+
+    assertQ(req("fl", "*,score", "q", fieldName+":15.00,EUR"), "//str[@name='id']='2'");
+    assertQ(req("fl", "*,score", "q", fieldName+":7.50,USD"), "//str[@name='id']='2'");
+    assertQ(req("fl", "*,score", "q", fieldName+":7.49,USD"), "//*[@numFound='0']");
+    assertQ(req("fl", "*,score", "q", fieldName+":7.51,USD"), "//*[@numFound='0']");
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test/org/apache/solr/schema/CurrencyFieldXmlFileTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldXmlFileTest.java b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldXmlFileTest.java
deleted file mode 100644
index e8bffe7..0000000
--- a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldXmlFileTest.java
+++ /dev/null
@@ -1,42 +0,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.
- */
-package org.apache.solr.schema;
-import org.junit.Test;
-
-/**
- * Tests currency field type using FileExchangeRateProvider
- */
-public class CurrencyFieldXmlFileTest extends AbstractCurrencyFieldTest {
-
-  public String field() {
-    return "amount";
-  }
-
-  @Test
-  public void testAsymetricPointQuery() throws Exception {
-    clearIndex();
-    assertU(adoc("id", "" + 1, field(), "10.00,USD"));
-    assertU(adoc("id", "" + 2, field(), "15.00,EUR"));
-    assertU(commit());
-
-    assertQ(req("fl", "*,score", "q", field()+":15.00,EUR"), "//str[@name='id']='2'");
-    assertQ(req("fl", "*,score", "q", field()+":7.50,USD"), "//str[@name='id']='2'");
-    assertQ(req("fl", "*,score", "q", field()+":7.49,USD"), "//*[@numFound='0']");
-    assertQ(req("fl", "*,score", "q", field()+":7.51,USD"), "//*[@numFound='0']");
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/core/src/test/org/apache/solr/schema/OpenExchangeRatesOrgProviderTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/OpenExchangeRatesOrgProviderTest.java b/solr/core/src/test/org/apache/solr/schema/OpenExchangeRatesOrgProviderTest.java
index ce44c38..972ebe6 100644
--- a/solr/core/src/test/org/apache/solr/schema/OpenExchangeRatesOrgProviderTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/OpenExchangeRatesOrgProviderTest.java
@@ -40,7 +40,7 @@ public class OpenExchangeRatesOrgProviderTest extends SolrTestCaseJ4 {
   @Override
   @Before
   public void setUp() throws Exception {
-    AbstractCurrencyFieldTest.assumeCurrencySupport
+    CurrencyFieldTypeTest.assumeCurrencySupport
       ("USD", "EUR", "MXN", "GBP", "JPY");
 
     super.setUp();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/example/example-DIH/solr/db/conf/managed-schema
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/db/conf/managed-schema b/solr/example/example-DIH/solr/db/conf/managed-schema
index de138ba..b96ff4c 100644
--- a/solr/example/example-DIH/solr/db/conf/managed-schema
+++ b/solr/example/example-DIH/solr/db/conf/managed-schema
@@ -202,8 +202,10 @@
    <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
    <dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>
    <dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
+   <dynamicField name="*_s_ns"  type="string"  indexed="true"  stored="false" />
    <dynamicField name="*_ss" type="string"  indexed="true"  stored="true" multiValued="true"/>
    <dynamicField name="*_l"  type="long"   indexed="true"  stored="true"/>
+   <dynamicField name="*_l_ns"  type="long"   indexed="true"  stored="false"/>
    <dynamicField name="*_ls" type="long"   indexed="true"  stored="true"  multiValued="true"/>
    <dynamicField name="*_t"  type="text_general"    indexed="true"  stored="true"/>
    <dynamicField name="*_txt" type="text_general"   indexed="true"  stored="true" multiValued="true"/>
@@ -703,17 +705,22 @@
 
    <!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
         Parameters:
-          defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
-          precisionStep:   Specifies the precisionStep for the TrieLong field used for the amount
-          providerClass:   Lets you plug in other exchange provider backend:
-                           solr.FileExchangeRateProvider is the default and takes one parameter:
-                             currencyConfig: name of an xml file holding exchange rates
-                           solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
-                             ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
-                             refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
+          amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field. 
+                              The dynamic field must have a field type that extends LongValueFieldType.
+                              Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
+          codeStrSuffix:    Required. Refers to a dynamic field for the currency code sub-field.
+                              The dynamic field must have a field type that extends StrField.
+                              Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
+          defaultCurrency:  Specifies the default currency if none specified. Defaults to "USD"
+          providerClass:    Lets you plug in other exchange provider backend:
+                            solr.FileExchangeRateProvider is the default and takes one parameter:
+                              currencyConfig: name of an xml file holding exchange rates
+                            solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
+                              ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
+                              refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
    -->
-    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
-             
+    <fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
+               defaultCurrency="USD" currencyConfig="currency.xml" />
 
 
    <!-- some examples for different languages (generally ordered by ISO code) -->

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6f4f2dd/solr/example/example-DIH/solr/mail/conf/managed-schema
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/mail/conf/managed-schema b/solr/example/example-DIH/solr/mail/conf/managed-schema
index 7b058eb..e027717 100644
--- a/solr/example/example-DIH/solr/mail/conf/managed-schema
+++ b/solr/example/example-DIH/solr/mail/conf/managed-schema
@@ -138,8 +138,10 @@
    <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
    <dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>
    <dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
+   <dynamicField name="*_s_ns"  type="string"  indexed="true"  stored="false" />
    <dynamicField name="*_ss" type="string"  indexed="true"  stored="true" multiValued="true"/>
    <dynamicField name="*_l"  type="long"   indexed="true"  stored="true"/>
+   <dynamicField name="*_l_ns"  type="long"   indexed="true"  stored="false"/>
    <dynamicField name="*_ls" type="long"   indexed="true"  stored="true"  multiValued="true"/>
    <dynamicField name="*_t"  type="text_general"    indexed="true"  stored="true"/>
    <dynamicField name="*_txt" type="text_general"   indexed="true"  stored="true" multiValued="true"/>
@@ -623,17 +625,22 @@
 
    <!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
         Parameters:
-          defaultCurrency: Specifies the default currency if none specified. Defaults to "USD"
-          precisionStep:   Specifies the precisionStep for the TrieLong field used for the amount
-          providerClass:   Lets you plug in other exchange provider backend:
-                           solr.FileExchangeRateProvider is the default and takes one parameter:
-                             currencyConfig: name of an xml file holding exchange rates
-                           solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
-                             ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
-                             refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
+          amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field. 
+                              The dynamic field must have a field type that extends LongValueFieldType.
+                              Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
+          codeStrSuffix:    Required. Refers to a dynamic field for the currency code sub-field.
+                              The dynamic field must have a field type that extends StrField.
+                              Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
+          defaultCurrency:  Specifies the default currency if none specified. Defaults to "USD"
+          providerClass:    Lets you plug in other exchange provider backend:
+                            solr.FileExchangeRateProvider is the default and takes one parameter:
+                              currencyConfig: name of an xml file holding exchange rates
+                            solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
+                              ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
+                              refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
    -->
-    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />
-             
+    <fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
+               defaultCurrency="USD" currencyConfig="currency.xml" />
 
 
    <!-- some examples for different languages (generally ordered by ISO code) -->