View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  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 org.apache.commons.cli2.option;
18  
19  import java.util.ArrayList;
20  import java.util.Comparator;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Set;
24  
25  import org.apache.commons.cli2.Argument;
26  import org.apache.commons.cli2.Option;
27  import org.apache.commons.cli2.OptionException;
28  import org.apache.commons.cli2.WriteableCommandLine;
29  import org.apache.commons.cli2.resource.ResourceConstants;
30  import org.apache.commons.cli2.resource.ResourceHelper;
31  
32  /**
33   * An Argument implementation that allows a variable size Argument to precede a
34   * fixed size argument.  The canonical example of it's use is in the unix
35   * <code>cp</code> command where a number of source can be specified with
36   * exactly one destination specfied at the end.
37   */
38  public class SourceDestArgument
39      extends ArgumentImpl {
40      private final Argument source;
41      private final Argument dest;
42  
43      /**
44       * Creates a SourceDestArgument using defaults where possible.
45       *
46       * @param source the variable size Argument
47       * @param dest the fixed size Argument
48       */
49      public SourceDestArgument(final Argument source,
50                                final Argument dest) {
51          this(source, dest, DEFAULT_INITIAL_SEPARATOR, DEFAULT_SUBSEQUENT_SEPARATOR,
52               DEFAULT_CONSUME_REMAINING, null);
53      }
54  
55      /**
56       * Creates a SourceDestArgument using the specified parameters.
57       *
58       * @param source the variable size Argument
59       * @param dest the fixed size Argument
60       * @param initialSeparator the inistial separator to use
61       * @param subsequentSeparator the subsequent separator to use
62       * @param consumeRemaining the token triggering consume remaining behaviour
63       * @param defaultValues the default values for the SourceDestArgument
64       */
65      public SourceDestArgument(final Argument source,
66                                final Argument dest,
67                                final char initialSeparator,
68                                final char subsequentSeparator,
69                                final String consumeRemaining,
70                                final List defaultValues) {
71          super("SourceDestArgument", null, sum(source.getMinimum(), dest.getMinimum()),
72                sum(source.getMaximum(), dest.getMaximum()), initialSeparator, subsequentSeparator,
73                null, consumeRemaining, defaultValues, 0);
74  
75          this.source = source;
76          this.dest = dest;
77  
78          if (dest.getMinimum() != dest.getMaximum()) {
79              throw new IllegalArgumentException(ResourceHelper.getResourceHelper().getMessage(ResourceConstants.SOURCE_DEST_MUST_ENFORCE_VALUES));
80          }
81      }
82  
83      private static int sum(final int a,
84                             final int b) {
85          return Math.max(a, Math.max(b, a + b));
86      }
87  
88      public void appendUsage(final StringBuffer buffer,
89                              final Set helpSettings,
90                              final Comparator comp) {
91          final int length = buffer.length();
92  
93          source.appendUsage(buffer, helpSettings, comp);
94  
95          if (buffer.length() != length) {
96              buffer.append(' ');
97          }
98  
99          dest.appendUsage(buffer, helpSettings, comp);
100     }
101 
102     public List helpLines(int depth,
103                           Set helpSettings,
104                           Comparator comp) {
105         final List helpLines = new ArrayList();
106         helpLines.addAll(source.helpLines(depth, helpSettings, comp));
107         helpLines.addAll(dest.helpLines(depth, helpSettings, comp));
108 
109         return helpLines;
110     }
111 
112     public void validate(WriteableCommandLine commandLine,
113                          Option option)
114         throws OptionException {
115         final List values = commandLine.getValues(option);
116 
117         final int limit = values.size() - dest.getMinimum();
118         int count = 0;
119 
120         final Iterator i = values.iterator();
121 
122         while (count++ < limit) {
123             commandLine.addValue(source, i.next());
124         }
125 
126         while (i.hasNext()) {
127             commandLine.addValue(dest, i.next());
128         }
129 
130         source.validate(commandLine, source);
131         dest.validate(commandLine, dest);
132     }
133 
134     public boolean canProcess(final WriteableCommandLine commandLine,
135                               final String arg) {
136         return source.canProcess(commandLine, arg) || dest.canProcess(commandLine, arg);
137     }
138 }