/*******************************************************************************
* Copyright (c) 2004, 2006
* Thomas Hallgren, Kenneth Olwing, Mitch Sonies
* Pontus Rydin, Nils Unden, Peer Torngren
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the individual
* copyright holders listed above, as Initial Contributors under such license.
* The text of such license is available at www.eclipse.org.
*******************************************************************************/
package org.eclipse.buckminster.cmdline.parser;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.buckminster.cmdline.Messages;
import org.eclipse.buckminster.cmdline.Option;
import org.eclipse.buckminster.cmdline.OptionDescriptor;
import org.eclipse.buckminster.cmdline.OptionValueType;
public class ParseResult {
static private final String DASH = "-"; //$NON-NLS-1$
static private final String DOUBLEDASH = "--"; //$NON-NLS-1$
static public ParseResult parse(String[] args, List<OptionDescriptor> optionDescriptors) throws NoOptionNameException, AmbiguousOptionException,
InvalidOptionException, OptionRequiresValueException {
List<Option> options = new ArrayList<Option>();
int max = args.length;
int i;
for (i = 0; i < max; i++) {
String arg = args[i].trim();
if (arg.equals(DOUBLEDASH)) {
// if it's a lone doubledash:
//
i++; // consume the arg
break; // end parsing
}
if (!arg.startsWith(DASH))
// if it doesn't start with a dash at all:
//
break; // end parsing (but the arg is not 'consumed')
if (arg.length() == 1)
// if we reach this spot we only have a single dash which is
// not normally useful
//
throw new NoOptionNameException();
// PDE automatically tacks '-pdelaunch' on to the cmd line
// when starting from the pde. Just throw it away!
//
if (arg.equals("-pdelaunch")) //$NON-NLS-1$
continue;
// Eclipse 3.3 adds a -launcher <path to executable>
// Skip those
//
if (arg.equals("-launcher")) //$NON-NLS-1$
{
++i;
continue;
}
// Eclipse 3.3 adds a -name Eclipse <number>
// Skip those
//
if (arg.equals("-name")) //$NON-NLS-1$
{
i += 2;
continue;
}
boolean isLongName = arg.startsWith(DOUBLEDASH);
// strip the dash(es)
//
String argName = arg.substring(1 + (isLongName ? 1 : 0));
// keep everyone honest, ensure we only get one character if one
// dash. If
// there are more characters, we treat the rest as a possible
// optionValue
// (i.e. bunching).
//
String optionValue = null;
if (!isLongName && argName.length() > 1) {
optionValue = argName.substring(1);
argName = argName.substring(0, 1);
}
// match only *one* of the descriptors, complain if ambiguities are
// found
//
OptionDescriptor descriptorToUse = null;
int top = optionDescriptors.size();
for (int idx = 0; idx < top; ++idx) {
// ensure we give precedence to exact matches (long names only)
// thus, if --foo and --foobar are valid options, --foo must
// not be seen as an abbrev for --foobar
//
OptionDescriptor descriptor = optionDescriptors.get(idx);
if (descriptor.isAcceptableName(argName, isLongName, true)) {
descriptorToUse = descriptor;
break;
}
// in the event of long names used, try the abbreviation
//
if (isLongName && descriptor.isAcceptableName(argName, isLongName, false)) {
if (descriptorToUse != null)
throw new AmbiguousOptionException(arg);
descriptorToUse = descriptor;
}
}
if (descriptorToUse == null)
throw new InvalidOptionException(arg);
if (optionValue != null) {
// 'bunched' option already provided a value
//
if (descriptorToUse.getType() == OptionValueType.NONE)
throw new InvalidOptionException(arg);
} else if (descriptorToUse.getType() == OptionValueType.NONE) {
// nothing to do
} else if (descriptorToUse.getType() == OptionValueType.OPTIONAL) {
// only use an existing next value if it doesn't start with -
//
if (i + 1 < max) {
String s = args[i + 1];
if (!s.startsWith(DASH)) {
i++;
optionValue = s;
}
}
} else if (descriptorToUse.getType() == OptionValueType.REQUIRED) {
if (i + 1 == max)
throw new OptionRequiresValueException(arg);
optionValue = args[++i];
} else
throw new InternalError(Messages.ParseResult_Unknown_OptionValueType);
options.add(new Option(descriptorToUse, argName, optionValue, isLongName));
}
String[] unparsed = new String[max - i];
System.arraycopy(args, i, unparsed, 0, unparsed.length);
return new ParseResult(options.toArray(new Option[options.size()]), unparsed);
}
private final Option[] options;
private final String[] unparsed;
private ParseResult(Option[] options, String[] unparsed) {
this.options = options;
this.unparsed = unparsed;
}
public Option[] getOptions() {
return options;
}
public String[] getUnparsed() {
return unparsed;
}
}