use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class MaskComposition method interpret.
@Override
public void interpret(InterpreterContext instrCtx) {
Instruction instruction = instrCtx.getCurrentInstruction();
if ((!(instruction.getData().getClass() == DataMap.class)) || (!(instruction.getOperation().getClass() == DataMap.class))) {
instrCtx.addErrorMessage("data and operation in composition instruction have to be of type DataMap, instruction: %1$s", instruction);
} else {
DataMap data = (DataMap) instruction.getData();
DataMap op = (DataMap) instruction.getOperation();
Object opWildcard = op.get(FilterConstants.WILDCARD);
Object dataWildcard = data.get(FilterConstants.WILDCARD);
if ((opWildcard != null && opWildcard.equals(FilterConstants.NEGATIVE)) || (dataWildcard != null && dataWildcard.equals(FilterConstants.NEGATIVE))) {
handleNegativeWildcard(data);
} else {
//process array range
composeArrayRange(data, op, instrCtx);
// process all fields
for (Entry<String, Object> entry : op.entrySet()) {
String fieldName = entry.getKey();
Object opMask = entry.getValue();
Object dataMask = data.get(fieldName);
if (!fieldName.equals(FilterConstants.START) && !fieldName.equals(FilterConstants.COUNT)) {
composeField(fieldName, opMask, dataMask, data, dataWildcard, instrCtx);
}
}
}
}
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class MaskComposition method composeField.
/**
* This method handles logic for single field composition.
* @return true if operation was successful and false otherwise
*/
private boolean composeField(final String fieldName, /**
* opMask is not final, because operation side of instruction should not be
* changed, so whenever it has to be merged with 1, clone is created
*/
Object opMask, final Object dataMask, final DataMap data, final Object dataWildcard, InterpreterContext instrCtx) {
instrCtx.setCurrentField(fieldName);
boolean failed = false;
if (dataMask == null) {
// avoid copying 1 if there exist wildcard with value 1
if (!opMask.equals(FilterConstants.POSITIVE) || !isMarkedAsMergedWith1(data))
// missing fields are copied
data.put(fieldName, opMask);
} else if (dataMask instanceof Integer) {
//if it is positive, then
if (((Integer) dataMask).equals(FilterConstants.POSITIVE)) {
if (opMask instanceof Integer) {
Integer merged = merge((Integer) dataMask, (Integer) opMask, instrCtx);
if (merged != null)
data.put(fieldName, merged);
else
failed = true;
} else if (opMask.getClass() == DataMap.class) {
opMask = cloneDataMap((DataMap) opMask, instrCtx);
if (opMask != null) {
if (!mergeWith1((DataMap) opMask, data, fieldName))
data.put(fieldName, opMask);
} else
failed = true;
} else {
instrCtx.addErrorMessage("field mask value of unsupported type: %1$s", opMask.getClass().getName());
failed = true;
}
}
} else if (dataMask.getClass() == DataMap.class) {
if (opMask instanceof Integer) {
if (((Integer) opMask).equals(FilterConstants.NEGATIVE))
data.put(fieldName, FilterConstants.NEGATIVE);
else
mergeWith1((DataMap) dataMask, data, fieldName);
} else if (opMask.getClass() == DataMap.class)
instrCtx.scheduleInstruction(new Instruction((DataMap) opMask, (DataMap) dataMask, instrCtx.getPath()));
else {
instrCtx.addErrorMessage("field mask value of unsupported type: %1$s", opMask.getClass().getName());
failed = true;
}
} else {
instrCtx.addErrorMessage("field mask value of unsupported type: %1$s", dataMask.getClass().getName());
failed = true;
}
//return true if operation was successful and false otherwise
return !failed;
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class MaskTree method addOperation.
/**
* Add an operation to this {@link MaskTree}, given a path indicating the field to which the operation
* applies and a {@link MaskOperation} representing the operation to be applied.
* @param path the path of the field to which the operation applies
* @param op the MaskOperation to be performed on the field
*/
public void addOperation(PathSpec path, MaskOperation op) {
List<String> segments = path.getPathComponents();
final DataMap fieldMask = new DataMap();
//map variable contains DataMap, into which current segment will be put
DataMap map = fieldMask;
for (int ii = 0; ii < segments.size() - 1; ++ii) {
String segment = Escaper.escapePathSegment(segments.get(ii));
DataMap childMap = new DataMap();
map.put(segment, childMap);
map = childMap;
}
String lastSegment = Escaper.escapePathSegment(segments.get(segments.size() - 1));
map.put(lastSegment, op.getRepresentation());
//compose existing tree with mask for specific field
try {
new DataComplexProcessor(new MaskComposition(), fieldMask, _representation).run(false);
} catch (DataProcessingException e) {
throw new IllegalStateException("error while building mask tree", e);
}
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class MaskTree method getOperationsImpl.
private void getOperationsImpl(DataMap data, PathSpec path, Map<PathSpec, MaskOperation> result) {
for (Map.Entry<String, Object> entry : data.entrySet()) {
String segment = Escaper.unescapePathSegment(entry.getKey());
PathSpec subpath = new PathSpec(path.getPathComponents(), segment);
Object value = entry.getValue();
if (value instanceof Integer) {
if (value.equals(MaskOperation.NEGATIVE_MASK_OP.getRepresentation())) {
result.put(subpath, MaskOperation.NEGATIVE_MASK_OP);
} else if (value.equals(MaskOperation.POSITIVE_MASK_OP.getRepresentation())) {
result.put(subpath, MaskOperation.POSITIVE_MASK_OP);
} else {
throw new IllegalStateException("invalid mask tree");
}
} else if (value.getClass() == DataMap.class) {
getOperationsImpl((DataMap) value, subpath, result);
} else {
throw new IllegalStateException("invalid mask tree");
}
}
}
use of com.linkedin.data.DataMap in project rest.li by linkedin.
the class Patch method interpret.
/**
* Interpret and execute the current instruction based on the
* interpreter context.
*
* @param instrCtx the current interpreter context
*/
public void interpret(final InterpreterContext instrCtx) {
Instruction instruction = instrCtx.getCurrentInstruction();
// operation's node is always DataMap
assert instruction.getOperation().getClass() == DataMap.class;
// data's node is always DataMap
assert instruction.getData().getClass() == DataMap.class;
//_usedFields variable is used to keep track of fields, which were already used
//at this nodes. The reason for it is that if field should not be used in more than
//one operation e.g. $set and $delete, because such patch becomes ambiguous.
//Each operation, upon being executed updates this variable.
final Map<String, String> usedFields = new HashMap<String, String>();
DataMap opNode = (DataMap) instruction.getOperation();
DataMap dataNode = (DataMap) instruction.getData();
/**
* Apply all supported operations here. _usedFields is used to keep track of fields
* that operations were applied to.
*/
executeSetCommand(opNode.get(SET_COMMAND), dataNode, usedFields, instrCtx);
executeDeleteCommand(opNode.get(DELETE_COMMAND), dataNode, usedFields, instrCtx);
// iterate over children
for (Entry<String, Object> entry : opNode.entrySet()) processChild(dataNode, entry.getKey(), entry.getValue(), usedFields, instrCtx);
}
Aggregations