0001: package com.salmonllc.html;
0002:
0003: import java.io.ByteArrayOutputStream;
0004: import java.io.PrintWriter;
0005: import java.io.Serializable;
0006: import java.util.Calendar;
0007: import java.util.Date;
0008: import java.util.GregorianCalendar;
0009: import java.util.Hashtable;
0010: import java.util.Vector;
0011:
0012: import com.salmonllc.html.events.SubmitEvent;
0013: import com.salmonllc.html.events.SubmitListener;
0014: import com.salmonllc.html.events.ValidateEvent;
0015: import com.salmonllc.html.events.ValidateListener;
0016: import com.salmonllc.html.events.ValueChangedEvent;
0017: import com.salmonllc.html.events.ValueChangedListener;
0018: import com.salmonllc.jsp.JspController;
0019: import com.salmonllc.jsp.JspDataTable;
0020: import com.salmonllc.jsp.JspLink;
0021: import com.salmonllc.jsp.JspContainer;
0022: import com.salmonllc.localizer.LanguageResourceFinder;
0023: import com.salmonllc.properties.Props;
0024: import com.salmonllc.sql.DataStoreBuffer;
0025: import com.salmonllc.sql.DataStoreEvaluator;
0026: import com.salmonllc.sql.DataStoreException;
0027: import com.salmonllc.sql.DataStoreExpression;
0028: import com.salmonllc.sql.ValidationRule;
0029: import com.salmonllc.util.MessageLog;
0030: import com.salmonllc.util.RegularExpressionMatcher;
0031: import com.salmonllc.util.VectorSort;
0032:
0033: /**
0034: * This is a special type of text component used in conjunction with the
0035: * HtmlComponentValidator to perform validations and display an error message.
0036: */
0037: public class HtmlValidatorText extends HtmlComponent implements
0038: SubmitListener, ValueChangedListener {
0039:
0040: private HtmlComponentValidator _val;
0041: private Hashtable _valueChangedItems;
0042: private Hashtable _ruleIndexes;
0043: private int _ruleNo;
0044: private DataStoreBuffer _ds;
0045: private String _font;
0046: private String _fontStartTag;
0047: private String _fontEndTag;
0048: private String _theme;
0049: private int _breaksBefore, _breaksAfter;
0050: private int _breaksBetween = 1;
0051: private ErrorEntries _errorEntries = new ErrorEntries();
0052: private String _dbProfile;
0053: private boolean _valOk;
0054: private boolean _validateNewRows = true;
0055: private boolean _autoPopulateLookups = false;
0056: private Vector _submitComponents;
0057: private boolean _fixSpecialHtml = true;
0058: private boolean _multipleErrorsOK = false;
0059: private float _nextSeq;
0060: private Vector _listeners;
0061: private DataStoreEvaluator _skipRowExp;
0062: private boolean _doSetFocus = true;
0063:
0064: private boolean _javaScriptRules = false;
0065: private boolean _regExpressionRules = false;
0066: private boolean _reqRules = false;
0067: private boolean _rangeRules = false;
0068:
0069: private boolean _useAlertsForErrors = false;
0070: private boolean _addFocusLinksToErrors = true;
0071: private boolean _useJavaScriptForRegExpRules = false;
0072: private boolean _useJavaScriptForReqRules = false;
0073: private boolean _useJavaScriptForRangeRules = false;
0074: //fc 06/11/04: Add this variable to indicate whether Javascript rules
0075: // should be validated on the client side only.
0076: // A value true means client side only validation for javascript enabled
0077: // validations otherwise validation occurs on both
0078: // client and server side which is the default.
0079: private boolean _useJavaScriptForValidationOnly = false;
0080: private HtmlComponent _extraComponent = null;
0081: private boolean _errorOnLastPass = false;
0082:
0083: private class ErrorEntry implements Serializable {
0084: String error;
0085: HtmlFormComponent comp;
0086: HtmlComponent extraDisplay;
0087: int row;
0088: float seq;
0089: }
0090:
0091: private class ErrorEntries extends VectorSort {
0092: public boolean compare(Object o1, Object o2) {
0093: ErrorEntry e1 = (ErrorEntry) o1;
0094: ErrorEntry e2 = (ErrorEntry) o2;
0095: float e1Val = (e1.row * 1000000) + e1.seq;
0096: float e2Val = (e2.row * 1000000) + e2.seq;
0097: return e1Val < e2Val;
0098: }
0099:
0100: public ErrorEntry getEntry(int row) {
0101: return (ErrorEntry) elementAt(row);
0102: }
0103: }
0104:
0105: /**
0106: * Constructs a new validator
0107: */
0108: public HtmlValidatorText(String name, String font, HtmlPage p,
0109: String theme) {
0110: super (name, p);
0111: if (_font == null)
0112: _font = HtmlText.FONT_ERROR;
0113: _font = font;
0114: setTheme(theme);
0115: _ruleNo = -1;
0116: }
0117:
0118: /**
0119: * Constructs a new validator
0120: */
0121: public HtmlValidatorText(String name, String font, HtmlPage p) {
0122: this (name, font, p, null);
0123: }
0124:
0125: /**
0126: * Constructs a new validator
0127: */
0128: public HtmlValidatorText(String name, HtmlPage p) {
0129: this (name, null, p, null);
0130: }
0131:
0132: /**
0133: * This method implements the SubmitListener interface and is used for the
0134: * internal operation of the component. It should not be called directly
0135: */
0136: public boolean submitPerformed(SubmitEvent e) throws Exception {
0137: if (_ds != null) {
0138: HtmlComponentValidator val = getValidator();
0139: val.reset();
0140: for (int i = 0; i < _ds.getRowCount(); i++) {
0141: if (_skipRowExp != null) {
0142: Object o = _skipRowExp.evaluateRow(i);
0143: if (o instanceof Boolean) {
0144: if (((Boolean) o).booleanValue())
0145: continue;
0146: }
0147: }
0148: int rowStat = _ds.getRowStatus(i);
0149: if (rowStat == DataStoreBuffer.STATUS_MODIFIED
0150: || rowStat == DataStoreBuffer.STATUS_NEW_MODIFIED
0151: || (_validateNewRows && rowStat == DataStoreBuffer.STATUS_NEW)
0152: || _ds.getBucketsModified(i)) {
0153: while (val.findNextError(i)) {
0154: HtmlFormComponent comp = val
0155: .getErrorComponent();
0156: String format = null;
0157: String value = "";
0158: int ruleNo = ((Integer) _ruleIndexes
0159: .get(new Integer(val.getCurrentRule())))
0160: .intValue();
0161: String error = val.getErrorMessage();
0162: if (comp != null) {
0163: int col = comp.getColumnNumber();
0164: if (col > -1) {
0165: value = val.getDataStoreBuffer()
0166: .getFormattedString(i, col);
0167: format = val.getDataStoreBuffer()
0168: .getFormat(col);
0169: }
0170: error = processErrorMessage(error, value,
0171: format);
0172: }
0173: addErrorMessage(error, comp, i, ruleNo);
0174: _valOk = false;
0175: }
0176: if (_listeners != null) {
0177: ValidateEvent evt = new ValidateEvent(
0178: getPage(), this , getName(),
0179: getFullName(), _ds, i);
0180: for (int j = 0; j < _listeners.size(); j++)
0181: ((ValidateListener) _listeners.elementAt(j))
0182: .validate(evt);
0183: }
0184: }
0185: }
0186:
0187: if (!_valOk) {
0188: if (!_multipleErrorsOK)
0189: _errorEntries.setSize(1);
0190: }
0191: }
0192:
0193: if (_listeners != null) {
0194: ValidateEvent evt = new ValidateEvent(getPage(), this ,
0195: getName(), getFullName(), _ds);
0196: for (int i = 0; i < _listeners.size(); i++)
0197: ((ValidateListener) _listeners.elementAt(i))
0198: .validateComplete(evt);
0199: }
0200: if (!_valOk) {
0201: e.setValidationFailed(true);
0202: HtmlFormComponent comp = _errorEntries.getEntry(0).comp;
0203: if (comp != null) {
0204: int row = _errorEntries.getEntry(0).row;
0205: if (_doSetFocus) {
0206: _ds.gotoRow(row);
0207: if (scrollToDataTableRow(comp, row))
0208: comp.setFocus(row);
0209: else
0210: comp.setFocus();
0211: }
0212: }
0213: if (e.getNextListener() instanceof HtmlValidatorText)
0214: return true;
0215: }
0216: return !e.isValidationFailed();
0217: }
0218:
0219: /**
0220: * This method implements the ValueChangedListener interface and is used for
0221: * the internal operation of the component. It should not be called directly
0222: */
0223: public boolean valueChanged(ValueChangedEvent e) throws Exception {
0224: HtmlComponent comp = e.getSubmitComponent();
0225: if (_submitComponents != null && comp != null) {
0226: boolean doProcess = false;
0227: for (int i = 0; i < _submitComponents.size(); i++) {
0228: if (_submitComponents.elementAt(i) == comp) {
0229: doProcess = true;
0230: break;
0231: }
0232: }
0233: if (!doProcess)
0234: return true;
0235: }
0236:
0237: HtmlFormComponent src = (HtmlFormComponent) e.getComponent();
0238: DataStoreBuffer ds = e.getDataStore();
0239: if (ds != null) {
0240: if (!ds.isFormattedStringValid(e.getColumn(), e
0241: .getNewValue())) {
0242: String error = (String) getValueChangedItems().get(src);
0243: String format = e.getDataStore().getFormat(
0244: e.getColumn());
0245: int ruleNo = ((Integer) (_ruleIndexes.get(src)))
0246: .intValue();
0247: if (error != null) {
0248: e
0249: .setAcceptValue(ValueChangedEvent.PROCESSING_KEEP_CHANGE_IN_QUEUE);
0250: addErrorMessage(processErrorMessage(error, e
0251: .getNewValue(), format), src, e.getRow(),
0252: ruleNo);
0253: _valOk = false;
0254: }
0255: }
0256: }
0257: return true;
0258: }
0259:
0260: /**
0261: * @see com.salmonllc.html.HtmlComponent#generateHTML(PrintWriter, int)
0262: */
0263: public void generateHTML(PrintWriter p, int rowNo) throws Exception {
0264:
0265: boolean displaySomething = true;
0266: if (!getVisible())
0267: displaySomething = false;
0268: if (_errorEntries.size() == 0)
0269: displaySomething = false;
0270:
0271: if (getUseJavaScript())
0272: p.println(generateValidationJavaScript());
0273:
0274: p.print("<DIV id=\"div" + getFullName() + "\">");
0275: if (displaySomething) {
0276: StringBuffer out = new StringBuffer();
0277: _errorEntries.sort();
0278: HtmlFormComponent comp = _errorEntries.getEntry(0).comp;
0279:
0280: if (_useAlertsForErrors) {
0281: String msg = _errorEntries.getEntry(0).error;
0282: StringBuffer script = new StringBuffer();
0283: script.append("var theFocus=null;\r\n");
0284:
0285: if (comp != null) {
0286: if (isInDataTableHeaderOrFooter(comp)) {
0287: generateJavaScriptForComponentByName(comp, comp
0288: .getFullName(), comp
0289: .getJavaScriptName(), msg, script,
0290: "true", null);
0291: } else if (isInDataTable(comp)) {
0292: int row = _errorEntries.getEntry(0).row;
0293: generateJavaScriptForComponentByName(comp, comp
0294: .getFullName()
0295: + "_" + row, comp.getJavaScriptName(),
0296: msg, script, "true", null);
0297: } else {
0298: generateJavaScriptForComponentByName(comp, comp
0299: .getFullName(), comp
0300: .getJavaScriptName(), msg, script,
0301: "true", null);
0302: }
0303: } else {
0304: script.append("var theMessage='" + msg + "';\r\n");
0305:
0306: }
0307: //getPage().writeScript("alert('" + escapeSingleQuote(msg) +
0308: // "');");
0309: script.append(" alert(theMessage);\r\n");
0310: script.append("if (theFocus != null) {\r\n");
0311: script.append(" theFocus.focus(); \r\n");
0312: script.append(" }\r\n");
0313: getPage().writeScript(script.toString());
0314: } else {
0315: for (int i = 0; i < _errorEntries.size(); i++) {
0316: String msg = _errorEntries.getEntry(i).error;
0317: if (_fixSpecialHtml)
0318: msg = fixSpecialHTMLCharacters(msg);
0319: boolean addLink = (_errorEntries.getEntry(i).comp != null && _addFocusLinksToErrors);
0320: if (addLink) {
0321: out.append("<a href=\"javascript:");
0322:
0323: if (isInDataTableHeaderOrFooter(comp)) {
0324: out.append(_errorEntries.getEntry(i).comp
0325: .getJavaScriptName());
0326: out.append(".focus();\">");
0327: } else {
0328: if (isInDataTable(comp)) {
0329: int row = _errorEntries.getEntry(i).row;
0330: if (isDataRowOnPage(comp, row)) {
0331: out.append(_errorEntries
0332: .getEntry(i).comp
0333: .getJavaScriptName());
0334: out.append("_");
0335: out.append(new Integer(row)
0336: .toString());
0337: out.append(".focus();\">");
0338: } else {
0339: out
0340: .append("scrollTo"
0341: + getFullName()
0342: + "('"
0343: + getDataTableNameForComp(comp)
0344: + "',"
0345: + row
0346: + ",'"
0347: + _errorEntries
0348: .getEntry(i).comp
0349: .getName()
0350: + "'" + ");\">");
0351: }
0352: } else {
0353: out
0354: .append(_errorEntries
0355: .getEntry(i).comp
0356: .getJavaScriptName());
0357: out.append(".focus();\">");
0358: }
0359: }
0360: }
0361:
0362: if (_fontStartTag != null)
0363: out.append(_fontStartTag);
0364:
0365: out.append(msg);
0366:
0367: if (_errorEntries.getEntry(i).extraDisplay != null) {
0368: _extraComponent = _errorEntries.getEntry(i).extraDisplay;
0369: ByteArrayOutputStream bout = new ByteArrayOutputStream();
0370: PrintWriter pout = new PrintWriter(bout);
0371: _extraComponent.generateHTML(pout, -1);
0372: pout.flush();
0373: out.append(bout.toString());
0374: pout.close();
0375: } else
0376: _extraComponent = null;
0377:
0378: if (_fontEndTag != null)
0379: out.append(_fontEndTag);
0380:
0381: if (addLink)
0382: out.append("</a>");
0383:
0384: if (i < (_errorEntries.size() - 1)) {
0385: for (int j = 0; j < _breaksBetween; j++)
0386: out.append("<BR>");
0387: }
0388: }
0389:
0390: for (int i = 0; i < _breaksBefore; i++)
0391: p.println("<BR>");
0392:
0393: p.print(out.toString());
0394:
0395: for (int i = 0; i < _breaksAfter; i++)
0396: p.println("<BR>");
0397:
0398: if (_addFocusLinksToErrors) {
0399: p
0400: .println("<INPUT type=\"hidden\" name=\""
0401: + getFullName()
0402: + "dataTable\" value=\"\">");
0403: p.println("<INPUT type=\"hidden\" name=\""
0404: + getFullName()
0405: + "dataTableRow\" value=\"-1\">");
0406: p
0407: .println("<INPUT type=\"hidden\" name=\""
0408: + getFullName()
0409: + "focusComp\" value=\"\">");
0410: p.println("<script language=\"javascript\">");
0411: p.println("function scrollTo" + getFullName()
0412: + "(tableName, row, focusComp){");
0413: p.println(" " + getFormString() + getFullName()
0414: + "dataTable.value=tableName;");
0415: p.println(" " + getFormString() + getFullName()
0416: + "dataTableRow.value=row;");
0417: p.println(" " + getFormString() + getFullName()
0418: + "focusComp.value=focusComp;");
0419: p.println(" " + getFormString() + "submit();");
0420: p.println("}");
0421: p.println("</script>");
0422: }
0423: }
0424: }
0425:
0426: p.println("</DIV>");
0427:
0428: _errorEntries.removeAllElements();
0429: _doSetFocus = true;
0430: _errorOnLastPass = displaySomething;
0431:
0432: }
0433:
0434: /**
0435: * This method sets the property theme for the component.
0436: *
0437: * @param theme
0438: * The theme to use.
0439: */
0440: public void setTheme(String theme) {
0441: Props props = getPage().getPageProperties();
0442:
0443: if (_font == null) {
0444: _fontStartTag = props.getThemeProperty(theme,
0445: HtmlText.FONT_ERROR + Props.TAG_START);
0446: _fontEndTag = props.getThemeProperty(theme,
0447: HtmlText.FONT_ERROR + Props.TAG_END);
0448: } else {
0449: _fontStartTag = props.getThemeProperty(theme, _font
0450: + Props.TAG_START);
0451: _fontEndTag = props.getThemeProperty(theme, _font
0452: + Props.TAG_END);
0453: }
0454:
0455: _theme = theme;
0456: }
0457:
0458: /**
0459: * Returns the number of line breaks to generate after the error text is
0460: * displayed.
0461: *
0462: * @return int
0463: */
0464: public int getBreaksAfter() {
0465: return _breaksAfter;
0466: }
0467:
0468: /**
0469: * Returns the number of line breaks to generate before the error text is
0470: * displayed.
0471: *
0472: * @return int
0473: */
0474: public int getBreaksBefore() {
0475: return _breaksBefore;
0476: }
0477:
0478: /**
0479: * Returns the number of line breaks between error messages if multiple are
0480: * displayed
0481: *
0482: * @return int
0483: */
0484: public int getBreaksBetween() {
0485: return _breaksBetween;
0486: }
0487:
0488: /**
0489: * Returns the DataStore validated by the validator
0490: *
0491: * @return DataStore
0492: */
0493: public DataStoreBuffer getDataStore() {
0494: return _ds;
0495: }
0496:
0497: /**
0498: * Returns the Font used to display the error message
0499: *
0500: * @return String
0501: */
0502: public String getFont() {
0503: return _font;
0504: }
0505:
0506: /**
0507: * Sets the number of line breaks to generate after the error text is
0508: * displayed.
0509: */
0510: public void setBreaksAfter(int breaksAfter) {
0511: _breaksAfter = breaksAfter;
0512: }
0513:
0514: /**
0515: * Sets the number of line breaks to generate before the error text is
0516: * displayed.
0517: */
0518: public void setBreaksBefore(int breaksBefore) {
0519: _breaksBefore = breaksBefore;
0520: }
0521:
0522: /**
0523: * Sets the number of line breaks between error messages if multiple are
0524: * displayed
0525: */
0526: public void setBreaksBetween(int breaksBetween) {
0527: _breaksBetween = breaksBetween;
0528: }
0529:
0530: /**
0531: * Sets the DataStore validated by the validator.
0532: */
0533: public void setDataStore(DataStoreBuffer ds) {
0534: _ds = ds;
0535: }
0536:
0537: /**
0538: * Sets the error message will display in.
0539: */
0540: public void setFont(String font) {
0541: _font = font;
0542: if (font == null)
0543: _font = HtmlText.FONT_ERROR;
0544: setTheme(_theme);
0545: }
0546:
0547: /**
0548: * Adds a type check rule to the validator. This makes sure that the value
0549: * in the component is the correct type for the datastore column it is bound
0550: * to.
0551: *
0552: * @param comp
0553: * The component to check
0554: * @param errorMessage
0555: * The error message to display if the validation fails. It can
0556: * have a %VALUE% token embedded in it to include the value of
0557: * the column in error in the message
0558: * @param localizationKey
0559: * For internationalization, the key value used to look up the
0560: * error message for the usesr language (may be null)
0561: */
0562: public void addTypeCheckRule(HtmlFormComponent comp,
0563: String errorMessage, String localizationKey)
0564: throws DataStoreException {
0565: if (comp == null)
0566: throw new DataStoreException(
0567: "Error. Component may not be null");
0568: comp.addValueChangedListener(this );
0569: getValueChangedItems().put(comp,
0570: computeErrorMessage(errorMessage, localizationKey));
0571: indexTypeCheckRule(comp);
0572: }
0573:
0574: /**
0575: * Adds a type check rule to the validator. This makes sure that the value
0576: * in the component is the correct type for the datastore column it is bound
0577: * to.
0578: *
0579: * @param comp
0580: * The component to check
0581: * @param errorMessage
0582: * The error message to display if the validation fails
0583: */
0584: public void addTypeCheckRule(HtmlFormComponent comp,
0585: String errorMessage) throws DataStoreException {
0586: this .addTypeCheckRule(comp, errorMessage, null);
0587: }
0588:
0589: /**
0590: * Adds a required rule to the validator. This makes sure that the value in
0591: * the component is entered by the user
0592: *
0593: * @param focusComp
0594: * The component to check
0595: * @param errorMessage
0596: * The error message to display if the validation fails
0597: * @param localizationKey
0598: * For internationalization, the key value used to look up the
0599: * error message for the usesr language (may be null)
0600: */
0601: public void addRequiredRule(HtmlFormComponent focusComp,
0602: String errorMessage, String localizationKey)
0603: throws DataStoreException {
0604: _reqRules = true;
0605: HtmlComponentValidator val = getValidator();
0606: String name = focusComp.getFullName();
0607: if (_ds != null)
0608: name = _ds.getColumnName(focusComp.getColumnNumber());
0609: val.addRequiredRule(name, computeErrorMessage(errorMessage,
0610: localizationKey), focusComp);
0611: indexOtherRule();
0612: }
0613:
0614: /**
0615: * Adds a required rule to the validator. This makes sure that the value in
0616: * the component is entered by the user
0617: *
0618: * @param focusComp
0619: * The component to check
0620: * @param errorMessage
0621: * The error message to display if the validation fails
0622: * @param localizationKey
0623: * For internationalization, the key value used to look up the
0624: * error message for the usesr language (may be null)
0625: */
0626: public void addRequiredRule(HtmlFormComponent focusComp,
0627: String errorMessage) throws DataStoreException {
0628: _reqRules = true;
0629: HtmlComponentValidator val = getValidator();
0630: String name = focusComp.getFullName();
0631: if (_ds != null)
0632: name = _ds.getColumnName(focusComp.getColumnNumber());
0633: val.addRequiredRule(name, errorMessage, focusComp);
0634: indexOtherRule();
0635: }
0636:
0637: /**
0638: * Adds a javascript rule to the validator. The rule can be any javascript
0639: * that returns a boolean value (true means the validation succeeded and
0640: * false means it failed). This rule is only executed on the client browser
0641: * and only if the validator is set to use javascript.
0642: *
0643: * @param regExp
0644: * A regular expression. The expression needs to match the column
0645: * in the datastore or the rule will be violated
0646: * @param focusComp
0647: * The component to check
0648: * @param errorMessage
0649: * The error message to display if the validation fails
0650: * @param localizationKey
0651: * For internationalization, the key value used to look up the
0652: * error message for the usesr language (may be null)
0653: */
0654: public void addRegularExpressionRule(String regExp,
0655: String errorMessage, String localizationKey,
0656: HtmlFormComponent focusComp) throws DataStoreException {
0657: _regExpressionRules = true;
0658: HtmlComponentValidator val = getValidator();
0659: String name = focusComp.getFullName();
0660: if (_ds != null)
0661: name = _ds.getColumnName(focusComp.getColumnNumber());
0662: val.addRegularExpressionRule(name, regExp, computeErrorMessage(
0663: errorMessage, localizationKey), focusComp);
0664: indexOtherRule();
0665: }
0666:
0667: /**
0668: * Adds a regular expression rule to the validator. The rule can be any
0669: * javascript that returns a boolean value (true means the validation
0670: * succeeded and false means it failed). This rule is only executed on the
0671: * client browser and only if the validator is set to use javascript.
0672: *
0673: * @param regExp
0674: * A regular expression. The expression needs to match the column
0675: * in the datastore or the rule will be violated
0676: * @param focusComp
0677: * The component to check
0678: * @param errorMessage
0679: * The error message to display if the validation fails
0680: */
0681: public void addRegularExpressionRule(String regExp,
0682: String errorMessage, HtmlFormComponent focusComp)
0683: throws DataStoreException {
0684: _regExpressionRules = true;
0685: HtmlComponentValidator val = getValidator();
0686: String name = focusComp.getFullName();
0687: if (_ds != null)
0688: name = _ds.getColumnName(focusComp.getColumnNumber());
0689: val.addRegularExpressionRule(name, regExp, errorMessage,
0690: focusComp);
0691: indexOtherRule();
0692: }
0693:
0694: /**
0695: * Adds a javascript rule to the validator. The rule can be any javascript
0696: * that returns a boolean value (true means the validation succeeded and
0697: * false means it failed). This rule is only executed on the client browser
0698: * and only if the validator is set to use javascript.
0699: *
0700: * @param javascript
0701: * A boolean javascript expression. If the expression returns
0702: * false it will trigger an error
0703: * @param focusComp
0704: * The component to check
0705: * @param errorMessage
0706: * The error message to display if the validation fails
0707: * @param localizationKey
0708: * For internationalization, the key value used to look up the
0709: * error message for the usesr language (may be null)
0710: */
0711: public void addJavascriptRule(String javascript,
0712: String errorMessage, String localizationKey,
0713: HtmlFormComponent focusComp) throws DataStoreException {
0714: _javaScriptRules = true;
0715: HtmlComponentValidator val = getValidator();
0716: val.addJavaScriptRule(convertJavaScript(javascript),
0717: computeErrorMessage(errorMessage, localizationKey),
0718: focusComp);
0719: indexOtherRule();
0720: }
0721:
0722: /**
0723: * Adds a javascript rule to the validator. The rule can be any javascript
0724: * that returns a boolean value (true means the validation succeeded and
0725: * false means it failed). This rule is only executed on the client browser
0726: * and only if the validator is set to use javascript.
0727: *
0728: * @param javascript
0729: * A boolean javascript expression. If the expression returns
0730: * false it will trigger an error
0731: * @param focusComp
0732: * The component to check
0733: * @param errorMessage
0734: * The error message to display if the validation fails
0735: * @param localizationKey
0736: * For internationalization, the key value used to look up the
0737: * error message for the usesr language (may be null)
0738: */
0739: public void addJavascriptRule(String javascript,
0740: String errorMessage, HtmlFormComponent focusComp)
0741: throws DataStoreException {
0742: _javaScriptRules = true;
0743: HtmlComponentValidator val = getValidator();
0744: val.addJavaScriptRule(convertJavaScript(javascript),
0745: errorMessage, focusComp);
0746: indexOtherRule();
0747: }
0748:
0749: private void addJavascriptRule(String javascript,
0750: String errorMessage, HtmlFormComponent focusComp,
0751: DataStoreBuffer ds) throws DataStoreException {
0752: _javaScriptRules = true;
0753: HtmlComponentValidator val = getValidator();
0754: val.addJavaScriptRule(convertJavaScript(javascript, ds),
0755: errorMessage, focusComp);
0756: indexOtherRule();
0757: }
0758:
0759: /**
0760: * Use this method to add validation rules that will be checked by the
0761: * validator.
0762: *
0763: * @param expression
0764: * A boolean expression that will trigger an error if evaluated
0765: * to false.
0766: * @param errorMessage
0767: * The error message to display if the validation fails. It can
0768: * have a %VALUE% token embedded in it to include the value of
0769: * the column in error in the message
0770: * @param localizationKey
0771: * For internationalization, the key value used to look up the
0772: * error message for the usesr language (may be null)
0773: * @param focusComp
0774: * The HtmlComponent to set focus too if the error expression
0775: * returns false.
0776: */
0777: public void addExpressionRule(String expression,
0778: String errorMessage, String localizationKey,
0779: HtmlFormComponent focusComp) throws DataStoreException {
0780: HtmlComponentValidator val = getValidator();
0781: val.addExpressionRule(expression, computeErrorMessage(
0782: errorMessage, localizationKey), focusComp);
0783: indexOtherRule();
0784: }
0785:
0786: /**
0787: * Use this method to add validation rules that will be checked by the
0788: * validator.
0789: *
0790: * @param expression
0791: * A boolean expression that will trigger an error if evaluated
0792: * to false.
0793: * @param errorMessage
0794: * The error message to display if the validation fails. It can
0795: * have a %VALUE% token embedded in it to include the value of
0796: * the column in error in the message
0797: * @param focusComp
0798: * The HtmlComponent to set focus too if the error expression
0799: * returns false.
0800: */
0801: public void addExpressionRule(String expression,
0802: String errorMessage, HtmlFormComponent focusComp)
0803: throws DataStoreException {
0804: addExpressionRule(expression, errorMessage, null, focusComp);
0805: }
0806:
0807: /**
0808: * Use this method to add validation rules that will be checked by the
0809: * validator.
0810: *
0811: * @param errorMessage
0812: * The error message to display if the validation fails. It can
0813: * have a %VALUE% token embedded in it to include the value of
0814: * the column in error in the message
0815: * @param localizationKey
0816: * For internationalization, the key value used to look up the
0817: * error message for the usesr language (may be null)
0818: * @param focusComp
0819: * The HtmlComponent to set focus too if the error expression
0820: * returns false.
0821: */
0822: public void addExpressionRule(DataStoreExpression expression,
0823: String errorMessage, String localizationKey,
0824: HtmlFormComponent focusComp) throws DataStoreException {
0825: HtmlComponentValidator val = getValidator();
0826: val.addExpressionRule(expression, computeErrorMessage(
0827: errorMessage, localizationKey), focusComp);
0828: indexOtherRule();
0829: }
0830:
0831: /**
0832: * Use this method to add validation rules that will be checked by the
0833: * validator.
0834: *
0835: * @param expression
0836: * A DataStoreExpression class that returns a boolean value. It
0837: * will trigger an error if the value returns false.
0838: * @param errorMessage
0839: * The error message to display if the validation fails. It can
0840: * have a %VALUE% token embedded in it to include the value of
0841: * the column in error in the message
0842: * @param focusComp
0843: * The HtmlComponent to set focus too if the error expression
0844: * returns false.
0845: */
0846: public void addExpressionRule(DataStoreExpression expression,
0847: String errorMessage, HtmlFormComponent focusComp)
0848: throws DataStoreException {
0849: addExpressionRule(expression, errorMessage, null, focusComp);
0850: }
0851:
0852: /**
0853: * Use this method to add validation rules that will be checked via a lookup
0854: * to another table.
0855: *
0856: * @param lookupTable
0857: * The name of the table to lookup the value against.
0858: * @param searchExpression
0859: * A DataStoreEvaluator expression that returns a String and will
0860: * be used as the where clause for the SQL that will validate the
0861: * data.
0862: * @param errorMessage
0863: * The error message to display if the validation fails. It can
0864: * have a %VALUE% token embedded in it to include the value of
0865: * the column in error in the message
0866: * @param localizationKey
0867: * For internationalization, the key value used to look up the
0868: * error message for the usesr language (may be null)
0869: * @param focusComp
0870: * The HtmlComponent to set focus to if the error expression
0871: * returns false.
0872: */
0873: public void addLookupRule(String lookupTable,
0874: String searchExpression, String errorMessage,
0875: String localizationKey, HtmlFormComponent focusComp)
0876: throws DataStoreException {
0877: HtmlComponentValidator val = getValidator();
0878: val.addLookupRule(lookupTable, searchExpression,
0879: computeErrorMessage(errorMessage, localizationKey),
0880: focusComp);
0881: indexOtherRule();
0882: }
0883:
0884: /**
0885: * Use this method to add validation rules that will be checked via a lookup
0886: * to another table.
0887: *
0888: * @param lookupTable
0889: * The name of the table to lookup the value against.
0890: * @param searchExpression
0891: * A DataStoreEvaluator expression that returns a String and will
0892: * be used as the where clause for the SQL that will validate the
0893: * data.
0894: * @param errorMessage
0895: * The error message to display if the validation fails. It can
0896: * have a %VALUE% token embedded in it to include the value of
0897: * the column in error in the message
0898: * @param focusComp
0899: * The HtmlComponent to set focus to if the error expression
0900: * returns false.
0901: */
0902: public void addLookupRule(String lookupTable,
0903: String searchExpression, String errorMessage,
0904: HtmlFormComponent focusComp) throws DataStoreException {
0905: addLookupRule(lookupTable, searchExpression, errorMessage,
0906: null, focusComp);
0907: }
0908:
0909: /**
0910: * Use this method to add validation rules that will be checked via a lookup
0911: * to another table. In addition to checking if a set of columns are valid,
0912: * this type of rule will also fill in a bucket in the datastore with a
0913: * description taken from the row retrieved in the lookup table.
0914: *
0915: * @param lookupTable
0916: * The name of the table to lookup the value against.
0917: * @param searchExpression
0918: * A DataStoreEvaluator expression that returns a String and will
0919: * be used as the where clause for the SQL that will validate the
0920: * data.
0921: * @param errorMessage
0922: * The error message to display if the validation fails. It can
0923: * have a %VALUE% token embedded in it to include the value of
0924: * the column in error in the message
0925: * @param localizationKey
0926: * For internationalization, the key value used to look up the
0927: * error message for the usesr language (may be null)
0928: * @param focusComp
0929: * The HtmlComponent to set focus to if the error expression
0930: * returns false.
0931: * @param descColumn
0932: * The name of the column in the lookup table used to fill in the
0933: * description.
0934: * @param descBucket
0935: * The name of a bucket column in the datastore to place the
0936: * description.
0937: */
0938: public void addLookupRule(String lookupTable,
0939: String searchExpression, String errorMessage,
0940: String localizationKey, HtmlFormComponent focusComp,
0941: String descColumn, String descBucket)
0942: throws DataStoreException {
0943: HtmlComponentValidator val = getValidator();
0944: val.addLookupRule(lookupTable, searchExpression,
0945: computeErrorMessage(errorMessage, localizationKey),
0946: focusComp, descColumn, descBucket);
0947: indexOtherRule();
0948: }
0949:
0950: /**
0951: * Use this method to add validation rules that will be checked via a lookup
0952: * to another table. In addition to checking if a set of columns are valid,
0953: * this type of rule will also fill in a bucket in the datastore with a
0954: * description taken from the row retrieved in the lookup table.
0955: *
0956: * @param lookupTable
0957: * The name of the table to lookup the value against.
0958: * @param searchExpression
0959: * A DataStoreEvaluator expression that returns a String and will
0960: * be used as the where clause for the SQL that will validate the
0961: * data.
0962: * @param errorMessage
0963: * The error message to display if the validation fails. It can
0964: * have a %VALUE% token embedded in it to include the value of
0965: * the column in error in the message
0966: * @param focusComp
0967: * The HtmlComponent to set focus to if the error expression
0968: * returns false.
0969: * @param descColumn
0970: * The name of the column in the lookup table used to fill in the
0971: * description.
0972: * @param descBucket
0973: * The name of a bucket column in the datastore to place the
0974: * description.
0975: */
0976: public void addLookupRule(String lookupTable,
0977: String searchExpression, String errorMessage,
0978: HtmlFormComponent focusComp, String descColumn,
0979: String descBucket) throws DataStoreException {
0980: addLookupRule(lookupTable, searchExpression, errorMessage,
0981: null, focusComp, descColumn, descBucket);
0982: }
0983:
0984: /**
0985: * Use this method to add validation rules that will be checked via a lookup
0986: * to another table.
0987: *
0988: * @param lookupTable
0989: * The name of the table to lookup the value against.
0990: * @param searchExpression
0991: * A DataStoreExpression that returns a String and will be used
0992: * as the where clause for the SQL that will validate the data.
0993: * @param errorMessage
0994: * The error message to display if the validation fails. It can
0995: * have a %VALUE% token embedded in it to include the value of
0996: * the column in error in the message
0997: * @param localizationKey
0998: * For internationalization, the key value used to look up the
0999: * error message for the usesr language (may be null)
1000: * @param focusComp
1001: * The HtmlComponent to set focus to if the error expression
1002: * returns false.
1003: */
1004: public void addLookupRule(String lookupTable,
1005: DataStoreExpression searchExpression, String errorMessage,
1006: String localizationKey, HtmlFormComponent focusComp)
1007: throws DataStoreException {
1008: HtmlComponentValidator val = getValidator();
1009: val.addLookupRule(lookupTable, searchExpression,
1010: computeErrorMessage(errorMessage, localizationKey),
1011: focusComp);
1012: indexOtherRule();
1013: }
1014:
1015: /**
1016: * Use this method to add validation rules that will be checked via a lookup
1017: * to another table.
1018: *
1019: * @param lookupTable
1020: * The name of the table to lookup the value against.
1021: * @param searchExpression
1022: * A DataStoreExpression that returns a String and will be used
1023: * as the where clause for the SQL that will validate the data.
1024: * @param errorMessage
1025: * The error message to display if the validation fails. It can
1026: * have a %VALUE% token embedded in it to include the value of
1027: * the column in error in the message
1028: * @param focusComp
1029: * The HtmlComponent to set focus to if the error expression
1030: * returns false.
1031: */
1032: public void addLookupRule(String lookupTable,
1033: DataStoreExpression searchExpression, String errorMessage,
1034: HtmlFormComponent focusComp) throws DataStoreException {
1035: addLookupRule(lookupTable, searchExpression, errorMessage,
1036: null, focusComp);
1037: }
1038:
1039: /**
1040: * Use this method to add validation rules that will be checked via a lookup
1041: * to another table. In addition to checking if a set of columns are valid,
1042: * this type of rule will also fill in a bucket in the datastore with a
1043: * description taken from the row retrieved in the lookup table.
1044: *
1045: * @param lookupTable
1046: * The name of the table to lookup the value against.
1047: * @param searchExpression
1048: * A DataStoreExpression that returns a String and will be used
1049: * as the where clause for the SQL that will validate the data.
1050: * @param errorMessage
1051: * The error message to display if the validation fails. It can
1052: * have a %VALUE% token embedded in it to include the value of
1053: * the column in error in the message
1054: * @param localizationKey
1055: * For internationalization, the key value used to look up the
1056: * error message for the usesr language (may be null)
1057: * @param focusComp
1058: * The HtmlComponent to set focus to if the error expression
1059: * returns false.
1060: * @param descColumn
1061: * The name of the column in the lookup table used to fill in the
1062: * description.
1063: * @param descBucket
1064: * The name of a bucket column in the datastore to place the
1065: * description.
1066: */
1067: public void addLookupRule(String lookupTable,
1068: DataStoreExpression searchExpression, String errorMessage,
1069: String localizationKey, HtmlFormComponent focusComp,
1070: String descColumn, String descBucket)
1071: throws DataStoreException {
1072: HtmlComponentValidator val = getValidator();
1073: val.addLookupRule(lookupTable, searchExpression,
1074: computeErrorMessage(errorMessage, localizationKey),
1075: focusComp, descColumn, descBucket);
1076: indexOtherRule();
1077: }
1078:
1079: /**
1080: * Use this method to add validation rules that will be checked via a lookup
1081: * to another table. In addition to checking if a set of columns are valid,
1082: * this type of rule will also fill in a bucket in the datastore with a
1083: * description taken from the row retrieved in the lookup table.
1084: *
1085: * @param lookupTable
1086: * The name of the table to lookup the value against.
1087: * @param searchExpression
1088: * A DataStoreExpression that returns a String and will be used
1089: * as the where clause for the SQL that will validate the data.
1090: * @param errorMessage
1091: * The error message to display if the validation fails. It can
1092: * have a %VALUE% token embedded in it to include the value of
1093: * the column in error in the message
1094: * @param focusComp
1095: * The HtmlComponent to set focus to if the error expression
1096: * returns false.
1097: * @param descColumn
1098: * The name of the column in the lookup table used to fill in the
1099: * description.
1100: * @param descBucket
1101: * The name of a bucket column in the datastore to place the
1102: * description.
1103: */
1104: public void addLookupRule(String lookupTable,
1105: DataStoreExpression searchExpression, String errorMessage,
1106: HtmlFormComponent focusComp, String descColumn,
1107: String descBucket) throws DataStoreException {
1108: addLookupRule(lookupTable, searchExpression, errorMessage,
1109: null, focusComp, descColumn, descBucket);
1110: }
1111:
1112: /**
1113: * Use this method to add a range validation rule.
1114: *
1115: * @param minValue
1116: * The minimum value the component must meet or null for no
1117: * minimum
1118: * @param maxValue
1119: * The maximum value the component must meet or null for no
1120: * maximum
1121: * @param errorMessage
1122: * The error message to display if the validation fails. It can
1123: * have a %VALUE% token embedded in it to include the value of
1124: * the column in error in the message
1125: * @param localizationKey
1126: * For internationalization, the key value used to look up the
1127: * error message for the usesr language (may be null)
1128: * @param focusComp
1129: * The HtmlComponent to set focus too if the error expression
1130: * returns false.
1131: */
1132: public void addRangeRule(Object minValue, Object maxValue,
1133: String errorMessage, String localizationKey,
1134: HtmlFormComponent focusComp) throws DataStoreException {
1135: _rangeRules = true;
1136: HtmlComponentValidator val = getValidator();
1137: String name = focusComp.getFullName();
1138: if (_ds != null)
1139: name = _ds.getColumnName(focusComp.getColumnNumber());
1140: val.addRangeRule(name, minValue, maxValue, computeErrorMessage(
1141: errorMessage, localizationKey), focusComp);
1142: indexOtherRule();
1143: }
1144:
1145: /**
1146: * Use this method to add a range validation rule.
1147: *
1148: * @param minValue
1149: * The minimum value the component must meet or null for no
1150: * minimum
1151: * @param maxValue
1152: * The maximum value the component must meet or null for no
1153: * maximum
1154: * @param errorMessage
1155: * The error message to display if the validation fails. It can
1156: * have a %VALUE% token embedded in it to include the value of
1157: * the column in error in the message
1158: * @param focusComp
1159: * The HtmlComponent to set focus too if the error expression
1160: * returns false.
1161: */
1162: public void addRangeRule(Object minValue, Object maxValue,
1163: String errorMessage, HtmlFormComponent focusComp)
1164: throws DataStoreException {
1165: _rangeRules = true;
1166: HtmlComponentValidator val = getValidator();
1167: val.addRangeRule(
1168: _ds.getColumnName(focusComp.getColumnNumber()),
1169: minValue, maxValue, errorMessage, focusComp);
1170: indexOtherRule();
1171: }
1172:
1173: private String computeErrorMessage(String message,
1174: String localizationKey) {
1175: if (localizationKey != null) {
1176: String val = LanguageResourceFinder.getResource(getPage()
1177: .getApplicationName(), localizationKey, getPage()
1178: .getLanguagePreferences());
1179: if (val != null)
1180: return val;
1181: }
1182: if (message == null)
1183: message = "A validation error has occurred";
1184:
1185: return message;
1186: }
1187:
1188: private String processErrorMessage(String error, String value,
1189: String format) {
1190: if (value == null)
1191: value = "null";
1192: if (format == null)
1193: format = "null";
1194: String val = replace(error, "%VALUE%", value);
1195: val = replace(val, "%FORMAT%", format.toLowerCase());
1196: return val;
1197: }
1198:
1199: private String replace(String sString, String sOldString,
1200: String sNewString) {
1201: StringBuffer sbString = new StringBuffer(sString);
1202: while (true) {
1203: int iIndex = sbString.toString().indexOf(sOldString);
1204: if (iIndex < 0)
1205: break;
1206: sbString.replace(iIndex, iIndex + sOldString.length(),
1207: sNewString);
1208: }
1209: return sbString.toString();
1210: }
1211:
1212: private Hashtable getValueChangedItems() {
1213: if (_valueChangedItems == null)
1214: _valueChangedItems = new Hashtable();
1215: return _valueChangedItems;
1216: }
1217:
1218: private HtmlComponentValidator getValidator()
1219: throws DataStoreException {
1220: if (_val == null) {
1221: if (_ds == null)
1222: _val = new HtmlComponentValidator(getPage()
1223: .getApplicationName(), _dbProfile,
1224: new DataStoreBuffer());
1225: else
1226: _val = new HtmlComponentValidator(getPage()
1227: .getApplicationName(), _dbProfile, _ds);
1228: }
1229: return _val;
1230: }
1231:
1232: /**
1233: * Gets the database profile used for lookup validations
1234: *
1235: * @return String
1236: */
1237: public String getDBProfile() {
1238: return _dbProfile;
1239: }
1240:
1241: /**
1242: * Sets the database profile used for lookup validations
1243: */
1244: public void setDBProfile(String dbProfile) {
1245: _dbProfile = dbProfile;
1246: }
1247:
1248: /**
1249: * Adds an HtmlSubmitButton to this component. The validation will fire when
1250: * the submit button is clicked.
1251: */
1252: public void addSubmitToListenTo(HtmlSubmitButton b) {
1253: b.insertSubmitListener(this );
1254: if (_submitComponents == null)
1255: _submitComponents = new Vector();
1256: _submitComponents.addElement(b);
1257: }
1258:
1259: /**
1260: * Adds an HtmlLink to this component. The validation will fire when the
1261: * link is clicked.
1262: */
1263: public void addSubmitToListenTo(HtmlLink b) {
1264: b.insertSubmitListener(this );
1265: if (_submitComponents == null)
1266: _submitComponents = new Vector();
1267: _submitComponents.addElement(b);
1268: b.setHref("none");
1269: }
1270:
1271: /**
1272: * Adds an JspLink to this component. The validation will fire when the link
1273: * is clicked.
1274: */
1275: public void addSubmitToListenTo(JspLink b) {
1276: b.insertSubmitListener(this );
1277: if (_submitComponents == null)
1278: _submitComponents = new Vector();
1279: _submitComponents.addElement(b);
1280: b.setHref("none");
1281: }
1282:
1283: /**
1284: * Adds an HtmlSubmitImage to this component. The validation will fire when
1285: * the submit image is clicked.
1286: */
1287: public void addSubmitToListenTo(HtmlSubmitImage b) {
1288: b.insertSubmitListener(this );
1289: if (_submitComponents == null)
1290: _submitComponents = new Vector();
1291: _submitComponents.addElement(b);
1292: }
1293:
1294: /**
1295: * @see com.salmonllc.html.HtmlComponent#processParms(Hashtable, int)
1296: */
1297: public boolean processParms(Hashtable parms, int rowNo)
1298: throws Exception {
1299: _valOk = true;
1300: _nextSeq = _ruleNo;
1301: String[] dt = (String[]) parms.get(getFullName() + "dataTable");
1302: String[] dtRow = (String[]) parms.get(getFullName()
1303: + "dataTableRow");
1304: String[] focusComp = (String[]) parms.get(getFullName()
1305: + "focusComp");
1306: if (dtRow != null && !dtRow[0].equals("-1")) {
1307: int row = Integer.parseInt(dtRow[0]);
1308: HtmlComponent table = ((JspController) getPage())
1309: .getComponent(dt[0]);
1310: HtmlFormComponent comp = (HtmlFormComponent) ((JspController) getPage())
1311: .getComponent(focusComp[0]);
1312: if (table != null) {
1313: if (table instanceof HtmlDataTable)
1314: ((HtmlDataTable) table)
1315: .setPage(((HtmlDataTable) table)
1316: .getPage(row));
1317: else
1318: ((JspDataTable) table)
1319: .setPage(((JspDataTable) table)
1320: .getPage(row));
1321: _doSetFocus = false;
1322: if (comp != null)
1323: comp.setFocus(row);
1324: submitPerformed(new SubmitEvent(getPage(), this ,
1325: getName(), getFullName()));
1326: return true;
1327: }
1328: }
1329:
1330: if (_extraComponent != null)
1331: return (_extraComponent.processParms(parms, rowNo));
1332:
1333: return super .processParms(parms, rowNo);
1334: }
1335:
1336: /**
1337: * @see com.salmonllc.html.HtmlComponent#executeEvent(int)
1338: */
1339: public boolean executeEvent(int eventType) throws Exception {
1340: if (_extraComponent != null)
1341: return _extraComponent.executeEvent(eventType);
1342: else
1343: return super .executeEvent(eventType);
1344: }
1345:
1346: /**
1347: * Returns a boolean value indicating whether or not the validation
1348: * succeeded
1349: */
1350: public boolean getValidationSucceeded() {
1351: return _valOk;
1352: }
1353:
1354: private boolean scrollToDataTableRow(HtmlFormComponent comp, int row) {
1355: HtmlComponent parent = comp.getParent();
1356: while (parent != null) {
1357: if (parent instanceof HtmlDataTable) {
1358: HtmlDataTable t = (HtmlDataTable) parent;
1359: t.setPage(t.getPage(row));
1360: return true;
1361: } else if (parent instanceof JspDataTable) {
1362: JspDataTable t = (JspDataTable) parent;
1363: t.setPage(t.getPage(row));
1364: return true;
1365: }
1366:
1367: parent = parent.getParent();
1368: }
1369: return false;
1370:
1371: }
1372:
1373: private boolean isInDataTable(HtmlFormComponent comp) {
1374:
1375: HtmlComponent parent = comp.getParent();
1376: while (parent != null) {
1377: if (parent instanceof HtmlDataTable)
1378: return true;
1379: else if (parent instanceof JspDataTable)
1380: return true;
1381:
1382: parent = parent.getParent();
1383: }
1384: return false;
1385:
1386: }
1387:
1388: private String getDataTableNameForComp(HtmlFormComponent comp) {
1389: HtmlComponent parent = comp.getParent();
1390: while (parent != null) {
1391: if (parent instanceof HtmlDataTable)
1392: return parent.getName();
1393: else if (parent instanceof JspDataTable)
1394: return parent.getName();
1395:
1396: parent = parent.getParent();
1397: }
1398: return null;
1399: }
1400:
1401: //fc 06/11/04: Indicates whether the component being validated is in a Data
1402: // Table or not.
1403: private boolean isComponentInDataTable(HtmlFormComponent comp) {
1404: HtmlComponent parent = comp.getParent();
1405: while (parent != null) {
1406: if (parent instanceof HtmlDataTable)
1407: return true;
1408: else if (parent instanceof JspDataTable)
1409: return true;
1410:
1411: parent = parent.getParent();
1412: }
1413: return false;
1414: }
1415:
1416: //fc 06/11/04: returns the datatable the given component is within.
1417: private HtmlComponent getComponentsDataTable(HtmlFormComponent comp) {
1418: HtmlComponent parent = comp.getParent();
1419: while (parent != null) {
1420: if (parent instanceof HtmlDataTable)
1421: return parent;
1422: else if (parent instanceof JspDataTable)
1423: return parent;
1424:
1425: parent = parent.getParent();
1426: }
1427: return null;
1428: }
1429:
1430: private boolean isDataRowOnPage(HtmlFormComponent comp, int row) {
1431: HtmlComponent parent = comp.getParent();
1432: while (parent != null) {
1433: if (parent instanceof HtmlDataTable)
1434: return ((HtmlDataTable) parent).isRowOnPage(row);
1435: else if (parent instanceof JspDataTable)
1436: return ((JspDataTable) parent).isRowOnPage(row);
1437: ;
1438:
1439: parent = parent.getParent();
1440: }
1441: return false;
1442: }
1443:
1444: /**
1445: * Returns the a value indicating whether or not new rows in the datastore
1446: * that haven't been modified get validated
1447: *
1448: * @return boolean
1449: */
1450: public boolean getValidateNewRows() {
1451: return _validateNewRows;
1452: }
1453:
1454: /**
1455: * Sets the a value indicating whether or not new rows in the datastore that
1456: * haven't been modified get validated
1457: *
1458: * @param validateNewRows
1459: * The validateNewRows to set
1460: */
1461: public void setValidateNewRows(boolean validateNewRows) {
1462: _validateNewRows = validateNewRows;
1463: }
1464:
1465: /**
1466: * Use this method to fill in the descriptions for lookup columns for the
1467: * current row in the datastore.
1468: */
1469: public void populateDescriptions() throws Exception {
1470: populateDescriptions(_ds.getRow());
1471: }
1472:
1473: /**
1474: * Use this method to fill in the descriptions for lookup columns.
1475: *
1476: * @param rowNo
1477: * The row number in the DataStore to fill in.
1478: */
1479: public void populateDescriptions(int rowNo) throws Exception {
1480: getValidator().populateDescriptions(rowNo);
1481: }
1482:
1483: /**
1484: * Removes all other messages and adds this one to the list for one request
1485: */
1486: public void setErrorMessage(String msg) {
1487: setErrorMessage(msg, null);
1488: }
1489:
1490: /**
1491: * Removes all other messages and adds this one to the list for one request
1492: *
1493: * @param msg
1494: * The message to add
1495: * @param comp
1496: * The component to set focus to
1497: * @param row
1498: * The row in the datastore to scroll to/set focus to
1499: * @param extraDisplay
1500: * An extra HTML component to display next to the error message
1501: */
1502: public void setErrorMessage(String msg, HtmlFormComponent comp,
1503: int row, HtmlComponent extraDisplay) {
1504: _errorEntries.removeAllElements();
1505: addErrorMessage(msg, comp, row, 1.0f, extraDisplay);
1506: }
1507:
1508: /**
1509: * Removes all other messages and adds this one to the list for one request
1510: *
1511: * @param msg
1512: * The message to add
1513: * @param comp
1514: * The component to set focus to
1515: * @param row
1516: * The row in the datastore to scroll to/set focus to
1517: */
1518: public void setErrorMessage(String msg, HtmlFormComponent comp,
1519: int row) {
1520: _errorEntries.removeAllElements();
1521: addErrorMessage(msg, comp, row, 1.0f);
1522: }
1523:
1524: /**
1525: * Removes all other messages and adds this one to the list for one request
1526: *
1527: * @param msg
1528: * The message to add
1529: * @param comp
1530: * The component to set focus to
1531: */
1532: public void setErrorMessage(String msg, HtmlFormComponent comp) {
1533: setErrorMessage(msg, comp, -1);
1534: }
1535:
1536: /**
1537: * Adds an error message to the list for one request
1538: */
1539: public void addErrorMessage(String msg) {
1540: addErrorMessage(msg, null, -1);
1541: }
1542:
1543: /**
1544: * Adds an error message to the list for one request
1545: *
1546: * @param msg
1547: * The message to add
1548: * @param comp
1549: * The component to set focus to
1550: */
1551: public void addErrorMessage(String msg, HtmlFormComponent comp) {
1552: addErrorMessage(msg, comp, -1);
1553: }
1554:
1555: /**
1556: * Adds an error message to the list for one request
1557: *
1558: * @param msg
1559: * The message to add
1560: * @param comp
1561: * The component to set focus to
1562: * @param row
1563: * The row in the datastore to scroll to/set focus to
1564: */
1565: public void addErrorMessage(String msg, HtmlFormComponent comp,
1566: int row) {
1567: _valOk = false;
1568: ErrorEntry entry = new ErrorEntry();
1569: entry.error = msg;
1570: _nextSeq += 1.0f;
1571: entry.seq = _nextSeq;
1572: if (_ds != null)
1573: entry.row = row > -1 ? row : _ds.getRow();
1574: else
1575: entry.row = row;
1576: entry.comp = comp;
1577: _errorEntries.addElement(entry);
1578: }
1579:
1580: /**
1581: * Adds an error message to the list for one request
1582: *
1583: * @param msg
1584: * The message to add
1585: * @param comp
1586: * The component to set focus to
1587: * @param row
1588: * The row in the datastore to scroll to/set focus to. Use -1 for
1589: * the current row.
1590: * @param seq
1591: * The position that the error should be displayed if there are
1592: * multiple errors. Errors generated by rules have an sequence
1593: * corresponding to the order that the rule was added (1.0, 2.0,
1594: * etc). Your errors can be inserted into the list by specifying
1595: * a number that falls in the middle of any two rules.
1596: *
1597: */
1598: public void addErrorMessage(String msg, HtmlFormComponent comp,
1599: int row, float seq) {
1600: addErrorMessage(msg, comp, row, seq, null);
1601: }
1602:
1603: private void addErrorMessage(String msg, HtmlFormComponent comp,
1604: int row, float seq, HtmlComponent extraDisplay) {
1605: _valOk = false;
1606: ErrorEntry entry = new ErrorEntry();
1607: entry.error = msg;
1608: entry.seq = seq;
1609: entry.extraDisplay = extraDisplay;
1610: if (_ds != null && row == -1)
1611: entry.row = _ds.getRow();
1612: else
1613: entry.row = row;
1614: entry.comp = comp;
1615: _errorEntries.addElement(entry);
1616: }
1617:
1618: /**
1619: * Sets the autoPopulateLookups flag. This indicates whether or not the
1620: * component will automatically populate lookup descriptions after it's
1621: * datasource get autoretreieved
1622: *
1623: * @param autoPopulateLookups
1624: * The autoPopulateLookups to set
1625: */
1626: public void setAutoPopulateLookups(boolean autoPopulateLookups) {
1627: _autoPopulateLookups = autoPopulateLookups;
1628: }
1629:
1630: /**
1631: * If autopopulate is true, it will populate all the description columns for
1632: * the datastore, otherwise it won't do anything
1633: */
1634: public void autoPopulateLookups() throws Exception {
1635: if (_autoPopulateLookups && _ds != null) {
1636: for (int i = 0; i < _ds.getRowCount(); i++)
1637: populateDescriptions(i);
1638: _ds.resetStatus();
1639: }
1640:
1641: }
1642:
1643: /**
1644: * Returns whether special html characters ( <,>,&,; etc..) should be
1645: * converted to Html Escape Sequences before being generated.
1646: */
1647: public boolean getFixSpecialHtmlCharacters() {
1648: return _fixSpecialHtml;
1649: }
1650:
1651: /**
1652: * Specify whether special html characters ( <,>,&,; etc..) should be
1653: * converted to Html Escape Sequences before being generated.
1654: */
1655: public void setFixSpecialHtmlCharacters(boolean fix) {
1656: _fixSpecialHtml = fix;
1657: }
1658:
1659: /**
1660: * Gets whether or not the validator will display multiple errors
1661: */
1662: public boolean getMultipleErrorsOK() {
1663: return _multipleErrorsOK;
1664: }
1665:
1666: /**
1667: * Sets whether or not the validator will display multiple errors
1668: */
1669: public void setMultipleErrorsOK(boolean multipleErrors) {
1670: _multipleErrorsOK = multipleErrors;
1671: }
1672:
1673: private void indexTypeCheckRule(HtmlComponent comp) {
1674: if (_ruleIndexes == null)
1675: _ruleIndexes = new Hashtable();
1676: Integer index = new Integer(++_ruleNo);
1677: _ruleIndexes.put(comp, index);
1678: }
1679:
1680: private void indexOtherRule() {
1681: if (_ruleIndexes == null)
1682: _ruleIndexes = new Hashtable();
1683: Integer index = new Integer(++_ruleNo);
1684: Integer valIndex = new Integer(_val.getRuleCount() - 1);
1685: _ruleIndexes.put(valIndex, index);
1686: }
1687:
1688: /**
1689: * This method adds a listener the will be notified when after the scripted
1690: * validations complete.
1691: *
1692: * @param l
1693: * The listener to add.
1694: */
1695: public void addValidateListener(ValidateListener l) {
1696: if (_listeners == null)
1697: _listeners = new Vector();
1698: //
1699: int listenersSize = _listeners.size();
1700: for (int i = 0; i < listenersSize; i++) {
1701: if (((ValueChangedListener) _listeners.elementAt(i)) == l)
1702: return;
1703: }
1704: _listeners.addElement(l);
1705: }
1706:
1707: /**
1708: * This method is called when the component is created from a Jsp validator
1709: * tag after all the fields are initialized. It is a convenient place for
1710: * sub classesto override to initialize the component.
1711: */
1712: public void initialize() {
1713:
1714: }
1715:
1716: /**
1717: * Returns the number of errors found in the validator
1718: */
1719: public int getErrorCount() {
1720: return _errorEntries.size();
1721: }
1722:
1723: /**
1724: * Returns the error message at the specified index
1725: */
1726: public String getErrorMessage(int index) {
1727: ErrorEntry e = (ErrorEntry) _errorEntries.elementAt(index);
1728: return e.error;
1729: }
1730:
1731: /**
1732: * Returns the error component at the specified index
1733: */
1734: public HtmlFormComponent getErrorComponent(int index) {
1735: ErrorEntry e = (ErrorEntry) _errorEntries.elementAt(index);
1736: return e.comp;
1737: }
1738:
1739: /**
1740: * Returns the error row at the specified index
1741: */
1742: public int getErrorRow(int index) {
1743: ErrorEntry e = (ErrorEntry) _errorEntries.elementAt(index);
1744: return e.row;
1745: }
1746:
1747: /**
1748: * Sets an expression that will cause a row to be skipped (not be validated)
1749: * if it evaluates to true
1750: */
1751: public void setSkipRowExpression(String exp)
1752: throws DataStoreException {
1753: _skipRowExp = new DataStoreEvaluator(_ds, exp);
1754: }
1755:
1756: /**
1757: * Sets an expression that will cause a row to be skipped (not be validated)
1758: * if it evaluates to true
1759: */
1760: public void setSkipRowExpression(DataStoreExpression exp)
1761: throws DataStoreException {
1762: _skipRowExp = new DataStoreEvaluator(_ds, exp);
1763: }
1764:
1765: /**
1766: * Imports any validation rules described in the datastore into the
1767: * validator
1768: */
1769: public void importRules(DataStoreBuffer ds) {
1770: //import any rules in the ds
1771: HtmlPage p = getPage();
1772: if (!(p instanceof JspController))
1773: return;
1774: JspController cont = (JspController) p;
1775:
1776: try {
1777: for (int i = 0; i < ds.getColumnCount(); i++) {
1778: ValidationRule[] v = ds.getValidationRulesForColumn(i);
1779: if (v != null) {
1780: String colName = ds.getColumnName(i);
1781: for (int j = 0; j < v.length; j++) {
1782: int type = v[j].getRuleType();
1783: HtmlComponent comp = cont.getBoundComponent(ds,
1784: colName);
1785: HtmlFormComponent fComp = null;
1786: if (comp instanceof HtmlFormComponent)
1787: fComp = (HtmlFormComponent) comp;
1788:
1789: if (type == ValidationRule.TYPE_EXPRESSION) {
1790: if (v[j].getDsExpression() != null)
1791: addExpressionRule(v[j]
1792: .getDsExpression(), v[j]
1793: .getErrorMessage(), fComp);
1794: else
1795: addExpressionRule(v[j].getExpression(),
1796: v[j].getErrorMessage(), fComp);
1797: } else if (type == ValidationRule.TYPE_TYPE_CHECK) {
1798: if (fComp != null)
1799: addTypeCheckRule(fComp, v[j]
1800: .getErrorMessage());
1801: } else if (type == ValidationRule.TYPE_REQUIRED) {
1802: if (fComp != null)
1803: addRequiredRule(fComp, v[j]
1804: .getErrorMessage());
1805: } else if (type == ValidationRule.TYPE_JAVASCRIPT) {
1806: if (fComp != null)
1807: addJavascriptRule(v[j].getExpression(),
1808: v[j].getErrorMessage(), fComp,
1809: ds);
1810: } else if (type == ValidationRule.TYPE_LOOKUP) {
1811: if (fComp != null)
1812: addLookupRule(v[j].getLookupTable(),
1813: v[j].getLookupExpression(),
1814: v[j].getErrorMessage(), null,
1815: fComp, v[j]
1816: .getDesciptionColumn(),
1817: v[j].getDescriptionBucket());
1818: } else if (type == ValidationRule.TYPE_REGULAR_EXPRESSION) {
1819: if (fComp != null)
1820: addRegularExpressionRule(v[j]
1821: .getExpression(), v[j]
1822: .getErrorMessage(), fComp);
1823: } else if (type == ValidationRule.TYPE_RANGE) {
1824: if (fComp != null)
1825: addRangeRule(v[j].getMinValue(), v[j]
1826: .getMaxValue(), v[j]
1827: .getErrorMessage(), fComp);
1828: }
1829: }
1830: }
1831: }
1832: } catch (DataStoreException ex) {
1833: MessageLog.writeErrorMessage("set data store", ex, this );
1834: }
1835: }
1836:
1837: /**
1838: * @return true if the component will use client side javascript for
1839: * validations where that is possible
1840: */
1841: public boolean getUseJavaScript() {
1842: return (_useJavaScriptForRegExpRules && _regExpressionRules)
1843: || (_useJavaScriptForReqRules && _reqRules)
1844: || (_useJavaScriptForRangeRules && _rangeRules)
1845: || _javaScriptRules;
1846: }
1847:
1848: /**
1849: * @returns true if the component will use javascript alert popups to
1850: * display errors
1851: */
1852: public boolean getUseAlertsForErrors() {
1853: return _useAlertsForErrors;
1854: }
1855:
1856: /**
1857: * Set to true if the component will use javascript alert popups to display
1858: * errors
1859: */
1860: public void setUseAlertsForErrors(boolean b) {
1861: _useAlertsForErrors = b;
1862: }
1863:
1864: /**
1865: * For javascript validations, this method generates the name of the on
1866: * click function used for submit buttons. This is used by the framework and
1867: * generally does not need to be called directly.
1868: */
1869: public static String generateOnClickJavaScriptFunctionName(
1870: String componentFullName) {
1871: return componentFullName + "_validate()";
1872: }
1873:
1874: /**
1875: * For javascript validations, this method generates the javascript function
1876: * that will fire when a sumbit button is clicked. This is used by the
1877: * framework and generally does not need to be called directly.
1878: */
1879: public static String generateOnClickJavaScriptForButtons(
1880: String onClickCode, Vector submitListeners,
1881: String componentFullName) {
1882: if (submitListeners == null)
1883: return null;
1884:
1885: boolean isThereAScript = false;
1886: StringBuffer valScript = new StringBuffer(
1887: "<script language=\"javaScript\">\r\n");
1888: valScript
1889: .append(" function "
1890: + generateOnClickJavaScriptFunctionName(componentFullName)
1891: + " {\r\n");
1892:
1893: for (int i = 0; i < submitListeners.size(); i++) {
1894: Object o = submitListeners.elementAt(i);
1895: if (o instanceof HtmlValidatorText) {
1896: HtmlValidatorText comp = (HtmlValidatorText) o;
1897: if (comp.getUseJavaScript()) {
1898: isThereAScript = true;
1899: valScript
1900: .append(" if (!"
1901: + generateOnClickJavaScriptFunctionName(comp
1902: .getFullName()) + ")\r\n");
1903: valScript.append(" return false;\r\n");
1904: }
1905: }
1906: }
1907:
1908: if (!isThereAScript)
1909: return null;
1910:
1911: if (onClickCode != null)
1912: valScript.append(onClickCode);
1913:
1914: valScript.append(" return true;\r\n");
1915: valScript.append(" }\r\n");
1916: valScript.append("</script>\r\n");
1917:
1918: return valScript.toString();
1919: }
1920:
1921: /**
1922: * Returns the body of a javascript on click method for validation for this
1923: * validator. Used internally by the framework and generally does not need
1924: * to be called directly.
1925: */
1926: private String generateValidationJavaScript() {
1927: String breaksBefore = "";
1928: for (int i = 0; i < _breaksBefore; i++)
1929: breaksBefore += "<BR>";
1930: String breaksAfter = "";
1931: for (int i = 0; i < _breaksAfter; i++)
1932: breaksAfter += "<BR>";
1933:
1934: if (!getUseJavaScript())
1935: return "";
1936:
1937: StringBuffer script = new StringBuffer();
1938: script.append("<script language=\"javaScript\">\r\n\r\n");
1939:
1940: script.append("function "
1941: + generateOnClickJavaScriptFunctionName(getFullName())
1942: + " {\r\n");
1943: script.append("\r\nfunction isNull(strText) {\r\n");
1944: script.append(" for (i = 0; i < strText.length; i++){\r\n");
1945: script
1946: .append(" if (strText.charAt(i) != ' ') return false;\r\n");
1947: script.append(" }\r\n");
1948: script.append(" return true;\r\n");
1949: script.append("}\r\n\r\n");
1950: script.append("var theSpan=document.getElementById(\"div"
1951: + getFullName() + "\");\r\n");
1952: script.append("var theFocus=null;\r\n");
1953: script.append("var theMessage='';\r\n");
1954:
1955: for (int i = 0; i < _val.getRuleCount(); i++) {
1956: if (_val.getRuleType(i) == ValidationRule.TYPE_REQUIRED
1957: && _useJavaScriptForReqRules)
1958: generateJavaScriptForRequiredRule(_val
1959: .getRuleFocusComponent(i), _val
1960: .getRuleErrorMessage(i), script);
1961: else if (_val.getRuleType(i) == ValidationRule.TYPE_JAVASCRIPT)
1962: generateJavaScriptForJavaScriptRule(_val
1963: .getRuleJavaScript(i), _val
1964: .getRuleFocusComponent(i), _val
1965: .getRuleErrorMessage(i), script);
1966: else if (_val.getRuleType(i) == ValidationRule.TYPE_REGULAR_EXPRESSION
1967: && _useJavaScriptForRegExpRules)
1968: generateJavaScriptForRegExpRule(_val
1969: .getRuleRegExpression(i), _val
1970: .getRuleFocusComponent(i), _val
1971: .getRuleErrorMessage(i), script);
1972: else if (_val.getRuleType(i) == ValidationRule.TYPE_RANGE
1973: && _useJavaScriptForRangeRules)
1974: generateJavaScriptForRangeRule(_val.getRuleMinValue(i),
1975: _val.getRuleMaxValue(i), _val
1976: .getRuleFocusComponent(i), _val
1977: .getRuleErrorMessage(i), script);
1978: }
1979:
1980: script.append("if (theFocus != null) {\r\n");
1981: if (_useAlertsForErrors)
1982: script.append(" alert(theMessage);\r\n");
1983: else {
1984: script
1985: .append(" while( theMessage.lastIndexOf('<BR>') == (theMessage.length - 4) )\r\n");
1986: script
1987: .append(" theMessage=theMessage.substr(0,theMessage.length - 4);\r\n");
1988: script.append(" theMessage='" + breaksBefore
1989: + "' + theMessage + '" + breaksAfter + "';\r\n");
1990: script.append(" theSpan.innerHTML=theMessage;");
1991: }
1992:
1993: script.append(" theFocus.focus(); \r\n");
1994: script.append(" window.event.returnValue = false;\r\n");
1995: script.append(" return false;\r\n");
1996: script.append(" }\r\n");
1997: script.append("else\r\n");
1998: script.append(" return true;\r\n");
1999: script.append("}\r\n");
2000: script.append("</script>");
2001:
2002: return script.toString();
2003: }
2004:
2005: private void generateJavaScriptForRegExpRule(
2006: RegularExpressionMatcher regExp,
2007: HtmlFormComponent focusComp, String message,
2008: StringBuffer script) {
2009:
2010: String test = "comp != null &&";
2011: if (regExp.getHandleNull() == RegularExpressionMatcher.HANDLE_NULL_DEFAULT)
2012: test += "!(exp.test(comp.value))";
2013: else if (regExp.getHandleNull() == RegularExpressionMatcher.HANDLE_NULL_RETURN_FALSE)
2014: test += "(isNull(comp.value) || !(exp.test(comp.value)))";
2015: else
2016: test += "(! isNull(comp.value) && !(exp.test(comp.value)))";
2017:
2018: String flags = regExp.getJavaScriptFlage();
2019: String reg = "exp = new RegExp('" + regExp.getPattern() + "'";
2020: if (flags != null && flags.length() > 0)
2021: reg += ",'" + flags + "'";
2022: reg += ");\r\n";
2023: generateJavaScriptForRule(focusComp, message, script, test, reg);
2024: }
2025:
2026: private void generateJavaScriptForRangeRule(Object minValue,
2027: Object maxValue, HtmlFormComponent focusComp,
2028: String message, StringBuffer script) {
2029: String vars = "";
2030: String test = "comp != null && (";
2031: if (minValue != null) {
2032: vars += "minValue=" + formatLiteral(minValue) + ";\r\n";
2033: test += "isNull(comp.value) || " + formatComp(minValue)
2034: + " < minValue";
2035: }
2036: if (maxValue != null) {
2037: vars += "maxValue=" + formatLiteral(maxValue) + ";\r\n";
2038: if (minValue != null)
2039: test += " ||";
2040:
2041: test += formatComp(maxValue) + " > maxValue";
2042: }
2043: test += ")";
2044:
2045: generateJavaScriptForRule(focusComp, message, script, test,
2046: vars);
2047: }
2048:
2049: private String formatComp(Object val) {
2050: if (val instanceof String)
2051: return "comp.value.toUpperCase()";
2052: else if (val instanceof Date)
2053: return "new Date(comp.value)";
2054: else
2055: return "comp.value";
2056: }
2057:
2058: private String formatLiteral(Object val) {
2059: if (val instanceof Date) {
2060: GregorianCalendar cal = new GregorianCalendar();
2061: cal.setTime(((Date) val));
2062: return "new Date(" + cal.get(Calendar.YEAR) + ","
2063: + cal.get(Calendar.MONTH) + ","
2064: + cal.get(Calendar.DAY_OF_MONTH) + ")";
2065: } else if (val instanceof String)
2066: return "'" + val.toString().toUpperCase() + "'";
2067: else
2068: return val.toString();
2069: }
2070:
2071: private void generateJavaScriptForRequiredRule(
2072: HtmlFormComponent focusComp, String message,
2073: StringBuffer script) {
2074: String test = "comp != null && isNull(comp.value)";
2075: generateJavaScriptForRule(focusComp, message, script, test,
2076: null);
2077: }
2078:
2079: private void generateJavaScriptForJavaScriptRule(String test,
2080: HtmlFormComponent focusComp, String message,
2081: StringBuffer script) {
2082: test = "!(" + test + ")";
2083: generateJavaScriptForRule(focusComp, message, script, test,
2084: null);
2085: }
2086:
2087: private void generateJavaScriptForRule(HtmlFormComponent focusComp,
2088: String message, StringBuffer script, String test,
2089: String extraScript) {
2090: //fc 06/11/04: Changed the logic for generating the appropriate
2091: // javacript depending on whether the component is in
2092: // a datatable or not.
2093: if (!isComponentInDataTable(focusComp)
2094: || isInDataTableHeaderOrFooter(focusComp))
2095: generateJavaScriptForComponentByName(focusComp, focusComp
2096: .getFullName(), focusComp.getJavaScriptName(),
2097: message, script, test, extraScript);
2098: else {
2099: HtmlComponent hcDataTable = getComponentsDataTable(focusComp);
2100: JspDataTable jdt = null;
2101: HtmlDataTable hdt = null;
2102: int iStartRow = 0;
2103: int iRowsPerPage = 0;
2104: if (hcDataTable instanceof JspDataTable) {
2105: jdt = (JspDataTable) hcDataTable;
2106: iStartRow = jdt.getFirstRowOnPage();
2107: iRowsPerPage = jdt.getRowsPerPage();
2108: } else {
2109: hdt = (HtmlDataTable) hcDataTable;
2110: iStartRow = hdt.getFirstRowOnPage();
2111: iRowsPerPage = hdt.getRowsPerPage();
2112: }
2113: for (int i = iStartRow; i < iStartRow + iRowsPerPage
2114: && i < _ds.getRowCount(); i++) {
2115: generateJavaScriptForComponentByName(focusComp,
2116: focusComp.getFullName() + "_" + i, focusComp
2117: .getJavaScriptName()
2118: + "_" + i, message, script, test,
2119: extraScript);
2120: }
2121: }
2122: }
2123:
2124: //fc 06/11/04: Moved code to this method for easier implementation of
2125: // generating javascript.
2126: private void generateJavaScriptForComponentByName(
2127: HtmlFormComponent focusComp, String sCompName,
2128: String sJavaScriptName, String message,
2129: StringBuffer script, String test, String extraScript) {
2130: script.append("comp=" + getFormString() + sCompName + ";\r\n");
2131: if (extraScript != null)
2132: script.append(extraScript);
2133: if (!_multipleErrorsOK || _useAlertsForErrors) {
2134: script
2135: .append("if (theFocus == null && " + test
2136: + ") {\r\n");
2137: script.append(" theFocus=comp;\r\n");
2138: } else {
2139: script.append("if (" + test + ") {\r\n");
2140: script.append(" if (theFocus == null)\r\n");
2141: script.append(" theFocus=comp;\r\n");
2142: }
2143: if (_useAlertsForErrors)
2144: script.append(" theMessage='"
2145: + escapeSingleQuote(message) + "';\r\n");
2146: else {
2147: if (!_multipleErrorsOK)
2148: script.append(" theMessage='"
2149: + formatMessage(message, focusComp,
2150: sJavaScriptName) + "';\r\n");
2151: else
2152: script.append(" theMessage+='"
2153: + formatMessage(message, focusComp,
2154: sJavaScriptName) + "';\r\n");
2155: }
2156: script.append("}\r\n");
2157:
2158: }
2159:
2160: private String escapeSingleQuote(String messageIn) {
2161: if (messageIn.indexOf('\'') == -1)
2162: return messageIn;
2163: StringBuffer sb = new StringBuffer(messageIn.length() + 10);
2164: for (int i = 0; i < messageIn.length(); i++) {
2165: char c = messageIn.charAt(i);
2166: if (c == '\'') {
2167: sb.append('\\');
2168: sb.append('\'');
2169: } else
2170: sb.append(c);
2171: }
2172: return sb.toString();
2173: }
2174:
2175: //fc 06/11/04: Updated this method to generate proper href for error
2176: // message.
2177: private String formatMessage(String message,
2178: HtmlFormComponent focusComp, String sJavaScriptName) {
2179: String out = "";
2180:
2181: if (focusComp != null && _addFocusLinksToErrors)
2182: out += "<a href=\"javascript:"
2183: + escapeSingleQuote(sJavaScriptName)
2184: + ".focus();\">";
2185:
2186: if (_fontStartTag != null)
2187: out += _fontStartTag + fixSpecialHTMLCharacters(message)
2188: + _fontEndTag;
2189: else
2190: out += fixSpecialHTMLCharacters(message);
2191:
2192: if (focusComp != null && _addFocusLinksToErrors)
2193: out += "</a>";
2194:
2195: for (int i = 0; i < _breaksBetween; i++)
2196: out += "<BR>";
2197:
2198: return out;
2199: }
2200:
2201: private String convertJavaScript(String javaScript) {
2202: JspController cont = (JspController) getPage();
2203: StringBuffer retVal = new StringBuffer(javaScript.length());
2204: StringBuffer temp = new StringBuffer();
2205: boolean tempMode = false;
2206: for (int i = 0; i < javaScript.length(); i++) {
2207: char c = javaScript.charAt(i);
2208: if (c == '%') {
2209: if (!tempMode) {
2210: tempMode = true;
2211: temp.append(c);
2212: } else {
2213: retVal.append(checkTemp(temp, cont));
2214: temp.setLength(0);
2215: temp.append(c);
2216: }
2217: } else if (!tempMode)
2218: retVal.append(c);
2219: else {
2220: if (Character.isLetterOrDigit(c) || c == '-'
2221: || c == '_')
2222: temp.append(c);
2223: else {
2224: tempMode = false;
2225: retVal.append(checkTemp(temp, cont));
2226: retVal.append(c);
2227: temp.setLength(0);
2228: }
2229: }
2230: }
2231: if (temp.length() > 0)
2232: retVal.append(checkTemp(temp, cont));
2233:
2234: return retVal.toString();
2235: }
2236:
2237: private String checkTemp(StringBuffer temp, JspController cont) {
2238: String compName = temp.substring(1);
2239: HtmlComponent comp = cont.getComponent(compName);
2240: if (comp != null && comp instanceof HtmlFormComponent)
2241: return ((HtmlFormComponent) comp).getJavaScriptName();
2242: else
2243: return temp.toString();
2244: }
2245:
2246: private String convertJavaScript(String javaScript,
2247: DataStoreBuffer ds) {
2248: JspController cont = (JspController) getPage();
2249: StringBuffer retVal = new StringBuffer(javaScript.length());
2250: StringBuffer temp = new StringBuffer();
2251: boolean tempMode = false;
2252: for (int i = 0; i < javaScript.length(); i++) {
2253: char c = javaScript.charAt(i);
2254: if (c == '%') {
2255: if (!tempMode) {
2256: tempMode = true;
2257: temp.append(c);
2258: } else {
2259: retVal.append(checkTemp(temp, cont, ds));
2260: temp.setLength(0);
2261: temp.append(c);
2262: }
2263: } else if (!tempMode)
2264: retVal.append(c);
2265: else {
2266: if (Character.isLetterOrDigit(c) || c == '-'
2267: || c == '_')
2268: temp.append(c);
2269: else if (c == '.') {
2270: HtmlFormComponent comp = checkTemp(temp, cont, ds);
2271: if (comp != null) {
2272: retVal.append(comp.getJavaScriptName());
2273: retVal.append(c);
2274: temp.setLength(0);
2275: tempMode = false;
2276: } else
2277: temp.append(c);
2278: } else {
2279: tempMode = false;
2280: HtmlFormComponent comp = checkTemp(temp, cont, ds);
2281: if (comp == null)
2282: retVal.append(temp);
2283: else
2284: retVal.append(comp.getJavaScriptName());
2285: retVal.append(c);
2286: temp.setLength(0);
2287: }
2288: }
2289: }
2290: if (temp.length() > 0) {
2291: HtmlFormComponent comp = checkTemp(temp, cont, ds);
2292: if (comp == null)
2293: retVal.append(temp);
2294: else
2295: retVal.append(comp.getJavaScriptName());
2296: }
2297:
2298: return retVal.toString();
2299: }
2300:
2301: private HtmlFormComponent checkTemp(StringBuffer temp,
2302: JspController cont, DataStoreBuffer ds) {
2303: String compName = temp.substring(1);
2304: int colIndex = ds.getColumnIndex(compName);
2305: if (colIndex > -1) {
2306: HtmlFormComponent test = cont.getBoundComponent(ds,
2307: compName);
2308: if (test != null)
2309: return test;
2310: }
2311: HtmlComponent comp = cont.getComponent(compName);
2312: if (comp != null && comp instanceof HtmlFormComponent)
2313: return ((HtmlFormComponent) comp);
2314: else
2315: return null;
2316: }
2317:
2318: /**
2319: * Returns whether or not error messages contain links that set focus to a
2320: * field when clicked on
2321: */
2322: public boolean getAddFocusLinksToErrors() {
2323: return _addFocusLinksToErrors;
2324: }
2325:
2326: /**
2327: * Sets whether or not error messages contain links that set focus to a
2328: * field when clicked on
2329: */
2330: public void setAddFocusLinksToErrors(boolean b) {
2331: _addFocusLinksToErrors = b;
2332: }
2333:
2334: /**
2335: * Returns whether or not to use javascript for range rules
2336: */
2337: public boolean getUseJavaScriptForRangeRules() {
2338: return _useJavaScriptForRangeRules;
2339: }
2340:
2341: /**
2342: * Returns whether or not to use javascript for regular expression rules
2343: */
2344: public boolean getUseJavaScriptForRegularExpRules() {
2345: return _useJavaScriptForRegExpRules;
2346: }
2347:
2348: /**
2349: * Sets whether or not to use javascript for required rules
2350: */
2351: public boolean getUseJavaScriptForRequiredRules() {
2352: return _useJavaScriptForReqRules;
2353: }
2354:
2355: /**
2356: * Sets whether or not to use javascript for range rules
2357: */
2358: public void setUseJavaScriptForRangeRules(boolean b) {
2359: _useJavaScriptForRangeRules = b;
2360: try {
2361: //fc 06/11/04: Updated logic to make validate range dependent on
2362: // the value of _useJavaScriptForValidationOnly.
2363: getValidator().setValidateRange(
2364: !(b && _useJavaScriptForValidationOnly));
2365: } catch (Exception ex) {
2366: }
2367: }
2368:
2369: /**
2370: * Sets whether or not to use javascript for regular expression rules
2371: */
2372: public void setUseJavaScriptForRegularExpRules(boolean b) {
2373: _useJavaScriptForRegExpRules = b;
2374:
2375: try {
2376: HtmlComponentValidator v = getValidator();
2377: //fc 06/11/04: Updated logic to make validate range dependent on
2378: // the value of _useJavaScriptForValidationOnly.
2379: v
2380: .setValidateRegExp(!(b && _useJavaScriptForValidationOnly));
2381: } catch (Exception ex) {
2382: }
2383: }
2384:
2385: /**
2386: * Sets whether or not to use javascript for required rules
2387: */
2388: public void setUseJavaScriptForRequiredRules(boolean b) {
2389: _useJavaScriptForReqRules = b;
2390: try {
2391: //fc 06/11/04: Updated logic to make validate range dependent on
2392: // the value of _useJavaScriptForValidationOnly.
2393: getValidator().setValidateRequired(
2394: !(b && _useJavaScriptForValidationOnly));
2395: } catch (Exception ex) {
2396: }
2397: }
2398:
2399: //fc 06/11/04 Added this method for setting _useJavaScriptForValidationOnly
2400: /**
2401: * Sets whether or not to use javascript only for validation, by default
2402: * validates on both client and server.
2403: */
2404: public void setUseJavaScriptForValidationsOnly(boolean b) {
2405: _useJavaScriptForValidationOnly = b;
2406: }
2407:
2408: /**
2409: * Enables or disables the use of javascript for all rule types
2410: */
2411: public void setUseJavaScript(boolean b) {
2412: setUseJavaScriptForRangeRules(b);
2413: setUseJavaScriptForRequiredRules(b);
2414: setUseJavaScriptForRegularExpRules(b);
2415:
2416: }
2417:
2418: /**
2419: * @return true if the last time the validator displayed there were errors
2420: * in it
2421: */
2422: public boolean isErrorOnLastPass() {
2423: return _errorOnLastPass;
2424: }
2425:
2426: /**
2427: * @return true if component is in a datatable header or footer.
2428: */
2429:
2430: public boolean isInDataTableHeaderOrFooter(HtmlComponent comp) {
2431:
2432: Object o = comp.getParent();
2433: if (o instanceof HtmlLookUpComponent) {
2434: //Special case for the HtmlLookupComponent
2435: return isInDataTableHeaderOrFooter(comp.getParent());
2436: } else if (o instanceof JspContainer) {
2437: JspContainer cont = (JspContainer) o;
2438: int compSize = cont.getComponentCount();
2439: for (int i = 0; i < compSize; i++) {
2440: if (comp == cont.getComponent(i))
2441: return (cont.getComponentType(i) == JspContainer.TYPE_HEADER || cont
2442: .getComponentType(i) == JspContainer.TYPE_FOOTER);
2443: }
2444: }
2445:
2446: return false;
2447:
2448: }
2449:
2450: }
|