use of org.jboss.hal.dmr.Composite in project console by hal.
the class DeploymentResources method readChildren.
public <T extends DeploymentResource> void readChildren(String subsystem, String resource, DeploymentResourceSupplier<T> supplier, Consumer<List<T>> callback) {
// /deployment=*/subsystem=<subsystem>:read-children-resources(child-type=<resource>)
// fails with "WFLYCTL0217: Child resource '\"deployment\" => \"*\"' not found"
// That's why we use: /deployment=*/subsystem=<subsystem>/<resource>=*:read-resource()
ResourceAddress deploymentAddress = DEPLOYMENT_TEMPLATE.append(SUBSYSTEM + "=" + subsystem).append(resource + "=*").resolve(statementContext);
Operation deploymentJobOperation = new Operation.Builder(deploymentAddress, READ_RESOURCE_OPERATION).param(INCLUDE_RUNTIME, true).param(RECURSIVE, true).build();
ResourceAddress subdeploymentAddress = SUBDEPLOYMENT_TEMPLATE.append(SUBSYSTEM + "=" + subsystem).append(resource + "=*").resolve(statementContext);
Operation subdeploymentJobOperation = new Operation.Builder(subdeploymentAddress, READ_RESOURCE_OPERATION).param(INCLUDE_RUNTIME, true).param(RECURSIVE, true).build();
dispatcher.execute(new Composite(deploymentJobOperation, subdeploymentJobOperation), (CompositeResult result) -> {
List<T> nodes = new ArrayList<>();
Consumer<ModelNode> nodeConsumer = node -> {
ResourceAddress address = new ResourceAddress(node.get(ADDRESS));
nodes.add(supplier.get(address, node.get(RESULT)));
};
result.step(0).get(RESULT).asList().forEach(nodeConsumer);
result.step(1).get(RESULT).asList().forEach(nodeConsumer);
callback.accept(nodes);
}, (operation, failure) -> {
logger.error("Unable to read {}/{} deployment resources: {}", subsystem, resource, failure);
callback.accept(emptyList());
});
}
use of org.jboss.hal.dmr.Composite in project console by hal.
the class CredentialReference method addCredentialReference.
private void addCredentialReference(String baseId, Metadata crMetadata, String credentialReferenceName, String alternativeName, Supplier<ResourceAddress> address, Callback callback) {
ResourceAddress fqAddress = address.get();
if (fqAddress != null) {
String id = Ids.build(baseId, credentialReferenceName, Ids.ADD);
Form<ModelNode> form = new ModelNodeForm.Builder<>(id, crMetadata).addOnly().include(STORE, ALIAS, CLEAR_TEXT, TYPE).unsorted().build();
form.addFormValidation(new CrFormValuesValidation(resources));
new AddResourceDialog(resources.messages().addResourceTitle(Names.CREDENTIAL_REFERENCE), form, (name, model) -> {
if (alternativeName != null) {
Operation undefine = new Operation.Builder(fqAddress, UNDEFINE_ATTRIBUTE_OPERATION).param(NAME, alternativeName).build();
Operation write = new Operation.Builder(fqAddress, WRITE_ATTRIBUTE_OPERATION).param(NAME, credentialReferenceName).param(VALUE, model).build();
dispatcher.execute(new Composite(undefine, write), (CompositeResult result) -> {
MessageEvent.fire(eventBus, Message.success(resources.messages().addSingleResourceSuccess(Names.CREDENTIAL_REFERENCE)));
callback.execute();
});
} else {
ca.add(credentialReferenceName, Names.CREDENTIAL_REFERENCE, fqAddress, model, callback);
}
}).show();
} else {
MessageEvent.fire(eventBus, Message.error(resources.messages().credentialReferenceAddressError()));
}
}
use of org.jboss.hal.dmr.Composite in project console by hal.
the class OperationFactory method fromChangeSet.
/**
* Turns a change-set into a composite operation containing
* {@linkplain org.jboss.hal.dmr.ModelDescriptionConstants#WRITE_ATTRIBUTE_OPERATION write-attribute} and
* {@linkplain org.jboss.hal.dmr.ModelDescriptionConstants#UNDEFINE_ATTRIBUTE_OPERATION undefine-attribute} operations.
* <p>
* The composite operation will contain {@linkplain org.jboss.hal.dmr.ModelDescriptionConstants#UNDEFINE_ATTRIBUTE_OPERATION
* undefine-attribute} operations which reflect the alternative attributes as defined in the specified metadata.
*
* @param address the fq address used for the operations
* @param changeSet the changed values
* @param metadata the metadata which should contain the attribute definitions of the change-set
*/
public Composite fromChangeSet(ResourceAddress address, Map<String, Object> changeSet, Metadata metadata) {
// TODO Is it safe to always use ATTRIBUTES as path when calling ResourceDescription methods?
Map<String, Operation> operations = new HashMap<>();
HashMap<String, Object> localChanges = new HashMap<>(changeSet);
ResourceDescription resourceDescription = metadata.getDescription();
// look for alternatives
Set<String> conflicts = new HashSet<>();
Map<String, List<String>> allAlternatives = localChanges.keySet().stream().filter(name -> {
Object value = changeSet.get(name);
return !isNullOrEmpty(value);
}).collect(toMap(identity(), name -> resourceDescription.findAlternatives(ATTRIBUTES, name)));
allAlternatives.forEach((attribute, alternatives) -> {
logger.debug("Alternatives resolution for {} -> [{}]", attribute, String.join(", ", alternatives));
HashSet<String> intersection = new HashSet<>(alternatives);
intersection.retainAll(changeSet.keySet());
if (intersection.isEmpty()) {
// the easy part: no conflicts
alternatives.forEach(alternative -> {
boolean alternativeDoesntExist = resourceDescription.findAttribute(ATTRIBUTES, alternative) == null;
if (resourceDescription.isDeprecated(ATTRIBUTES, alternative) || alternativeDoesntExist) {
logger.debug("Skip undefine operations for deprecated or non-existent alternative {}", alternative);
} else {
logger.debug("Add undefine operations for alternative {}", alternative);
operations.putIfAbsent(alternative, undefineAttribute(address, alternative));
List<String> requires = resourceDescription.findRequires(ATTRIBUTES, alternative);
if (!requires.isEmpty()) {
logger.debug("Add undefine operations for attributes which require {}: [{}]", alternative, String.join(", ", requires));
requires.forEach(r -> operations.putIfAbsent(r, undefineAttribute(address, r)));
}
}
});
} else {
// possible conflicts: one or more alternatives are also in the change-set
// just collect for now and resolve later
conflicts.add(attribute);
conflicts.addAll(intersection);
logger.debug("Record conflict {} <-> [{}]", attribute, String.join(", ", intersection));
}
alternatives.forEach(localChanges::remove);
});
if (!conflicts.isEmpty()) {
// try to resolve conflicts: only one of the conflicting attributes must have a value other than
// null, empty or default
logger.debug("Try to resolve conflicts between alternatives [{}]", String.join(", ", conflicts));
Map<Boolean, List<String>> resolution = conflicts.stream().collect(groupingBy(conflict -> {
Object value = changeSet.get(conflict);
return isNullOrEmpty(value) || resourceDescription.isDefaultValue(ATTRIBUTES, conflict, value);
}));
List<String> undefine = resolution.getOrDefault(true, Collections.emptyList());
List<String> write = resolution.getOrDefault(false, Collections.emptyList());
if (write.size() > 1) {
logger.error("More than one conflicting alternative attribute which is not null, empty or default: [{}]. This should have been caught by a form validation. Adding the write operations anyway to get an appropriate error message from the server.", String.join(", ", write));
}
logger.debug("Add undefine operations for [{}], write operation for [{}]", String.join(", ", undefine), String.join(", ", write));
undefine.forEach(u -> {
operations.putIfAbsent(u, undefineAttribute(address, u));
localChanges.remove(u);
// process requires of the current undefine attribute
List<String> requires = resourceDescription.findRequires(ATTRIBUTES, u);
requires.forEach(ur -> {
operations.putIfAbsent(ur, undefineAttribute(address, ur));
localChanges.remove(ur);
});
});
write.forEach(w -> {
operations.putIfAbsent(w, writeAttribute(address, w, changeSet.get(w), resourceDescription, true));
localChanges.remove(w);
List<String> writeAlternatives = resourceDescription.findAlternatives(ATTRIBUTES, w);
// process alternatives of the current write attribute
writeAlternatives.forEach(wa -> {
operations.putIfAbsent(wa, undefineAttribute(address, wa));
localChanges.remove(wa);
});
});
}
// handle the remaining attributes
logger.debug("Process remaining attributes [{}]", String.join(", ", localChanges.keySet()));
localChanges.forEach((name, value) -> operations.putIfAbsent(name, writeAttribute(address, name, value, resourceDescription, false)));
return new Composite(operations.values().stream().filter(Objects::nonNull).collect(toList()));
}
use of org.jboss.hal.dmr.Composite in project console by hal.
the class OperationFactory method resetResource.
/**
* Creates a composite operation which resets the attributes of the specified resource. Only attributes which are nillable,
* w/o alternatives and not read-only will be reset. The composite contains
* {@linkplain org.jboss.hal.dmr.ModelDescriptionConstants#UNDEFINE_ATTRIBUTE_OPERATION undefine-attribute} operations for
* each attribute of type {@code EXPRESSION, LIST, OBJECT, PROPERTY} or {@code STRING} and
* {@linkplain org.jboss.hal.dmr.ModelDescriptionConstants#WRITE_ATTRIBUTE_OPERATION write-attribute} operations for
* attributes of type {@code BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT} or {@code LONG} if they have a default
* value.
*
* @param address the fq address used for the operations
* @param attributes the attributes to reset
* @param metadata the metadata which should contain the attribute definitions of the change-set
* @return a composite to reset the attributes or an empty composite if no attributes could be reset.
*/
Composite resetResource(ResourceAddress address, Set<String> attributes, Metadata metadata) {
List<Operation> operations = new ArrayList<>();
ResourceDescription description = metadata.getDescription();
// collect all attributes from the 'requires' list of this attribute
// HashMultimap<String, String> requires = HashMultimap.create();
TreeSet<String> requires = new TreeSet<>();
ModelNode attributesDescription = description.get(ATTRIBUTES);
attributes.forEach(attribute -> {
ModelNode attributeDescription = attributesDescription.get(attribute);
if (attributeDescription != null && attributeDescription.hasDefined(REQUIRES)) {
failSafeList(attributeDescription, REQUIRES).forEach(node -> requires.add(node.asString()));
/*
* .map(ModelNode::asString) .forEach(requiresName -> { requires.add(requiresName); });
*/
}
});
attributes.stream().map(attribute -> description.findAttribute(ATTRIBUTES, attribute)).filter(Objects::nonNull).forEach(property -> {
ModelNode attributeDescription = property.getValue();
boolean nillable = attributeDescription.hasDefined(NILLABLE) && attributeDescription.get(NILLABLE).asBoolean();
boolean readOnly = attributeDescription.hasDefined(ACCESS_TYPE) && READ_ONLY.equals(attributeDescription.get(ACCESS_TYPE).asString());
boolean alternatives = attributeDescription.hasDefined(ALTERNATIVES) && !attributeDescription.get(ALTERNATIVES).asList().isEmpty();
boolean requiredBy = requires.contains(property.getName());
if (nillable && !readOnly && !alternatives && !requiredBy) {
boolean hasDefault = attributeDescription.hasDefined(DEFAULT);
ModelType type = attributeDescription.get(TYPE).asType();
switch(type) {
case BIG_DECIMAL:
case BIG_INTEGER:
case BOOLEAN:
case BYTES:
case DOUBLE:
case INT:
case LONG:
if (hasDefault) {
operations.add(undefineAttribute(address, property.getName()));
}
break;
case EXPRESSION:
case LIST:
case OBJECT:
case PROPERTY:
case STRING:
operations.add(undefineAttribute(address, property.getName()));
break;
case TYPE:
case UNDEFINED:
break;
default:
break;
}
}
});
return new Composite(operations);
}
use of org.jboss.hal.dmr.Composite in project console by hal.
the class ComplexAttributeOperations method reset.
/**
* Undefines all non required attributes in the specified form. After the attributes in the complex attribute have been
* undefined a standard success message is fired and the specified callback is executed.
* <p>
* If the form contains only required attributes, a warning message is fired and the specified callback is executed.
*
* @param complexAttribute the name of the complex attribute
* @param type the human readable name of the complex attribute
* @param address the fq address for the operation
* @param form the form which should be reset
* @param callback the callback executed after the resource has been saved
*/
@JsIgnore
public <T> void reset(String complexAttribute, String type, ResourceAddress address, Metadata metadata, Form<T> form, Callback callback) {
Set<String> attributes = stream(form.getBoundFormItems().spliterator(), false).map(FormItem::getName).collect(toSet());
Composite composite = operationFactory(complexAttribute).resetResource(address, attributes, metadata);
reset(type, composite, callback);
}
Aggregations