001// Copyright 2005-2006 Ferdinand Prantl <prantl@users.sourceforge.net>
002// Copyright 2001-2004 The Apache Software Foundation
003// All rights reserved.
004//
005// Licensed under the Apache License, Version 2.0 (the "License");
006// you may not use this file except in compliance with the License.
007// 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// See http://ant-eclipse.sourceforge.net for the most recent version
018// and more information.
019
020package prantl.ant.eclipse;
021
022import java.util.Iterator;
023import java.util.Set;
024import java.util.Vector;
025
026import org.apache.tools.ant.BuildException;
027
028/**
029 * Configures a component preferences in a file under the directory <tt>.settings</tt>
030 * using variable elements. The version element is mandatory and will be generated
031 * automatically if not provided. The attributes <tt>name</tt> of all elements
032 * describing the preferences must be distinct.
033 * 
034 * @since Ant-Eclipse 1.0
035 * @author Ferdinand Prantl &lt;prantl@users.sourceforge.net&gt;
036 */
037public abstract class PreferencesElement {
038
039    private static final String VERSION_NAME = "eclipse.preferences.version";
040
041    private static final String VERSION_VALUE = "1";
042
043    private SettingsElement settings = null;
044
045    private String name = null;
046
047    private Vector variables = new Vector();
048
049    /**
050     * Creates a new instance of the element for preferences under the settings element.
051     * 
052     * @param parent
053     *        The parent settings element of this preferences one.
054     * @since Ant-Eclipse 1.0
055     */
056    PreferencesElement(SettingsElement parent) {
057        settings = parent;
058    }
059
060    /**
061     * Returns the name of the file with preferences. The name must not be <tt>null</tt>,
062     * it is a mandatory attribute.
063     * 
064     * @return The name of the file with preferences or <tt>null</tt> if not having been
065     *         set.
066     */
067    public String getName() {
068        return name;
069    }
070
071    /**
072     * Sets the name of the file with preferences. Used internally to set default names of
073     * the files for preferences.
074     * 
075     * @param value
076     *        A name of the file with preferences.
077     * @since Ant-Eclipse 1.0
078     */
079    void internalSetName(String value) {
080        settings.validatePreferencesName(value);
081        name = value;
082    }
083
084    /**
085     * Returns the version of the preferences set by this element (<tt>1</tt> is used
086     * as a default). The default value should be left.
087     * 
088     * @return The version of the Eclipse preferences (<tt>1</tt> is used as a
089     *         default).
090     */
091    public String getVersion() {
092        // return version;
093        VariableElement variable = getVariable(VERSION_NAME);
094        return variable == null ? VERSION_VALUE : variable.getValue();
095    }
096
097    /**
098     * Sets the version of the Eclipse preferences. The default value should be left and
099     * not set explicitely.
100     * 
101     * @param value
102     *        A valid version of the Eclipse preferences.
103     * @since Ant-Eclipse 1.0
104     */
105    public void setVersion(String value) {
106        internalCreateVariable(VERSION_NAME, value);
107    }
108
109    /**
110     * Returns a list with instances of the class VariableElement defining variables for a
111     * file <em>&lt;full qualified class
112     * name&gt;</em> under the directory
113     * <tt>.settings</tt>. If it is empty the version element will be generated
114     * automatically.
115     * 
116     * @return A list with instances of the descendants of the class PreferencesElement.
117     */
118    public Vector getVariables() {
119        return variables;
120    }
121
122    /**
123     * Adds a definition of a new variable element. Used internally to add undeclared
124     * variable definitions and allow the low-level variable element.
125     * 
126     * @return A definition of a new variable element.
127     * @since Ant-Eclipse 1.0
128     */
129    VariableElement internalCreateVariable() {
130        variables.addElement(new VariableElement(this));
131        return (VariableElement) variables.lastElement();
132    }
133
134    /**
135     * Adds a definition of a new variable element, with its name and value. Used
136     * internally to add undeclared variable definitions.
137     * 
138     * @param name
139     *        A name of the configuration variable.
140     * @param value
141     *        A value of the configuration variable.
142     * @since Ant-Eclipse 1.0
143     */
144    void internalCreateVariable(String name, String value) {
145        VariableElement variable = internalCreateVariable();
146        variable.setName(name);
147        variable.setValue(value);
148    }
149
150    /**
151     * Adds a definition of a new variable element, with its name and value, only if not
152     * yet defined. Used internally to add default variable definitions.
153     * 
154     * @param name
155     *        A name of the configuration variable.
156     * @param value
157     *        A value of the configuration variable.
158     * @since Ant-Eclipse 1.0
159     */
160    void internalAddVariable(String name, String value) {
161        if (!hasVariable(name))
162            internalCreateVariable(name, value);
163    }
164
165    /**
166     * Performs the validation of the element at the time when the whole build file was
167     * parsed checking the content of the element and possibly adding mandatory variables
168     * with default settings.
169     * 
170     * @since Ant-Eclipse 1.0
171     */
172    public void validate() {
173        if (!hasVariable(VERSION_NAME))
174            setVersion(VERSION_VALUE);
175        for (int i = 0, size = variables.size(); i != size; ++i) {
176            VariableElement variable = (VariableElement) variables.get(i);
177            variable.validate();
178        }
179    }
180
181    /**
182     * Checks if the variable with the specified name is allowed to be defined according
183     * to the already parsed content.
184     * 
185     * @param name
186     *        The name of the configuration variable to validate.
187     * @since Ant-Eclipse 1.0
188     */
189    void validateVariableName(String name) {
190        if (hasVariable(name))
191            throw new BuildException(
192                    name.equals(VERSION_NAME) ? "The variable \""
193                            + VERSION_NAME
194                            + "\" cannot be defined as an element if there has been an attribute \"version\" used for the whole preferences."
195                            : "The variable named \"" + name
196                                    + "\" has alredy been defined.");
197    }
198
199    /**
200     * Checks if the variable with the specified name has already been defined for this
201     * preferences.
202     * 
203     * @param name
204     *        The name of the configuration variable to look for.
205     * @return <tt>True</tt> if the variable with the specified name is present.
206     * @since Ant-Eclipse 1.0
207     */
208    boolean hasVariable(String name) {
209        return getVariable(name) != null;
210    }
211
212    /**
213     * Returns the element defining the variable with the specified name or <tt>null</tt>
214     * if not having been defined.
215     * 
216     * @param name
217     *        The element defining the configuration variable or <tt>null</tt> if not
218     *        present.
219     * @return The element defining the variable with the specified name or <tt>null</tt>
220     *         if not present.
221     * @since Ant-Eclipse 1.0
222     */
223    VariableElement getVariable(String name) {
224        for (int i = 0, size = variables.size(); i != size; ++i) {
225            VariableElement variable = (VariableElement) variables.get(i);
226            if (name.equals(variable.getName()))
227                return variable;
228        }
229        return null;
230    }
231
232    /**
233     * Returns a new string with a list of string representations of the items from the
234     * passed set in the format "item1", "item2" and "item3" useful to display allowed
235     * value list as a string.
236     * 
237     * @param set
238     *        Set to list as a string.
239     * @return A new string with a list of string representations of the items from the
240     *         passed set in the format "item1", "item2" and "item3".
241     * @since Ant-Eclipse 1.0
242     */
243    String getValidValues(Set set) {
244        StringBuffer result = new StringBuffer();
245        Iterator iterator = set.iterator();
246        for (int i = 0, size = set.size(); i != size; ++i) {
247            result.append('\"');
248            result.append(iterator.next());
249            if (i == size - 2)
250                result.append("\" and ");
251            else if (i == size - 1)
252                result.append('\"');
253            else
254                // if (i < count - 2)
255                result.append("\", ");
256        }
257        return result.toString();
258    }
259
260}