All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.form.ValidateDispatcher Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Adobe Systems Incorporated and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Adobe Systems
 * Incorporated and its suppliers and may be covered by U.S. and Foreign
 * Patents, patents in process, and are protected by trade secret or copyright
 * law. Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained from
 * Adobe Systems Incorporated.
 */
package com.adobe.xfa.form;

import com.adobe.xfa.AppModel;
import com.adobe.xfa.Arg;
import com.adobe.xfa.Element;
import com.adobe.xfa.EnumAttr;
import com.adobe.xfa.EnumValue;
import com.adobe.xfa.EventManager;
import com.adobe.xfa.ProtoableNode;
import com.adobe.xfa.Schema;
import com.adobe.xfa.ScriptHandler;
import com.adobe.xfa.XFA;
import com.adobe.xfa.template.TemplateModel;
import com.adobe.xfa.template.containers.Container;
import com.adobe.xfa.ut.BooleanHolder;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.Peer;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.ResourceLoader;
import com.adobe.xfa.ut.StringUtils;

/**
 * @exclude from public api.
 */
class ValidateDispatcher extends com.adobe.xfa.ScriptDispatcher {
	
	private final int 		meRunAt;
	private final String	msBarcodeType;
	
	
	ValidateDispatcher(Element scriptContextNode,
						String sEventContext,
						int nEventID,
						EventManager eventManager,
						String sScript,
						String sContentType,
						String sBarcodeType,
						int eRunAt) {
		super(scriptContextNode,
				sEventContext, 
				nEventID, 
				eventManager,
				sScript,
				sContentType);
		
		meRunAt = eRunAt;
		msBarcodeType = sBarcodeType;
	}

	public boolean validate(Element node) {
		
		if (node == null)
			return false;
		
		assert node instanceof FormField   ||
			   node instanceof FormSubform ||
			   node instanceof FormExclGroup;

			Container container = (Container)node;
			Container.ValidationState eValidationState = container.getValidationState();	
			
			boolean bValidateResult = validateInternal(container);

			// If validation state changes, or the reason for validation failure changes,
			// queue up a validationState event for this container.
			if (eValidationState != container.getValidationState()) {
				
				FormModel formModel = (FormModel)(node.getModel());
				formModel.addValidationStateChanged(container);
			}

			return bValidateResult;
	}
	
	private boolean validateInternal(Container node) {
		
		String sScript = getScript();
		String sContentType = getContentType();

		FormModel formModel = (FormModel)node.getModel();

		if (!formModel.getValidationsEnabled())
			return true;

		int eModelRunAtSetting = formModel.getRunScripts();
		int eRunAt = getRunAt();

		// ensure we can run the script
		if (eModelRunAtSetting == EnumAttr.RUNSCRIPTS_NONE)
			return true;
		else if (eModelRunAtSetting == EnumAttr.RUNSCRIPTS_SERVER && eRunAt == EnumAttr.RUNAT_CLIENT)
			return true;
		else if (eModelRunAtSetting == EnumAttr.RUNSCRIPTS_CLIENT && eRunAt == EnumAttr.RUNAT_SERVER)
			return true;

		Arg returnCode = new Arg();
		
		node.setErrorText("");
		node.setValidationState(Container.ValidationState.VALIDATIONSTATE_VALID);

		Element validateNode = node.getElement(XFA.VALIDATETAG, true, 0, false, false);

		boolean bNullTest = false;
		boolean bFormatTest = false;
		boolean bScriptTest = false;
		boolean bBarcodeTest = !StringUtils.isEmpty(msBarcodeType);

		if (validateNode != null) {
			bNullTest = validateNode.getEnum(XFA.NULLTESTTAG) != EnumAttr.TEST_DISABLED;
			bFormatTest = validateNode.getEnum(XFA.FORMATTESTTAG) != EnumAttr.TEST_DISABLED;
			bScriptTest = validateNode.getEnum(XFA.SCRIPTTESTTAG) != EnumAttr.TEST_DISABLED;
		}
				
		// no dependency tracking for subform
		if (node instanceof FormField ||
			node instanceof FormExclGroup) {
			// remove old Dependencies
			formModel.removeDependency(node,false);

			// For null fields we ignore the results of the validation script.  However,
			// it's necessary to execute the script anyway, to set up dependencies.
			
			FormDependencyTracker tracker = new FormDependencyTracker(node, false);
			try {
				if (bScriptTest && !StringUtils.isEmpty(sScript))
					returnCode = node.evaluate(sScript, sContentType, ScriptHandler.VALIDATE, true);

				// the field is dependent on itself so if there is no script (nullTest and formatTest) or
				// if the script doesn't compare itself with something (not a very good validation script)
				// we still want the validations to fire when the field change (before the exit event).
				tracker.addDependency(node);
			}
			finally {
				tracker.dispose();
			}
		}
		else {
			// subform -- no dependency tracking
			if (!StringUtils.isEmpty(sScript))
				returnCode = node.evaluate(sScript, sContentType, ScriptHandler.VALIDATE, true);
		}

		FormModel.Validate validate = formModel.getValidate();

		if (validate == null)
			validate = formModel.getDefaultValidate();

		if (validate != null) {
			if (formModel.isActivityExcluded("validate"))
				return true;

			if (formModel.isActivityExcluded("scriptTest"))
				bScriptTest = false;
			else
				bScriptTest = bScriptTest && validate.isScriptTestEnabled() && !node.getIsNull();

			if (formModel.isActivityExcluded("nullTest"))
				bNullTest = false;
			else
				bNullTest = bNullTest && validate.isNullTestEnabled() && node.getIsNull();
			
			if (formModel.isActivityExcluded("formatTest"))
				bFormatTest = false;
			else
				bFormatTest = bFormatTest && validate.isFormatTestEnabled() && 
					                !node.getIsNull() && node instanceof FormField;
			
			if (formModel.isActivityExcluded("barcodeTest"))
				bBarcodeTest = false;
			else
				bBarcodeTest = bBarcodeTest && validate.isBarcodeTestEnabled() && 
									!node.getIsNull();

			// get the current value for validate.disable
			boolean bOldDisableValidate = false;
			if (validateNode != null && validateNode.isPropertySpecified(XFA.DISABLEALLTAG, true, 0))
				bOldDisableValidate = validateNode.getEnum(XFA.DISABLEALLTAG) == EnumAttr.BOOL_TRUE;
			
			BooleanHolder bDisableValidate = new BooleanHolder(bOldDisableValidate);

			// barcode test
			
			if (bBarcodeTest) {
				// Get the value
				String sValue = ((FormField)node).getRawValue();
				// Validate it
				if (!validate.validateBarcode(node, msBarcodeType, sValue)) {
					FormField formField = (FormField)node;
					int oResId = 0;
					if (StringUtils.isEmpty(sValue))
						// "Invalid Barcode Value: Empty value is not a valid value for barcodes of type %1."
						oResId = ResId.NullBarcodeValue;
					else
						// "Invalid Barcode Value: %1 is an invalid value for barcodes of type %2."
						oResId = ResId.InvalidBarcodeValue;

					MsgFormatPos error = new MsgFormatPos(oResId);
					if (!StringUtils.isEmpty(sValue))
						error.format(sValue);
					error.format(msBarcodeType);
					
					String sMessage = error.toString();
					node.setErrorText(sMessage);
					node.setValidationState(Container.ValidationState.VALIDATIONSTATE_BARCODETEST);

					if (!validate.onValidateBarcodeTestFailed(formField, sMessage))
						return false;
				}
			}

			// null test

			if (bNullTest) {
				//Lookup error string.
				//XFA spec says it's the  element named "nullTest"
				String sMessage = FormModel.getValidationMessage(validateNode, XFA.NULLTEST);

				//Stop validating if false is returned. 
				boolean bRetVal = validate.onValidateNullTestFailed((ProtoableNode)node, sMessage, bDisableValidate);
				
				// if disableValidate has been set, update validate.disableAll
				if (bDisableValidate.value && bDisableValidate.value != bOldDisableValidate)
					updateDisableAll(node);
				
				// Provide default errorText, if necessary
				if (StringUtils.isEmpty(sMessage)) {
					sMessage = ResourceLoader.loadResource(ResId.ValidationFailed);
				}
				
				node.setErrorText(sMessage);
				node.setValidationState(Container.ValidationState.VALIDATIONSTATE_NULLTEST);
				
				if (!bRetVal)
					return false;
			}
			
			// format test

			if (bFormatTest) {
				FormField formField = (FormField)node;

				//Determine whether the picture formatting
				//is valid wrt to the rawvalue.
				if (!formField.hasValidFormattedValue()) {
					//Lookup error string.
					//XFA spec says it's the  element named "formatTest"
					String sMessage = FormModel.getValidationMessage(validateNode, XFA.FORMATTEST);
												
					//Stop validating if false is returned. 
					boolean bRetVal = validate.onValidateFormatTestFailed(formField, sMessage, bDisableValidate);
					
					// if disableValidate has been set, update validate.disableAll
					if (bDisableValidate.value && bDisableValidate.value != bOldDisableValidate)
						updateDisableAll(node);
					
					// Provide default errorText, if necessary
					if (StringUtils.isEmpty(sMessage)) {
						sMessage = ResourceLoader.loadResource(ResId.ValidationFailed);
					}

					node.setErrorText(sMessage);
					node.setValidationState(Container.ValidationState.VALIDATIONSTATE_FORMATTEST);
					
					if (!bRetVal)
						return false;
				}
			}
			
			// script test
			boolean bRet = true;
			if (bScriptTest) {
				if (StringUtils.isEmpty(sScript))
					return true;

				// Allow a commented-out script (or one which returns no value) to pass validation
				boolean bValidate = (returnCode.getArgType() == Arg.EMPTY
						            || returnCode.getArgType() == Arg.NULL
									|| returnCode.getAsBool(false).booleanValue());

				if (!bValidate) {
					// Watson 2460535: (mergedXDP) Need to get the validation node again since the validation 
					// message might have been updated by the script. 
					validateNode = node.getElement(XFA.VALIDATETAG, 0);
					
					//Look up the validation message. 
					//According to XFA spec it's the  element named "scriptTest"
					//or with no name.
					String sMessage = FormModel.getValidationMessage(validateNode, XFA.SCRIPTTEST);
			
					validate.onValidateScriptFailed((ProtoableNode)node, sScript, sContentType, sMessage, bDisableValidate);
					
					// if disableValidate has been set, update validate.disableAll
					if (bDisableValidate.value && bDisableValidate.value != bOldDisableValidate)
						updateDisableAll(node);
					
					// Provide default errorText, if necessary
					if (StringUtils.isEmpty(sMessage)) {
						sMessage = ResourceLoader.loadResource(ResId.ValidationFailed);
					}

					node.setErrorText(sMessage);
					node.setValidationState(Container.ValidationState.VALIDATIONSTATE_SCRIPTTEST);

					
					bRet = false;
				}
			}
			
			return bRet;
		}
		
		return true;
	}
	
	private void updateDisableAll(Element node) {
		assert node != null;
		
		if (node != null) {
			Element validate = node.getElement(XFA.VALIDATETAG, 0);
			if (validate != null)
				validate.setAttribute(EnumValue.getEnum(XFA.DISABLEALLTAG, EnumAttr.BOOL_TRUE), XFA.DISABLEALLTAG);
		}
	}
	
	public void dispatch() {
		Element node = getActionContextNode();
		if (node == null)
			return;
		

		// As of //https://zerowing.corp.adobe.com/display/xtg/InactivePresenceXFAProposal,
		// event processing associated with inactive containers must not occur.	
		// To mitigate performance on older forms, only do this check for XFA 3.0 documents and higher.
		AppModel appModel = node.getAppModel();
		if (appModel != null) {
			TemplateModel templateModel = TemplateModel.getTemplateModel(appModel, false);
			if ((templateModel != null) &&
				(templateModel.getOriginalXFAVersion() >= Schema.XFAVERSION_30) &&
				(node instanceof Container)) {
				Container poContainerImpl = (Container)node;
				int ePresence = poContainerImpl.getRuntimePresence(EnumAttr.UNDEFINED);
				if (EnumAttr.PRESENCE_INACTIVE == ePresence)
					return;
			}
		}
		
	    validate(node);
	}

	public String getDispatcherType() {
		return "validate";
	}

	int getRunAt() {
		return meRunAt;
	}
	
	@Override
	public void updateFromPeer(Object peerNode, 
						int eventType, 
						String arg1, 
						Object arg2) {
		
		Element node = getActionContextNode();
		if (node == null)
			return;
		
		// Change of presence means we need to queue validates 
		// (In case the object was inactive before)
		// This won't do anything if the object is still inactive.
		if (peerNode == node && 
		   node instanceof Container &&
		   eventType == Peer.ATTR_CHANGED && 
		   arg1.equals(XFA.PRESENCE) ) {
			// note would be nice to directly access mpoNodeImpl->mpModel
			FormModel formModel = (FormModel)node.getModel();
			formModel.queueCalculatesAndValidates(node, true);
		}	
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy