Source for net.dpml.cli.option.PropertyOption

   1: /*
   2:  * Copyright 2003-2005 The Apache Software Foundation
   3:  * Copyright 2005 Stephen McConnell
   4:  *
   5:  * Licensed under the Apache License, Version 2.0 (the "License");
   6:  * you may not use this file except in compliance with the License.
   7:  * You may obtain a copy of the License at
   8:  *
   9:  *     http://www.apache.org/licenses/LICENSE-2.0
  10:  *
  11:  * Unless required by applicable law or agreed to in writing, software
  12:  * distributed under the License is distributed on an "AS IS" BASIS,
  13:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14:  * See the License for the specific language governing permissions and
  15:  * limitations under the License.
  16:  */
  17: package net.dpml.cli.option;
  18: 
  19: import java.util.Collections;
  20: import java.util.Comparator;
  21: import java.util.List;
  22: import java.util.ListIterator;
  23: import java.util.Set;
  24: 
  25: import net.dpml.cli.DisplaySetting;
  26: import net.dpml.cli.HelpLine;
  27: import net.dpml.cli.OptionException;
  28: import net.dpml.cli.WriteableCommandLine;
  29: import net.dpml.cli.resource.ResourceConstants;
  30: 
  31: /**
  32:  * Handles the java style "-Dprop=value" opions
  33:  * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
  34:  * @version @PROJECT-VERSION@
  35:  */
  36: public class PropertyOption extends OptionImpl
  37: {
  38:    /** 
  39:     * The default property option name.
  40:     */
  41:     public static final String DEFAULT_OPTION_STRING = "-D";
  42:     
  43:    /** 
  44:     * The default property option description.
  45:     */
  46:     public static final String DEFAULT_DESCRIPTION = "Set property values.";
  47: 
  48:     /**
  49:      * A default PropertyOption instance
  50:      */
  51:     public static final PropertyOption INSTANCE = new PropertyOption();
  52:     
  53:     private final String m_optionString;
  54:     private final String m_description;
  55:     private final Set m_prefixes;
  56: 
  57:     /**
  58:      * Creates a new PropertyOption using the default settings of a "-D" trigger
  59:      * and an id of 'D'
  60:      */
  61:     public PropertyOption() 
  62:     {
  63:         this( DEFAULT_OPTION_STRING, DEFAULT_DESCRIPTION, 'D' );
  64:     }
  65: 
  66:     /**
  67:      * Creates a new PropertyOption using the specified parameters
  68:      * @param optionString the trigger for the Option
  69:      * @param description the description of the Option
  70:      * @param id the id of the Option
  71:      */
  72:     public PropertyOption(
  73:       final String optionString, final String description, final int id )
  74:     {
  75:         super( id, false );
  76:         m_optionString = optionString;
  77:         m_description = description;
  78:         m_prefixes = Collections.singleton( optionString );
  79:     }
  80: 
  81:     /**
  82:      * Indicates whether this Option will be able to process the particular
  83:      * argument.
  84:      * 
  85:      * @param commandLine the CommandLine object to store defaults in
  86:      * @param argument the argument to be tested
  87:      * @return true if the argument can be processed by this Option
  88:      */
  89:     public boolean canProcess(
  90:       final WriteableCommandLine commandLine, final String argument )
  91:     {
  92:         return ( argument != null ) 
  93:           && argument.startsWith( m_optionString ) 
  94:           && ( argument.length() > m_optionString.length() );
  95:     }
  96: 
  97:     /**
  98:      * Identifies the argument prefixes that should be considered options. This
  99:      * is used to identify whether a given string looks like an option or an
 100:      * argument value. Typically an option would return the set [--,-] while
 101:      * switches might offer [-,+].
 102:      * 
 103:      * The returned Set must not be null.
 104:      * 
 105:      * @return The set of prefixes for this Option
 106:      */
 107:     public Set getPrefixes() 
 108:     {
 109:         return m_prefixes;
 110:     }
 111: 
 112:     /**
 113:      * Processes String arguments into a CommandLine.
 114:      * 
 115:      * The iterator will initially point at the first argument to be processed
 116:      * and at the end of the method should point to the first argument not
 117:      * processed. This method MUST process at least one argument from the
 118:      * ListIterator.
 119:      * 
 120:      * @param commandLine the CommandLine object to store results in
 121:      * @param arguments the arguments to process
 122:      * @throws OptionException if any problems occur
 123:      */
 124:     public void process(
 125:       final WriteableCommandLine commandLine, final ListIterator arguments )
 126:       throws OptionException 
 127:     {
 128:         final String arg = (String) arguments.next();
 129: 
 130:         if( !canProcess( commandLine, arg ) )
 131:         {
 132:             throw new OptionException(
 133:               this,
 134:               ResourceConstants.UNEXPECTED_TOKEN, 
 135:               arg );
 136:         }
 137:         
 138:         final int propertyStart = m_optionString.length();
 139:         final int equalsIndex = arg.indexOf( '=', propertyStart );
 140:         final String property;
 141:         final String value;
 142: 
 143:         if( equalsIndex < 0 )
 144:         {
 145:             property = arg.substring( propertyStart );
 146:             value = "true";
 147:         }
 148:         else
 149:         {
 150:             property = arg.substring( propertyStart, equalsIndex );
 151:             value = arg.substring( equalsIndex + 1 );
 152:         }
 153:         commandLine.addProperty( property, value );
 154:     }
 155: 
 156:     /**
 157:      * Identifies the argument prefixes that should trigger this option. This
 158:      * is used to decide which of many Options should be tried when processing
 159:      * a given argument string.
 160:      * 
 161:      * The returned Set must not be null.
 162:      * 
 163:      * @return The set of triggers for this Option
 164:      */
 165:     public Set getTriggers()
 166:     {
 167:         return Collections.singleton( m_optionString );
 168:     }
 169: 
 170:     /**
 171:      * Checks that the supplied CommandLine is valid with respect to this
 172:      * option.
 173:      * 
 174:      * @param commandLine the CommandLine to check.
 175:      * @throws OptionException if the CommandLine is not valid.
 176:      */
 177:     public void validate( WriteableCommandLine commandLine ) throws OptionException
 178:     {
 179:         // PropertyOption needs no validation
 180:     }
 181: 
 182:     /**
 183:      * Appends usage information to the specified StringBuffer
 184:      * 
 185:      * @param buffer the buffer to append to
 186:      * @param helpSettings a set of display settings @see DisplaySetting
 187:      * @param comp a comparator used to sort the Options
 188:      */
 189:     public void appendUsage(
 190:       final StringBuffer buffer, final Set helpSettings, final Comparator comp ) 
 191:     {
 192:         final boolean display = helpSettings.contains( DisplaySetting.DISPLAY_PROPERTY_OPTION );
 193:         final boolean bracketed = helpSettings.contains( DisplaySetting.DISPLAY_ARGUMENT_BRACKETED );
 194: 
 195:         if( display )
 196:         {
 197:             buffer.append( m_optionString );
 198:             if( bracketed ) 
 199:             {
 200:                 buffer.append( '<' );
 201:             }
 202:             buffer.append( "property" );
 203:             if( bracketed ) 
 204:             {
 205:                 buffer.append( '>' );
 206:             }
 207:             buffer.append( "=" );
 208:             if( bracketed )
 209:             {
 210:                 buffer.append( '<' );
 211:             }
 212:             buffer.append( "value" );
 213:             if( bracketed )
 214:             {
 215:                 buffer.append( '>' );
 216:             }
 217:         }
 218:     }
 219: 
 220:     /**
 221:      * The preferred name of an option is used for generating help and usage
 222:      * information.
 223:      * 
 224:      * @return The preferred name of the option
 225:      */
 226:     public String getPreferredName() 
 227:     {
 228:         return m_optionString;
 229:     }
 230: 
 231:     /**
 232:      * Returns a description of the option. This string is used to build help
 233:      * messages as in the HelpFormatter.
 234:      * 
 235:      * @see net.dpml.cli.util.HelpFormatter
 236:      * @return a description of the option.
 237:      */
 238:     public String getDescription()
 239:     {
 240:         return m_description;
 241:     }
 242: 
 243:     /**
 244:      * Builds up a list of HelpLineImpl instances to be presented by HelpFormatter.
 245:      * 
 246:      * @see HelpLine
 247:      * @see net.dpml.cli.util.HelpFormatter
 248:      * @param depth the initial indent depth
 249:      * @param helpSettings the HelpSettings that should be applied
 250:      * @param comp a comparator used to sort options when applicable.
 251:      * @return a List of HelpLineImpl objects
 252:      */
 253:     public List helpLines(
 254:       final int depth, final Set helpSettings, final Comparator comp )
 255:     {
 256:         if( helpSettings.contains( DisplaySetting.DISPLAY_PROPERTY_OPTION ) ) 
 257:         {
 258:             final HelpLine helpLine = new HelpLineImpl( this, depth );
 259:             return Collections.singletonList( helpLine );
 260:         } 
 261:         else
 262:         {
 263:             return Collections.EMPTY_LIST;
 264:         }
 265:     }
 266: }