Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.rbmhtechnology.vind.model.InverseSearchQuery Maven / Gradle / Ivy
package com.rbmhtechnology.vind.model;
import com.rbmhtechnology.vind.api.Document;
import com.rbmhtechnology.vind.api.query.filter.Filter;
import com.rbmhtechnology.vind.api.query.inverseSearch.InverseSearchQueryFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.rbmhtechnology.vind.model.DocumentFactory.ID;
import static com.rbmhtechnology.vind.model.DocumentFactory.TYPE;
import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.nonNull;
public class InverseSearchQuery {
private Logger log = LoggerFactory.getLogger(getClass());
private final Filter query;
private final Map values = new HashMap<>();
private final String id;
private final String type;
private float score;
private final DocumentFactory factory;
protected InverseSearchQuery(String id, Filter query, DocumentFactory factory) {
this.id = id;
this.type = factory.getType();
this.query = query;
this.factory = factory;
final byte[] serializedQuery;
try {
serializedQuery = serializeQuery(this.query);
} catch (IOException e) {
throw new RuntimeException("Error serializing query to byte []: " + e.getMessage(),e);
}
this.setValue(InverseSearchQueryFactory.BINARY_QUERY_FIELD, ByteBuffer.wrap(serializedQuery));
}
public static byte[] serializeQuery(Filter query) throws IOException
{
final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
final ObjectOutputStream oos = new ObjectOutputStream(bytesOut);
oos.writeObject(query);
oos.flush();
byte[] bytes = bytesOut.toByteArray();
bytesOut.close();
oos.close();
return bytes;
}
public InverseSearchQuery setValue(String field, Object value) {
if (this.hasField(field)) {
FieldDescriptor descriptor = this.listFieldDescriptors().get(field);
checkField(field,value);
if (descriptor.isMultiValue()) {
if(Collection.class.isAssignableFrom(value.getClass())) {
this.values.put(field,value);
} else {
Collection validValues = new ArrayList<>();
validValues.add(value);
this.values.put(field,validValues);
}
} else {
this.values.put(field,value);
}
} else {
log.error("There is no such field name [{}] for this document", field);
throw new IllegalArgumentException("There is no such field name [" + field + "] for this document");
}
return this;
}
public InverseSearchQuery setValue(FieldDescriptor field, T value) {
checkField(field.getName(), value);
return this.setValue(field.getName(), value);
}
public InverseSearchQuery setValues(String field, Object... values) {
if (this.hasField(field)) {
if (this.listFieldDescriptors().get(field).isMultiValue()) {
Collection validValues = new ArrayList<>();
for(Object value: values) {
checkField(field, value);
validValues.add(value);
}
this.values.put(field, validValues);
} else {
log.error("Invalid operation: Field {} is not multivalued", field);
throw new IllegalArgumentException("Invalid operation: Field "+field+" is not multivalued");
}
} else {
log.error("There is no such a field name [{}] for this document", field);
throw new IllegalArgumentException("There is no such a field name [" + field+"] for this document");
}
return this;
}
public InverseSearchQuery setValues(MultiValueFieldDescriptor field, T... value) {
return this.setValues(field, value);
}
public InverseSearchQuery setValues(MultiValuedComplexField field, T... value) {
return this.setValues(field.getName(), value);
}
public InverseSearchQuery setValues(String field, Collection> values) {
checkField(field, values);
this.values.put(field, values);
return this;
}
public InverseSearchQuery setValues(MultiValueFieldDescriptor field, Collection value) {
return this.setValues(field, value);
}
public InverseSearchQuery setContextualizedValues(MultiValuedComplexField field, Collection value) {
return this.setValues(field.getName(), value); }
public InverseSearchQuery setValues(MultiValuedComplexField field, Collection value) {
return this.setValues(field.getName(), value);
}
public InverseSearchQuery clear(String field) {
checkField(field, null);
values.remove(field);
return this;
}
public InverseSearchQuery clear(FieldDescriptor> field) {
return this.clear(field.getName());
}
protected void checkField(String field, Object val) {
if(field == null || ID.equals(field) || TYPE.equals(field)){
log.error("Invalid field name {}: unable to modify the aforementioned field.", field);
throw new IllegalArgumentException("Invalid field name "+field+": unable to modify the aforementioned field.");
}
if (!this.listFieldDescriptors().containsKey(field)) {
log.error("The field {} does not exist in this factory",field);
throw new IllegalArgumentException("The field " + field + " does not exist in this factory");
} else if (val != null) {
FieldDescriptor> fieldDescriptor = this.listFieldDescriptors().get(field);
//Check if it is a multivalued parameter
if(Collection.class.isAssignableFrom(val.getClass())) {
//Find elements in the collection which are not valid types
final Collection valueCollection = (Collection) val;
Optional notValidOptional;
if(ComplexFieldDescriptor.class.isAssignableFrom(fieldDescriptor.getClass())) {
Class storeType = ((ComplexFieldDescriptor) fieldDescriptor).getStoreType();
notValidOptional = valueCollection.stream()
.filter(t -> !(storeType.isAssignableFrom(t.getClass()) || fieldDescriptor.getType().isAssignableFrom(t.getClass())))
.findAny();
} else {
notValidOptional = valueCollection.stream()
.filter(t -> !fieldDescriptor.getType().isAssignableFrom(t.getClass()))
.findAny();
}
//check if the fieldDescriptor is set as multivalued and there are no invalid elements on the parameter collection
if (fieldDescriptor.isMultiValue()) {
if (notValidOptional.isPresent()) {
Object invalidVal = notValidOptional.get();
log.error("Value: '{}' of type [{}] is not assignable to field descriptor '{}' of type [{}]", invalidVal, invalidVal.getClass(), fieldDescriptor.getName(), fieldDescriptor.getType());
throw new IllegalArgumentException(MessageFormat.format(
"Value: ''{0}'' of type [{1}] is not assignable to field descriptor ''{2}'' of type [{3}]",
invalidVal, invalidVal.getClass(), fieldDescriptor.getName(), fieldDescriptor.getType()));
}
} else {
log.error("A collection can not be assigned to Field descriptor '{}', it is not a multivalued field", fieldDescriptor.getName());
throw new IllegalArgumentException("A collection can not be assigned to Field descriptor '" + fieldDescriptor.getName() +
"', it is not a multivalued field");
}
}else{
if(ComplexFieldDescriptor.class.isAssignableFrom(fieldDescriptor.getClass())) {
if (!fieldDescriptor.getType().isAssignableFrom(val.getClass())){
Class storeType = ((ComplexFieldDescriptor) fieldDescriptor).getStoreType();
if (storeType != null && !(storeType.isAssignableFrom(val.getClass()) )) {
log.error("Value: '{}' of type [{}] is not assignable to field descriptor '{}' of type [{}]",val, val.getClass(), fieldDescriptor.getName(),storeType);
throw new IllegalArgumentException(MessageFormat.format(
"Value: ''{0}'' of type [{1}] is not assignable to field descriptor ''{2}'' of type [{3}]",
val, val.getClass(), fieldDescriptor.getName(), storeType));
}
}
} else
if (!fieldDescriptor.getType().isAssignableFrom(val.getClass())) {
log.error("Value: '{}' of type [{}] is not assignable to field descriptor '{}' of type [{}]",val, val.getClass(), fieldDescriptor.getName(),fieldDescriptor.getType());
throw new IllegalArgumentException(MessageFormat.format(
"Value: ''{0}'' of type [{1}] is not assignable to field descriptor ''{2}'' of type [{3}]",
val, val.getClass(), fieldDescriptor.getName(), fieldDescriptor.getType()));
}
}
}
}
public InverseSearchQuery addValue(String field, Object value) {
checkField(field, value);
final FieldDescriptor fieldDescriptor = this.listFieldDescriptors().get(field);
if (!fieldDescriptor.isMultiValue()) {
log.error("Invalid operation: The field {} is not multivalued.", field);
throw new IllegalArgumentException("Invalid operation: The field "+field+" is not multivalued.");
}
Collection values = (Collection) this.values.get(field);
if (values == null) {
values = new ArrayList<>();
}
this.values.put(field, values);
return this;
}
public InverseSearchQuery addValue(MultiValueFieldDescriptor field, T value) {
return this.addValue(field, value);
}
public InverseSearchQuery addValue(MultiValuedComplexField field, T value) {
return this.addValue(field.getName(), value);
}
public InverseSearchQuery removeValue(String field, Object value) {
checkField(field, value);
Collection values = (Collection) this.values.get(field);
if (values == null) {
return this;
}
values.remove(value);
this.values.put(field, values);
return this;
}
public Document removeValue(FieldDescriptor field, T value) {
return this.removeValue(field, value);
}
public Object getValue(String field) {
if (ID.equals(field)) return getId(); //TODO should this work?
if (TYPE.equals(field)) return getType();//TODO should this work?
checkField(field, null);
return this.values.get(field);
}
public T getValue(FieldDescriptor descriptor) {
String field = descriptor.getName();
return (T) this.getValue(field);
}
public T getValue(String field, Class clazz) {
Object objectValue = this.getValue(field);
if (clazz.isAssignableFrom(objectValue.getClass())) {
return clazz.cast(objectValue);
} else {
log.error("Incompatible types: Field type [{}] does not mach parameter type [{}]",objectValue.getClass(),clazz);
throw new IllegalArgumentException("Incompatible types: Field type ["+objectValue.getClass()+"] does not mach parameter type ["+clazz+"]");
}
}
public String getId() {
return this.id;
}
public String getType() {
return type;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public boolean hasValue(String field) {
return ID.equals(field) || TYPE.equals(field) || (nonNull(values.get(field)));
}
public boolean hasValue(FieldDescriptor descriptor) {
return hasValue(descriptor.getName());
}
public boolean hasField(String fieldName) {
return ID.equals(fieldName) || TYPE.equals(fieldName) || this.listFieldDescriptors().containsKey(fieldName);
}
public FieldDescriptor> getFieldDescriptor(String fieldName) {
return this.listFieldDescriptors().get(fieldName);
}
public Map> listFieldDescriptors() {
return unmodifiableMap(factory.getInverseSearchMetaFields());
}
public Map getValues() {
Map collect = this.values.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey, entry -> entry.getValue()));
return collect;
}
public DocumentFactory getFactory() {
return factory;
}
public Filter getQuery() {
return query;
}
@Override
public String toString() {
return "DocumentImpl{" +
"query= "+query+
"metadata= " + values +
", id='" + getValue(DocumentFactory.ID, String.class) + '\'' +
", type='" + type + '\'' +
'}';
}
}