package ca.svarb.jyacl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import ca.svarb.utils.ClassReader;
import ca.svarb.utils.TextUtils;
public class UsageParser {
private Collection<Usage> usages=new ArrayList<Usage>();
private Collection<CliOption> usageOptions;
private boolean isUnnamed=false;
public UsageParser(ClassReader classReader) {
makeUsages(classReader);
}
/**
* Identify the usage form used in the arguments and return the
* options provided by that usage. Also removes the usage
* identifier switch from the argument list.
* @param arguments Original arguments list. Will be modified
* if the usage can be identified.
* @return
* @throws CliException If no usage could be identified
*/
public Usage identifyUsage(List<Argument> arguments) throws CliException {
Usage identifiedUsage=null;
// If only one usage is available, it is unnamed
if ( usages.size()==1 ) {
identifiedUsage=usages.iterator().next();
} else {
for(Usage usage : usages) {
if ( argumentListContains(arguments, usage.getName()) ) {
identifiedUsage=usage;
}
}
}
if (identifiedUsage==null) throw new CliException("Could not identify usage. Specify one of "+TextUtils.buildDelimitedString(usages, ", "));
return identifiedUsage;
}
private boolean argumentListContains(List<Argument> arguments, String name) {
Iterator<Argument> iterator = arguments.iterator();
Argument argument=null;
while( iterator.hasNext() ) {
argument=iterator.next();
if (argument.getName().equals(name) ) {
iterator.remove();
return true;
}
}
return false;
}
private void makeUsages(ClassReader classReader) {
usageOptions = classReader.getCliOptions();
for (CliOption cliOption : usageOptions) {
Class<?> returnType = cliOption.getReturnType();
if(returnType.isInterface()) {
ClassReader usageReader = new ClassReader(returnType);
Collection<CliOption> usageOptions = usageReader.getCliOptions();
Usage usage = new Usage(cliOption.getName(), returnType, usageOptions);
usages.add(usage);
} else {
// If no interfaces defined, there is a single unnamed usage
Usage usage = new Usage(usageOptions);
usages.add(usage);
this.isUnnamed=true;
return;
}
}
}
Collection<Usage> getUsages() {
return this.usages;
}
public boolean isUnnamedUsage() {
return this.isUnnamed;
}
}