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     */
017    package org.apache.commons.cli2.commandline;
018    
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.Collections;
022    import java.util.HashSet;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Set;
026    import java.util.StringTokenizer;
027    import java.util.prefs.BackingStoreException;
028    import java.util.prefs.Preferences;
029    
030    import org.apache.commons.cli2.Option;
031    import org.apache.commons.cli2.option.PropertyOption;
032    
033    /**
034     * A CommandLine implementation using the Preferences API, useful when
035     * constructing a complex DefaultingCommandLine
036     *
037     * This implementation uses the children of a single preference node to populate
038     * the CommandLine.  Options are keyed from their preferred name and presence in
039     * the Preferences object is taken as presence in the CommandLine.  Argument
040     * values are taken from the Preference value and are optionally separated using
041     * the separator char defined, at construction time.  Switch values can be
042     * specified using a simple value of <code>true</code> or <code>false</code>;
043     * obviously this means that Switches with Arguments are not supported by this
044     * implementation.
045     *
046     * @see java.util.prefs.Preferences
047     * @see org.apache.commons.cli2.commandline.DefaultingCommandLine
048     * @see org.apache.commons.cli2.Option#getPreferredName()
049     */
050    public class PreferencesCommandLine extends CommandLineImpl {
051    
052        private static final char NUL = '\0';
053        private final Preferences preferences;
054        private final Option root;
055        private final char separator;
056    
057        /**
058         * Creates a new PreferencesCommandLine using the specified root Option and
059         * Preferences node.  Argument values will be separated using the char 0.
060         *
061         * @param root the CommandLine's root Option
062         * @param preferences the Preferences node to get values from
063         */
064        public PreferencesCommandLine(final Option root, final Preferences preferences){
065            this(root,preferences,NUL);
066        }
067    
068        /**
069         * Creates a new PreferencesCommandLine using the specified root Option,
070         * Preferences node and value separator.
071         *
072         * @param root the CommandLine's root Option
073         * @param preferences the Preferences node to get values from
074         * @param separator the character to split argument values
075         */
076        public PreferencesCommandLine(final Option root, final Preferences preferences, final char separator){
077            this.root = root;
078            this.preferences = preferences;
079            this.separator = separator;
080        }
081    
082        public boolean hasOption(Option option) {
083            if(option==null){
084                return false;
085            }
086            else{
087                try {
088                    return Arrays.asList(preferences.keys()).contains(option.getPreferredName());
089                } catch (BackingStoreException e) {
090                    return false;
091                }
092            }
093        }
094    
095        public Option getOption(String trigger) {
096            return root.findOption(trigger);
097        }
098    
099        public List getValues(final Option option, final List defaultValues) {
100            final String value = preferences.get(option.getPreferredName(),null);
101    
102            if(value==null){
103                return defaultValues;
104            }
105            else if(separator>NUL){
106                final List values = new ArrayList();
107                final StringTokenizer tokens = new StringTokenizer(value,String.valueOf(separator));
108    
109                while(tokens.hasMoreTokens()){
110                    values.add(tokens.nextToken());
111                }
112    
113                return values;
114            }
115            else{
116                return Collections.singletonList(value);
117            }
118        }
119    
120        public Boolean getSwitch(final Option option, final Boolean defaultValue) {
121            final String value = preferences.get(option.getPreferredName(),null);
122            if("true".equals(value)){
123                return Boolean.TRUE;
124            }
125            else if("false".equals(value)){
126                return Boolean.FALSE;
127            }
128            else{
129                return defaultValue;
130            }
131        }
132    
133        public String getProperty(final String property) {
134            return getProperty(new PropertyOption(), property);
135        }
136    
137        public String getProperty(final Option option, final String property, final String defaultValue) {
138            return preferences.get(property, defaultValue);
139        }
140    
141            public Set getProperties(final Option option) {
142            try {
143                return new HashSet(Arrays.asList(preferences.keys()));
144            } catch (BackingStoreException e) {
145                return Collections.EMPTY_SET;
146            }
147        }
148    
149        public Set getProperties() {
150            return getProperties(new PropertyOption());
151        }
152    
153        public List getOptions() {
154            try {
155                final List options = new ArrayList();
156                final Iterator keys = Arrays.asList(preferences.keys()).iterator();
157                while (keys.hasNext()) {
158                    final String trigger = (String) keys.next();
159                    final Option option = root.findOption(trigger);
160                    if (option != null) {
161                        options.add(option);
162                    }
163                }
164                return Collections.unmodifiableList(options);
165            } catch (BackingStoreException e) {
166                return Collections.EMPTY_LIST;
167            }
168        }
169    
170        public Set getOptionTriggers() {
171            final Set triggers = new HashSet();
172            final Iterator options = getOptions().iterator();
173            while(options.hasNext()){
174                final Option option = (Option)options.next();
175                triggers.addAll(option.getTriggers());
176            }
177            return Collections.unmodifiableSet(triggers);
178        }
179    }