Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AbstractOptionSpecification |
|
| 3.8;3.8 |
1 | package com.lexicalscope.jewel.cli; | |
2 | ||
3 | import static java.util.Arrays.asList; | |
4 | ||
5 | import java.util.List; | |
6 | ||
7 | import com.lexicalscope.fluentreflection.FluentMethod; | |
8 | import com.lexicalscope.jewel.cli.specification.OptionSpecification; | |
9 | import com.lexicalscope.jewel.cli.specification.SpecificationMultiplicity; | |
10 | ||
11 | /* | |
12 | * Copyright 2012 Tim Wood | |
13 | * | |
14 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
15 | * you may not use this file except in compliance with the License. | |
16 | * You may obtain a copy of the License at | |
17 | * | |
18 | * http://www.apache.org/licenses/LICENSE-2.0 | |
19 | * | |
20 | * Unless required by applicable law or agreed to in writing, software | |
21 | * distributed under the License is distributed on an "AS IS" BASIS, | |
22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
23 | * See the License for the specific language governing permissions and | |
24 | * limitations under the License. | |
25 | */ | |
26 | ||
27 | 566 | abstract class AbstractOptionSpecification implements OptionSpecification, Comparable<OptionSpecification> { |
28 | protected final OptionAdapter annotation; | |
29 | private final List<String> defaultValue; | |
30 | ||
31 | 574 | public AbstractOptionSpecification(final OptionAdapter annotation) { |
32 | 574 | this.annotation = annotation; |
33 | ||
34 | 574 | if (annotation.defaultToNull() && annotation.hasDefaultValue()) |
35 | { | |
36 | 2 | throw new InvalidOptionSpecificationException("option cannot have null default and non-null default value: " |
37 | + annotation.method()); | |
38 | } | |
39 | 572 | else if (annotation.defaultToNull()) |
40 | { | |
41 | 26 | if (annotation.isMultiValued()) |
42 | { | |
43 | 16 | defaultValue = null; |
44 | } | |
45 | else | |
46 | { | |
47 | 10 | defaultValue = asList((String) null); |
48 | } | |
49 | } | |
50 | 546 | else if (annotation.hasDefaultValue()) |
51 | { | |
52 | 34 | defaultValue = asList(annotation.defaultValue()); |
53 | } | |
54 | else | |
55 | { | |
56 | 512 | defaultValue = null; |
57 | } | |
58 | ||
59 | 572 | if(hasExactCount() && exactly() < minimum() || exactly() > maximum()) |
60 | { | |
61 | 0 | throw new InvalidOptionSpecificationException("option has maximum and minimum and exact count which can never be satisfied: " |
62 | + annotation.method()); | |
63 | } | |
64 | 572 | else if(minimum() > maximum()) |
65 | { | |
66 | 0 | throw new InvalidOptionSpecificationException("minimum cannot be greater than maximum: " |
67 | + annotation.method()); | |
68 | } | |
69 | 572 | else if(maximum() < 0) |
70 | { | |
71 | 0 | throw new InvalidOptionSpecificationException("maximum must not be less than zero: " |
72 | + annotation.method()); | |
73 | } | |
74 | 572 | } |
75 | ||
76 | @Override public final List<String> getDefaultValue() { | |
77 | 1392 | return defaultValue; |
78 | } | |
79 | ||
80 | @Override public final boolean hasDefaultValue() { | |
81 | 1324 | return getDefaultValue() != null || annotation.defaultToNull(); |
82 | } | |
83 | ||
84 | @Override public final String getDescription() { | |
85 | 246 | return annotation.description(); |
86 | } | |
87 | ||
88 | @Override public final Class<?> getType() { | |
89 | 2890 | return annotation.getValueType().classUnderReflection(); |
90 | } | |
91 | ||
92 | @Override public final boolean isMultiValued() { | |
93 | 1110 | return annotation.isMultiValued(); |
94 | } | |
95 | ||
96 | @Override public final boolean isOptional() { | |
97 | 1348 | return getOptionalityMethod() != null || isBoolean() || hasDefaultValue(); |
98 | } | |
99 | ||
100 | public abstract boolean isBoolean(); | |
101 | ||
102 | @Override public final String getCanonicalIdentifier() { | |
103 | 1366 | return getMethod().property(); |
104 | } | |
105 | ||
106 | @Override public final FluentMethod getMethod() { | |
107 | 2164 | return annotation.method(); |
108 | } | |
109 | ||
110 | @Override public final FluentMethod getOptionalityMethod() { | |
111 | 1596 | return annotation.correspondingOptionalityMethod(); |
112 | } | |
113 | ||
114 | @Override public final int compareTo(final OptionSpecification other) { | |
115 | 566 | return getCanonicalIdentifier().compareTo(other.getCanonicalIdentifier()); |
116 | } | |
117 | ||
118 | @Override public final boolean isHidden() { | |
119 | 98 | return annotation.isHidden(); |
120 | } | |
121 | ||
122 | @Override public boolean allowedThisManyValues(final int count) { | |
123 | 266 | if(count == 0 && !hasValue()) |
124 | { | |
125 | 36 | return true; |
126 | } | |
127 | 230 | else if(count == 1 && hasValue() && !isMultiValued()) |
128 | { | |
129 | 132 | return true; |
130 | } | |
131 | 98 | else if(isMultiValued() && hasExactCount()) |
132 | { | |
133 | 4 | return count == exactly(); |
134 | } | |
135 | 94 | else if(isMultiValued()) |
136 | { | |
137 | 72 | return minimum() <= count && count <= maximum(); |
138 | } | |
139 | 22 | return false; |
140 | } | |
141 | ||
142 | @Override | |
143 | public final int maximum() { | |
144 | 1810 | return annotation.maximum(); |
145 | } | |
146 | ||
147 | @Override | |
148 | public final int minimum() { | |
149 | 672 | return annotation.minimum(); |
150 | } | |
151 | ||
152 | @Override | |
153 | public final int exactly() { | |
154 | 604 | return annotation.exactly(); |
155 | } | |
156 | ||
157 | @Override | |
158 | public final boolean hasExactCount() { | |
159 | 682 | return annotation.exactly() >= 0; |
160 | } | |
161 | ||
162 | @Override public <T> T compareCountToSpecification( | |
163 | final int valueCount, | |
164 | final SpecificationMultiplicity<T> specificationMultiplicity) { | |
165 | 68 | if(!hasValue() && valueCount > 0) { |
166 | 12 | return specificationMultiplicity.expectedNoneGotSome(); |
167 | 56 | } else if(!isMultiValued() && hasValue() && valueCount == 0) { |
168 | 12 | return specificationMultiplicity.expectedOneGotNone(); |
169 | 44 | } else if(!isMultiValued() && valueCount > 1) { |
170 | 20 | return specificationMultiplicity.expectedOneGotSome(); |
171 | 24 | } else if(isMultiValued()) { |
172 | 24 | if(hasExactCount() && valueCount != exactly()) { |
173 | 8 | if(valueCount < exactly()) { |
174 | 0 | return specificationMultiplicity.expectedExactGotTooFew(exactly(), valueCount); |
175 | } else { | |
176 | 8 | return specificationMultiplicity.expectedExactGotTooMany(exactly(), valueCount); |
177 | } | |
178 | 16 | } else if(valueCount < minimum()) { |
179 | 8 | return specificationMultiplicity.expectedMinimumGotTooFew(minimum(), valueCount); |
180 | 8 | } else if(valueCount > maximum()) { |
181 | 8 | return specificationMultiplicity.expectedMaximumGotTooMany(maximum(), valueCount); |
182 | } | |
183 | } | |
184 | 0 | return specificationMultiplicity.allowed(); |
185 | } | |
186 | ||
187 | @Override public int maximumArgumentConsumption() { | |
188 | 24 | if(isMultiValued()) { |
189 | 10 | if(hasExactCount()) { |
190 | 0 | return exactly(); |
191 | } else { | |
192 | 10 | return maximum(); |
193 | } | |
194 | 14 | } else if (hasValue()) { |
195 | 8 | return 1; |
196 | } | |
197 | 6 | return 0; |
198 | } | |
199 | } |