Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fortify.cli.common.json.JsonHelper;
import com.fortify.cli.ssc._common.rest.ssc.SSCUrls;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagAssignmentHelper;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagDescriptor;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagUpdateHelper;

import kong.unirest.HttpRequest;
import kong.unirest.UnirestInstance;
Expand All @@ -42,7 +42,7 @@ public HttpRequest<?> buildRequest(String appVersionId, List<String> addCustomTa
return null;
}
ArrayNode current = getInitialTags(appVersionId);
SSCCustomTagUpdateHelper tagUpdateHelper = new SSCCustomTagUpdateHelper(unirest);
SSCCustomTagAssignmentHelper tagUpdateHelper = new SSCCustomTagAssignmentHelper(unirest);
List<SSCCustomTagDescriptor> currentDescriptors = JsonHelper.stream(current)
.map(tag -> JsonHelper.treeToValue(tag, SSCCustomTagDescriptor.class))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@
package com.fortify.cli.ssc.custom_tag.cli.cmd;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fortify.cli.common.exception.FcliSimpleException;
import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.output.transform.IActionCommandResultSupplier;
import com.fortify.cli.ssc._common.output.cli.cmd.AbstractSSCJsonNodeOutputCommand;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagDefinitionHelper;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagValueType;

import kong.unirest.UnirestInstance;
Expand Down Expand Up @@ -51,7 +49,8 @@ public class SSCCustomTagCreateCommand extends AbstractSSCJsonNodeOutputCommand

@Override
public JsonNode getJsonNode(UnirestInstance unirest) {
ObjectNode body = buildBody();
ObjectNode body = new SSCCustomTagDefinitionHelper(unirest).buildCreateBody(
name, valueType, description, restriction, hidden, requiresComment, extensible, values);
var response = unirest.post("/api/v1/customTags")
.body(body)
.asObject(JsonNode.class).getBody();
Expand All @@ -67,42 +66,4 @@ public String getActionCommandResult() {
public boolean isSingular() {
return true;
}

// --- Private body-building helpers below ---
private ObjectNode buildBody() {
ObjectNode body = JsonNodeFactory.instance.objectNode();
body.put("name", name);
body.put("description", description != null ? description : "");
body.put("valueType", valueType.name());
body.put("restriction", restriction);
body.put("hidden", hidden);
body.put("requiresComment", requiresComment);
body.put("customTagType", "CUSTOM");
if (valueType == SSCCustomTagValueType.LIST) {
body.put("extensible", extensible);
body.set("valueList", buildValueList());
}
return body;
}

private ArrayNode buildValueList() {
if (values == null || values.isBlank()) {
throw new FcliSimpleException("At least one value must be specified for LIST type using --values");
}
var valueList = JsonNodeFactory.instance.arrayNode();
String[] vals = values.split(",");
for (int i = 0; i < vals.length; i++) {
String val = vals[i].trim();
ObjectNode entry = JsonNodeFactory.instance.objectNode();
entry.put("lookupIndex", i+1);
entry.put("deletable", true);
entry.put("lookupValue", val);
entry.put("description", "");
entry.putNull("auditAssistantTrainingLabel");
entry.put("hidden", false);
entry.put("seqNumber", i+1);
valueList.add(entry);
}
return valueList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@
*/
package com.fortify.cli.ssc.custom_tag.cli.cmd;

import java.util.LinkedHashMap;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fortify.cli.common.exception.FcliSimpleException;
import com.fortify.cli.common.output.cli.mixin.OutputHelperMixins;
import com.fortify.cli.common.output.transform.IActionCommandResultSupplier;
import com.fortify.cli.ssc._common.output.cli.cmd.AbstractSSCJsonNodeOutputCommand;
import com.fortify.cli.ssc.custom_tag.cli.mixin.SSCCustomTagResolverMixin;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagDefinitionHelper;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagDescriptor;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagHelper;

import kong.unirest.UnirestInstance;
import lombok.Getter;
Expand Down Expand Up @@ -57,12 +52,14 @@ public class SSCCustomTagUpdateCommand extends AbstractSSCJsonNodeOutputCommand

@Override
public JsonNode getJsonNode(UnirestInstance unirest) {
SSCCustomTagDefinitionHelper customTagDefinitionHelper = new SSCCustomTagDefinitionHelper(unirest);
SSCCustomTagDescriptor desc = customTagResolver.getCustomTagDescriptor(unirest);
ObjectNode updateData = buildBody(desc);
ObjectNode updateData = customTagDefinitionHelper.buildUpdateBody(
desc, name, description, restriction, hidden, requiresComment, extensible, values, addValues, rmValues);
unirest.put("/api/v1/customTags/{id}")
.routeParam("id", desc.getId())
.body(updateData).asObject(JsonNode.class).getBody();
return new SSCCustomTagHelper(unirest).getDescriptorByCustomTagSpec(desc.getGuid(), true).asJsonNode();
return customTagDefinitionHelper.getDescriptorByCustomTagSpec(desc.getGuid(), true).asJsonNode();
}

@Override
Expand All @@ -74,78 +71,4 @@ public String getActionCommandResult() {
public boolean isSingular() {
return true;
}

// --- Private body-building helpers below ---
private ObjectNode buildBody(SSCCustomTagDescriptor desc) {
ObjectNode body = (ObjectNode)desc.asJsonNode().deepCopy();
if (name != null && !name.isBlank()) { body.put("name", name); }
if (description != null) { body.put("description", description); }
if (restriction != null) { body.put("restriction", restriction); }
if (hidden != null) { body.put("hidden", hidden); }
if (requiresComment != null) { body.put("requiresComment", requiresComment); }
if (extensible != null && "LIST".equalsIgnoreCase(body.path("valueType").asText())) { body.put("extensible", extensible); }
if ("LIST".equalsIgnoreCase(body.path("valueType").asText())) {
body.set("valueList", buildValueList(body));
}
return body;
}

private ArrayNode buildValueList(ObjectNode body) {
LinkedHashMap<String, ObjectNode> valueMap = buildValueMap(body);
if (values != null) {
valueMap.clear();
addValuesToMap(valueMap, values);
}
if (addValues != null) {
addValuesToMap(valueMap, addValues);
}
if (rmValues != null) {
removeValuesFromMap(valueMap, rmValues);
}
if (valueMap.isEmpty()) {
throw new FcliSimpleException("At least one value must be specified for LIST type");
}
var newValueList = JsonNodeFactory.instance.arrayNode();
int idx = 1;
for (ObjectNode entry : valueMap.values()) {
entry.put("lookupIndex", idx);
entry.put("seqNumber", idx);
newValueList.add(entry);
idx++;
}
return newValueList;
}

private LinkedHashMap<String, ObjectNode> buildValueMap(ObjectNode body) {
var valueList = body.withArray("valueList");
LinkedHashMap<String, ObjectNode> valueMap = new LinkedHashMap<>();
for (JsonNode v : valueList) {
valueMap.put(v.path("lookupValue").asText(), (ObjectNode)v);
}
return valueMap;
}

private void addValuesToMap(LinkedHashMap<String, ObjectNode> valueMap, String valuesStr) {
String[] vals = valuesStr.split(",");
for (String val : vals) {
val = val.trim();
if (!valueMap.containsKey(val)) {
ObjectNode entry = JsonNodeFactory.instance.objectNode();
entry.put("lookupValue", val);
entry.put("deletable", true);
entry.put("description", "");
entry.putNull("auditAssistantTrainingLabel");
entry.put("hidden", false);
valueMap.put(val, entry);
}
}
}

private void removeValuesFromMap(LinkedHashMap<String, ObjectNode> valueMap, String valuesStr) {
String[] vals = valuesStr.split(",");
for (String val : vals) {
val = val.trim();
valueMap.remove(val);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import org.apache.commons.lang3.StringUtils;

import com.fortify.cli.common.cli.util.EnvSuffix;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagDefinitionHelper;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagDescriptor;
import com.fortify.cli.ssc.custom_tag.helper.SSCCustomTagHelper;

import kong.unirest.UnirestInstance;
import lombok.Getter;
Expand All @@ -30,7 +30,7 @@ public SSCCustomTagDescriptor getCustomTagDescriptor(UnirestInstance unirest) {
String customTagNameOrGuid = getCustomTagNameOrGuid();
return StringUtils.isBlank(customTagNameOrGuid)
? null
: new SSCCustomTagHelper(unirest).getDescriptorByCustomTagSpec(customTagNameOrGuid, true);
: new SSCCustomTagDefinitionHelper(unirest).getDescriptorByCustomTagSpec(customTagNameOrGuid, true);
}
}
public static class OptionalOption extends AbstractSSCCustomTagResolverMixin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,30 @@

import kong.unirest.UnirestInstance;

public class SSCCustomTagUpdateHelper {
private final SSCCustomTagHelper tagHelper;
public class SSCCustomTagAssignmentHelper {
private final SSCCustomTagDefinitionHelper tagDefinitionHelper;

public SSCCustomTagUpdateHelper(UnirestInstance unirest) {
this.tagHelper = new SSCCustomTagHelper(unirest);
public SSCCustomTagAssignmentHelper(UnirestInstance unirest) {
this.tagDefinitionHelper = new SSCCustomTagDefinitionHelper(unirest);
}

/**
* Resolves tag specs (name, guid, id) to descriptors using SSCCustomTagHelper.
*/
public Set<SSCCustomTagDescriptor> resolveTagSpecs(List<String> tagSpecs) {
return tagHelper.getDescriptorsByCustomTagSpec(tagSpecs, false).collect(Collectors.toSet());
return tagDefinitionHelper.getDescriptorsByCustomTagSpec(tagSpecs, false).collect(Collectors.toSet());
}

/**
* Computes the updated stream of custom tag descriptors given current, add, and remove specs.
*/
public Stream<SSCCustomTagDescriptor> computeUpdatedTagDescriptors(List<SSCCustomTagDescriptor> currentTags, List<String> addSpecs, List<String> rmSpecs) {
var currentTagsStream = currentTags.stream();
var addDescriptorsStream = tagHelper.getDescriptorsByCustomTagSpec(addSpecs, false);
var rmDescriptors = tagHelper.getDescriptorsByCustomTagSpec(rmSpecs, false).toList();
var addDescriptorsStream = tagDefinitionHelper.getDescriptorsByCustomTagSpec(addSpecs, false);
var rmDescriptors = tagDefinitionHelper.getDescriptorsByCustomTagSpec(rmSpecs, false).toList();
return Stream.concat(
currentTagsStream.filter(tag -> rmDescriptors.stream().noneMatch(rmTag -> rmTag.isEqualById(tag))),
addDescriptorsStream
).distinct();
}

/**
* Overload: Accepts current custom tags as json nodes, resolves to descriptors, then computes updated descriptors.
*/
public Stream<SSCCustomTagDescriptor> computeUpdatedTagDescriptors(JsonNode currentTagsNode, List<String> addSpecs, List<String> rmSpecs) {
return computeUpdatedTagDescriptors(
SSCCustomTagHelper.toDescriptors(currentTagsNode),
SSCCustomTagDefinitionHelper.toDescriptors(currentTagsNode),
addSpecs, rmSpecs);
}
}
Loading
Loading