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

com.adobe.xfa.Obj Maven / Gradle / Ivy

/*
 * 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;

import com.adobe.xfa.ut.Assertions;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.MsgFormat;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.Peer;
import com.adobe.xfa.ut.PeerImpl;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.StringUtils;


/**
 * A base class to represent all XFA objects, templates and data.
 * The methods defined in this class are primarily for use in scripting environments.
 */
public abstract class Obj implements Peer {

	private PeerImpl mPeers;
	private String maClassName;	// interned
	private int meClassTag; // Default class tag XFA.INVALID_ELEMENT indicates we're not part

	/**
	 * @exclude from published api.
	 */
	public Obj() {
		maClassName = null;
		meClassTag = XFA.INVALID_ELEMENT;
	}

	/**
	 * @exclude from published api.
	 */
	final public void addPeer(Peer poPeerNode) {
		if (mPeers == null) {
			mPeers = new PeerImpl(this);
		}
		
		mPeers.addPeer(poPeerNode);
	}

	/**
	 * @exclude from published api.
	 */
	final public void addPeeredNode(Peer poPeer) {
		if (mPeers == null) {
			mPeers = new PeerImpl(this);
		}
		
		mPeers.addPeeredNode(poPeer);
	}

	/**
	 * @exclude from published api.
	 */
	final public void clearPeers() {
		if (mPeers != null)
			mPeers.clearPeers();
	}
	
	/**
	 * @exclude from published api.
	 */
	final public void deafen() {
		if (mPeers == null) {
			mPeers = new PeerImpl(this);
		}

		mPeers.deafen();
	}

	/**
	 * recursive method, Find the function description
	 * @param table
	 * @param sName the function name.
	 *
	 * @exclude from published api.
	 */
	private ScriptFuncObj findScriptFunc(ScriptTable table, String sName) {
		while (table != null) {
		
			// ensure the script table has a listing for functions
			if (table.mFuncTable != null) {
				// loop through until you find a property that matches the name
				final ScriptFuncObj[] funcTable = table.mFuncTable;
				for (int i = 0; i < funcTable.length; i++) {
					final ScriptFuncObj funcObj = funcTable[i];
					if (sName.equals(funcObj.getName())) {
						return funcObj;
					}
				}
			}
			
			// no match found, search parent class
			table = table.mParentClass;
		}

		return null;
	}

	/**
	 * recursive method, Find the property description
	 * @param table
	 * @param sName the property name
	 *
	 * @exclude from published api.
	 */
	private ScriptPropObj findScriptProp(ScriptTable table, String sName) {
		
		while (table != null) {
		
			// ensure the script table has a listing for properties
			if (table.mPropTable != null) {
				// loop through until you find a property that matches the name
				final ScriptPropObj[] propTable = table.mPropTable;
				for (int i = 0; i < propTable.length; i++) {
					final ScriptPropObj propObj = propTable[i];
					
					if (sName.equals(propObj.getName() == null ? "" : propObj.getName()))
						return propObj;
				}
			}
			
			// no match found, search parent class
			table = table.mParentClass;
		}

		return null;
	}

	/**
	 * Set the class name and class tag for this node instance.
	 * @param sClassName This String must be interned.
	 * @param eClassTag
	 *
	 * @exclude from published api.
	 */
	@FindBugsSuppress(code="ES")
	public final void setClass( String sClassName, int eClassTag ) {
		if (Assertions.isEnabled) if ( sClassName != null ) assert(sClassName == sClassName.intern());
		maClassName = sClassName;
		meClassTag = eClassTag;
	}
	
	/**
	 * @exclude from published api.
	 */
	public final void setClassTag( int eClassTag ) {
		meClassTag = eClassTag;
	}
	
	/**
	 * @exclude from published api.
	 */
	public final int getClassTag() {
		return meClassTag;
	}
	
	/**
	 * Returns the atomic name of this element's class.
	 * @return the class name as an interned string.
	 *
	 * @exclude from published api.
	 */
	public /*final*/ String getClassAtom() {
//		assert maClassName != null;
		return maClassName;
	}

	/**
	 * Gets the name of this object's class.
	 * Overriden by derived classes such as Element that have a local name
	 * that may be returned instead.
	 * @return the class name.
	 *
	 * @exclude from published api.
	 */
	public String getClassName() {
		return getClassAtom();
	}

	/**
	 * if bPeek, return a function in oDesc that won't create any objects if
	 * called, and return FALSE if the property isn't specified.
	 *
	 * @exclude from published api.
	 */
	protected ScriptDynamicPropObj getDynamicScriptProp(String sPropertyName, boolean bPropertyOverride, boolean bPeek) {
		return null;
	}

	/**
	 * @param bCreate
	 *            if true, create if the map doesn't exist.
	 * @return The event table
	 *
	 * @exclude from published api.
	 */
	protected EventManager.EventTable getEventTable(boolean bCreate) {
		return null;
	}

	/**
	 * Gets the requested peer.
	 * 
	 * @param nPeer
	 *            the 0-based position of the peer to retrieve.
	 * @return the peer at the requested position. When there are not more peers
	 *         to return, this will return a null object.
	 *
	 * @exclude from published api.
	 */
	final public Peer getPeer(int nPeer /* =0 */) {
		if (mPeers == null) {
			return null;
		}
		return mPeers.getPeer(nPeer);
	}

	/**
	 * Gets the information on a script method.
	 * @param sName the name of the method
	 * @return the script function object or null if not found.
	 *
	 * @exclude from published api.
	 */
	public ScriptFuncObj getScriptMethodInfo(String sName) {
		return findScriptFunc(getScriptThis().getScriptTable(), sName);
	}

	/**
	 * @param sPropertyName
	 * @return the script property with the specified name, or null if not found.
	 * 
	 * @exclude from published api.
	 */
	protected ScriptPropObj getScriptProp(String sPropertyName) {
		return findScriptProp(getScriptTable(), sPropertyName);
	}

	/**
	 * @exclude from published api.
	 */
	public boolean getScriptProperty(Arg retValue,
									String sPropertyName,
									DependencyTracker dependencyTracker /* = null */,
									boolean bPeek /* = false */,
									boolean bSuppressExceptions /* = false */) {

		// bPropertyOverride(#sPropertyName) means don't hunt for child nodes by name
		// only get xfaproperty or child element(based on classname) or script property
		boolean bPropertyOverride = sPropertyName.startsWith("#");

		String sPropName;
		if (bPropertyOverride)
			sPropName = sPropertyName.substring(1); // Skip over "#"
		else
			sPropName = sPropertyName;

        // first add any virtual dependencies
	    if (dependencyTracker != null)
	        dependencyTracker.addVirtualDependency(this, sPropertyName);
		
	    Obj scriptThis = getScriptThis();

		boolean bGotDynamicScriptProp = false;
		boolean bHasDynamicProp = false;

		if (sPropName.length() != 0) {
			ScriptDynamicPropObj desc = scriptThis.getDynamicScriptProp(sPropName, bPropertyOverride, bPeek);

			if (desc != null) {
				
				assert desc.hasGetter();
				
				if (!validateUsage(desc.getXFAVersion(), desc.getAvailability(), false)) {
					final boolean bIsFatal = validateUsageFailedIsFatal(desc.getXFAVersion(), desc.getAvailability());
					
					if (bIsFatal && bSuppressExceptions)
						return false;
					
					if (bIsFatal) {
						MsgFormatPos message = new MsgFormatPos(ResId.InvalidGetPropertyException);
						message.format(scriptThis.getClassAtom());
						message.format(sPropName);
						retValue.setException(new ExFull(message));
						return true;
					}
					else { // warn							
						MsgFormatPos reason = new MsgFormatPos(ResId.InvalidScriptVersionException);
						reason.format(getClassAtom());
						reason.format(sPropName);
						sendMessenge(new ExFull(reason), LogMessage.MSG_WARNING);
					}
				}
				
				bHasDynamicProp = true;
				
				bGotDynamicScriptProp = desc.invokeGetProp(this, retValue, sPropName);
			}
		}

		if (! bGotDynamicScriptProp) {

			ScriptPropObj prop = getScriptProp(sPropName);
			if (prop != null && prop.hasGetter()) {
				
				if (!validateUsage(prop.getXFAVersion(), prop.getAvailability(), false)) {
					final boolean bIsFatal = validateUsageFailedIsFatal(prop.getXFAVersion(), prop.getAvailability());
					
					if (bIsFatal && bSuppressExceptions)
						return false;
					
					if (bIsFatal) {
						MsgFormatPos message = new MsgFormatPos(ResId.InvalidGetPropertyException);
						message.format(scriptThis.getClassAtom());
						message.format(sPropName);
						retValue.setException(new ExFull(message));
					}
					else {
						MsgFormatPos reason = new MsgFormatPos(ResId.InvalidScriptVersionException);
						reason.format(getClassAtom());
						reason.format(sPropName);
						sendMessenge(new ExFull(reason), LogMessage.MSG_WARNING);
					}
				}				
				
				prop.invokeGetProp(this, retValue, dependencyTracker);
			}
			else if (prop != null && bHasDynamicProp) {
				// Don't suppress because the user needs to know they are trying get a property
				// with only a set function
				MsgFormatPos message = new MsgFormatPos(ResId.InvalidGetPropertyException);
				message.format(scriptThis.getClassAtom());
				message.format(sPropName);
				retValue.setException(new ExFull(message));
			}
			else {
				if (bSuppressExceptions)
					return false;

				if (sPropName.length() == 0) {
					// default property
					MsgFormatPos message = new MsgFormatPos(
							ResId.NoDefaultGetPropertyException, getClassAtom());
					retValue.setException(new ExFull(message));
				} else {
					MsgFormatPos message = new MsgFormatPos(
							ResId.InvalidGetPropertyException, getClassAtom());
					message.format(sPropName);
					retValue.setException(new ExFull(message));
				}
			}
		}
		
		// track dependencies if required
		if (dependencyTracker != null) {
			int eType = retValue.getArgType();
			if (eType != Arg.EXCEPTION)
				dependencyTracker.addDependency(this);
		}
		
		return true;
	}

	/**
	 * @exclude from published api.
	 */
	public ScriptTable getScriptTable() {
		return ObjScript.getScriptTable();
	}

	/**
 	 * Gets the object to be used in concert with getScriptTable() etc.
 	 * It's almost always "this", but it needs to be overridable to support the $record
 	 * pseudomodel, which redirects all script properties to the current record.  Simply
 	 * overriding getScriptTable and redirecting that call to the current record doesn't
 	 * work, because when a callback function is invoked, the supplied object pointer
 	 * would be the pseudo model, not the record.
	 *
	 * @exclude from published api.
	 */
 	public Obj getScriptThis() {
 		return this;
 	}

	/**
	 * Call a scripting function (method).
	 * 
	 * @param sFunctionName
	 *            The name of the function/method to call. If this parameter is
	 *            an empty string, then an attempt is made to invoke a default
	 *            function.
	 * @param parameters
	 *            an array of parameters to the method.
	 * @return the return value of the function.
	 * @exception ResId.InvalidMethodException
	 *                if the function name is unknown.
	 * @exception ResId.BadParamCountException
	 *                if the number of parameters in nParamCount is not valid
	 *                for the specified fucntion.
	 * @exception ResId.ArgumentMismatchException
	 *                if one or more of the argument types in pParameters is
	 *                incorrect for the specified function.
	 * @exception ResId.NoDefaultMethodException
	 *                if sFunctionName is an empty string, and the object
	 *                doesn't have a default function.
	 *
	 * @exclude from published api.
	 */
	public boolean invokeFunction(Arg retValue,
								  String sFunctionName,
								  Arg[] parameters,
								  DependencyTracker dependencyTracker /* = null */,
								  boolean bSuppressExceptions /* = false */) {
		Obj scriptThis = getScriptThis();
		ScriptFuncObj func = getScriptMethodInfo(sFunctionName);
		if (func != null) {
			if (!validateUsage(func.getXFAVersion(), func.getAvailability(), false)) {
				final boolean bIsFatal = validateUsageFailedIsFatal(func.getXFAVersion(), func.getAvailability());
				
				if (bIsFatal && bSuppressExceptions)
					return false;
				
				MsgFormatPos reason = new MsgFormatPos(ResId.InvalidScriptVersionException);
				reason.format(getClassAtom());
				reason.format(sFunctionName);
				
				if (bIsFatal)
					throw new ExFull(reason);
				else // warn
					sendMessenge(new ExFull(reason), LogMessage.MSG_WARNING);
			}			
			
			//
			// check that we have a min num of params
			//
			if (parameters.length < func.getMinParam()) {
				// don't suppress bad param exceptions: these need to
				// be returned to the user so they know what is wrong
				throw new ExFull(new MsgFormat(ResId.BadParamCountException, sFunctionName));
			}
			for (int i = 0; i < parameters.length; i++) {
				//
				// ensure we are less than the max num of params.
				//
				if (i == func.getParamTypes().length) {
					// don't suppress bad param exceptions: these need to
					// be returned to the user so they know what is wrong
					throw new ExFull(new MsgFormat(ResId.BadParamCountException, sFunctionName));
				}
				//
				// ensure the params are correct
				//
				if (func.getParamTypes()[i] != Arg.INVALID
						&& ! parameters[i].isCompatibleWith(func.getParamTypes()[i])) {
					//
					// don't suppress bad param exceptions: these need to
					// be returned to the user so they know what is wrong
					//
					throw new ExFull(ResId.ArgumentMismatchException);
				}
			}
			//
			// params must be ok; check permissions
			if (!func.invokePermsFunc(this, parameters)) {
				MsgFormatPos message = new MsgFormatPos(ResId.PermissionsViolationExceptionMethod);
				message.format(sFunctionName);
				throw new ExFull(message);
			}
			
			//
			// call function
			//
			func.invoke(scriptThis, retValue, parameters, dependencyTracker);

			// ensure the return type is correct
			int nRetType = func.getRetType();
			//
			// JavaPort: TODO.  This is new in Java -- this code originally
			// asserted, but this isn't programming error; it's a scripting error:
			// the function the user called, returned something unexpected (it
			// likely threw an exception which got caught and didn't ripple
			// through the reflection API).  Moreover, this probably needs
			// a different ResId.
			//
			if (nRetType == Arg.INVALID || retValue.isCompatibleWith(nRetType)) {
				if (bSuppressExceptions)
					return false;
			//	MsgFormatPos message = new MsgFormatPos(ResId.InvalidMethodException);
			//	message.format(scriptThis.getClassAtom());
			//	message.format(sFunctionName);
			//	retValue.setException(new ExFull(message));
			}
		}
		else if (StringUtils.isEmpty(sFunctionName)) {
			if (bSuppressExceptions)
				return false;
			//
			// default method
			//
			MsgFormatPos message = new MsgFormatPos(ResId.NoDefaultMethodException);
			message.format(scriptThis.getClassAtom());
			retValue.setException(new ExFull(message));
		}
		else {
			if (bSuppressExceptions)
				return false;
			MsgFormatPos message = new MsgFormatPos(ResId.InvalidMethodException);
			message.format(scriptThis.getClassAtom());
			message.format(sFunctionName);
			retValue.setException(new ExFull(message));
		}
		//
		// track dependencies if required
		//
		if (dependencyTracker != null) {
			int eType = retValue.getArgType();
			if (eType != Arg.EXCEPTION)
				dependencyTracker.addDependency(this);
		}
		return true;
	}

	/**
	 * @exclude from published api.
	 */
	final public boolean isDeaf() {
		if (mPeers == null) {
			return false;
		}
		return mPeers.isDeaf();
	}

	/**
	 * @exclude from published api.
	 */
	final public boolean isMute() {
		if (mPeers == null) {
			return false;
		}
		return mPeers.isMute();
	}

	/**
	 * Determine if the class of this object is the same as the Obj class.
	 * 
	 * @param oClass
	 *            Obj to check the class with.
	 * @return true if the classes are the same, else false.
	 *
	 * @exclude from published api.
	 */
	@FindBugsSuppress(code="ES")
	public final boolean isSameClass(Obj oClass) {
		return oClass.getClassAtom() == getClassAtom();
	}

	/**
	 * Determine if the class of this object is the same as the String sClass.
	 * Note: Works only when comparing to the same actual string instance (from
	 * the XFA namespace). For example, isSameClass(XFA::nodeTag()) will work if
	 * the object in question is an Obj. However, isSameClass("node") will not
	 * work even though the two strings are equal. See the
	 * SharesImpl method of String.
	 * 
	 * @param aClass
	 *            string from the XFA namespace. This String must be interned.
	 * @return true if the classes are the same, else false.
	 *
	 * @exclude from published api.
	 */
	@FindBugsSuppress(code="ES")
	public final boolean isSameClass(String aClass) {
		return aClass == getClassAtom();
	}
	
	/**
	 * Determine if the class of this object is the same as the class tag.
	 * 
	 * @param eClassTag
	 *            string from the XFA namespace.
	 * @return true if the classes are the same, else false.
	 *
	 * @exclude from published api.
	 */
	public final boolean isSameClass(int eClassTag) {
	    return (eClassTag == meClassTag);
	}
	
	/**
	 * @exclude from published api.
	 */
	final public void mute() {
		if (mPeers == null) {
			mPeers = new PeerImpl(this);
		}
		mPeers.mute();
	}

	/**
	 * @exclude from published api.
	 */
	public void notifyPeers(int eventType, String arg1, Object arg2) {
		if (mPeers == null) {
			return;
		}
		mPeers.notifyPeers(eventType, arg1, arg2);
	}

	/**
	 * Remove a peer node from the notification list.
	 * 
	 * @param peerNode
	 *            The reference to the peer object to be removed.
	 *
	 * @exclude from published api.
	 */
	final public void removePeer(Peer peerNode) {
		if (mPeers == null) {
			return;
		}
		mPeers.removePeer(peerNode);
	}

	/**
	 * @exclude from published api.
	 */
	final public void removePeeredNode(Peer peer) {
		if (mPeers == null) {
			return;
		}
		mPeers.removePeeredNode(peer);
	}
	
	/**
	 * Send message to host so it can be logged
	 * @param error contains message Id and text
	 * @param eSeverity the message severity
	 * @exclude from published api.
	 */
	public void sendMessenge(ExFull error, int eSeverity /* = LogMessage.MSG_WARNING */) {
		// Do nothing - derived classes may override
	}

	/**
	 * @param sPropertyName
	 *            The name of the property to set. If this parameter is an empty
	 *            string, then an attempt is made to set the default property.
	 * @param propertyValue
	 *            The value of assign to this property.
	 * @param bSuppressExceptions 
	 * 			If true, quietly return false on error, else throw an exception for any errors.
	 * @exception NoDefaultSetPropertyException
	 *                if sPropertyName is an empty string, and the object does
	 *                not have a default property.
	 * @exception InvalidSetPropertyException
	 *                if sPropertyName is not a valid property for the object.
	 *
	 * @exclude from published api.
	 */
	public boolean setScriptProperty(String sPropertyName,
									Arg propertyValue,
									boolean bSuppressExceptions /* = false */) {

		// bPropertyOverride(#sPropertyName) means don't hunt for child nodes by name 
		// only get xfaproperty or child element(based on classname) or script property
		boolean bPropertyOverride = sPropertyName.startsWith("#");
		String sPropName;
		if (bPropertyOverride)
			sPropName = sPropertyName.substring(1);		// Skip over "#"
		else
			sPropName = sPropertyName;

		boolean bError = false;
		Obj scriptThis = getScriptThis();

		// bPropertyOverride means don't hunt for child nodes -- only properties are wanted
		if (sPropertyName.length() != 0) {
			ScriptDynamicPropObj desc = scriptThis.getDynamicScriptProp(sPropName, bPropertyOverride, false);
		
			if (desc != null) {

				boolean bReturnVal = false;
				
				// validate that the property exist for this version of the doc, and for this client
				if (!validateUsage(desc.getXFAVersion(), desc.getAvailability(), false)) {
					final boolean bIsFatal = validateUsageFailedIsFatal(desc.getXFAVersion(), desc.getAvailability());
					
					if (bIsFatal && bSuppressExceptions)
						return false;

					MsgFormatPos reason = new MsgFormatPos(ResId.InvalidScriptVersionException);
					reason.format(getClassAtom());
					reason.format(sPropName);
					
					if (bIsFatal)
						throw(new ExFull(reason));
					else // warn
						sendMessenge(new ExFull(reason), LogMessage.MSG_WARNING);
				}
				
				if (desc.hasSetter()) {
					// check permission
					if (!desc.invokePermsFunc(this)) {
						MsgFormatPos message = new MsgFormatPos(ResId.PermissionsViolationExceptionProperty);
						if (StringUtils.isEmpty(sPropName))
							message.format(getClassAtom());
						else
							message.format(sPropName);
						throw new ExFull(message);
					}
					
					bReturnVal = desc.invokeSetProp(this, propertyValue, sPropName);
				}

				if (bReturnVal)
					return true;
				else if (desc.hasGetter()) {
					Arg retVal = new Arg();
					boolean bGetProp = desc.invokeGetProp(this, retVal, sPropName);
					if (bGetProp && retVal.getArgType() == Arg.OBJECT) {
						Obj obj = retVal.getObject();
						return obj.setScriptProperty("", propertyValue, bSuppressExceptions);
					}
				}
				
				// Don't suppress because the user needs to know they are trying to update
				// a read property
				MsgFormatPos message = new MsgFormatPos(ResId.InvalidSetPropertyException);
				message.format(scriptThis.getClassAtom());
				message.format(sPropertyName);
				throw new ExFull(message);
			}
		}
		
		if (! bError) {
			ScriptPropObj prop = getScriptProp(sPropName);
			
			if (prop != null) {
			
				// validate that the property exists for this version of the doc, and for this client
				if (!validateUsage(prop.getXFAVersion(), prop.getAvailability(), false)) {
					final boolean bIsFatal = validateUsageFailedIsFatal(prop.getXFAVersion(), prop.getAvailability());					
					
					if (bIsFatal && bSuppressExceptions)
						return false;
					
					MsgFormatPos reason = new MsgFormatPos(ResId.InvalidScriptVersionException);
					reason.format(getClassAtom());
					reason.format(sPropertyName);
					if (bIsFatal)
						throw new ExFull(reason);
					else // warn
						sendMessenge(new ExFull(reason), LogMessage.MSG_WARNING);
				}
				
				if (prop.hasSetter()) {				
					// ensure the params are correct
					if (prop.getParamType() != Arg.INVALID && ! propertyValue.isCompatibleWith(prop.getParamType())) {
						// don't suppress bad param exceptions, these need to be returned to the user so they know what
						// is wrong
						throw new ExFull(ResId.ArgumentMismatchException);
					}
		
					// check permissions
					if (!prop.invokePermsFunc(this)) {
						MsgFormatPos message = new MsgFormatPos(ResId.PermissionsViolationExceptionProperty);
						message.format(sPropName);
						throw new ExFull(message);
					}

					
					//
					// The XFAArg::INVALID check guarding the isCompatibileWith() call above exists because
					// field value checking is to complicated to run as a pre-flight.  Instead, we go ahead
					// and do the set, letting the set code generate any errors, and then fish the errors
					// out and throw them.
					// (In particular, XFAFloatImpl's, XFADecimalImpl's and XFAIntegerImpl's setValue() calls
					// are all known to generate type mismatch error entries.)
					//
					Model oModel = null;
					LogMessenger oTempLogMessenger = new LogMessenger();
					LogMessenger oSaveLogMessenger = null;
					int nStartErrorCount = 0;
					if (this instanceof Element) {
						oModel = ((Element)this).getModel();
					}
					if (oModel != null) {
						// plug in a temp LogMessenger so that any error messages generated
						// don't get sent to a log file
						oSaveLogMessenger = oModel.getLogMessenger();
						oModel.setLogMessenger(oTempLogMessenger);
						nStartErrorCount = oModel.getErrorList().size();
				}

					bError = prop.invokeSetProp(this, propertyValue);
					
					if (oModel != null) {
						// restore the LogMessenger (the old one must be cleared first
						// as setLogMessenger() will copy any pending messages from it to
						// the new one)
						oTempLogMessenger.removeStoredMessages();
						oModel.setLogMessenger(oSaveLogMessenger);

						// and now check to see if there are any additional messages in
						// the errorList which we want to extract and throw back to our
						// script
						if (oModel.getErrorList().size() > nStartErrorCount) {
							int nErrors = oModel.getErrorList().size();
							ExFull oError = oModel.getErrorList().get(nErrors - 1);
							oModel.removeLastError();
		
							MsgFormatPos sError = new MsgFormatPos(oError.toString());
							throw new ExFull(sError);
						}
 
					}

					
					if (! bError)
						return true;
				}
				
				// Don't suppress because the user needs to know they are trying to update
				// a read property
				MsgFormatPos message = new MsgFormatPos(ResId.InvalidSetPropertyException);
				message.format(scriptThis.getClassAtom());
				message.format(sPropertyName);
				throw new ExFull(message);
			}
			else if (sPropName.length() == 0) {
				if (bSuppressExceptions)
					return false;
	
				// default property
				MsgFormatPos message = new MsgFormatPos(ResId.NoDefaultSetPropertyException, getClassAtom());
				throw new ExFull(message);
			}
			else { // unknown property
				if (bSuppressExceptions)
					return false;

				MsgFormatPos message = new MsgFormatPos(ResId.InvalidSetPropertyException);
				message.format(scriptThis.getClassAtom());
				message.format(sPropertyName);
				throw new ExFull(message);
			}				
		}
		
		return true;
	}

	/**
	 * @exclude from published api.
	 */
	final public void unDeafen() {
		if (mPeers == null) {
			return;
		}
		mPeers.unDeafen();
	}

	/**
	 * @exclude from published api.
	 */
	final public void unMute() {
		if (mPeers == null) {
			return;
		}
		mPeers.unMute();
	}

	/**
	 * @exclude from published api.
	 */
	public void updateFromPeer(Object peerNode, int eventType, String arg1, Object arg2) {

		// Do nothing
		// Derived classes can override this to receive peer update notifications
	}
	
	/**
	 * @exclude from public api.
	 */
	public void peerRemoved(Peer peer) {
		// Do nothing
		// Derived classes can override this to receive peerRemoved notifications
	}

	/**
	 * Validate if the given Version and Availability flags are valid for the
	 * current document
	 * 
	 * @param nXFAVersion
	 *            The target XFA Version
	 * @param nAvailability
	 *            The target Availability flags, this indicates for what clients
	 *            the script is available
	 * @param bUpdateVersion
	 *            indicates if the model version can be updated by the calling
	 *            code
	 * @return if true, Version and Availability flags are valid
	 * 
	 * @exclude from published api.
	 */
	public boolean validateUsage(int nXFAVersion, int nAvailability, boolean bUpdateVersion) {
		return true;
	}
	
	/**
	 * Determines if disallowing a version should be considered a fatal error.
	 * 

* This method is called after calling * {@link #validateUsage(int, int, boolean)} when that method returns false. * * @param nXFAVersion * The target XFA Version * @param nAvailability * The target Availability flags, this indicates for what clients * the script is available * @return true if disallowing nVersion should be considered a fatal error * * @see #validateUsage(int, int, boolean) * @exclude from published api. */ public boolean validateUsageFailedIsFatal(int nXFAVersion, int nAvailability) { return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy