Source for net.dpml.cli.option.Command

   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.ArrayList;
  20: import java.util.Collections;
  21: import java.util.Comparator;
  22: import java.util.HashSet;
  23: import java.util.Iterator;
  24: import java.util.List;
  25: import java.util.ListIterator;
  26: import java.util.Set;
  27: 
  28: import net.dpml.cli.Argument;
  29: import net.dpml.cli.DisplaySetting;
  30: import net.dpml.cli.Group;
  31: import net.dpml.cli.OptionException;
  32: import net.dpml.cli.WriteableCommandLine;
  33: import net.dpml.cli.resource.ResourceConstants;
  34: import net.dpml.cli.resource.ResourceHelper;
  35: 
  36: /**
  37:  * Represents a cvs "update" style command line option.
  38:  *
  39:  * Like all Parents, Commands can have child options and can be part of
  40:  * Arguments.
  41:  *
  42:  * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
  43:  * @version @PROJECT-VERSION@
  44:  */
  45: public class Command extends ParentImpl
  46: {
  47:     /** The display name for the command */
  48:     private final String m_preferredName;
  49: 
  50:     /** The aliases for this command */
  51:     private final Set m_aliases;
  52: 
  53:     /** All the names for this command */
  54:     private final Set m_triggers;
  55: 
  56:     /**
  57:      * Creates a new Command instance.
  58:      *
  59:      * @param preferredName the name normally used to refer to the Command
  60:      * @param description a description of the Command
  61:      * @param aliases alternative names for the Command
  62:      * @param required true if the Command is required
  63:      * @param argument an Argument that the command takes
  64:      * @param children the Group of child options for this Command
  65:      * @param id a unique id for the Command
  66:      * @see ParentImpl#ParentImpl(Argument, Group, String, int, boolean)
  67:      */
  68:     public Command(
  69:       final String preferredName, final String description, final Set aliases, 
  70:       final boolean required, final Argument argument, final Group children, final int id )
  71:     {
  72:         super( argument, children, description, id, required );
  73: 
  74:         // check the preferred name is valid
  75:         if( ( preferredName == null ) || ( preferredName.length() < 1 ) )
  76:         {
  77:             throw new IllegalArgumentException(
  78:               ResourceHelper.getResourceHelper().getMessage(
  79:                 ResourceConstants.COMMAND_PREFERRED_NAME_TOO_SHORT ) );
  80:         }
  81: 
  82:         m_preferredName = preferredName;
  83: 
  84:         // gracefully and defensively handle aliases
  85:         
  86:         if( null == aliases )
  87:         {
  88:             m_aliases = Collections.EMPTY_SET;
  89:         }
  90:         else
  91:         {
  92:             m_aliases = Collections.unmodifiableSet( new HashSet( aliases ) );
  93:         }
  94:         
  95:         // populate the triggers Set
  96:         final Set newTriggers = new HashSet();
  97:         newTriggers.add( preferredName );
  98:         newTriggers.addAll( m_aliases );
  99:         m_triggers = Collections.unmodifiableSet( newTriggers );
 100:     }
 101: 
 102:    /**
 103:     * Process the parent.
 104:     * @param commandLine the commandline
 105:     * @param arguments an iterator of arguments
 106:     * @exception OptionException if an error occurs
 107:     */
 108:     public void processParent(
 109:       final WriteableCommandLine commandLine, final ListIterator arguments )
 110:       throws OptionException
 111:     {
 112:         // grab the argument to process
 113:         final String arg = (String) arguments.next();
 114: 
 115:         // if we can process it
 116:         if( canProcess( commandLine, arg ) )
 117:         {
 118:             // then note the option
 119:             commandLine.addOption( this );
 120: 
 121:             // normalise the argument list
 122:             arguments.set( m_preferredName );
 123:         }
 124:         else
 125:         {
 126:             throw new OptionException(
 127:               this,
 128:               ResourceConstants.UNEXPECTED_TOKEN, 
 129:               arg );
 130:         }
 131:     }
 132: 
 133:     /**
 134:      * Identifies the argument prefixes that should trigger this option. This
 135:      * is used to decide which of many Options should be tried when processing
 136:      * a given argument string.
 137:      * 
 138:      * The returned Set must not be null.
 139:      * 
 140:      * @return The set of triggers for this Option
 141:      */
 142:     public Set getTriggers()
 143:     {
 144:         return m_triggers;
 145:     }
 146: 
 147:     /**
 148:      * Checks that the supplied CommandLine is valid with respect to this
 149:      * option.
 150:      * 
 151:      * @param commandLine the CommandLine to check.
 152:      * @throws OptionException if the CommandLine is not valid.
 153:      */
 154:     public void validate( WriteableCommandLine commandLine ) throws OptionException
 155:     {
 156:         if( isRequired() && !commandLine.hasOption( this ) )
 157:         {
 158:             throw new OptionException(
 159:               this,
 160:               ResourceConstants.OPTION_MISSING_REQUIRED,
 161:               getPreferredName() );
 162:         }
 163:         super.validate( commandLine );
 164:     }
 165: 
 166:     /**
 167:      * Appends usage information to the specified StringBuffer
 168:      * 
 169:      * @param buffer the buffer to append to
 170:      * @param helpSettings a set of display settings @see DisplaySetting
 171:      * @param comp a comparator used to sort the Options
 172:      */
 173:     public void appendUsage(
 174:       final StringBuffer buffer, final Set helpSettings, final Comparator comp )
 175:       {
 176:         // do we display optionality
 177:         final boolean optional =
 178:           !isRequired() && helpSettings.contains( DisplaySetting.DISPLAY_OPTIONAL );
 179:         final boolean displayAliases = 
 180:           helpSettings.contains( DisplaySetting.DISPLAY_ALIASES );
 181: 
 182:         if( optional )
 183:         {
 184:             buffer.append( '[' );
 185:         }
 186: 
 187:         buffer.append( m_preferredName );
 188: 
 189:         if( displayAliases && !m_aliases.isEmpty() )
 190:         {
 191:             buffer.append( " (" );
 192:             final List list = new ArrayList( m_aliases );
 193:             Collections.sort( list );
 194:             for( final Iterator i = list.iterator(); i.hasNext();)
 195:             {
 196:                 final String alias = (String) i.next();
 197:                 buffer.append( alias );
 198:                 if( i.hasNext() )
 199:                 {
 200:                     buffer.append( ',' );
 201:                 }
 202:             }
 203:             buffer.append( ')' );
 204:         }
 205: 
 206:         super.appendUsage( buffer, helpSettings, comp );
 207:         if( optional )
 208:         {
 209:             buffer.append( ']' );
 210:         }
 211:     }
 212: 
 213:     /**
 214:      * The preferred name of an option is used for generating help and usage
 215:      * information.
 216:      * 
 217:      * @return The preferred name of the option
 218:      */
 219:     public String getPreferredName()
 220:     {
 221:         return m_preferredName;
 222:     }
 223: }