View Javadoc

1   /*
2    AbstractOption.java
3    Creation date : 2/06/2010
4    Copyright © Benjamin Croizet (graffity2199@yahoo.fr)
5   
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    or GNU Lesser General Public License as published by the
9    Free Software Foundation; either version 3 of the License,
10   or (at your option) any later version.
11  
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16  
17   You should have received copies of the GNU General Public License
18   and GNU Lesser General Public License along with this program;
19   if not, write to the Free Software Foundation, Inc.,
20   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21   http://www.fsf.org/licensing/licenses/gpl.html
22   http://www.gnu.org/licenses/lgpl.html
23   */
24  
25  package net.sourceforge.plantumldependency.commoncli.option;
26  
27  import static java.util.logging.Level.SEVERE;
28  import static java.util.logging.Logger.getLogger;
29  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.COMMA_CHAR;
30  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.LINE_CHAR;
31  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.SPACE_CHAR;
32  import static net.sourceforge.plantumldependency.common.constants.CharacterConstants.TAB_CHAR;
33  import static net.sourceforge.plantumldependency.common.constants.log.ErrorConstants.UNEXPECTED_ERROR;
34  import static net.sourceforge.plantumldependency.common.utils.check.ParameterCheckerUtils.checkNull;
35  import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.FULL_USAGE_DESCRIPTION_NULL_ERROR;
36  import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.OPTION_NAME_NULL_ERROR;
37  import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.OPTION_SECONDARY_NAMES_NULL_ERROR;
38  import static net.sourceforge.plantumldependency.commoncli.constants.log.ErrorConstants.OPTION_STATUS_NULL_ERROR;
39  
40  import java.util.Set;
41  import java.util.TreeSet;
42  import java.util.logging.Logger;
43  
44  import net.sourceforge.plantumldependency.commoncli.option.status.OptionStatus;
45  
46  /**
47   * The abstract implementation of the {@link Option} interface, providing common behaviors.
48   *
49   * @author Benjamin Croizet (<a href="mailto:graffity2199@yahoo.fr>graffity2199@yahoo.fr</a>)
50   * @since 1.3.0
51   * @version 1.3.0
52   */
53  public abstract class AbstractOption implements Option {
54  
55      /** Serial version UID. */
56      private static final long serialVersionUID = -2714033818095664600L;
57  
58      /** The class logger. */
59      private static final transient Logger LOGGER = getLogger(AbstractOption.class.getName());
60  
61      /**
62       * The full option usage description, explaining what the option does (used for helping
63       * message).
64       */
65      private StringBuilder fullUsageDescription;
66  
67      /** The option main name (for instance "-v" or "-o"). */
68      private String name;
69  
70      /** The {@link Set} containing all option secondary names. */
71      private Set < String > secondaryNames;
72  
73      /** The option status, telling if the option is active, inactive or hidden. */
74      private OptionStatus status;
75  
76      /**
77       * Default constructor.
78       *
79       * @param optionName
80       *            the option main name (for instance "-v" or "-o"), mustn't be <code>null</code>.
81       * @param optionSecondaryNames
82       *            the {@link Set} containing all option secondary names, mustn't be
83       *            <code>null</code> but may be empty. <i>Note : a new {@link Set} is created.</i>
84       * @param fullOptionDescription
85       *            the full option usage description, explaining what the option does (used for
86       *            helping message). <i>Note : a new {@link StringBuilder} is created.</i>
87       * @param optionStatus
88       *            the option status, telling if the option is active, inactive or hidden, mustn't be
89       *            <code>null</code>.
90       * @since 1.3.0
91       */
92      protected AbstractOption(final String optionName, final Set < String > optionSecondaryNames,
93              final StringBuilder fullOptionDescription, final OptionStatus optionStatus) {
94          setName(optionName);
95          setSecondaryNames(new TreeSet < String >(optionSecondaryNames));
96          setFullUsageDescription(new StringBuilder(fullOptionDescription));
97          setStatus(optionStatus);
98      }
99  
100     /**
101      * {@inheritDoc}
102      *
103      * @since 1.3.0
104      */
105     @Override
106     public int compareTo(final Option o) {
107         return getName().compareTo(o.getName());
108     }
109 
110     /**
111      * {@inheritDoc}
112      *
113      * @since 1.3.0
114      */
115     @Override
116     public Option deepClone() {
117         AbstractOption a = null;
118 
119         try {
120             a = (AbstractOption) super.clone();
121             a.fullUsageDescription = new StringBuilder(getFullUsageDescription());
122             a.secondaryNames = new TreeSet < String >(getSecondaryNames());
123         } catch (final CloneNotSupportedException cnse) {
124             LOGGER.log(SEVERE, UNEXPECTED_ERROR, cnse);
125         }
126 
127         return a;
128     }
129 
130     /**
131      * {@inheritDoc}
132      *
133      * @since 1.3.0
134      */
135     @Override
136     public boolean equals(final Object obj) {
137         if (this == obj) {
138             return true;
139         }
140         if (obj == null) {
141             return false;
142         }
143         if (getClass() != obj.getClass()) {
144             return false;
145         }
146         final AbstractOption other = (AbstractOption) obj;
147         if (name == null) {
148             if (other.name != null) {
149                 return false;
150             }
151         } else if (!name.equals(other.name)) {
152             return false;
153         }
154         return true;
155     }
156 
157     /**
158      * {@inheritDoc}
159      *
160      * @since 1.3.0
161      */
162     @Override
163     public Set < String > getAllNames() {
164         final Set < String > allNames = new TreeSet < String >(getSecondaryNames());
165         allNames.add(getName());
166         return allNames;
167     }
168 
169     /**
170      * {@inheritDoc}
171      *
172      * @since 1.3.0
173      */
174     @Override
175     public StringBuilder getFullUsage() {
176         final StringBuilder buffer = new StringBuilder(getName());
177 
178         for (final String secondaryName : getSecondaryNames()) {
179             buffer.append(COMMA_CHAR);
180             buffer.append(SPACE_CHAR);
181             buffer.append(secondaryName);
182         }
183 
184         buffer.append(getFullUsageAdditions());
185         buffer.append(LINE_CHAR);
186         buffer.append(TAB_CHAR);
187         buffer.append(TAB_CHAR);
188         buffer.append(getFullUsageDescription());
189         buffer.append(getFullUsageDescriptionAdditions());
190 
191         return buffer;
192     }
193 
194     /**
195      * Gets the full option usage additions, which can add additional information for the option
196      * synopsis information (if necessary, used for helping message).
197      *
198      * @return the full option usage additions.
199      * @since 1.3.0
200      */
201     protected abstract StringBuilder getFullUsageAdditions();
202 
203     /**
204      * Gets the value of <code>fullUsageDescription</code>.
205      *
206      * @return the value of <code>fullUsageDescription</code>.
207      * @see #setFullUsageDescription(StringBuilder)
208      * @since 1.3.0
209      */
210     private StringBuilder getFullUsageDescription() {
211         return fullUsageDescription;
212     }
213 
214     /**
215      * Gets the full option usage additions, which can add additional description explaining what
216      * the option does (if necessary, used for helping message).
217      *
218      * @return the full option usage additions.
219      * @since 1.3.0
220      */
221     protected abstract StringBuilder getFullUsageDescriptionAdditions();
222 
223     /**
224      * {@inheritDoc}
225      *
226      * @since 1.3.0
227      */
228     @Override
229     public StringBuilder getMainUsage() {
230         final StringBuilder buffer = new StringBuilder(getName());
231         buffer.append(getMainUsageAdditions());
232         return buffer;
233     }
234 
235     /**
236      * Gets the full option main usage additions, which can add additional information for the main
237      * option synopsis information (if necessary, used for helping message).
238      *
239      * @return the full option main usage additions.
240      * @since 1.3.0
241      */
242     protected abstract StringBuilder getMainUsageAdditions();
243 
244     /**
245      * {@inheritDoc}
246      *
247      * @since 1.3.0
248      */
249     @Override
250     public String getName() {
251         return name;
252     }
253 
254     /**
255      * {@inheritDoc}
256      *
257      * @since 1.3.0
258      */
259     @Override
260     public Set < String > getSecondaryNames() {
261         return secondaryNames;
262     }
263 
264     /**
265      * Gets the value of <code>status</code>.
266      *
267      * @return the value of <code>status</code>.
268      * @since 1.3.0
269      */
270     @Override
271     public OptionStatus getStatus() {
272         return status;
273     }
274 
275     /**
276      * {@inheritDoc}
277      *
278      * @since 1.3.0
279      */
280     @Override
281     public int hashCode() {
282         final int prime = 31;
283         int result = 1;
284         result = prime * result + ((name == null) ? 0 : name.hashCode());
285         return result;
286     }
287 
288     /**
289      * {@inheritDoc}
290      *
291      * @since 1.3.0
292      */
293     @Override
294     public boolean isMandatory() {
295         return getStatus().isMandatory();
296     }
297 
298     /**
299      * Sets the value of <code>fullUsageDescription</code>.
300      *
301      * @param value
302      *            the <code>fullUsageDescription</code> to set, can be <code>null</code>.
303      * @see #getFullUsageDescription()
304      * @since 1.3.0
305      */
306     private void setFullUsageDescription(final StringBuilder value) {
307         checkNull(value, FULL_USAGE_DESCRIPTION_NULL_ERROR);
308 
309         fullUsageDescription = value;
310     }
311 
312     /**
313      * Sets the value of <code>name</code>.
314      *
315      * @param value
316      *            the <code>name</code> to set, can be <code>null</code>.
317      * @see #getName()
318      * @since 1.3.0
319      */
320     private void setName(final String value) {
321         checkNull(value, OPTION_NAME_NULL_ERROR);
322 
323         name = value;
324     }
325 
326     /**
327      * Sets the value of <code>secondaryNames</code>.
328      *
329      * @param value
330      *            the <code>secondaryNames</code> to set, can be <code>null</code>.
331      * @see #getSecondaryNames()
332      * @since 1.3.0
333      */
334     private void setSecondaryNames(final Set < String > value) {
335         checkNull(value, OPTION_SECONDARY_NAMES_NULL_ERROR);
336 
337         secondaryNames = value;
338     }
339 
340     /**
341      * Sets the value of <code>status</code>.
342      *
343      * @param value
344      *            the <code>status</code> to set, can be <code>null</code>.
345      * @see #getStatus()
346      * @since 1.3.0
347      */
348     private void setStatus(final OptionStatus value) {
349         checkNull(value, OPTION_STATUS_NULL_ERROR);
350 
351         status = value;
352     }
353 
354     /**
355      * {@inheritDoc}
356      *
357      * @since 1.3.0
358      */
359     @Override
360     public String toString() {
361         return getClass().getSimpleName() + " [fullUsageDescription=" + fullUsageDescription + ", name=" + name
362                 + ", secondaryNames=" + secondaryNames + ", status=" + status + "]";
363     }
364 }