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    
020    package prantl.ant.eclipse;
021    
022    import java.util.Iterator;
023    import java.util.Set;
024    import java.util.Vector;
025    
026    import 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     */
037    public 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    }