Skip to content

Commit

Permalink
chore: Partial data-extract implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
rsenden committed Feb 20, 2024
1 parent da6fc5c commit cb4730b
Show file tree
Hide file tree
Showing 37 changed files with 2,531 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,24 @@
package com.fortify.cli.common.cli.mixin;

import java.io.File;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Stack;

import com.formkiq.graalvm.annotations.Reflectable;
import com.fortify.cli.common.util.PicocliSpecHelper;
import com.fortify.cli.common.util.StringUtils;

import lombok.Getter;
import lombok.NoArgsConstructor;
import picocli.CommandLine.Command;
import picocli.CommandLine.IParameterPreprocessor;
import picocli.CommandLine.Mixin;
import picocli.CommandLine.Model.ArgSpec;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Model.UnmatchedArgsBinding;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;

Expand Down Expand Up @@ -78,4 +89,72 @@ private String getPlainPrompt(CommandSpec spec, Object... promptArgs) {
return prompt;
}
}

/**
* This mixin allows for collecting any unmatched command line options
* and parsing them into an [option name]=[value] map.
*/
@Command(preprocessor = OptionParametersMixinPreprocessor.class)
public static final class OptionParametersMixin {
@Getter private Map<String, String> options = new LinkedHashMap<>();

public final <T> T setUnmatchedArgs(T arg) {
parse((String[])arg);
return arg;
}

private final void parse(String[] argsArray) {
var args = asDeque(argsArray);
while ( !args.isEmpty() ) {
var opt = args.pop();
if ( !opt.startsWith("-") ) {
throw new IllegalArgumentException("Unknown command line option: "+opt);
} else {
opt = opt.replaceFirst("-+", "");
if ( args.peek().startsWith("-") ) {
options.put(opt, "");
} else {
options.put(opt, args.pop());
}
}
}
}

private final Deque<String> asDeque(String[] args) {
Deque<String> result = new ArrayDeque<>();
// Split --opt=value into separate args on the Deque
for ( var arg: args ) {
if ( arg.startsWith("--") ) {
// Allow for --opt=val, adding option and value as separate args
var elts = arg.split("=", 2);
result.add(elts[0]);
if ( elts.length==2 ) { result.add(elts[1]); }
} else if ( arg.startsWith("-") ) {
result.add(arg.substring(0,2));
if ( arg.length()>2 ) {
var val = arg.substring(2);
if ( val.startsWith("=") ) { val = val.substring(1); }
result.add(val);
}
} else {
result.add(arg);
}
}
return result;
}
}

@Reflectable @NoArgsConstructor
static final class OptionParametersMixinPreprocessor implements IParameterPreprocessor {
@Override
public final boolean preprocess(Stack<String> args, CommandSpec commandSpec, ArgSpec argSpec, Map<String, Object> info) {
var mixin = commandSpec.mixins().values().stream()
.map(CommandSpec::userObject)
.filter(o->o instanceof OptionParametersMixin)
.map(OptionParametersMixin.class::cast)
.findFirst().get();
commandSpec.addUnmatchedArgsBinding(UnmatchedArgsBinding.forStringArrayConsumer(mixin::setUnmatchedArgs));
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright 2021, 2023 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/
package com.fortify.cli.common.data_extract.cli.cmd;

import java.util.List;

import com.fortify.cli.common.cli.cmd.AbstractRunnableCommand;
import com.fortify.cli.common.cli.mixin.CommonOptionMixins.OptionParametersMixin;
import com.fortify.cli.common.data_extract.helper.DataExtractTemplateExecutor;
import com.fortify.cli.common.data_extract.helper.DataExtractTemplateHelper;
import com.fortify.cli.common.progress.cli.mixin.ProgressWriterFactoryMixin;
import com.fortify.cli.common.util.DisableTest;
import com.fortify.cli.common.util.DisableTest.TestType;

import picocli.CommandLine.Mixin;
import picocli.CommandLine.Option;

public abstract class AbstractDataExtractCreateCommand extends AbstractRunnableCommand implements Runnable {
@Option(names={"-t", "--template"}, required=true) private String template;
@DisableTest({TestType.MULTI_OPT_SPLIT, TestType.MULTI_OPT_PLURAL_NAME, TestType.OPT_LONG_NAME})
@Option(names="--<template-parameter>", paramLabel="<value>", descriptionKey="fcli.data-extract.create.template-parameter")
private List<String> dummyForSynopsis;
@Mixin private OptionParametersMixin templateParameters;
@Mixin private ProgressWriterFactoryMixin progressWriterFactory;

@Override
public final void run() {
initMixins();
try ( var progressWriter = progressWriterFactory.create() ) {
progressWriter.writeProgress("Loading template %s", template);
var templateDescriptor = DataExtractTemplateHelper.load(getType(), template);
progressWriter.writeProgress("Executing template %s", template);
try ( var templateExecutor = DataExtractTemplateExecutor.builder()
.template(templateDescriptor)
.inputParameters(templateParameters.getOptions())
.progressWriter(progressWriter).build() )
{
configure(templateExecutor);
templateExecutor.execute();
}
}
}

protected abstract String getType();
protected abstract void configure(DataExtractTemplateExecutor templateExecutor);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright 2021, 2023 Open Text.
*
* The only warranties for products and services of Open Text
* and its affiliates and licensors ("Open Text") are as may
* be set forth in the express warranty statements accompanying
* such products and services. Nothing herein should be construed
* as constituting an additional warranty. Open Text shall not be
* liable for technical or editorial errors or omissions contained
* herein. The information contained herein is subject to change
* without notice.
*******************************************************************************/
package com.fortify.cli.common.data_extract.cli.cmd;

import com.fasterxml.jackson.databind.JsonNode;
import com.fortify.cli.common.output.cli.cmd.AbstractOutputCommand;
import com.fortify.cli.common.output.cli.cmd.IJsonNodeSupplier;

public abstract class AbstractDataExtractListTemplatesCommand extends AbstractOutputCommand implements IJsonNodeSupplier {
@Override
public final JsonNode getJsonNode() {
// TODO Auto-generated method stub
return null;
}
@Override
public final boolean isSingular() {
return false;
}
protected abstract String getType();


}
Loading

0 comments on commit cb4730b

Please sign in to comment.