You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2014/10/03 22:00:34 UTC
svn commit: r1629301 - in /lucene/dev/branches/branch_5x/solr/core/src:
java/org/apache/solr/rest/schema/ java/org/apache/solr/schema/
test/org/apache/solr/rest/schema/ test/org/apache/solr/schema/
Author: noble
Date: Fri Oct 3 20:00:33 2014
New Revision: 1629301
URL: http://svn.apache.org/r1629301
Log:
SOLR-6476
Added:
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/SchemaManager.java (props changed)
- copied unchanged from r1629271, lucene/dev/trunk/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java (with props)
lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestBulkSchemaConcurrent.java (with props)
lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestSchemaManager.java (with props)
Modified:
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java Fri Oct 3 20:00:33 2014
@@ -70,7 +70,7 @@ abstract class BaseFieldTypeResource ext
while (!success) {
try {
synchronized (oldSchema.getSchemaUpdateLock()) {
- newSchema = oldSchema.addFieldTypes(newFieldTypes);
+ newSchema = oldSchema.addFieldTypes(newFieldTypes, true);
getSolrCore().setLatestSchema(newSchema);
success = true;
}
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java Fri Oct 3 20:00:33 2014
@@ -173,7 +173,7 @@ public class CopyFieldCollectionResource
while (!success) {
try {
synchronized (oldSchema.getSchemaUpdateLock()) {
- newSchema = oldSchema.addCopyFields(fieldsToCopy);
+ newSchema = oldSchema.addCopyFields(fieldsToCopy,true);
if (null != newSchema) {
getSolrCore().setLatestSchema(newSchema);
success = true;
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java Fri Oct 3 20:00:33 2014
@@ -178,7 +178,7 @@ public class DynamicFieldCollectionResou
}
firstAttempt = false;
synchronized (oldSchema.getSchemaUpdateLock()) {
- newSchema = oldSchema.addDynamicFields(newDynamicFields, copyFields);
+ newSchema = oldSchema.addDynamicFields(newDynamicFields, copyFields, true);
if (null != newSchema) {
getSolrCore().setLatestSchema(newSchema);
success = true;
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java Fri Oct 3 20:00:33 2014
@@ -32,9 +32,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
/**
* This class responds to requests at /solr/(corename)/schema/dynamicfields/(pattern)
@@ -142,12 +147,12 @@ public class DynamicFieldResource extend
} else {
ManagedIndexSchema oldSchema = (ManagedIndexSchema)getSchema();
Object copies = map.get(IndexSchema.COPY_FIELDS);
- List<String> copyFieldNames = null;
+ Collection<String> copyFieldNames = null;
if (copies != null) {
if (copies instanceof List) {
copyFieldNames = (List<String>)copies;
} else if (copies instanceof String) {
- copyFieldNames = Collections.singletonList(copies.toString());
+ copyFieldNames = singletonList(copies.toString());
} else {
String message = "Invalid '" + IndexSchema.COPY_FIELDS + "' type.";
log.error(message);
@@ -163,7 +168,7 @@ public class DynamicFieldResource extend
try {
SchemaField newDynamicField = oldSchema.newDynamicField(fieldNamePattern, fieldType, map);
synchronized (oldSchema.getSchemaUpdateLock()) {
- newSchema = oldSchema.addDynamicField(newDynamicField, copyFieldNames);
+ newSchema = oldSchema.addDynamicFields(singletonList(newDynamicField), singletonMap(newDynamicField.getName(), copyFieldNames), true);
if (null != newSchema) {
getSolrCore().setLatestSchema(newSchema);
success = true;
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java Fri Oct 3 20:00:33 2014
@@ -199,7 +199,7 @@ public class FieldCollectionResource ext
}
firstAttempt = false;
synchronized (oldSchema.getSchemaUpdateLock()) {
- newSchema = oldSchema.addFields(newFields, copyFields);
+ newSchema = oldSchema.addFields(newFields, copyFields, true);
if (null != newSchema) {
getSolrCore().setLatestSchema(newSchema);
success = true;
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/rest/schema/SchemaResource.java Fri Oct 3 20:00:33 2014
@@ -16,18 +16,26 @@ package org.apache.solr.rest.schema;
* limitations under the License.
*/
+import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.rest.BaseSolrResource;
import org.apache.solr.rest.GETable;
+import org.apache.solr.rest.POSTable;
import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.SchemaManager;
import org.restlet.representation.Representation;
import org.restlet.resource.ResourceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.List;
+
/**
* This class responds to requests at /solr/(corename)/schema
*/
-public class SchemaResource extends BaseSolrResource implements GETable {
+public class SchemaResource extends BaseSolrResource implements GETable,POSTable {
private static final Logger log = LoggerFactory.getLogger(SchemaResource.class);
public SchemaResource() {
@@ -50,4 +58,25 @@ public class SchemaResource extends Base
return new SolrOutputRepresentation();
}
+
+ @Override
+ public Representation post(Representation representation) {
+ SolrRequestInfo requestInfo = SolrRequestInfo.getRequestInfo();
+ List<String> errs = null;
+ try {
+ String text = representation.getText();
+ errs = new SchemaManager(requestInfo.getReq()).performOperations(new StringReader(text));
+ } catch (IOException e) {
+ requestInfo.getRsp().add("errors", Collections.singletonList("Error reading input String " + e.getMessage()));
+ requestInfo.getRsp().setException(e);
+ }
+ if(!errs.isEmpty()){
+ requestInfo.getRsp().add("errors", errs);
+ }
+
+
+ return new BaseSolrResource.SolrOutputRepresentation();
+ }
+
+
}
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/IndexSchema.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/IndexSchema.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/IndexSchema.java Fri Oct 3 20:00:33 2014
@@ -72,6 +72,9 @@ import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+
/**
* <code>IndexSchema</code> contains information about the valid fields in an index
* and the types of those fields.
@@ -1471,23 +1474,26 @@ public class IndexSchema {
}
/**
- * Copies this schema, adds the given field to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
+ * Copies this schema, adds the given field to the copy
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param newField the SchemaField to add
+ * @param persist to persist the schema or not or not
* @return a new IndexSchema based on this schema with newField added
* @see #newField(String, String, Map)
*/
+ public IndexSchema addField(SchemaField newField, boolean persist) {
+ return addFields(Collections.singletonList(newField),Collections.EMPTY_MAP,persist );
+ }
+
public IndexSchema addField(SchemaField newField) {
- String msg = "This IndexSchema is not mutable.";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ return addField(newField, true);
}
/**
- * Copies this schema, adds the given field to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
+ * Copies this schema, adds the given field to the copy
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param newField the SchemaField to add
@@ -1496,14 +1502,12 @@ public class IndexSchema {
* @see #newField(String, String, Map)
*/
public IndexSchema addField(SchemaField newField, Collection<String> copyFieldNames) {
- String msg = "This IndexSchema is not mutable.";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ return addFields(singletonList(newField), singletonMap(newField.getName(), copyFieldNames), true);
}
/**
- * Copies this schema, adds the given fields to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
+ * Copies this schema, adds the given fields to the copy
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param newFields the SchemaFields to add
@@ -1511,99 +1515,57 @@ public class IndexSchema {
* @see #newField(String, String, Map)
*/
public IndexSchema addFields(Collection<SchemaField> newFields) {
- String msg = "This IndexSchema is not mutable.";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
+ return addFields(newFields, Collections.<String, Collection<String>>emptyMap(), true);
}
/**
- * Copies this schema, adds the given fields to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
+ * Copies this schema, adds the given fields to the copy.
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param newFields the SchemaFields to add
* @param copyFieldNames 0 or more names of targets to copy this field to. The target fields must already exist.
+ * @param persist Persist the schema or not
* @return a new IndexSchema based on this schema with newFields added
* @see #newField(String, String, Map)
*/
- public IndexSchema addFields(Collection<SchemaField> newFields, Map<String, Collection<String>> copyFieldNames) {
+ public IndexSchema addFields(Collection<SchemaField> newFields, Map<String, Collection<String>> copyFieldNames, boolean persist) {
String msg = "This IndexSchema is not mutable.";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
- /**
- * Copies this schema, adds the given dynamic field to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
- * {@link #getSchemaUpdateLock()}.
- *
- * @param newDynamicField the SchemaField to add
- * @return a new IndexSchema based on this schema with newField added
- * @see #newDynamicField(String, String, Map)
- */
- public IndexSchema addDynamicField(SchemaField newDynamicField) {
- String msg = "This IndexSchema is not mutable.";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
- }
/**
- * Copies this schema, adds the given dynamic field to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
- * {@link #getSchemaUpdateLock()}.
- *
- * @param newDynamicField the SchemaField to add
- * @param copyFieldNames 0 or more names of targets to copy this field to. The targets must already exist.
- * @return a new IndexSchema based on this schema with newDynamicField added
- * @see #newDynamicField(String, String, Map)
- */
- public IndexSchema addDynamicField(SchemaField newDynamicField, Collection<String> copyFieldNames) {
- String msg = "This IndexSchema is not mutable.";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
- }
-
- /**
- * Copies this schema, adds the given dynamic fields to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
- * {@link #getSchemaUpdateLock()}.
- *
- * @param newDynamicFields the SchemaFields to add
- * @return a new IndexSchema based on this schema with newDynamicFields added
- * @see #newDynamicField(String, String, Map)
- */
- public IndexSchema addDynamicFields(Collection<SchemaField> newDynamicFields) {
- String msg = "This IndexSchema is not mutable.";
- log.error(msg);
- throw new SolrException(ErrorCode.SERVER_ERROR, msg);
- }
-
- /**
- * Copies this schema, adds the given dynamic fields to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
+ * Copies this schema, adds the given dynamic fields to the copy,
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param newDynamicFields the SchemaFields to add
* @param copyFieldNames 0 or more names of targets to copy this field to. The target fields must already exist.
+ * @param persist to persist the schema or not or not
* @return a new IndexSchema based on this schema with newDynamicFields added
* @see #newDynamicField(String, String, Map)
*/
public IndexSchema addDynamicFields
- (Collection<SchemaField> newDynamicFields, Map<String, Collection<String>> copyFieldNames) {
+ (Collection<SchemaField> newDynamicFields,
+ Map<String, Collection<String>> copyFieldNames,
+ boolean persist) {
String msg = "This IndexSchema is not mutable.";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
}
/**
- * Copies this schema and adds the new copy fields to the copy, then
- * persists the new schema. Requires synchronizing on the object returned by
+ * Copies this schema and adds the new copy fields to the copy
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param copyFields Key is the name of the source field name, value is a collection of target field names. Fields must exist.
+ * @param persist to persist the schema or not or not
* @return The new Schema with the copy fields added
*/
- public IndexSchema addCopyFields(Map<String, Collection<String>> copyFields){
+ public IndexSchema addCopyFields(Map<String, Collection<String>> copyFields, boolean persist){
String msg = "This IndexSchema is not mutable.";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
@@ -1673,15 +1635,16 @@ public class IndexSchema {
}
/**
- * Copies this schema, adds the given field type to the copy, then persists the
- * new schema. Requires synchronizing on the object returned by
+ * Copies this schema, adds the given field type to the copy,
+ * Requires synchronizing on the object returned by
* {@link #getSchemaUpdateLock()}.
*
* @param fieldTypeList a list of FieldTypes to add
+ * @param persist to persist the schema or not or not
* @return a new IndexSchema based on this schema with the new types added
* @see #newFieldType(String, String, Map)
*/
- public IndexSchema addFieldTypes(List<FieldType> fieldTypeList) {
+ public IndexSchema addFieldTypes(List<FieldType> fieldTypeList, boolean persist) {
String msg = "This IndexSchema is not mutable.";
log.error(msg);
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
@@ -1690,13 +1653,13 @@ public class IndexSchema {
/**
* Returns a FieldType if the given typeName does not already
* exist in this schema. The resulting FieldType can be used in a call
- * to {@link #addFieldType(FieldType)}.
+ * to {@link #addFieldTypes(java.util.List, boolean)}.
*
* @param typeName the name of the type to add
* @param className the name of the FieldType class
* @param options the options to use when creating the FieldType
* @return The created FieldType
- * @see #addFieldType(FieldType)
+ * @see #addFieldTypes(java.util.List, boolean)
*/
public FieldType newFieldType(String typeName, String className, Map<String,?> options) {
String msg = "This IndexSchema is not mutable.";
Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java?rev=1629301&r1=1629300&r2=1629301&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java Fri Oct 3 20:00:33 2014
@@ -80,6 +80,9 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+
/** Solr-managed schema - non-user-editable, but can be mutable via internal and external REST API requests. */
public final class ManagedIndexSchema extends IndexSchema {
@@ -386,23 +389,11 @@ public final class ManagedIndexSchema ex
}
}
- @Override
- public ManagedIndexSchema addField(SchemaField newField) {
- return addFields(Arrays.asList(newField));
- }
-
- @Override
- public ManagedIndexSchema addField(SchemaField newField, Collection<String> copyFieldNames) {
- return addFields(Arrays.asList(newField), Collections.singletonMap(newField.getName(), copyFieldNames));
- }
@Override
- public ManagedIndexSchema addFields(Collection<SchemaField> newFields) {
- return addFields(newFields, Collections.<String, Collection<String>>emptyMap());
- }
-
- @Override
- public ManagedIndexSchema addFields(Collection<SchemaField> newFields, Map<String, Collection<String>> copyFieldNames) {
+ public ManagedIndexSchema addFields(Collection<SchemaField> newFields,
+ Map<String, Collection<String>> copyFieldNames,
+ boolean persist) {
ManagedIndexSchema newSchema = null;
if (isMutable) {
boolean success = false;
@@ -439,12 +430,15 @@ public final class ManagedIndexSchema ex
aware.inform(newSchema);
}
newSchema.refreshAnalyzers();
- success = newSchema.persistManagedSchema(false); // don't just create - update it if it already exists
- if (success) {
- log.debug("Added field(s): {}", newFields);
- } else {
- log.error("Failed to add field(s): {}", newFields);
- newSchema = null;
+
+ if(persist) {
+ success = newSchema.persistManagedSchema(false); // don't just create - update it if it already exists
+ if (success) {
+ log.debug("Added field(s): {}", newFields);
+ } else {
+ log.error("Failed to add field(s): {}", newFields);
+ newSchema = null;
+ }
}
} else {
String msg = "This ManagedIndexSchema is not mutable.";
@@ -454,25 +448,10 @@ public final class ManagedIndexSchema ex
return newSchema;
}
- @Override
- public IndexSchema addDynamicField(SchemaField newDynamicField) {
- return addDynamicFields(Arrays.asList(newDynamicField));
- }
-
- @Override
- public IndexSchema addDynamicField(SchemaField newDynamicField, Collection<String> copyFieldNames) {
- return addDynamicFields(Arrays.asList(newDynamicField),
- Collections.singletonMap(newDynamicField.getName(), copyFieldNames));
- }
-
- @Override
- public ManagedIndexSchema addDynamicFields(Collection<SchemaField> newDynamicFields) {
- return addDynamicFields(newDynamicFields, Collections.<String,Collection<String>>emptyMap());
- }
@Override
public ManagedIndexSchema addDynamicFields(Collection<SchemaField> newDynamicFields,
- Map<String,Collection<String>> copyFieldNames) {
+ Map<String,Collection<String>> copyFieldNames, boolean persist) {
ManagedIndexSchema newSchema = null;
if (isMutable) {
boolean success = false;
@@ -489,7 +468,7 @@ public final class ManagedIndexSchema ex
}
dFields.add(new DynamicField(newDynamicField));
newSchema.dynamicFields = dynamicFieldListToSortedArray(dFields);
-
+
Collection<String> copyFields = copyFieldNames.get(newDynamicField.getName());
if (copyFields != null) {
for (String copyField : copyFields) {
@@ -503,11 +482,13 @@ public final class ManagedIndexSchema ex
aware.inform(newSchema);
}
newSchema.refreshAnalyzers();
- success = newSchema.persistManagedSchema(false); // don't just create - update it if it already exists
- if (success) {
- log.debug("Added dynamic field(s): {}", newDynamicFields);
- } else {
- log.error("Failed to add dynamic field(s): {}", newDynamicFields);
+ if(persist) {
+ success = newSchema.persistManagedSchema(false); // don't just create - update it if it already exists
+ if (success) {
+ log.debug("Added dynamic field(s): {}", newDynamicFields);
+ } else {
+ log.error("Failed to add dynamic field(s): {}", newDynamicFields);
+ }
}
} else {
String msg = "This ManagedIndexSchema is not mutable.";
@@ -518,7 +499,7 @@ public final class ManagedIndexSchema ex
}
@Override
- public ManagedIndexSchema addCopyFields(Map<String, Collection<String>> copyFields) {
+ public ManagedIndexSchema addCopyFields(Map<String, Collection<String>> copyFields, boolean persist) {
ManagedIndexSchema newSchema = null;
if (isMutable) {
boolean success = false;
@@ -536,21 +517,19 @@ public final class ManagedIndexSchema ex
aware.inform(newSchema);
}
newSchema.refreshAnalyzers();
- success = newSchema.persistManagedSchema(false); // don't just create - update it if it already exists
- if (success) {
- log.debug("Added copy fields for {} sources", copyFields.size());
- } else {
- log.error("Failed to add copy fields for {} sources", copyFields.size());
+ if(persist) {
+ success = newSchema.persistManagedSchema(false); // don't just create - update it if it already exists
+ if (success) {
+ log.debug("Added copy fields for {} sources", copyFields.size());
+ } else {
+ log.error("Failed to add copy fields for {} sources", copyFields.size());
+ }
}
}
return newSchema;
}
-
- public ManagedIndexSchema addFieldType(FieldType fieldType) {
- return addFieldTypes(Collections.singletonList(fieldType));
- }
- public ManagedIndexSchema addFieldTypes(List<FieldType> fieldTypeList) {
+ public ManagedIndexSchema addFieldTypes(List<FieldType> fieldTypeList, boolean persist) {
if (!isMutable) {
String msg = "This ManagedIndexSchema is not mutable.";
log.error(msg);
@@ -611,24 +590,26 @@ public final class ManagedIndexSchema ex
}
newSchema.refreshAnalyzers();
-
- boolean success = newSchema.persistManagedSchema(false);
- if (success) {
- if (log.isDebugEnabled()) {
- StringBuilder fieldTypeNames = new StringBuilder();
- for (int i=0; i < fieldTypeList.size(); i++) {
- if (i > 0) fieldTypeNames.append(", ");
- fieldTypeNames.append(fieldTypeList.get(i).typeName);
+
+ if (persist) {
+ boolean success = newSchema.persistManagedSchema(false);
+ if (success) {
+ if (log.isDebugEnabled()) {
+ StringBuilder fieldTypeNames = new StringBuilder();
+ for (int i=0; i < fieldTypeList.size(); i++) {
+ if (i > 0) fieldTypeNames.append(", ");
+ fieldTypeNames.append(fieldTypeList.get(i).typeName);
+ }
+ log.debug("Added field types: {}", fieldTypeNames.toString());
}
- log.debug("Added field types: {}", fieldTypeNames.toString());
+ } else {
+ // this is unlikely to happen as most errors are handled as exceptions in the persist code
+ log.error("Failed to add field types: {}", fieldTypeList);
+ throw new SolrException(ErrorCode.SERVER_ERROR,
+ "Failed to persist updated schema due to underlying storage issue; check log for more details!");
}
- } else {
- // this is unlikely to happen as most errors are handled as exceptions in the persist code
- log.error("Failed to add field types: {}", fieldTypeList);
- throw new SolrException(ErrorCode.SERVER_ERROR,
- "Failed to persist updated schema due to underlying storage issue; check log for more details!");
}
-
+
return newSchema;
}
@@ -834,7 +815,7 @@ public final class ManagedIndexSchema ex
* are copied; otherwise, they are not.
* @return A shallow copy of this schema
*/
- private ManagedIndexSchema shallowCopy(boolean includeFieldDataStructures) {
+ ManagedIndexSchema shallowCopy(boolean includeFieldDataStructures) {
ManagedIndexSchema newSchema = null;
try {
newSchema = new ManagedIndexSchema
Added: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java?rev=1629301&view=auto
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java (added)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/rest/schema/TestBulkSchemaAPI.java Fri Oct 3 20:00:33 2014
@@ -0,0 +1,236 @@
+package org.apache.solr.rest.schema;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.commons.io.FileUtils;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.schema.SchemaManager;
+import org.apache.solr.util.RestTestBase;
+import org.apache.solr.util.RestTestHarness;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.After;
+import org.junit.Before;
+import org.noggit.JSONParser;
+import org.noggit.ObjectBuilder;
+import org.restlet.ext.servlet.ServerServlet;
+
+import java.io.File;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+
+public class TestBulkSchemaAPI extends RestTestBase {
+
+ private static File tmpSolrHome;
+ private static File tmpConfDir;
+
+ private static final String collection = "collection1";
+ private static final String confDir = collection + "/conf";
+
+
+ @Before
+ public void before() throws Exception {
+ tmpSolrHome = createTempDir().toFile();
+ tmpConfDir = new File(tmpSolrHome, confDir);
+ FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
+
+ final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
+ final ServletHolder solrRestApi = new ServletHolder("SolrSchemaRestApi", ServerServlet.class);
+ solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrSchemaRestApi");
+ extraServlets.put(solrRestApi, "/schema/*"); // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
+
+ System.setProperty("managed.schema.mutable", "true");
+ System.setProperty("enable.update.log", "false");
+
+ createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml",
+ "/solr", true, extraServlets);
+ }
+
+ @After
+ public void after() throws Exception {
+ if (jetty != null) {
+ jetty.stop();
+ jetty = null;
+ }
+ server = null;
+ restTestHarness = null;
+ }
+
+ public void testMultipleAddFieldWithErrors() throws Exception {
+
+ String payload = SolrTestCaseJ4.json( "{\n" +
+ " 'add-field' : {\n" +
+ " 'name':'a1',\n" +
+ " 'type': 'string1',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':false\n" +
+ " },\n" +
+ " 'add-field' : {\n" +
+ " 'type': 'string',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':true\n" +
+ " }\n" +
+ " \n" +
+ " }");
+
+ String response = restTestHarness.post("/schema?wt=json", payload);
+ Map map = (Map) ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
+ List l = (List) map.get("errors");
+
+ List errorList = (List) ((Map) l.get(0)).get(SchemaManager.ERR_MSGS);
+ assertEquals(1, errorList.size());
+ assertTrue (((String)errorList.get(0)).contains("No such field type"));
+ errorList = (List) ((Map) l.get(1)).get(SchemaManager.ERR_MSGS);
+ assertEquals(1, errorList.size());
+ assertTrue (((String)errorList.get(0)).contains("is a required field"));
+
+ }
+
+
+ public void testMultipleCommands() throws Exception{
+ String payload = "{\n" +
+ " 'add-field' : {\n" +
+ " 'name':'a1',\n" +
+ " 'type': 'string',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':false\n" +
+ " },\n" +
+ " 'add-field' : {\n" +
+ " 'name':'a2',\n" +
+ " 'type': 'string',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':true\n" +
+ " },\n" +
+ " 'add-dynamic-field' : {\n" +
+ " 'name' :'*_lol',\n" +
+ " 'type':'string',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':true\n" +
+ " },\n" +
+ " 'add-copy-field' : {\n" +
+ " 'source' :'a1',\n" +
+ " 'dest':['a2','hello_lol']\n" +
+ " },\n" +
+ " 'add-field-type' : {\n" +
+ " 'name' :'mystr',\n" +
+ " 'class' : 'solr.StrField',\n" +
+ " 'sortMissingLast':'true'\n" +
+ " },\n" +
+ " 'add-field-type' : {" +
+ " 'name' : 'myNewTxtField',\n" +
+ " 'class':'solr.TextField','positionIncrementGap':'100',\n" +
+ " 'analyzer' : {\n" +
+ " 'charFilters':[\n" +
+ " {'class':'solr.PatternReplaceCharFilterFactory','replacement':'$1$1','pattern':'([a-zA-Z])\\\\\\\\1+'}\n" +
+ " ],\n" +
+ " 'tokenizer':{'class':'solr.WhitespaceTokenizerFactory'},\n" +
+ " 'filters':[\n" +
+ " {'class':'solr.WordDelimiterFilterFactory','preserveOriginal':'0'},\n" +
+ " {'class':'solr.StopFilterFactory','words':'stopwords.txt','ignoreCase':'true'},\n" +
+ " {'class':'solr.LowerCaseFilterFactory'},\n" +
+ " {'class':'solr.ASCIIFoldingFilterFactory'},\n" +
+ " {'class':'solr.KStemFilterFactory'}\n" +
+ " ]\n" +
+ " }\n" +
+ " }"+
+ " }";
+
+ RestTestHarness harness = restTestHarness;
+
+
+ String response = harness.post("/schema?wt=json", SolrTestCaseJ4.json( payload));
+
+ Map map = (Map) ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
+ assertNull(response, map.get("errors"));
+
+
+ Map m = getObj(harness, "a1", "fields");
+ assertNotNull("field a1 not created", m);
+
+ assertEquals("string", m.get("type"));
+ assertEquals(Boolean.TRUE, m.get("stored"));
+ assertEquals(Boolean.FALSE, m.get("indexed"));
+
+ m = getObj(harness,"a2", "fields");
+ assertNotNull("field a2 not created", m);
+
+ assertEquals("string", m.get("type"));
+ assertEquals(Boolean.TRUE, m.get("stored"));
+ assertEquals(Boolean.TRUE, m.get("indexed"));
+
+ m = getObj(harness,"*_lol", "dynamicFields");
+ assertNotNull("field *_lol not created",m );
+
+ assertEquals("string", m.get("type"));
+ assertEquals(Boolean.TRUE, m.get("stored"));
+ assertEquals(Boolean.TRUE, m.get("indexed"));
+
+ List l = getCopyFields(harness,"a1");
+ Set s =new HashSet();
+ assertEquals(2,l.size());
+ s.add(((Map) l.get(0)).get("dest"));
+ s.add(((Map) l.get(1)).get("dest"));
+ assertTrue(s.contains("hello_lol"));
+ assertTrue(s.contains("a2"));
+
+ m = getObj(harness,"mystr", "fieldTypes");
+ assertNotNull(m);
+ assertEquals("solr.StrField",m.get("class"));
+ assertEquals("true",String.valueOf(m.get("sortMissingLast")));
+
+ m = getObj(harness,"myNewTxtField", "fieldTypes");
+ assertNotNull(m);
+
+
+ }
+
+ public static Map getObj(RestTestHarness restHarness, String fld, String key) throws Exception {
+ Map map = getRespMap(restHarness);
+ List l = (List) ((Map)map.get("schema")).get(key);
+ for (Object o : l) {
+ Map m = (Map) o;
+ if(fld.equals(m.get("name"))) return m;
+ }
+ return null;
+ }
+
+ public static Map getRespMap(RestTestHarness restHarness) throws Exception {
+ String response = restHarness.query("/schema?wt=json");
+ return (Map) ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
+ }
+
+ public static List getCopyFields(RestTestHarness harness, String src) throws Exception {
+ Map map = getRespMap(harness);
+ List l = (List) ((Map)map.get("schema")).get("copyFields");
+ List result = new ArrayList();
+ for (Object o : l) {
+ Map m = (Map) o;
+ if(src.equals(m.get("source"))) result.add(m);
+ }
+ return result;
+
+ }
+
+
+}
Added: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestBulkSchemaConcurrent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestBulkSchemaConcurrent.java?rev=1629301&view=auto
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestBulkSchemaConcurrent.java (added)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestBulkSchemaConcurrent.java Fri Oct 3 20:00:33 2014
@@ -0,0 +1,194 @@
+package org.apache.solr.schema;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.impl.HttpSolrServer;
+import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
+import org.apache.solr.common.cloud.ZkStateReader;
+import org.apache.solr.util.RESTfulServerProvider;
+import org.apache.solr.util.RestTestHarness;
+import org.noggit.JSONParser;
+import org.noggit.ObjectBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static java.text.MessageFormat.format;
+import static org.apache.solr.rest.schema.TestBulkSchemaAPI.getCopyFields;
+import static org.apache.solr.rest.schema.TestBulkSchemaAPI.getObj;
+
+public class TestBulkSchemaConcurrent extends AbstractFullDistribZkTestBase {
+ static final Logger log = LoggerFactory.getLogger(TestBulkSchemaConcurrent.class);
+ private List<RestTestHarness> restTestHarnesses = new ArrayList<>();
+
+ private void setupHarnesses() {
+ for (final SolrServer client : clients) {
+ RestTestHarness harness = new RestTestHarness(new RESTfulServerProvider() {
+ @Override
+ public String getBaseURL() {
+ return ((HttpSolrServer)client).getBaseURL();
+ }
+ });
+ restTestHarnesses.add(harness);
+ }
+ }
+ @Override
+ public void doTest() throws Exception {
+
+ final int threadCount = 5;
+ setupHarnesses();
+ Thread[] threads = new Thread[threadCount];
+ final List<List> collectErrors = new ArrayList<>();
+
+
+ for(int i=0;i<threadCount;i++){
+ final int finalI = i;
+ threads[i] = new Thread(){
+ @Override
+ public void run() {
+ try {
+ ArrayList errs = new ArrayList();
+ collectErrors.add(errs);
+ invokeBulkCall(finalI,errs);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+ };
+
+ threads[i].start();
+ }
+
+ for (Thread thread : threads) thread.join();
+
+ boolean success = true;
+
+ for (List e : collectErrors) {
+ if(!e.isEmpty()){
+ success = false;
+ log.error(e.toString());
+ }
+
+ }
+
+ assertTrue(success);
+
+
+ }
+
+ private void invokeBulkCall(int seed, ArrayList<String> errs) throws Exception {
+ String payload = "{\n" +
+ " 'add-field' : {\n" +
+ " 'name':'replaceFieldA',\n" +
+ " 'type': 'string',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':false\n" +
+ " },\n" +
+ " 'add-dynamic-field' : {\n" +
+ " 'name' :'replaceDynamicField',\n" +
+ " 'type':'string',\n" +
+ " 'stored':true,\n" +
+ " 'indexed':true\n" +
+ " },\n" +
+ " 'add-copy-field' : {\n" +
+ " 'source' :'replaceFieldA',\n" +
+ " 'dest':['replaceDynamicCopyFieldDest']\n" +
+ " },\n" +
+ " 'add-field-type' : {\n" +
+ " 'name' :'myNewFieldTypeName',\n" +
+ " 'class' : 'solr.StrField',\n" +
+ " 'sortMissingLast':'true'\n" +
+ " }\n" +
+ "\n" +
+ " }";
+ String aField = "a" + seed;
+ String dynamicFldName = "*_lol" + seed;
+ String dynamicCopyFldDest = "hello_lol"+seed;
+ String newFieldTypeName = "mystr" + seed;
+
+
+ RestTestHarness publisher = restTestHarnesses.get(r.nextInt(restTestHarnesses.size()));
+ payload = payload.replace("replaceFieldA1", aField);
+
+ payload = payload.replace("replaceDynamicField", dynamicFldName);
+ payload = payload.replace("dynamicFieldLol","lol"+seed);
+
+ payload = payload.replace("replaceDynamicCopyFieldDest",dynamicCopyFldDest);
+ payload = payload.replace("myNewFieldTypeName", newFieldTypeName);
+ String response = publisher.post("/schema?wt=json", SolrTestCaseJ4.json(payload));
+ Map map = (Map) ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
+ Object errors = map.get("errors");
+ if(errors!= null){
+ errs.add(new String(ZkStateReader.toJSON(errors), StandardCharsets.UTF_8));
+ return;
+ }
+
+ //get another node
+ RestTestHarness harness = restTestHarnesses.get(r.nextInt(restTestHarnesses.size()));
+ long startTime = System.nanoTime();
+ boolean success = false;
+ long maxTimeoutMillis = 100000;
+ Set<String> errmessages = new HashSet<>();
+ while ( ! success
+ && TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS) < maxTimeoutMillis) {
+ errmessages.clear();
+ Map m = getObj(harness, aField, "fields");
+ if(m== null) errmessages.add(format("field {0} not created", aField));
+
+ m = getObj(harness, dynamicFldName, "dynamicFields");
+ if(m== null) errmessages.add(format("dynamic field {0} not created", dynamicFldName));
+
+ List l = getCopyFields(harness, "a1");
+ if(!checkCopyField(l,aField,dynamicCopyFldDest))
+ errmessages.add(format("CopyField source={0},dest={1} not created" , aField,dynamicCopyFldDest));
+
+ m = getObj(harness, "mystr", "fieldTypes");
+ if(m == null) errmessages.add(format("new type {} not created" , newFieldTypeName));
+ Thread.sleep(10);
+ }
+ if(!errmessages.isEmpty()){
+ errs.addAll(errmessages);
+ }
+ }
+
+ private boolean checkCopyField(List<Map> l, String src, String dest) {
+ if(l == null) return false;
+ for (Map map : l) {
+ if(src.equals(map.get("source")) &&
+ dest.equals(map.get("dest"))) return true;
+ }
+ return false;
+ }
+
+
+}
Added: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestSchemaManager.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestSchemaManager.java?rev=1629301&view=auto
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestSchemaManager.java (added)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/schema/TestSchemaManager.java Fri Oct 3 20:00:33 2014
@@ -0,0 +1,77 @@
+package org.apache.solr.schema;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.List;
+
+public class TestSchemaManager extends SolrTestCaseJ4 {
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig.xml","schema-tiny.xml");
+ }
+
+ @Test
+ public void testParsing() throws IOException {
+ String x = "{\n" +
+ " \"add-field\" : {\n" +
+ " \"name\":\"a\",\n" +
+ " \"type\": \"string\",\n" +
+ " \"stored\":true,\n" +
+ " \"indexed\":false\n" +
+ " },\n" +
+ " \"add-field\" : {\n" +
+ " \"name\":\"b\",\n" +
+ " \"type\": \"string\",\n" +
+ " \"stored\":true,\n" +
+ " \"indexed\":false\n" +
+ " }\n" +
+ "\n" +
+ "}";
+
+ List<SchemaManager.Operation> ops = SchemaManager.parse(new StringReader(x));
+ assertEquals(2,ops.size());
+ assertTrue( SchemaManager.captureErrors(ops).isEmpty());
+
+ x = " {\"add-field\" : [{\n" +
+ " \"name\":\"a1\",\n" +
+ " \"type\": \"string\",\n" +
+ " \"stored\":true,\n" +
+ " \"indexed\":false\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\":\"a2\",\n" +
+ " \"type\": \"string\",\n" +
+ " \"stored\":true,\n" +
+ " \"indexed\":true\n" +
+ " }]\n" +
+ " }";
+ ops = SchemaManager.parse(new StringReader(x));
+ assertEquals(2,ops.size());
+ assertTrue( SchemaManager.captureErrors(ops).isEmpty());
+
+ }
+
+
+
+}