Skip to content

Commit

Permalink
Simplify async message formatting with Velocity
Browse files Browse the repository at this point in the history
Main changes:
1. Added request.getAttributesSimplified() method.
2. Added formatter.identifiersAsAttributes field.
3. Added requestFormatter variable.
  • Loading branch information
mederly committed Dec 1, 2020
1 parent acebd85 commit dcb2416
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
Expand Up @@ -15,7 +15,9 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
Expand Down Expand Up @@ -116,7 +118,36 @@ public Map<String, Collection<?>> getAttributes() {
}

public void setAttributes(Map<String, Collection<?>> attributes) {
this.attributes = attributes;
this.attributes = new HashMap<>(attributes);
}

public void addAttributes(Map<String, Collection<?>> added) {
if (attributes != null) {
attributes.putAll(added);
} else {
setAttributes(added);
}
}

/**
* Returns simplified version of the attributes map, suitable e.g. for presentation via Velocity.
* Each attribute with no values or one value is replaced by scalar, i.e. null or the single item.
* Attributes with multiple values are represented as lists.
*/
public Map<String, Object> getAttributesSimplified() {
Map<String, Object> rv = new HashMap<>();
for (Map.Entry<String, Collection<?>> entry : attributes.entrySet()) {
String name = entry.getKey();
Collection<?> values = entry.getValue();
if (values.isEmpty()) {
rv.put(name, null);
} else if (values.size() == 1) {
rv.put(name, values.iterator().next());
} else {
rv.put(name, new ArrayList<>(values));
}
}
return rv;
}

public Map<String, Collection<?>> getPrimaryIdentifiers() {
Expand Down
Expand Up @@ -53,6 +53,12 @@ public class JsonRequestFormatter {
*/
private boolean changeMapAsAttributes;

/**
* Should we put identifiers into attributes map? It is done before putting changes into attributes,
* so any identifiers changed will have new values in attributes map (assuming changeMapAsAttributes is also true).
*/
private boolean identifiersAsAttributes;

public JsonRequestFormatter(@NotNull OperationRequested operationRequested) {
this.operationRequested = operationRequested;
}
Expand Down Expand Up @@ -83,6 +89,19 @@ public void setChangeMapAsAttributes(boolean changeMapAsAttributes) {
this.changeMapAsAttributes = changeMapAsAttributes;
}

public boolean isIdentifiersAsAttributes() {
return identifiersAsAttributes;
}

public JsonRequestFormatter identifiersAsAttributes() {
identifiersAsAttributes = true;
return this;
}

public void setIdentifiersAsAttributes(boolean identifiersAsAttributes) {
this.identifiersAsAttributes = identifiersAsAttributes;
}

/**
* Does default formatting: creates the request and returns its JSON form.
*/
Expand All @@ -105,7 +124,7 @@ public String toJson() throws JsonProcessingException {
* Fills-in the request in the default way.
* (If you need a custom way of doing this, you can use individual setXXX methods as needed.)
*/
public void createRequest() {
public JsonAsyncProvisioningRequest createRequest() {
setOperationName();
setObjectClass();
if (operationRequested instanceof OperationRequested.Add) {
Expand All @@ -122,6 +141,7 @@ public void createRequest() {
} else {
throw new IllegalStateException("Unsupported operation requested: " + operationRequested);
}
return request;
}

/** Sets operation name in the request. */
Expand All @@ -135,22 +155,28 @@ public void setObjectClass() {
}

/**
* Sets the attributes in the request. Uses attributes in the shadow as the source.
* Adds the attributes to the request. Uses attributes in the shadow as the source.
* This is obviously fully appropriate for ADD operation. But for MODIFY/DELETE operation
* the attributes usually contain values _before_ the operation. Nevertheless, it might make
* some sense to call this method even in these cases.
*/
public void setAttributes() {
request.setAttributes(transformAttributesMap(operationRequested.getAttributeValueMap()));
request.addAttributes(transformAttributesMap(operationRequested.getAttributeValueMap()));
}

/**
* Sets primary and secondary identifiers. Useful for MODIFY and DELETE operations. Can
* be used for ADD operations as well, if needed.
*
* If {@link #identifiersAsAttributes} is set, these identifiers are added also to the attributes section.
*/
public void setIdentifiers() {
request.setPrimaryIdentifiers(transformAttributesMap(operationRequested.getPrimaryIdentifiersValueMap()));
request.setSecondaryIdentifiers(transformAttributesMap(operationRequested.getSecondaryIdentifiersValueMap()));
if (identifiersAsAttributes) {
request.addAttributes(request.getPrimaryIdentifiers());
request.addAttributes(request.getSecondaryIdentifiers());
}
}

private Map<String, Collection<?>> transformAttributesMap(Map<ItemName, Collection<?>> attributes) {
Expand All @@ -172,7 +198,7 @@ private Map<String, Collection<?>> transformAttributesMap(Map<ItemName, Collecti
*/
public void setAttributesFromChanges() {
Map<ItemName, ItemDelta<?, ?>> changeMap = ((OperationRequested.Modify) operationRequested).getAttributeChangeMap();
request.setAttributes(transformChangeMapToAttributes(changeMap));
request.addAttributes(transformChangeMapToAttributes(changeMap));
}

private Map<String, Collection<?>> transformChangeMapToAttributes(Map<ItemName, ItemDelta<?, ?>> changeMap) {
Expand Down
Expand Up @@ -38,6 +38,7 @@ public class OperationRequestTransformer {

private static final String VAR_OPERATION_REQUESTED = "operationRequested";
private static final String VAR_TRANSFORMER_HELPER = "transformerHelper";
private static final String VAR_REQUEST_FORMATTER = "requestFormatter";

public OperationRequestTransformer(@NotNull AsyncProvisioningConnectorInstance connectorInstance) {
this.connectorInstance = connectorInstance;
Expand All @@ -60,6 +61,7 @@ public AsyncProvisioningRequest transformOperationRequested(@NotNull OperationRe
VariablesMap variables = new VariablesMap();
variables.put(VAR_OPERATION_REQUESTED, operationRequested, operationRequested.getClass());
variables.put(VAR_TRANSFORMER_HELPER, transformerHelper, TransformerHelper.class);
variables.put(VAR_REQUEST_FORMATTER, transformerHelper.jsonRequestFormatter(operationRequested), JsonRequestFormatter.class);

List<?> list = connectorInstance.getUcfExpressionEvaluator().evaluate(transformExpression, variables,
SchemaConstantsGenerated.C_ASYNC_PROVISIONING_REQUEST, "creating asynchronous provisioning request",
Expand Down

0 comments on commit dcb2416

Please sign in to comment.