139 for (int i = 0; i < keys.length; i++) {
140 String c = keys[i];
141 String rn = tag + "." + c;
142 try {
143 presentationKeys.put(keys[i], (c == null ? null : b.getString(rn)));
144 }
145 catch (MissingResourceException e) {
146 System.err.println("WARNING: missing resource " + rn);
147 presentationKeys.put(keys[i], c);
148 }
149 } // for
150 } // else
151 }
152
153 /**
154 * Get the set of keys currently used this question. Includes all hidden and
155 * read-only values as well.
156 * @return The set of keys (internal non-i18n value)
157 * @see #setKeys
158 */
159 public Enumeration getKeys() {
160 if (value != null)
161 return value.keys();
162 else
163 return null;
164 }
165
166 /**
167 * Get the default response for this question.
168 * @return the default response for this question.
169 *
170 * @see #setDefaultValue
171 */
172 public Properties getDefaultValue() {
173 return defaultValue;
174 }
175
176 /**
177 * Set the default response for this question,
178 * used by the clear method.
179 * @param props the default response for this question.
199 }
200
201 /**
202 * Verify this question is on the current path, and if it is,
203 * return the current value.
204 * @return the current value of this question
205 * @throws Interview.NotOnPathFault if this question is not on the
206 * current path
207 * @see #getValue
208 */
209 public Properties getValueOnPath() throws Interview.NotOnPathFault {
210 interview.verifyPathContains(this);
211 return getValue();
212 }
213
214 public String getStringValue() {
215 StringBuffer result = new StringBuffer();
216 if (value != null) {
217 String sep = System.getProperty("line.separator");
218
219 Enumeration names = value.propertyNames();
220 ArrayList list = Collections.list(names);
221 Collections.sort(list);
222 for (Object o : list) {
223 String key = (String)o;
224 result.append(key);
225 result.append("=");
226 result.append(value.getProperty(key));
227 result.append(sep);
228 }
229 }
230
231 return result.toString();
232 }
233
234 /**
235 * Set the current value.
236 * @param newValue Value represented as a single string. May not be null. May be
237 * an empty string.
238 * @see #getValue
239 */
240 public void setValue(String newValue) {
241 if (value == null || value.size() == 0)
242 return;
243
303 String o = data.get(tag);
304 if (o != null) {
305 setValue(load(o));
306 }
307 }
308
309 protected static Properties load(String s) {
310 Properties2 p2 = new Properties2();
311
312 try {
313 p2.load(new StringReader(s));
314 } catch (IOException e) {
315 //e.printStackTrace();
316 // what to do?! source should be really stable since it is a
317 // String
318 }
319
320 // repopulate a J2SE properties object
321 Properties p = new Properties();
322
323 Enumeration e = p2.propertyNames();
324 while(e.hasMoreElements()) {
325 Object next = e.nextElement();
326 p.put( next, p2.get(next) );
327 } // while
328
329 return p;
330 }
331
332 /**
333 * Save the value for this question in a dictionary, using
334 * the tag as the key.
335 * @param data The map in which to save the value for this question.
336 */
337 protected void save(Map<String, String> data) {
338 if (value == null)
339 return;
340
341 Properties2 p2 = new Properties2();
342 p2.load(value);
343 StringWriter sw = new StringWriter();
394 ValueConstraints c = getConstraints(key);
395 if (c == null || c.isVisible())
396 return true;
397 else
398 return false;
399 }
400
401 /**
402 * Get the keys which are currently invalid and blocking the question
403 * (getNext() returning null). It is recommended but not required that
404 * this method return null if the question is not blocked (getNext() !=
405 * null). This default implementation of this method is to check any
406 * ValueConstraint objects for each key and return those results. If you
407 * override this method, it is highly recommended that you allow this to
408 * take place, then add in any additional checking to the results provided
409 * by this base implementation.
410 * @return Invalid key in index zero, <em>localized</em> explanation
411 * in index one. Null means there are no invalid keys.
412 */
413 public String[][] getInvalidKeys() {
414 Enumeration names = value.propertyNames();
415 List<String> badKeys = new ArrayList<>();
416 List<String> reasons = new ArrayList<>();
417
418 while (names.hasMoreElements()) {
419 String curr = (String)(names.nextElement());
420 ValueConstraints rules = getConstraints(curr);
421
422 if (rules == null) {
423 continue; // no checks, next key
424 }
425 else {
426 String reason = rules.isValid(value.getProperty(curr));
427 if (reason != null) {
428 badKeys.add(curr);
429 reasons.add(reason);
430 }
431 }
432 }
433
434 // repack data for return
673 for(int i = 0; it.hasNext(); i++) {
674 data[i][0] = it.next();
675 data[i][1] = (String)(value.get(data[i][0]));
676 } // for
677
678 return data;
679 }
680 }
681
682 /**
683 * @return The keys and values which are not allocated to any group.
684 * Null if there are no ungrouped values.
685 * @see #getGroup
686 * @see #setGroup
687 */
688 public String[][] getUngrouped() {
689 if (value == null || value.size() == 0)
690 return null;
691
692 if (keyGroups != null) {
693 Set keys = keyGroups.keySet();
694 if (keys != null) {
695 String[] gps = getGroups();
696 Properties copy = (Properties)(value.clone());
697
698 // remove all grouped entries from the copied
699 // question value
700 for (int i = 0; i < gps.length; i++) {
701 String[][] vals = getGroup(gps[i]);
702
703 for (int j = 0; j < vals.length; j++)
704 copy.remove(vals[j][0]);
705 }
706
707 if (copy.size() > 0) {
708 Enumeration en = copy.propertyNames();
709 String[][] ret = new String[copy.size()][2];
710 int i = 0;
711
712 while (en.hasMoreElements()) {
713 String key = (String)(en.nextElement());
714 ret[i][0] = key;
715 ret[i][1] = copy.getProperty(key);
716 i++;
717 } // while
718
719 return ret;
720 }
721 else
722 return null;
723 }
724 }
725 // no groups, return the entire value set
726 String[][] ret = new String[value.size()][2];
727 Enumeration en = value.propertyNames();
728 int i = 0;
729
730 while (en.hasMoreElements()) {
731 String key = (String)(en.nextElement());
732 ret[i][0] = key;
733 ret[i][1] = value.getProperty(key);
734 i++;
735 } // while
736
737 return ret; // no groups in use
738 }
739
740 // ------------ PRESENTATION ---------------
741
742 /**
743 * Get the display (localized) name of the group.
744 * The resource necessary is the question tag, with the group name and ".group"
745 * appended. That is <code>jck.qTable.basic.group</code> and
746 * <code>jck.qTable.advanced.group</code>.
747 * @param group The internal group name, as is used in the rest of this API.
|
139 for (int i = 0; i < keys.length; i++) {
140 String c = keys[i];
141 String rn = tag + "." + c;
142 try {
143 presentationKeys.put(keys[i], (c == null ? null : b.getString(rn)));
144 }
145 catch (MissingResourceException e) {
146 System.err.println("WARNING: missing resource " + rn);
147 presentationKeys.put(keys[i], c);
148 }
149 } // for
150 } // else
151 }
152
153 /**
154 * Get the set of keys currently used this question. Includes all hidden and
155 * read-only values as well.
156 * @return The set of keys (internal non-i18n value)
157 * @see #setKeys
158 */
159 public Enumeration<?> getKeys() {
160 if (value != null)
161 return value.keys();
162 else
163 return null;
164 }
165
166 /**
167 * Get the default response for this question.
168 * @return the default response for this question.
169 *
170 * @see #setDefaultValue
171 */
172 public Properties getDefaultValue() {
173 return defaultValue;
174 }
175
176 /**
177 * Set the default response for this question,
178 * used by the clear method.
179 * @param props the default response for this question.
199 }
200
201 /**
202 * Verify this question is on the current path, and if it is,
203 * return the current value.
204 * @return the current value of this question
205 * @throws Interview.NotOnPathFault if this question is not on the
206 * current path
207 * @see #getValue
208 */
209 public Properties getValueOnPath() throws Interview.NotOnPathFault {
210 interview.verifyPathContains(this);
211 return getValue();
212 }
213
214 public String getStringValue() {
215 StringBuffer result = new StringBuffer();
216 if (value != null) {
217 String sep = System.getProperty("line.separator");
218
219 SortedSet<String> names = new TreeSet<>(value.stringPropertyNames());
220 for (String key : names) {
221 result.append(key);
222 result.append("=");
223 result.append(value.getProperty(key));
224 result.append(sep);
225 }
226 }
227
228 return result.toString();
229 }
230
231 /**
232 * Set the current value.
233 * @param newValue Value represented as a single string. May not be null. May be
234 * an empty string.
235 * @see #getValue
236 */
237 public void setValue(String newValue) {
238 if (value == null || value.size() == 0)
239 return;
240
300 String o = data.get(tag);
301 if (o != null) {
302 setValue(load(o));
303 }
304 }
305
306 protected static Properties load(String s) {
307 Properties2 p2 = new Properties2();
308
309 try {
310 p2.load(new StringReader(s));
311 } catch (IOException e) {
312 //e.printStackTrace();
313 // what to do?! source should be really stable since it is a
314 // String
315 }
316
317 // repopulate a J2SE properties object
318 Properties p = new Properties();
319
320 Enumeration<?> e = p2.propertyNames();
321 while(e.hasMoreElements()) {
322 Object next = e.nextElement();
323 p.put( next, p2.get(next) );
324 } // while
325
326 return p;
327 }
328
329 /**
330 * Save the value for this question in a dictionary, using
331 * the tag as the key.
332 * @param data The map in which to save the value for this question.
333 */
334 protected void save(Map<String, String> data) {
335 if (value == null)
336 return;
337
338 Properties2 p2 = new Properties2();
339 p2.load(value);
340 StringWriter sw = new StringWriter();
391 ValueConstraints c = getConstraints(key);
392 if (c == null || c.isVisible())
393 return true;
394 else
395 return false;
396 }
397
398 /**
399 * Get the keys which are currently invalid and blocking the question
400 * (getNext() returning null). It is recommended but not required that
401 * this method return null if the question is not blocked (getNext() !=
402 * null). This default implementation of this method is to check any
403 * ValueConstraint objects for each key and return those results. If you
404 * override this method, it is highly recommended that you allow this to
405 * take place, then add in any additional checking to the results provided
406 * by this base implementation.
407 * @return Invalid key in index zero, <em>localized</em> explanation
408 * in index one. Null means there are no invalid keys.
409 */
410 public String[][] getInvalidKeys() {
411 Enumeration<?> names = value.propertyNames();
412 List<String> badKeys = new ArrayList<>();
413 List<String> reasons = new ArrayList<>();
414
415 while (names.hasMoreElements()) {
416 String curr = (String)(names.nextElement());
417 ValueConstraints rules = getConstraints(curr);
418
419 if (rules == null) {
420 continue; // no checks, next key
421 }
422 else {
423 String reason = rules.isValid(value.getProperty(curr));
424 if (reason != null) {
425 badKeys.add(curr);
426 reasons.add(reason);
427 }
428 }
429 }
430
431 // repack data for return
670 for(int i = 0; it.hasNext(); i++) {
671 data[i][0] = it.next();
672 data[i][1] = (String)(value.get(data[i][0]));
673 } // for
674
675 return data;
676 }
677 }
678
679 /**
680 * @return The keys and values which are not allocated to any group.
681 * Null if there are no ungrouped values.
682 * @see #getGroup
683 * @see #setGroup
684 */
685 public String[][] getUngrouped() {
686 if (value == null || value.size() == 0)
687 return null;
688
689 if (keyGroups != null) {
690 Set<String> keys = keyGroups.keySet();
691 if (keys != null) {
692 String[] gps = getGroups();
693 Properties copy = (Properties)(value.clone());
694
695 // remove all grouped entries from the copied
696 // question value
697 for (int i = 0; i < gps.length; i++) {
698 String[][] vals = getGroup(gps[i]);
699
700 for (int j = 0; j < vals.length; j++)
701 copy.remove(vals[j][0]);
702 }
703
704 if (copy.size() > 0) {
705 Set<String> en = copy.stringPropertyNames();
706 String[][] ret = new String[copy.size()][2];
707 int i = 0;
708 for (String key : en) {
709 ret[i][0] = key;
710 ret[i][1] = copy.getProperty(key);
711 i++;
712 } // while
713
714 return ret;
715 }
716 else
717 return null;
718 }
719 }
720 // no groups, return the entire value set
721 String[][] ret = new String[value.size()][2];
722 Enumeration<?> en = value.propertyNames();
723 int i = 0;
724
725 while (en.hasMoreElements()) {
726 String key = (String)(en.nextElement());
727 ret[i][0] = key;
728 ret[i][1] = value.getProperty(key);
729 i++;
730 } // while
731
732 return ret; // no groups in use
733 }
734
735 // ------------ PRESENTATION ---------------
736
737 /**
738 * Get the display (localized) name of the group.
739 * The resource necessary is the question tag, with the group name and ".group"
740 * appended. That is <code>jck.qTable.basic.group</code> and
741 * <code>jck.qTable.advanced.group</code>.
742 * @param group The internal group name, as is used in the rest of this API.
|