001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2017
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028package edu.wisc.ssec.mcidasv.startupmanager.options;
029
030import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.EMPTY_STRING;
031import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.QUOTE_CHAR;
032import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.QUOTE_STRING;
033import static edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.SET_PREFIX;
034
035import javax.swing.JCheckBox;
036import javax.swing.JComponent;
037import javax.swing.JTextField;
038
039import edu.wisc.ssec.mcidasv.startupmanager.Platform;
040import edu.wisc.ssec.mcidasv.startupmanager.StartupManager;
041import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.OptionPlatform;
042import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.Type;
043import edu.wisc.ssec.mcidasv.startupmanager.options.OptionMaster.Visibility;
044
045public abstract class AbstractOption implements Option {
046
047    /**
048     * A unique identifier for an option. Should be the same as the 
049     * startup variable name found in the startup preference file.
050     */
051    private final String optionId;
052
053    /** 
054     * Brief description of the option. It will appear as the option's 
055     * label in the GUI.
056     */
057    private final String label;
058
059    /** @see Type */
060    private final Type optionType;
061
062    /** @see OptionPlatform */
063    private final OptionPlatform optionPlatform;
064
065    /** @see Visibility */
066    private final Visibility optionVisibility;
067
068    /**
069     * Creates an option that can hold a specified sort of data and that
070     * applies to a given platform.
071     * 
072     * @param id ID used to refer to this option.
073     * @param label Text that'll be used as the GUI label for this option
074     * @param optionType Type of data this option will represent.
075     * @param optionPlatform Platform(s) where this option is applicable.
076     * @param optionVisibility Visibility behavior of this option.
077     */
078    public AbstractOption(final String id, final String label, 
079        final Type optionType, final OptionPlatform optionPlatform, 
080        final Visibility optionVisibility) 
081    {
082        this.optionId = id;
083        this.label = label;
084        this.optionType = optionType;
085        this.optionPlatform = optionPlatform;
086        this.optionVisibility = optionVisibility;
087    }
088
089    /**
090     * Determines if the option applies to the current platform.
091     * 
092     * @return {@code true} if this option is applicable, {@code false} 
093     * otherwise.
094     */
095    protected boolean onValidPlatform() {
096        OptionPlatform platform = getOptionPlatform();
097        if (platform == OptionPlatform.ALL) {
098            return true;
099        }
100        if (platform == OptionMaster.getInstance().convertToOptionPlatform()) {
101            return true;
102        }
103        return false;
104    }
105
106    /**
107     * Tests the specified string to see if it's valid for the current 
108     * platform. Currently strings that contain {@literal "SET "} 
109     * <b>[ note the space ]</b> are considered to be Windows-only, while 
110     * strings lacking {@literal "SET "} are considered Unix-like.
111     * 
112     * @param text The string to test.
113     * 
114     * @return Whether or not the string is valid.
115     */
116    protected boolean isValidPrefFormat(final String text) {
117        assert text != null;
118        boolean hasSet = text.contains(SET_PREFIX);
119        boolean isWin = StartupManager.getInstance().getPlatform() == Platform.WINDOWS;
120        return isWin == hasSet;
121    }
122
123    /**
124     * Returns this option's type.
125     * 
126     * @return Option's type.
127     * 
128     * @see Type
129     */
130    public Type getOptionType() {
131        return optionType;
132    }
133
134    /**
135     * Returns the platform(s) to which this option applies.
136     * 
137     * @return Option's platform.
138     * 
139     * @see OptionPlatform
140     */
141    public OptionPlatform getOptionPlatform() {
142        return optionPlatform;
143    }
144
145    /**
146     * Returns whether or not this option represents a visible UI element.
147     * 
148     * @return The option's visibility.
149     * 
150     * @see Visibility
151     */
152    public Visibility getOptionVisibility() {
153        return optionVisibility;
154    }
155
156    /**
157     * Returns the ID used when referring to this option.
158     * 
159     * @return Option's ID.
160     */
161    public String getOptionId() {
162        return optionId;
163    }
164
165    /**
166     * Returns a brief description of this option. Mostly useful for 
167     * providing a GUI label.
168     * 
169     * @return Option's label.
170     */
171    public String getLabel() {
172        return label;
173    }
174
175    /**
176     * Initializes the current option using a relevant variable from the 
177     * startup script.
178     * 
179     * @param text Line from the startup script that represents the current
180     * option.
181     * 
182     * @throws IllegalArgumentException if {@code text} is not in the proper
183     * format for the current platform.
184     */
185    public void fromPrefsFormat(final String text) {
186        if (!isValidPrefFormat(text)) {
187            throw new IllegalArgumentException("Incorrect syntax for this platform: " + text);
188        }
189        String copy = new String(text);
190        if (StartupManager.getInstance().getPlatform() == Platform.WINDOWS) {
191            copy = copy.replace(SET_PREFIX, EMPTY_STRING);
192        }
193        String[] chunks = copy.split("=");
194        if (chunks.length == 2 && chunks[0].equals(optionId)) {
195            setValue(chunks[1]);
196        } else {
197            setValue(EMPTY_STRING);
198        }
199    }
200
201    /**
202     * Returns a string representation of the current option that is suitable 
203     * for use in the startup script.
204     * 
205     * @return Current value of this option as a startup script variable. The 
206     * formatting changes slightly between {@literal "Unix-like"} platforms 
207     * and Windows.
208     * 
209     * @see #isValidPrefFormat(String)
210     */
211    public String toPrefsFormat() {
212        Platform platform = StartupManager.getInstance().getPlatform();
213        StringBuilder str = new StringBuilder(optionId);
214        String value = getValue();
215        if (platform == Platform.WINDOWS) {
216            str.insert(0, SET_PREFIX);
217        }
218        str.append('=');
219        if ((platform != Platform.WINDOWS) && value.contains(" ")) {
220            str.append(QUOTE_CHAR).append(value).append(QUOTE_CHAR);
221        } else {
222            str.append(value);
223        }
224        return str.toString();
225    }
226
227    /**
228     * Returns the GUI component that represents the option. 
229     * {@link BooleanOption BooleanOptions} are represented by a
230     * {@link JCheckBox}, while {@link TextOption TextOptions} appear as a
231     * {@link JTextField}.
232     * 
233     * @return The GUI representation of this option.
234     */
235    public abstract JComponent getComponent();
236
237    /**
238     * Returns the value of the option. Note that
239     * {@link BooleanOption BooleanOptions} return either {@literal "0"} or
240     * {@literal "1"}.
241     * 
242     * @return The current value of the option.
243     */
244    public abstract String getValue();
245
246    /**
247     * Forces the value of the option to the data specified. Note that 
248     * {@link BooleanOption BooleanOptions} accept either {@literal "0"}, or
249     * {@literal "1"}.
250     * 
251     * @param value New value to use.
252     */
253    public abstract void setValue(final String value);
254
255    /**
256     * Friendly string representation of the option.
257     * 
258     * @return {@code String} containing relevant info about the option.
259     * 
260     * @see TextOption#toString()
261     * @see BooleanOption#toString()
262     */
263    public abstract String toString();
264}