﻿/*************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
*  Copyright 2004, 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.
*
* $Id: //bridge/piggy/REL2/third_party/ols/ols.jsx#2 $
* $DateTime: 2007/06/18 05:56:59 $
* $Change: 121434 $
* $Author: mgrover $
*
**************************************************************************/

/*
@@@BUILDINFO@@@ ols.jsx 3.2.21.0
*/

/*
@@@START_XML@@@
<?xml version="1.0" encoding="UTF-8"?>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en_US">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>From the Tools menu you can access online services such as printing photos, PhotoStamps, photo books, calendars, greeting cards as well as online sharing and backup. (Some services may not be available in all geographical regions).</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="de_DE">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>Über das Menü "Extras" können Sie auf Onlinedienste wie Fotoabzüge, PhotoStamps, Fotoalben, Kalender, Grußkarten sowie Onlinefreigabe und -sicherung zugreifen. (Einige Dienste sind möglicherweise nicht in allen geografischen Regionen verfügbar.)</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="es_ES">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>En el menú Herramientas, puede acceder a los servicios en línea como la impresión de fotografías, PhotoStamps, álbumes de fotografías, calendarios, tarjetas de felicitación, y además podrá compartir sus imágenes y realizarles copia de seguridad en línea. (Puede que algunos servicios no estén disponibles en algunos países).</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="fr_FR">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>A partir du menu Outils, vous pouvez accéder aux services en ligne comme l'impression ou l'horodatage de photos, les albums photo, les calendriers et les cartes de voeux, ainsi que le partage et la sauvegarde en ligne (certains services peuvent ne pas être disponibles dans toutes les régions géographiques).</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="it_IT">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>Dal menu Strumenti, potete accedere ai servizi in linea quali ad esempio stampa di foto, PhotoStamps, album fotografici, calendari, cartoline, condivisione in linea e backup. (È possibile che alcuni servizi non siano disponibili per tutte le aree geografiche).</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="ja_JP">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>ツールメニューからは、写真のプリント、PhotoStamps、フォトブック、カレンダ、グリーティングカード、オンラインでの共有やバックアップなどのオンラインサービスにアクセスできます（地域によっては一部のサービスが利用できない場合があります）。</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="nl_NL">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>Via het menu Extra krijgt u toegang tot de online services om foto's af te drukken, fotostempels, fotoalbums, kalenders en wenskaarten te maken, online te delen en een back-up te maken (sommige services zijn mogelijk niet beschikbaar in bepaalde geografische regio's).</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="sv_SE">
     <dc:title>Photoshop Services</dc:title>
     <dc:description>Från menyn Verktyg kan du gå till onlinetjänster som utskrift av foton, PhotoStamps, fotoböcker, kalendrar och gratulationskort samt säkerhetskopiering och delning online. (Vissa av tjänsterna är kanske inte tillgängliga i alla geografiska områden.)</dc:description>
</ScriptInfo>
@@@END_XML@@@
*/

onlineservices = { };

if ( BridgeTalk.appName == "bridge" && BridgeTalk.appVersion == "2.0" )
{
    
    $.level=0;

    onlineservices.startupDelay			= 15000;
    onlineservices.versionString 		= "3.2.21";

    onlineservices.debugMenu   			= false;
    
    
    onlineservices.longpath 			= "";
    onlineservices.menuCacheFileName 	= "bolsa.dat";
    onlineservices.olsName 				= "Online Services";
    onlineservices.hostName				= "Adobe Creative Suite 3.0";
    onlineservices.configName			= "ols_config.xml";
    
	 	  
    onlineservices.isMac 				= (File.fs == "Macintosh");
    onlineservices.isWin 				= (File.fs == "Windows");

    onlineservices.logLevel				= 0;   // log everything
    onlineservices.maxErrNum			= 10;
    
    // Default setting for automatic Service retrieval, changing this boolean will
    // alter the startup behavior of OLS, true = auto check for services, false = do no check.
    onlineservices.AutomaticServiceCheckingEnabled = false;
    
	onlineservices.defaultPrintService = undefined;
	
    onlineservices.menuIds =  new Array;
    onlineservices.serviceFileTypes = {};

    onlineservices.getSupportedLocale = function ( )
    {
    	if (app.locale == "en_US" || app.locale == "en_GB" ||
	 		app.locale == "en_UN" || app.locale == "de_DE" ||
 	 		app.locale == "es_ES" || app.locale == "fr_FR" || 
   	 		app.locale == "it_IT" || app.locale == "ja_JP" || 
   	 		app.locale == "nl_NL" || app.locale == "sv_SE")

		 	return app.locale;
		else
			return "en_UN";
	}
	
    /*****************************************************************************
     * Log
     *****************************************************************************/
    
    onlineservices.initLog = function ( )
    {
	// If there is Debug.ini, it set stockphoto.core.log.DebugINIData object.
	// Format of OLSDebug.ini.
	// lev=0 :Everything 1:important only 2:very important only<=default>
	// OLSDebug.ini location:
	// Windows - Program Files\Adobe\Adobe Bridge CS3\
	// Mac - Applications\Adobe Bridge CS3\Bridge\Contents\MaxOS\
	// Log file BridgeLog.txt is located in the same folder as Bridge.exe
		fs = new File( Folder.startup.fsName + "/OLSDebug.ini" );
 		if( ( fs != undefined )&&( fs.exists ) ) 
		{
			app.logging = 1;
			onlineservices.logString(0, "==============================");
			fs.open();
			js = fs.readln();
			if ((js == "") && (fs.eof))
				js = "lev=2";
				
			fs.close();
			try 
			{
				eval(js);
				onlineservices.logLevel = lev;
			} 
			catch(e) 
			{
			}
			delete fs;
		}
		else
			app.logging = 0;
    }

    onlineservices.logString = function ( lev, str)
    {
        if (lev >= onlineservices.logLevel)
        {
            app.log("[OLS] - " + str);
        }
    }

    onlineservices.logObject = function( lev, prefix, obj ) 
    {
        // lev: 0:Everything 1:important only 2:very important only<=default>
        var e = "";
        for (i in obj) 
        {
            if (e == "")
            {
                e += "{ ";
            }
            else 
            {
                e += ", ";
            }
            e += i + ":" + obj[i];
        }
        e += " }";
        onlineservices.logString( lev, prefix+e );
    }

    /*****************************************************************************
     * Localization
     *****************************************************************************/
    onlineservices.beginLocalize = function()
    {
    	var pathSpec = "{STARTUP}" + "/";
	    pathSpec += (File.fs == "Macintosh") ? "../" : "";
    	pathSpec += "Resources/";
	    if (app.language == "Chinese")
		    pathSpec += "{LOCALE}";
    	else
	    	pathSpec += "{LANGUAGE}";
    	pathSpec += (File.fs == "Macintosh") ? ".lproj/" : "/";
	    pathSpec += "{FILENAME}" + ".dat";
    	onlineservices.oldZStringPath = app.zStringPathSpecifier;
	    app.zStringPathSpecifier = pathSpec;
    }

    onlineservices.endLocalize = function()
    {
    	app.zStringPathSpecifier = onlineservices.oldZStringPath;
    }

    onlineservices.localize = function( str )
    {
        onlineservices.beginLocalize();
        var result = localize( str );
        onlineservices.endLocalize();
        return result;
    }
    
    onlineservices.localize1Param = function( str, p1 )
    {
        onlineservices.beginLocalize();
        var result = localize( str, p1 );
        onlineservices.endLocalize();
        return result;
    }
    
    onlineservices.localize2Params = function( str, p1, p2)
    {
        onlineservices.beginLocalize();
        var result = localize( str, p1, p2 );
        onlineservices.endLocalize();
        return result;
    }
    
	// Service names are localized in OLS Manifests.
    onlineservices.localizeMenuName = function( str )
    {
       return str; 
    }
    

    /*********************************************************************************************
     * 						OLS Menu Setup and Caching support
     *********************************************************************************************/
     
	onlineservices.menubarLocation0    = "after submenu/VersionCue";    // Do not localize.
    onlineservices.menubarLocation     = "before FileInfo";             // Do not localize.
    onlineservices.contextmenuLocation = "before Thumbnail/FileInfo";   // Do not localize.
    onlineservices.menuId			   = "Tools/PhotoshopServices";
    onlineservices.menuitemLocation    = "at the end of Tools/PhotoshopServices"; // Do not localize.

    onlineservices.menubar =
        new MenuElement
        (
            "menu"
        ,   onlineservices.localize("$$$/CS2/OLS/Menus/PhotoshopServices=Photoshop Services")
        ,   '-' + onlineservices.menubarLocation0
        ,   "Tools/PhotoshopServices"
        );

	/**
	 * Builds Menu command with  check mark for toggling Automated Manifest checking on/off
	 *
	 */
    onlineservices.buildAutomateMenu = function()
    {
    	var menuId = 'ols.automatic.manifest';
		var olsAutoCheckforServices =   
			new MenuElement
			(
				"command"
			,   onlineservices.localize("$$$/CS2/OLS/Menus/AutoUpdateNewServices=Automatically check for services")
			,   onlineservices.menuitemLocation
			,   menuId
		); 
		olsAutoCheckforServices.checked = onlineservices.AutomaticServiceCheckingEnabled;
		olsAutoCheckforServices.onSelect = function()
		{
			if( onlineservices.AutomaticServiceCheckingEnabled == true)
				onlineservices.AutomaticServiceCheckingEnabled = false;
			else
				onlineservices.AutomaticServiceCheckingEnabled = true;

			onlineservices.logString(0, "Automatically check for services Clicked oldCheck=" + this.checked + " newCheck=" + onlineservices.AutomaticServiceCheckingEnabled);
			this.checked = onlineservices.AutomaticServiceCheckingEnabled;
			onlineservices.putMenuCache(onlineservices.menuCache);
			onlineservices.initializeOLS();
		}
		onlineservices.menuIds[onlineservices.menuIds.length] = menuId;
	}
    
 	/**
	 * Builds Menu command with  check mark for toggling Automated Manifest checking on/off
	 *
	 */
    onlineservices.buildEnablePhotoShopServicesMenu = function()
    {
    	var menuId = 'ols.enable.services';
		var olsEnablePhotoShopServices =   
			new MenuElement
			(
				"command"
			,   onlineservices.localize("$$$/CS2/OLS/EnableDialog/EnablingPhotoshopServices=Enabling Photoshop Services")+"..."
			,   onlineservices.menuitemLocation
			,   menuId
		); 
		olsEnablePhotoShopServices.onSelect = function()
		{
			onlineservices.logString(0, "Enabling Photoshop Services Clicked");
			onlineservices.enablePhotoshopServicesInfo();
		}
		onlineservices.menuIds[onlineservices.menuIds.length] = menuId;
	}


	/**
	 * Debug Menu command support - displays debug infor (version and timestamp of library)
	 *
	 */
    onlineservices.debugInfo = function()
    {
      onlineservices.showDebugInfo();
    };
  
    if ( onlineservices.debugMenu )
    {
        onlineservices.menubar.debugInfo =
            new MenuElement
            (
                "command"
            ,   onlineservices.localize("$$$/CS2/OLS/Menus/DebugInfo=Debug Info...")
            ,   onlineservices.menuitemLocation
            );
        onlineservices.menubar.debugInfo.onSelect = function()
        {
            onlineservices.showDebugInfo();
        };
    }
 
	/**
	 * Debug Menu command support - displays debug infor (version and timestamp of library)
	 *
	 */
    onlineservices.showDebugInfo = function ()
    {
        var jsxVersion   = "ols.jsx version: " + onlineservices.versionString;
        var libFilename  = onlineservices.getLibFilename();
        var libVersion   = libFilename + " version: ";
        var libBuildDate = libFilename + " build date: ";
        
        onlineservices.loadLib();
        if ( onlineservices.lib != undefined )
        {
            libVersion   += onlineservices.lib.getOLSCS2Version();
            libBuildDate += onlineservices.lib.getOLSCS2BuildDate();
        }
        else
        {
            libVersion   += "lib not found";
            libBuildDate += "lib not found";
        }
        Window.alert( jsxVersion + '\n' + libVersion + '\n' + libBuildDate );
    }
    
    
		/*************************************
		 * Menu Command OnSelect functions
		 ************************************/
     onlineservices.enablePhotoshopServicesInfo = function()
    {
		var dlg = new Window('dialog', onlineservices.localize("$$$/CS2/OLS/EnableDialog/EnablingPhotoshopServices=Enabling Photoshop Services"),[100,100,660,340]);
		dlg.center();
		dlg.msgSt = dlg.add('statictext', [20,20,550,200], 
		onlineservices.localize("$$$/CS2/OLS/EnableDialog/EnableServicesInfo1=Photoshop Services are a collection of carefully selected Online resources tailored to meet the needs of Photoshop and Creative Suite users.")+"\n\n"+
		onlineservices.localize("$$$/CS2/OLS/EnableDialog/EnableServicesInfo2=To begin accessing Photoshop Services, you must first enable them by going to your Tools menu and selecting 'Tools->Photoshop Services->Automatically check for new services'.")+" "+
		onlineservices.localize("$$$/CS2/OLS/EnableDialog/EnableServicesInfo3=By enabling this automatic check, your Photoshop Services choices will always be kept up to date as new services become available.")+"\n"+
		onlineservices.localize("$$$/CS2/OLS/EnableDialog/EnableServicesInfo4=(Please note there will be a short delay before the services show up in the menu.)"),{multiline:true});
        dlg.Done = dlg.add('button', [460,205,530,225], 'OK', {name:'ok'});
		dlg.show();	
	}

	 
	/**
	 * Setup and execute service request which requires File Selection
	 *
	 */
 	onlineservices.OLSSelectRequireSelections = function() 
 	{
   		onlineservices.logString(0, "Enter OLSSelectRequireSelections");
		var selection = app.document.selections;
		if(!onlineservices.preflightSelections( selection, this.id))
			return;
		onlineservices.terminateSessions();
		onlineservices.begin( "job" );
		onlineservices.begin( "service-spec" );
			onlineservices.set( "id", this.id );
		onlineservices.end();
		onlineservices.includeDocuments( selection );
		onlineservices.end();
		
		onlineservices.pumpOls();
   		onlineservices.logString(0, "Exit OLSSelectRequireSelections");		
   	};
 
	/**
	 * Setup and execute gerneric service request - no prerequisites
	 *
	 */
     onlineservices.OLSSelect = function()
    {
    	onlineservices.terminateSessions();
        onlineservices.begin( "job" );
           onlineservices.begin( "service-spec" );
                onlineservices.set( "id", this.id );
           onlineservices.end();
       onlineservices.end();
       
	   onlineservices.pumpOls();
    };
    
	/**
	 * A hook to provide Photoshop a mechanism to launch a 
	 *   the print online workflow.
	 *
	 * @param	inThumbs	Thumb selection doc selection.
	 */
    onlineservices.printOnline = function (inThumbs)
    {
		onlineservices.logString(0, "Enter printOnline");    
    	if (inThumbs == undefined)
    		inThumbs = app.document.selections;
    		
    	if(onlineservices.defaultPrintService != undefined)
    	{
			if(!onlineservices.preflightSelections( inThumbs, onlineservices.defaultPrintService))
				return;
			onlineservices.terminateSessions();
			onlineservices.begin( "job" );
			onlineservices.begin( "service-spec" );
				onlineservices.set( "id", onlineservices.defaultPrintService );
			onlineservices.end();
			onlineservices.includeDocuments(inThumbs );
			onlineservices.end();
    	}
    	else
    	{
			onlineservices.terminateSessions();
			onlineservices.begin( "job" );
				onlineservices.begin( "service-spec" );
					onlineservices.set( "workflow", "print-photo" );
				onlineservices.end();
				onlineservices.includeDocuments( inThumbs );
			onlineservices.end();
        }
	   onlineservices.pumpOls();
 	   onlineservices.logString(0, "Exit printOnline");	   
    }

      

		/***************************************************
		 * SuMenu and Menu Command Build/Teardown functionss
		 ***************************************************/

	/**
	 * Teardown dynamically generated SubMenu and Menu Commands.
	 */
	onlineservices.tearDownMenus = function ()
	{
		if(onlineservices.menuIds == undefined)
			return;
		var index = 0;	
		while(onlineservices.menuIds[index] != undefined)
			MenuElement.remove(onlineservices.menuIds[index++]);
			
	}
	
	/**
	 * Sets up the FileTypes array for this service. This is later used to filter
	 *  selections when the service is invoked.
	 * 
	 * @param	inFileTypesElement			the element object to append to
	 * @param	inServiceId					String constains the unique serviceid 
	*/
	onlineservices.addServiceFileTypes = function (inFileTypesElement, inServiceId)
	{
		if(onlineservices.OLSElement_IsValid(inFileTypesElement))
		{
			var fileTypeArray = new Array;
			for ( var fileTypeIndex = 0; fileTypeIndex < onlineservices.OLSElement_GetChildElementCount(inFileTypesElement); fileTypeIndex++ ) 
				 fileTypeArray[fileTypeIndex] = onlineservices.OLSElement_GetChildElement( inFileTypesElement, fileTypeIndex ).value;
			onlineservices.serviceFileTypes[inServiceId]= fileTypeArray;
		}

	}

	/**
	 * Builds a Submenu, used during the generation of Dynamic Menu hierarchy
	 * 
	 * @param	inMenuName			The display name of the Menu
	 * @param	inMenuid			The menu id (typically based on the service id) for this command. 
	 */
    onlineservices.buildOLSSubMenu = function (inMenuName,inMenuid)
    {
    	var submenu =  new MenuElement
        		(
            		"menu"
        		,   onlineservices.localizeMenuName(inMenuName)
        		,   onlineservices.menuitemLocation
        		,   inMenuid
        );
        onlineservices.menuIds[onlineservices.menuIds.length]=inMenuid;

    }

	/**
	 * Builds an  Menu Command, used during the generation of Dynamic Menu hierarchy
	 * 
	 * @param	inServiceElement	The Service Element to be executed by this command.
	 * @param	inSubMenuId			The id of the menu in which this command is appended
	 */
    onlineservices.buildOLSMenuCommand = function (inServiceElement, inSubMenuId)
    {
		var name 	= onlineservices.OLSElement_FindFirstChildElement( inServiceElement, "title" ).value
		var id 		= onlineservices.OLSElement_FindFirstChildElement( inServiceElement, "id" ).value
		var rank 	= onlineservices.OLSElement_FindFirstChildElement( inServiceElement, "rank" ).value
		var requiresFiles = onlineservices.OLSElement_FindFirstChildElement ( inServiceElement, "service-requires-files" ).value
		var fileTypeListNode = onlineservices.OLSElement_FindFirstChildElement ( inServiceElement, "file-type-list" );
		
		var location = onlineservices.menuitemLocation;
		if(inSubMenuId)
		{
			location = "at the end of "+inSubMenuId
		}
		var command =         new MenuElement
			(
				"command"
			,   onlineservices.localizeMenuName(name+"...")
			,   location
			,   id
		);
             		
   	   if(requiresFiles == "true")
   	   {
   	   		command.onSelect  = onlineservices.OLSSelectRequireSelections;
        	command.onDisplay = function(m) { m.enabled = app.document != undefined && app.document.selectionsLength > 0; };
        	onlineservices.addServiceFileTypes(fileTypeListNode, id);
       }
       else
       {
      		command.onSelect = onlineservices.OLSSelect;
       }
	   if(inSubMenuId == "print-photo" && rank == "1")
			onlineservices.defaultPrintService = id;
   		onlineservices.menuIds[onlineservices.menuIds.length]=id;

    }
    	

	/**
	* Parses a description of the services from a Serialized description
	* ordered by Workflow Rank and inside that individual Service Rank.
	* All workflows with greater than 1 service will be represented as a 
	* submenu below the OnlineServices menu structure. Workflows with only
	* a single service will not have a submenu, the service will be represented
	* as a single menu command directly in under the OnlineServices menu.
	*
	* @param	inMenuDesc		Serialized Services Menu Description generated by OLS library.	
	*/
	onlineservices.buildOLSMenus = function (inMenuDesc) 
	{
		onlineservices.logString(0, "Enter buildOLSMenus");  
		onlineservices.putMenuCache(inMenuDesc);

		// setup parentMenu
		onlineservices.tearDownMenus();
		
		// Create a fresh menu array
		onlineservices.menuIds = new Array;
		
		// Deserialize the menu description into an OLS Element
		var serviceMenusElement = onlineservices.OLSElement_Deserialize(inMenuDesc);
 		if(serviceMenusElement == null || !onlineservices.OLSElement_IsValid(serviceMenusElement))
 		{
	 		onlineservices.logString(0, "build default menu");  
			onlineservices.buildEnablePhotoShopServicesMenu();
 			onlineservices.buildAutomateMenu();		
			return false;
		}

		onlineservices.logString(0, "build menu from catch");  
		for ( var serviceMenuIndex = 0; serviceMenuIndex < onlineservices.OLSElement_GetChildElementCount(serviceMenusElement); serviceMenuIndex++ ) 
		{
			var workflowElement = onlineservices.OLSElement_GetChildElement( serviceMenusElement, serviceMenuIndex );
			var serviceListElement = onlineservices.OLSElement_FindFirstChildElement( workflowElement, "service-list");
			
			if(onlineservices.OLSElement_GetChildElementCount(serviceListElement) == 1)
			{
				var serviceElement = onlineservices.OLSElement_FindFirstChildElement( serviceListElement, "service");
				onlineservices.buildOLSMenuCommand(serviceElement,onlineservices.menuId);
			}
			else
			{
				var workflowName 	= onlineservices.OLSElement_FindFirstChildElement( workflowElement, "title" ).value;
				var workflowId 		= onlineservices.OLSElement_FindFirstChildElement( workflowElement, "workflow" ).value;
				onlineservices.buildOLSSubMenu(workflowName,workflowId);
				for ( var serviceNodesIndex = 0; serviceNodesIndex < onlineservices.OLSElement_GetChildElementCount(serviceListElement); serviceNodesIndex++ ) 
				{
					var serviceElement = onlineservices.OLSElement_GetChildElement( serviceListElement, serviceNodesIndex);
					onlineservices.buildOLSMenuCommand(serviceElement,workflowId);
				}
			}
		}
		onlineservices.buildAutomateMenu();		
		return true;

	}
	
		/************************************************************************
		 * 					Menu Cache File Support
		 *
		 * Note: The cache consists of 3 items. 
		 *   1) Version String (matched against the version of the jsx
		 *   2) Flag which triggers on/off Automatic Background Manifest checking
		 *   3) Services Menu Description which consists of serialized OLS Elements 
		 ************************************************************************/
 
	/**
	 * Retrieves Cache Path for serialized OLS Menu Description
	 * 
	 * @return	Path of ols menu Cache file	
	 */
    onlineservices.getMenuCachePath = function()
    {
        var cachePath = Folder.userData.fsName+ "/Adobe/" + onlineservices.olsName+ "/" +onlineservices.hostName+ "/" +onlineservices.menuCacheFileName;

        return cachePath;
    }
    
	/**
	 * Retrieves the persisted Menu Cache, does simple version check of the cache
	 *    and 
	 * 
	 * @return	Serialized Services Menu Description generated by OLS library.	
	 *          Undefined is no cached Service Menu Descriptions exist
	 */
    onlineservices.getMenuCache = function()
    {
	     	   	
        var menuCacheFile = new File( onlineservices.getMenuCachePath() );
      	if(menuCacheFile.exists)
     	{
     		menuCacheFile.open('r');
     		menuCacheFile.encoding = 'UTF-8';
			var version = menuCacheFile.readln();
			if(version != onlineservices.versionString)
			{
				onlineservices.removeMenuCache();
				return undefined;
			}
    			
 			var cacheSetting = menuCacheFile.readln();
			if(cacheSetting == "true")
				onlineservices.AutomaticServiceCheckingEnabled = true;
			else
				onlineservices.AutomaticServiceCheckingEnabled = false;

     		var menuDesc = menuCacheFile.read();
  			menuCacheFile.close();
   			if(menuDesc.lengh == 0)
   				return undefined;
   			else
     			return menuDesc;
		}
		return undefined;
    }
    
	/**
	 * 	Writes out a Menu Cache, associated version string and  AutomaticServiceCheckingEnabled
	 *  flag.
	 * 
	 * @param inMenuDesc	Serialized Services Menu Description generated by OLS library.	
	 *          			Undefined is no cached Service Menu Descriptions exist
	 */
    onlineservices.putMenuCache = function (inMenuDesc)
    {
    	   	
        var menuCacheFile = new File( onlineservices.getMenuCachePath() );
         
     	menuCacheFile.open('w');
     	menuCacheFile.encoding = 'UTF-8';
     	menuCacheFile.writeln(onlineservices.versionString);
     	var automaticChecking = "false";
		if(onlineservices.AutomaticServiceCheckingEnabled == true)
			automaticChecking = "true"
     	menuCacheFile.writeln(automaticChecking);

		if(inMenuDesc != undefined && inMenuDesc.length > 0)
		{
			menuCacheFile.write(inMenuDesc);
    		menuCacheFile.close();
    	}
    		
    }

    
	/**
	 * 	Removes any pre-existing Menu Cache file
	 * 
	 * @param inMenuDesc	Serialized Services Menu Description generated by OLS library.	
	 *          			Undefined is no cached Service Menu Descriptions exist
	 */
     onlineservices.removeMenuCache = function ()
    {
        var menuCacheFile = new File( onlineservices.getMenuCachePath() );
      	if(menuCacheFile.exists)
     		menuCacheFile.remove();
    }


    /*****************************************************************************
     * Element Utilities - data structures to facilitate data exchange using 
     * OLS Element objects. see COLSElement.cpp
     *****************************************************************************/


	/**
	 * Create a new element object with the specified name and value.  The
	 * name must be valid by OLS rules.  The value can be null or simply
	 * unspecified.  If the name is invalid, the null is returned.  Otherwise
	 * the new element object is returned.
	 *
	 * @param	inName							the name of the element object to create
	 * @param	inValue							the value of the element object to create, can be null or unspecified
	 */
	onlineservices.OLSElement_New = function ( inName, inValue )
	{
		var		name;
		var		value;
		var		element;

		// Validate the name
		if ( null == inName )
			return null;
		name = inName.toString();
//		if ( !onlineservices.sOLSElementNamePattern.test( name ) )
//			return null;
	
		// Validate the value
		if ( null != inValue )
			value = inValue.toString();
		
		// Create the element
		element = new Object;
		element.name = name;
		element.value = value;
		element.elementArray = null;
		
		return element;
	}
	
	/**
	 * Get the number of child element objects contained in the
	 * element's child element object array.  Validates the
	 * element object before returning.  If the element object
	 * is invalid the returns zero.  Otherwise, returns the
	 * number of child element objects in the child element object array.
	 *
	 * @param	inElement						the element object to get the number of child element objects from
	 * @return									the number of child element objects found if successful, otherwise zero
	 */
	onlineservices.OLSElement_GetChildElementCount = function ( inElement )
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return 0;
			
		if ( null == inElement.elementArray )
			return 0;
			
		return inElement.elementArray.length;
	}
	
	/**
	 * Get the child element object at the specifed index.  Validates
	 * the element object before returning.  If the element object
	 * is invalid or the index is outside of the child element object array
	 * size then null is returned.  Otherwise, the child element object
	 * found in the child element object array at the specified index is
	 * returned.
	 *
	 * @param	inElement						the element object to get the child element object from
	 * @param	inIndex							the index of the child element object to obtain
	 * @return									the child element object if found, otherwise null
	 */
	onlineservices.OLSElement_GetChildElement = function ( inElement, inIndex )
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return null;
			
		if ( null == inElement.elementArray )
			return null;
			
		if ( inElement.elementArray.length <= inIndex )
			return null;
			
		return inElement.elementArray[inIndex];
	}
	
	/**
	 * Find the first child element object with a given name in an
	 * element object child element array.  Validates the element object
	 * before finding.  If the element object is not valid or a child
	 * element with the specified name cannot be found, then null is
	 * returned.  Otherwise, the child element object found is
	 * returned.
	 *
	 * @param	inElement						the element object to search for a child element object
	 * @param	inName							the name of the first child element object to find
	 * @return									the child element object if found, otherwise null
	 */
	onlineservices.OLSElement_FindFirstChildElement = function ( inElement, inName ) 
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return null;
		if ( null == inName )
			return null;
			
		if ( null == inElement.elementArray )
			return null;
	
		for ( var index = 0; index < inElement.elementArray.length; index++ )
		{
			var			element;
			
			element = inElement.elementArray[index];
			if ( element.name == inName )
				return element;
		}
	
		return null;
	}
	
	/**
	 * Append an element object to the child element object array of
	 * an element.  Validates the element object and child element object 
	 * before appending.  If the element object or child element object is 
	 * invalid or the element object already has a value (and, therefore, cannot 
	 * contain child element objects) then null is returned.  If all succeeds, then 
	 * the element object with the appended child element object is returned.
	 *
	 * @param	inElement						the element object to append to
	 * @param	inChildElement					the child element object to append
	 * @return									the element object if success, otherwise null
	 */
	onlineservices.OLSElement_AppendChildElement = function ( inElement, inChildElement )
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return null;
		if ( !onlineservices.OLSElement_IsValid( inChildElement ) )
			return null;
	
		// If there is already a value, then bail
		if ( null != inElement.value )
			return null;
			
		// Make sure there is an element array		
		if ( null == inElement.elementArray )
			inElement.elementArray = new Array;
		
		// Append it
		inElement.elementArray = inElement.elementArray.concat( inChildElement );
		
		return inElement;
	}
	
	/**
	 * Append the child element objects of a source element object to an element object.  
	 * Validates the element object and source element object before appending.  
	 * If the element object or source element object is invalid or the element object 
	 * already has a value (and, therefore, cannot contain child element objects) then null 
	 * is returned.  If all succeeds, then the element object with the appended child
	 * element objects is returned.
	 *
	 * @param	inElement						the element object to append to
	 * @param	inSourceElement					the element object with child element objects to append
	 * @return									the element object if success, otherwise null
	 */
	onlineservices.OLSElement_AppendChildElements = function ( inElement, inSourceElement )
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return null;
		if ( !onlineservices.OLSElement_IsValid( inSourceElement ) )
			return null;
	
		// If there is already a value, then bail
		if ( null != inElement.value )
			return null;
			
		// If the source element doesn't have child elements, then just leave
		if ( null == inSourceElement.elementArray )
			return inElement;
		if ( 0 >= inSourceElement.elementArray.length )
			return inElement;
			
		// Make sure there is an element array		
		if ( null == inElement.elementArray )
			inElement.elementArray = new Array;
			
		// Add the array
		inElement.elementArray = inElement.elementArray.concat( inSourceElement.elementArray );
		
		return inElement;
	}
	
	/**
	 * Serialize an element object into JavaScript object literal representation.  
	 * Serializes the element object, its name, value and all child elements.  This function 
	 * is invoked recursively to serialize all child element objects.  Validates
	 * the element object before serializing.
	 * 
	 * @param	inElement						the element object to serialize
	 * @return									the serialized element string
	 */
	onlineservices.OLSElement_Serialize = function ( inElement )
	{
		var		elementString;
		
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return "{}";
		
		// Name
		elementString = "{name:\"" + inElement.name + "\"";
	
		// Value
		if ( null != inElement.value )
			elementString += ",value:\"" + inElement.value + "\"";
	
		// Child elements
		if ( null != inElement.elementArray )
		{
			// Element array start
			elementString += ",elementArray:[";
			
			// Add all of the child elements
			for ( var index = 0; index < inElement.elementArray.length; index++ )
			{
				// Add a separating comma
				if ( 0 < index )
					elementString += ",";
					
				// Add the serialized child element
				elementString += onlineservices.OLSElement_Serialize( inElement.elementArray[index] );
			}
	
			// Element array end
			elementString += "]";
		}
	
		elementString += "}";
	
		return elementString;
	}
		
	/**
	 * Deserialize a serialized element.  Since an element object is serialized  
	 * in JavaScript object literal representation it is only necesssary to evaluate 
	 * the string to deserialize into an element object.
	 *
	 * @param	inSerializedElementString		the serialized element string
	 * @return									the deserialized element object
	 */
	onlineservices.OLSElement_Deserialize = function (inSerializedElementString)
	{
		var		element;
		
		try{
			eval( "element = " + inSerializedElementString );
		}
		catch(p)
		{
			return null; 
		}
		
		return element;
	}
	
	/**
	 * Validates an element object.  Ensures that the element object has a valid name and
	 * either a valid value or valid child element object array, but not both.
	 *
	 * @param	inElement						the element object to validate
	 * @return									is the element object valid
	 */
	onlineservices.OLSElement_IsValid = function ( inElement )
	{
		if ( null == inElement )
			return false;
		if ( typeof inElement != "object" )
			return false;
		if ( null == inElement.name )
			return false;
 		if ( typeof inElement.name != "string" )
			return false;
//		if ( !onlineservices.sOLSElementNamePattern.test( inElement.name ) )
//			return false; XXXshg 
		if ( ( null != inElement.value ) && ( null != inElement.elementArray ) )
			return false;
		if ( null != inElement.value )
			if ( typeof inElement.value != "string" )
				return false;
		if ( null != inElement.elementArray )
			if ( ( typeof inElement.elementArray != "object" ) || 
					( inElement.elementArray.constructor != Array ) )
				return false;
		
		return true;
	}
	
         
    /*****************************************************************************
     * Common code
     *****************************************************************************/

	/**
	 * First of a sequence of calls required to set data typically used by a
	 * Service workflow.
	 *
	 * @param	inName		outter  most tag for this request.
	 */
    onlineservices.begin = function ( inName )
    {
		app.initializeOpera();   
        onlineservices.loadLib();
        if ( onlineservices.lib != undefined )
        {
            onlineservices.lib.begin( inName );
        }
    }

	/**
	 * Follows the "begin" operation and sets individual element required
	 *
	 * @param	inName		Name and Value pair describing a service element.
	 * @param	inValue		
	 */
    onlineservices.set = function ( inName, inValue )
    {
        onlineservices.loadLib();
        if ( onlineservices.lib != undefined )
        {
			onlineservices.lib.set( inName, inValue );
		}
    }
       
	/**
	 * Brackets with "begin" a series of sets operations. See COLSElements.cpp
	 * and ClientManager.cpp for details.
	 *
	 * @param	inName		Name and Value pair describing a service element.
	 * @param	inValue		
	 */
    onlineservices.end = function ()
    {
        onlineservices.loadLib();
        if ( onlineservices.lib != undefined )
        {
			onlineservices.lib.end();
		}
    }
    
    
	/**
	 * Messages the Library to terminate any outstanding sessions
	 */
    onlineservices.terminateSessions = function ()
    {
        onlineservices.loadLib();
        if ( onlineservices.lib != undefined )
        {
			onlineservices.lib.terminateSessions();
		}
    }


    onlineservices.isDocumentSelected = function ()
    {
        return app.document != undefined && app.document.selectionsLength > 0;
    }

    onlineservices.log = function (str)
    {
        app.console( "[OnlineServices] " + str + "\n" );
    };

    onlineservices.dumpObj = function ( prefix, obj )
    {
        var e = "";
        for (i in obj)
        {
            if (e == "")
            {
                e += "{ ";
            }
            else
            {
                e += ", ";
            }
            e += i + ":" + obj[i];
        }
        e += " }";
        onlineservices.log(prefix + e);
    }

    
    onlineservices.createProgressView = function ( description, percent, detail )
    {
		onlineservices.logString(0, "Enter createProgressView description=" + description + " percent=" + percent + " detail=" + detail);
		if (onlineservices.progressView)
		{
			onlineservices.progressView.description.text = description;
			onlineservices.progressView.progress.value = percent;
			onlineservices.progressView.detail.text = detail;
			onlineservices.progressView.layout.layout(true);
			onlineservices.progressView.show();
		}
		else
		{
			var v = new Window( 'palette' );
			v.orientation            = 'column';
			v.alignChildren          = 'fill';
    
			v.description            = v.add( 'statictext' );
			v.description.text		 = onlineservices.longpath;
        
			v.progress               = v.add( 'progressbar' );
			v.progress.preferredSize = { width:300, height:20 };
			v.progress.value         = percent;

			v.detail                 = v.add( 'statictext' );
			v.detail.justify         = 'center';
			v.detail.text            = detail;
        
			v.cancelButton = v.add( 'button' );
			v.cancelButton.alignment = 'right';
			v.cancelButton.text = onlineservices.localize( "$$$/CS2/OLS/SessionManager/CancelButton=Cancel" );

			v.center();
			v.show();
        
			v.cancelButton.onClick = function ()
			{
				onlineservices.terminateSessions();
			}

			v.onClose = function ()
			{
				onlineservices.terminateSessions();
			}
			
			onlineservices.progressView = v;
			v.description.text       = description;
		}
		onlineservices.logString(0, "Exit createProgressView");
    }

    onlineservices.updateProgressView = function ( description, bytesCompleted, bytesTotal )
    {
		onlineservices.logString(0, "Enter updateProgressView bytesCompleted=" + bytesCompleted + " bytesTotal=" + bytesTotal);
        if ( bytesCompleted != bytesTotal )
        {
            var descriptionDecoded = unescape( description );
            var detail = bytesCompleted.toString() + " / " + bytesTotal.toString(); // FIXME: Zstring needed;
            var percent;
            
            if ( bytesCompleted == 0 )
            {
                percent = 0;
            }
            else if ( bytesCompleted >= bytesTotal )
            {
                percent = 100;
            }
            else
            {
                percent = Math.ceil( bytesCompleted / bytesTotal * 100 );
            }
           
            if ( onlineservices.progressView )
            {
                if ( onlineservices.progressView.description.text != descriptionDecoded )
                {
                    onlineservices.createProgressView( descriptionDecoded, percent, detail );
                }
                else
                {
                    onlineservices.progressView.progress.value = percent;
                    onlineservices.progressView.detail.text = detail;
                }
            }
            else
            {
                onlineservices.createProgressView( descriptionDecoded, percent, detail );
            }
        }
        else
        {
			if ( onlineservices.progressView )
			{
				onlineservices.progressView.hide();
			}
        }
    onlineservices.logString(0, "Exit updateProgressView");
    }

   onlineservices.hideProgressView = function ()
    {
	    onlineservices.logString(0, "Enter hideProgressView");
        if ( onlineservices.progressView )
        {
            onlineservices.progressView.hide();
        }
    }
    
    onlineservices.finishProgressView = function ()
    {
	    onlineservices.logString(0, "Enter finishProgressView");
        if ( onlineservices.progressView )
        {
            onlineservices.progressView.close();
            onlineservices.progressView = undefined;
        }
    }

    onlineservices.loadLocale = function ()
    {
        if ( onlineservices.lib )
        {
			var l =onlineservices.getSupportedLocale();
			onlineservices.logString(0, "loadLocale locale=" + l);			
     	   onlineservices.lib.set("app_locale", l);
        }
    }

    onlineservices.bringAppToFront = function ()
    {
		BridgeTalk.bringToFront("bridge");
    }

    onlineservices.getLibFilename = function ()
    {
        var libFilename;
        if ( onlineservices.isWin )
        {
            libFilename = "ols.dll";
        }
        else // if ( onlineservices.isMac )
        {
            libFilename = "ols.bundle";
        }
        return libFilename;

    }
    
    onlineservices.getLibPath = function ()
    {
        var libFilename = onlineservices.getLibFilename();
        var libPath;
        if ( onlineservices.isWin )
        {
            libPath = Folder.startup + "/" + libFilename;
        }
        else // if ( onlineservices.isMac )
        {
            libPath = Folder.startup.fsName + "/../../../Plug-ins/" + libFilename;
        }
        return libPath;
    }

   onlineservices.getOLSConfigPath = function ()
    {
        var configPath;
        if ( onlineservices.isWin )
        {
            configPath = Folder.startup.fsName + "/"+ onlineservices.configName;
        }
        else // if ( onlineservices.isMac )
        {
            configPath = Folder.startup.fsName + "/../../../Plug-ins/" + onlineservices.configName;
        }
        return configPath;
    }
    
    onlineservices.loadLib = function ()
    {
        if ( onlineservices.lib == undefined )
        {
            var libPath = onlineservices.getLibPath();
            var libFileObj = new File( libPath );
            if ( libFileObj.exists )
            {
				try
				{
					onlineservices.lib = new ExternalObject( "lib:" + File.decode(libPath) );
					onlineservices.lib.startBolsa(onlineservices.hostName,onlineservices.getOLSConfigPath());
					onlineservices.restoreProperties();
					onlineservices.loadLocale();
				}
				catch (e)
				{
					var fs = new File( Folder.startup.fsName + "/OLSDebug.ini" );
					if( ( fs != undefined )&&( fs.exists ) ) 
						Window.alert( "OLS library not found(" + e + "): " + File.decode(libPath));
				}
            }
            else
            {
				var fs = new File( Folder.startup.fsName + "/OLSDebug.ini" );
				if( ( fs != undefined )&&( fs.exists ) ) 
					Window.alert( "OLS library not found: " + File.decode(libPath) );
            }
        }
    }


    onlineservices.restoreProperties = function ()
    {
        if ( app.preferences.onlineservicesPropertyKeysA  == undefined
          || app.preferences.onlineservicesPropertyKeysB  == undefined
          || app.preferences.onlineservicesPropertyValues == undefined )
        {
            return;
        }
        
        var keysA  = eval( app.preferences.onlineservicesPropertyKeysA );
        var keysB  = eval( app.preferences.onlineservicesPropertyKeysB );
        var values = eval( app.preferences.onlineservicesPropertyValues );

        if ( keysA.length != keysB.length || keysB.length != values.length )
        {
            return;
        }
        
        onlineservices.begin( "cs2-ols-properties" ); // Do not localize.
        
        for ( var i in keysA )
        {
            onlineservices.begin( "cs2-ols-property" ); // Do not localize.
                onlineservices.set( "key-a", unescape( keysA[i] ) ); // Do not localize.
                onlineservices.set( "key-b", unescape( keysB[i] ) ); // Do not localize.
                onlineservices.set( "value", unescape( values[i] ) ); // Do not localize.
            onlineservices.end();
        }

        onlineservices.end();
    }
   
    onlineservices.getProperty = function (keyA, keyB)
    {
    	var value = undefined;
    	
        if ( app.preferences.onlineservicesPropertyKeysA  == undefined
          || app.preferences.onlineservicesPropertyKeysB  == undefined
          || app.preferences.onlineservicesPropertyValues == undefined )
        {
            return value;
        }
        
        var keysA  = eval( app.preferences.onlineservicesPropertyKeysA );
        var keysB  = eval( app.preferences.onlineservicesPropertyKeysB );
        var values = eval( app.preferences.onlineservicesPropertyValues );

        if ( keysA.length != keysB.length || keysB.length != values.length )
        {
            return value;
        }
                
        for ( var i in keysA )
        {
        	if (unescape( keysA[i]) == keyA && unescape( keysB[i] == keyB))
        	{
        		value = unescape( values[i] );
        		break;
        	}
        }
        
        return value;
    }

    onlineservices.beginProperties = function ()
    {
        onlineservices.propertyKeysA  = new Array;
        onlineservices.propertyKeysB  = new Array;
        onlineservices.propertyValues = new Array;
    }

    onlineservices.setProperty = function ( keyA, keyB, value )
    {
        onlineservices.propertyKeysA.push(  escape( keyA ) );
        onlineservices.propertyKeysB.push(  escape( keyB ) );
        onlineservices.propertyValues.push( escape( value ) );
    }

    onlineservices.endProperties = function ()
    {
        app.preferences.onlineservicesPropertyKeysA  = onlineservices.propertyKeysA.toSource();
        app.preferences.onlineservicesPropertyKeysB  = onlineservices.propertyKeysB.toSource();
        app.preferences.onlineservicesPropertyValues = onlineservices.propertyValues.toSource();
    }
    
    onlineservices.getLocation = function ()
    {
    		var location = onlineservices.getProperty("country", "user_pref");	// Do not localize.
    	
    		if (location == undefined)
    		{
    			location = onlineservices.getSupportedLocale();
    			location = location.substr(3, 2);
    		}
    	
    		return location;
    }
    
    onlineservices.initializeOLS = function ()
    {
		onlineservices.logString(0, "Enter initializeOLS");
		onlineservices.loadLib();
		
		if (onlineservices.lib != undefined)
		{
			// Try to build menus from cache if it's there
 			onlineservices.buildOLSMenus(onlineservices.lib.getServiceList()); 
 			
 			if(onlineservices.AutomaticServiceCheckingEnabled == false)
				return;
			
			// fire off an async request to get any service updates.
			onlineservices.lib.refreshServiceList();

			onlineservices.pumpOls();
		}
		onlineservices.logString(0, "Exit initializeOLS");		
    
    }
    
    onlineservices.pumpOls = function ()
    {
		if ( onlineservices.lib == undefined )
 			return;

		if(onlineservices.lib.isNewManifest())
		{
	   		onlineservices.logString(0, "pumpOls - buildOLSMenus");
 			onlineservices.buildOLSMenus(onlineservices.lib.getServiceList()); 
 		}
       
      	if ( onlineservices.lib.pumpOLS() )
        {
            onlineservices.logString(0, "pumpOls - processMessages");        
            onlineservices.processMessages();
        }
        
        if(onlineservices.lib.isOLSSessionActive())
        	onlineservices.repeatServiceTask();
	}		
	

    onlineservices.processMessages = function ()
    {
        while ( onlineservices.processMessage() )
        {
        }
    }

    
    onlineservices.processMessage = function ()
    {
        var msg = onlineservices.lib.getMessage();
		if ( typeof( msg ) == "script" )
        {
            var delay  = 1; 		// In milliseconds.
            var repeat = false;
            onlineservices.logString(0, "script = " + script);            
            app.scheduleTask( script, delay, repeat );
            return true;
        }
        else
        {
            return false;
        }        
    }
    
   
    onlineservices.repeatServiceTask = function ()
    {
        var script = 'onlineservices.pumpOls();';
        var delay  = 100; // In milliseconds.
        var repeat = false;
      	app.scheduleTask( script, delay, repeat );
    }


    onlineservices.concat_paths = function ( path1, path2 )
    {
        var separator;
        if ( onlineservices.isWin )
        {
            separator = '\\';
        }
        else // if ( onlineservices.isMac )
        {
            separator = '/';
        }
        // FIXME: Can't blindly insert a separator.
        return path1 + '\\' + path2;
    }
    
	 //---------------------------------------------------------
	// functionName - trim	- trims white space from the both ends of a string
	//
	// Description
	// arguments	- any string
	// returns		- a trimmed string
	onlineservices.trim = function( st )  
	{
		var str = new String( st );
		str = str.replace( /^\s+/ , "" );
		str = str.replace( /\s+$/ , "" );
		return str
	}
	
	onlineservices.getCharsAfter = function( str, ch )  {
		s = new String( onlineservices.trim( str ) );
		var idx = s.indexOf( ch );
		if (idx == -1 )  {
			return "";
		} else {
			return s.substr( ( idx + ch.length ) );		
		}
	}
	
    /*****************************************************************************
     * 			Service Support for filtering and accumulating Documents and
     *			transfering document references to OLS
    *****************************************************************************/
    
   /*
       Excerpted from OLSMessageExchangeConstants.h (internal):
       
        #define kOLSName_File                 "file"
        #define kOLSName_File_Id              "id"
        #define kOLSName_File_Type            "type"
        #define kOLSName_File_Name            "name"
        #define kOLSName_File_Caption         "caption"
        #define kOLSName_File_Url             "url"
        #define kOLSName_File_Size            "size"
        #define kOLSName_File_Created         "created"
        #define kOLSName_File_Modified        "modified"
        #define kOLSName_File_Version         "version"
        #define kOLSName_File_Xmp             "xmp"

        #define kOLSName_ImageInfo            "image-info"
        #define kOLSName_ImageInfo_Width      "width"
        #define kOLSName_ImageInfo_Height     "height"
        #define kOLSName_ImageInfo_Resolution "resolution"
        #define kOLSName_ImageInfo_Rotation   "rotation"

        #define kOLSName_Color                "color"
        #define kOLSName_Color_Space          "space"
        #define kOLSName_Color_BitsPerChannel "bits-per-channel"
        #define kOLSName_Color_Profile        "profile"
     */
     
	/**
	 * Create an Element (procedurally) which encapsulates all inDocuments data
	 *
	 * @param	inDocuments			reference to Documents selected
	 */
    onlineservices.includeDocuments = function ( inDocuments )
    {
        onlineservices.logString(0, "Enter includeDocumens");
           
        onlineservices.longpath = "";
		
        onlineservices.lib.begin( "file-list" );

		app.preflightFiles(inDocuments);
		
		for (i=0; i<inDocuments.length; i++)
		{
			var thumbnail = inDocuments[i];
			if ( !thumbnail.container )
				onlineservices.includeDocument( thumbnail );
		}
            
        onlineservices.lib.end();
        onlineservices.logString(0, "Exit includeDocumens");        
    }
    
	/**
	 * Package and send a document data list to the OLS library
	 *
	 * @param	inDocuments			reference to Documents selected
	 */
    onlineservices.includeDocument = function ( thumbnail )
    {
        var spec = thumbnail.spec;
		if (spec == undefined)
			return;
			
        var m = thumbnail.synchronousMetadata;
        var d;
        
        onlineservices.logString(0, "Enter includeDocumen");
        onlineservices.lib.begin( "file" );
      
			var id = onlineservices.hashString( spec.fsName ).toString( 16 );
			if ( spec.modified != undefined )
			{
				id = id + ':' + onlineservices.formatDate( spec.modified );
			}
			
			onlineservices.lib.set( "id", id ); 
			onlineservices.lib.set( "name", unescape(spec.name) );
			onlineservices.lib.set( "fullpath", spec.fsName );
			onlineservices.lib.set( "escaped-name", escape( spec.fsName ) );
			onlineservices.lib.set( "encoded-name", File.encode( spec.fsName ) );
			onlineservices.lib.set( "size", spec.length.toString() ); 
			onlineservices.lib.set( "type", thumbnail.mimeType );
			d = spec.created;
			if ( d != undefined )
			{
				onlineservices.lib.set( "created", onlineservices.formatDate( d ) );
			}
			d = spec.modified;
			if ( d != undefined )
			{
				onlineservices.lib.set( "modified", onlineservices.formatDate( d ) );
			}

			onlineservices.lib.begin( "image-info" );

				onlineservices.lib.set( "dimensions", m.FileDimensions );
				onlineservices.lib.set( "resolution", m.FileResolution );
				
				onlineservices.lib.begin( "color" );
			
					// XXX shg Bug ID 1265765- note that this xmp data is localized. Specifically in the case of
					// our service partners they are not handling the localized "space". jpeg is rarely
					// anything but RGB so we are working around the partner problem by not sending this
					// data for jpeg files.
					if(thumbnail.mimeType != "image/jpeg") 
						onlineservices.lib.set( "space", m.FileColorMode );
					onlineservices.lib.set( "bits-per-channel", m.FileBitDepth );
					onlineservices.lib.set( "profile", m.FileColorProfile );

				onlineservices.lib.end();

			onlineservices.lib.end();
			
        onlineservices.lib.end();
        if (onlineservices.longpath.length < spec.fsName.length)
        {
            onlineservices.longpath = spec.fsName;
        }
        onlineservices.logString(0, "Exit includeDocumen");
    }

	/**
	 * Preflight Documents targeted for a specific service. Ensure that all 
	 * document image mime types are appropriate.
	 *
	 * @param	inDocuments			reference to Documents selected
	 * @param	inServiceID			Service ID used to determine associated file filters.
	 */
    onlineservices.preflightSelections = function ( inDocuments, inServiceId )
    {
		onlineservices.logString(0, "Enter preflightSelections");
    	var preflightFileTypes = onlineservices.serviceFileTypes[inServiceId];
    	if(preflightFileTypes == undefined)
    	{
    		preflightFileTypes = new Array;
    		preflightFileTypes[0] = "image/jpeg";
    	}

    	var typeErrList = "";
    	var typeErrNum = 0;
		var paramErrList = "";
		var paramErrNum = 0;
    	
		for (i=0; i<inDocuments.length; i++)
		{
			var thumbnail = inDocuments[i];
			onlineservices.logString(0, thumbnail.name);
			if ( !thumbnail.container )
			{
				var supported = false;
				for(var index = 0; index < preflightFileTypes.length; index++)
				{
				 	//alert("thumbnail.mimetype = " + thumbnail.mimeType);
					if ( thumbnail.mimeType == preflightFileTypes[index])
					{
						supported = true;
						var m = thumbnail.synchronousMetadata;
						var spec = thumbnail.spec;
						
						if (((m.FileDimensions == "") || (spec.length == -1)) && 
							 (paramErrNum <= onlineservices.maxErrNum))
						{
							if (paramErrNum < onlineservices.maxErrNum)
								paramErrList += "\n" + thumbnail.name;;
							else
								paramErrList +="\n......";
							paramErrNum++;
						}
						break;
					}
				}
				if ((supported == false) && (typeErrNum <= onlineservices.maxErrNum))
				{
					if (typeErrNum < onlineservices.maxErrNum)
						typeErrList += "\n" + thumbnail.name;
					else
						typeErrList += "\n......";
					typeErrNum++;
				}
			}
		}

		var alertString = "";
		if (typeErrNum > 0)
		{		
			var formatsString = onlineservices.buildFileFormatsString(preflightFileTypes);
			alertString = onlineservices.localize("$$$/CS2/OLS/ErrorHandler/AcceptableFormat=Files selected for uploading to this service must be one of the following formats: ")+formatsString + typeErrList;
		}
		
		if (paramErrNum > 0)
		{
			if (alertString != "")
				alertString += "\n\n";
			alertString += onlineservices.localize("$$$/CS2/OLS/ErrorHandler/ImgMetadataErr=Files selected for uploading to this service do not have all required metadata:\n ") + paramErrList;
		}

		if (alertString != "")
		{
			onlineservices.logString(0, "Exit preflightSelections - false\n" + alertString);
			Window.alert(alertString);
			return false;
		}
		onlineservices.logString(0, "Exit preflightSelections - true");
		return true;
    }


	/**
	 * Used to build a string from the mime types which can be used as part of an alert
	 * indicating which file types are permissable for a service. 
	 *
	 * @param	inPreflightFileTypes	Array of mime names
	 */
	onlineservices.buildFileFormatsString = function (inPreflightFileTypes)
	{
		var supportedImagesString = '\n';
		for(var index = 0; index < inPreflightFileTypes.length; index++)
		{
			inPreflightFileTypes[index];
			supportedImagesString += onlineservices.getCharsAfter(inPreflightFileTypes[index].toUpperCase(),"/") + '\n';
		}
		return supportedImagesString;
	}
	
 

    /*****************************************************************************
	 *   		Additional utilities used in formating Document information
	 *   				prior to executing an OLS Service. 
    *****************************************************************************/
    onlineservices.twoDigits = function ( n )
    {
        if ( n < 10 )
        {
            return '0'+n;
        }
        else
        {
            return n;
        }
    }
    
    onlineservices.formatDate = function ( d )
    {
        return d.getUTCFullYear()
            + '-' + onlineservices.twoDigits( 1 + d.getUTCMonth() )
            + '-' + onlineservices.twoDigits( d.getUTCDate() )
            + '_' + onlineservices.twoDigits( d.getUTCHours() )
            + ':' + onlineservices.twoDigits( d.getUTCMinutes() )
            + ':' + onlineservices.twoDigits( d.getUTCSeconds() );
    }
    
    onlineservices.hashString = function ( str )
    {
        var result = 1;
        for ( var i = 0; i < str.length; ++i )
        {
            result = ( 10*result + str.charCodeAt( i ) ) % 0xFFFFFFFF;
        }
        return result;
    }  

   
 

    /*****************************************************************************
     * Element Utilities - data structures to facilitate data exchange using 
     * OLS Element objects. see COLSElement.cpp
     *****************************************************************************/


	/**
	 * Create a new element object with the specified name and value.  The
	 * name must be valid by OLS rules.  The value can be null or simply
	 * unspecified.  If the name is invalid, the null is returned.  Otherwise
	 * the new element object is returned.
	 *
	 * @param	inName							the name of the element object to create
	 * @param	inValue							the value of the element object to create, can be null or unspecified
	 */
	onlineservices.OLSElement_New = function ( inName, inValue )
	{
		var		name;
		var		value;
		var		element;

		// Validate the name
		if ( null == inName )
			return null;
		name = inName.toString();
//		if ( !onlineservices.sOLSElementNamePattern.test( name ) )
//			return null;
	
		// Validate the value
		if ( null != inValue )
			value = inValue.toString();
		
		// Create the element
		element = new Object;
		element.name = name;
		element.value = value;
		element.elementArray = null;
		
		return element;
	}
	
	
	/**
	 * Get the number of child element objects contained in the
	 * element's child element object array.  Validates the
	 * element object before returning.  If the element object
	 * is invalid the returns zero.  Otherwise, returns the
	 * number of child element objects in the child element object array.
	 *
	 * @param	inElement						the element object to get the number of child element objects from
	 * @return									the number of child element objects found if successful, otherwise zero
	 */
	onlineservices.OLSElement_GetChildElementCount = function ( inElement )
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return 0;
			
		if ( null == inElement.elementArray )
			return 0;
			
		return inElement.elementArray.length;
	}
	
	/**
	 * Get the child element object at the specifed index.  Validates
	 * the element object before returning.  If the element object
	 * is invalid or the index is outside of the child element object array
	 * size then null is returned.  Otherwise, the child element object
	 * found in the child element object array at the specified index is
	 * returned.
	 *
	 * @param	inElement						the element object to get the child element object from
	 * @param	inIndex							the index of the child element object to obtain
	 * @return									the child element object if found, otherwise null
	 */
	onlineservices.OLSElement_GetChildElement = function ( inElement, inIndex )
	{
		if ( !onlineservices.OLSElement_IsValid( inElement ) )
			return null;
			
		if ( null == inElement.elementArray )
			return null;
			
		if ( inElement.elementArray.length <= inIndex )
			return null;
			
		return inElement.elementArray[inIndex];
	}
	
         

   /*****************************************************************************
     * onlineservices.core
     *****************************************************************************/

    onlineservices.core = { };

    onlineservices.core.eventHandler = function ( event )
    {
        var result = { handled: false };
        var target = event.object

    //	onlineservices.dumpObj("Event: ", event);

        if (target instanceof Thumbnail)
        {
    //		return onlineservices.core.doThumbEvent(event);
        }
        else if (target instanceof Document)
        {
    //		return onlineservices.core.doDocEvent(event)
        }
        else if (target instanceof App)
        {
    //		return onlineservices.core.doAppEvent(event);
        }

        return result;
    }


    onlineservices.initialize = function ()
    {

        app.eventHandlers.push( { handler: onlineservices.core.eventHandler } );
        
        // One shot to do OLS initializations
        app.scheduleTask( 'onlineservices.initializeOLS();', onlineservices.startupDelay,false);
    }

	onlineservices.initLog();

    /*****************************************************************************
     * Code to execute at the time this script is loaded.
     *****************************************************************************/
 	// get menu cache and build menu 
    onlineservices.buildOLSMenus(onlineservices.getMenuCache());
 	

    onlineservices.initialize();

	    
} // Endif ( BridgeTalk.appName == "bridge" )
else
{
	// ***************
	// Point App APIs
	// ***************

};

/*****************************************************************************
 * End
 *****************************************************************************/
