com.redhat.lightblue.eval.UnsetExpressionEvaluator Maven / Gradle / Ivy
/*
Copyright 2013 Red Hat, Inc. and/or its affiliates.
This file is part of lightblue.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
package com.redhat.lightblue.eval;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.redhat.lightblue.crud.CrudConstants;
import com.redhat.lightblue.metadata.ArrayElement;
import com.redhat.lightblue.metadata.FieldTreeNode;
import com.redhat.lightblue.query.UnsetExpression;
import com.redhat.lightblue.util.JsonDoc;
import com.redhat.lightblue.util.MutablePath;
import com.redhat.lightblue.util.Path;
/**
* Removes a field from a doc.
*
* Removals take place one by one, results of a removal are visible to the
* subsequent operations
*/
public class UnsetExpressionEvaluator extends Updater {
private static final Logger LOGGER = LoggerFactory.getLogger(UnsetExpressionEvaluator.class);
private static final class AbsPath {
/**
* The field to unset
*/
private final Path field;
/**
* If field refers to an array element, the absolute array field
* containing that element
*/
private final Path absArrayField;
/**
* Absolute path to field
*/
private final Path absField;
public AbsPath(Path p, FieldTreeNode fieldNode, Path absField) {
field = p;
if (fieldNode instanceof ArrayElement) {
MutablePath mp = new MutablePath();
fieldNode.getParent().getFullPath(mp);
absArrayField = mp.immutableCopy();
} else {
absArrayField = null;
}
this.absField = absField;
}
public String toString() {
StringBuilder bld = new StringBuilder();
bld.append(field.toString());
if (absArrayField != null) {
bld.append("(arr:").append(absArrayField.toString()).append(")");
}
return bld.toString();
}
}
private final List fields;
private final JsonNodeFactory factory;
public UnsetExpressionEvaluator(JsonNodeFactory factory, FieldTreeNode context, UnsetExpression expr) {
fields = new ArrayList<>(expr.getFields().size());
this.factory = factory;
for (Path p : expr.getFields()) {
FieldTreeNode node = context.resolve(p);
if (node == null) {
throw new EvaluationError(CrudConstants.ERR_INVALID_DEREFERENCE + p);
}
fields.add(new AbsPath(p, node, node.getFullPath()));
}
LOGGER.debug("context {} fields {}", context, fields);
}
@Override
public void getUpdateFields(Set setFields) {
for (AbsPath x : fields) {
setFields.add(x.absField);
}
}
@Override
public boolean update(JsonDoc doc, FieldTreeNode contextMd, Path contextPath) {
boolean ret = false;
MutablePath p = new MutablePath();
for (AbsPath x : fields) {
Path fld = new Path(contextPath, x.field);
LOGGER.debug("Removing {}", fld);
if (doc.modify(fld, null, false) != null) {
ret = true;
if (x.absArrayField != null) {
// This is an array
p.set(x.absArrayField);
p.rewriteIndexes(fld);
ArrayNode node = (ArrayNode) doc.get(p);
p.setLast(p.getLast() + "#");
doc.modify(p, factory.numberNode(node.size()), false);
}
}
}
return ret;
}
}