001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.cli2.commandline;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.HashSet;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Properties;
025import java.util.Set;
026import java.util.StringTokenizer;
027
028import org.apache.commons.cli2.Option;
029import org.apache.commons.cli2.option.PropertyOption;
030
031/**
032 * A CommandLine implementation using a java Properties instance, useful for
033 * constructing a complex DefaultingCommandLine
034 *
035 * Options are keyed from their property name and presence in the Properties
036 * instance is taken as presence in the CommandLine.  Argument values are taken
037 * from the property value and are optionally separated using the separator
038 * char, defined at construction time.  Switch values can be specified using a
039 * simple value of <code>true</code> or <code>false</code>; obviously this means
040 * that Switches with Arguments are not supported by this implementation.
041 *
042 * @see java.util.Properties
043 * @see org.apache.commons.cli2.commandline.DefaultingCommandLine
044 * @see org.apache.commons.cli2.Option#getPreferredName()
045 */
046public class PropertiesCommandLine extends CommandLineImpl {
047
048    private static final char NUL = '\0';
049    private final Properties properties;
050    private final Option root;
051    private final char separator;
052
053    /**
054     * Creates a new PropertiesCommandLine using the specified root Option,
055     * Properties instance.  The character 0 is used as the value separator.
056     *
057     * @param root the CommandLine's root Option
058     * @param properties the Properties instance to get values from
059     */
060    public PropertiesCommandLine(final Option root, final Properties properties){
061        this(root,properties,NUL);
062    }
063
064    /**
065     * Creates a new PropertiesCommandLine using the specified root Option,
066     * Properties instance and value separator.
067     *
068     * @param root the CommandLine's root Option
069     * @param properties the Properties instance to get values from
070     * @param separator the character to split argument values
071     */
072    public PropertiesCommandLine(final Option root, final Properties properties, final char separator){
073        this.root = root;
074        this.properties = properties;
075        this.separator = separator;
076    }
077
078
079    public boolean hasOption(Option option) {
080        if(option==null){
081            return false;
082        }
083        else{
084            return properties.containsKey(option.getPreferredName());
085        }
086    }
087
088    public Option getOption(String trigger) {
089        return root.findOption(trigger);
090    }
091
092    public List getValues(final Option option, final List defaultValues) {
093        final String value = properties.getProperty(option.getPreferredName());
094
095        if(value==null){
096            return defaultValues;
097        }
098        else if(separator>NUL){
099            final List values = new ArrayList();
100            final StringTokenizer tokens = new StringTokenizer(value,String.valueOf(separator));
101
102            while(tokens.hasMoreTokens()){
103                values.add(tokens.nextToken());
104            }
105
106            return values;
107        }
108        else{
109            return Collections.singletonList(value);
110        }
111    }
112
113    public Boolean getSwitch(final Option option, final Boolean defaultValue) {
114        final String value = properties.getProperty(option.getPreferredName());
115        if("true".equals(value)){
116            return Boolean.TRUE;
117        }
118        else if("false".equals(value)){
119            return Boolean.FALSE;
120        }
121        else{
122            return defaultValue;
123        }
124    }
125
126    public String getProperty(final String property) {
127        return getProperty(new PropertyOption(), property);
128    }
129
130    public String getProperty(final Option option, final String property, final String defaultValue) {
131        return properties.getProperty(property,defaultValue);
132    }
133
134        public Set getProperties(final Option option) {
135        return properties.keySet();
136    }
137
138    public Set getProperties() {
139        return getProperties(new PropertyOption());
140    }
141
142    public List getOptions() {
143        final List options = new ArrayList();
144        final Iterator keys = properties.keySet().iterator();
145        while(keys.hasNext()){
146            final String trigger = (String)keys.next();
147            final Option option = root.findOption(trigger);
148            if(option!=null){
149                options.add(option);
150            }
151        }
152        return Collections.unmodifiableList(options);
153    }
154
155    public Set getOptionTriggers() {
156        final Set triggers = new HashSet();
157        final Iterator options = getOptions().iterator();
158        while(options.hasNext()){
159            final Option option = (Option)options.next();
160            triggers.addAll(option.getTriggers());
161        }
162        return Collections.unmodifiableSet(triggers);
163    }
164}