I've found it's available in Ruby, but I recognize it from what I've done in Python; the "splat" operator. Long story short, I'm wondering if there's a simpler way to accomplish what I currently am, mimicking what the "splat" operator does.
I made a central method that the rest can call because I realized I have several very similar ones, and they were all doing the same except for a few minor things. Here's the method signature:
private String callScript(String scriptLocation, String... extraArgs) throws Exception {
I want to require at least one argument (the scriptLocation
), and then allow any number of extra arguments. What I end up doing with this is creating a ProcessBuilder
. My desire is to do something like this:
ProcessBuilder pb = new ProcessBuilder("something", scriptLocation, /* extraArgs */);
But of course, the ProcessBuilder
constructor only accepts things like:
List<String>
String[]
String...
So my approach obviously wouldn't work.
My current workaround, which works fine as far as I know, is:
List<String> finalArgs = new ArrayList<String>();
finalArgs.add("something");
finalArgs.add(scriptLocation);
finalArgs.addAll(Arrays.asList(extraArgs));
ProcessBuilder pb = new ProcessBuilder(finalArgs);
(yes, I understand I don't have to use List
and could just make a String[]
)
(and yes, I understand I could loop through extraArgs
and add them to finalArgs
individually, instead of having to use addAll
and Arrays.asList()
)
(and yes, I know I can make a function that effectively accomplishes my workaround by returning certain arguments combined with variable arguments)
So I guess outside of these last three statements, is there anything that can achieve this?
It depends on your definition of simpler, but you could write a class utilizing the Builder pattern:
public class MyProcessBuilder {
List<String> args;
MyProcessBuilder( String text, String location ) {
args = new ArrayList<String>();
args.add( text );
args.add( location );
}
MyProcessBuilder arg( String arg ) {
args.add( arg );
return this;
}
MyProcessBuilder args( String... args ) {
this.args.addAll( Arrays.asList( args ) );
return this;
}
public ProcessBuilder go() {
return new ProcessBuilder( args );
}
public static MyProcessBuilder callScript( String location ) {
return new MyProcessBuilder( "something", location );
}
public static void main( String[] args ) {
callScript( "/tmp/bla" ).arg( "something else" ).arg( "more" ).go();
}
}
Write a utility splat()
and publish it?:)
This might look more uniform:
List<String> finalArgs = new ArrayList<String>();
finalArgs.addAll(Arrays.asList( "something" ));
finalArgs.addAll(Arrays.asList( scriptLocation ));
finalArgs.addAll(Arrays.asList( extraArgs )));
ProcessBuilder pb = new ProcessBuilder(finalArgs);
When you call
ProcessBuilder pb = new ProcessBuilder("something", scriptLocation, /* extraArgs */);
If you have
public ProcessBuilder(String something, String scriptLocation, String... extraArgs);
Then you can call this method in many ways:
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh");
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh","someArg");
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh","someArg","someArg2");
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh");
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",new String[]{});
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",new String[]{"someArg"});
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",new String[]{"someArg","someArg2"});
ArrayList<String> someStringList = new ArrayList<String>();
someStringList .add("SomeArg");
someStringList .add("SomeArg2");
String[] extraArgs = someStringList .toArray(new String[someStringList .size()]);
ProcessBuilder pb = new ProcessBuilder("something", "/tmp/script.sh",extraArgs);