2
package org.crosswire.common.config;
4
import java.io.Serializable;
5
import java.lang.reflect.InvocationTargetException;
6
import java.lang.reflect.Method;
8
import org.apache.log4j.Logger;
9
import org.crosswire.common.util.UserLevel;
10
import org.jdom.Element;
13
* Every Choice must be able to:<ul>
14
* <li>get and set itself using a String</li>
15
* <li>provide some simple help about itself</li>
16
* <li>elect a user level for itself (Beginner, Intermediate, Advanced)</li>
17
* <li>provide a GUI editor for itself</li>
20
* <p><table border='1' cellPadding='3' cellSpacing='0'>
21
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
23
* Distribution Licence:<br />
24
* JSword is free software; you can redistribute it
25
* and/or modify it under the terms of the GNU General Public License,
26
* version 2 as published by the Free Software Foundation.<br />
27
* This program is distributed in the hope that it will be useful,
28
* but WITHOUT ANY WARRANTY; without even the implied warranty of
29
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30
* General Public License for more details.<br />
31
* The License is available on the internet
32
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
33
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
34
* MA 02111-1307, USA<br />
35
* The copyright to this program is held by it's authors.
36
* </font></td></tr></table>
38
* @author Joe Walker [joe at eireneh dot com]
41
public abstract class ReflectedChoice implements Choice, Serializable
44
* Simple ctor so there is a default
46
public void init(Element option) throws StartupException
48
// The important 3 things saying what we update and how we describe ourselves
49
Element introspector = option.getChild("introspect");
50
if (introspector == null)
51
throw new StartupException("Missing introspect element in config.xml");
53
String clazzname = introspector.getAttributeValue("class");
54
propertyname = introspector.getAttributeValue("property");
56
log.debug("Looking up "+clazzname+".set"+propertyname+"("+getConvertionClass().getName()+" arg0)");
60
clazz = Class.forName(clazzname);
62
catch (ClassNotFoundException ex)
64
throw new StartupException("Specified class not found "+clazz.getName(), ex);
69
setter = clazz.getMethod("set"+propertyname, new Class[] { getConvertionClass() });
71
catch (NoSuchMethodException ex)
73
throw new StartupException("Specified method not found "+clazz.getName()+".set"+propertyname+"("+getConvertionClass().getName()+" arg0)", ex);
80
getter = clazz.getMethod("get"+propertyname, new Class[0]);
84
getter = clazz.getMethod("is"+propertyname, new Class[0]);
87
catch (NoSuchMethodException ex)
89
throw new StartupException("Specified method not found "+clazz.getName()+".get"+propertyname+"()", ex);
92
if (getter.getReturnType() != getConvertionClass())
94
log.debug("Not using "+propertyname+" from "+clazz.getName()+" because the return type of the getter is not "+getConvertionClass().getName());
95
throw new StartupException("Mismatch of return types, found: "+getter.getReturnType()+" required:"+getConvertionClass());
99
Element childele = option.getChild("help");
100
if (childele == null)
102
helptext = childele.getTextTrim();
104
// 2 optional config attrubites
105
level = UserLevel.forName(option.getAttributeValue("level"));
106
String priorityname = option.getAttributeValue("priority");
107
if (priorityname == null)
108
priority = ReflectedChoice.PRIORITY_NORMAL;
110
priority = Integer.parseInt(priorityname);
114
* Convert from a reflection return value to a String for storage
116
public abstract String convertToString(Object orig);
119
* Convert from a stored string to an object to use with relfection
121
public abstract Object convertToObject(String orig);
124
* Get some help on this Field. In this case we are just providing
125
* a default help text, that isn't much use.
126
* @return The default help text
128
public String getHelpText()
134
* Get some help on this Field. In this case we are just providing
135
* a default help text, that isn't much use.
136
* @return The default help text
138
public void setHelpText(String helptext)
140
this.helptext = helptext;
144
* Gets a default user level (beginner to advanced)
145
* @return The user level
147
public UserLevel getUserLevel()
153
* Gets a default user level (beginner to advanced)
154
* @param level The user level
156
protected void setUserLevel(UserLevel level)
162
* Is this Choice OK to write out to a file, or should we use settings
163
* in this run of the program, but forget them for next time. A
164
* typical use of this is for password configuration.
165
* @return True if it is safe to store the value in a config file.
167
public boolean isSaveable()
173
* Sometimes we need to ensure that we configure items in a certain
174
* order, the config package moves the changes to the application
175
* starting with the highest priority, moving to the lowest
176
* @return A priority level
178
public int getPriority()
184
* Sometimes we need to ensure that we configure items in a certain
185
* order, the config package moves the changes to the application
186
* starting with the highest priority, moving to the lowest
187
* @param priority A priority level
189
public void setPriority(int priority)
191
this.priority = priority;
195
* Do we need to restart the program in order for this change to have
197
* @return True if a restart is required
199
public boolean requiresRestart()
205
* @see org.crosswire.common.config.Choice#getString()
207
public String getString()
211
Object retval = getter.invoke(null, new Object[0]);
212
return convertToString(retval);
214
catch (IllegalAccessException ex)
216
log.error("Illegal access getting value from "+clazz.getName()+"."+getter.getName(), ex);
219
catch (InvocationTargetException ex)
221
log.error("Failed to get value from "+clazz.getName()+"."+getter.getName(), ex);
227
* @see org.crosswire.common.config.Choice#setString(String)
229
public void setString(String value) throws Exception
231
setter.invoke(null, new Object[] { convertToObject(value) });
234
/** The highest level priority generally for system level stuff */
235
public static final int PRIORITY_SYSTEM = 10;
237
/** The priority level for important but non system level stuff */
238
public static final int PRIORITY_EXTENDER = 9;
240
/** The priority level for important but non system level stuff */
241
public static final int PRIORITY_HIGHEST = 8;
243
/** The priority level for normal use */
244
public static final int PRIORITY_NORMAL = 6;
246
/** The priority level for creating items for later configuring */
247
public static final int PRIORITY_CTOR = 4;
249
/** The priority level for configuring previously created items */
250
public static final int PRIORITY_ACCESSOR = 2;
252
/** The lowest level priority generally for system level stuff */
253
public static final int PRIORITY_LOWEST = 0;
256
private String propertyname;
259
* The method to call to get the value
261
private Method getter;
264
* The method to call to set the value
266
private Method setter;
269
* The help text (tooltip) for this item
271
private String helptext = "No help available";
276
private UserLevel level = UserLevel.BEGINNER;
279
* The priority of this config level
281
private int priority = PRIORITY_NORMAL;
286
protected static Logger log = Logger.getLogger(ReflectedChoice.class);