Common Custom data source
Common_CustomDataSource_CSharp\TiledMapDataSource_CSharp\TileFunctionality.cs
// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 


using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web;

namespace TiledMapDataSource_CSharp
{
    public class TileFunctionality : ITileFunctionality, IRequiresJavaScriptRegistration
    {

        private string serviceUrl = null;
        private string urlGeneratorJSFunction = null;
        private string vdir;

        bool firstInitialization = true;

        TileCacheInfo tileCacheInfo;
        TileAccessInfo tileAccessInfo;

        string tileAccessInfoKey;

        private string name = string.Empty;
        IGISResource resource = null;
        System.Web.UI.WebControls.WebControl _webControl;
        bool _initialized = false;

        private ScriptTag scriptTag;


        public TileFunctionality(string name, MapResource resource, TileCacheInfo tci)
        {
            this.name = name;
            this.resource = resource;
            this.tileCacheInfo = tci;

        }

        public MapResource MapResource
        {
            get { return resource as MapResource; }
        }

        #region ITileFunctionality Members
        public string UrlGeneratorJSFunction
        {
            get { return urlGeneratorJSFunction; }
        }

        public string ServiceUrl
        {
            get { return serviceUrl; }
        }

        public WebImageFormat ImageFormat
        {
            get
            {
                if (tileAccessInfo != null)
                    return tileAccessInfo.WebImageFormat;
                else
                    throw new Exception(ResourceUtility.GetResourceString("TileFunctionalityExceptionFunctionalityNotInitialized"));
            }
        }

        public ESRI.ArcGIS.ADF.Web.MapImage Draw(string mapFunctionalityName, long column, long row, int level)
        {
            return Draw(column, row, level, ref tileAccessInfo);
        }

        internal static ESRI.ArcGIS.ADF.Web.MapImage Draw(long column, long row, int level,
            ref TileAccessInfo tileInfo)
        {
            ESRI.ArcGIS.ADF.Web.MapImage mapImage = null;
            return mapImage;
        }

        #endregion

        #region Private properties and fields

        private string key
        {
            get
            {
                return string.Format("{0}:{1}", MapResource.key, name);
            }
        }


        #endregion

        #region IGISFunctionality Members

        public System.Web.UI.WebControls.WebControl WebControl
        {
            get { return _webControl; }
            set { _webControl = value; }
        }

        public string Name
        {
            get
            {
                return this.name;
            }
            set
            {
                this.name = value;
            }
        }

        public IGISResource Resource
        {
            get
            {
                return this.resource;
            }
            set
            {
                this.resource = value;
            }
        }

        public bool Initialized
        {
            get { return _initialized; }
        }

        public void LoadState()
        {
            if (resource == null || resource.DataSource == null || resource.DataSource.State == null)
            {
                throw new Exception(ResourceUtility.GetResourceString("MapFunctionalityExceptionResourceAssociatedWithFunctionIsNotValid"));
            }

            // Load previous state if it was saved before.
            object o = resource.DataSource.State[key];
            if (o != null)
            {
                TileFunctionality tf = o as TileFunctionality;
                serviceUrl = tf.serviceUrl;
                urlGeneratorJSFunction = tf.urlGeneratorJSFunction;
                vdir = tf.vdir;

                firstInitialization = false;

                tileAccessInfo = tf.tileAccessInfo;
                tileAccessInfoKey = tf.tileAccessInfoKey;

                scriptTag = tf.scriptTag;
            }
        }

        /// <summary>Initializes the functionality to prepare it for use.</summary>
        public void Initialize()
        {
            bool javaScriptPossible = WebControl != null && WebControl.Page != null;
            if (firstInitialization)
            {
                #region Get Image Format Information
                System.Drawing.Imaging.ImageFormat systemImageFormat;
                WebImageFormat webImageFormat;
                string imageFormatExtension;
                setImageFormatVars(out webImageFormat, out systemImageFormat, out imageFormatExtension);

                //Populate in tile access information
                tileAccessInfo = new TileAccessInfo();
                tileAccessInfo.ImageFormat = systemImageFormat;
                tileAccessInfo.ImageFormatExtension = imageFormatExtension;
                tileAccessInfo.CacheTileFormat = tileCacheInfo == null ? string.Empty : tileCacheInfo.CacheTileFormat;
                tileAccessInfo.WebImageFormat = webImageFormat;
                #endregion

                #region Figure out how to access tiles
                #region Get Service Url/VDir
                if (vdir == null)
                {
                    try
                    {
                        vdir = tileCacheInfo.Url;
                        if (vdir == null)
                            vdir = string.Empty;
                    }
                    catch
                    {
                        vdir = string.Empty;
                    }
                }
                #endregion

                tileAccessMethod tileAccess = tileAccessMethod.JavascriptAccessVirtualDirectory;

                #endregion

                #region Tile access information                
                tileAccessInfo.TileAccess = tileAccess;
                tileAccessInfo.VirtualDirectory = vdir;
                #endregion

                #region Store tile access information in session
                tileAccessInfoKey = Guid.NewGuid().ToString("N");
                System.Web.SessionState.HttpSessionState session = null;
                try
                {
                    System.Web.HttpContext httpContext = System.Web.HttpContext.Current;
                    if (httpContext != null)
                        session = httpContext.Session;
                }
                catch { }
                if (session != null)
                    session[tileAccessInfoKey] = tileAccessInfo;
                #endregion

            }

            #region Set up javascript tile access if necessary
            if (javaScriptPossible)
            {
                if (tileAccessInfo.TileAccess == tileAccessMethod.JavascriptAccessVirtualDirectory)
                {
                    #region
                    //Function used by an ADF JavaScript tile layer to determine tile urls
                    // Tile layer created for you in Map_Rendering.cs-ResourceToJS.  
                    serviceUrl = vdir;
                    urlGeneratorJSFunction = string.Format("tiledMapVirtualDirectoryTileUrlGenerator_{0}", tileAccessInfo.ImageFormatExtension);
                    string builder = string.Format(@"
                            function pad(toPad, padding, totalLength, padLeft)
                            {{
                                if (toPad.length < totalLength){{
                                    if (padLeft) toPad = padding + toPad;
                                else toPad = toPad + padding;
                                }}
                                if (toPad.length >= totalLength) return toPad;
                                return pad(toPad, padding, totalLength, padLeft);
                            }}

                            function {0}(level, column, row, vdir)
                            {{
                                var sLevel = 'L' + pad(level.toString(), '0', 2, true);
                                var sRow = 'R' + pad(row.toString(16), '0', 8, true);
                                var sColumn = 'C' + pad(column.toString(16), '0', 8, true) + '.{1}';
                                return vdir + '/' + sLevel + '/' + sRow + '/' + sColumn;
                            }}", 
                              urlGeneratorJSFunction,
                              tileAccessInfo.ImageFormatExtension); 
                                
                    scriptTag = new ScriptTag(urlGeneratorJSFunction, "javascript", null, builder, null, null, null);

                    #endregion
                }

            }
            #endregion

            _initialized = true;
        }

        /// <summary>Saves the state of the functionality, typically for use between requests.</summary>
        public void SaveState()
        {
            resource.DataSource.State[key] = this;
        }

        /// <summary>Disposes of the functionality.</summary>
        public void Dispose()
        {
            _initialized = false;
        }

        /// <summary>
        /// Determines if the functionality supports an operation.
        /// </summary>
        /// <param name="operation">Operations are members (methods, properties) on the functionality class.</param>
        public bool Supports(string operation)
        {
            return true;
        }

        #endregion


        #region Private Methods
        private MapFunctionality GetMapFunctionality(string name)
        {
            MapFunctionality mapFunctionality = resource.Functionalities.Find(name) as MapFunctionality;
            return mapFunctionality;
        }

        void setImageFormatVars(out WebImageFormat webImageFormat, out System.Drawing.Imaging.ImageFormat systemImageFormat,
            out string imageFormatExtension)
        {
            #region figure out web image format
            webImageFormat = WebImageFormat.PNG8;
            try
            {
                switch (tileCacheInfo.CacheTileFormat)
                {
                    case "PNG8":
                        webImageFormat = WebImageFormat.PNG8;
                        break;
                    case "PNG24":
                        webImageFormat = WebImageFormat.PNG24;
                        break;
                    case "PNG32":
                        webImageFormat = WebImageFormat.PNG32;
                        break;
                    case "JPEG":
                        webImageFormat = WebImageFormat.JPG;
                        break;
                }
            }
            catch (Exception ex)
            {
                string test = ex.Message;
            }

            if (string.IsNullOrEmpty(tileCacheInfo.CacheTileFormat))
                webImageFormat = Converter.ToWebImageFormat(MapResource.DisplaySettings.ImageDescriptor.ImageFormat);
            #endregion

            systemImageFormat = Converter.ToMicrosoftImageFormat(webImageFormat);
            imageFormatExtension = Converter.ExtensionFromWebImageFormat(webImageFormat);
        }

        #endregion


        #region IRequiresJavaScriptRegistration Members

        public ScriptTag ScriptTag
        {
            get { return scriptTag; }
        }
        #endregion

    }
}