001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.plugin;
021
022 import org.crsh.util.Utils;
023
024 import java.util.List;
025 import java.util.Arrays;
026 import java.util.Collections;
027 import java.util.HashMap;
028 import java.util.Map;
029 import java.util.concurrent.TimeUnit;
030
031 public abstract class PropertyDescriptor<T> {
032
033 /** The display value returned when a property is secret. */
034 public static final String SECRET_DISPLAY_VALUE = "*****";
035
036 public static PropertyDescriptor<String> create(String name, String defaultValue, String description, boolean secret) {
037 return new PropertyDescriptor<String>(String.class, name, defaultValue, description, secret) {
038 @Override
039 protected String doParse(String s) throws Exception {
040 return s;
041 }
042 };
043 }
044
045
046 public static PropertyDescriptor<String> create(String name, String defaultValue, String description) {
047 return create(name, defaultValue, description, false);
048 }
049
050 public static PropertyDescriptor<Integer> create(String name, Integer defaultValue, String description, boolean secret) {
051 return new PropertyDescriptor<Integer>(Integer.class, name, defaultValue, description, secret) {
052 @Override
053 protected Integer doParse(String s) throws Exception {
054 return Integer.parseInt(s);
055 }
056 };
057 }
058
059 public static PropertyDescriptor<Integer> create(String name, Integer defaultValue, String description) {
060 return create(name, defaultValue, description, false);
061 }
062
063 public static PropertyDescriptor<List> create(String name, List defaultValue, String description, boolean secret) {
064 return new PropertyDescriptor<List>(List.class, name, defaultValue, description, secret) {
065 @Override
066 protected List doParse(String s) throws Exception {
067 String[] split = Utils.split(s, ',');
068 List<String> list = Arrays.asList(split);
069 for (int i = 0;i < list.size();i++) {
070 list.set(i, list.get(i).trim());
071 }
072 return list;
073 }
074 };
075 }
076
077 public static PropertyDescriptor<List> create(String name, List defaultValue, String description) {
078 return create(name, defaultValue, description, false);
079 }
080
081 /** . */
082 private static final Map<String, PropertyDescriptor<?>> INTERNAL_ALL = new HashMap<String, PropertyDescriptor<?>>();
083
084 /** . */
085 public static final Map<String, PropertyDescriptor<?>> ALL = Collections.unmodifiableMap(INTERNAL_ALL);
086
087 /** . */
088 public static final PropertyDescriptor<TimeUnit> VFS_REFRESH_UNIT = new PropertyDescriptor<TimeUnit>(TimeUnit.class, "vfs.refresh_unit", TimeUnit.SECONDS, "The refresh time unit") {
089 @Override
090 public TimeUnit doParse(String s) {
091 return TimeUnit.valueOf(s);
092 }
093 };
094
095 /** . */
096 public static final PropertyDescriptor<Integer> VFS_REFRESH_PERIOD = PropertyDescriptor.create("vfs.refresh_period", (Integer)null, "The refresh rate period");
097
098 /** . */
099 public final Class<T> type;
100
101 /** . */
102 public final String name;
103
104 /** . */
105 public final T defaultValue;
106
107 /** . */
108 public final String description;
109
110 /** . */
111 public final boolean secret;
112
113 /**
114 * Create a new property descriptor.
115 *
116 * @param type the property type
117 * @param name the property name
118 * @param defaultValue the default value
119 * @param description the description
120 * @throws NullPointerException if the type, name or description is null
121 */
122 protected PropertyDescriptor(Class<T> type, String name, T defaultValue, String description) throws NullPointerException {
123 this(type, name, defaultValue, description, false);
124 }
125
126 /**
127 * Create a new property descriptor.
128 *
129 * @param type the property type
130 * @param name the property name
131 * @param defaultValue the default value
132 * @param description the description
133 * @param secret the value is secret (like a password)
134 * @throws NullPointerException if the type, name or description is null
135 */
136 protected PropertyDescriptor(Class<T> type, String name, T defaultValue, String description, boolean secret) throws NullPointerException {
137 if (type == null) {
138 throw new NullPointerException("No null type accepted");
139 }
140 if (name == null) {
141 throw new NullPointerException("No null name accepted");
142 }
143 if (description == null) {
144 throw new NullPointerException("No null description accepted");
145 }
146
147 this.type = type;
148 this.name = name;
149 this.defaultValue = defaultValue;
150 this.description = description;
151 this.secret = secret;
152
153 //
154 INTERNAL_ALL.put(name, this);
155 }
156
157 public final String getName() {
158 return name;
159 }
160
161 public final String getDescription() {
162 return description;
163 }
164
165 public final Class<T> getType() {
166 return type;
167 }
168
169 public final T getDefaultValue() {
170 return defaultValue;
171 }
172
173 public final String getDefaultDisplayValue() {
174 return secret ? SECRET_DISPLAY_VALUE : String.valueOf(defaultValue);
175 }
176
177 /**
178 * Parse a string representation of a value and returns the corresponding typed value.
179 *
180 * @param s the string to parse
181 * @return the corresponding value
182 * @throws NullPointerException if the argument is null
183 * @throws IllegalArgumentException if the string value cannot be parsed for some reason
184 */
185 public final T parse(String s) throws NullPointerException, IllegalArgumentException {
186 if (s == null) {
187 throw new NullPointerException("Cannot parse null property values");
188 }
189 try {
190 return doParse(s);
191 }
192 catch (Exception e) {
193 throw new IllegalArgumentException("Illegal property value " + s, e);
194 }
195 }
196
197 @Override
198 public boolean equals(Object obj) {
199 if (obj == this) {
200 return true;
201 } else if (obj instanceof PropertyDescriptor<?>) {
202 PropertyDescriptor<?> that = (PropertyDescriptor<?>)obj;
203 return name.equals(that.name) && type.equals(that.type);
204 } else {
205 return false;
206 }
207 }
208
209 /**
210 * Parse a string representation of a value and returns the correspondig property value.
211 *
212 * @param s the string to parse
213 * @return the corresponding property
214 * @throws NullPointerException if the argument is null
215 * @throws IllegalArgumentException if the string value cannot be parsed for some reason
216 */
217 public final Property<T> toProperty(String s) throws NullPointerException, IllegalArgumentException {
218 T value = parse(s);
219 return new Property<T>(this, value);
220 }
221
222 /**
223 * Implements the real parsing, the string argument must nto be null. The returned value must not be null instead an
224 * exception must be thrown.
225 *
226 * @param s the string to parse
227 * @return the related value
228 * @throws Exception any exception that would prevent parsing to hapen
229 */
230 protected abstract T doParse(String s) throws Exception;
231
232 @Override
233 public final String toString() {
234 return "PropertyDescriptor[name=" + name + ",type=" + type.getName() + ",description=" + description + "]";
235 }
236 }