/** * @return Locale-specific sample input string which meets datatype criteria for node. Used for * error reporting. */ String getSampleInputString() { /* Create the help-string showing allowable range of input values. Can be re-created (e.g. if range dynamically changes */ String min = null; String max = null; String other = null; String rangeStr = null; String s = null; s = Datum.getExampleFormatStr(triceps, mask, datumType); if (!(s == null || s.equals(""))) { rangeStr = " (e.g. " + s + ")"; } if (answerType == PASSWORD) { return ""; } if (minDatum == null && maxDatum == null && allowableDatumValues == null && pattern == null && rangeStr != null) { return rangeStr; } if (minDatum != null) { setMinDatum(minDatum); min = minDatum.stringVal(true, mask); } if (maxDatum != null) { setMaxDatum(maxDatum); max = maxDatum.stringVal(true, mask); } if (allowableDatumValues != null) { other = buildOrList(allowableDatumValues); } if (minDatum != null && maxDatum != null) { if ((new DatumMath()).lt(maxDatum, minDatum).booleanVal()) { setError(triceps.get("max_less_than_min") + "(" + minStr + " - " + maxStr + ")"); } } rangeStr = "(" + ((min != null) ? min : "") + " - " + ((max != null) ? max : "") + ")"; if (other != null) { rangeStr = " [" + rangeStr + other + "]"; } if (pattern != null) { rangeStr = "(e.g. m/" + pattern + "/"; } if (!rangeStr.equals("( - )")) { return " " + rangeStr; } return ""; }
/** * Helper function to build OR list of data values * * @param v vector of Nodes */ private String buildOrList(Vector v) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < v.size(); ++i) { Datum d = (Datum) v.elementAt(i); sb.append("," + ((i == v.size() - 1) ? (" " + triceps.get("or")) : "") + " " + d.stringVal()); } return sb.toString(); }
void setMaxDatum(Datum d) { if (d == null) { maxDatum = null; } else { maxDatum = d.cast(datumType, mask); } }
void setDatumType(int type) { if (Datum.isValidType(type)) { datumType = type; } else { datumType = Datum.INVALID; } }
/** @return false if the selected value violates the validation criteria */ boolean isWithinRange(Datum d) { boolean err = false; if (minDatum != null) { if (!(new DatumMath()).ge(d, minDatum).booleanVal()) { err = true; } } if (maxDatum != null) { if (!(new DatumMath()).le(d, maxDatum).booleanVal()) { err = true; } } if (err && allowableDatumValues != null) { /* then not within valid range - so check if it is an outlying, but allowable value */ for (int i = 0; i < allowableDatumValues.size(); ++i) { if ((new DatumMath()).eq(d, (Datum) allowableDatumValues.elementAt(i)).booleanVal()) { err = false; break; } } } if (pattern != null) { if (!Pattern.matches(pattern, d.stringVal())) { err = true; } } if (err) { if (answerType == PASSWORD) { setError(triceps.get("incorrect_password")); } else { setError( triceps.get("please_enter_a") + Datum.getTypeName(triceps, datumType) + triceps.get("in_the_range") + getSampleInputString()); } } return !(err); }
public String getLocalizedAnswer(Datum datum) { int num_choices = numAnswerChoices(); String answer = ""; if (num_choices > 0) { Vector choices = getAnswerChoices(); if (datum.isSpecial()) { answer = datum.toString(); } else { String s = datum.stringVal(); for (int j = 0; j < choices.size(); ++j) { AnswerChoice ac = (AnswerChoice) choices.elementAt(j); if (ac.getValue().equals(s)) { answer = ac.getMessage(); } } } } else { answer = triceps.toString(this, true); } return answer; }
/** * Create HTML input field for this node, given its currently selected value and possible error * messages * * @param datum the value * @param errMsg optional error messages * @param autogen whether to auto-number the options * @return HTML fragment */ String prepareChoicesAsHTML(Datum datum, String errMsg, boolean autogen) { /* errMsg is a hack - only applies to RADIO_HORIZONTAL */ StringBuffer sb = new StringBuffer(); String defaultValue = ""; AnswerChoice ac; Enumeration ans = null; Vector v = null; switch (answerType) { case RADIO: // will store integers ans = getAnswerChoices().elements(); while (ans.hasMoreElements()) { // for however many radio buttons there are ac = (AnswerChoice) ans.nextElement(); ac.parse(triceps); sb.append( "<input type='radio' name='" + getLocalName() + "' id ='" + getLocalName() + "' value='" + ac.getValue() + "'" + (isSelected(datum, ac) ? " checked " : " ") + ">" + ac.getMessage() + "<br>"); } break; case RADIO_HORIZONTAL: { // will store integers /* table underneath questions */ v = getAnswerChoices(); ans = v.elements(); int count = v.size(); if (count > 0) { Double pct = new Double(100. / (double) count); sb.append("<table cellpadding='0' cellspacing='1' border='1' width='100%'>"); sb.append("<tr>"); while (ans.hasMoreElements()) { // for however many radio buttons there are ac = (AnswerChoice) ans.nextElement(); ac.parse(triceps); sb.append("<td valign='top' width='" + pct.toString() + "%'>"); sb.append( "<input type='radio' name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + ac.getValue() + "'" + (isSelected(datum, ac) ? " checked " : " ") + ">" + ac.getMessage()); sb.append("</td>"); } sb.append("</tr>"); sb.append("</table>"); } } break; case RADIO_HORIZONTAL2: { /* table underneath questions */ v = getAnswerChoices(); ans = v.elements(); int count = v.size(); int max_width = Integer.parseInt( triceps.getSchedule().getReserved(Schedule.ANSWER_OPTION_FIELD_WIDTH)); if (count > 0) { Double pct = new Double((double) max_width / (double) count); sb.append( "<table cellpadding='0' cellspacing='1' border='1' width='100%'>"); // oddly, 100% // means all of // the enclosing // <td>, but for // embedded // <td>s, need // actual // percent of // top-level // table! sb.append("<tr>"); while (ans.hasMoreElements()) { // for however many radio buttons there are ac = (AnswerChoice) ans.nextElement(); ac.parse(triceps); sb.append("<td valign='top' width='" + pct.toString() + "%'>"); sb.append( "<input type='radio' name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + ac.getValue() + "'" + (isSelected(datum, ac) ? " checked " : " ") + ">" + ac.getMessage()); sb.append("</td>"); } sb.append("</tr>"); sb.append("</table>"); } } break; case CHECK: ans = getAnswerChoices().elements(); while (ans.hasMoreElements()) { // for however many radio buttons there are ac = (AnswerChoice) ans.nextElement(); ac.parse(triceps); sb.append( "<input type='checkbox' name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + ac.getValue() + "'" + (isSelected(datum, ac) ? " checked " : " ") + ">" + ac.getMessage() + "<br>"); } break; case COMBO: // stores integers as value case COMBO2: case LIST2: case LIST: { StringBuffer choices = new StringBuffer(); ans = getAnswerChoices().elements(); int optionNum = 0; int totalLines = 0; boolean nothingSelected = true; while (ans.hasMoreElements()) { // for however many radio buttons there are ac = (AnswerChoice) ans.nextElement(); ac.parse(triceps); ++optionNum; String messageStr = ac.getMessage(); String prefix = "<option value='" + ac.getValue() + "'"; boolean selected = isSelected(datum, ac); if (selected) { nothingSelected = false; } int max_text_len = Integer.parseInt( triceps.getSchedule().getReserved(Schedule.MAX_TEXT_LEN_FOR_COMBO)); v = subdivideMessage(messageStr, max_text_len); for (int i = 0; i < v.size(); ++i) { choices.append(prefix); if (i == 0 && selected) { choices.append(" selected"); } choices.append(">"); if (i == 0) { // show selection number if (answerType == COMBO || answerType == LIST) { choices.append((autogen) ? String.valueOf(optionNum) : ac.getValue()); choices.append(") "); } } else { // indent to indicate that same as previous choices.append(" "); } choices.append((String) v.elementAt(i)); choices.append("</option>"); } totalLines += v.size(); } sb.append( "<select name='" + getLocalName() + "' id='" + getLocalName() + "' " + ((answerType == LIST || answerType == LIST2) ? (" size = '" + Math.min(MAX_ITEMS_IN_LIST, totalLines + 1) + "' ") : " ") + ">"); sb.append( "<option value=''" + ((nothingSelected) ? " selected" : "") + ">" + // so that focus is properly shifted on List box triceps.get("select_one_of_the_following") + "</option>"); // first choice is empty sb.append(choices); sb.append("</select>"); } break; case TEXT: // stores Text type if (datum != null && datum.exists()) { defaultValue = datum.stringVal(); } sb.append( "<input type='text' " + " name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + (new XMLAttrEncoder()).encode(defaultValue) + "'>"); break; case MEMO: if (datum != null && datum.exists()) { defaultValue = datum.stringVal(); } sb.append( "<textarea rows='5'" + " name='" + getLocalName() + "' id='" + getLocalName() + "'>" + (new XMLAttrEncoder()).encode(defaultValue) + "</textarea>"); break; case PASSWORD: // stores Text type if (datum != null && datum.exists()) { defaultValue = datum.stringVal(); } sb.append( "<input type='password'" + " name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + (new XMLAttrEncoder()).encode(defaultValue) + "'>"); break; case DOUBLE: // stores Double type if (datum != null && datum.exists()) { defaultValue = datum.stringVal(); } sb.append( "<input type='text'" + " name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + defaultValue + "'>"); break; default: /* case DATE: case TIME: case YEAR: case MONTH: case DAY: case WEEKDAY: case HOUR: case MINUTE: case SECOND: case MONTH_NUM: case DAY_NUM: */ if (datum != null && datum.exists()) { defaultValue = datum.stringVal(); } sb.append( "<input type='text'" + " name='" + getLocalName() + "' id='" + getLocalName() + "' value='" + defaultValue + "'>"); break; case NOTHING: sb.append(" "); break; } return sb.toString(); }
/** * Helper function to parse the Question or Eval field, which also includes optional validation * criteria */ private void parseQuestionOrEvalTypeField() { StringTokenizer ans; int z; if (questionOrEvalTypeField == null) { if (AUTHORABLE) { setParseError(triceps.get("questionOrEvalTypeField_must_exist")); } else { setParseError("syntax error"); } return; } ans = new StringTokenizer(questionOrEvalTypeField, ";", true); // return ';' tokens too for (int field = 0; ans.hasMoreTokens(); ) { String s = null; s = ans.nextToken(); if (";".equals(s)) { ++field; continue; } switch (field) { case 0: questionOrEvalTypeStr = s; for (z = 0; z < ACTION_TYPES.length; ++z) { if (questionOrEvalTypeStr.equalsIgnoreCase(ACTION_TYPES[z])) { questionOrEvalType = z; break; } } break; case 1: datumTypeStr = s; datumType = Datum.parseDatumType(s); if (datumType == -1) { if (AUTHORABLE) { setParseError(triceps.get("invalid_dataType") + datumTypeStr); } else { setParseError("syntax error"); } datumType = Datum.INVALID; } break; case 2: minStr = s; break; case 3: maxStr = s; break; case 4: /* FIXME: HACK -- does double duty -- either a formatting mask, OR a regex input mask */ if (s == null || s.trim().length() == 0 || !s.startsWith("PERL5")) { mask = s; pattern = null; } else { pattern = s.substring("PERL5".length()); try { Pattern.compile(pattern); } catch (PatternSyntaxException ex) { setParseError( "Invalid Regular Expression Pattern " + pattern + " " + ex.getMessage()); } } break; default: /* extra parameters are additional allowable values, as Strings that will be parsed */ if (allowableValues == null) { allowableValues = new Vector(); } allowableValues.addElement(s); break; } } }