com.yahoo.document.fieldpathupdate.AssignFieldPathUpdate Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.document.fieldpathupdate;
import com.yahoo.document.Document;
import com.yahoo.document.DocumentCalculator;
import com.yahoo.document.DocumentType;
import com.yahoo.document.datatypes.FieldPathIteratorHandler;
import com.yahoo.document.datatypes.FieldValue;
import com.yahoo.document.datatypes.NumericFieldValue;
import com.yahoo.document.select.parser.ParseException;
import com.yahoo.document.serialization.DocumentUpdateReader;
import com.yahoo.document.serialization.VespaDocumentSerializer6;
import java.util.HashMap;
import java.util.Map;
/**
* @author Thomas Gundersen
*/
public class AssignFieldPathUpdate extends FieldPathUpdate {
class SimpleAssignIteratorHandler extends FieldPathIteratorHandler {
FieldValue newValue;
boolean removeIfZero;
boolean createMissingPath;
SimpleAssignIteratorHandler(FieldValue newValue, boolean removeIfZero, boolean createMissingPath) {
this.newValue = newValue;
this.removeIfZero = removeIfZero;
this.createMissingPath = createMissingPath;
}
@Override
public ModificationStatus doModify(FieldValue fv) {
if (!fv.getDataType().equals(newValue.getDataType())) {
throw new IllegalArgumentException("Trying to assign " + newValue + " of type " + newValue.getDataType() + " to an instance of " + fv.getDataType());
} else {
if (removeIfZero && (newValue instanceof NumericFieldValue) && ((NumericFieldValue)newValue).getNumber().longValue() == 0) {
return ModificationStatus.REMOVED;
}
fv.assign(newValue);
}
return ModificationStatus.MODIFIED;
}
@Override
public boolean createMissingPath() {
return createMissingPath;
}
@Override
public boolean onComplex(FieldValue fv) {
return false;
}
}
class MathAssignIteratorHandler extends FieldPathIteratorHandler {
DocumentCalculator calc;
Document doc;
boolean removeIfZero;
boolean createMissingPath;
MathAssignIteratorHandler(String expression, Document doc, boolean removeIfZero, boolean createMissingPath) throws ParseException {
this.calc = new DocumentCalculator(expression);
this.doc = doc;
this.removeIfZero = removeIfZero;
this.createMissingPath = createMissingPath;
}
@Override
public ModificationStatus doModify(FieldValue fv) {
if (fv instanceof NumericFieldValue) {
Map vars = new HashMap();
for (Map.Entry entry : getVariables().entrySet()) {
if (entry.getValue().getKey() != null && entry.getValue().getKey() instanceof NumericFieldValue) {
vars.put(entry.getKey(), ((NumericFieldValue)entry.getValue().getKey()).getNumber());
} else {
vars.put(entry.getKey(), entry.getValue().getIndex());
}
}
vars.put("value", ((NumericFieldValue)fv).getNumber());
try {
Number d = calc.evaluate(doc, vars);
if (removeIfZero && d.longValue() == 0) {
return ModificationStatus.REMOVED;
} else {
fv.assign(calc.evaluate(doc, vars));
}
} catch (IllegalArgumentException e) {
// Ignore divide by zero
return ModificationStatus.NOT_MODIFIED;
}
} else {
throw new IllegalArgumentException("Trying to perform arithmetic on " + fv + " of type " + fv.getDataType());
}
return ModificationStatus.MODIFIED;
}
@Override
public boolean createMissingPath() {
return createMissingPath;
}
@Override
public boolean onComplex(FieldValue fv) {
return false;
}
}
FieldValue fieldValue = null;
String expression = null;
boolean createMissingPath = true;
boolean removeIfZero = false;
// Flag bits
public static final int ARITHMETIC_EXPRESSION = 1;
public static final int REMOVE_IF_ZERO = 2;
public static final int CREATE_MISSING_PATH = 4;
/**
* Creates an assignment update that overwrites the old value with the given new value.
*
* @param type The document type the assignment works on.
* @param fieldPath The field path of the field to be overwritten.
* @param whereClause A document selection string that selects documents and variables to be updated.
* @param newValue The new value of the assignment.
*/
public AssignFieldPathUpdate(DocumentType type, String fieldPath, String whereClause, FieldValue newValue) {
super(FieldPathUpdate.Type.ASSIGN, type, fieldPath, whereClause);
setNewValue(newValue);
}
public AssignFieldPathUpdate(DocumentType type, String fieldPath, FieldValue newValue) {
super(FieldPathUpdate.Type.ASSIGN, type, fieldPath, null);
setNewValue(newValue);
}
/**
* Creates an assign statement based on a mathematical expression.
*
* @param type The document type the assignment works on.
* @param fieldPath The field path of the field to be overwritten.
* @param whereClause A document selection string that selects documents and variables to be updated.
* @param expression The mathematical expression to apply. Use $value to signify the previous value of the field.
*/
public AssignFieldPathUpdate(DocumentType type, String fieldPath, String whereClause, String expression) {
super(FieldPathUpdate.Type.ASSIGN, type, fieldPath, whereClause);
setExpression(expression);
}
/**
* Creates an assign update from a serialized object.
*
* @param type The document type the assignment will work on.
* @param reader A reader that can deserialize something into this object.
*/
public AssignFieldPathUpdate(DocumentType type, DocumentUpdateReader reader) {
super(FieldPathUpdate.Type.ASSIGN, type, reader);
reader.read(this);
}
public AssignFieldPathUpdate(DocumentType type, String fieldPath) {
super(FieldPathUpdate.Type.ASSIGN, type, fieldPath, null);
}
/**
* Turns this assignment into a literal one.
*
* @param value The new value to assign to the document.
*/
public void setNewValue(FieldValue value) {
fieldValue = value;
expression = null;
}
/**
*
* @return Returns the value to assign, or null if this is a mathematical expression.
*/
public FieldValue getNewValue() {
return fieldValue;
}
/**
* Turns this assignment into a mathematical expression assignment.
*
* @param value The expression to use for assignment.
*/
public void setExpression(String value) {
expression = value;
fieldValue = null;
}
/**
*
* @return Returns the arithmetic expression to assign, or null if this is not a mathematical expression.
*/
public String getExpression() {
return expression;
}
/**
* If set to true, and the new value assigned evaluates to a numeric value of 0, removes the value instead of setting it.
* Default is false.
*/
public void setRemoveIfZero(boolean removeIfZero) {
this.removeIfZero = removeIfZero;
}
/**
* If set to true, and any part of the field path specified does not exist (except for array indexes), we create the path as necessary.
* Default is true.
*/
public void setCreateMissingPath(boolean createMissingPath) {
this.createMissingPath = createMissingPath;
}
/**
*
* @return Returns true if this assignment is an arithmetic operation.
*/
public boolean isArithmetic() {
return expression != null;
}
FieldPathIteratorHandler getIteratorHandler(Document doc) {
if (expression != null) {
try {
return new MathAssignIteratorHandler(expression, doc, removeIfZero, createMissingPath);
} catch (ParseException e) {
return null;
}
} else {
return new SimpleAssignIteratorHandler(fieldValue, removeIfZero, createMissingPath);
}
}
@Override
public void serialize(VespaDocumentSerializer6 data) {
data.write(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
AssignFieldPathUpdate that = (AssignFieldPathUpdate) o;
if (createMissingPath != that.createMissingPath) return false;
if (removeIfZero != that.removeIfZero) return false;
if (expression != null ? !expression.equals(that.expression) : that.expression != null) return false;
if (fieldValue != null ? !fieldValue.equals(that.fieldValue) : that.fieldValue != null) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (fieldValue != null ? fieldValue.hashCode() : 0);
result = 31 * result + (expression != null ? expression.hashCode() : 0);
result = 31 * result + (createMissingPath ? 1 : 0);
result = 31 * result + (removeIfZero ? 1 : 0);
return result;
}
@Override
public String toString() {
return "Assign: " + super.toString() + " : " + (isArithmetic() ? getExpression() : getNewValue().toString());
}
public boolean getCreateMissingPath() {
return createMissingPath;
}
public boolean getRemoveIfZero() {
return removeIfZero;
}
public FieldValue getFieldValue() {
return fieldValue;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy