Source Code Cross Referenced for CLIPParser.java in  » Portal » Open-Portal » com » sun » portal » desktop » dp » cli » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Portal » Open Portal » com.sun.portal.desktop.dp.cli 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // ***************************************************************
0002:        // *                                                             *
0003:        // * File:CLIPParser.java                                        *
0004:        // *                                                             *
0005:        // *  Copyright (c) 2001 Sun Microsystems, Inc.                  *
0006:        // *  All rights reserved.                                       *
0007:        // *                                                             *
0008:        // *                                                             *
0009:        // * Date      - Dec/15/2001                                     *
0010:        // * Author    - alejandro.abdelnur@sun.com                      *
0011:        // *                                                             *
0012:        // ***************************************************************
0013:
0014:        //package com.iplanet.common.util;
0015:        package com.sun.portal.desktop.dp.cli;
0016:
0017:        import java.util.List;
0018:        import java.util.ArrayList;
0019:        import java.util.Map;
0020:        import java.util.HashMap;
0021:        import java.util.StringTokenizer;
0022:        import java.util.Set;
0023:        import java.util.HashSet;
0024:        import java.util.Iterator;
0025:        import java.util.Collections;
0026:
0027:        /**
0028:         * The CLIPParser implements a Command Line User Interface parser following
0029:         * the Sun ONE UI Style Project Guide 2.1.
0030:         * <P>
0031:         * It parses the command line arguments according to the <B>CLIP full</B> specification.
0032:         * <P>
0033:         * Refer to the <A HREF="http://bones.red.iplanet.com/ftp/hie/projects/DesktopUIStyle/Version2-1Final/Desktop_UI_Style_Guide/A_La_Carte/CLUI/BareNakedGuidelines/Home.htm#CLIPSpec">CLIP specification</A> for more details.
0034:         * <P>
0035:         * CLIPParser instances are thread-safe.
0036:         * <P>
0037:         * CLIPParser example with sub commands:
0038:         * <P>
0039:         * <PRE>
0040:         *
0041:         *      import com.iplanet.common.util. CLIPParser;
0042:         *      import com.iplanet.common.util. CLIPException;
0043:         *
0044:         *      public class CLIPParserTest {
0045:         *
0046:         *          public static void main(String[] args) throws CLIPException {
0047:         *
0048:         *              CLIPParser.Option[] options0 = new CLIPParser.Option[2];
0049:         *              options0[0] = new CLIPParser.Option("user","u",CLIPParser.REGULAR,null,"user name");
0050:         *              options0[1] = new CLIPParser.Option("password","p",CLIPParser.REGULAR,null,"user password");
0051:         *
0052:         *              CLIPParser.Option[] options1 = new CLIPParser.Option[4];
0053:         *              options1[0] = new CLIPParser.Option("user","u",CLIPParser.REGULAR,null,"user name");
0054:         *              options1[1] = new CLIPParser.Option("password","p",CLIPParser.REGULAR,null,"user password");
0055:         *              options1[3] = new CLIPParser.Option("owner","o",CLIPParser.REGULAR,"user","elements owner");
0056:         *              options1[2] = new CLIPParser.Option("verbose","v",CLIPParser.BOOLEAN,"false","echoes actions");
0057:         *
0058:         *              CLIPParser.Option[] options2 = new CLIPParser.Option[3];
0059:         *              options2[0] = new CLIPParser.Option("user","u",CLIPParser.REGULAR,null,"user name");
0060:         *              options2[1] = new CLIPParser.Option("password","p",CLIPParser.REGULAR,null,"user password");
0061:         *              options2[2] = new CLIPParser.Option("verbose","v",CLIPParser.BOOLEAN,"false","echos actions");
0062:         *
0063:         *              CLIPParser.SubCommand[] subCommands = new CLIPParser.SubCommand[3];
0064:         *
0065:         *              subCommands[0] = new CLIPParser.SubCommand("list",options0,0,0,"Lists current elements","");
0066:         *              subCommands[1] = new CLIPParser.SubCommand("add",options1,1,10000,"Adds new elements","elements to add");
0067:         *              subCommands[2] = new CLIPParser.SubCommand("remove",options2,1,1000,"Removes existing elements","elemenst to remove");
0068:         *
0069:         *              CLIPParser clip = new CLIPParser(subCommands,"Super command (w/ sub commands)");
0070:         *
0071:         *              clip.verifyArguments(args);
0072:         *
0073:         *              if (clip.needsHelp(args)) {
0074:         *                  System.out.println(clip.getHelp(args));
0075:         *              }
0076:         *              else {
0077:         *                  System.out.println(clip.toString(args));
0078:         *              }
0079:         *          }
0080:         *
0081:         *      }
0082:         *
0083:         * </PRE>
0084:         *
0085:         * @author <A HREF="mailto:alejandro.abdelnur@sun.com">Alejandro Abdelnur</A>
0086:         *
0087:         */
0088:        public class CLIPParser {
0089:
0090:            /**
0091:             * Prefix for all types of options.
0092:             *
0093:             */
0094:            private static final String OPTION_PREFIX = "-";
0095:
0096:            /**
0097:             * The switch for short option arguments.
0098:             *
0099:             */
0100:            private static final String SHORT_OPTION = OPTION_PREFIX;
0101:
0102:            /**
0103:             * The switch for long option arguments.
0104:             *
0105:             */
0106:            private static final String LONG_OPTION = OPTION_PREFIX + "-";
0107:
0108:            /**
0109:             * The switch for negating a boolean option argument.
0110:             *
0111:             */
0112:            private static final String NEGATE_OPTION = OPTION_PREFIX + "-no-";
0113:
0114:            /**
0115:             * Indicates that no more options occur.
0116:             *
0117:             */
0118:            private static final String NO_MORE_OPTIONS = OPTION_PREFIX + "-";
0119:
0120:            /**
0121:             * Indicates addition to collection option.
0122:             *
0123:             */
0124:            private static final String ADD_TO_COLLECTION_OPTION = OPTION_PREFIX
0125:                    + "-add-";
0126:
0127:            /**
0128:             * Indicates removal from collection option.
0129:             *
0130:             */
0131:            private static final String REMOVE_FROM_COLLECTION_OPTION = OPTION_PREFIX
0132:                    + "-remove-";
0133:
0134:            /**
0135:             * Type for boolean options.
0136:             *
0137:             */
0138:            public static final int BOOLEAN = 0;
0139:
0140:            /**
0141:             * Type for regular options.
0142:             *
0143:             */
0144:            public static final int REGULAR = 1;
0145:
0146:            /**
0147:             * Type for collection options.
0148:             *
0149:             */
0150:            public static final int COLLECTION = 2;
0151:
0152:            /**
0153:             * The Option class defines a CLIP option.
0154:             * <P>
0155:             * It defines the long and short (if exists) names, if the option is mandatory, its type and default value (if any).
0156:             * <P>
0157:             *
0158:             * @author <A HREF="mailto:alejandro.abdelnur@sun.com">Alejandro Abdelnur</A>
0159:             *
0160:             */
0161:            public static class Option {
0162:                private String _longName;
0163:                private String _shortName;
0164:                private boolean _mandatory;
0165:                private int _type;
0166:                private String _argName = null;
0167:                private String[] _defaultValues;
0168:                private String _helpMessage;
0169:
0170:                /**
0171:                 * Creates a CLIPParser Option.
0172:                 * <P>
0173:                 *
0174:                 * @param longName option's long name, it can not be NULL and it has to be at least 2 characters.
0175:                 *
0176:                 * @param shortName option's short name, it can be undefined (NULL) or it has to be exactly one character.
0177:                 *
0178:                 * @param type indicates the type of the option, it can be BOOLEAN, REGULAR or COLLECTION.
0179:                 *
0180:                 * @param defaultValues specifies the option default value if any, NULL indicates no default value.
0181:                 *                      If the option has not default value the option is mandatory.
0182:                 *                      If the option is a collection the elements have to be separated with commas or white spaces,
0183:                 *                      if a white space is present then the commas are consider part of a single value.
0184:                 *                      For boolean options the default value can be 'true' or 'false'.
0185:                 *
0186:                 * @param argName option argument name
0187:                 *
0188:                 * @param helpMessage help message for the option.
0189:                 *
0190:                 * @throws IllegalArgumentException if the information passed is invalid.
0191:                 *
0192:                 */
0193:                public Option(String longName, String shortName, int type,
0194:                        String defaultValues, String argName, String helpMessage)
0195:                        throws IllegalArgumentException {
0196:                    verifyName(longName,
0197:                            "CLIPParser.Option - Option's long name");
0198:                    _longName = longName;
0199:
0200:                    if (shortName != null && shortName.length() > 1) {
0201:                        throw new IllegalArgumentException(
0202:                                "CLIPParser.Option - Option's short name has to be undefined (NULL) or one character long");
0203:                    }
0204:                    if (shortName != null && shortName.equals("-")) {
0205:                        throw new IllegalArgumentException(
0206:                                "CLIPParser.Option - Option's short name can not be '-'");
0207:                    }
0208:                    _shortName = shortName;
0209:
0210:                    _mandatory = defaultValues == null;
0211:
0212:                    _argName = argName;
0213:
0214:                    if (helpMessage == null) {
0215:                        throw new IllegalArgumentException(
0216:                                "CLIPParser.Option - Option's help can not be NULL");
0217:                    }
0218:                    _helpMessage = helpMessage;
0219:
0220:                    _type = type;
0221:                    switch (type) {
0222:                    case BOOLEAN:
0223:                        if (defaultValues != null) {
0224:                            if (!defaultValues.equals("true")
0225:                                    && !defaultValues.equals("false")) {
0226:                                throw new IllegalArgumentException(
0227:                                        "CLIPParser.Option - Boolean default value has to be 'true' or 'false'");
0228:                            }
0229:                            _defaultValues = new String[1];
0230:                            _defaultValues[0] = defaultValues;
0231:                        }
0232:                        break;
0233:                    case REGULAR:
0234:                        if (defaultValues != null) {
0235:                            _defaultValues = new String[1];
0236:                            _defaultValues[0] = defaultValues;
0237:                        }
0238:                        break;
0239:                    case COLLECTION:
0240:                        if (shortName != null) {
0241:                            throw new IllegalArgumentException(
0242:                                    "CLIPParser.Option - Collection options can not have short names");
0243:                        }
0244:                        if (defaultValues != null) {
0245:                            List l = new ArrayList();
0246:                            String tokenSeparator = (defaultValues.indexOf(" ") > -1) ? " "
0247:                                    : ",";
0248:                            StringTokenizer tokens = new StringTokenizer(
0249:                                    defaultValues, tokenSeparator);
0250:                            while (tokens.hasMoreTokens()) {
0251:                                String token = tokens.nextToken();
0252:                                l.add(token);
0253:                            }
0254:                            _defaultValues = new String[l.size()];
0255:                            l.toArray(_defaultValues);
0256:                        }
0257:                        break;
0258:                    default:
0259:                        throw new IllegalArgumentException(
0260:                                "CLIPParser.Option - Invalid type");
0261:                    }
0262:                }
0263:
0264:                public Option(String longName, String shortName, int type,
0265:                        String defaultValues, String helpMessage)
0266:                        throws IllegalArgumentException {
0267:                    this (longName, shortName, type, defaultValues, null,
0268:                            helpMessage);
0269:                }
0270:            }
0271:
0272:            /**
0273:             * The SubCommand class defines a CLIP sub command.
0274:             * <P>
0275:             * A sub command has a set of options, a mininum and maximum number of operands
0276:             * and help messages.
0277:             * <P>
0278:             *
0279:             * @author <A HREF="mailto:alejandro.abdelnur@sun.com">Alejandro Abdelnur</A>
0280:             *
0281:             */
0282:            public static class SubCommand {
0283:                private String _subCommandName;
0284:                private List _orderedOptions;
0285:                private Map _validOptions;
0286:                private Map _defaultOptionValues;
0287:                private int _minOperands;
0288:                private int _maxOperands;
0289:                private String _subCommandHelp;
0290:                private String _operandsHelp;
0291:
0292:                /**
0293:                 * Creates a CLIPParser Option.
0294:                 * <P>
0295:                 *
0296:                 * @param name name of the sub command or NULL if no sub command are expected for this CLIPParser.
0297:                 *
0298:                 * @param options array with all the valid options for the sub command, or NULL if the sub command expects no options.
0299:                 *
0300:                 * @param minOperands minimum number of operands the sub command expects.
0301:                 *
0302:                 * @param maxOperands maximum number of operands the sub command expects.
0303:                 *
0304:                 * @param subCommandHelp help message for the sub command.
0305:                 *
0306:                 * @param operandsHelp help message for the operands.
0307:                 *
0308:                 * @throws IllegalArgumentException if invalid information is passed.
0309:                 *
0310:                 */
0311:                public SubCommand(String name, Option[] options,
0312:                        int minOperands, int maxOperands,
0313:                        String subCommandHelp, String operandsHelp)
0314:                        throws IllegalArgumentException {
0315:                    if (name != null) {
0316:                        verifyName(name, "CLIPParser - Sub command");
0317:                    }
0318:                    _subCommandName = name;
0319:
0320:                    _validOptions = new HashMap();
0321:                    _orderedOptions = new ArrayList();
0322:
0323:                    if (options != null) {
0324:                        for (int i = 0; i < options.length; i++) {
0325:                            if (options[i] == null) {
0326:                                throw new IllegalArgumentException(
0327:                                        "CLIPParser.SubCommand - Sub command '"
0328:                                                + name
0329:                                                + "', option instances can not be NULL");
0330:                            }
0331:                            if (_validOptions.containsKey(options[i]._longName)) {
0332:                                throw new IllegalArgumentException(
0333:                                        "CLIPParser.SubCommand - Sub command '"
0334:                                                + name
0335:                                                + "', option long names can not be duplicated within a CLIPParser instance");
0336:                            }
0337:                            _validOptions.put(options[i]._longName, options[i]);
0338:                            _orderedOptions.add(options[i]);
0339:                            if (options[i]._shortName != null) {
0340:                                if (_validOptions
0341:                                        .containsKey(options[i]._shortName)) {
0342:                                    throw new IllegalArgumentException(
0343:                                            "CLIPParser.SubCommand - Sub command '"
0344:                                                    + name
0345:                                                    + "', option short names can not be duplicated within a CLIPParser instance");
0346:                                }
0347:                                _validOptions.put(options[i]._shortName,
0348:                                        options[i]);
0349:                            }
0350:                        }
0351:                    }
0352:
0353:                    _defaultOptionValues = new HashMap();
0354:                    if (options != null) {
0355:                        for (int i = 0; i < options.length; i++) {
0356:                            String[] defaultValues = options[i]._defaultValues;
0357:                            if (defaultValues != null) {
0358:                                List l = new ArrayList();
0359:                                for (int j = 0; j < defaultValues.length; j++) {
0360:                                    l.add(defaultValues[j]);
0361:                                }
0362:                                _defaultOptionValues.put(options[i]._longName,
0363:                                        l);
0364:                            }
0365:                        }
0366:                    }
0367:
0368:                    if (minOperands < 0) {
0369:                        throw new IllegalArgumentException(
0370:                                "CLIPParser.SubCommand - Sub command '"
0371:                                        + name
0372:                                        + "', minimum number of operands can not be less than zero");
0373:                    }
0374:                    _minOperands = minOperands;
0375:
0376:                    if (minOperands > maxOperands) {
0377:                        throw new IllegalArgumentException(
0378:                                "CLIPParser.SubCommand - Sub command '"
0379:                                        + name
0380:                                        + "', maximum number of operands can not be less than minimum number of operands");
0381:                    }
0382:                    _maxOperands = maxOperands;
0383:
0384:                    if (subCommandHelp == null) {
0385:                        throw new IllegalArgumentException(
0386:                                "CLIPParser.SubCommand - Sub command '" + name
0387:                                        + "', sub command help can not be NULL");
0388:                    }
0389:                    _subCommandHelp = subCommandHelp;
0390:
0391:                    if (operandsHelp == null) {
0392:                        throw new IllegalArgumentException(
0393:                                "CLIPParser.SubCommand - Sub command '" + name
0394:                                        + "', operands help can not be NULL");
0395:                    }
0396:                    _operandsHelp = operandsHelp;
0397:                }
0398:            }
0399:
0400:            private String _commandName;
0401:            private String _commandHelpMessage;
0402:            private Map _subCommands;
0403:            private List _orderedSubCommands;
0404:
0405:            /**
0406:             * Verifies a name (sub command or long option name ) is well formed.
0407:             *
0408:             */
0409:            private static void verifyName(String name,
0410:                    String exceptionMsgPrefix) {
0411:                if (name == null || name.length() < 2) {
0412:                    throw new IllegalArgumentException(exceptionMsgPrefix
0413:                            + " has to be at least 2 chars long");
0414:                }
0415:                if (name.equals("--")) {
0416:                    throw new IllegalArgumentException(exceptionMsgPrefix
0417:                            + " can not be '--'");
0418:                }
0419:                if (name.startsWith("-") || name.endsWith("-")) {
0420:                    throw new IllegalArgumentException(exceptionMsgPrefix
0421:                            + " can not start or end with '-'");
0422:                }
0423:                if (!name.equals(name.toLowerCase())) {
0424:                    throw new IllegalArgumentException(exceptionMsgPrefix
0425:                            + " has to be in lower case");
0426:                }
0427:            }
0428:
0429:            /**
0430:             * Creates a CLIP parser instance.
0431:             * <P>
0432:             *
0433:             */
0434:            private CLIPParser() {
0435:                _subCommands = new HashMap();
0436:                _orderedSubCommands = new ArrayList();
0437:            }
0438:
0439:            /**
0440:             * Creates a CLIP parser instance with a set of sub commands.
0441:             * <P>
0442:             *
0443:             * @param commandName name of the command
0444:             *
0445:             * @param subCommand array of sub commands for the CLIPParser.
0446:             *
0447:             * @param help message for the command.
0448:             *
0449:             * @throws IllegalArgumentException if invalid information is passed.
0450:             *
0451:             */
0452:            public CLIPParser(String commandName, SubCommand[] subCommands,
0453:                    String commandHelpMessage) throws IllegalArgumentException {
0454:                this ();
0455:                _commandName = commandName;
0456:                _commandHelpMessage = commandHelpMessage;
0457:                if (subCommands == null || subCommands.length == 0) {
0458:                    throw new IllegalArgumentException(
0459:                            "CLIPParser - sub command array can not be null or empty");
0460:                }
0461:                for (int i = 0; i < subCommands.length; i++) {
0462:                    if (subCommands[i]._subCommandName == null) {
0463:                        throw new IllegalArgumentException(
0464:                                "CLIPParser - Sub command can not be null");
0465:                    }
0466:                    addSubCommand(subCommands[i]);
0467:                }
0468:            }
0469:
0470:            /**
0471:             * Creates a CLIP parser instance with no sub commands.
0472:             * <P>
0473:             *
0474:             * @param options array with all the valid options for the sub command, or NULL if the sub command expects no options.
0475:             *
0476:             * @param minOperands minimum number of operands the sub command expects.
0477:             *
0478:             * @param maxOperands maximum number of operands the sub command expects.
0479:             *
0480:             * @param commandName name of the command
0481:             *
0482:             * @param commandHelp help message for the command.
0483:             *
0484:             * @param operandsHelp help message for the operands.
0485:             *
0486:             * @throws IllegalArgumentException if invalid information is passed.
0487:             *
0488:             */
0489:            public CLIPParser(String commandName, Option[] options,
0490:                    int minOperands, int maxOperands,
0491:                    String commandHelpMessage, String operandsHelp)
0492:                    throws IllegalArgumentException {
0493:                this ();
0494:                _commandName = commandName;
0495:                _commandHelpMessage = commandHelpMessage;
0496:                SubCommand subCommand = new SubCommand(null, options,
0497:                        minOperands, maxOperands, _commandHelpMessage,
0498:                        operandsHelp);
0499:                addSubCommand(subCommand);
0500:            }
0501:
0502:            /**
0503:             * Adds a sub command and its options to the parser.
0504:             *
0505:             * <P>
0506:             *
0507:             * @param name name of the sub command or NULL if no sub command are expected for this CLIPParser.
0508:             *
0509:             * @param options array with all the valid options for the sub command, or NULL if the sub command expects no options.
0510:             *
0511:             * @param minOperands minimum number of operands the sub command expects.
0512:             *
0513:             * @param maxOperands maximum number of operands the sub command expects.
0514:             *
0515:             * @param subCommandHelp help message for the sub command.
0516:             *
0517:             * @param operandsHelp help message for the operands.
0518:             *
0519:             * @throws IllegalArgumentException if invalid information is passed.
0520:             *
0521:             */
0522:            private void addSubCommand(SubCommand subCommand)
0523:                    throws IllegalArgumentException {
0524:                if (subCommand._subCommandName != null) {
0525:                    verifyName(subCommand._subCommandName,
0526:                            "CLIPParser - Sub command");
0527:                }
0528:                if (_subCommands.containsKey(subCommand._subCommandName)) {
0529:                    throw new IllegalArgumentException(
0530:                            "CLIPParser - Sub command '"
0531:                                    + subCommand._subCommandName
0532:                                    + "', sub command already defined");
0533:                }
0534:
0535:                _subCommands.put(subCommand._subCommandName, subCommand);
0536:                _orderedSubCommands.add(subCommand);
0537:            }
0538:
0539:            /**
0540:             * Verifies the argument array is valid for the CLIP parser definition.
0541:             * <P>
0542:             *
0543:             * @param args argument array to verify.
0544:             *
0545:             * @throws CLIPException thrown if the argument array could not be processed successfuly.
0546:             *
0547:             */
0548:            public void verifyArguments(String[] args) throws CLIPException {
0549:                boolean skip = args.length == 1
0550:                        && (args[0].equals("--help") || (args[0].equals("-?")));
0551:                if (!skip) {
0552:                    getSubCommand(args);
0553:                    skip = args.length == 2
0554:                            && (args[1].equals("--help") || (args[0]
0555:                                    .equals("-?")));
0556:                    if (!skip) {
0557:                        getOptions(args);
0558:                        getOperands(args);
0559:                    }
0560:                }
0561:            }
0562:
0563:            /**
0564:             * Returns the sub command from the argument array.
0565:             * <P>
0566:             *
0567:             * @param args argument array to parse for sub command.
0568:             *
0569:             * @return the entered sub command or NULL if no sub command was found.
0570:             *
0571:             * @throws CLIPException thrown if the sub command is invalid.
0572:             *
0573:             */
0574:            public String getSubCommand(String[] args) throws CLIPException {
0575:                boolean hasSubCommands = !_subCommands.containsKey(null);
0576:                String firstArgument = (args.length > 0 && hasSubCommands) ? args[0]
0577:                        : null;
0578:                SubCommand subCommand = (SubCommand) _subCommands
0579:                        .get(firstArgument);
0580:                if (subCommand == null) {
0581:                    throw new CLIPException("Invalid sub command: "
0582:                            + firstArgument, 0);
0583:                }
0584:                return firstArgument;
0585:            }
0586:
0587:            /**
0588:             * Returns a Map with all the (key,value) for all the options.
0589:             * <P>
0590:             * The key is the option long name.
0591:             * <P>
0592:             * The value is always a String array, it's length is always one except if it's a collection option, then the
0593:             * length is the number of collection values in the option.
0594:             * <P>
0595:             * If the option is a boolean option (not option value or it a negated option "--no-<OPTION>") the value will be
0596:             * <B>true</B> or <B>false</B>.
0597:             * <P>
0598:             *
0599:             * @param args argument array to parse for options.
0600:             *
0601:             * @return a Map instance with all the options of the argument array.
0602:             *
0603:             * @throws CLIPException thrown if there are invalid or incorrect options in the argument array or if mandatory options
0604:             *         are missing from the argument array.
0605:             *
0606:             */
0607:            public Map getOptions(String[] args) throws CLIPException {
0608:                SubCommand subCommand = (SubCommand) _subCommands
0609:                        .get(getSubCommand(args));
0610:
0611:                Map map = new HashMap();
0612:                Iterator i = subCommand._defaultOptionValues.keySet()
0613:                        .iterator();
0614:                while (i.hasNext()) {
0615:                    String optionName = (String) i.next();
0616:                    List optionValues = (List) subCommand._defaultOptionValues
0617:                            .get(optionName);
0618:                    map.put(optionName, ((ArrayList) optionValues).clone());
0619:                }
0620:
0621:                int argumentIndex = processOptions(args, map);
0622:                i = subCommand._validOptions.keySet().iterator();
0623:                while (i.hasNext()) {
0624:                    String optionName = (String) i.next();
0625:                    Option option = (Option) subCommand._validOptions
0626:                            .get(optionName);
0627:                    if (option._defaultValues == null
0628:                            && !map.containsKey(option._longName)) {
0629:                        throw new CLIPException("Missing mandatory option: "
0630:                                + option._longName, argumentIndex);
0631:                    }
0632:                }
0633:                return massageOptions(map);
0634:            }
0635:
0636:            /**
0637:             * Returns a String array with all the operands of the argument array.
0638:             * <P>
0639:             * All the operands after the options end or after the operand demarcator "--".
0640:             * <P>
0641:             *
0642:             * @param args argument array to parse for operands.
0643:             *
0644:             * @return all the operands from the argument array, if the argument array has no operands it returns an empty array.
0645:             *
0646:             * @throws CLIPException thrown if the operands can not be process because errors in the options or if the number
0647:             *         of operands in the argument array is outside of the minimum and maximum operand boundaries.
0648:             *
0649:             */
0650:            public String[] getOperands(String[] args) throws CLIPException {
0651:                SubCommand subCommand = (SubCommand) _subCommands
0652:                        .get(getSubCommand(args));
0653:
0654:                int i = processOptions(args, new HashMap());
0655:
0656:                int numberOfOperands = args.length - i;
0657:                if (subCommand._minOperands > numberOfOperands
0658:                        || numberOfOperands > subCommand._maxOperands) {
0659:                    throw new CLIPException("Invalid number of operands", i);
0660:                }
0661:
0662:                for (int j = i; j < args.length; j++) {
0663:                    if (args[j].equals("--")) {
0664:                        throw new CLIPException("'--' can not be an operand", j);
0665:                    }
0666:                }
0667:
0668:                String[] operands = new String[numberOfOperands];
0669:                if (args.length > 0) {
0670:                    System.arraycopy(args, i, operands, 0, numberOfOperands);
0671:                }
0672:                return operands;
0673:            }
0674:
0675:            /**
0676:             * Process options and returns index where operands start.
0677:             * <P>
0678:             * Used by getOptions and getOperands.
0679:             *
0680:             */
0681:            private int processOptions(String[] args, Map map)
0682:                    throws CLIPException {
0683:                SubCommand subCommand = (SubCommand) _subCommands
0684:                        .get(getSubCommand(args));
0685:
0686:                boolean allOptionsProcessed = false;
0687:                int i = (subCommand._subCommandName != null) ? 1 : 0;
0688:                while (!allOptionsProcessed && i < args.length) {
0689:
0690:                    if (args[i].startsWith(ADD_TO_COLLECTION_OPTION)) {
0691:                        String optionName = args[i]
0692:                                .substring(ADD_TO_COLLECTION_OPTION.length());
0693:                        Option option = (Option) subCommand._validOptions
0694:                                .get(optionName);
0695:                        if (optionName.length() < 2 || option == null) {
0696:                            throw new CLIPException("Invalid option: "
0697:                                    + optionName, i);
0698:                        }
0699:                        if (option._type != COLLECTION) {
0700:                            throw new CLIPException("Not a collection option: "
0701:                                    + optionName, i);
0702:                        }
0703:                        List values = getOptionValues(subCommand, map,
0704:                                optionName);
0705:                        if ((i + 1) == args.length) {
0706:                            throw new CLIPException(
0707:                                    "Missing collection values to add to option: "
0708:                                            + optionName, i);
0709:                        } else {
0710:                            i++;
0711:                            String optionValue = args[i];
0712:                            StringTokenizer tokens = new StringTokenizer(
0713:                                    optionValue,
0714:                                    (optionValue.indexOf(" ") > -1) ? " " : ",");
0715:                            while (tokens.hasMoreTokens()) {
0716:                                String token = tokens.nextToken();
0717:                                values.add(token);
0718:                            }
0719:                        }
0720:                    } else if (args[i]
0721:                            .startsWith(REMOVE_FROM_COLLECTION_OPTION)) {
0722:                        String optionName = args[i]
0723:                                .substring(REMOVE_FROM_COLLECTION_OPTION
0724:                                        .length());
0725:                        Option option = (Option) subCommand._validOptions
0726:                                .get(optionName);
0727:                        if (optionName.length() < 2 || option == null) {
0728:                            throw new CLIPException("Invalid option: "
0729:                                    + optionName, i);
0730:                        }
0731:                        if (option._type != COLLECTION) {
0732:                            throw new CLIPException("Not a collection option: "
0733:                                    + optionName, i);
0734:                        }
0735:                        if ((i + 1) == args.length) {
0736:                            throw new CLIPException(
0737:                                    "Missing collection values to delete from option: "
0738:                                            + optionName, i);
0739:                        } else {
0740:                            i++;
0741:                            List values = getOptionValues(subCommand, map,
0742:                                    optionName);
0743:                            String optionValue = args[i];
0744:                            StringTokenizer tokens = new StringTokenizer(
0745:                                    optionValue,
0746:                                    (optionValue.indexOf(" ") > -1) ? " " : ",");
0747:                            while (tokens.hasMoreTokens()) {
0748:                                String token = tokens.nextToken();
0749:                                if (values.contains(token)) {
0750:                                    values.remove(token);
0751:                                } else { // if the option value is name/value pair, removes if name is specified
0752:                                    for (int j = 0; j < values.size(); j++) {
0753:                                        String v = (String) values.get(j);
0754:                                        if (v.startsWith(token + "=")) {
0755:                                            values.remove(j);
0756:                                        }
0757:                                    }
0758:                                }
0759:                            }
0760:                        }
0761:                    } else if (args[i].equals(NO_MORE_OPTIONS)) { // only operands follow, stop processing options
0762:                        i++;
0763:                        allOptionsProcessed = true;
0764:                    } else if (args[i].startsWith(NEGATE_OPTION)) {
0765:                        String optionName = args[i].substring(NEGATE_OPTION
0766:                                .length());
0767:                        Option option = (Option) subCommand._validOptions
0768:                                .get(optionName);
0769:                        if (option == null) {
0770:                            throw new CLIPException("Invalid option: "
0771:                                    + optionName, i);
0772:                        }
0773:                        if (option._type != BOOLEAN) {
0774:                            throw new CLIPException("Not a boolean option: "
0775:                                    + optionName, i);
0776:                        }
0777:                        String optionValue = "false";
0778:                        List values = getOptionValues(subCommand, map,
0779:                                optionName);
0780:                        values.clear();
0781:                        values.add(optionValue);
0782:                    } else if (args[i].startsWith(LONG_OPTION)) {
0783:                        String optionName = args[i].substring(LONG_OPTION
0784:                                .length());
0785:                        Option option = (Option) subCommand._validOptions
0786:                                .get(optionName);
0787:                        if (option == null) {
0788:                            throw new CLIPException("Invalid option: "
0789:                                    + optionName, i);
0790:                        }
0791:
0792:                        if (option._type == BOOLEAN) {
0793:                            String optionValue = "true";
0794:                            List values = getOptionValues(subCommand, map,
0795:                                    optionName);
0796:                            values.clear();
0797:                            values.add(optionValue);
0798:                        } else if (option._type == REGULAR) {
0799:                            if ((i + 1) == args.length) {
0800:                                throw new CLIPException(
0801:                                        "Missing value for regular option: "
0802:                                                + optionName, i);
0803:                            } else {
0804:                                i++;
0805:                                String optionValue = args[i];
0806:                                List values = getOptionValues(subCommand, map,
0807:                                        optionName);
0808:                                values.clear();
0809:                                values.add(optionValue);
0810:                            }
0811:                        } else if (option._type == COLLECTION) {
0812:                            if ((i + 1) == args.length) {
0813:                                throw new CLIPException(
0814:                                        "Missing value for collection option: "
0815:                                                + optionName, i);
0816:                            } else {
0817:                                i++;
0818:                                String optionValue = args[i];
0819:                                List values = getOptionValues(subCommand, map,
0820:                                        optionName);
0821:                                values.clear();
0822:                                StringTokenizer tokens = new StringTokenizer(
0823:                                        optionValue,
0824:                                        (optionValue.indexOf(" ") > -1) ? " "
0825:                                                : ",");
0826:                                while (tokens.hasMoreTokens()) {
0827:                                    String token = tokens.nextToken();
0828:                                    values.add(token);
0829:                                }
0830:                            }
0831:                        } else {
0832:                            throw new CLIPException(
0833:                                    "CLIPParser - Internal error", i);
0834:                        }
0835:                    } else if (args[i].startsWith(SHORT_OPTION)) {
0836:                        String optionName = args[i].substring(SHORT_OPTION
0837:                                .length());
0838:
0839:                        // process a set of short options within a single -, all but the last have to be of boolean type
0840:                        for (int j = 0; j < optionName.length() - 1; j++) {
0841:                            String shortOptionName = "" + optionName.charAt(j);
0842:                            Option option = (Option) subCommand._validOptions
0843:                                    .get(shortOptionName);
0844:                            if (option == null) {
0845:                                throw new CLIPException("Invalid option: "
0846:                                        + shortOptionName, i);
0847:                            }
0848:                            if (option._type == BOOLEAN) {
0849:                                String optionValue = "true";
0850:                                List values = getOptionValues(subCommand, map,
0851:                                        shortOptionName);
0852:                                values.clear();
0853:                                values.add(optionValue);
0854:                            } else {
0855:                                throw new CLIPException(
0856:                                        "Not an boolean option: "
0857:                                                + shortOptionName, i);
0858:                            }
0859:                        }
0860:
0861:                        optionName = ""
0862:                                + optionName.charAt(optionName.length() - 1);
0863:                        Option option = (Option) subCommand._validOptions
0864:                                .get(optionName);
0865:                        if (option == null) {
0866:                            throw new CLIPException("Invalid option: "
0867:                                    + optionName, i);
0868:                        }
0869:
0870:                        if (option._type == BOOLEAN) {
0871:                            String optionValue = "true";
0872:                            List values = getOptionValues(subCommand, map,
0873:                                    optionName);
0874:                            values.clear();
0875:                            values.add(optionValue);
0876:                        } else if (option._type == REGULAR) {
0877:                            if ((i + 1) == args.length) {
0878:                                throw new CLIPException(
0879:                                        "Missing value for regular option: "
0880:                                                + optionName, i);
0881:                            } else {
0882:                                i++;
0883:                                String optionValue = args[i];
0884:                                List values = getOptionValues(subCommand, map,
0885:                                        optionName);
0886:                                values.clear();
0887:                                values.add(optionValue);
0888:                            }
0889:                        } else {
0890:                            throw new CLIPException(
0891:                                    "CLIPParser - Internal error", i);
0892:                        }
0893:                    } else {
0894:                        allOptionsProcessed = true;
0895:                    }
0896:
0897:                    i++;
0898:                }
0899:
0900:                if (allOptionsProcessed) {
0901:                    i--;
0902:                }
0903:
0904:                return i;
0905:            }
0906:
0907:            /**
0908:             * Maps from short to long options and creates option value list.
0909:             *
0910:             */
0911:            private List getOptionValues(SubCommand subCommand, Map map,
0912:                    String optionName) {
0913:                Option option = (Option) subCommand._validOptions
0914:                        .get(optionName);
0915:                String longName = option._longName;
0916:                List list = (List) map.get(longName);
0917:                if (list == null) {
0918:                    list = new ArrayList();
0919:                    map.put(longName, list);
0920:                }
0921:                return list;
0922:            }
0923:
0924:            /**
0925:             * Converts Map entries from List to String[].
0926:             *
0927:             */
0928:            private Map massageOptions(Map map) {
0929:                Iterator i = map.keySet().iterator();
0930:                while (i.hasNext()) {
0931:                    String option = (String) i.next();
0932:                    List values = (List) map.get(option);
0933:                    String[] arrayValues = new String[values.size()];
0934:                    values.toArray(arrayValues);
0935:                    map.put(option, arrayValues);
0936:                }
0937:                return map;
0938:            }
0939:
0940:            /**
0941:             * Returns the name part of a name/value pair element.
0942:             * <P>
0943:             * It uses '=' as the name/value separator.
0944:             * <P>
0945:             *
0946:             * @param element the option or operand name/value pair element.
0947:             *
0948:             * @return the name portion of the name/value pair or the complete
0949:             *         element if there is no value.
0950:             *
0951:             */
0952:            public static String getName(String element) {
0953:                String name = element;
0954:                int index = element.indexOf("=");
0955:                if (index > -1) {
0956:                    name = element.substring(0, index);
0957:                }
0958:                return name;
0959:            }
0960:
0961:            /**
0962:             * Returns the value part of a name/value pair element.
0963:             * <P>
0964:             * It uses '=' as the name/value separator.
0965:             * <P>
0966:             *
0967:             * @param element the option or operand name/value pair element.
0968:             *
0969:             * @return the value portion of the name/value pair or <B>null</B>
0970:             *         if there is not value in the element.
0971:             *
0972:             */
0973:            public static String getValue(String element) {
0974:                String value = null;
0975:                int index = element.indexOf("=");
0976:                if (index > -1) {
0977:                    value = element.substring(index + 1);
0978:                }
0979:                return value;
0980:            }
0981:
0982:            /**
0983:             * String representation of the processed command arguments.
0984:             * <P>
0985:             *
0986:             * @param args argument array
0987:             *
0988:             * @return String representation.
0989:             *
0990:             * @throws CLIPException thrown if the argument array could not be processed successfuly.
0991:             *
0992:             */
0993:            public String toString(String[] args) throws CLIPException {
0994:                StringBuffer sb = new StringBuffer(1024);
0995:                String subCmd = getSubCommand(args);
0996:                Map options = getOptions(args);
0997:                String[] operands = getOperands(args);
0998:
0999:                sb.append("\n").append("Sub-command: ").append(subCmd).append(
1000:                        "\n").append("\n").append("Options: ").append("\n");
1001:                Iterator i = options.keySet().iterator();
1002:                while (i.hasNext()) {
1003:                    String option = (String) i.next();
1004:                    String[] values = (String[]) options.get(option);
1005:                    sb.append(("  " + option + "              ").substring(0,
1006:                            12)
1007:                            + ": ");
1008:                    for (int j = 0; j < values.length; j++) {
1009:                        sb.append(values[j]).append(" ");
1010:                    }
1011:                    sb.append("\n");
1012:                }
1013:                sb.append("\n").append("Operands: ").append("\n");
1014:                for (int j = 0; j < operands.length; j++) {
1015:                    sb.append("  ").append(operands[j]).append("\n");
1016:                }
1017:                sb.append("\n");
1018:                return sb.toString();
1019:            }
1020:
1021:            /**
1022:             * Returns if the command invocation needs help or not.
1023:             * <P>
1024:             * It may be an exlicit request for help, using the --help (-?) option,
1025:             * or because an invalid argument set has been given.
1026:             * <P>
1027:             *
1028:             * @param args the array argument.
1029:             *
1030:             * @return <B>true</B> if help is needed, <B>false</B> otherwise.
1031:             *
1032:             */
1033:            public boolean needsHelp(String[] args) {
1034:                boolean help = false;
1035:                try {
1036:                    verifyArguments(args);
1037:                    Map options = getOptions(args);
1038:                    help = options.containsKey("help")
1039:                            && ((String[]) options.get("help"))[0]
1040:                                    .equals("true");
1041:                } catch (CLIPException ex) {
1042:                    help = true;
1043:                }
1044:                return help;
1045:            }
1046:
1047:            /**
1048:             * Returns the Help for the command.
1049:             * <P>
1050:             * Using the current arguments determines if a full help or a sub command help
1051:             * should be returned.
1052:             * <P>
1053:             *
1054:             * @param args the current argument array, to determine the type of help to return.
1055:             *
1056:             * @return the help for the command.
1057:             *
1058:             */
1059:            public String getHelp(String[] args) {
1060:                boolean fullHelp = false;
1061:                String firstArgument = (args.length > 0) ? args[0] : null;
1062:                fullHelp = !_subCommands.containsKey(firstArgument);
1063:                SubCommand subCommand;
1064:
1065:                if (!fullHelp) {
1066:                    subCommand = (SubCommand) _subCommands.get(firstArgument);
1067:                } else {
1068:                    subCommand = (SubCommand) _subCommands.get(null);
1069:                    fullHelp = subCommand == null
1070:                            || subCommand._subCommandName != null;
1071:                }
1072:
1073:                StringBuffer sb = new StringBuffer(2048);
1074:
1075:                if (fullHelp) {
1076:                    sb.append("Usage: " + _commandName
1077:                            + " SUBCOMMAND ARGUMENTS\n\n");
1078:                    sb.append(_commandHelpMessage).append("\n\n");
1079:                    sb.append("The accepted values for SUBCOMMAND are:\n\n");
1080:                    int size = _orderedSubCommands.size();
1081:                    for (int i = 0; i < size; i++) {
1082:                        subCommand = (SubCommand) _orderedSubCommands.get(i);
1083:                        String name = subCommand._subCommandName;
1084:                        if (name == null) {
1085:                            name = "<NO SUB COMMAND>  ";
1086:                        } else {
1087:                            name = name + "\t";
1088:                        }
1089:                        sb.append(name).append(subCommand._subCommandHelp)
1090:                                .append(".\n");
1091:                    }
1092:                } else {
1093:                    sb.append("Usage: " + _commandName + " "
1094:                            + subCommand._subCommandName + " [OPTIONS...]\n\n");
1095:                    sb.append(subCommand._subCommandHelp).append(".\n\n");
1096:                    doOptionsHelp(sb, "", subCommand._orderedOptions);
1097:                    if (subCommand._maxOperands > 0) {
1098:                        if (subCommand._maxOperands == 1) {
1099:                            sb.append("\nOPERAND\n");
1100:                        } else {
1101:                            sb.append("\nOPERANDS\n");
1102:                        }
1103:                        sb.append("  ").append(subCommand._operandsHelp)
1104:                                .append("\n");
1105:                    }
1106:                }
1107:                return sb.toString();
1108:            }
1109:
1110:            /**
1111:             * Returns if the command invocation needs version or not.
1112:             * <P>
1113:             * When version is detected anywhere in the options, no further parsing
1114:             * is performed.  A version option is considered to be one of the
1115:             * followings: <code>"-V"</code>, <code>"--version"</code> or
1116:             * <code>"--version=true"</code>.
1117:             * <P>
1118:             *
1119:             * @param args the array argument.
1120:             *
1121:             * @return <B>true</B> if version is needed, <B>false</B> otherwise.
1122:             *
1123:             */
1124:            public boolean needsVersion(String[] args) {
1125:                for (int i = 0; i < args.length; i++) {
1126:                    if (args[i].equals("-V") || args[i].equals("--version")) {
1127:                        return true;
1128:                    }
1129:                }
1130:                return false;
1131:            }
1132:
1133:            /**
1134:             * Renders the help for a seto of options, used by getHelp.
1135:             *
1136:             */
1137:            private void doOptionsHelp(StringBuffer sb, String padding,
1138:                    List options) {
1139:                int size = options.size();
1140:                for (int i = 0; i < size; i++) {
1141:                    Option option = (Option) options.get(i);
1142:                    sb.append(padding);
1143:                    if (option._shortName != null) {
1144:                        sb.append('-').append(option._shortName);
1145:                        if (option._argName != null) {
1146:                            sb.append(" ").append(option._argName);
1147:                        }
1148:                        sb.append(", ");
1149:                    }
1150:                    sb.append("--").append(option._longName);
1151:                    if (option._argName != null) {
1152:                        sb.append("=").append(option._argName).append("\n\t");
1153:                    }
1154:                    sb.append("\t").append(option._helpMessage).append(" (");
1155:                    if (option._defaultValues == null) {
1156:                        sb.append("none");
1157:                    } else {
1158:                        for (int j = 0; j < option._defaultValues.length; j++) {
1159:                            if (j > 0) {
1160:                                sb.append(' ');
1161:                            }
1162:                            sb.append(option._defaultValues[j]);
1163:                        }
1164:                    }
1165:                    sb.append(")\n\n");
1166:                }
1167:            }
1168:
1169:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.