/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed 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.springframework.data.solr.core.schema;
import java.util.Map;
import org.apache.solr.client.solrj.request.schema.SchemaRequest;
import org.apache.solr.client.solrj.response.schema.SchemaRepresentation;
import org.apache.solr.client.solrj.response.schema.SchemaResponse.UpdateResponse;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.schema.SchemaDefinition.CopyFieldDefinition;
import org.springframework.data.solr.core.schema.SchemaDefinition.FieldDefinition;
import org.springframework.data.solr.core.schema.SchemaDefinition.SchemaField;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
* {@link SchemaOperations} implementation based on {@link SolrTemplate}.
*
* @author Christoph Strobl
* @since 2.1
*/
public class DefaultSchemaOperations implements SchemaOperations {
private final SolrTemplate template;
private final String collection;
public DefaultSchemaOperations(String collection, SolrTemplate template) {
Assert.hasText(collection, "Collection must not be null or empty!");
Assert.notNull(template, "Template must not be null.");
this.template = template;
this.collection = collection;
}
/*
* (non-Javadoc)
* @see org.springframework.data.solr.core.schema.SchemaOperations#getSchemaName()
*/
@Override
public String getSchemaName() {
return template
.execute(solrClient -> new SchemaRequest.SchemaName().process(solrClient, collection).getSchemaName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.solr.core.schema.SchemaOperations#getSchemaVersion()
*/
@Override
public Double getSchemaVersion() {
return template.execute(
solrClient -> new Double(new SchemaRequest.SchemaVersion().process(solrClient, collection).getSchemaVersion()));
}
/*
* (non-Javadoc)
* @see org.springframework.data.solr.core.schema.SchemaOperations#readSchema()
*/
@Override
public SchemaDefinition readSchema() {
SchemaRepresentation representation = template
.execute(solrClient -> new SchemaRequest().process(solrClient, collection).getSchemaRepresentation());
SchemaDefinition sd = new SchemaDefinition(collection);
for (Map<String, Object> fieldValueMap : representation.getFields()) {
sd.addFieldDefinition(FieldDefinition.fromMap(fieldValueMap));
}
for (Map<String, Object> fieldValueMap : representation.getCopyFields()) {
CopyFieldDefinition cf = CopyFieldDefinition.fromMap(fieldValueMap);
sd.addCopyField(cf);
if (sd.getFieldDefinition(cf.getSource()) != null) {
sd.getFieldDefinition(cf.getSource()).setCopyFields(cf.getDestination());
}
}
return sd;
}
/*
* (non-Javadoc)
* @see org.springframework.data.solr.core.schema.SchemaOperations#addField(org.springframework.data.solr.core.schema.SchemaDefinition.SchemaField)
*/
@Override
public void addField(final SchemaField field) {
if (field instanceof FieldDefinition) {
addField((FieldDefinition) field);
} else if (field instanceof CopyFieldDefinition) {
addCopyField((CopyFieldDefinition) field);
}
}
private void addField(final FieldDefinition field) {
template.execute(solrClient -> {
UpdateResponse response = new SchemaRequest.AddField(field.asMap()).process(solrClient, collection);
if (hasErrors(response)) {
throw new SchemaModificationException(
String.format("Adding field %s with args %s to collection %s failed with status %s. Server returned %s.",
field.getName(), field.asMap(), collection, response.getStatus(), response));
}
return Integer.valueOf(response.getStatus());
});
if (!CollectionUtils.isEmpty(field.getCopyFields())) {
CopyFieldDefinition cf = new CopyFieldDefinition();
cf.setSource(field.getName());
cf.setDestination(field.getCopyFields());
addCopyField(cf);
}
}
private void addCopyField(final CopyFieldDefinition field) {
template.execute(solrClient -> {
UpdateResponse response = new SchemaRequest.AddCopyField(field.getSource(), field.getDestination())
.process(solrClient, collection);
if (hasErrors(response)) {
throw new SchemaModificationException(String.format(
"Adding copy field %s with destinations %s to collection %s failed with status %s. Server returned %s.",
field.getSource(), field.getDestination(), collection, response.getStatus(), response));
}
return Integer.valueOf(response.getStatus());
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.solr.core.schema.SchemaOperations#removeField(java.lang.String)
*/
@Override
public void removeField(final String name) {
template.execute(solrClient -> {
UpdateResponse response = new SchemaRequest.DeleteField(name).process(solrClient, collection);
if (hasErrors(response)) {
throw new SchemaModificationException(
String.format("Removing field with name %s from collection %s failed with status %s. Server returned %s.",
name, collection, response.getStatus(), response));
}
return Integer.valueOf(response.getStatus());
});
}
private boolean hasErrors(UpdateResponse response) {
if (response.getStatus() != 0
|| response.getResponse() != null && !CollectionUtils.isEmpty(response.getResponse().getAll("errors"))) {
return true;
}
return false;
}
}