blob: 4109bdb37251854184c6014f928806ca2220a7c6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.command.internal.env.commandline;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.BitSet;
import java.util.ResourceBundle;
import java.util.Vector;
import org.eclipse.wst.command.internal.env.common.StringUtils;
/**
* <p>This is a generic command line parsing class. The programmer need only specify
* the characteristics of their command line(ie. positional parameters, flags, etc)
* and this class will perform the rest of the parsing work. As an added bonus this
* class will also create formated help text that displays the syntax of this
* command line.
*
* <p>The main parameter to the CommandLine constructor is a two dimensional String
* array. There are 5 columns in this array and as many rows as needed for each
* flag or positional parameter. The five columns are:
*
* <ol>
* <li>The name of the flag(eg. "help" or "a", etc)
* Note: no dash should be in the name here. The user would specify "-help" on the
* command line though.
* <li>The name of the flag parameter(if any)
* <li>A string indicating whether this flag can appear more than once on the
* command line.
* <li>A string indicating whether this flag must be specified on the command line.
* <li>A help text string which describes this particular flag or positional parameter.
* </ol>
*
* <p>Each row in the string array is associate with either a positional parameter
* or with a flag. For example, consider this command line:
* <ul>
* <li>My_prog required_parm1 -ab parm_for_ab required_parm2 -help optional_parms
* </ul>
*
* <p>In this example My_prog is the name of the program. required_parm1 and
* required_parm2 must be specified on the command line. Notice that they do not
* have to be adjacent to each other on the command line. optional_parms may optionally
* specified. optional_parms can be 0 or more parameters. They does not need to be
* adjacent to the required parameters, but they do need to follow the required
* parameters. Two flags are specified "-ab" and "-help". The "-ab" flag has a
* parameter "parm_for_ab" associated with it. Note: a flag can not have an optional
* parameter. (ie. a flag either never have a parameter or it always has a parameter)
* In this example, the first two rows in the string array would describe required_parm1
* and required_parm2. The third entry would describe optional_parms. The fourth and
* fifth rows would describe "-ab" and "-help". For this command line the string array
* would look like this:
*
* <ul>
* <li>{ { CommandLine.POSITIONAL, "parm1", CommandLine.NO_DUPS,
* CommandLine.REQUIRED, "parm1 help text" },
* <li>{ CommandLine.POSITIONAL, "parm2", CommandLine.NO_DUPS,
* CommandLine.REQUIRED, "parm2 help text" },
* <li>{ CommandLine.POSITIONAL, "optional_parms", CommandLine.DUPS_OK,
* CommandLine.REQUIRED, "optional help text" },
* <li>{ "ab", "parm_for_ab", CommandLine.NO_DUPS,
* CommandLine.OPTIONAL, "ab help text" },
* <li>{ "help", CommandLine.NO_PARM, CommandLine.NO_DUPS,
* CommandLine.OPTIONAL, "displays this help text" } }
* </ul>
*
* <p>String array rules:
*
* <ol>
* <li>Positional rows must always come first in the array. These rows must
* have a name specified in column 2, except for one case. If you want to indicate that
* there are no optional positional parameters you would put CommandLine.NO_PARM
* in column 2 of the positional row. You would also need to put CommandLine.OPTIONAL
* in column 4 since this row is for optional parameters(or the non-existence of
* optional parameters as the case may be)
* <li>Once a positional row specifies that it is optional, no further positional rows
* may be specified.
* <li>At least one positional row must be specified, even if it is to just to specify that
* there are no optional parameters.
* <li>Flag names must be in lower case. Note: the user can specify upper or lower case
* on the command line.
* <li>If a flag has a parameter the name of the parameter should be put into column 2.
* otherwise CommandLine.NO_PARM should be put in column 2.
* <li>If a flag is allowed to appear more than once on the command line then
* CommandLine.DUPS_OK should be put into column 3, otherwise CommandLine.NO_DUPS
* should be put into column 3.
* <li>If a flag must be specified on the command line then CommandLine.REQUIRED should
* be specified in column 4, otherwise CommandLine.OPTIONAL should be specified.
* <li>A help flag must be specified.
* <li>The strings specified in the flags column, the parameter name column, and the
* help column are always translated using the resource bundle specified. Of
* course the special string values such as POSITIONAL and NO_PARM are not
* translated.
* </ol>
*
* <p> Flag matching rules:
* <ol>
* <li>The parser will attempt to match a user specified flag with the minimum number
* of programmer specified flag characters. For example, if the programmer has
* specified that the flag is "help" the user could specify "-h", "-he", "-hel", or
* "-help". If the programmer has also specified a flag called "hello", the
* user would get an error message for specifing either "-h", "-he" or "-hel", since
* it is ambiguous which flag is being refered to. Both "-hell" and "-hello"
* would be ok for the user to specify the hello flag on the command line.
* <li>If a flag has a parameter, the parameter may be immediately adjacent to the flag.
* For example if "abcd" is specified as a flag with a parameter, the user could
* specify the following assuming there are no other ambiguous flags. "-abcdparm",
* "-abcparm", "-abparm", or "-aparm" where parm is the parameter for the flag.
* (Of course the user can always put a white space between the flag and the
* parameter.)
* <li>If a flag does not have a parameter and a parameter is adjacent to it then this
* parameter is interpreted as a positional parameter. For example if "abcb" is
* specified as a flag and the user specifies "-abhello", then the first "ab" will be
* interpreted as the flag and "hello" will be interpreted as a positional
* parameter.
* </ol>
*
* @author Peter Moogk
* @date July 13, 2000
**/
public class CommandLine
{
// Constant strings that the user should use in their flags_info input array.
/**
* Specifies that this flag or positional parameter is required.
**/
public static final String REQUIRED = "required";
/**
* Specifies that this flag or positional parameter is optional.
**/
public static final String OPTIONAL = "optional";
/**
* Specifies that this flag may be specified more than once on the command line.
* Note: This string has no meaning for positional parameters.
**/
public static final String DUPS_OK = "dups_ok";
/**
* Specifies that this flag may not be specified more than once on the command line.
* Note: This string has no meaning for positional parameters.
**/
public static final String NO_DUPS = "no_dups";
/**
* Specifies that a row is a positional parameter row.
**/
public static final String POSITIONAL = "";
/**
* Specifies that a flag has no parameter. For positional parameters this
* string indicates that there are no optional parameters.
**/
public static final String NO_PARM = "";
/**
* @param flags_info This parameter specifies the characteristics of the
* command line parser. See the class description for a
* definition of what this string array should look like.
* @param help_flag This string indicates which flag in the flags_info
* array is the help flag.
* @param tool_name This string indicates the name of the tool that this
* command line parser is being used for. This string
* is only used when creating the help text.
**/
public CommandLine( String[][] flags_info,
String help_flag,
String tool_name,
ResourceBundle flagMessages )
throws InternalErrorExc
{
this.flags_info = flags_info;
this.help_flag = help_flag;
this.tool_name = tool_name;
this.flagMessages = flagMessages;
messages = ResourceBundle.getBundle( "org.eclipse.wst.command.internal.env.commandline.commandline" );
verify_flags_info();
}
/**
* Call this method to parse a command line.
* @param args This is the string array from the command line.
* @throws Flag_error If the user has specified the command line incorrectly
* a Flag_error exception will be thrown. Use getMessage
* to get a description of the user error.
*
* @throws Help_specified If the user specifies the help flag this exception
* will be thrown. Use getMessage to get a fully
* formatted syntax description of this command line.
**/
public void check_flags( String[] args ) throws Flag_error
{
flags_specified = new Vector[flags_info.length];
for( int index = 0; index < args.length; index++ )
{
boolean processed_the_next_arg = process_arg( args, index );
if( processed_the_next_arg == true ) index++;
}
// If help was specified we will not check the regular rules.
if( !flag_specified( help_flag ) )
{
// Check for flags breaking the rules specified in flags_info.
check_rules();
// Call subclassed method to see if more processing is required.
more_processing();
}
}
/**
* This method is for subclasses of this class. This method is called at
* the very end of check_flags method. It is intended that subclasses would
* perform additional command line checking here.
**/
protected void more_processing() throws Flag_error, InternalErrorExc
{
}
/**
* Once the command line has been parsed by calling check_flags a
* call can be made to this method to get the parameters for this flag.
* If the flag was not specified on the command line null will be returned.
* If the flag was specified, but has no parameters a valid vector will be
* returned containing a null.
**/
public String[] get_flag_parms( String flag )
{
int row = 0;
boolean flag_found = false;
while( flag_found == false && row < flags_info.length )
{
if( flags_info[row][FLAG_COL].equals( flag ) )
{
flag_found = true;
}
else
{
row++;
}
}
if( flag_found == true )
{
Vector parms = flags_specified[row];
return parms == null ? null : (String[])(parms.toArray( new String[0] ));
}
return null;
}
/**
* Call this method to get all of the positional parameters.
* This method returns both the required positionals and the
* optional positionals in that order. If no positional parameters
* were specified null will be returned.
**/
public String[] get_positionals()
{
return (String[])flags_specified[POSITIONAL_ROW].toArray( new String[0] );
}
/**
* This method returns true if this flag was specified by the user
* otherwise false is returned.
**/
public boolean flag_specified( String flag )
{
return get_flag_parms( flag ) != null;
}
/**
* This method returns fully formated help text syntax for this
* command line.
**/
public String get_help_text()
{
StringBuffer help_text = new StringBuffer(400);
int help_width = HELP_LINE_LEN -
2 - // blanks
1 - // dash
max_flag_size - // flag field
1 - // blank
max_name_size - // name field
1; // blank
help_text.append( messages.getString( FlagMessages.PARSER_INFO_SYNTAX ) +
": " + tool_name + " " );
// Display the required positionals if any.
for( int index = 0; index < required_positionals; index++ )
{
help_text.append( flagMessages.getString( flags_info[index][NAME_COL] ) +
" " );
}
help_text.append( "[" + messages.getString( FlagMessages.PARSER_FLAGS ) +
"] " );
if( optional_positionals_allowed == true )
{
help_text.append( flagMessages.getString( flags_info[optional_list_index][NAME_COL] ) );
}
help_text.append( "\n " + messages.getString( FlagMessages.PARSER_INFO_WHERE ) + "\n" );
// Create one line of description for each parameter
for( int row = 0; row < flags_info.length; row++ )
{
String columnId = flags_info[row][NAME_COL];
String columnName = columnId == NO_PARM ? "" : flagMessages.getString( columnId );
String flagId = flags_info[row][FLAG_COL];
String flagName = flagId == POSITIONAL ? POSITIONAL : flagMessages.getString(flagId);
int flag_padding = max_flag_size - flagName.length();
int name_padding = max_name_size - columnName.length();
// Skip this row if this is a marker for no optional positionals.
if( flags_info[row][FLAG_COL] == POSITIONAL &&
flags_info[row][NAME_COL] == NO_PARM ) continue;
if( flagName == POSITIONAL )
{
help_text.append( getBlanks(3 ) );
}
else
{
help_text.append( " -" + flagName );
}
help_text.append( getBlanks( flag_padding + 1 ) );
help_text.append( columnName );
help_text.append( getBlanks( name_padding + 1 ) );
String columnHelp = flagMessages.getString( flags_info[row][HELP_COL] );
String[] split_help_text
= StringUtils.splitter( columnHelp, help_width );
if( split_help_text.length > 0 )
help_text.append( split_help_text[0] + "\n" );
else
help_text.append( "\n" );
for( int index = 1; index < split_help_text.length; index++ )
{
help_text.append( getBlanks( HELP_LINE_LEN - help_width ) );
help_text.append( split_help_text[index] + "\n" );
}
help_text.append( "\n" );
}
return "" + help_text;
}
/**
* Return a string with the specified number of blanks.
*/
private String getBlanks( int count )
{
char[] blanks = new char[count];
Arrays.fill( blanks, 0, count, ' ' );
return new String( blanks );
}
/**
* This class is the base for all command line exception classes.
**/
static public class ErrorExc extends Exception
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 3257567317259793720L;
public ErrorExc( String message, String[] args )
{
super( MessageFormat.format( message, args ) );
}
}
/**
* This class will be thrown when an internal error is detected.
* This usually happens if the flag description information was
* specified incorrectly.
**/
static public class InternalErrorExc extends IllegalArgumentException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 3258410621136614450L;
public InternalErrorExc( String message, String[] args )
{
super( MessageFormat.format( message, args ) );
}
public InternalErrorExc( String message )
{
this( message, (String[])null );
}
public InternalErrorExc( String message, String arg )
{
this( message, new String[]{ arg } );
}
}
/**
* This class will be thrown if a user error occurs while parsing the command line.
**/
static public class Flag_error extends ErrorExc
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 3832621776877663537L;
public Flag_error( String message, String[] args )
{
super( message, args );
}
public Flag_error( String message, String arg )
{
super( message, new String[]{ arg } );
}
public Flag_error( String message )
{
super( message, null );
}
}
/**
* Tries to process a single flag on the command line.
* @param args All the command line parameters.
* @param arg_index This is the index of the argument that is to be processed.
* @return returns true if the argument we are processing is a flag that has a
* parameter and the parameter is specified in the next argument.
**/
private boolean process_arg( String[] args, int arg_index ) throws Flag_error
{
boolean processed_next_arg = false;
if( args[arg_index].charAt(0) == '-' )
{
// This is the start of a flag.
int flag_index = 1;
int info_index = get_info_index( args[arg_index], flag_index );
int max_index = get_max_index( args[arg_index], flag_index, info_index );
if( flags_info[info_index][NAME_COL] != NO_PARM )
{
// This flag takes a parameter so check if it is stuck to this
// arg.
if( max_index < args[arg_index].length() )
{
add_flag_parm( info_index,
args[arg_index].substring( max_index,
args[arg_index].length() ) );
}
else
{
// This flag has a parameter and it wasn't stuck to the flag,
// so we will try to get it from the next arg.
if( arg_index+1 < args.length &&
args[arg_index+1].charAt(0) != '-' )
{
// We found an parameter in the next string so we will use this
// one as a parameter for this flag. Note: if was no parameter
// after the flag at all, the error will be caught in the
// check_rules method.
add_flag_parm( info_index, args[arg_index+1] );
processed_next_arg = true;
}
else
{
// Error missing paramater. This error is caught by check_rules.
add_flag_parm( info_index, null );
}
}
}
else
{
// The flag does not have a parameter so we will add a null.
add_flag_parm( info_index, null );
// Check to see if a positional parameter is stuck to this flag.
if( max_index < args[arg_index].length() )
{
add_positional( args[arg_index].substring( max_index,
args[arg_index].length() ) );
}
}
}
else
{
// This is a positional parameter.
add_positional( args[arg_index] );
}
return processed_next_arg;
}
/**
* Finds the row for the flag that uniquely matched this flag str.
* @return returns the flags_info index of the matching flag.
**/
private int get_info_index( String flag_str, int start_index )
throws Flag_error
{
//int info_start = 1;
//int info_end = flags_info.length;
int info_index;
int found_count = 0;
int info_col_index = 0;
int last_info_index = 0;
BitSet flags_rejected = new BitSet();
// Loop over each char in flag_str. Note: we will probably bail early.
for( int flag_col_index = start_index; flag_col_index < flag_str.length(); flag_col_index++ )
{
// Loop over each flag in flag_info
for( info_index = 0; info_index < flags_info.length; info_index++ )
{
String flagId = flags_info[info_index][FLAG_COL];
String flagName = flagId == POSITIONAL ? POSITIONAL : flagMessages.getString( flagId );
if( flags_rejected.get( info_index ) == false &&
info_col_index < flagName.length() &&
Character.toLowerCase(flag_str.charAt(flag_col_index)) ==
flagName.charAt(info_col_index) )
{
found_count++;
last_info_index = info_index;
}
else
{
flags_rejected.set( info_index );
}
}
if( found_count == 1 )
{
// We have a match.
return last_info_index;
}
else if( found_count == 0 )
{
// Flag not found at all.
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_FLAG_NOT_FOUND ),
flag_str.substring( start_index ) );
}
else
{
// More than one flag was found with this char so we will go to the
// next char to uniquely match it.
info_col_index++;
//info_start = last_info_index - found_count + 1;
//info_end = last_info_index + 1;
found_count = 0;
}
}
// The only way to get to this code is if the loop exited with
// the found_count greater than 1. Therefore, the flag specified is
// ambiguous.
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_AMBIGUOUS_FLAG ),
flag_str.substring( start_index) );
}
/**
* This method tries to match as many characters as possible of the user
* specified flag with the matched flag string.
* @return returns the position of the last matching flag chararacter.
**/
private int get_max_index( String flag_str, int flag_start, int info_index )
{
int flag_col_index = flag_start;
int info_col_index = 0;
String info_str = flagMessages.getString( flags_info[info_index][FLAG_COL] );
while( flag_col_index < flag_str.length() &&
info_col_index < info_str.length() )
{
if( Character.toLowerCase( flag_str.charAt(flag_col_index) ) !=
info_str.charAt(info_col_index) )
break;
flag_col_index++;
info_col_index++;
}
return flag_col_index;
}
/**
* Adds a positional parameter to flags_specified.
**/
private void add_positional( String positional_parm )
{
if( flags_specified[POSITIONAL_ROW] == null )
flags_specified[POSITIONAL_ROW] = new Vector(3);
flags_specified[POSITIONAL_ROW].add( positional_parm );
}
/**
* Adds a flag and its parameter to flags_specified. If only the
* flag was specified, then a null should be passed to flag_parm.
**/
private void add_flag_parm( int flag_index, String flag_parm )
throws Flag_error
{
if( flags_info[flag_index][DUP_COL] == NO_DUPS &&
flags_specified[flag_index] != null )
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_DUPLICATE_FLAGS_NOT_ALLOWED ),
flagMessages.getString( flags_info[flag_index][FLAG_COL] ) );
if( flags_specified[flag_index] == null )
flags_specified[flag_index] = new Vector(3);
flags_specified[flag_index].add( flag_parm );
}
/**
* Checks that the user hasn't broken any command line rules.
**/
private void check_rules() throws Flag_error
{
// Check that all of the required positionals were specified.
int positional_count = 0;
if( flags_specified[POSITIONAL_ROW] != null )
{
positional_count = flags_specified[POSITIONAL_ROW].size();
}
if( required_positionals > positional_count )
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_MISSING_POSITIONAL ),
flagMessages.getString( flags_info[required_positionals-1][NAME_COL] ) );
else if( required_positionals < positional_count &&
optional_positionals_allowed == false )
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_TOO_MANY_POSITIONALS ) );
for( int row = 0; row < flags_info.length; row++ )
{
if( flags_info[row][FLAG_COL] == POSITIONAL ) continue;
if( flags_specified[row] == null &&
flags_info[row][REQUIRED_COL] == REQUIRED )
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_MISSING_REQUIRED_FLAG ),
flagMessages.getString( flags_info[row][FLAG_COL] ) );
int parm_count = 0;
if( flags_specified[row] != null ) parm_count = flags_specified[row].size();
// Check for too many flag parameters.
if( flags_info[row][DUP_COL] == NO_DUPS && parm_count > 1 )
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_DUPLICATE_FLAGS_NOT_ALLOWED ),
flagMessages.getString( flags_info[row][FLAG_COL] ) );
// Check for missing flag parameter.
if( parm_count > 0 && flags_info[row][NAME_COL] != NO_PARM )
{
for( int index = 0; index < flags_specified[row].size(); index++ )
{
if( flags_specified[row].elementAt(index) == null )
throw new Flag_error( messages.getString( FlagMessages.PARSER_ERROR_MISSING_FLAG_PARAMETER ),
new String[]
{ flagMessages.getString( flags_info[row][FLAG_COL] ),
flagMessages.getString( flags_info[row][NAME_COL] ) } );
}
}
}
}
/**
* This method verifies that a proper flags_info string array was passed
* to us by the programmer.
**/
private void verify_flags_info() throws InternalErrorExc
{
boolean done_positionals = false;
boolean help_specified = false;
required_positionals = 0;
optional_positionals_allowed = false;
optional_list_index = -1;
max_flag_size = 0;
max_name_size = 0;
if( flags_info == null || flags_info.length == 0 )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_NO_FLAGS_DATA_SPECIFIED ) );
if( flags_info[POSITIONAL_ROW] != null &&
flags_info[POSITIONAL_ROW].length > 0 &&
flags_info[POSITIONAL_ROW][FLAG_COL] != POSITIONAL )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_FIRST_FLAG_NOT_POSITIONAL ) );
for( int row = 0; row < flags_info.length; row++ )
{
if( flags_info[row] == null )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_NULL_FLAG_ROW ) );
if( flags_info[row].length != 5 )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_INCORRECT_ROW_SIZE ) );
if( flags_info[row][FLAG_COL] == null ||
flags_info[row][NAME_COL] == null ||
flags_info[row][HELP_COL] == null )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_NULL_IN_ROW ) );
if( flags_info[row][FLAG_COL].equals( help_flag ) ) help_specified = true;
String flagId = flags_info[row][FLAG_COL];
String nameId = flags_info[row][NAME_COL];
String flag_col = flagId == POSITIONAL ? POSITIONAL : flagMessages.getString( flagId );
String name_col = nameId == NO_PARM ? NO_PARM : flagMessages.getString( nameId );
if( flag_col.length() > max_flag_size )
max_flag_size = flag_col.length();
if( name_col != NO_PARM && name_col.length() > max_name_size )
max_name_size = name_col.length();
// Ensure that flags are all in lowercase.
if( !flag_col.equals( flag_col.toLowerCase() ) )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_FLAG_NOT_LOWERCASE ),
flag_col );
// Ensure that only the predefined dup strings are used.
// Note: it's ok to use != when comparing constant strings literals.
if( flags_info[row][DUP_COL] == null ||
( flags_info[row][DUP_COL] != NO_DUPS &&
flags_info[row][DUP_COL] != DUPS_OK ) )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_INCORRECT_DUP_STRING ),
flags_info[row][DUP_COL] );
// Ensure that only the predefined required strings are used.
if( flags_info[row][REQUIRED_COL] == null ||
( flags_info[row][REQUIRED_COL] != REQUIRED &&
flags_info[row][REQUIRED_COL] != OPTIONAL ) )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_INCORRECT_REQUIRED_STRING ),
flags_info[row][REQUIRED_COL] );
// Count the number of required positionals.
if( flags_info[row][FLAG_COL] == POSITIONAL )
{
if( flags_info[row][REQUIRED_COL] == REQUIRED )
{
if( flags_info[row][NAME_COL] == NO_PARM )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_REQUIRED_POSITIONAL_NEEDS_NAME ) );
required_positionals++;
}
else if( flags_info[row][NAME_COL] != NO_PARM )
{
// We use the NAME_COL field for an optional positional to denote
// whether additional positionals are allowed or not.
optional_positionals_allowed = true;
optional_list_index = row;
}
}
// Ensure that positionals are at the beginning of the info.
if( flags_info[row][FLAG_COL] != POSITIONAL ||
( done_positionals == false &&
flags_info[row][FLAG_COL] == POSITIONAL &&
flags_info[row][REQUIRED_COL] == OPTIONAL ) )
{
done_positionals = true;
}
else if( done_positionals == true )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_POSITIONAL_NOT_AT_BEGINNING ) );
}
// Ensure that a help flag was specified in the info list.
if( help_specified == false )
throw new InternalErrorExc( messages.getString( FlagMessages.PARSER_ERROR_HELP_FLAG_NOT_SPECIFIED ) );
}
/**
* This method is used to dump internal information about a parsed
* command line.
**/
public String toString()
{
StringBuffer b = new StringBuffer(100);
for( int row = 0; row < flags_info.length; row++ )
{
b.append( "\n" );
if( flags_info[row][FLAG_COL] == POSITIONAL )
b.append( "Positional:" );
else
b.append( flagMessages.getString( flags_info[row][FLAG_COL] ) + ":" );
if( flags_specified[row] == null )
b.append( "no parameters" );
else
for( int parm_index = 0; parm_index < flags_specified[row].size(); parm_index++ )
{
String parm = (String)flags_specified[row].elementAt(parm_index);
b.append( parm + ":" );
}
b.append( "\n" );
}
return ""+b;
}
private static final int FLAG_COL = 0;
private static final int NAME_COL = 1;
private static final int DUP_COL = 2;
private static final int REQUIRED_COL = 3;
private static final int HELP_COL = 4;
private static final int POSITIONAL_ROW = 0;
private static final int HELP_LINE_LEN = 75;
private String[][] flags_info;
private String help_flag;
private String tool_name;
private Vector[] flags_specified;
private int required_positionals;
private boolean optional_positionals_allowed;
private int optional_list_index;
private int max_flag_size;
private int max_name_size;
protected ResourceBundle messages;
private ResourceBundle flagMessages;
}