// in reverse order of how they should execute, as that is the way adding a Stage.IMMEDIATE step works
// Last to execute is the handler that assembles the overall response from the pieces created by all the other steps
final ReadResourceAssemblyHandler assemblyHandler = new ReadResourceAssemblyHandler(directAttributes, metrics, otherAttributes, directChildren, childResources);
context.addStep(assemblyHandler, queryRuntime ? OperationContext.Stage.VERIFY : OperationContext.Stage.IMMEDIATE, queryRuntime);
final ImmutableManagementResourceRegistration registry = context.getResourceRegistration();
// Get the model for this resource.
final Resource resource = nullSafeReadResource(context, registry);
final Map<String, Set<String>> childrenByType = registry != null ? getChildAddresses(registry, resource, null) : Collections.<String, Set<String>>emptyMap();
final ModelNode model = resource.getModel();
if (model.isDefined()) {
// Store direct attributes first
for (String key : model.keys()) {
// In case someone put some garbage in it
if (!childrenByType.containsKey(key)) {
directAttributes.put(key, model.get(key));
}
}
if (defaults) {
//get the model description
final DescriptionProvider descriptionProvider = registry.getModelDescription(PathAddress.EMPTY_ADDRESS);
final Locale locale = getLocale(context, operation);
final ModelNode nodeDescription = descriptionProvider.getModelDescription(locale);
if (nodeDescription.isDefined() && nodeDescription.hasDefined(ATTRIBUTES)) {
for (String key : nodeDescription.get(ATTRIBUTES).keys()) {
if ((!childrenByType.containsKey(key)) &&
(!directAttributes.containsKey(key) || !directAttributes.get(key).isDefined()) &&
nodeDescription.get(ATTRIBUTES).hasDefined(key) &&
nodeDescription.get(ATTRIBUTES, key).hasDefined(DEFAULT)) {
directAttributes.put(key, nodeDescription.get(ATTRIBUTES, key, DEFAULT));
}
}
}
}
}
// Next, process child resources
for (Map.Entry<String, Set<String>> entry : childrenByType.entrySet()) {
String childType = entry.getKey();
Set<String> children = entry.getValue();
if (children.isEmpty()) {
// Just treat it like an undefined attribute
directAttributes.put(childType, new ModelNode());
} else {
for (String child : children) {
boolean storeDirect = !recursive;
if (recursive) {
PathElement childPE = PathElement.pathElement(childType, child);
PathAddress relativeAddr = PathAddress.pathAddress(childPE);
ImmutableManagementResourceRegistration childReg = registry.getSubModel(relativeAddr);
if (childReg == null) {
throw new OperationFailedException(new ModelNode().set(MESSAGES.noChildRegistry(childType, child)));
}
// Decide if we want to invoke on this child resource
boolean proxy = childReg.isRemote();
boolean runtimeResource = childReg.isRuntimeOnly();
if (!runtimeResource || (queryRuntime && !proxy) || (proxies && proxy)) {
final int newDepth = recursiveDepth > 0 ? recursiveDepth - 1 : 0;
// Add a step to read the child resource
ModelNode rrOp = new ModelNode();
rrOp.get(OP).set(opName);
rrOp.get(OP_ADDR).set(PathAddress.pathAddress(address, childPE).toModelNode());
rrOp.get(RECURSIVE).set(operation.get(RECURSIVE));
rrOp.get(RECURSIVE_DEPTH).set(newDepth);
rrOp.get(PROXIES).set(proxies);
rrOp.get(INCLUDE_RUNTIME).set(queryRuntime);
ModelNode rrRsp = new ModelNode();
childResources.put(childPE, rrRsp);
OperationStepHandler rrHandler = childReg.getOperationHandler(PathAddress.EMPTY_ADDRESS, opName);
context.addStep(rrRsp, rrOp, rrHandler, OperationContext.Stage.IMMEDIATE);
} else {
storeDirect = true;
}
}