Common CustomDataSourceCommon_CustomDataSource_CSharp\CustomDataSource_CSharp\REXMLDataSource_CSharp\QueryFunctionality.cs
// Copyright 2007 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 System.Data;
using System.Web.UI;
using ESRI.ArcGIS.ADF.Web.Geometry;
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web.Display.Graphics;
using System.Collections;
using ESRI.ArcGIS.ADF.Web;
namespace REXMLDataSource_CSharp
{
public class QueryFunctionality : IQueryFunctionality
{
public QueryFunctionality(string name, MapResource resource)
{
this.name = name;
this.resource = resource;
}
private GraphicsDataSet GetGraphicsDataSet(string mapFunctionalityName)
{
MapResource mapResource = resource as MapResource;
if (mapResource == null)
return null;
if (mapFunctionalityName == null)
{
return mapResource.Graphics;
}
else
{
MapFunctionality mapFunctionality = mapResource.Functionalities.Find(mapFunctionalityName) as MapFunctionality;
return mapFunctionality == null ? null : mapFunctionality.GraphicsDataSet;
}
}
private GraphicsLayer GetGraphicsLayer(string mapFunctionalityName, string layerID)
{
GraphicsDataSet gds = GetGraphicsDataSet(mapFunctionalityName);
if (gds == null)
return null;
string tableName = layerID;
if (tableName == null)
return null;
return gds.Tables[tableName] as GraphicsLayer;
}
#region IQueryFunctionality implementation
public DataTable[] Find(string mapFunctionalityName, FindParameters findParameters)
{
List<DataTable> datatables = new List<DataTable>();
GraphicsDataSet graphicsDataSet = GetGraphicsDataSet(mapFunctionalityName);
if (graphicsDataSet == null) return null;
QueryFilter filter = new QueryFilter();
filter.MaxRecords = findParameters.MaxRecords;
filter.ReturnADFGeometries = findParameters.ReturnADFGeometries;
IDictionaryEnumerator en = findParameters.LayersAndFields.GetEnumerator();
while (en.MoveNext())
{
string layerID = en.Key as string;
string[] searchFields = en.Value as string[];
// Build where clause
StringBuilder whereExpression = new StringBuilder();
for (int i = 0; i < searchFields.Length; i++)
{
if (findParameters.UseSqlContains)
{
// todo: change to use SQL CONTAINS statement
whereExpression.Append(String.Format("{0} like '%{1}%'", searchFields[i], findParameters.FindString));
}
else
{
whereExpression.Append(String.Format("{0} like '%{1}%'", searchFields[i], findParameters.FindString));
}
if (i != searchFields.Length - 1) whereExpression.Append(" OR ");
}
filter.WhereClause = whereExpression.ToString();
GraphicsLayer glayer = graphicsDataSet.Tables[layerID] as GraphicsLayer;
if (glayer != null)
{
if (findParameters.FindOption != FindOption.VisibleLayers || (findParameters.FindOption == FindOption.VisibleLayers && glayer.Visible == true))
{
datatables.Add(Query(mapFunctionalityName, glayer.TableName, filter));
}
}
}
return datatables.ToArray();
}
public DataTable[] Identify(string mapFunctionalityName, Geometry geometry, int tolerance, IdentifyOption option, string[] layers)
{
List<DataTable> datatables = new List<DataTable>();
GraphicsDataSet graphicsDataSource = GetGraphicsDataSet(mapFunctionalityName);
if (graphicsDataSource == null)
return null;
SpatialFilter sf = new SpatialFilter();
sf.SearchOrder = SearchOrder.Spatial;
if (geometry is Point)
{
Point point = geometry as Point;
MapResource mr = Resource as MapResource;
sf.Geometry = point.Expand(tolerance, graphicsDataSource.FullExtent);
}
else
{
throw new NotSupportedException("GraphicsLayer only supports Points in the Identify method.");
}
if (layers == null)
{
foreach (GraphicsLayer glb in graphicsDataSource.Tables)
{
datatables.Add(Query(mapFunctionalityName, glb.TableName, sf));
}
}
else
{
foreach (string o in layers)
{
datatables.Add(Query(mapFunctionalityName, o, sf));
}
}
return datatables.ToArray();
}
public DataTable Query(string mapFunctionalityName, string layerID, QueryFilter queryFilter)
{
GraphicsLayer glayer = GetGraphicsLayer(mapFunctionalityName, layerID);
if (glayer == null)
return null;
#region Create Table
DataTable dataTable = null;
List<DataColumn> columns = new List<DataColumn>();
foreach (DataColumn col in glayer.Columns)
{
if (queryFilter.SubFields.Count == 0 || queryFilter.SubFields.IndexOf(col.ColumnName) != -1)
columns.Add(CloneColumn(col));
else if (queryFilter.ReturnADFGeometries && (col.DataType == typeof(GraphicElement) || col.DataType == typeof(Geometry)))
columns.Add(CloneColumn(col));
}
if (queryFilter.ReturnADFGeometries)
{
if (glayer is FeatureGraphicsLayer)
{
FeatureGraphicsLayer flayer = glayer as FeatureGraphicsLayer;
dataTable = new FeatureGraphicsLayer(flayer.TableName, columns.ToArray(), flayer.GeometryColumnName,
flayer.GraphicsIDColumn.ColumnName, flayer.FeatureType);
}
else
{
ElementGraphicsLayer elayer = glayer as ElementGraphicsLayer;
dataTable = new ElementGraphicsLayer(elayer.TableName, columns.ToArray(), elayer.GraphicsColumn.ColumnName,
elayer.GraphicsIDColumn.ColumnName);
}
}
if (dataTable == null)
{
dataTable = new DataTable(glayer.TableName);
dataTable.Columns.AddRange(columns.ToArray());
}
#endregion
// Do query
if (queryFilter is SpatialFilter)
{
SpatialFilter sf = queryFilter as SpatialFilter;
if (sf.SearchOrder == SearchOrder.Spatial)
{
InitialSpatialQuery(glayer, dataTable, sf);
AttributeQueryOnSpatialResults(dataTable, queryFilter);
}
else
{
List<Geometry> geometries = InitialAttributeQuery(glayer, dataTable, queryFilter);
SpatialQueryOnAttributeResults(dataTable, sf, geometries);
}
}
else
{
InitialAttributeQuery(glayer, dataTable, queryFilter);
}
if (dataTable.Rows.Count > queryFilter.MaxRecords && queryFilter.MaxRecords > 0)
{
while (dataTable.Rows.Count > queryFilter.MaxRecords)
dataTable.Rows.RemoveAt(dataTable.Rows.Count - 1);
}
return dataTable;
}
private List<Geometry> InitialAttributeQuery(GraphicsLayer glayer, DataTable resultsDataTable, QueryFilter queryFilter)
{
List<Geometry> geometries = new List<Geometry>();
DataRow[] rows = glayer.Select(queryFilter.WhereClause);
foreach (DataRow row in rows)
{
resultsDataTable.ImportRow(row);
geometries.Add(glayer.GeometryFromRow(row));
}
return geometries;
}
private void InitialSpatialQuery(GraphicsLayer glayer, DataTable resultsDataTable, SpatialFilter sf)
{
foreach (DataRow row in glayer.Rows)
{
Geometry geometry = glayer.GeometryFromRow(row);
// To implemement, evaluate feature geometry and spatial filter geometry
// if (geometry != null && GeometriesIntersect(geometry, sf.Geometry))
if (geometry != null)
{
resultsDataTable.ImportRow(row);
}
}
}
private void AttributeQueryOnSpatialResults(DataTable dataTable, QueryFilter queryFilter)
{
if (queryFilter.WhereClause == "")
return;
DataRow[] rows = dataTable.Select(queryFilter.WhereClause);
foreach (DataRow row in dataTable.Rows)
{
if (Array.IndexOf(rows, row) == -1)
dataTable.Rows.Remove(row);
}
}
private void SpatialQueryOnAttributeResults(DataTable dataTable, SpatialFilter sf, List<Geometry> geometries)
{
if (geometries == null || geometries.Count == 0)
return;
for (int i = 0, j = 0; i < dataTable.Rows.Count; ++i, ++j)
{
// To implement, evaluate if feature geometry intersects spatial filter geometry
/*if (!GeometriesIntersect(geometries[j], sf.Geometry))
{
dataTable.Rows.Remove(dataTable.Rows[i]);
--i;
}*/
}
}
public void GetQueryableLayers(string mapFunctionalityName, out string[] layerIDs, out string[] layerNames, FeatureType featureType)
{
layerIDs = null;
layerNames = null;
List<DataTable> tables = new List<DataTable>();
GraphicsDataSet gds = GetGraphicsDataSet(mapFunctionalityName);
if (gds == null)
return;
foreach (GraphicsLayer glayer in gds.Tables)
{
FeatureGraphicsLayer gl = glayer as FeatureGraphicsLayer;
if (gl != null && gl.FeatureType != featureType)
continue;
tables.Add(glayer);
}
layerIDs = new string[tables.Count];
layerNames = new string[tables.Count];
for (int i = 0; i < tables.Count; ++i)
{
layerIDs[i] = tables[i].TableName;
layerNames[i] = tables[i].TableName;
}
}
public void GetQueryableLayers(string mapFunctionalityName, out string[] layerIDs, out string[] layerNames)
{
layerIDs = null;
layerNames = null;
GraphicsDataSet gds = GetGraphicsDataSet(mapFunctionalityName);
if (gds == null)
return;
layerIDs = new string[gds.Tables.Count];
layerNames = new string[gds.Tables.Count];
for (int i = 0; i < gds.Tables.Count; ++i)
{
layerIDs[i] = gds.Tables[i].TableName;
layerNames[i] = gds.Tables[i].TableName;
}
}
public string[] GetFields(string mapFunctionalityName, string layerID)
{
GraphicsLayer glayer = GetGraphicsLayer(mapFunctionalityName, layerID);
if (glayer == null)
return null;
string[] fields = new string[glayer.Columns.Count];
for (int i = 0; i < glayer.Columns.Count; ++i)
{
fields[i] = glayer.Columns[i].ColumnName;
}
return fields;
}
public string[] GetFields(string mapFunctionalityName, string layerID, out Type[] fieldTypes)
{
GraphicsLayer glayer = GetGraphicsLayer(mapFunctionalityName, layerID);
if (glayer == null)
{
fieldTypes = null;
return null;
}
string[] fields = new string[glayer.Columns.Count];
fieldTypes = new Type[glayer.Columns.Count];
for (int i = 0; i < glayer.Columns.Count; ++i)
{
fields[i] = glayer.Columns[i].ColumnName;
fieldTypes[i] = glayer.Columns[i].DataType;
}
return fields;
}
#endregion
#region IGISFunctionality implementation
private string name = string.Empty;
private IGISResource resource = null;
[NonSerialized]
System.Web.UI.WebControls.WebControl _webControl;
public System.Web.UI.WebControls.WebControl WebControl
{
get { return _webControl; }
set { _webControl = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public IGISResource Resource
{
get { return resource; }
set { resource = value; }
}
bool _initialized = false;
public bool Initialized
{
get { return _initialized; }
}
public void LoadState() { }
public void Initialize() { _initialized = true; }
public void SaveState() { }
public void Dispose() { _initialized = false; }
public bool Supports(string operation)
{
return true;
}
#endregion
public static DataColumn CloneColumn(DataColumn toClone)
{
DataColumn column1 = (DataColumn)Activator.CreateInstance(toClone.GetType());
column1.AllowDBNull = toClone.AllowDBNull;
column1.AutoIncrement = toClone.AutoIncrement;
column1.AutoIncrementStep = toClone.AutoIncrementStep;
column1.AutoIncrementSeed = toClone.AutoIncrementSeed;
column1.Caption = toClone.Caption;
column1.ColumnName = toClone.ColumnName;
column1.DataType = toClone.DataType;
column1.DefaultValue = toClone.DefaultValue;
column1.ColumnMapping = toClone.ColumnMapping;
column1.ReadOnly = toClone.ReadOnly;
column1.MaxLength = toClone.MaxLength;
column1.DateTimeMode = toClone.DateTimeMode;
column1.Namespace = toClone.Namespace;
column1.Prefix = toClone.Prefix;
column1.Unique = toClone.Unique;
if (toClone.ExtendedProperties != null)
{
foreach (object obj1 in toClone.ExtendedProperties.Keys)
{
column1.ExtendedProperties[obj1] = toClone.ExtendedProperties[obj1];
}
}
return column1;
}
}
}