001    /*
002     * Copyright (C) 2010 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    /**
034     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
035     * @version $Revision$
036     */
037    public class OptionDescriptor<B extends TypeBinding> extends ParameterDescriptor<B> {
038    
039      /** . */
040      private final int arity;
041    
042      /** . */
043      private final List<String> names;
044    
045      public OptionDescriptor(
046        B binding,
047        Type javaType,
048        List<String> names,
049        Description info,
050        boolean required,
051        boolean password,
052        boolean unquote,
053        Class<? extends Completer> completerType,
054        Annotation annotation) throws IllegalValueTypeException, IllegalParameterException {
055        super(
056          binding,
057          javaType,
058          info,
059          required,
060          password,
061          unquote,
062          completerType,
063          annotation);
064    
065        //
066        if (getMultiplicity() == Multiplicity.MULTI && getType() == SimpleValueType.BOOLEAN) {
067          throw new IllegalParameterException();
068        }
069    
070        //
071        names = new ArrayList<String>(names);
072        for (String name : names) {
073          if (name == null) {
074            throw new IllegalParameterException("Option name must not be null");
075          }
076          if (name.length() == 0) {
077            throw new IllegalParameterException("Option name cannot be empty");
078          }
079          if (name.contains("-")) {
080            throw new IllegalParameterException("Option name must not contain the hyphen character");
081          }
082        }
083    
084        //
085        if (getType() == SimpleValueType.BOOLEAN) {
086          arity = 0;
087        } else {
088          arity = 1;
089        }
090    
091        //
092        this.names = Collections.unmodifiableList(names);
093      }
094    
095      public int getArity() {
096        return arity;
097      }
098    
099      public List<String> getNames() {
100        return names;
101      }
102    
103      @Override
104      public Object parse(List<String> values) throws CmdSyntaxException {
105        if (arity == 0) {
106          if (values.size() > 0) {
107            throw new CmdSyntaxException("Too many option values: " + values);
108          }
109          // It's a boolean and it is true
110          return Boolean.TRUE;
111        } else {
112          if (getMultiplicity() == Multiplicity.SINGLE) {
113            if (values.size() > 1) {
114              throw new CmdSyntaxException("Too many option values: " + values);
115            }
116            String value = values.get(0);
117            try {
118              return parse(value);
119            } catch (Exception e) {
120              throw new CmdSyntaxException("Could not parse value: <" + value + ">");
121            }
122          } else {
123            List<Object> v = new ArrayList<Object>(values.size());
124            for (String value : values) {
125              try {
126                v.add(parse(value));
127              } catch (Exception e) {
128                throw new CmdSyntaxException("Could not parse value: <" + value + ">");
129              }
130            }
131            return v;
132          }
133        }
134      }
135    
136      /**
137       * Prints the option names as an alternative of switches surrounded by a square brace,
138       * for instance:  "[-f --foo]"
139       *
140       * @param writer the writer to print to
141       * @throws IOException any io exception
142       */
143      public void printUsage(Appendable writer) throws IOException {
144        writer.append("[");
145        boolean a = false;
146        for (String optionName : names) {
147          if (a) {
148            writer.append(" | ");
149          }
150          writer.append(optionName.length() == 1 ? "-" : "--").append(optionName);
151          a = true;
152        }
153        writer.append("]");
154      }
155    
156      @Override
157      public String toString() {
158        return "OptionDescriptor[" + names + "]";
159      }
160    }