in core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/SetSensorWorkflowStep.java [83:207]
protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
EntityValueToSet sensor = context.getInput(SENSOR);
if (sensor==null) throw new IllegalArgumentException("Sensor name is required");
String sensorNameFull = context.resolve(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_INPUT, sensor.name, String.class);
if (Strings.isBlank(sensorNameFull)) throw new IllegalArgumentException("Sensor name is required");
List<Object> sensorNameIndexes = MutableList.of();
String sensorNameBase = extractSensorNameBaseAndPopulateIndices(sensorNameFull, sensorNameIndexes);
TypeToken<?> type = context.lookupType(sensor.type, () -> TypeToken.of(Object.class));
final Entity entity = sensor.entity!=null ? sensor.entity : context.getEntity();
AttributeSensor<Object> sensorBase = (AttributeSensor<Object>) Sensors.newSensor(type, sensorNameBase);
AtomicReference<Object> resolvedValue = new AtomicReference<>();
Object oldValue;
Runnable resolve = () -> {
// // might need to be careful if defined type is different or more generic than type specified here;
// // but that should be fine as XML persistence preserves types
// Sensor<?> sd = entity.getEntityType().getSensor(sensorName);
// if (!type.isSupertypeOf(sd.getTypeToken())) {
// ...
// }
resolvedValue.set(context.getInput(VALUE.getName(), type));
};
DslPredicates.DslPredicate require = context.getInput(REQUIRE);
if (require==null && sensorNameIndexes.isEmpty()) {
resolve.run();
oldValue = entity.sensors().set(sensorBase, resolvedValue.get());
} else {
oldValue = entity.sensors().modify(sensorBase, oldBase -> {
if (require!=null) {
Object old = oldBase;
MutableList<Object> indexes = MutableList.copyOf(sensorNameIndexes);
while (!indexes.isEmpty()) {
Object i = indexes.remove(0);
if (old == null) break;
if (old instanceof Map) old = ((Map) old).get(i);
else if (old instanceof Iterable && i instanceof Integer) {
int ii = (Integer)i;
int size = Iterables.size((Iterable) old);
if (ii==-1) ii = size-1;
old = (ii<0 || ii>=size) ? null : Iterables.get((Iterable) old, ii);
} else {
throw new IllegalArgumentException("Cannot find argument '" + i + "' in " + old);
}
}
if (old == null && !((AbstractEntity.BasicSensorSupport) entity.sensors()).contains(sensorBase.getName())) {
DslPredicates.DslEntityPredicateDefault requireTweaked = new DslPredicates.DslEntityPredicateDefault();
requireTweaked.sensor = sensorNameFull;
requireTweaked.check = WrappedValue.of(require);
if (!requireTweaked.apply(entity)) {
throw new SensorRequirementFailedAbsent("Sensor " + sensorNameFull + " unset or unavailable when there is a non-absent requirement");
}
} else {
if (!require.apply(old)) {
throw new SensorRequirementFailed("Sensor " + sensorNameFull + " value does not match requirement", old);
}
}
}
resolve.run();
// now set
Object result;
if (!sensorNameIndexes.isEmpty()) {
result = oldBase;
// ensure mutable
result = makeMutable(result, sensorNameIndexes);
Object target = result;
MutableList<Object> indexes = MutableList.copyOf(sensorNameIndexes);
while (!indexes.isEmpty()) {
Object i = indexes.remove(0);
boolean isLast = indexes.isEmpty();
Object nextTarget;
if (target instanceof Map) {
nextTarget = ((Map) target).get(i);
if (nextTarget==null || isLast || !(nextTarget instanceof MutableMap)) {
// ensure mutable
nextTarget = isLast ? resolvedValue.get() : makeMutable(nextTarget, indexes);
((Map) target).put(i, nextTarget);
}
} else if (target instanceof Iterable && i instanceof Integer) {
int ii = (Integer)i;
int size = Iterables.size((Iterable) target);
if (ii==-1) ii = size-1;
boolean outOfBounds = ii < 0 || ii >= size;
nextTarget = outOfBounds ? null : Iterables.get((Iterable) target, ii);
if (nextTarget==null || isLast || (!(nextTarget instanceof MutableMap) && !(nextTarget instanceof MutableSet) && !(nextTarget instanceof MutableList))) {
nextTarget = isLast ? resolvedValue.get() : makeMutable(nextTarget, indexes);
if (outOfBounds) {
((Collection) target).add(nextTarget);
} else {
if (!(target instanceof List)) throw new IllegalStateException("Cannot set numerical position index in a non-list collection (and was not otherwise known as mutable; e.g. use MutableSet): "+target);
((List) target).set(ii, nextTarget);
}
}
} else {
throw new IllegalArgumentException("Cannot find argument '" + i + "' in " + target);
}
target = nextTarget;
}
} else {
result = resolvedValue.get();
}
return Maybe.of(result);
});
}
context.noteOtherMetadata("Value set", resolvedValue.get());
if (oldValue!=null) context.noteOtherMetadata("Previous value", oldValue);
return context.getPreviousStepOutput();
}