001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.cmdline;
021    
022    import org.crsh.cmdline.binding.TypeBinding;
023    import org.crsh.cmdline.matcher.CmdSyntaxException;
024    import org.crsh.cmdline.spi.Completer;
025    
026    import java.io.IOException;
027    import java.lang.annotation.Annotation;
028    import java.lang.reflect.Type;
029    import java.util.ArrayList;
030    import java.util.Collections;
031    import java.util.List;
032    
033    public class OptionDescriptor<B extends TypeBinding> extends ParameterDescriptor<B> {
034    
035      /** . */
036      private final int arity;
037    
038      /** . */
039      private final List<String> names;
040    
041      public OptionDescriptor(
042        B binding,
043        Type javaType,
044        List<String> names,
045        Description info,
046        boolean required,
047        boolean password,
048        boolean unquote,
049        Class<? extends Completer> completerType,
050        Annotation annotation) throws IllegalValueTypeException, IllegalParameterException {
051        super(
052          binding,
053          javaType,
054          info,
055          required,
056          password,
057          unquote,
058          completerType,
059          annotation);
060    
061        //
062        if (getMultiplicity() == Multiplicity.MULTI && getType() == SimpleValueType.BOOLEAN) {
063          throw new IllegalParameterException();
064        }
065    
066        //
067        names = new ArrayList<String>(names);
068        for (String name : names) {
069          if (name == null) {
070            throw new IllegalParameterException("Option name must not be null");
071          }
072          if (name.length() == 0) {
073            throw new IllegalParameterException("Option name cannot be empty");
074          }
075          if (name.contains("-")) {
076            throw new IllegalParameterException("Option name must not contain the hyphen character");
077          }
078        }
079    
080        //
081        if (getType() == SimpleValueType.BOOLEAN) {
082          arity = 0;
083        } else {
084          arity = 1;
085        }
086    
087        //
088        this.names = Collections.unmodifiableList(names);
089      }
090    
091      public int getArity() {
092        return arity;
093      }
094    
095      public List<String> getNames() {
096        return names;
097      }
098    
099      @Override
100      public Object parse(List<String> values) throws CmdSyntaxException {
101        if (arity == 0) {
102          if (values.size() > 0) {
103            throw new CmdSyntaxException("Too many option values: " + values);
104          }
105          // It's a boolean and it is true
106          return Boolean.TRUE;
107        } else {
108          if (getMultiplicity() == Multiplicity.SINGLE) {
109            if (values.size() > 1) {
110              throw new CmdSyntaxException("Too many option values: " + values);
111            }
112            String value = values.get(0);
113            try {
114              return parse(value);
115            } catch (Exception e) {
116              throw new CmdSyntaxException("Could not parse value: <" + value + ">");
117            }
118          } else {
119            List<Object> v = new ArrayList<Object>(values.size());
120            for (String value : values) {
121              try {
122                v.add(parse(value));
123              } catch (Exception e) {
124                throw new CmdSyntaxException("Could not parse value: <" + value + ">");
125              }
126            }
127            return v;
128          }
129        }
130      }
131    
132      /**
133       * Prints the option names as an alternative of switches surrounded by a square brace,
134       * for instance:  "[-f --foo]"
135       *
136       * @param writer the writer to print to
137       * @throws IOException any io exception
138       */
139      public void printUsage(Appendable writer) throws IOException {
140        writer.append("[");
141        boolean a = false;
142        for (String optionName : names) {
143          if (a) {
144            writer.append(" | ");
145          }
146          writer.append(optionName.length() == 1 ? "-" : "--").append(optionName);
147          a = true;
148        }
149        writer.append("]");
150      }
151    
152      @Override
153      public String toString() {
154        return "OptionDescriptor[" + names + "]";
155      }
156    }