Common Custom EditorTask
Common_CustomEditorTask_CSharp\CustomEditorTask_CSharp\CustomUtilities.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.
// 

namespace CustomEditorTask_CSharp
{
    internal class CustomUtilities
    {
        // Get layer definition for layer currently being edited
        internal static ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerDefinition GetLayerDefinition(
            ESRI.ArcGIS.ADF.ArcGISServer.Editor.Editor editor)
        {
            ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem = 
                editor.Map.MapResourceManagerInstance.ResourceItems.Find(editor.MapResource.Name);

            return mapResourceItem.GetUpdatedLayerDefinition(editor.SelectedLayerID.ToString());
        }

        // Overload to allow function call with CustomEditor
        internal static ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerDefinition GetLayerDefinition(CustomEditor customEditor)
        {
            return GetLayerDefinition((ESRI.ArcGIS.ADF.ArcGISServer.Editor.Editor)customEditor);
        }

        // Get list of fields for currently selected layer
        internal static string GetFields(CustomEditor customEditor)
        {
            string fields = "";
            for (int i = 0; i < customEditor.CurrentLayerDefinition.LayerFormat.Fields.Count; i++)
            {
                if (customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Visible)
                {
                    if (customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Alias.Length > 0)
                    {
                        fields += customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Alias + ":::";
                    }
                    else
                    {
                        fields += customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Name + ":::";
                    }
                }
            }
            fields = fields.Substring(0, fields.Length - 3);
            return fields;
        }

        // Get list of fields for currently selected layer
        internal static string GetFields(CustomEditor customEditor, FieldType fieldType)
        {
            string fields = "";
            for (int i = 0; i < customEditor.CurrentLayerDefinition.LayerFormat.Fields.Count; i++)
            {
                ESRI.ArcGIS.ADF.Web.DataSources.FieldInfo fieldInfo =
                    customEditor.CurrentLayerDefinition.LayerFormat.Fields[i];

                if (customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Visible)
                {
                    if ((fieldType == FieldType.Numeric) && (fieldInfo.Type.ToLower() != "double") &&
                    (fieldInfo.Type.ToLower() != "int") && (fieldInfo.Type.ToLower() != "long") &&
                    (fieldInfo.Type.ToLower() != "int32") && (fieldInfo.Type.ToLower() != "int16") &&
                    (fieldInfo.Type.ToLower() != "int64") && (fieldInfo.Type.ToLower() != "short") &&
                    (fieldInfo.Type.ToLower() != "byte") && (fieldInfo.Type.ToLower() != "float") &&
                    (fieldInfo.Type.ToLower() != "single"))
                    {
                        continue;
                    }
                    else if ((fieldType == FieldType.Text) && (fieldInfo.Type.ToLower() != "string") &&
                    (fieldInfo.Type.ToLower() != "char"))
                    {
                        continue;
                    }

                    if (customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Alias.Length > 0)
                    {
                        fields += customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Alias + ":::";
                    }
                    else
                    {
                        fields += customEditor.CurrentLayerDefinition.LayerFormat.Fields[i].Name + ":::";
                    }
                }
            }
           if (fields.Length > 0) 
               fields = fields.Substring(0, fields.Length - 3);
            return fields;
        }

        // Get sample values for passed-in field
        internal static string GetSampleValues(string fieldAlias, ESRI.ArcGIS.ADF.ArcGISServer.Editor.Editor editor)
        {
            // Get database field name for passed-in alias
            string fieldName = CustomUtilities.GetFieldName(fieldAlias, (CustomEditor)editor);

            // Make sure field name was found
            if (fieldName == null)
                return null;

            // Make sure querying is supported for the current map resource
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal agsMapResourceLocal = editor.MapResource;
            bool querySupported = agsMapResourceLocal.SupportsFunctionality(
                typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));
            if (!querySupported)
                return null;

            // Create query functionality and query filter
            ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality =
                (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)agsMapResourceLocal.CreateFunctionality(
                typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), "query");
            ESRI.ArcGIS.ADF.Web.QueryFilter adfQueryFilter = new ESRI.ArcGIS.ADF.Web.QueryFilter();
            adfQueryFilter.ReturnADFGeometries = false;
            CustomEditorTask customEditorTask = (CustomEditorTask)editor.EditorTask;
            adfQueryFilter.MaxRecords = customEditorTask.SampleValueLimit;
            adfQueryFilter.SubFields = new ESRI.ArcGIS.ADF.StringCollection(fieldName, char.Parse(","));

            // Execute query
            System.Data.DataTable resultsDataTable = queryFunctionality.Query(editor.MapFunctionality.Name,
                editor.SelectedLayerID.ToString(), adfQueryFilter);

            // Make sure results were returned
            if (resultsDataTable == null)
                return null;

            // Retrieve results from table and format into results string
            string results = ":::";

            // Replace periods in field name if necessary
            if (fieldName != resultsDataTable.Columns[0].ColumnName)
                fieldName = fieldName.Replace(".", "_");
            
            for (int i = 0; i < resultsDataTable.Rows.Count; i++)
            {
                // Get field value from current row
                string result = resultsDataTable.Rows[i][fieldName].ToString();
                // Make sure value is not already in results string and is not empty
                if ((results.IndexOf(System.String.Format(":::{0}:::", result)) < 0) && (result != "")
                && (result != " ") && (result != "NaN") && (result != null))
                    results += System.String.Format("{0}:::", resultsDataTable.Rows[i][fieldName].ToString());
            }
            if (results.Length > 5)
                results = results.Substring(3, results.Length - 6);

            return results;
        }

        // Get actual database field name for passed-in alias
        internal static string GetFieldName(string fieldAlias, CustomEditor editor)
        {
            //find field name based on alias
            string fieldName = null;
            for (int i = 0; i < editor.CurrentLayerDefinition.LayerFormat.Fields.Count; i++)
            {
                if (editor.CurrentLayerDefinition.LayerFormat.Fields[i].Alias == fieldAlias)
                {
                    fieldName = editor.CurrentLayerDefinition.LayerFormat.Fields[i].Name;
                    break;
                }
            }

            // If no matching alias was found, check whether passed-in alias
            // matches an actual database field name
            for (int i = 0; i < editor.CurrentLayerDefinition.LayerFormat.Fields.Count; i++)
            {
                if (editor.CurrentLayerDefinition.LayerFormat.Fields[i].Name == fieldAlias)
                {
                    fieldName = editor.CurrentLayerDefinition.LayerFormat.Fields[i].Name;
                    break;
                }
            }

            return fieldName;
        }

        // Replace field aliases in passed-in string with corresponding actual database field names
        public static string ReplaceAliases(string fieldAliasesString, CustomEditor customEditor)
        {
            string[] fieldAliasesArray = fieldAliasesString.Split(';');
            string fieldNamesString = "";
            for (int i = 0; i < fieldAliasesArray.Length; i++)
            {
                fieldNamesString += CustomUtilities.GetFieldName(fieldAliasesArray[i], customEditor);
                if (i < fieldAliasesArray.Length - 1)
                    fieldNamesString += ";";
            }

            return fieldNamesString;
        }

        // Execute query and return feature ids from results
        public static int[] DoQuery(string query, ESRI.ArcGIS.ADF.ArcGISServer.Editor.Editor editor)
        {
            ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal agsMapResourceLocal = editor.MapResource;

            // Make sure querying is supported for the current map resource
            bool querySupported = agsMapResourceLocal.SupportsFunctionality(
                typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));

            if (!querySupported)
                return new int[0];

            // Create query functionality and query filter
            ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality =
                (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)agsMapResourceLocal.CreateFunctionality(
                typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), "query");
            ESRI.ArcGIS.ADF.Web.QueryFilter adfQueryFilter = new ESRI.ArcGIS.ADF.Web.QueryFilter();
            adfQueryFilter.ReturnADFGeometries = false;
            adfQueryFilter.MaxRecords = editor.EditorTask.SelectionLimit;
            adfQueryFilter.WhereClause = query;

            // Execute query
            System.Data.DataTable dtResults = queryFunctionality.Query(editor.MapFunctionality.Name,
                editor.SelectedLayerID.ToString(), adfQueryFilter);

            // Make sure results were returned
            if (dtResults == null)
                return new int[0];

            // copy object IDs of results to array
            int[] idSet = new int[dtResults.Rows.Count];
            for (int i = 0; i < dtResults.Rows.Count; i++)
            {
                idSet[i] = (int)dtResults.Rows[i][editor.FeatureLayer.FeatureClass.OIDFieldName];
            }

            return idSet;
        }

        // Update the passed-in selection based on the selection mode
        internal static System.Collections.Generic.List<int> UpdateSelection(int[] currentSelection, int[] newSelection, 
            out bool selectionChanged, ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorTask editorTask)
        {
            System.Collections.Generic.List<int> selectedIDsList = new System.Collections.Generic.List<int>();
            selectionChanged = false;

            // Get the selection limit
            int selectionLimit = editorTask.SelectionLimit;

            switch (editorTask.FeatureSelectionMode)
            {
                case ESRI.ArcGIS.ADF.ArcGISServer.Editor.FeatureSelectionMode.CreateNew :
                    // Add IDs of newly selected features to selection list
                    if (newSelection.Length > 0)
                    {
                        if (newSelection.Length > selectionLimit)
                            System.Array.Resize(ref newSelection, selectionLimit);
                        selectedIDsList.AddRange(newSelection);
                        selectionChanged = true;
                    }
                    else
                    {
                        if (currentSelection != null && currentSelection.Length > 0)
                            selectionChanged = true;
                    }
                    break;

                case ESRI.ArcGIS.ADF.ArcGISServer.Editor.FeatureSelectionMode.Add:
                    // Add IDs of currently selected features to selection list
                    if (currentSelection != null)
                        selectedIDsList.AddRange(currentSelection);
                    
                    // Resize list of newly selected ids to be within selection limit
                    if (newSelection.Length > selectionLimit)
                        System.Array.Resize(ref newSelection, selectionLimit);

                    int numAdded = 0;
                    
                    // Add newly selected IDs to current IDs
                    foreach (int i in newSelection)
                    {
                        if (!selectedIDsList.Contains(i))
                        {
                            selectedIDsList.Add(i);
                            if (++numAdded == selectionLimit)
                                break;
                        }
                    }
                    // Set selection changed flag based on whether any IDs were added to selection
                    selectionChanged = numAdded > 0;
                    break;

                case ESRI.ArcGIS.ADF.ArcGISServer.Editor.FeatureSelectionMode.Remove:
                    // Add all currently selected IDs to selection
                    if (currentSelection != null)
                        selectedIDsList.AddRange(currentSelection);
                    
                    // Compare newly selected IDs to selection (currently selected IDs)
                    // and remove any newsly selected IDs already selected
                    foreach (int i in newSelection)
                    {
                        if (selectedIDsList.Contains(i))
                        {
                            selectedIDsList.Remove(i);
                            selectionChanged = true;
                        }
                    }
                    break;

                case ESRI.ArcGIS.ADF.ArcGISServer.Editor.FeatureSelectionMode.Toggle:
                    // Exit if no new features selected
                    if (newSelection.Length == 0)
                        break;

                    selectionChanged = true;
                    // Set featuresToAddCount to number of newly selected features or selection limit 
                    // depending on whether number of newly selected features exceeds limit
                    int featuresToAddCount = selectionLimit < newSelection.Length ? selectionLimit : newSelection.Length;

                    // Add IDs of currently selected features to selection
                    if (currentSelection != null)
                        selectedIDsList.AddRange(currentSelection);

                    // Check to see whether each newly selected feature is already selected.
                    // If so, remove it from selection.  if not, add it to selection.
                    for (int i = 0; i < featuresToAddCount; ++i)
                    {
                        int currentID = newSelection[i];
                        int index = selectedIDsList.IndexOf(currentID);
                        if (index == -1)
                            selectedIDsList.Add(currentID);
                        else
                            selectedIDsList.RemoveAt(index);
                    }
                    break;
            }

            return selectedIDsList;
        }

        internal static System.Web.UI.Control FindControl(string controlID, System.Web.UI.Control parentControl)
        {
            if (parentControl.ID == controlID)
                return parentControl;

            if (parentControl.Controls != null)
            {
                foreach (System.Web.UI.Control childControl in parentControl.Controls)
                {
                    System.Web.UI.Control foundControl = FindControl(controlID, childControl);
                    if (foundControl != null)
                        return foundControl;
                }
            }

            return null;
        }

        internal enum FieldType { All, Text, Numeric }
    }
}