Coverage Report - com.lexicalscope.jewel.cli.OptionsSpecificationImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
OptionsSpecificationImpl
93%
71/76
81%
47/58
2.812
 
 1  
 /*
 2  
  * Copyright 2006 Tim Wood
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 7  
  *
 8  
  * Unless required by applicable law or agreed to in writing, software
 9  
  * distributed under the License is distributed on an "AS IS" BASIS,
 10  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 11  
  * See the License for the specific language governing permissions and
 12  
  * limitations under the License.
 13  
  */
 14  
 
 15  
 package com.lexicalscope.jewel.cli;
 16  
 
 17  
 import java.util.ArrayList;
 18  
 import java.util.HashMap;
 19  
 import java.util.Iterator;
 20  
 import java.util.LinkedHashSet;
 21  
 import java.util.List;
 22  
 import java.util.Map;
 23  
 import java.util.Set;
 24  
 import java.util.TreeMap;
 25  
 import java.util.TreeSet;
 26  
 
 27  
 import com.lexicalscope.fluent.FluentDollar;
 28  
 import com.lexicalscope.fluent.list.FluentList;
 29  
 import com.lexicalscope.fluentreflection.FluentClass;
 30  
 import com.lexicalscope.fluentreflection.FluentMethod;
 31  
 import com.lexicalscope.jewel.cli.specification.CliSpecification;
 32  
 import com.lexicalscope.jewel.cli.specification.OptionsSpecification;
 33  
 import com.lexicalscope.jewel.cli.specification.ParsedOptionSpecification;
 34  
 import com.lexicalscope.jewel.cli.specification.UnparsedOptionSpecification;
 35  
 
 36  
 class OptionsSpecificationImpl<O> implements OptionsSpecification<O>, CliSpecification {
 37  
     private final FluentClass<O> klass;
 38  
 
 39  
     private final Set<ParsedOptionSpecification> options;
 40  248
     private final Map<String, ParsedOptionSpecification> optionsByName =
 41  
             new TreeMap<String, ParsedOptionSpecification>();
 42  248
     private final Map<FluentMethod, ParsedOptionSpecification> optionsMethod =
 43  
             new HashMap<FluentMethod, ParsedOptionSpecification>();
 44  248
     private final Map<FluentMethod, ParsedOptionSpecification> optionalOptionsMethod =
 45  
             new HashMap<FluentMethod, ParsedOptionSpecification>();
 46  
 
 47  248
     private final Map<FluentMethod, UnparsedOptionSpecification> unparsedOptionsMethod =
 48  
             new HashMap<FluentMethod, UnparsedOptionSpecification>();
 49  248
     private final Map<FluentMethod, UnparsedOptionSpecification> unparsedOptionalOptionsMethod =
 50  
             new HashMap<FluentMethod, UnparsedOptionSpecification>();
 51  
 
 52  
     OptionsSpecificationImpl(
 53  
             final FluentClass<O> klass,
 54  
             final List<ParsedOptionSpecification> optionSpecifications,
 55  248
             final List<UnparsedOptionSpecification> unparsedSpecifications) {
 56  248
         this.klass = klass;
 57  
 
 58  248
         if(klass.annotatedWith(CommandLineInterface.class) &&
 59  
            klass.annotation(CommandLineInterface.class).order().equals(OptionOrder.DEFINITION))
 60  
         {
 61  4
             options = new LinkedHashSet<ParsedOptionSpecification>();
 62  
         }
 63  
         else
 64  
         {
 65  244
             options = new TreeSet<ParsedOptionSpecification>();
 66  
         }
 67  
 
 68  248
         for (final ParsedOptionSpecification optionSpecification : optionSpecifications) {
 69  430
             addOption(optionSpecification);
 70  430
         }
 71  
 
 72  248
         for (final UnparsedOptionSpecification optionSpecification : unparsedSpecifications) {
 73  60
             addUnparsedOption(optionSpecification);
 74  60
         }
 75  248
     }
 76  
 
 77  
     @Override public boolean isSpecified(final String key) {
 78  240
         return optionsByName.containsKey(key);
 79  
     }
 80  
 
 81  
     @Override public ParsedOptionSpecification getSpecification(final String key) {
 82  262
         return optionsByName.get(key);
 83  
     }
 84  
 
 85  
     @Override public ParsedOptionSpecification getSpecification(final FluentMethod method) {
 86  28
         if (optionsMethod.containsKey(method)) {
 87  28
             return optionsMethod.get(method);
 88  
         }
 89  0
         return optionalOptionsMethod.get(method);
 90  
     }
 91  
 
 92  
     @Override public FluentList<ParsedOptionSpecification> getMandatoryOptions() {
 93  176
         final FluentList<ParsedOptionSpecification> result = FluentDollar.$.list(ParsedOptionSpecification.class);
 94  176
         for (final ParsedOptionSpecification specification : options) {
 95  322
             if (!specification.isOptional() && !specification.hasDefaultValue()) {
 96  112
                 result.add(specification);
 97  
             }
 98  322
         }
 99  
 
 100  176
         return result;
 101  
     }
 102  
 
 103  
     @Override public Iterator<ParsedOptionSpecification> iterator() {
 104  146
         return new ArrayList<ParsedOptionSpecification>(optionsByName.values()).iterator();
 105  
     }
 106  
 
 107  
     @Override public UnparsedOptionSpecification getUnparsedSpecification() {
 108  98
         return unparsedOptionsMethod.values().iterator().next();
 109  
     }
 110  
 
 111  
     @Override public boolean hasUnparsedSpecification() {
 112  548
         return !unparsedOptionsMethod.values().isEmpty();
 113  
     }
 114  
 
 115  
     @Override public String getApplicationName() {
 116  2
         final String applicationName = applicationName();
 117  2
         if (applicationName != null)
 118  
         {
 119  2
             return applicationName;
 120  
         }
 121  0
         return klass.name();
 122  
     }
 123  
 
 124  
     private String applicationName() {
 125  36
         if (klass.annotatedWith(CommandLineInterface.class))
 126  
         {
 127  18
             final String applicationName = klass.annotation(CommandLineInterface.class).application();
 128  18
             if (applicationName != null && !applicationName.trim().equals("")) {
 129  14
                 return applicationName.trim();
 130  
             }
 131  
         }
 132  22
         return null;
 133  
     }
 134  
 
 135  
     private void addOption(final ParsedOptionSpecification optionSpecification) {
 136  430
         for (final String name : optionSpecification.getNames()) {
 137  504
             optionsByName.put(name, optionSpecification);
 138  504
         }
 139  430
         options.add(optionSpecification);
 140  
 
 141  430
         optionsMethod.put(optionSpecification.getMethod(), optionSpecification);
 142  
 
 143  430
         if (optionSpecification.isOptional()) {
 144  232
             optionalOptionsMethod.put(optionSpecification.getOptionalityMethod(), optionSpecification);
 145  
         }
 146  430
     }
 147  
 
 148  
     private void addUnparsedOption(final UnparsedOptionSpecification optionSpecification) {
 149  60
         unparsedOptionsMethod.put(optionSpecification.getMethod(), optionSpecification);
 150  
 
 151  60
         if (optionSpecification.isOptional()) {
 152  16
             unparsedOptionalOptionsMethod.put(optionSpecification.getOptionalityMethod(), optionSpecification);
 153  
         }
 154  60
     }
 155  
 
 156  
     @Override public void describeTo(final HelpMessage helpMessage) {
 157  26
         if (!hasCustomApplicationName() && (!hasUnparsedSpecification() || getUnparsedSpecification().isHidden())) {
 158  22
             helpMessage.noUsageInformation();
 159  
         } else {
 160  4
             if (hasCustomApplicationName()) {
 161  4
                 helpMessage.hasUsageInformation(applicationName());
 162  
             }
 163  
             else
 164  
             {
 165  0
                 helpMessage.hasUsageInformation();
 166  
             }
 167  
 
 168  4
             if (getMandatoryOptions().isEmpty()) {
 169  4
                 helpMessage.hasOnlyOptionalOptions();
 170  
             }
 171  
             else
 172  
             {
 173  0
                 helpMessage.hasSomeMandatoryOptions();
 174  
             }
 175  
 
 176  4
             if (hasUnparsedSpecification() && !getUnparsedSpecification().isHidden()) {
 177  4
                 if (getUnparsedSpecification().isMultiValued()) {
 178  4
                     helpMessage.hasUnparsedMultiValuedOption(getUnparsedSpecification().getValueName());
 179  
                 }
 180  
                 else
 181  
                 {
 182  0
                     helpMessage.hasUnparsedOption(getUnparsedSpecification().getValueName());
 183  
                 }
 184  
             }
 185  
         }
 186  
 
 187  26
         helpMessage.startOfOptions();
 188  
 
 189  26
         for (final ParsedOptionSpecification specification : options) {
 190  92
             if(!specification.isHidden())
 191  
             {
 192  90
                 new ParsedOptionSummary(specification).describeOptionTo(helpMessage.option());
 193  
             }
 194  92
         }
 195  
 
 196  26
         helpMessage.endOfOptions();
 197  26
     }
 198  
 
 199  
     private boolean hasCustomApplicationName() {
 200  30
         return !nullOrBlank(applicationName());
 201  
     }
 202  
 
 203  
     static boolean nullOrBlank(final String string) {
 204  30
         return string == null || string.trim().equals("");
 205  
     }
 206  
 
 207  
     @Override public String toString() {
 208  26
         final HelpMessageBuilderImpl helpMessage = new HelpMessageBuilderImpl();
 209  26
         describeTo(helpMessage);
 210  26
         return helpMessage.toString();
 211  
     }
 212  
 }