Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CommandLineParserConfig #126

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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 @@ -57,9 +57,6 @@ public final class CommandLineArgumentParser implements CommandLineParser {
public static final String COMMENT = "#";
public static final String POSITIONAL_ARGUMENTS_NAME = "Positional Argument";

// Extension for collection argument list files
static final String COLLECTION_LIST_FILE_EXTENSION = ".args";

private static final Logger logger = LogManager.getLogger();

// Map from (full class) name of each CommandLinePluginDescriptor requested and
Expand Down Expand Up @@ -113,7 +110,7 @@ private boolean inArgumentMap(ArgumentDefinition arg){
// and into which the values will be assigned.
private final Object callerArguments;

private final Set<CommandLineParserOptions> parserOptions;
private final CommandLineParserConfig config;

// null if no @PositionalArguments annotation
private Field positionalArguments;
Expand Down Expand Up @@ -151,7 +148,7 @@ public CommandLineArgumentParser(final Object callerArguments) {
this(
callerArguments,
Collections.emptyList(),
Collections.emptySet()
new CommandLineParserConfig() {}
);
}

Expand All @@ -162,17 +159,18 @@ public CommandLineArgumentParser(final Object callerArguments) {
* should be used by this command line parser to extend the list of
* command line arguments with dynamically discovered plugins. If
* null, no descriptors are loaded.
* @param parserConfig configuration for the behaviour of the parser.
*/
public CommandLineArgumentParser(
final Object callerArguments,
final List<? extends CommandLinePluginDescriptor<?>> pluginDescriptors,
final Set<CommandLineParserOptions> parserOptions) {
final CommandLineParserConfig parserConfig) {
Utils.nonNull(callerArguments, "The object with command line arguments cannot be null");
Utils.nonNull(pluginDescriptors, "The list of pluginDescriptors cannot be null");
Utils.nonNull(parserOptions, "The set of parser options cannot be null");
Utils.nonNull(parserConfig, "The parser configuration cannot be null");

this.callerArguments = callerArguments;
this.parserOptions = parserOptions;
this.config = parserConfig;

createArgumentDefinitions(callerArguments, null);
createCommandLinePluginArgumentDefinitions(pluginDescriptors);
Expand Down Expand Up @@ -622,7 +620,7 @@ private void setArgument(ArgumentDefinition argumentDefinition, List<String> val
throw new CommandLineException("Argument '" + argumentDefinition.getNames() + "' cannot be specified more than once.");
}
if (argumentDefinition.isCollection) {
if (!parserOptions.contains(CommandLineParserOptions.APPEND_TO_COLLECTIONS)) {
if (!config.getAppendToCollections()) {
// if this is a collection then we only want to clear it once at the beginning, before we process
// any of the values, unless we're in APPEND_TO_COLLECTIONS mode, in which case we leave the initial
// and append to it
Expand Down Expand Up @@ -718,8 +716,9 @@ private void setArgument(ArgumentDefinition argumentDefinition, List<String> val
*/
private List<String> expandListFile(final List<String> originalValues) {
List<String> expandedValues = new ArrayList<>(originalValues.size());

for (String stringValue: originalValues) {
if (stringValue.endsWith(COLLECTION_LIST_FILE_EXTENSION)) {
if (config.getExpansionFileExtensions().stream().anyMatch(stringValue::endsWith)) {
expandedValues.addAll(loadCollectionListFile(stringValue));
}
else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.broadinstitute.barclay.argparser;

import java.util.Collection;
import java.util.Collections;

/**
* Interface for the command line parser configuration.
*
* @author Daniel Gomez-Sanchez (magicDGS)
*/
public interface CommandLineParserConfig {

/**
* Default extension for collection argument list files.
*/
public static final String DEFAULT_COLLECTION_LIST_FILE_EXTENSION = ".args";

/**
* Configuration for append/replace values in a Collection argument.
*
* <p>The default behavior is returning {@code false}, which:
*
* <p><ul>
* <li>Replace the contents of a collection argument with any values from the command line.</li>
* <li>Optionally allow the special singleton value of "null" to clear the contents of the collection.</li>
* </ul></p>
*
* <p>Returning {@code true} changes the behavior so that any collection arguments are ADDED to the
* initial values of the collection, and allows the special value "null" to be used first to clear the initial
* values.
*
* @return {@code true} if the result should be append to the initial values of the collection;
* {@code false} if they should be substituted.
*/
default public boolean getAppendToCollections() {
return false;
}

/**
* Configuration for loading Collection arguments from files ending with concrete extensions.
*
* <p>Default behaviour returns {@link #DEFAULT_COLLECTION_LIST_FILE_EXTENSION} as the file
* extension to expand.
*
* @return extension(s) for detect an argument as a file for loading a Collection argument.
*/
default Collection<String> getExpansionFileExtensions() {
return Collections.singleton(DEFAULT_COLLECTION_LIST_FILE_EXTENSION);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public void processWorkUnit(
if (argumentContainer instanceof CommandLinePluginProvider) {
pluginDescriptors = ((CommandLinePluginProvider) argumentContainer).getPluginDescriptors();
clp = new CommandLineArgumentParser(
argumentContainer, pluginDescriptors, Collections.emptySet()
argumentContainer, pluginDescriptors, new CommandLineParserConfig() {}
);
} else {
clp = new CommandLineArgumentParser(argumentContainer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,21 @@ public Object[][] uninitializedCollections() {
// the same behavior on collections with no initial values
{
inputArgs,
Collections.EMPTY_SET, // replace mode
new CommandLineParserConfig() {}, // replace mode
makeList("L1", "L2"),
makeList("S1"),
makeList("HS1"),
expectedFileList
},
{
inputArgs,
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS), // append mode
// append mode
new CommandLineParserConfig() {
@Override
public boolean getAppendToCollections() {
return true;
}
},
makeList("L1", "L2"),
makeList("S1"),
makeList("HS1"),
Expand All @@ -58,14 +64,14 @@ public Object[][] uninitializedCollections() {
@Test(dataProvider="uninitializedCollections")
public void testUninitializedCollections(
final String[] args,
final Set<CommandLineParserOptions> parserOptions,
final CommandLineParserConfig parserConfig,
final List<String> expectedList,
final List<String> expectedArrayList,
final List<String> expectedHashSet,
final List<File> expectedCollection)
{
final UninitializedCollections o = new UninitializedCollections();
final CommandLineArgumentParser clp = new CommandLineArgumentParser(o, Collections.emptyList(), parserOptions);
final CommandLineArgumentParser clp = new CommandLineArgumentParser(o, Collections.emptyList(), parserConfig);
Assert.assertTrue(clp.parseArguments(System.err, args));
Assert.assertEquals(o.LIST, expectedList);
Assert.assertEquals(o.ARRAY_LIST, expectedArrayList);
Expand All @@ -84,45 +90,52 @@ public Object[][] initializedCollections() {
final String[] inputArgsWithNullAtStart = new String[] {"--LIST", "null", "--LIST", "baz", "--LIST", "frob"};
final String[] inputArgsWithNullMidStream = new String[] {"--LIST", "baz", "--LIST", "null", "--LIST", "frob"};

final CommandLineParserConfig appendConfig = new CommandLineParserConfig() {
@Override
public boolean getAppendToCollections() {
return true;
}
};

return new Object[][]{
{
inputArgs,
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS),
appendConfig,
makeList("foo", "bar", "baz", "frob") // original values retained
},
{
inputArgs,
Collections.emptySet(),
new CommandLineParserConfig() {},
makeList("baz", "frob") // original values replaced
},
{
inputArgsWithNullAtStart,
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS),
appendConfig,
makeList("baz", "frob") // original values replaced
},
{
inputArgsWithNullAtStart,
Collections.emptySet(),
new CommandLineParserConfig() {},
makeList("baz", "frob") // original values replaced
},
{
inputArgsWithNullMidStream,
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS),
appendConfig,
makeList("frob") // reset mid-stream via midstream null
},
{
inputArgsWithNullMidStream,
Collections.emptySet(),
new CommandLineParserConfig() {},
makeList("frob") // reset mid-stream via midstream null
},
{
new String[]{},
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS),
appendConfig,
makeList("foo", "bar")
},
{
new String[]{},
Collections.singleton(Collections.emptySet()),
new CommandLineParserConfig() {},
makeList("foo", "bar")
}
};
Expand All @@ -131,13 +144,13 @@ public Object[][] initializedCollections() {
@Test(dataProvider="initializedCollections")
public void testInitializedCollections(
final String[] args,
final Set<CommandLineParserOptions> parserOptions,
final CommandLineParserConfig parserConfig,
final List<String> expectedResult) {
final InitializedCollections o = new InitializedCollections();
final CommandLineParser clp = new CommandLineArgumentParser(
o,
Collections.emptyList(),
parserOptions
parserConfig
);
Assert.assertTrue(clp.parseArguments(System.err, args));
Assert.assertEquals(o.LIST, expectedResult);
Expand All @@ -157,16 +170,22 @@ class CollectionForListFileArguments {
@DataProvider(name="listFileArguments")
public Object[][] listFileArguments() {
final String[] inputArgs = new String[] { "shmiggle0", "shmiggle1", "shmiggle2" };

return new Object[][] {
{
// replace mode
Collections.EMPTY_SET, // parser options
inputArgs, // args
new String[] {"shmiggle0", "shmiggle1", "shmiggle2"}, // expected result
// replace mode (default configuration)
new CommandLineParserConfig() {}, // parser config
inputArgs, // args
new String[] {"shmiggle0", "shmiggle1", "shmiggle2"}, // expected result
},
{
// append mode
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS), // parser options
new CommandLineParserConfig() {
@Override
public boolean getAppendToCollections() {
return true;
}
}, // parser config
inputArgs, // args
new String[] {"foo", "bar", "shmiggle0", "shmiggle1", "shmiggle2"}, // expected result
},
Expand All @@ -176,7 +195,7 @@ public Object[][] listFileArguments() {
// Test that .list files populate collections with file contents, both mpdes
@Test(dataProvider="listFileArguments")
public void testCollectionFromListFile(
final Set<CommandLineParserOptions> parserOptions,
final CommandLineParserConfig parserConfig,
final String [] argList,
final String[] expectedList) throws IOException
{
Expand All @@ -187,7 +206,7 @@ public void testCollectionFromListFile(
final CommandLineParser clp = new CommandLineArgumentParser(
o,
Collections.emptyList(),
parserOptions
parserConfig
);

final String[] args = {"--LIST", argListFile.getAbsolutePath()};
Expand All @@ -196,14 +215,37 @@ public void testCollectionFromListFile(
Assert.assertEquals(o.LIST, makeList(expectedList));
}

@Test
public void testDoNotExpandCollectionListFile() {
final CollectionForListFileArguments o = new CollectionForListFileArguments();
final CommandLineParser clp = new CommandLineArgumentParser(
o,
Collections.emptyList(),
new CommandLineParserConfig() {
@Override
public Collection<String> getExpansionFileExtensions() {
return Collections.emptySet();
}
}
);

final String noListFile = "no_arg_list_file" + CommandLineParserConfig.DEFAULT_COLLECTION_LIST_FILE_EXTENSION;

final String[] args = {"--LIST", noListFile};
Assert.assertTrue(clp.parseArguments(System.err, args));

Assert.assertEquals(o.LIST, makeList(noListFile));
}

@DataProvider(name="mixedListFileArguments")
public Object[][] mixedListFileArguments() {
final String[] inputArgList1 = { "shmiggle0", "shmiggle1", "shmiggle2" };
final String[] inputArgList2 = { "test2_shmiggle0", "test2_shmiggle1", "test2_shmiggle2" };

return new Object[][] {
{
// replace mode
Collections.EMPTY_SET, // parser options
new CommandLineParserConfig() {}, // parser config
inputArgList1, // args list 1
inputArgList2, // args list 2
new String[] {"shmiggle0", "shmiggle1", "shmiggle2"}, // expected result list 1
Expand All @@ -217,7 +259,12 @@ public Object[][] mixedListFileArguments() {
},
{
// append mode
Collections.singleton(CommandLineParserOptions.APPEND_TO_COLLECTIONS), // parser options
new CommandLineParserConfig() {
@Override
public boolean getAppendToCollections() {
return true;
}
}, // parser config
inputArgList1, // args list 1
inputArgList2, // args list 2
new String[] {"foo", "bar", "shmiggle0", "shmiggle1", "shmiggle2"}, // expected result list 1
Expand All @@ -236,7 +283,7 @@ public Object[][] mixedListFileArguments() {
// Test that .list files intermixed with explicit command line values populate collections correctly, both mpdes
@Test(dataProvider="mixedListFileArguments")
public void testCollectionFromListFileMixed(
final Set<CommandLineParserOptions> parserOptions,
final CommandLineParserConfig parserConfig,
final String [] argList1,
final String [] argList2,
final String[] expectedList1,
Expand All @@ -250,7 +297,7 @@ public void testCollectionFromListFileMixed(
final CommandLineParser clp = new CommandLineArgumentParser(
o,
Collections.emptyList(),
parserOptions
parserConfig
);

// mix command line values and file values
Expand Down Expand Up @@ -281,7 +328,7 @@ public void testCollectionThatCannotBeAutoInitialized() {
// Helper methods

private File createListArgumentFile(final String fileName, final String[] argList) throws IOException {
final File listFile = File.createTempFile(fileName, CommandLineArgumentParser.COLLECTION_LIST_FILE_EXTENSION);
final File listFile = File.createTempFile(fileName, CommandLineParserConfig.DEFAULT_COLLECTION_LIST_FILE_EXTENSION);
listFile.deleteOnExit();
try (final PrintWriter writer = new PrintWriter(listFile)) {
Arrays.stream(argList).forEach(arg -> writer.println(arg));
Expand Down
Loading