You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cf...@apache.org on 2012/06/18 20:10:25 UTC
svn commit: r1351437 [11/12] - in /incubator/flex/trunk/frameworks/projects:
automation_agent/ automation_agent/bundles/ automation_agent/bundles/da_DK/
automation_agent/bundles/de_DE/ automation_agent/bundles/en_US/
automation_agent/bundles/es_ES/ aut...
Added: incubator/flex/trunk/frameworks/projects/tool_air/src/mx/automation/tool/ToolAdapter.as
URL: http://svn.apache.org/viewvc/incubator/flex/trunk/frameworks/projects/tool_air/src/mx/automation/tool/ToolAdapter.as?rev=1351437&view=auto
==============================================================================
--- incubator/flex/trunk/frameworks/projects/tool_air/src/mx/automation/tool/ToolAdapter.as (added)
+++ incubator/flex/trunk/frameworks/projects/tool_air/src/mx/automation/tool/ToolAdapter.as Mon Jun 18 18:10:20 2012
@@ -0,0 +1,3824 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package mx.automation.tool
+{
+
+ import flash.display.DisplayObject;
+ import flash.events.Event;
+ import flash.events.IEventDispatcher;
+ import flash.events.TimerEvent;
+ import flash.geom.Point;
+ import flash.utils.Timer;
+ import flash.utils.getQualifiedClassName;
+
+ import mx.automation.Automation;
+ import mx.automation.AutomationClass;
+ import mx.automation.AutomationConstants;
+ import mx.automation.AutomationError;
+ import mx.automation.AutomationHelper;
+ import mx.automation.AutomationID;
+ import mx.automation.AutomationIDPart;
+ import mx.automation.IAutomationClass;
+ import mx.automation.IAutomationEventDescriptor;
+ import mx.automation.IAutomationManager2;
+ import mx.automation.IAutomationMethodDescriptor;
+ import mx.automation.IAutomationObject;
+ import mx.automation.IAutomationPropertyDescriptor;
+ import mx.automation.IAutomationTabularData;
+ import mx.automation.codec.AdvancedDataGridSelectedCellCodec;
+ import mx.automation.codec.ArrayPropertyCodec;
+ import mx.automation.codec.AssetPropertyCodec;
+ import mx.automation.codec.AutomationObjectPropertyCodec;
+ import mx.automation.codec.ChartItemCodec;
+ import mx.automation.codec.ColorPropertyCodec;
+ import mx.automation.codec.DatePropertyCodec;
+ import mx.automation.codec.DateRangePropertyCodec;
+ import mx.automation.codec.DateScrollDetailPropertyCodec;
+ import mx.automation.codec.DefaultPropertyCodec;
+ import mx.automation.codec.FilePropertyCodec;
+ import mx.automation.codec.HitDataCodec;
+ import mx.automation.codec.IAutomationPropertyCodec;
+ import mx.automation.codec.KeyCodePropertyCodec;
+ import mx.automation.codec.KeyModifierPropertyCodec;
+ import mx.automation.codec.ListDataObjectCodec;
+ import mx.automation.codec.RendererPropertyCodec;
+ import mx.automation.codec.ScrollDetailPropertyCodec;
+ import mx.automation.codec.ScrollDirectionPropertyCodec;
+ import mx.automation.codec.TabObjectCodec;
+ import mx.automation.codec.TriggerEventPropertyCodec;
+ import mx.automation.events.AutomationAirEvent;
+ import mx.automation.events.AutomationCustomReplayEvent;
+ import mx.automation.events.AutomationRecordEvent;
+ import mx.automation.events.EventDetails;
+ import mx.controls.Alert;
+ import mx.controls.Image;
+ import mx.controls.SWFLoader;
+ import mx.core.EventPriority;
+ import mx.core.FlexGlobals;
+ import mx.core.mx_internal;
+ import mx.managers.IMarshalSystemManager;
+ import mx.managers.ISystemManager;
+ import mx.managers.PopUpManager;
+ import mx.managers.SystemManager;
+ import mx.resources.IResourceManager;
+ import mx.resources.ResourceManager;
+
+ import spark.automation.codec.SparkDropDownListBaseSelectedItemCodec;
+
+ use namespace mx_internal;
+
+ [ResourceBundle("automation_agent")]
+ [ResourceBundle("tool_air")]
+
+ /**
+ * @private
+ */
+ public class ToolAdapter implements IToolCodecHelper
+ {
+ include "../../core/Version.as";
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Captures all properties of all objects in the application's active
+ * window/dialog box/Web page in the Active Screen of each step.
+ * This means that all objects can be added to object repository /
+ * added checkpoints, etc.
+ * @private
+ */
+ public static const COMPLETE:uint = 0;
+
+ /**
+ * (Default). Captures all properties of all objects in the application's
+ * active window/dialog box/Web page in the Active Screen of the first
+ * step performed in an application's window, plus all properties
+ * of the recorded object in subsequent steps in the same window
+ * (it is an optimization of Complete mode).
+ * As in Complete mode, in this mode, all objects can be added to object
+ * repository / added checkpoints, etc.
+ * @private
+ */
+ public static const PARTIAL:uint = 1;
+
+ /**
+ * Captures properties only for the recorded object and its parent in the
+ * Active Screen of each step.
+ * This means that only the recorded objects and its parents can be added
+ * to object repository / added checkpoints, etc.
+ * @private
+ */
+ public static const MINIMUM:uint = 2;
+
+ /**
+ * Disables capturing of Active Screen files for all applications
+ * and Web pages.
+ * This means no Active Screen will be shown.
+ * @private
+ */
+ public static const NONE:uint = 3;
+
+
+ // indicates what type of application is being automation currently.
+ /**
+ * @private
+ */
+ public static const ApplicationType_Flex:int = 0;
+ /**
+ * @private
+ */
+ public static const ApplicationType_AIR:int = 1;
+
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ private static var isInitialized:Boolean = false;
+
+ /**
+ * @private
+ */
+ private static var qtpCodecHelper:IToolCodecHelper;
+
+
+ /**
+ * @private
+ */
+ public static var _applicationType:int = -1;
+
+ /**
+ * @private
+ */
+ public static var _applicationId:String;
+
+ /**
+ * @private
+ */
+ //private var sandboxRoot:IEventDispatcher;
+
+
+ /**
+ * @private
+ * The highest place we can listen for events in our DOM
+ */
+ private static var mainListenerObj:IEventDispatcher;
+
+
+ /**
+ * @private
+ */
+ private var lastApplicationName:String;
+
+ /**
+ * @private
+ */
+ private var lastRequestName:String;
+
+
+ /**
+ * @private
+ */
+ private var requestPending:Boolean;
+
+
+ /**
+ * @private
+ */
+ private var requestResultObjArray:Array;
+
+ /**
+ * @private
+ */
+ private var resultRecieved:Boolean;
+
+ /**
+ * @private
+ */
+ private var sm:ISystemManager;
+
+ /**
+ * @private
+ */
+ // private var _smMSm:IMarshalSystemManager;
+
+ /*
+ public function get smMSm():IMarshalSystemManager
+ {
+ if(!_smMSm)
+ _smMSm = IMarshalSystemManager(sm.getImplementation("mx.managers::IMarshalSystemManager"));
+
+ return _smMSm;
+ }
+ */
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 4
+ */
+ public function ToolAdapter()
+ {
+ super();
+ sm = FlexGlobals.topLevelApplication.systemManager;
+ //smMSm = sm as IMarshalSystemManager;
+ //_smMSm = IMarshalSystemManager((FlexGlobals.topLevelApplication.systemManager as SystemManager).getImplementation("max.manager::IMarshalSystemManager"));
+ //_smMSm = IMarshalSystemManager((Automation.getMainApplication().systemManager as SystemManager).getImplementation("max.manager::IMarshalSystemManager"));
+ // working line _smMSm = IMarshalSystemManager(sm.getImplementation("mx.managers::IMarshalSystemManager"));
+
+
+ // the following code is to take care of Marshalling in Automation
+ // we need to handle all the methods which can reach Tool (which will be a part of
+ // main applicaiton. We need to send the information about this function call to other applications.
+ //sandboxRoot = sm.getSandboxRoot();
+
+ // these events are coming from the main application and the children are listening to the main application
+ if(sm.isTopLevelRoot() == false)
+ {
+ var eventDetailsToListenFromParent:Array = new Array();
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.FIND_OBJECTIDS,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.RUN,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_ACTIVESCREEN,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_PARENT,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_RECTANGLE,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_ELEMENT_FROM_POINT,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_ELEMENT_TYPE,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_DISPLAY_NAME,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_PROPERTIES,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.BUILD_DESCRIPTION,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_CHILDREN,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.LEARN_CHILD_OBJECTS,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_LAST_ERROR,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.SET_LAST_ERROR,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_TABULAR_ATTRIBUTES,
+ interAppRequestHandler));
+ eventDetailsToListenFromParent.push(new EventDetails(ToolMarshallingEvent.GET_TABULAR_DATA,
+ interAppRequestHandler));
+
+ automationManager.addEventListenersToAllParentApplications(eventDetailsToListenFromParent);
+ //addEventListenersToAllParentApplications(eventDetailsToListenFromParent);
+ }
+
+
+
+
+ var eventDetailsToListenFromChildren:Array = new Array();
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.FIND_OBJECTIDS_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.RUN_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_ACTIVESCREEN_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_PARENT_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_RECTANGLE_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_ELEMENT_FROM_POINT_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_ELEMENT_TYPE_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_DISPLAY_NAME_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_PROPERTIES_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.BUILD_DESCRIPTION_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_CHILDREN_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.LEARN_CHILD_OBJECTS_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_LAST_ERROR_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_TABULAR_ATTRIBUTES_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.GET_TABULAR_DATA_REPLY,
+ interAppReplyHandler));
+ eventDetailsToListenFromChildren.push(new EventDetails(ToolMarshallingEvent.RECORD,
+ marhsalledRecordHandler));
+
+ automationManager.addEventListenersToAllChildApplications(eventDetailsToListenFromChildren);
+
+ automationManager.addEventListener(AutomationRecordEvent.RECORD,recordHandler, false, EventPriority.DEFAULT_HANDLER, true);
+ automationManager.addEventListener(AutomationAirEvent.NEW_AIR_WINDOW,newWindowHandler);
+
+ if (!isInitialized)
+ {
+ isInitialized = true;
+
+ qtpCodecHelper = this;
+
+ // Add the default serializers.
+ addPropertyCodec(
+ "object", new DefaultPropertyCodec());
+
+ addPropertyCodec(
+ "keyCode", new KeyCodePropertyCodec());
+
+ addPropertyCodec(
+ "keyModifier", new KeyModifierPropertyCodec());
+
+ addPropertyCodec(
+ "object[]", new ArrayPropertyCodec(new DefaultPropertyCodec()));
+
+ addPropertyCodec(
+ "color", new ColorPropertyCodec());
+
+ addPropertyCodec(
+ "color[]", new ArrayPropertyCodec(new ColorPropertyCodec()));
+
+ addPropertyCodec(
+ "automationObject", new AutomationObjectPropertyCodec());
+
+ addPropertyCodec(
+ "automationObject[]",
+ new ArrayPropertyCodec(new AutomationObjectPropertyCodec()));
+
+ addPropertyCodec(
+ "asset", new AssetPropertyCodec());
+
+ addPropertyCodec(
+ "asset[]", new ArrayPropertyCodec(new AssetPropertyCodec()));
+
+ addPropertyCodec(
+ "listDataObject", new ListDataObjectCodec());
+
+ addPropertyCodec(
+ "listDataObject[]",
+ new ArrayPropertyCodec(new ListDataObjectCodec()));
+
+ addPropertyCodec(
+ "rendererObject", new RendererPropertyCodec());
+
+ addPropertyCodec(
+ "dateRange", new DateRangePropertyCodec());
+
+ addPropertyCodec(
+ "dateObject", new DatePropertyCodec());
+
+ addPropertyCodec(
+ "dateRange[]",
+ new ArrayPropertyCodec(new DateRangePropertyCodec()));
+
+ addPropertyCodec(
+ "event", new TriggerEventPropertyCodec());
+
+ addPropertyCodec(
+ "tab", new TabObjectCodec());
+
+ addPropertyCodec(
+ "scrollDetail", new ScrollDetailPropertyCodec());
+
+ addPropertyCodec(
+ "dateScrollDetail", new DateScrollDetailPropertyCodec());
+
+ addPropertyCodec(
+ "scrollDirection", new ScrollDirectionPropertyCodec());
+
+ addPropertyCodec(
+ "AdvancedDataGridSelectedCell[]", new ArrayPropertyCodec(new AdvancedDataGridSelectedCellCodec()));
+
+ addPropertyCodec(
+ "ChartItemCodec", new ChartItemCodec());
+
+ addPropertyCodec(
+ "ChartItemCodec[]", new ArrayPropertyCodec(new ChartItemCodec()));
+
+ addPropertyCodec(
+ "hitDataCodec[]", new ArrayPropertyCodec(new HitDataCodec()));
+
+ addPropertyCodec(
+ "fileCodec", new FilePropertyCodec());
+
+ addPropertyCodec(
+ "SparkDropDownListBaseSelectedItem", new SparkDropDownListBaseSelectedItemCodec());
+
+
+ /*
+ This portion of the code is removed to make the automation_dmv source compilable in Flex Builder source.
+
+ Why this code was used :
+ To make the application which does not need the datavisuaalisation components, not including these codes
+ The required codecs were supposed to be present in the automation_dmv swc and hence only if the user
+ provides this swc, these classes would have been loaded.
+ But to make these classes under the automation_dmv , we bring the dependancy of qtp and automation source
+ as the codecs use IToolProper.... class. Hence we cannot compile them independantly
+
+ try
+ {
+ // check for availability of chart codec.
+ // it may not be available if user has not included chart delegates
+ var codec:Object = getDefinitionByName("mx.automation.codec.HitDataCodec");
+
+ addPropertyCodec(
+ "hitDataCodec[]", new ArrayPropertyCodec(new codec()));
+ }
+ catch(e:Error)
+ {
+ }
+ */
+
+ var message:String;
+ /*
+
+
+ if (Capabilities.playerType != "ActiveX")
+ {
+ message = resourceManager.getString(
+ "automation_agent", "notActiveX");
+ trace(message);
+ return;
+ }
+
+ if (! Capabilities.os.match(/^Windows/))
+ {
+ message = resourceManager.getString(
+ "automation_agent", "notWindows", [Capabilities.os]);
+ trace(message);
+ return;
+ }
+
+ if (!ExternalInterface.available)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "noExternalInterface");
+ trace(message);
+ return;
+ }
+
+ if (!playerID || playerID.length == 0)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "noPlayerID");
+ trace(message);
+ return;
+ }
+
+ if (playerID.match(/[\.-]/))
+ {
+ message = resourceManager.getString(
+ "automation_agent", "invalidPlayerID", [playerID]);
+ trace(message);
+ return;
+ }
+ */
+
+ try
+ {
+ //ToolAgent.initSocket();
+ //beginRecording();
+
+ /*
+ // for js driver
+ ExternalInterface.addCallback("SetTestingEnvironment",
+ setTestingEnvironment);
+
+ // Add QTP callbacks
+ ExternalInterface.addCallback("GetParent", getParent);
+ ExternalInterface.addCallback("GetChildren", getChildren);
+ ExternalInterface.addCallback("BuildDescription", buildDescription);
+ ExternalInterface.addCallback("FindObjectId", findObjectID);
+ ExternalInterface.addCallback("FindObjectId2", findObjectIDs);
+ ExternalInterface.addCallback("GetDisplayName", getDisplayName);
+ ExternalInterface.addCallback("GetElementType", getElementType);
+ ExternalInterface.addCallback("GetProperties", getProperties);
+ ExternalInterface.addCallback("GetTabularData", getTabularData);
+ ExternalInterface.addCallback("GetTabularAttributes",
+ getTabularAttributes);
+ ExternalInterface.addCallback("Run", run);
+ ExternalInterface.addCallback("GetLastError", getLastError);
+ ExternalInterface.addCallback("SetLastError", setLastError);
+ ExternalInterface.addCallback("BeginRecording", beginRecording);
+ ExternalInterface.addCallback("EndRecording", endRecording);
+ ExternalInterface.addCallback("GetElementFromPoint",
+ getElementFromPoint);
+ ExternalInterface.addCallback("GetRectangle", getRectangle);
+ ExternalInterface.addCallback("GetActiveScreen", getActiveScreen);
+ ExternalInterface.addCallback("LearnChildObjects", learnChildObjects);
+
+ // Register ActiveX plugin
+ ExternalInterface.call("eval",
+ "try { window._mx_testing_plugin_" + playerID +
+ " = new ActiveXObject('TEAPluginIE.TEAFlexAgentIE'); }" +
+ "catch(e) { document.getElementById('" + playerID +
+ "').SetLastError(e.message); } ");
+
+ if (lastError)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "unableToLoadPluginGeneric",
+ [lastError.message]);
+ trace(message);
+ return;
+ }
+
+ ExternalInterface.call("eval",
+ "if (!window._mx_testing_plugin_" + playerID +
+ ".RegisterPluginWithTool(self, " + "'" + playerID + "')) {" +
+ "document.getElementById('" + playerID +
+ "').SetLastError('TEAPluginIE.TEAFlexAgentIE is not scriptable'); }");
+
+ if (lastError)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "unableToLoadPluginGeneric",
+ [lastError.message]);
+ trace(message);
+ return;
+ }
+
+ // Load environment XML
+ var te:String = ExternalInterface.call("window._mx_testing_plugin_" +
+ playerID +
+ ".GetTestingEnvironment");
+ setTestingEnvironment(te);
+ */
+
+ }
+ catch (se:SecurityError)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "unableToLoadPluginGeneric",
+ [se.message]);
+ Automation.automationDebugTracer.traceMessage("ToolAdapter","ToolAdapter()",message);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ private var lastError:Error;
+
+ /**
+ * @private
+ */
+ private var propertyCodecMap:Object = [];
+
+ /**
+ * @private
+ * Used for accessing localized Error messages.
+ */
+ private static var resourceManager:IResourceManager =
+ ResourceManager.getInstance();
+
+ /**
+ * @private
+ * Used for accessing localized Error messages.
+ */
+ private var detailsSentToTool :Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // automationManager
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ private function get automationManager():IAutomationManager2
+ {
+ //return Automation.automationManager ;
+ return Automation.automationManager2 as IAutomationManager2;
+ }
+
+ //----------------------------------
+ // playerID
+ //----------------------------------
+
+ /**
+ * @private
+ */
+ private function get playerID():String
+ {
+ return FlexGlobals.topLevelApplication.id;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * Registers a custom codec to encoding an decoding of object properties and
+ * event properties to and from a testing tool. For example, ColorPicker
+ * events can contain the selected color. A special color codec is provided
+ * to encode and decode colors from their native number format to hex.
+ *
+ * Predefined codecs include:
+ * "" - The default codec that supports basic types such as String, Number, int and uint.
+ * "color" - Converts a number to hex.
+ * "keyCode" - Converts a keyCode number to a human readable string
+ * "keyState" - Converts ctrlKey, shiftKey and altKey booleans to a human
+ * readable bitfield string.
+ * "skin" - Converts a skin asset class name to closely resemble it's
+ * original asset name. Path separators and periods in the orignal
+ * path name will be converted to underscores. This is only available
+ * on readonly properties.
+ * "automationObject" - Converts an object to it's automationName.
+ *
+ * @param codecName the name of the codec.
+ *
+ * @param codec the implementation of the codec.
+ */
+ private function addPropertyCodec(codecName:String, codec:IAutomationPropertyCodec):void
+ {
+ propertyCodecMap[codecName] = codec;
+ }
+
+
+ /**
+ * @private
+ */
+ public function setTestingEnvironment(te:String):void
+ {
+ //trace (te);
+ automationManager.automationEnvironment = new ToolEnvironment(new XML(te));
+
+ // For supportig Marshalling we need the env information as string and
+ // the name of the class which interprets the information
+ // this information will be used by the Automation Manger in each of the AppDomain
+ // to intialise the class with the details.
+ // #IMP: MARSHALLING NOTE#: The name of the class needs to be maintained across versions
+ // However the implementation of the class can be different in each version.
+ automationManager.automationEnvironmentString = te;
+ automationManager.automationEnvironmentHandlingClassName = "mx.automation.tool.ToolEnvironment";
+ }
+
+ /**
+ * Encodes a single value to a testing tool value. Unlike encodeProperties which
+ * takes an object which contains all the properties to encode, this method
+ * takes the actual value to encode. This is useful for encoding return values.
+ *
+ * @param obj the value to be encoded.
+ *
+ * @param propertyDescriptor the property descriptor that describes this value.
+ *
+ * @param relativeParent the IAutomationObject that is related to this value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 4
+ */
+ public function encodeValue(value:Object,
+ testingToolType:String,
+ codecName:String,
+ relativeParent:IAutomationObject):Object
+ {
+ //setup a fake descriptor and object to send to the codec
+ var pd:ToolPropertyDescriptor =
+ new ToolPropertyDescriptor("value",
+ false,
+ false,
+ testingToolType,
+ codecName);
+ var obj:Object = {value:value};
+ return getPropertyValue(obj, pd, relativeParent);
+ }
+
+
+ public function getPropertyValue(obj:Object,
+ pd:ToolPropertyDescriptor,
+ relativeParent:IAutomationObject = null):Object
+ {
+ var codec:IAutomationPropertyCodec = propertyCodecMap[pd.codecName];
+
+ if (codec == null)
+ codec = propertyCodecMap["object"];
+
+ if (relativeParent == null)
+ relativeParent = obj as IAutomationObject;
+
+ return codec.encode(automationManager, obj, pd, relativeParent);
+ }
+
+ /**
+ * Encodes properties in an AS object to an array of values for a testing tool
+ * using the codecs. Since the object being passed in may not be an IAutomationObject
+ * (it could be an event class) and some of the properties require the
+ * IAutomationObject to be transcoded (such as the item renderers in
+ * a list event), relativeParent should always be set to the relevant
+ * IAutomationObject.
+ *
+ * @param obj the object that contains the properties to be encoded.
+ *
+ * @param propertyDescriptors the property descriptors that describes the properties for this object.
+ *
+ * @param relativeParent the IAutomationObject that is related to this object.
+ *
+ * @return the encoded property value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Flex 4
+ */
+ public function encodeProperties(obj:Object,
+ propertyDescriptors:Array,
+ interactionReplayer:IAutomationObject):Array
+ {
+ var result:Array = [];
+ var consecutiveDefaultValueCount:Number = 0;
+ for (var i:int = 0; i < propertyDescriptors.length; i++)
+ {
+ var val:Object = getPropertyValue(obj,
+ propertyDescriptors[i],
+ interactionReplayer);
+
+ var isDefaultValueNull:Boolean = propertyDescriptors[i].defaultValue == "null";
+
+ consecutiveDefaultValueCount = (!(val == null && isDefaultValueNull) &&
+ (propertyDescriptors[i].defaultValue == null ||
+ val == null ||
+ propertyDescriptors[i].defaultValue != val.toString())
+ ? 0
+ : consecutiveDefaultValueCount + 1);
+
+ result.push(val);
+ }
+
+ result.splice(result.length - consecutiveDefaultValueCount,
+ consecutiveDefaultValueCount);
+
+ return result;
+ }
+
+
+
+ /**
+ * @private
+ */
+ private function getValuesWithTypeInformation(elemetnsArray:Array):Array
+ {
+ var count:int = elemetnsArray.length;
+ var index:int = 0;
+
+ var currentArgsArray:Array= new Array();
+
+ while(index < count)
+ {
+ var currentObject:Object = elemetnsArray[index];
+ var currentObjectType:String = getQualifiedClassName(currentObject);
+
+ var currentobjString:String;
+ if(currentObject == null)
+ currentobjString = ClientSocketHandler.nullValueIndicator;
+ else
+ currentobjString = currentObject.toString();
+
+ var currentArgString:String = currentObjectType+ ClientSocketHandler.typeValueSeparator + currentobjString;
+ currentArgsArray.push(currentArgString);
+
+ index++;
+ }
+
+ return currentArgsArray;
+ }
+
+ /**
+ * @private
+ */
+ private function handleIncompleteRecord(event:Event):void
+ {
+ if (!automationManager.isSynchronized(null))
+ {
+ var myTimer:Timer = new Timer(1000,1);
+ myTimer.addEventListener("timer", handleIncompleteRecord);
+ myTimer.start();
+ }
+ else
+ {
+
+ var objectId2Object:Object = findObjectIDs(currentDescriptionXMLString);
+ var objectId2Array:Array = (objectId2Object["result"] as Array);
+ var objectId2String:String ="";
+ if(objectId2Array)
+ {
+ var completeString:String;
+ objectId2String = objectId2Array.join(ClientSocketHandler.objectIdSeparators);
+ objectId2String = objectId2Array.join(ClientSocketHandler.objectIdSeparators);
+ completeString = recordInfoString+ objectId2String + ClientSocketHandler.recordInfoSeparator;
+
+ var request1:RequestData = new RequestData();
+ request1.requestID = ClientSocketHandler.activeScreenDataStoreRequestString;
+ request1.requestData = activeScreenString;
+
+ var request2:RequestData = new RequestData();
+ request2.requestID = ClientSocketHandler.recordRequestString;
+ request2.requestData = completeString;
+
+ if(sm.isTopLevelRoot() == false)
+ {
+ // send the event to the root applicaiton and let it take care of the socket communication.
+ var marshalledEvent:ToolMarshallingEvent = new ToolMarshallingEvent(
+ ToolMarshallingEvent.RECORD);
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+ var recordDetails:Array = new Array();
+ recordDetails.push(request1);
+ recordDetails.push(request2);
+ marshalledEvent.interAppDataToMainApp = recordDetails;
+
+ dispatchEventToParent(marshalledEvent);
+
+ }
+ else
+ {
+ if(ToolAgent.clientSocketHandler)
+ {
+ (ToolAgent.clientSocketHandler).addToRecordRequestQueue(request1);
+ (ToolAgent.clientSocketHandler).addToRecordRequestQueue(request2);
+
+ //trace ("calling processQueuedRecordRequests ToolAgent");
+ (ToolAgent.clientSocketHandler).processQueuedRecordRequests(true);
+ }
+ }
+ /*
+ Application.application.alpha= appAlpha;
+ Application.application.enabled = true; */
+ ClientSocketHandler.enableApplication();
+ }
+ }
+ }
+
+ private var recordInfoString:String;
+ private var activeScreenString:String;
+ private var currentDescriptionXMLString:String;
+ private var appAlpha:int = -1;
+ private function recordHandler(event:AutomationRecordEvent):void
+ {
+ if(event.isDefaultPrevented())
+ return;
+
+ automationManager.incrementCacheCounter();
+
+ try
+ {
+ var obj:IAutomationObject = event.automationObject ;
+ var rid:AutomationID = automationManager.createID(obj);
+ var descriptionXML:XML = getDescriptionXML(rid, obj);
+
+ // We are storing the actual pretty printing value so that we can
+ // reset it back when we are done with our operation.
+ // Ref: http://bugs.adobe.com/jira/browse/FLEXENT-1140
+ var actualPrettyPrinting:Boolean = XML.prettyPrinting;
+
+ XML.prettyPrinting = false;
+ var parentRids:Array = [];
+
+ while (obj)
+ {
+ rid = automationManager.createID(obj);
+ parentRids.push(rid.toString());
+ obj = automationManager.getParent(obj);
+ }
+
+ // the last rid corresponds to the highest parent
+ // get the window id for this obejct
+ // clone the automationID
+ var rid1:AutomationID = rid.clone();
+ //get the first part
+ var objectIdPart:AutomationIDPart = rid1.removeFirst();
+ var windowId:String = automationManager.getAIRWindowUniqueIDFromAutomationIDPart(objectIdPart);
+
+
+ var completeString:String = parentRids.join(":|:");
+ completeString=completeString.concat(ClientSocketHandler.recordInfoSeparator,descriptionXML.toXMLString(),ClientSocketHandler.recordInfoSeparator,event.name);
+ // now we have parentRids | descriptionXML | event name in the complete string
+
+
+ // for the argument arrays
+ var argsArray:Array = event.args as Array;
+ if(argsArray)
+ {
+ var argLength:int = argsArray.length;
+
+ if(argLength != 0)
+ {
+ var argString :String = (getValuesWithTypeInformation(event.args as Array)).join(ClientSocketHandler.eventArgsSeparator) ;
+ //completeString=completeString.concat(ClientSocketHandler.recordInfoSeparator,event.args.join(ClientSocketHandler.eventArgsSeparator),ClientSocketHandler.recordInfoSeparator);
+ completeString=completeString.concat(ClientSocketHandler.recordInfoSeparator,argString,ClientSocketHandler.recordInfoSeparator);
+
+ }
+ else
+ completeString=completeString.concat(ClientSocketHandler.recordInfoSeparator,ClientSocketHandler.recordNoArgIndicator,ClientSocketHandler.recordInfoSeparator);
+ }
+ else
+ completeString=completeString.concat(ClientSocketHandler.recordInfoSeparator,ClientSocketHandler.recordNoArgIndicator,ClientSocketHandler.recordInfoSeparator);
+ // now we have the argument details also in the complete string
+
+
+ // get the active screen details
+ // before sending the record details , capture the active screen details and send
+ // for the time being we dont have the player coordinates in screen coordinates
+ // we need the top offset and left offset of the player
+
+ // we need the stage start points
+
+ //get the point for sub apps using automation manager's API, that returns main
+ //air app's start point. Retuns null if this is main air app
+ var stageStartCoordinate:Point = automationManager.getStartPointInScreenCoordinates(windowId);
+
+ if(!stageStartCoordinate) //null if this is main air app
+ stageStartCoordinate = getStageStartPointInScreenCoords(windowId);
+
+ if(!stageStartCoordinate)
+ stageStartCoordinate = new Point(0,0);
+
+ // we would have got the message for this. so the user is not expected to proceed.
+ // the above is done to avoid the null obejct access.
+
+
+ var resultObj:Object = getActiveScreen(0,parentRids[0],stageStartCoordinate.x,stageStartCoordinate.y);
+ // var activeScreenData:String = resultObj.result;
+ activeScreenString = resultObj.result;
+
+ // calculate object ID string
+ var objectId2Object:Object = findObjectIDs(descriptionXML.toXMLString());
+ var objectId2Array:Array = (objectId2Object["result"] as Array);
+ var objectId2String:String ="";
+ if(objectId2Array)
+ {
+ objectId2String = objectId2Array.join(ClientSocketHandler.objectIdSeparators);
+ completeString = completeString+ objectId2String + ClientSocketHandler.recordInfoSeparator;
+
+ var request1:RequestData = new RequestData();
+ request1.requestID = ClientSocketHandler.activeScreenDataStoreRequestString;
+ request1.requestData = activeScreenString;
+
+ var request2:RequestData = new RequestData();
+ request2.requestID = ClientSocketHandler.recordRequestString;
+ request2.requestData = completeString;
+
+
+ if(sm.isTopLevelRoot() == false)
+ {
+ // send the event to the root applicaiton and let it take care of the socket communication.
+ var marshalledEvent:ToolMarshallingEvent = new ToolMarshallingEvent(
+ ToolMarshallingEvent.RECORD);
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+ var recordDetails:Array = new Array();
+ recordDetails.push(request1);
+ recordDetails.push(request2);
+ marshalledEvent.interAppDataToMainApp = recordDetails;
+
+ dispatchEventToParent(marshalledEvent);
+
+ }
+ else
+ {
+ if(ToolAgent.clientSocketHandler)
+ {
+ (ToolAgent.clientSocketHandler).addToRecordRequestQueue(request1);
+ (ToolAgent.clientSocketHandler).addToRecordRequestQueue(request2);
+
+ //trace ("calling processQueuedRecordRequests ToolAgent");
+ (ToolAgent.clientSocketHandler).processQueuedRecordRequests(true);
+ }
+ }
+
+ }
+ else
+ {
+ /*
+ appAlpha = Application.application.alpha;
+ Application.application.alpha= .4;
+ Application.application.enabled = false;
+ */
+
+ ClientSocketHandler.disableApplication();
+
+ currentDescriptionXMLString = descriptionXML.toXMLString();
+ recordInfoString = completeString;
+ var myTimer:Timer = new Timer(1000,1);
+ myTimer.addEventListener("timer", handleIncompleteRecord);
+ myTimer.start();
+ }
+
+
+
+
+
+
+
+ //rani
+ /*
+ ExternalInterface.call("window._mx_testing_plugin_" + playerID + ".Record",
+ parentRids,
+ descriptionXML.toXMLString(),
+ event.name,
+ event.args);*/
+ XML.prettyPrinting = actualPrettyPrinting;
+
+ }
+ catch (e:Error)
+ {
+ lastError = e;
+ Automation.automationDebugTracer.traceMessage("ToolAdapter","recordHandler()",e.message);
+ }
+
+ automationManager.decrementCacheCounter();
+ }
+
+ private function marhsalledRecordHandler(event:Event):void
+ {
+ // Marshalling events are needeed across applicaiton domain
+ // so this conversion shall fail in the same domain
+ // i.e the above check is to avoid the echoing
+ if(event is ToolMarshallingEvent)
+ return;
+
+ // this handler is only for the main app. so if we are not the main app root
+ // application, we should not handle it, we should just pass to our parent.
+
+ //if(smMSm && (smMSm.useSWFBridge() == true))
+ if(sm.isTopLevelRoot() == false)
+ {
+ var event1:ToolMarshallingEvent = ToolMarshallingEvent.marshal(event);
+ dispatchEventToParent(event1);
+ }
+ else
+ {
+ // i.e take the deta send from the sub app and call the external interface call.
+ // #IMP: MARSHALLING NOTE#:
+ var recordDetails:Array = event["interAppDataToMainApp"];
+ if(recordDetails && recordDetails.length == 2)
+ {
+ /* ExternalInterface.call("window._mx_testing_plugin_" + playerID + ".Record",
+ recordDetails[0], //parentRids,
+ recordDetails[1], //descriptionXML.toXMLString(),
+ recordDetails[2], //event.name,
+ recordDetails[3]); // event.args); */
+ if(ToolAgent.clientSocketHandler)
+ {
+ (ToolAgent.clientSocketHandler).addToRecordRequestQueue(recordDetails[0]);
+ (ToolAgent.clientSocketHandler).addToRecordRequestQueue(recordDetails[1]);
+
+ //trace ("calling processQueuedRecordRequests ToolAgent");
+ (ToolAgent.clientSocketHandler).processQueuedRecordRequests(true);
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ public function beginRecording():Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ automationManager.addEventListener(AutomationRecordEvent.RECORD,
+ recordHandler, false, EventPriority.DEFAULT_HANDLER, true);
+ automationManager.beginRecording();
+
+
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function endRecording():Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ automationManager.endRecording();
+ automationManager.removeEventListener(AutomationRecordEvent.RECORD,
+ recordHandler);
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function getElementType(objID:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try{
+ var rid:AutomationID = AutomationID.parse(objID);
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+ if (fromTool == true)
+ detailsSentToTool = true;
+ var target:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ o.result = automationManager.getAutomationClassName(target);
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_ELEMENT_TYPE,details);
+
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+ }
+ catch (e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function getDisplayName(objID:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+ var target:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ o.result = automationManager.getAutomationName(target);
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_DISPLAY_NAME,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ private function replayEvent(target:IAutomationObject, eventName:String, args:Array):Object
+ {
+ var automationClass:IAutomationClass =
+ automationManager.automationEnvironment.getAutomationClassByInstance(target);
+
+ var message:String;
+
+ // try to find the automation class
+ if (! automationClass)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "classNotFound",
+ [AutomationClass.getClassName(target)]);
+ throw new Error(message);
+ }
+
+ var eventDescriptor:IAutomationEventDescriptor =
+ automationClass.getDescriptorForEventByName(eventName);
+
+ if (!eventDescriptor)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "methodNotFound",
+ [eventName, automationClass]);
+ throw new Error(message);
+ }
+
+ var retValue:Object = eventDescriptor.replay(target, args);
+ return {value:retValue, type:null};
+ }
+
+ private function replayMethod(target:IAutomationObject, method:String, args:Array):Object
+ {
+ var automationClass:IAutomationClass =
+ automationManager.automationEnvironment.getAutomationClassByInstance(target);
+
+ var message:String;
+
+ // try to find the automation class
+ if (! automationClass)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "classNotFound",
+ [AutomationClass.getClassName(target)]);
+ throw new Error(message);
+ }
+
+ var methodDescriptor:IAutomationMethodDescriptor =
+ automationClass.getDescriptorForMethodByName(method);
+
+ if (!methodDescriptor)
+ {
+ message = resourceManager.getString(
+ "automation_agent", "methodNotFound",
+ [method, automationClass]);
+ throw new Error(message);
+ }
+
+ var retValue:Object = methodDescriptor.replay(target, args);
+
+ if(retValue is IAutomationObject)
+ retValue = automationManager.createID(IAutomationObject(retValue)).toString();
+
+ return {value:retValue, type:methodDescriptor.returnType};
+ }
+
+ private var replayResultObj:Object = null;
+ private function replayDefaultHandler(event:AutomationCustomReplayEvent):void
+ {
+ replayResultObj = { result:null, error:0 };
+ if(event.isDefaultPrevented())
+ return;
+
+ automationManager.removeEventListener(AutomationCustomReplayEvent.CUSTOM_REPLAY,replayDefaultHandler);
+
+ if((event.type != AutomationCustomReplayEvent.CUSTOM_REPLAY) ||
+ (event.automationObject == null )||
+ (event.name == null))
+ return;
+
+
+
+ //var o:Object = { result:null, error:0 };
+
+ try
+ {
+ replayResultObj.result = replayMethod(event.automationObject, event.name, event.args);
+ }
+ catch(e:Error)
+ {
+ try
+ {
+ //replayResultObj.result = replayEvent(target, method, args);
+ replayResultObj.result = replayEvent(event.automationObject, event.name, event.args);
+ }
+ catch(e:Error)
+ {
+ automationManager.decrementCacheCounter();
+ throw e;
+ }
+ }
+
+ }
+ /**
+ * @private
+ */
+ public function replay(target:IAutomationObject, method:String, args:Array):Object
+ {
+ // first let us dispatch the custom replay event.
+ replayResultObj = null;
+
+ // create the custom replay event and dispatch the same
+ var customReplayEventObj:AutomationCustomReplayEvent =
+ new AutomationCustomReplayEvent(AutomationCustomReplayEvent.CUSTOM_REPLAY,false,true);
+ //customReplayEventObj.cancelable should be true. We need to make this true as the default handler can prevent the default.
+
+ customReplayEventObj.automationObject = target;
+ customReplayEventObj.name = method;
+ customReplayEventObj.args = args;
+
+
+ // dispatch the event from the automation manager.
+ automationManager.addEventListener(AutomationCustomReplayEvent.CUSTOM_REPLAY,replayDefaultHandler,false,
+ EventPriority.DEFAULT_HANDLER,false);
+
+ automationManager.dispatchEvent(customReplayEventObj);
+ return replayResultObj;
+
+
+ }
+
+
+ /**
+ * @private
+ */
+ public function run(objID:String, method:String, args:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var resultObj:Object;
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentAppName:String = getApplicationName();
+
+ if(requiredApplicationName != currentAppName)
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+ details.push(method);
+ details.push(args);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+
+ resultObj = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.RUN,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ resultObj = requestResultObjArray[0];
+ detailsSentToTool = true;
+ }
+ }
+ else
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+
+ // ***************************************
+ var target:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ resultObj = replay(target, method, convertArrayFromCrazyToAs(args));
+ }
+
+ // if we have not sent the request to QTP, we need to send the error message that we are not yet synchronised
+ // we need this message only if the request to this method has come from QTP
+ if((detailsSentToTool == false)&&(fromTool == true))
+ {
+ // we dont expect this case to happen. But just to be on the
+ // safe side we are keeping this error
+ var message:String = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+
+ return resultObj;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function findObjectID(descriptionXML:String):Object
+ {
+ // this method is not used in 3 onwards
+ // hence this method is modified to support Marshalling
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = new AutomationID();
+ var x:XML = new XML(descriptionXML);
+ while (x)
+ {
+ var part:AutomationIDPart = new AutomationIDPart();
+ part.automationClassName = x.@type.toString();
+ var automationClass:IToolAutomationClass =
+ automationManager.automationEnvironment.getAutomationClassByName(part.automationClassName) as IToolAutomationClass;
+ var propertyCaseRemapping:Object = automationClass.propertyLowerCaseMap;
+
+ for (var property:Object in x.Property)
+ {
+ var propertyName:String = x.Property[property].@name.toString().toLowerCase();
+
+ if (propertyName in propertyCaseRemapping)
+ {
+ var propertyDescriptor:ToolPropertyDescriptor =
+ propertyCaseRemapping[propertyName];
+
+ propertyName = propertyDescriptor.name;
+
+ var regEx:String = x.Property[property].@regExp;
+ var value:String = x.Property[property].@value;
+
+ if (regEx == "true" || regEx == "t")
+ part[propertyName] = new RegExp(value);
+ else
+ part[propertyName] = value;
+ }
+ }
+ rid.addLast(part);
+ x = x.Element.length() == 1 ? x.Element[0] : null;
+ }
+
+ var message:String;
+ if (!automationManager.isSynchronized(null))
+ {
+ message = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ var obj:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ if (!automationManager.isSynchronized(obj))
+ {
+ message = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ if (!automationManager.isVisible(obj as DisplayObject))
+ {
+ message = resourceManager.getString(
+ "automation_agent", "invisible");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ o.result = automationManager.createID(obj).toString();
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function findObjectIDs(descriptionXML:String, fromTool :Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ var message:String;
+ try
+ {
+ var rid:AutomationID = new AutomationID();
+ var x:XML = new XML(descriptionXML);
+ var partIndex:int = 0;
+
+ var sameApplication:Boolean = true;
+ var requiredApplicationName :String ;
+ while (x && sameApplication)
+ {
+ var part:AutomationIDPart = new AutomationIDPart();
+ part.automationClassName = x.@type.toString();
+ var automationClass:IToolAutomationClass =
+ automationManager.automationEnvironment.getAutomationClassByName(part.automationClassName) as IToolAutomationClass;
+ var propertyCaseRemapping:Object = automationClass.propertyLowerCaseMap;
+
+ for (var property:Object in x.Property)
+ {
+ var propertyName:String = x.Property[property].@name.toString().toLowerCase();
+
+ if (propertyName in propertyCaseRemapping)
+ {
+ var propertyDescriptor:ToolPropertyDescriptor =
+ propertyCaseRemapping[propertyName];
+
+ propertyName = propertyDescriptor.name;
+
+ var regEx:String = x.Property[property].@regExp;
+ var value:String = x.Property[property].@value;
+
+ if (regEx == "true" || regEx == "t")
+ part[propertyName] = new RegExp(value);
+ else
+ part[propertyName] = value;
+ }
+ }
+ rid.addLast(part);
+
+ // we need to decide whehter we are in the correct application
+ if((partIndex == 0) && (fromTool == true))
+ {
+ requiredApplicationName = automationManager.getApplicationNameFromAutomationIDPart(part);
+ //requiredApplicationName = part["automationName"][0].toString();
+ var currentAppName:String = getApplicationName();
+
+ // we need to check whether this request is for the
+ // root application or sub application.
+ // if it is for the sub applicaiton, we need to send the information as event to the other
+ // applications and wait for the result.
+ if(requiredApplicationName != currentAppName )
+ sameApplication = false;
+ }
+ partIndex++;
+ x = x.Element.length() == 1 ? x.Element[0] : null;
+ }
+
+ if (!automationManager.isSynchronized(null))
+ {
+ message = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+
+ // before we call methods on the automation manger, whether this request is for the
+ // root application or sub application.
+ // if it is for the sub applicaiton, we need to send the information as event to the other
+ // applications and wait for the result.
+ if(sameApplication == true )
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+
+ //here we can proceed with the root applicaiton.
+ var autObjects:Array = automationManager.resolveID(rid);
+ for (var i:int = 0; i < autObjects.length; ++i)
+ {
+ autObjects[i] = automationManager.createID(autObjects[i]).toString();
+ }
+ o.result = autObjects;
+ detailsSentToTool = true;
+ }
+ else
+ {
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(descriptionXML);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.FIND_OBJECTIDS ,
+ details);
+
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to Tool
+ o.result = requestResultObjArray[0];
+ detailsSentToTool = true;
+ }
+ }
+
+ // if we have not sent the request to QTP, we need to send the error message that we are not yet synchronised
+ // we need this message only if the request to this method has come from QTP
+ if((detailsSentToTool == false)&&(fromTool == true))
+ {
+ // we dont expect this case to happen. But just to be on the
+ // safe side we are keeping this error
+ var message1:String = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message1,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function buildDescription(objID:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+ if (fromTool == true)
+ detailsSentToTool = true;
+ var obj:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ //Don't use getDescriptionXML because it uses the attributes
+ //that were sent into us, and in theory those attributes could
+ //be regular expressions used to find the item
+ //var result:XML = getDescriptionXML(rid, obj);
+ //XML.prettyPrinting = false;
+ //o.result = stripSlashRHack(result.toXMLString());
+ o.result = getActiveOrLearnXMLTree(objID, false).learnChildrenXML;
+ }
+ else
+ {
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.BUILD_DESCRIPTION ,
+ details);
+
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to Tool
+ o = requestResultObjArray[0];
+ detailsSentToTool = true;
+ }
+ }
+
+ // if we have not sent the request to QTP, we need to send the error message that we are not yet synchronised
+ // we need this message only if the request to this method has come from QTP
+ if((detailsSentToTool == false)&&(fromTool == true))
+ {
+ // we dont expect this case to happen. But just to be on the
+ // safe side we are keeping this error
+ var message:String = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ }
+ catch (e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function getPropertyDescriptors(obj:IAutomationObject,
+ names:Array = null,
+ forVerification:Boolean = true,
+ forDescription:Boolean = true):Array
+ {
+ if (!obj)
+ return null;
+
+ try
+ {
+ automationManager.incrementCacheCounter();
+
+ var automationClass:IToolAutomationClass =
+ automationManager.automationEnvironment.getAutomationClassByInstance(obj) as IToolAutomationClass;
+ var i:int;
+ var propertyCaseRemapping:Object = automationClass.propertyLowerCaseMap;
+
+ var result:Array = [];
+ if (!names)
+ {
+ var propertyDescriptors:Array =
+ automationClass.getPropertyDescriptors(obj,
+ forVerification,
+ forDescription);
+ names = [];
+ for (i = 0; i < propertyDescriptors.length; i++)
+ {
+ names[i] = propertyDescriptors[i].name;
+ }
+ }
+ for (i = 0; i < names.length; i++)
+ {
+ var lowerCaseName:String = names[i].toLowerCase();
+ var propertyDescriptor:ToolPropertyDescriptor =
+ propertyCaseRemapping[lowerCaseName];
+ result.push(propertyDescriptor);
+ }
+
+ automationManager.decrementCacheCounter();
+ }
+ catch(e:Error)
+ {
+ automationManager.decrementCacheCounter();
+
+ throw e;
+ }
+
+ return result;
+ }
+
+ private function encodeValues(obj:IAutomationObject, values:Array, descriptors:Array):Array
+ {
+ var result:Array = [];
+ for (var i:int = 0; i < values.length; ++i)
+ {
+ var descriptor:ToolPropertyDescriptor = descriptors[i];
+ var codec:IAutomationPropertyCodec = propertyCodecMap[descriptor.codecName];
+
+ if (codec == null)
+ codec = propertyCodecMap["object"];
+
+ var relativeParent:IAutomationObject = obj;
+
+ var retValue:Object = codec.encode(automationManager, obj, descriptor, relativeParent);
+ result.push({value:retValue, descriptor:descriptor});
+ }
+
+ return result;
+ }
+
+
+ /**
+ * @private
+ */
+ public function getProperties(objID:String, names:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+
+ // we are in the same applicaiton, and hence we can proceed.
+ var obj:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ var asNames:Array = convertArrayFromCrazyToAs(names);
+
+ var descriptors:Array = [];
+ if(asNames && asNames.length)
+ {
+ //trace("getProperties 1- Lenght of Name"+ asNames.length);
+ var automationClass:IToolAutomationClass =
+ automationManager.automationEnvironment.getAutomationClassByInstance(obj) as IToolAutomationClass;;
+ var propertyCaseRemapping:Object = automationClass.propertyLowerCaseMap;
+ for (var i:int = 0; i < asNames.length; i++)
+ {
+
+ var lowerCaseName:String = asNames[i].toLowerCase();
+ var propertyDescriptor:IAutomationPropertyDescriptor =
+ propertyCaseRemapping[lowerCaseName];
+ // trace("getProperties 2 + Name - "+ lowerCaseName);
+ if(propertyDescriptor)
+ {
+ asNames[i] = propertyDescriptor.name;
+ descriptors.push(propertyDescriptor);
+ //trace("getProperties 3 + Name - found"+ lowerCaseName);
+ }
+ else
+ {
+ // descriptor was not found delete the entry.
+ asNames.splice(i, 1);
+ //trace("getProperties 3 + Name - Not found"+ lowerCaseName);
+ }
+
+ }
+
+ }
+
+ var values:Array = automationManager.getProperties(obj, asNames);
+ var x:Array = encodeValues(obj, values, descriptors);
+
+ //trace("getProperties 4 + found values"+ x.length);
+ for (var no:int = 0; no < x.length; ++no)
+ {
+ x[no] = x[no].value;
+ }
+
+
+ o.result = getValuesWithTypeInformation(x);
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+ details.push(names);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_PROPERTIES,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+ }
+ catch (e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function getParent(objID:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+ var obj:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ obj = automationManager.getParent(obj);
+ o.result = (obj
+ ? automationManager.createID(obj).toString()
+ : null);
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_PARENT,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+
+ // if we have not sent the request to QTP, we need to send the error message that we are not yet synchronised
+ // we need this message only if the request to this method has come from QTP
+ if((detailsSentToTool == false)&&(fromTool == true))
+ {
+ // we dont expect this case to happen. But just to be on the
+ // safe side we are keeping this error
+ var message:String = resourceManager.getString(
+ "automation_agent", "notSynchronized");
+ throw new AutomationError(message,
+ AutomationError.OBJECT_NOT_VISIBLE);
+ }
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function getChildren(objID:String,
+ filterXMLString:String = null, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromAutomationID(rid);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+ var autObject:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ var children:Array;
+ if (autObject.numAutomationChildren > 0)
+ {
+ var part:AutomationIDPart = createPartFromFilterXML(filterXMLString);
+ children = automationManager.getChildrenFromIDPart(autObject, part);
+
+ for (var i:int = 0; i < children.length; ++i)
+ {
+ children[i] = automationManager.createID(children[i]).toString();
+ }
+ }
+ else
+ children = [automationManager.createID(autObject).toString()];
+
+ o.result = children;
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(objID);
+ details.push(filterXMLString);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_CHILDREN,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+ }
+ catch (e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function setLastError(message:String, fromTool:Boolean = true):void
+ {
+ // we need to find out which was the last responded application.
+ var currentAppname:String = getApplicationName();
+ if ((fromTool == false) || (currentAppname == lastResponseRecievedApplicationName))
+ {
+ lastError = new Error(message);
+ }
+ else
+ {
+ // this will be called if the fromTool == true and currentAppname != lastResponseRecievedApplicationName
+ // we need to dispatch the event and get the error details from the appropriate application
+
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ details.push(message);
+ handleRequestToDifferentApplication(lastResponseRecievedApplicationName,
+ ToolMarshallingEvent.SET_LAST_ERROR,details);
+
+ }
+ }
+
+ /**
+ * @private
+ */
+ public function getLastError(fromTool:Boolean = true):Object
+ {
+ // we need to find out which was the last responded application.
+ var currentAppname:String = getApplicationName();
+ if ((fromTool == false) || (currentAppname == lastResponseRecievedApplicationName))
+ {
+ detailsSentToTool = true;
+ return { result: (lastError ? lastError.message.substr(0, 1 << 9) : null),
+ error: 0 };
+ }
+ else
+ {
+ var o:Object = { result:null, error:0 };
+ // we will reach this condition only when fromTool == true and
+ // currentAppname != lastResponseRecievedApplicationName
+ // we need to dispatch the event and get the error details from the appropriate application
+
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ var details:Array = new Array();
+ //details.push(lastResponseRecievedApplicationName);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+
+ o.result = handleRequestToDifferentApplication(lastResponseRecievedApplicationName,
+ ToolMarshallingEvent.GET_LAST_ERROR,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+
+ return o;
+ }
+ }
+
+ /**
+ * @private
+ */
+ protected function getRectangle(objID:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ var rid:AutomationID = AutomationID.parse(objID);
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromObjectIDString(objID);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+
+ if (fromTool == true)
+ detailsSentToTool = true;
+ var obj:IAutomationObject = automationManager.resolveIDToSingleObject(rid);
+ o.result = automationManager.getRectangle(obj as DisplayObject);
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+ var details:Array = new Array();
+ details.push(objID);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_RECTANGLE,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ public function getRectangleInScreenCoordinates(objID:String):Array
+ {
+ // for AIR, we need to add the chromeHeight and Chrome width to get the screen coordinates
+ // as the app 0,0 does not include the chrome details.
+
+ var boundarObj:Object = getRectangle(objID);
+ var objBoundaryInAppCoordinates:Array = boundarObj["result"] as Array;
+ var objBoundaryInScreenCoordinates:Array = new Array();
+
+ var windowId:String = automationManager.getAIRWindowUniqueIDFromObjectIDString(objID);
+
+ if(objBoundaryInAppCoordinates.length == 4)
+ {
+ var stageStartScreenCoordinate:Point = getStageStartPointInScreenCoords(windowId);
+
+ if(!stageStartScreenCoordinate)
+ stageStartScreenCoordinate = new Point(0,0);
+ // we would have got the message for this. so the user is not expected to proceed.
+ // the above is done to avoid the null obejct access.
+
+
+ //var chromeHeight:int = getChromeHeight(); // for flex this will return 0
+ //var chromeWidth:int = getChromeWidth(); // for flex this will return 0
+
+ var chromeHeight:int = 0; // for flex this will return 0
+ var chromeWidth:int = 0; // for flex this will return 0
+
+ objBoundaryInScreenCoordinates.push(objBoundaryInAppCoordinates[0] + stageStartScreenCoordinate.x+chromeWidth);
+ objBoundaryInScreenCoordinates.push(objBoundaryInAppCoordinates[1] + stageStartScreenCoordinate.y+chromeHeight);
+ objBoundaryInScreenCoordinates.push(objBoundaryInAppCoordinates[2] + stageStartScreenCoordinate.x+chromeWidth);
+ objBoundaryInScreenCoordinates.push(objBoundaryInAppCoordinates[3] + stageStartScreenCoordinate.y+chromeHeight);
+ /*trace (String(objBoundaryInScreenCoordinates[0]) +
+ String(objBoundaryInScreenCoordinates[1]) +
+ String( objBoundaryInScreenCoordinates[2] ) +
+ String( objBoundaryInScreenCoordinates[3])
+ );*/
+ }
+
+ return objBoundaryInScreenCoordinates;
+
+ }
+ /**
+ * @private
+ */
+ public function getElementFromPoint(x:int, y:int, windowId:String, fromTool:Boolean= true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+
+ try
+ {
+ var details:Array = new Array();
+ details.push(x);
+ details.push(y);
+ details.push(windowId);
+
+ // here the handling is different from the other methods
+ // here we need just let the sub application handle the point
+ // first. if no sub application handles the point, then the main application needs to handle the same
+ if(fromTool == true)
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+
+ // in the case of this method, we need to let all application process
+ // the request. If the application is able to process the details, we need to
+ // get the details. If we get a Popup or Alerts we need to give the importance of the same.
+ // secondly we need to give priority of a non SWFLoader object.
+
+ // first let us call from the main applicaiton
+ var appWindow:DisplayObject = automationManager.getAIRWindow(windowId);
+ //Application.application as DisplayObject;
+ var appPoint:Point = convertScreenPointToStagePoint(new Point(x,y),windowId);
+ var appGlobalPoint:Point = appWindow.localToGlobal(appPoint);
+ var obj:IAutomationObject = automationManager.getElementFromPoint2(appGlobalPoint.x, appGlobalPoint.y,windowId);
+ var result:AutomationID;
+ var mainAppObj:Object = null;
+
+
+ // add the result to the resultObejct array if the result is not a SWFLoader
+ // Note: we need to check how the object is to be handled when the
+ // application is loaded using Loader
+ if((obj != null) && (!(isObjectSWFLoader(obj1))))
+ {
+
+ var currentAppName1:String = getApplicationName();
+ // we dont need to find out if the object belong to popup
+ // if we dont get a pop up from child, and if we got and
+ // object from main application, main application object has the
+ // preference.
+ var isPopup1:Boolean = automationManager.isObjectPopUp(obj);
+ mainAppObj = { result:null, applicationName:currentAppName1,
+ isPopup:isPopup1, error:0 };
+ var resultY:AutomationID = automationManager.createID(obj);
+ mainAppObj.result = resultY.toString();
+ }
+
+ // irrespective of the result from the main application we
+ // to check what is the object at this point by other application.
+ handleRequestToDifferentApplication(null,
+ ToolMarshallingEvent.GET_ELEMENT_FROM_POINT,details);
+
+ if(mainAppObj)
+ {
+ var tempArray:Array = new Array();
+ tempArray.push(mainAppObj);
+ requestResultObjArray = tempArray.concat(requestResultObjArray);
+ }
+
+ // we would have got replies from all applicaitons which could process the object
+ var count:int = requestResultObjArray.length;
+ if(count != 0)
+ {
+ var index:int = 0;
+ var requiredObjectIdentified:Boolean = false;
+ // process each object
+ var currentObj:Object = null;
+ while((!requiredObjectIdentified) && (index < count))
+ {
+ currentObj = requestResultObjArray[index];
+ if(currentObj["isPopup"] == true)
+ {
+ // NOTE: TBD: we need to handle the case of other objects which can be
+ // hosted by the PopupManager
+ requiredObjectIdentified = true;
+ }
+ index++;
+ }
+
+ if(requiredObjectIdentified == true)
+ {
+ lastApplicationName = currentObj["applicationName" ];
+ o.result = currentObj.result;
+ }
+ else
+ {
+ // the last loaded application need not be the application on the top.
+ // this depends on the order of the swfloader in an application.
+ // so we need to get the index of the last application.
+ var lastRequiredObjectIndex:int = automationManager.getTopApplicationIndex(requestResultObjArray);
+
+ //var lastRequiredObjectIndex:int = requestResultObjArray.length - 1;
+
+ if(lastRequiredObjectIndex != -1)
+ {
+ currentObj = requestResultObjArray[lastRequiredObjectIndex];
+ lastApplicationName = currentObj["applicationName" ];
+ o.result = currentObj.result;
+ }
+ }
+ }
+
+ detailsSentToTool = true;
+ }
+ else
+ {
+ appWindow = FlexGlobals.topLevelApplication as DisplayObject;
+ appPoint = convertScreenPointToStagePoint(new Point(x,y),windowId);
+ if(appPoint)
+ {
+ appGlobalPoint = appWindow.localToGlobal(appPoint);
+ var obj1:IAutomationObject = automationManager.getElementFromPoint(appGlobalPoint.x, appGlobalPoint.y);
+
+ // check whether the object is a child of system manager
+ // we expect the Alerts and object hosted by the PopupManager
+ // only to get a special treatment
+ if((obj1 != null) && (!isObjectSWFLoader(obj1)))
+ {
+ var isPopup:Boolean = automationManager.isObjectPopUp(obj1);
+
+ var result1:AutomationID = automationManager.createID(obj1);
+
+ var currentAppName:String = getApplicationName();
+ var o2:Object = { result:null, applicationName:currentAppName,
+ isPopup:isPopup, error:0 };
+ o2.result = result1.toString();
+ return o2;
+ }
+ }
+ }
+ }
+ catch (e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+
+ private function isObjectSWFLoader(obj:Object):Boolean
+ {
+ var retValue:Boolean = false;
+ if(obj is SWFLoader)
+ {
+ // Image is also a SWFLoader. But we should not ignore that.
+ if(!(obj is Image))
+ retValue = true;
+ }
+ return retValue
+ }
+
+ /**
+ * @private
+ */
+ public function getActiveScreen(level:uint,
+ objID:String,
+ leftOffset:int,
+ topOffset:int, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromObjectIDString(objID);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+ if (fromTool == true)
+ detailsSentToTool = true;
+ //we could make the 2nd parameter true if we wanted to support
+ //the complete level
+ o.result = getActiveOrLearnXMLTree(objID, false, "", true, leftOffset, topOffset).learnChildrenXML;
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+ var details:Array = new Array();
+ details.push(level);
+ details.push(objID);
+ details.push(leftOffset);
+ details.push(topOffset);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.GET_ACTIVESCREEN,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
+ // since we have recieved the result, we can send the information back to QTP
+ o = requestResultObjArray[0] as Object;
+ detailsSentToTool = true;
+ }
+ }
+
+ }
+ catch(e:Error)
+ {
+ throw e;
+ }
+ return o;
+ });
+ }
+
+ /**
+ * @private
+ */
+ public function learnChildObjects(objID:String,
+ filterXMLString:String, fromTool:Boolean = true):Object
+ {
+ return useErrorHandler(function():Object
+ {
+ var o:Object = { result:null, error:0 };
+ try
+ {
+ // we need to find out whether the current app and the
+ // reuired app are the same.
+ var requiredApplicationName:String = getApplicationNameFromObjectIDString(objID);
+ var currentApplicationName:String = getApplicationName();
+ if(requiredApplicationName == currentApplicationName)
+ {
+ if (fromTool == true)
+ detailsSentToTool = true;
+ //we could make the 2nd parameter true if we wanted to support
+ //the complete level
+ o.result = getActiveOrLearnXMLTree(objID, true, filterXMLString);
+ }
+ else
+ {
+ // we need to send this as information to the other application
+ // and let the appropriate application handle it.
+
+ // #IMP: MARSHALLING NOTE#: This order of ariguments should not be changed
+ // across versions. If any new arguements is needed in new versions
+ // add them to the end of the list and handle appropriately in the
+ // handler of this event.
+ var details:Array = new Array();
+ details.push(objID);
+ details.push(filterXMLString);
+
+ if(fromTool == true)
+ {
+ requestPending = false;
+ resultRecieved = false;
+ }
+ o.result = handleRequestToDifferentApplication(requiredApplicationName,
+ ToolMarshallingEvent.LEARN_CHILD_OBJECTS,details);
+ if((resultRecieved == true)&&(fromTool == true))
+ {
[... 1251 lines stripped ...]