001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.validation.impl;
018:
019: import java.util.Map;
020:
021: import org.apache.avalon.framework.CascadingRuntimeException;
022: import org.apache.avalon.framework.context.Context;
023: import org.apache.cocoon.components.ContextHelper;
024: import org.apache.cocoon.forms.formmodel.Widget;
025: import org.apache.cocoon.forms.util.JavaScriptHelper;
026: import org.apache.cocoon.forms.validation.ValidationError;
027: import org.apache.cocoon.forms.validation.ValidationErrorAware;
028: import org.apache.cocoon.forms.validation.WidgetValidator;
029: import org.apache.excalibur.xml.sax.XMLizable;
030: import org.mozilla.javascript.Function;
031:
032: /**
033: * A {@link org.apache.cocoon.forms.validation.WidgetValidator} implemented as a JavaScript snippet.
034: * <p>
035: * This snippet must return a value which can be of different types. The only way to indicate
036: * successfull validation is to return a boolean <code>true</code> value.
037: * <p>
038: * To indicate validation error, a number of result types are possible:
039: * <ul>
040: * <li>A boolean <code>false</code>: the validator <strong>must</strong> then have
041: * set a validation error on the validated widget or one of its children.</li>
042: * <li>A {@link ValidationError}: this error is then set on the validated widget.</li>
043: * <li>A <code>String</code>: a validation error using that string as a non-i18nized message is
044: * then set on the validated widget</li>
045: * <li>An <code>XMLizable</code> such as {@link org.apache.cocoon.forms.util.I18nMessage}: this
046: * xmlizable is used to build a validation error that is set on the validated widget.</li>
047: * </ul>
048: * <p>
049: * The JavaScript snippet has the "this" and "widget" variables set to the validated widget, and, if the form
050: * is used in a flowscript, can use the flow's global values and fonctions and the <code>cocoon</code> object.
051: *
052: * @version $Id: JavaScriptValidator.java 449149 2006-09-23 03:58:05Z crossley $
053: */
054: public class JavaScriptValidator implements WidgetValidator {
055:
056: private final Function function;
057: private final Context avalonContext;
058:
059: public JavaScriptValidator(Context context, Function function) {
060: this .function = function;
061: this .avalonContext = context;
062: }
063:
064: public final boolean validate(Widget widget) {
065:
066: Map objectModel = ContextHelper
067: .getObjectModel(this .avalonContext);
068:
069: Object result;
070:
071: try {
072: result = JavaScriptHelper.callFunction(this .function,
073: widget, new Object[] { widget }, objectModel);
074: } catch (RuntimeException re) {
075: throw re; // rethrow
076: } catch (Exception e) {
077: throw new CascadingRuntimeException(
078: "Error invoking JavaScript event handler", e);
079: }
080:
081: if (result == null) {
082: throw new RuntimeException(
083: "Validation script did not return a value");
084: }
085:
086: if (result instanceof Boolean) {
087: return ((Boolean) result).booleanValue();
088: }
089:
090: if (result instanceof ValidationError) {
091: // Set the validation error on the widget
092: ((ValidationErrorAware) widget)
093: .setValidationError((ValidationError) result);
094: return false;
095: }
096:
097: if (result instanceof String) {
098: // Set a non-i18n error on the current widget
099: ((ValidationErrorAware) widget)
100: .setValidationError(new ValidationError(
101: (String) result, false));
102: return false;
103: }
104:
105: if (result instanceof XMLizable) {
106: // Set a xmlizable error (e.g. I18nMessage) on the current widget
107: ((ValidationErrorAware) widget)
108: .setValidationError(new ValidationError(
109: (XMLizable) result));
110: return false;
111: }
112:
113: throw new RuntimeException(
114: "Validation script returned an unexpected value of type "
115: + result.getClass());
116: }
117: }
|