001package co.codewizards.cloudstore.client;
002
003import org.kohsuke.args4j.CmdLineException;
004import org.kohsuke.args4j.CmdLineParser;
005import org.kohsuke.args4j.Option;
006import org.kohsuke.args4j.OptionDef;
007import org.kohsuke.args4j.spi.OneArgumentOptionHandler;
008import org.kohsuke.args4j.spi.Setter;
009
010/**
011 * <p>
012 * Option handler implementation to interprete a time period (e.g. "5 minutes".
013 * </p>
014 * <p>
015 * The time period is specified in the command line by writing a number
016 * directly followed (no space!) by a unit. For example 5 minutes could be
017 * written as "5min" or "300s" (300 seconds are 5 minutes).
018 * </p>
019 * <p>
020 * This handler can be chosen for every <code>long</code> property using
021 * the {@link Option} annotation like this:
022 * </p>
023 * <pre>
024 * &#64;Option(name="-myArg", handler=TimePeriodOptionHandler.class)
025 * private long myArg;
026 * </pre>
027 * <p>
028 * The <code>long</code> property will be set to the milliseconds value.
029 * For example, if the command line user passes "5min", the <code>long</code> value
030 * will be 300000 (5 min * 60 s * 1000 ms).
031 * </p>
032 *
033 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
034 */
035public class TimePeriodOptionHandler extends OneArgumentOptionHandler<Long>
036{
037        /**
038         * Units based on <a target="_blank" href="http://en.wikipedia.org/wiki/ISO_31-1">ISO 31-1</a> (where it exists).
039         *
040         * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
041         */
042        public static enum Unit {
043                /**
044                 * Millisecond.
045                 */
046                ms("Millisecond", 1L),
047
048                /**
049                 * Second.
050                 */
051                s("Second", 1000L),
052
053                /**
054                 * Minute.
055                 */
056                min("Minute", 60L * s.msec),
057
058                /**
059                 * Hour.
060                 */
061                h("Hour", 60L * min.msec),
062
063                /**
064                 * Day.
065                 */
066                d("Day", 24L * h.msec),
067
068                /**
069                 * Year. <a target="_blank" href="http://en.wikipedia.org/wiki/Year">Abbreviation from latin "annus".</a>
070                 */
071                a("Year", 365L * d.msec),
072
073                /**
074                 * Year (alternative for convenience).
075                 */
076                y("Year", 365L * d.msec)
077                ;
078
079                private String displayName;
080                private long msec;
081
082                private Unit(String displayName, long msec)
083                {
084                        this.displayName = displayName;
085                        this.msec = msec;
086                }
087
088                public long toMSec(long value)
089                {
090                        return value * msec;
091                }
092
093                public String getDisplayName() {
094                        return displayName;
095                }
096
097                public static String getAllUnitsWithDisplayName()
098                {
099                        return getAllUnitsWithDisplayName(", ");
100                }
101
102                public static String getAllUnitsWithDisplayName(String separator)
103                {
104                        return getAllUnitsWithDisplayName("%s (%s)", separator);
105                }
106
107                public static String getAllUnitsWithDisplayName(String unitFormat, String separator)
108                {
109                        StringBuilder sb = new StringBuilder();
110
111                        for (Unit u : values()) {
112                                if (sb.length() > 0)
113                                        sb.append(separator);
114
115                                sb.append(String.format(unitFormat, u.name(), u.getDisplayName()));
116                        }
117
118                        return sb.toString();
119                }
120        }
121
122        public TimePeriodOptionHandler(CmdLineParser parser, OptionDef option, Setter<Long> setter)
123        {
124                super(parser, option, setter);
125        }
126
127        @Override
128        protected Long parse(String argument) throws NumberFormatException, CmdLineException
129        {
130                Unit unit = null;
131                for (Unit u : Unit.values()) {
132                        if (argument.endsWith(u.name()) && (unit == null || unit.name().length() < u.name().length()))
133                                unit = u;
134                }
135
136                if (unit == null)
137                        throw new CmdLineException(owner, "Argument '" + argument + "' does not end with one of the following unit-suffixes: " + Unit.getAllUnitsWithDisplayName());
138
139                String numberVal = argument.substring(0, argument.length() - unit.name().length()).trim();
140                long valueMSec = Long.parseLong(numberVal);
141                return unit.toMSec(valueMSec);
142        }
143
144}