1 package net.sourceforge.jparam.paramset;
2
3 import net.sourceforge.jparam.JParamException;
4
5 /***
6 * Represents a single parameter in a ParamSet
7 */
8
9 public class Param {
10 private String name;
11
12 private String description;
13
14 boolean isInput;
15
16 boolean isOutput;
17
18 Object defaultValue;
19
20 Object assignedValue;
21
22 Class typeBound;
23
24 /***
25 * Creates a Param object with given attributes. Set defaultValue to null to
26 * indicate there's no default value.
27 */
28 protected Param(String name_description, boolean isInput, boolean isOutput,
29 Object defaultValue, Class typeBound) throws JParamException {
30 separateNameAndDescription(name_description);
31 this.isInput = isInput;
32 this.isOutput = isOutput;
33 this.assignedValue = null;
34
35 if (typeBound == null)
36 typeBound = Object.class;
37
38 this.typeBound = typeBound;
39
40 setDefaultValue(defaultValue);
41 }
42
43 protected void clearValue() {
44 assignedValue = null;
45 }
46
47 /***
48 * Returns the parameter's name.
49 */
50 public String getName() {
51 return name;
52 }
53
54 /***
55 * Returns the parameter's description.
56 */
57 public String getDescription() {
58 return description;
59 }
60
61 /***
62 * Sets the parameter's description.
63 */
64 public void setDescription(String description) {
65 this.description = description;
66 }
67
68 /***
69 * Returns whether the parameter is an input parameter
70 */
71 public boolean isInput() {
72 return isInput;
73 }
74
75 /***
76 * Returns whether the parameter is an output parameter
77 */
78 public boolean isOutput() {
79 return isOutput;
80 }
81
82 /***
83 * Returns whether the parameter was assigned a value. If the parameter has
84 * a default value, this method may return false, but getValue will still
85 * return a non null object.
86 */
87 public boolean wasAssignedTo() {
88 return (assignedValue != null);
89 }
90
91 public boolean hasDefaultValue() {
92 return (defaultValue != null);
93 }
94
95 public boolean hasGivenValue() {
96 return (wasAssignedTo() || hasDefaultValue());
97 }
98
99 /***
100 * Returns the parameter's type bound. If getValue() returns a valid object
101 * (non null), then it is guaranteed to be assignable to a variable of this
102 * class.
103 */
104 public Class getTypeBound() {
105 return typeBound;
106 }
107
108 /***
109 * Returns the parameter's current value, or null if no such value exists.
110 */
111 public Object getValue() {
112 if (assignedValue != null)
113 return assignedValue;
114 return defaultValue;
115 }
116
117 /***
118 * Sets the parameter's current value. If val is not null, then calls to
119 * wasAssignedTo() following this call will return true. If val is null,
120 * this removed the parameter's value, and resets wasAssignedTo(), so it
121 * will return false.
122 */
123 public void setValue(Object value) throws JParamException {
124 if ((value != null) && !typeBound.isInstance(value)) {
125 throw new JParamException(
126 "assigned value does not conform to parameter's typeBound, parameter type: "
127 + typeBound.getName() + ", value type: "
128 + value.getClass().getName());
129 }
130 this.assignedValue = value;
131 }
132
133 /***
134 * Returns the parameter's default value, or null if it has none.
135 */
136 public Object getDefaultValue() {
137 return defaultValue;
138 }
139
140 /***
141 * Sets the parameter's default value. null removes it. If defaultValue
142 * isn't null, it must be compatible with the parameter's typeBound.
143 */
144 public void setDefaultValue(Object defaultValue) throws JParamException {
145 if ((defaultValue != null) && !typeBound.isInstance(defaultValue)) {
146 throw new JParamException(
147 "default value does not conform to parameter's typeBound");
148 }
149 this.defaultValue = defaultValue;
150 }
151
152 /***
153 * Extracts name and optional description, separated by !, and assigns them
154 * to class members. Also checks that the parameter's name is a legal
155 * identifier.
156 */
157 private void separateNameAndDescription(String s) throws JParamException {
158 int separatorPos = s.indexOf('!');
159
160 this.description = (separatorPos == -1) ? "" : s.substring(
161 separatorPos + 1).trim();
162
163 String name = (separatorPos == -1) ? s.trim() : s.substring(0,
164 separatorPos).trim();
165 if (name.length() == 0)
166 throw new JParamException("empty parameter name in '" + s + "'");
167 verifyName(name);
168 this.name = name;
169 }
170
171 /***
172 * Verifies that name is a legal identifier. Throws an exception if it
173 * isn't.
174 */
175 private void verifyName(String name) throws JParamException {
176 if (name.length() == 0)
177 throw new JParamException("empty parameter name in " + name);
178
179 String msg = "'" + name + "' isn't a legal parameter name";
180
181 String firstChar = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
182 if (firstChar.indexOf(name.charAt(0)) == -1) {
183 throw new JParamException(msg + ": '" + name.charAt(0)
184 + "' is not allowed as first character");
185 }
186
187 String idChars = firstChar + "0123456789";
188
189 for (int i = 1; i < name.length(); ++i) {
190 char c = name.charAt(i);
191 if (idChars.indexOf(c) == -1) {
192 throw new JParamException(msg + ": character '" + c
193 + "' is not allowed");
194 }
195 }
196 }
197
198 }