Frames | No Frames |
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: }