Imports Microsoft.VisualBasic
Imports System.IO
Imports System.IO.File
Imports System.Data
Imports System.Data.SqlClient

Imports ESRI.ArcGIS.ADF.Web
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools
Imports ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer
Imports ESRI.ArcGIS.ADF.Web.DataSources
Imports ESRI.ArcGIS.ADF.ArcGISServer
Imports ESRI.ArcGIS.Server

Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geometry

Imports ICSharpCode.SharpZipLib.Zip
Imports ApWSCommon.ApWSCommon
Public Class ApSConfigAHS
  Inherits ApWSCommon.ApWSCommon.ApSConfig
  Public Shared AppName As String = "HISWEB"  '..Application name, set at Pag_Load.
  Public Const K_MAPSERVICE_NAME As String = "MapServiceName"
  Public Const ResourceIdx As Integer = 0

  Public Const CB_Control_Type_HIS As String = "CUAHSI"
  Public Const CB_ControlType As String = "ControlType"
  Public Const CB_EventArg As String = "EventArg"
  Public Const CB_EventVal As String = "EventVal"
  Public Const CB_ActiveLayer As String = "ActiveLayer"
  Public Const CB_CBGeneralServerProc As String = "HandleResponse"
  Public Const CB_CB2Server As String = "CB2Server"
  Public Const CB_CallAGSP As String = "CallAGSP"
  Public Const CB_CBShowMsg As String = "ShowMsg"
  Public Const CB_CBDoEval As String = "DOEVAL"
  Public Const CB_CBShowConfirm As String = "Confirm"
  Public Const CB_CBShowConfirmEnd As String = "EOCSign"
  Public Const CB_LastExt As String = "LastExtent"

  'Session variables
  Public Const KS_ACTIVENETWORK As String = "ActiveNetwork"
  Public Const KS_ACTIVELAYER As String = "ActiveLayerIndex"
  Public Const SELECTED_STATIONS_CURRENT_MAP_EXTENT As String = "Map1_Selected_CurrentExtent"
  Public Const CURRENT_MAP_EXTENT As String = "Map1_CurrentExtent"
  Public Const KS_SELECTED_CURRENTEXT As String = "Map1_SelectedExtent"
  Public Const KS_SELECTED_CURRENTEXT_SAVED As String = "Map1_SelectedExtent_Saved"
  Public Const SELECTED_STATION_LIST_SUBSET As String = "Map1_SelectedStationListSubset"
  Public Const KS_HOSTNAME As String = "Host_Name"
  Public Const KS_NEW As String = "New"
  Public Const KS_UPDATE As String = "Update"
  Public Const KS_SITEINFO As String = "siteInfo"
  Public Const KS_TIMESERIES As String = "timeSeries"
  Public Const KS_CSV As String = "csv"
  Public Const KS_IMAGE As String = "chart"
  '..Note: KS_SELECTED:htSelected holds hte oids of current and last selections (Keyed on LayerName&"_C", and LayerName&"_L")
  '   while KS_SiteCodes only holds the SiteCodes String of the current selection.
  Public Const KS_Selected As String = "KS_SELECTED"     '..HashTable, keyed on LayerName&"_L" for last selected, LayerName&"_C" for current selected, values are int() OIDs
  Public Const KS_SiteCodes As String = "KS_SiteCodes"   '..hashtable holding  key=LayerName,value=StringOfSiteCode=11161900|11162000|11162620|11162630|11162800|11162900
  Public Const KS_LastSiteCodes As String = "LastSiteCodes"   '..Holds the last sitecodes used to select the stations with Variable. informs of '11161900','11162000','11162620' 
  Public Const KS_C As String = "_C"   '..CurrentSelected, value=int() OIDs
  Public Const KS_L As String = "_L"   '..LastSelected, value=int() OIDs
  Public Const KS_NL As String = "Z6834"  '..NewLine combination.

  Public Const K_TagError As String = "<error>"
  Public Const K_TagErrorEnd As String = "</error>"
  Public Const K_TagInfo As String = "<info>"  'info tag.
  Public Const K_TagInfoEnd As String = "</info>"
  Public Const K_ItemSep As String = "ZYAMP"   '..ItemSeperator.
  Public Const K_KVSep As String = "ZYEQ"      '..Key/Value seperator
  Public Const K_AT As String = "@"            '..ItemSep  3rd level
  Public Const K_PP As String = "|"            '..Rec sep. 2nd level
  Public Const K_Sep2 As String = "~"           '..2 level ItemSeperator.
  Public Const K_Sep1 As String = "???"         '..1 level ItemSeperator.
  '1 level deliminator ??? (2 of them, first part of 0 level item contains 2 numbers, e.g., 123,500 - 123 sites of total 500 have the variable.
  '2nt level deliminator "~"  (2nd part of the 0 level sperator, 6 of them)
  '3rd level deliminator "|" applied to element 6 (index=5)
  '4th level deliminator "@" applied to each element splited using "|"
  'to produce 3 elements, 1st=SiteCode,2nd=SiteName,3rd=number of observations.
  Public Const K_ConfirmSep As String = ":eq:"

  Public Const SITEINFO_REQUEST As String = "getSiteInfo"
  Public Const CSV_REQUEST As String = "getCSV"
  Public Const CHART_REQUEST As String = "getChart"
  Public Const ADDTOCART_REQUEST As String = "addToCart"
  Public Const ACTIVELAYER_UPDATE_REQUEST As String = "ActiveLayer"
  Public Const PREVIOUS_SELECTED_EXTENT_REQUEST As String = "PreviousSelectedExtent"
  Public Const CLEAR_SELECTED_FEATURES_REQUEST As String = "ClearSelection"
  Public Const ADDTOCART_MULTIPLE_REQUEST As String = "addToCartMultiple"
  Public Const CHECK_AVAILABILITY_REQUEST As String = "CheckAvailability"
  Public Const VARIABLE_MATCH_REQUEST As String = "getVariableMatchList"
  Public Const HISID_REQUEST As String = "HISID"
  Public Const K_LastExt As String = "LastExtent"
  Public Const K_CurrentExt As String = "CurrentExtent"

  ' TOOLBAR tool selection text  constants
  Public Const TOOL_SELECTED_CLEARSELECTED As String = "ClearSelection"
  Public Const TOOL_SELECTED_PREVIOUSSELECTED As String = "PreviousSelected"

  ' Single selection - add to cart db  sql queries input parameters  constants
  Public Const MySelect_INSERT_QUERY = "insert into MySelect (USessionID,SiteCode,SiteName,Network,VariableName,VariableCode,ValueCount,BeginDate,EndDate,UserName) values (@USessionID,@siteId,@siteName,@network,@variableName,@variableCode,@ValueCount,@beginDate,@endDate,@UserName) "
  Public Const MySelect_IS_DUPLICATE_RECORD = "SELECT COUNT(VariableCode) FROM MySelect WHERE (USessionID =@USessionID) AND (SiteCode =@siteId) AND (VariableCode = @variableCode)"

  ' Query  variables for a network
  Public Const QueryVariables_SQLQUERY_NETWORK_VARIABLES As String = "SELECT distinct VariableCode, VariableName FROM Variables WHERE VariableCode IS NOT NULL AND VariableName IS NOT NULL ORDER BY VariableName"  '"SELECT distinct VariableCode, VariableName FROM Variables WHERE VariableCode IS NOT NULL AND VariableName IS NOT NULL AND networkId =@networkId ORDER BY VariableName"
  ' check availability  function constants
  '  Public Const CheckAvailability_SQLQUERY_NETWORK_SELECTEDSTATIONS = ""
  'Public Const CheckAvailability_SQLQUERY_NETWORK As String = "SELECT DISTINCT SiteCode,SiteName,VariableID,BeginDateTime,EndDateTime,ValueCount FROM SeriesCatalog WHERE (VariableID IN (SELECT VariableID FROM Variables WHERE (networkId = @networkId) AND (VariableCode = @variableCode)))"

  ' CreateDataTableSiteCodeInfo  functions constants
  Public Const DB_AppDB As String = "APPDB"
  Public Const TB_Sites As String = "Sites"
  Public Const TB_Network As String = "Network"
  Public Const TB_Variables As String = "Variables"
  Public Const TB_MYSELECT As String = "MySelect"
  Public Const TB_TSTypeInfo As String = "TSTYPEINFO"
  Public Const TB_MembershipUsers As String = "vw_aspnet_Membershipusers"
  Public Const FD_NetworkName As String = "NetworkName"
  Public Const FD_NetworkID As String = "NetworkID"
  Public Const FD_SiteCode As String = "SiteCode"
  Public Const FD_SiteName As String = "SiteName"
  Public Const FD_SiteID As String = "SiteID"
  Public Const FD_ID As String = "ID"
  Public Const FD_ValueCount As String = "ValueCount"
  Public Const FD_USESSIONID As String = "USessionID"
  Public Const FD_NETWORK As String = "Network"
  Public Const FD_VARIABLENAME As String = "VariableName"
  Public Const FD_VARIABLECODE As String = "VariableCode"
  Public Const FD_VARIABLEID As String = "VariableID"
  Public Const FD_BEGINDATE As String = "BeginDate"
  Public Const FD_ENDDATE As String = "EndDate"
  Public Const FD_BeginDateTime As String = "BeginDateTime"    'GetsiteInfoLocal
  Public Const FD_EndDateTime As String = "EndDateTime"        'GetsiteInfoLocal
  Public Const FD_HYDROID As String = "HYDROID"
  Public Const FD_TSTYPEID As String = "TSTYPEID"
  Public Const FD_TSVARIABLEID As String = "VARIABLE"

  Public Const FD_Email As String = "Email"
  Public Const FD_UserName As String = "UserName"
  Public Const MAX_Loops As Integer = 10000000
  Public Const UnknowUser As String = "Anonymous"

  Public Const K_NumOfRecs As String = "numofRecs"
  Public Const K_ChartInput As String = "ChartInput"
  Public Const K_NoDataValue As String = "NoDataValue"


  ' Cart.aspx 
  ' bindGrid
  Public Const CART_BINDGRID_SQL = "SELECT ID, SiteCode, SiteName, Network, VariableName, VariableCode, ValueCount, BeginDate, EndDate FROM MySelect WHERE USessionID='Session.SessionID'"

  'Private Shared mResourceName As String = ""
  Private Shared cHisNetworks As HISNetworks
  Private Shared mMapServiceName As String = ""
  Public Shared mResourceIndex As Integer = 0
  Public Shared mLogger As ErrorLogger
  Public Shared htNetworkID As Hashtable
  Public Shared MaxNumberOfSites As Integer = 200
  Public Shared HostName As String = ""
  Public Shared QueryInterval As Integer = 50     '..Query interval.
  Public Shared DBForDownLoad As String = "App_Data\HISDownloadSchema.mdb"
  'Public Shared pPage As System.Web.UI.Page
  Public Shared CMD_TimeOut As Integer = 120
  Public Shared K_Value2Replace(,) As String = {{"&", "AND"}, {"=", "EQ"}, {"@", "AT"}, {"|", "Pipe"}}   '(OrgString,ReplacingString)

  Public Shared MyDBConBase As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
  Public Enum SelectActions
    NewSet = 0
    Add = 1
    Remove = 2
  End Enum
  Public Shared Property Logger() As ErrorLogger
    Get
      Return mLogger
    End Get
    Set(ByVal value As ErrorLogger)
      mLogger = value
    End Set
  End Property
  Public Shared Property HisNetworks() As HISNetworks
    Get
      If cHisNetworks Is Nothing Then

      End If
      Return cHisNetworks
    End Get
    Set(ByVal value As HISNetworks)
      cHisNetworks = value
    End Set
  End Property
  Public Shared Property MapServiceName() As String
    '..MapServiceName - to get mapfunctionality. zye.
    Get
      Return mMapServiceName
    End Get
    Set(ByVal value As String)
      mMapServiceName = value
    End Set
  End Property

  'Public Shared Property ResourceName() As String
  '  '..ResourceName - to get mapfunctionality. zye.
  '  Get
  '    Return mResourceName
  '  End Get
  '  Set(ByVal value As String)
  '    mResourceName = value
  '  End Set
  'End Property
  Public Property ResourceIndex() As Integer
    '..Returns resource index, may change if graphics layer is added dynamically. 
    '..use ResourceName to get mapfunctionality instead. zye.
    Get
      Return mResourceIndex
    End Get
    Set(ByVal value As Integer)
      mResourceIndex = value
    End Set
  End Property

  Public Shared Function GetLayer(ByVal pMapCtrl As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, ByVal sLayerName As String, ByVal ServerName As String) As ESRI.ArcGIS.Carto.ILayer
    '..Given mapctrl, layername, returns ILayer, zye.
    Dim pLayer As ESRI.ArcGIS.Carto.ILayer = Nothing
    Try
      Dim pMF As MapFunctionality
      pMF = pMapCtrl.GetFunctionality(ServerName)
      pLayer = GetLayer(pMF, sLayerName)
    Catch ex As Exception

    End Try
    Return pLayer
  End Function
  Public Shared Function GetLayer(ByVal mf As MapFunctionality, ByVal sLayerName As String) As ILayer
    '..Given mf, layername, returns ILayer, zye.
    Dim pLayer As ILayer
    Dim pGisRecsLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapServer As ESRI.ArcGIS.Carto.IMapServer
    Dim pMapServerObjects As IMapServerObjects
    Dim pMap As IMap
    Try
      'ESRI.ArcGIS.ADF.Web.DataSources.IGISResource pGisRecs = mf.Resource
      'pGisRecs = CType(mf.Resource, IGISDataSource)
      pGisRecsLocal = mf.Resource  '  pGisRecs
      pMapServer = pGisRecsLocal.MapServer
      pMapServerObjects = pMapServer
      pMap = pMapServerObjects.Map(pMapServer.DefaultMapName)
      pLayer = GetLayerByName(pMap, sLayerName, True)
    Catch ex As Exception
      pLayer = Nothing
    End Try
    Return pLayer

  End Function
  Public Shared Function GetLayerIndex(ByVal pMf As MapFunctionality, ByVal LayerName As String) As Integer
    '..given mf, and layername,  returns its index in the map, zye.
    Dim pGISRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription
    Dim pLayerDescs As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription()
    Dim pMapLayerInfos As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo()
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = Nothing
    Dim LayerIndex As Integer
    Dim intReturns() As Integer = Nothing
    Try
      pGISRes = pMf.Resource
      pGisResLocal = pGISRes
      pMapDesc = pMf.MapDescription
      pLayerDescs = pMapDesc.LayerDescriptions
      pMapLayerInfos = pGisResLocal.MapServerInfo.MapLayerInfos
      LayerIndex = GetLayerIndex(pMapLayerInfos, LayerName)
    Catch ex As Exception
      LayerIndex = -1
    End Try
    Return LayerIndex
  End Function
  Public Shared Function GetLayerIndex(ByVal cMapLayerInfos() As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo, ByVal sName As String) As Integer
    '..returns a layer's index in the Map control.  zye
    Dim iL As Integer = -1
    Dim i As Integer
    Dim mLInfo As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo
    Dim s As String = ""
    Try
      s = sName.ToLower
      For i = 0 To cMapLayerInfos.Length - 1
        mLInfo = cMapLayerInfos(i)
        If (mLInfo.Name.ToLower = s) Then
          iL = i
          Exit For
        End If
      Next
    Catch ex As Exception
      iL = -1
    End Try
    Return iL
  End Function
  ''' <summary>
  '''  Given a field name return its index
  ''' </summary>
  ''' <param name="pRow"></param>
  ''' <param name="sName"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetFieldIndex(ByVal pRow As IRow, ByVal sName As String) As Integer
    '..Given a fieldname, and irow, returns its index. zye.
    Dim pField As IField
    Dim pFields As IFields
    Dim iIndex = -1, i, iCnt As Integer
    Dim s As String
    Dim sDotName As String
    Try
      pFields = pRow.Fields
      sName = sName.Trim.ToLower
      sDotName = "." & sName
      iCnt = pFields.FieldCount
      For i = 0 To iCnt - 1
        pField = pFields.Field(i)
        s = pField.Name
        s = s.Trim.ToLower
        If ((s = sName) OrElse (s.EndsWith(sDotName))) Then
          iIndex = i
          Exit For
        End If
      Next
    Catch ex As Exception
      iIndex = -1
    End Try
    Return iIndex
  End Function
  Public Shared Function GetFieldIndex(ByVal pTable As ITable, ByVal sName As String) As Integer
    '..Given a fieldname, and itable, returns its index. zye.
    Dim pField As IField
    Dim pFields As IFields
    Dim iIndex = -1, i, iCnt As Integer
    Dim s As String
    Dim sDotName As String
    Try
      pFields = pTable.Fields
      sName = sName.Trim.ToLower
      sDotName = "." & sName
      iCnt = pFields.FieldCount
      For i = 0 To iCnt - 1
        pField = pFields.Field(i)
        s = pField.Name
        s = s.Trim.ToLower
        If ((s = sName) OrElse (s.EndsWith(sDotName))) Then
          iIndex = i
          Exit For
        End If
      Next
    Catch ex As Exception
      iIndex = -1
    End Try
    Return iIndex
  End Function
  Public Shared Function SetApWebFieldsIndex(ByVal pTable As ITable, ByRef cApWebFields As ApWebFields) As Boolean
    '..update the ApWebField.index for a given itable.  zye.
    Dim pApWebField As ApWebField
    Dim iIndex As Integer
    Dim b As Boolean = False
    Try
      For Each pApWebField In cApWebFields.Values
        iIndex = GetFieldIndex(pTable, pApWebField.Name)
        If iIndex < 0 Then
          iIndex = GetFieldIndex(pTable, pApWebField.FieldAlias)
        End If
        If iIndex < 0 Then
          iIndex = GetFieldIndex(pTable, pApWebField.FieldAlias)
        End If
        pApWebField.Index = iIndex
      Next
      b = True
    Catch ex As Exception

    End Try
    Return b
  End Function
  Public Shared Function SetApWebFieldsIndex(ByVal pRow As IRow, ByRef cApWebFields As ApWebFields) As Boolean
    '..update the ApWebField.index for a given irow.  zye.
    Dim pApWebField As ApWebField
    Dim iIndex As Integer
    Dim b As Boolean = False
    Try
      For Each pApWebField In cApWebFields.Values
        iIndex = GetFieldIndex(pRow, pApWebField.Name)
        If iIndex < 0 Then
          iIndex = GetFieldIndex(pRow, pApWebField.FieldAlias)
        End If
        If iIndex < 0 Then
          iIndex = GetFieldIndex(pRow, pApWebField.FieldAlias)
        End If
        pApWebField.Index = iIndex
      Next
      b = True
    Catch ex As Exception

    End Try
    Return b
  End Function
  ''' -----------------------------------------------------------------------------
  ''' <summary>
  '''   chk the value to see it is an object or a basic .net type.
  ''' </summary>
  ''' <param name="o"></param>
  ''' <param name="s"></param>
  ''' <returns>true is object,false, is not object</returns>
  ''' <remarks>
  ''' </remarks>
  ''' <history>
  ''' 	[ye]	4/21/2006	Created
  ''' </history>
  ''' -----------------------------------------------------------------------------
  Public Overloads Shared Function IsTypeObject(ByVal o As Object, ByRef s As String) As Boolean
    Dim bOk As Boolean
    Try
      If Not o Is Nothing Then
        If (o.GetType.Name = "Object") Or (o.GetType.Name = "KeyCollection") Or (o.GetType.Name) = "ValueCollection" Then
          bOk = True
        Else
          s = CType(o, String)
          bOk = False
        End If
      End If
      's = CType(o, String)
      'bOk = False
    Catch ex As Exception
      bOk = True
      s = ""
    End Try
    Return bOk
  End Function
  ''' <summary>
  ''' Given KeyFieldName, KeyFieldValue, return the value of ValueField.
  ''' KeyFieldValue = 1,2,3,4 etc if KeyField is of numeric type.
  ''' KeyFieldValue = 'a','b','c' etc, if KeyField is of String Type.
  ''' </summary>
  ''' <param name="ConnectionString"></param>
  ''' <param name="TableName"></param>
  ''' <param name="KeyFieldName"></param>
  ''' <param name="KeyFieldValue"></param>
  ''' <param name="ValueFieldName"></param>
  ''' <param name="bFirstValue">boolean, true get the first value only, if one to many relation exists</param>
  ''' <returns>Value of ValueField (or values seperated by V_Sep, default=","</returns>
  ''' <remarks></remarks>
  Public Shared Function GetFieldValue(ByVal ConnectionString As String, ByVal TableName As String, ByVal KeyFieldName As String, _
    ByVal KeyFieldValue As String, ByVal ValueFieldName As String, ByVal bFirstValue As Boolean, ByVal V_Sep As String) As String
    Dim pConn As SqlConnection = Nothing
    Dim pCmd As SqlCommand = Nothing
    Dim pReader As SqlDataReader = Nothing
    Dim sReturn As String = ""
    Dim s As String
    Try
      If (V_Sep = "") Then
        V_Sep = ","
      End If
      pConn = New SqlConnection
      pConn.ConnectionString = ConnectionString
      pCmd = New SqlCommand
      pCmd.CommandType = CommandType.Text
      pCmd.Connection = pConn
      pCmd.Connection.Open()
      pCmd.CommandText = "SELECT " & ValueFieldName & " FROM " & TableName & " WHERE " & KeyFieldName & " IN (" & KeyFieldValue & ")"
      pReader = pCmd.ExecuteReader()

      Do While pReader.Read
        s = convert.ToString(pReader.GetValue(0))
        If (sReturn = "") Then
          If (bFirstValue) Then
            sReturn = s
            Exit Do
          End If
        Else
          sReturn = sReturn & V_Sep & s
        End If
      Loop
    Catch ex As Exception
      Throw ex
    Finally
      If Not pCmd Is Nothing Then
        pCmd.Dispose()
      End If
      If Not (pConn Is Nothing) Then
        If ((pConn.State = ConnectionState.Open) OrElse (pConn.State = ConnectionState.Connecting) OrElse (pConn.State = ConnectionState.Executing) OrElse (pConn.State = ConnectionState.Fetching)) Then
          pConn.Close()
          pConn.Dispose()
        End If
      End If
    End Try
    Return sReturn
  End Function
  Public Shared Function GetSelectedFeatureIDs(ByVal pMapCtrl As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, ByVal LayerName As String, ByVal ResourceName As String, ByRef SelectedIds() As Integer) As Integer
    '..Get selected feature's oids, zye.
    Dim nCnt As Integer = 0
    Dim pMF As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality
    Try
      pMF = pMapCtrl.GetFunctionality(ResourceName)
      nCnt = GetSelectedFeatureIDs(pMF, LayerName, ResourceName, SelectedIds)
    Catch ex As Exception
      nCnt = -1
    End Try
    Return nCnt
  End Function
  ''' <summary>
  ''' Getting the selected via map, not from the saved hashtable.  Zye
  ''' </summary>
  ''' <param name="pMF"></param>
  ''' <param name="LayerName"></param>
  ''' <param name="ResourceName"></param>
  ''' <param name="SelectedIds"></param>
  ''' <returns>int = number of selected features</returns>
  ''' <remarks></remarks>
  Public Shared Function GetSelectedFeatureIDs(ByVal pMF As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality, _
    ByVal LayerName As String, ByVal ResourceName As String, ByRef SelectedIds() As Integer) As Integer
    '..Getting the selected via map, not from the saved hashtable.  Zye
    Dim nCnt As Integer = 0
    Dim pGISRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription
    Dim pLayerDescs As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription()
    Dim pMapLayerInfos As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo()
    Dim LayerId As Integer

    Try
      pGISRes = pMF.Resource
      pGisResLocal = pGISRes
      pMapDesc = pMF.MapDescription
      pLayerDescs = pMapDesc.LayerDescriptions
      pMapLayerInfos = pGisResLocal.MapServerInfo.MapLayerInfos
      Dim lName As String = LayerName.ToLower
      LayerId = GetLayerIndex(pMapLayerInfos, lName)
      If (LayerId >= 0) Then
        Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription
        pLayerDesc = pLayerDescs(LayerId)
        If (Not pLayerDesc Is Nothing) AndAlso (Not pLayerDesc.SelectionFeatures Is Nothing) Then
          SelectedIds = pLayerDesc.SelectionFeatures
          nCnt = SelectedIds.Length
        End If
      End If
    Catch ex As Exception
      nCnt = -1
    End Try
    Return nCnt
  End Function
  ''' <summary>
  ''' 'given a geom, returns int() of selected oids. zye.
  ''' </summary>
  ''' <param name="pmf"></param>
  ''' <param name="LayerName"></param>
  ''' <param name="FilterGeom"></param>
  ''' <param name="pSpatialRel"></param>
  ''' <param name="ShpFldName"></param>
  ''' <param name="pColor"></param>
  ''' <param name="SelectAction"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function ApplySelection(ByVal pmf As MapFunctionality, ByVal LayerName As String, ByVal FilterGeom As Geometry, ByVal pSpatialRel As ESRI.ArcGIS.ADF.ArcGISServer.esriSpatialRelEnum, _
    ByVal ShpFldName As String, ByVal pColor As RgbColor, ByVal SelectAction As SelectActions) As Integer()
    '..apply selections, given a geom, zye.
    Dim intReturns() As Integer = Nothing
    Dim pSpf As ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter
    Try
      pSpf = New ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter()
      pSpf.FilterGeometry = FilterGeom
      pSpf.GeometryFieldName = ShpFldName
      pSpf.SpatialRel = pSpatialRel
      intReturns = ApplySelection(pmf, LayerName, pSpf, pColor, SelectAction)
    Catch ex As Exception

    End Try
    Return intReturns
  End Function
  ''' <summary>
  ''' Given a geom, returns int() of selected oids. zye.
  ''' </summary>
  ''' <param name="pMF"></param>
  ''' <param name="LayerName"></param>
  ''' <param name="pQF"></param>
  ''' <param name="pSelColor"></param>
  ''' <param name="SelectAction"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function ApplySelection(ByVal pMF As MapFunctionality, ByVal LayerName As String, ByVal pQF As ESRI.ArcGIS.ADF.ArcGISServer.QueryFilter, ByVal pSelColor As RgbColor, ByVal SelectAction As SelectActions) As Integer()
    '..apply selections, given a geom, returns int() of selected oids. zye.
    Dim pGISRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription
    Dim pLayerDescs As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription()
    Dim pMapLayerInfos As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo()
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = Nothing
    Dim LayerIndex As Integer
    Dim intReturns() As Integer = Nothing
    Dim NewIDs() As Integer
    Try
      pGISRes = pMF.Resource
      pGisResLocal = pGISRes
      pMapDesc = pMF.MapDescription
      pLayerDescs = pMapDesc.LayerDescriptions
      pMapLayerInfos = pGisResLocal.MapServerInfo.MapLayerInfos
      LayerIndex = GetLayerIndex(pMapLayerInfos, LayerName)
      pLayerDesc = pLayerDescs(LayerIndex)

      'Dim pMSDP As MapServerDcomProxy = pGisResLocal.MapServerProxy
      'Dim pFIDSet As ESRI.ArcGIS.ADF.ArcGISServer.FIDSet
      'pFIDSet = pMSDP.QueryFeatureIDs(pMapDesc.Name, pLayerDesc.LayerID, pQF)
      NewIDs = GetFeatureIDs(pMF, LayerIndex, pQF)
      If (SelectAction = SelectActions.NewSet) Then
        pLayerDesc.SelectionFeatures = NewIDs
      Else
        Dim IDList As ArrayList = New ArrayList
        Dim OrgIDs() As Integer = pLayerDesc.SelectionFeatures
        'NewIDs = pFIDSet.FIDArray
        Dim iValue As Integer
        Dim i As Integer
        If (SelectAction = SelectActions.Add) Then
          For i = 0 To OrgIDs.Length - 1
            iValue = OrgIDs(i)
            IDList.Add(iValue)
          Next
          For i = 0 To NewIDs.Length - 1
            iValue = NewIDs(i)
            IDList.Add(iValue)
          Next
        Else
          If (SelectAction = SelectActions.Remove) Then
            Dim alIDs As ArrayList = New ArrayList
            For i = 0 To NewIDs.Length - 1
              iValue = NewIDs(i)
              alIDs.Add(iValue)
            Next
            For i = 0 To OrgIDs.Length - 1
              iValue = OrgIDs(i)
              If (Not alIDs.Contains(iValue)) Then
                IDList.Add(iValue)
              End If
            Next
          End If
        End If
        Dim intList(IDList.Count) As Integer
        For i = 0 To IDList.Count - 1
          intList(i) = CType(IDList.Item(i), Integer)
        Next
        pLayerDesc.SelectionFeatures = intList
      End If   'If (SelectAction = SelectActions.NewSet) Then
      If Not pSelColor Is Nothing Then
        pLayerDesc.SelectionColor = pSelColor
      End If
      intReturns = pLayerDesc.SelectionFeatures
    Catch ex As Exception
      intReturns = Nothing
    End Try
    Return intReturns
  End Function
  ''' <summary>
  '''   Given a pQF, get features filtered by the pQF.
  ''' </summary>
  ''' <param name="pMF"></param>
  ''' <param name="LayerName"></param>
  ''' <param name="pQF"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetFeatureIDs(ByVal pMF As MapFunctionality, ByVal LayerName As String, ByVal pQF As ESRI.ArcGIS.ADF.ArcGISServer.QueryFilter) As Integer()
    '..get features' oids filtered by pQF as int() zye
    Dim pGISRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription
    Dim pLayerDescs As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription()
    Dim pMapLayerInfos As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo()
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = Nothing
    Dim LayerIndex As Integer
    Dim intReturns() As Integer = Nothing
    Try
      pGISRes = pMf.Resource
      pGisResLocal = pGISRes
      pMapDesc = pMF.MapDescription
      pLayerDescs = pMapDesc.LayerDescriptions
      pMapLayerInfos = pGisResLocal.MapServerInfo.MapLayerInfos
      LayerIndex = GetLayerIndex(pMapLayerInfos, LayerName)
      intReturns = GetFeatureIDs(pMF, LayerIndex, pQF)
    Catch ex As Exception
      intReturns = Nothing
    End Try
    Return intReturns
  End Function
  Public Shared Function GetFeatureIDs(ByVal pMF As MapFunctionality, ByVal LayerIndex As Integer, ByVal pQF As ESRI.ArcGIS.ADF.ArcGISServer.QueryFilter) As Integer()
    '..get features' oids filtered by pQF as int() zye
    Dim pGISRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription
    Dim intReturns() As Integer = Nothing
    Try
      pGISRes = pMF.Resource
      pGisResLocal = pGISRes
      pMapDesc = pMF.MapDescription
      Dim pMSDP As MapServerDcomProxy = pGisResLocal.MapServerProxy
      Dim pFIDSet As ESRI.ArcGIS.ADF.ArcGISServer.FIDSet
      pFIDSet = pMSDP.QueryFeatureIDs(pMapDesc.Name, LayerIndex, pQF)
      intReturns = pFIDSet.FIDArray
    Catch ex As Exception
      intReturns = Nothing
    End Try
    Return intReturns
  End Function
  Public Shared Function GetShapeFieldName(ByVal mf As MapFunctionality, ByVal LayerName As String) As String
    '..Get Shp Field name., zye.
    Dim ShpName As String = "Shape"
    Dim pFL As IFeatureLayer
    Try
      pFL = GetLayer(mf, LayerName)
      If (Not pFL Is Nothing) Then
        Dim pFC As IFeatureClass = pFL.FeatureClass
        If Not pFC Is Nothing Then
          ShpName = pFC.ShapeFieldName
        End If
      End If
    Catch ex As Exception
      ShpName = "Shape"
    End Try
    Return ShpName
  End Function
  ''' <summary>
  '''   returns hashtable hosting current/last selected features' oids()
  '''   key                 value
  '''   LayerName&"_C"      int() OIDs of current selected features for the layer
  '''   LayerName&"_L"      int() OIDs of last selected features for the layer
  ''' </summary>
  ''' <param name="oPage"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>

  Public Shared Function GetSelected_Hashtable(ByVal oPage As System.Web.UI.Page) As Hashtable
    '..Returns the hashtable holding:
    '..Key=LayerName&"_C" - current selection.
    '..Key=LayerName&"_L" - last selection
    '..zye
    Dim htRet As Hashtable = New Hashtable
    Try
      htRet = oPage.Session(KS_Selected)
    Catch ex As Exception
      htRet = New Hashtable
    End Try
    If htRet Is Nothing Then
      htRet = New Hashtable
    End If
    Return htRet
  End Function


  ''' <summary>
  '''   returns hashtable hosting sitedcodes of selected features' 
  '''   key                 value
  '''   LayerName           StringOfSiteCode ='11161900'|'11162000'|'11162620'|'11162630'|'11162800'|'11162900'
  '''                       pipe delimited sitecodes.
  ''' </summary>
  ''' <param name="oPage"></param>
  ''' <returns>hashtable of sitedcodes of selected features</returns>
  ''' <remarks></remarks>
  Public Shared Function GetSiteCode_Hashtable(ByVal oPage As System.Web.UI.Page) As Hashtable
    '..Returns the hashtable holding:
    '  LayerName           StringOfSiteCode ='11161900','11162000','11162620','11162630','11162800','11162900'
    '..zye
    Dim htRet As Hashtable = New Hashtable
    Try
      htRet = oPage.Session(KS_SiteCodes)
    Catch ex As Exception
      htRet = New Hashtable
    End Try
    If htRet Is Nothing Then
      htRet = New Hashtable
    End If
    Return htRet
  End Function
  Public Shared Function GetLastSelectedIDs(ByVal oPage As System.Web.UI.Page, ByVal LayerName As String) As Integer()
    '..Get last selected oids, zye.
    Dim intReturns() As Integer
    Dim htRet As Hashtable
    Try
      htRet = GetSelected_Hashtable(oPage)
      intReturns = HashtableGetValue(htRet, LayerName & ApSConfigAHS.KS_L)
    Catch ex As Exception
      intReturns = Nothing
    End Try
    Return intReturns
  End Function
  Public Shared Function ToggleSelected(ByVal oPage As System.Web.UI.Page, ByVal pMapCtrl As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, ByVal sResourceName As String, ByVal LayerName As String) As Integer()
    '..Toggle selection, current/last, zye.
    Dim intSelected() As Integer = Nothing
    Dim nCnt As Integer
    Dim htSelected As Hashtable
    Dim LastSelected() As Integer = Nothing
    Dim pMf As MapFunctionality
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription
    Dim sMsg As String = ""
    Try
      nCnt = GetSelectedFeatureIDs(pMapCtrl, LayerName, sResourceName, intSelected)
      htSelected = GetSelected_Hashtable(oPage)
      Try
        LastSelected = GetLastSelectedIDs(oPage, LayerName)
      Catch ex As Exception
        LastSelected = Nothing
      End Try
      pMf = pMapCtrl.GetFunctionality(sResourceName)
      pLayerDesc = GetLayerDescription(pMf, LayerName)
      If Not LastSelected Is Nothing Then
        pLayerDesc.SelectionFeatures = LastSelected
      Else
        pLayerDesc.SelectionFeatures = Nothing
      End If
      '..switch between last selected and current selected.
      ApSConfigAHS.HashtableAddValue(htSelected, LayerName & ApSConfigAHS.KS_L, intSelected, True)
      ApSConfigAHS.HashtableAddValue(htSelected, LayerName & ApSConfigAHS.KS_C, LastSelected, True)
      oPage.Session(ApSConfigAHS.KS_Selected) = htSelected
      's = SaveSelectedSiteCodes(oPage, LayerName, pMf, LastSelected, sMsg, )

    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("ToggleSelected:" & ex.Message & "," & ex.StackTrace, True, -1, False)
      End If
    End Try
    Return LastSelected
  End Function
  Public Shared Function GetLayerDescription(ByVal pMf As MapFunctionality, ByVal LayerID As Integer) As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription
    '..Try to get layerdesc.  zye.
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = Nothing
    Try
      Dim pGisRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = pMf.Resource
      Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal = pGisRes
      Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription = pMf.MapDescription
      Dim pLayerDescs As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription() = pMapDesc.LayerDescriptions
      pLayerDesc = pLayerDescs(LayerID)
    Catch ex As Exception

    End Try
    Return pLayerDesc
  End Function
  Public Shared Function GetLayerDescription(ByVal pMf As MapFunctionality, ByVal LayerName As String) As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription
    '..given a functionality, return layerdesc. zye.
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = Nothing
    Dim iIndex As Integer
    Try
      Dim pGisRes As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = pMf.Resource
      Dim pGisResLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal = pGisRes
      Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription = pMf.MapDescription
      Dim pLayerDescs As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription() = pMapDesc.LayerDescriptions
      iIndex = GetLayerIndex(pMf, LayerName)
      pLayerDesc = GetLayerDescription(pMf, iIndex)
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("GetLayerDescription: " & ex.Message & "," & ex.StackTrace, True, -1, False)
      End If
    End Try
    Return pLayerDesc
  End Function
  Public Shared Function ClearSelectedFeatures(ByVal pMapCtrl As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, Optional ByVal bRefresh As Boolean = False) As Integer
    '..Remove selected features, originally appears in multiple places, consolidated here. zye.
    Dim ds As Long = Date.Now.Ticks
    Dim nCnt As Integer = 0
    Dim oPage As System.Web.UI.Page
    Dim mf As MapFunctionality
    Dim pGisRecs As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisRecsLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim pMapDesc As ESRI.ArcGIS.ADF.ArcGISServer.MapDescription
    Dim pLayerDescs() As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription
    Dim pLayerDesc As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription
    Dim SelectionID() As Integer
    Dim sMsg As String = ""
    Dim pMapLayerInfos As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo()
    Dim pMapLayerInfo As ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo

    Dim i As Integer
    Dim oNetwork As HISNetwork
    Try
      oPage = pMapCtrl.Page
      mf = CType(pMapCtrl.GetFunctionality(MapServiceName), MapFunctionality)
      pGisRecs = mf.Resource
      pGisRecsLocal = CType(pGisRecs, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)
      pMapDesc = mf.MapDescription
      pLayerDescs = pMapDesc.LayerDescriptions
      pMapLayerInfos = pGisRecsLocal.MapServerInfo.MapLayerInfos
      ' Get the current extent and save it before drawing the new extent
      'Dim mappoly As ESRI.ArcGIS.ADF.Web.Geometry.Envelope = CType(pMapCtrl.Page.Session(ApSConfigAHS.KS_SELECTED_CURRENTEXT), ESRI.ArcGIS.ADF.Web.Geometry.Envelope)
      'If Not mappoly Is Nothing Then
      '  pMapCtrl.Page.Session(ApSConfigAHS.KS_SELECTED_CURRENTEXT_SAVED) = mappoly
      '  pMapCtrl.Page.Session(ApSConfigAHS.KS_SELECTED_CURRENTEXT) = Nothing
      'End If
      For i = 0 To pLayerDescs.Length - 1
        pLayerDesc = pLayerDescs(i)
        If (Not pLayerDesc Is Nothing) Then
          SelectionID = pLayerDesc.SelectionFeatures
          If ((Not SelectionID Is Nothing) AndAlso (SelectionID.Length > 0)) Then
            nCnt = nCnt & SelectionID.Length
            pMapLayerInfo = pMapLayerInfos(i)
            oNetwork = HisNetworks.GetNetworkByLayerName(pMapLayerInfo.Name)
            If (Not oNetwork Is Nothing) Then
              ClearSelectedSiteCode(oPage, oNetwork.LayerName)
            End If
            Dim htSelected As Hashtable
            htSelected = GetSelected_Hashtable(oPage)
            '..switch between last selected and current selected.
            ApSConfigAHS.HashtableAddValue(htSelected, pMapLayerInfo.Name & ApSConfigAHS.KS_L, SelectionID, True)
            oPage.Session(ApSConfigAHS.KS_Selected) = htSelected
          End If
          pLayerDesc.SelectionFeatures = Nothing
        End If
      Next
      If bRefresh = True Then
        pMapCtrl.Refresh()
      End If

    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("ClearSelectedFeatures: " & ex.Message & "," & ex.StackTrace, True, ds, False)
      End If
      nCnt = 0
    End Try
    Return nCnt
  End Function
  Public Shared Function SaveSelectedSiteCodes(ByVal oPage As System.Web.UI.Page, ByVal LayerName As String, ByVal pMf As MapFunctionality, ByVal SelectedOIDs() As Integer, ByRef sMsg As String, Optional ByVal SiteCodeFieldName As String = "SiteCodes") As String
    '..Given oids() return "|" delimited sitecodes 
    Dim SiteCodes As String
    Dim pFL As ESRI.ArcGIS.Carto.IFeatureLayer
    Dim pFC As ESRI.ArcGIS.Geodatabase.IFeatureClass
    Try
      pFL = ApSConfigAHS.GetLayer(pMf, LayerName)
      pFC = pFL.FeatureClass
      SiteCodes = SaveSelectedSiteCodes(oPage, LayerName, CType(pFC, ITable), SelectedOIDs, sMsg, SiteCodeFieldName)
    Catch ex As Exception
      sMsg = ex.ToString
      SiteCodes = ""
    End Try
    Return SiteCodes
  End Function
  Public Shared Function GetSiteCodesViaOIDs(ByVal pMF As MapFunctionality, ByVal LayerName As String, ByVal SiteCodeFieldName As String, ByVal OIDs() As Integer, ByRef sMsg As String, Optional ByVal sDel As String = "|") As String
    '..Given oids() return "|" delimited sitecodes 
    Dim sSitecodes As String
    Dim pFL As ESRI.ArcGIS.Carto.IFeatureLayer
    Dim pFC As ESRI.ArcGIS.Geodatabase.IFeatureClass
    Dim pTable As ITable
    Dim sb As System.Text.StringBuilder = New StringBuilder
    Dim i As Integer
    Try
      pFL = ApSConfigAHS.GetLayer(pMF, LayerName)
      pFC = pFL.FeatureClass
      pTable = CType(pFC, ITable)
      i = pTable.Fields.FindField(SiteCodeFieldName)
      If (i > 0) Then
        sSitecodes = GetSiteCodesViaOIDs(pTable, SiteCodeFieldName, OIDs, sMsg, sDel)
      Else
        sMsg = "Field:" & SiteCodeFieldName & " does not exist in " & LayerName
        sSitecodes = ""
      End If
    Catch ex As Exception
      sSitecodes = ""
    End Try
    Return sSitecodes
  End Function
  ''' <summary>
  '''   Given oids() return "|" delimited sitecodes 
  ''' </summary>
  ''' <param name="pTable">ITable hosting SiteCodes</param>
  ''' <param name="SiteCodeFieldName"></param>
  ''' <param name="OIDs">int() array</param>
  ''' <param name="sMsg">return msg if there is an error</param>
  ''' <param name="sDel">deliminator, default="|"</param>
  ''' <returns>"|" delimited sitecodes </returns>
  ''' <remarks></remarks>
  Public Shared Function GetSiteCodesViaOIDs(ByVal pTable As ITable, ByVal SiteCodeFieldName As String, ByVal OIDs() As Integer, ByRef sMsg As String, Optional ByVal sDel As String = "|") As String
    '..Given oids() return "|" delimited sitecodes 
    Dim sSitecodes As String
    Dim sb As System.Text.StringBuilder = New StringBuilder
    Try
      Dim i As Integer = 0
      Dim FID As Integer
      Dim nCnt As Integer
      Dim sCode As String
      Dim pRow As IRow
      Dim iFld As Integer
      If (SiteCodeFieldName = "") Then
        SiteCodeFieldName = FD_SiteCode
      End If
      If sDel = "" Then
        sDel = "|"
      End If
      iFld = GetFieldIndex(pTable, SiteCodeFieldName)
      If (iFld >= 0) Then
        nCnt = OIDs.Length
        For i = 0 To nCnt - 1
          FID = OIDs(i)
          pRow = pTable.GetRow(FID)
          Try
            sCode = "" & pRow.Value(iFld)
          Catch ex As Exception
            sCode = ""
          End Try
          If (sCode <> "") Then
            If (sb.Length = 0) Then
              sb.Append(sCode)
            Else
              sb.Append(sDel & sCode)
            End If
          End If
        Next
        sSitecodes = sb.ToString
      Else
        sMsg = "Field:" & SiteCodeFieldName & " does not exist."
        sSitecodes = ""
      End If
    Catch ex As Exception
      sSitecodes = ""
    End Try
    Return sSitecodes

  End Function
  ''' <summary>
  '''  SaveSiteCodes given an array of OID() of sites
  ''' </summary>
  ''' <param name="oPage"></param>
  ''' <param name="LayerName"></param>
  ''' <param name="pTable"></param>
  ''' <param name="SelectedOIDs"></param>
  ''' <param name="sMsg"></param>
  ''' <param name="SiteCodeFieldName"></param>
  ''' <param name="sDel"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function SaveSelectedSiteCodes(ByVal oPage As System.Web.UI.Page, ByVal LayerName As String, _
    ByVal pTable As ITable, ByVal SelectedOIDs() As Integer, ByRef sMsg As String, _
    Optional ByVal SiteCodeFieldName As String = "SiteCodes", Optional ByVal sDel As String = "|") As String
    '..Save the selected feature's sitecodes.  zye.
    Dim SiteCodes As String = ""
    Dim htSiteCode As Hashtable
    Try
      SiteCodes = GetSiteCodesViaOIDs(pTable, SiteCodeFieldName, SelectedOIDs, sMsg, sDel)
    Catch ex As Exception
      SiteCodes = ""
    End Try
    htSiteCode = ApSConfigAHS.GetSiteCode_Hashtable(oPage)
    ApSConfigAHS.HashtableAddValue(htSiteCode, LayerName, SiteCodes, True)
    oPage.Session(ApSConfigAHS.KS_SiteCodes) = htSiteCode
    Return SiteCodes
  End Function
  Public Shared Function ClearSelectedSiteCode(ByVal oPage As System.Web.UI.Page, ByVal LayerName As String) As Boolean
    Dim htSiteCode As Hashtable
    Dim b As Boolean
    Try
      htSiteCode = GetSiteCode_Hashtable(oPage)
      HashtableAddValue(htSiteCode, LayerName, "", True)
      b = True
    Catch ex As Exception
      b = False
    End Try
    Return b
  End Function
  Public Shared Function GetSelectedSiteCodes(ByVal oPage As System.Web.UI.Page, ByVal LayerName As String) As String
    Dim htSiteCodes As Hashtable
    Dim SiteCodes As String = ""
    Try
      htSiteCodes = GetSiteCode_Hashtable(oPage)
      SiteCodes = HashtableGetString(htSiteCodes, LayerName)
    Catch ex As Exception
      SiteCodes = ""
    End Try
    Return SiteCodes
  End Function
  Public Shared Shadows Function Write2Log(ByVal sMsg As String, Optional ByVal bAddTime As Boolean = False, Optional ByVal nTime As Long = -1, _
    Optional ByVal bTimeBeforeMsg As Boolean = True, Optional ByVal UID As String = "") As Integer
    Dim iok As Integer
    Try
      If (mLogger Is Nothing) Then
        iok = 0
      Else
        iok = mLogger.write2Log(sMsg, bAddTime, nTime, bTimeBeforeMsg)
      End If
    Catch ex As Exception
      iok = -1
    End Try
    Return iok
  End Function
  'Public Shared Function GetNetworkID(ByVal NetworkName As String) As Integer
  '  '..Given a networkname, return NetworkId. zye
  '  Dim NetworkId As Integer = -1
  '  If htNetworkID Is Nothing Then
  '    htNetworkID = New Hashtable
  '  End If
  '  Try
  '    NetworkId = HashtableGetInteger(htNetworkID, NetworkName, -1)
  '  Catch ex As Exception
  '    NetworkId = -1
  '  End Try
  '  If NetworkId = -1 Then
  '    Try
  '      Dim sConn As String
  '      sConn = ConfigurationManager.ConnectionStrings(ApSConfigAHS.K_ODEConn).ConnectionString
  '      NetworkId = Convert.ToInt32(ApSConfigAHS.GetFieldValue(sConn, ApSConfigAHS.TB_Network, ApSConfigAHS.FD_NetworkName, "'" & NetworkName & "'", ApSConfigAHS.FD_NetworkID, True, ","))
  '      If NetworkId >= 0 Then
  '        HashtableAddValue(htNetworkID, NetworkName, NetworkId, True)
  '      End If
  '    Catch ex As Exception
  '      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
  '        ApSConfigAHS.Write2Log("GetNetworkID:" & ex.Message & "," & ex.StackTrace, True, -1, False)
  '      End If
  '      NetworkId = 2
  '    End Try
  '  End If
  '  Return NetworkId
  'End Function
  ''' <summary>
  '''  Given VriableCode, return VariableName.
  ''' </summary>
  ''' <param name="oNetwork"></param>
  ''' <param name="VariableCode"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetVariableName(ByVal oNetwork As HISNetwork, ByVal VariableCode As String) As String
    Dim VariableName As String = ""
    Dim sCon As String
    Try
      sCon = oNetwork.DBConnection
      VariableName = GetVariableName(sCon, VariableCode)
    Catch ex As Exception
      VariableName = ""
    End Try
    Return VariableName
  End Function
  ''' <summary>
  '''  Given VriableCode, return VariableName. zye.
  ''' </summary>
  ''' <param name="VariableCode"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetVariableName(ByVal sCon As String, ByVal VariableCode As String) As String
    Dim ds As Long = Date.Now.Ticks
    Dim VariableName As String = ""
    Try
      VariableName = GetFieldValue(sCon, TB_Variables, FD_VARIABLECODE, "'" & VariableCode & "'", FD_VARIABLENAME, True, ",")
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("GetVariableName:" & ex.Message & "," & ex.StackTrace, True, ds, False)
      End If
      VariableName = ""
    Finally
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogDSTime) = ApSConfigAHS.DebugType.LogDSTime) Then
        ApSConfigAHS.Write2Log("GetVariableName:", True, ds, False)
      End If

    End Try
    Return VariableName
  End Function




  ''' <summary>
  '''  Given SiteCode, return SiteName.
  ''' </summary>
  ''' <param name="SiteCode"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetSiteName(ByVal oNetwork As HISNetwork, ByVal SiteCode As String) As String
    Dim NetworkID As Integer = -1
    Dim SiteName As String = ""
    Dim sCon As String = ""
    Try
      sCon = oNetwork.DBConnection
      SiteName = GetSiteName(sCon, SiteCode)
    Catch ex As Exception
      SiteName = ""
    End Try
    Return SiteName
  End Function

  ''' <summary>
  '''  Given SiteCode, return SiteName. zye.
  ''' </summary>
  ''' <param name="SiteCode"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  '''Public Shared Function GetSiteName(ByVal NetworkID As Integer, ByVal SiteCode As String) As String
  Public Shared Function GetSiteName(ByVal sCon As String, ByVal SiteCode As String) As String
    Dim ds As Long = Date.Now.Ticks
    Dim SiteName As String = ""
    Try

      SiteName = GetFieldValue(sCon, TB_Sites, FD_SiteCode, "'" & SiteCode & "'", FD_SiteName, True, ",")
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("GetSiteName:" & ex.Message & "," & ex.StackTrace, True, ds, False)
      End If
      SiteName = ""
    Finally
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogDSTime) = ApSConfigAHS.DebugType.LogDSTime) Then
        ApSConfigAHS.Write2Log("GetSiteName:", True, ds, False)
      End If
    End Try
    Return SiteName
  End Function
  Public Shared Function GetWebSiteName(ByVal oPage As System.Web.UI.Page, ByRef WebPath As String, ByRef MainPageName As String) As String
    ''Get WebSiteInfo zye.
    Dim PagePath As String
    Dim LastSlash As Integer
    Dim WebSiteName As String
    Try
      PagePath = oPage.Request.FilePath
      LastSlash = PagePath.LastIndexOf("/")
      WebSiteName = PagePath.Substring(1, (LastSlash - 1))
      WebPath = oPage.Server.MapPath(WebPath)

      MainPageName = oPage.Server.MachineName   'PagePath.Substring((LastSlash + 1))
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("GetWebSiteName:" & ex.Message & "," & ex.StackTrace, True, -1, False)
      End If
      WebSiteName = ""
    End Try
    Return WebSiteName
  End Function
  Public Shared Function GetSelectedSiteCodes(ByVal oPage As System.Web.UI.Page) As String()
    '..SiteCodes are stored in a hashtable keyed on LayerName, value= "|" separated sitecodes.
    Dim oNetWork As HISNetwork
    Dim ArrSiteCodes() As String
    Dim SiteCodes As String
    Try
      oNetWork = oPage.Session(ApSConfigAHS.KS_ACTIVENETWORK)
      SiteCodes = ApSConfigAHS.GetSelectedSiteCodes(oPage, oNetWork.LayerName)
      If SiteCodes <> "" Then
        ArrSiteCodes = SiteCodes.Split("|")
      Else
        ArrSiteCodes = Nothing
      End If
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("GetSelectedSiteCodes:" & ex.Message & "," & ex.StackTrace, True, -1, False)
      End If
      ArrSiteCodes = Nothing
    End Try
    Return ArrSiteCodes
  End Function
  Public Shared Function ParseString2D(ByVal sSiteCodes As String, _
  Optional ByVal RecordSep As String = "|", Optional ByVal FieldSep As String = "@") As Hashtable
    '..Given a Sitecodes string in this format:
    '  "11113500@SANTA PAULA C NR SANTA PAULA@50|11114000@SANTA CLARA RIVER AT MONTALVO CA@244, parse it to 3 arrays
    '  returns Hashtable key=the index of Items (seperated by ItemSep)
    '  value=String() array, the length of each string array = number of fields.
    '  Hashtable.count = number of records.
    Dim htReturns As Hashtable = New Hashtable
    Dim SiteCodes() As String
    Dim Rec() As String   '..array holding pased items.
    Dim nRecs As Integer = 0
    Dim nItems As Integer = 0
    Dim i As Integer
    Dim sRec As String
    Try
      If (RecordSep = "") Then
        RecordSep = "|"
      End If
      If (FieldSep = "") Then
        FieldSep = "@"
      End If
      If (sSiteCodes.Length > 0) Then
        SiteCodes = sSiteCodes.Split("|")
        Try
          nRecs = SiteCodes.Length
          For i = 0 To nRecs - 1
            sRec = SiteCodes(i)
            Rec = sRec.Split(FieldSep)
            htReturns.Add(i, Rec)
          Next
        Catch ex As Exception

        End Try
      End If
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("PaarseString2D:" & ex.Message & "," & ex.StackTrace, True, -1, False)
      End If

    End Try
    Return htReturns
  End Function
  Public Shared Function SaveSelectedOIDs(ByVal oPage As System.Web.UI.Page, ByVal pmf As MapFunctionality, _
    ByVal LayerName As String, Optional ByVal bAsLast As Boolean = True) As Integer()
    '..Save the currect selected feature's oids (integer()) as lastselection set before apply the new selection. zye
    Dim orgIds() As Integer = Nothing
    Dim n As Integer
    Dim htSelectedFeatures As Hashtable
    htSelectedFeatures = ApSConfigAHS.GetSelected_Hashtable(oPage)
    '..Getting the selected via map, not from the saved hashtable.
    n = ApSConfigAHS.GetSelectedFeatureIDs(pmf, LayerName, ApSConfigAHS.MapServiceName, orgIds)
    Dim sKey As String
    If (bAsLast = True) Then
      sKey = LayerName & ApSConfigAHS.KS_L
    Else
      sKey = LayerName & ApSConfigAHS.KS_C
    End If
    ApSConfigAHS.HashtableAddValue(htSelectedFeatures, sKey, orgIds, True)
    oPage.Session(ApSConfigAHS.KS_Selected) = htSelectedFeatures
    Return orgIds
  End Function
  Public Shared Function GetFeaturesByGeom(ByVal pmf As MapFunctionality, ByVal LayerName As String, ByVal FilterGeom As Geometry, ByVal pSpatialRel As ESRI.ArcGIS.ADF.ArcGISServer.esriSpatialRelEnum, ByVal ShpFldName As String) As Integer()
    '..Given a layername , and extentget return oids (as int()) of features.  zye. 
    Dim pSpf As ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter
    Dim intIDs() As Integer
    Try
      If (ShpFldName = "") Then
        ShpFldName = GetShapeFieldName(pmf, LayerName)
      End If
      pSpf = New ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter()
      pSpf.FilterGeometry = FilterGeom
      pSpf.GeometryFieldName = ShpFldName
      pSpf.SpatialRel = pSpatialRel
      intIDs = GetFeatureIDs(pmf, LayerName, pSpf)
    Catch ex As Exception
      intIDs = Nothing
    End Try
    Return intIDs
  End Function
  Public Shared Function GetSelectionColor() As RgbColor
    Dim pSelColor As RgbColor
    'pSelColor = New RgbColor
    'pSelColor.Red = 255
    'pSelColor.Blue = 10
    'pSelColor.Green = 250
    'pSelColor.AlphaValue = 250
    pSelColor = Nothing
    Return pSelColor
  End Function
  ''' <summary>
  '''   Given a layername, returns feature oids in the current map extent.  zye.
  ''' </summary>
  ''' <param name="oPage"></param>
  ''' <param name="pmf"></param>
  ''' <param name="LayerName"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetOIDsInMapExtent(ByVal oPage As System.Web.UI.Page, ByVal pmf As MapFunctionality, ByVal LayerName As String) As Integer()
    '..Given a layername, returns feature oids in the current map extent. zye.
    Dim ds As Long = Date.Now.Ticks
    Dim pMappoly As ESRI.ArcGIS.ADF.Web.Geometry.Envelope
    Dim intIDs() As Integer = Nothing
    Dim sMsg As String = ""
    Dim pServerContext As IServerContext
    Dim pGisRecs As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource
    Dim pGisRecsLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    Dim env As EnvelopeN
    Try
      pGisRecs = pmf.Resource
      pGisRecsLocal = CType(pGisRecs, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)
      pServerContext = pGisRecsLocal.ServerContextInfo.ServerContext()
      pMappoly = CType(oPage.Session(ApSConfigAHS.CURRENT_MAP_EXTENT), ESRI.ArcGIS.ADF.Web.Geometry.Envelope)
      env = ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.FromAdfEnvelope(pMappoly)
      intIDs = ApSConfigAHS.GetFeaturesByGeom(pmf, LayerName, env, ESRI.ArcGIS.ADF.ArcGISServer.esriSpatialRelEnum.esriSpatialRelIntersects, "")
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("GetOIDsInMapExtent:", True, ds, False)
      End If
      intIDs = Nothing
    End Try
    Return intIDs
  End Function
  ''' <summary>
  '''   Given a full path, returns the PathName leading to the LastPart Name.  
  '''   LastPart name can be either a file name or dir name.
  '''   e.g., FullPathName="E:\Program Files\Microsoft Visual Studio 8\VB\Snippets\1033\application\"
  '''   returns "E:\Program Files\Microsoft Visual Studio 8\VB\Snippets\1033\
  '''   LastPart="application\"
  ''' </summary>
  ''' <param name="FullPathName"></param>
  ''' <param name="LastPart">OutParam, last part of the elem.</param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetPathName(ByVal FullPathName As String, ByRef LastPart As String, Optional ByVal PathSep As String = "\") As String
    Dim nLen As Integer
    Dim n As Integer
    Dim sFullName As String
    Dim sReturn As String
    Try
      If (PathSep Is Nothing) OrElse (PathSep.Length = 0) Then
        PathSep = "\"
      End If
      sFullName = FullPathName
      nLen = sFullName.Length
      n = sFullName.LastIndexOf(PathSep)
      If (nLen = n + 1) Then
        sFullName = FullPathName.Substring(0, n - 1)
        n = sFullName.LastIndexOf(PathSep)
      End If
      sReturn = sFullName.Substring(0, n + 1)
      LastPart = FullPathName.Substring(n + 1)
    Catch ex As Exception
      sReturn = ""
    End Try
    Return sReturn
  End Function
  ''' <summary>
  '''  PathName=FullPathName leading to the Folder the File and ZipFile
  '''  e.g., "e:\inetpub\wwwroot\HISWEB\csv\" is the folder hosting the file and zip file.
  '''  when zipping the file, only the csv\ will be used (relative path, rather than fullpath.
  '''  FileName=The file to be zipped.
  ''' </summary>
  ''' <param name="PathName"></param>
  ''' <param name="FileName"></param>
  ''' <remarks></remarks>
  Public Shared Function AddToZip(ByVal PathName As String, ByVal FileName As String, Optional ByVal bDeleteOrg As Boolean = False) As String
    Dim FullFileName As String
    PathName = IIf(PathName.EndsWith("\"), PathName, PathName & "\")
    FullFileName = PathName & FileName
    Dim sZipFileName As String
    Try
      Dim inFile As System.IO.FileStream = File.OpenRead(FullFileName)
      Dim buffer(inFile.Length) As Byte
      inFile.Read(buffer, 0, buffer.Length)
      inFile.Close()

      Dim sLastPart As String = ""
      sZipFileName = System.IO.Path.ChangeExtension(FileName, "zip")
      Dim zs As ZipOutputStream = New ZipOutputStream(File.Create(PathName & sZipFileName))
      'Dim zs As ZipOutputStream = New ZipOutputStream(File.Create(System.IO.Path.ChangeExtension(FullFileName, "zip")))
      zs.SetLevel(5)
      PathName = ApSConfigAHS.GetPathName(PathName, sLastPart)
      Dim zEntry As ZipEntry = New ZipEntry(sLastPart & FileName)
      zs.PutNextEntry(zEntry)
      zs.Write(buffer, 0, buffer.Length)
      zs.Finish()
      zs.Close()
      If bDeleteOrg = True Then
        Try
          System.IO.File.Delete(FullFileName)
        Catch ex As Exception
          If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
            ApSConfigAHS.Write2Log(":" & ex.Message & ", " & ex.StackTrace, True, -1, False)
          End If
        End Try
      End If
    Catch ex As Exception
      sZipFileName = FileName
    End Try
    Return sZipFileName
  End Function
  Public Shared Function MakeMsg4Web(ByVal sMsg As String) As String
    ''..Remove the web/app reserved char 
    Dim n As Integer
    Dim sReturn As String = ""
    Dim s As String
    Dim sp As String
    Dim i As Integer
    Try
      sReturn = sMsg
      If ((Not sMsg Is Nothing) AndAlso (sMsg.Length > 0)) Then
        n = K_Value2Replace.Length() / 2
        For i = 0 To n - 1
          s = K_Value2Replace(i, 0)
          sp = K_Value2Replace(i, 1)
          If (sMsg.Contains(s)) Then
            sMsg = sMsg.Replace(s, sp)
          End If
        Next
        sReturn = sMsg
      End If
    Catch ex As Exception
      sReturn = sMsg
    End Try
    Return sReturn
  End Function

  Public Shared Function GetLayerOnServer(ByVal HostName As String, ByVal ServerObjectName As String, ByVal LayerName As String) As ILayer
    Dim pSC As IServerContext = Nothing
    Dim pLayer As ILayer
    Dim pGISConn As IGISServerConnection
    Dim pSOM As IServerObjectManager
    Dim pServerObject As IServerObject
    Dim pMapServer As ESRI.ArcGIS.Carto.IMapServer
    Dim pMapServerObjects As ESRI.ArcGIS.Carto.IMapServerObjects
    Dim pMap As ESRI.ArcGIS.Carto.IMap
    Try
      pGISConn = New GISServerConnectionClass()
      pGISConn.Connect(HostName)
      pSOM = pGISConn.ServerObjectManager
      pSC = pSOM.CreateServerContext(ServerObjectName, "MapServer")
      pServerObject = pSC.ServerObject
      pMapServer = pServerObject
      pMapServerObjects = pMapServer
      pMap = pMapServerObjects.Map(pMapServer.DefaultMapName)
      pLayer = ApSConfigAHS.GetLayerByName(pMap, LayerName)
    Catch ex As Exception
      pLayer = Nothing
    Finally
      If (Not pSC Is Nothing) Then
        pSC.ReleaseContext()
        pSC = Nothing
      End If
    End Try
    Return pLayer
  End Function
  Public Shared Function GetFeatureClassOnServer(ByVal HostName As String, ByVal ServerObjectName As String, ByVal LayerName As String) As IFeatureClass
    Dim pFC As IFeatureClass
    Try
      Dim pFL As IFeatureLayer
      pFL = GetLayerOnServer(HostName, ServerObjectName, LayerName)
      pFC = pFL.FeatureClass
    Catch ex As Exception
      pFC = Nothing
    End Try
    Return pFC
  End Function
  Public Shared Function CreateDatasetFeatureClass(ByVal pFDS As ESRI.ArcGIS.Geodatabase.IFeatureDataset, ByVal strName As String, _
  ByVal featType As ESRI.ArcGIS.Geodatabase.esriFeatureType, Optional ByVal geomType As ESRI.ArcGIS.Geometry.esriGeometryType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint, _
  Optional ByVal pFields As ESRI.ArcGIS.Geodatabase.IFields = Nothing, Optional ByVal pCLSID As UID = Nothing, _
  Optional ByVal pCLSEXT As UID = Nothing, Optional ByVal strConfigWord As String = "", _
  Optional ByVal OIDFldName As String = "OID", Optional ByVal ShpFldName As String = "Shape", _
  Optional ByVal SpatialRef As ISpatialReference = Nothing, Optional ByVal bHasM As Boolean = False, _
  Optional ByVal bHasZ As Boolean = False, Optional ByVal GridSize As Double = 0) As ESRI.ArcGIS.Geodatabase.FeatureClass
    '*****************************************************************
    ' Copyright, 2001 ESRI, All Rights Reserved.
    '*****************************************************************
    'Description: Create a FeatureClassDataset under a given FeatureDataSet.
    '  pFDS=GeoFeatureDataset under which the new FeatureClassDataset (FCD) will reside.
    '  strName=TheName of the FeatureClassDataset (FCD) to be created.
    '  featType=Feature Type of the FCD to be created.
    '  geomType=Geometry type of the FCD to be created.
    '  pFields=Fields of the new FCD will have.  If pFields are not provided, a new pFieldsEdit (pFields)
    '    will be created to contain OID and SHP fields.  If pFields does not contain OID or SHP fld,
    '    the missing field will be created.
    '  pClsID=ClassID (UID) of the newly created FCD
    '  pClsExt=ClassExtID (UID) of the newly created FCD
    '  OIDFldName=used to create OID field when the OIDFld is not provided by the calling program.
    '  ShpFldName=used to create Shp field when the SHPFld is not provided by the calling program.
    'History: Modified zye 08-08-2001 @ 11:29:10
    '*****************************************************************
    Dim pFeatureClass As IFeatureClass
    Dim pClassSchemaEdit As IClassSchemaEdit
    Dim s As String

    s = "!~#$%^&*()-+= `/?><,';:"""
    If pFDS Is Nothing Then Exit Function

    Try
      If geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryAny Then
        geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint
      End If
      If (pCLSID Is Nothing) Then
        pCLSID = Nothing
        pCLSID = New UID
        If featType = 0 Then
          featType = ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple  'esriFTSimple
        End If
        Select Case featType
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple
            pCLSID.Value = "esriGeoDatabase.Feature"
            If geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryLine Then geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleJunction
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint
            pCLSID.Value = "esriGeoDatabase.SimpleJunctionFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTComplexJunction
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint
            pCLSID.Value = "esriGeoDatabase.ComplexJunctionFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleEdge
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline
            pCLSID.Value = "esriGeoDatabase.SimpleEdgeFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTComplexEdge
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline
            pCLSID.Value = "esriGeoDatabase.ComplexEdgeFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTAnnotation
        End Select
      End If

      ' set up a simple fields collection
      Dim pFieldsEdit As ESRI.ArcGIS.Geodatabase.IFieldsEdit
      If (pFields Is Nothing) Then
        pFieldsEdit = New ESRI.ArcGIS.Geodatabase.Fields
        pFieldsEdit.AddField(CreateGeometryField(geomType, GridSize, 0, bHasM, bHasZ, SpatialRef, ShpFldName))
        pFieldsEdit.AddField(CreateField(OIDFldName, ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID, "object identifer"))
        pFields = pFieldsEdit
      End If
      '..Make sure OID field and ShapeField exist in the pFields
      Dim pField As IField
      Dim bOIDFldExist As Boolean
      Dim bShpFldExist As Boolean

      bShpFldExist = False
      bOIDFldExist = False
      Dim i As Integer

      For i = 0 To pFields.FieldCount - 1 ' pField In pFields
        pField = pFields.Field(i)
        If pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID Then
          bOIDFldExist = True
        End If
        If pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then
          bShpFldExist = True
        End If
        If bOIDFldExist = True And bShpFldExist = True Then
          Exit For
        End If
      Next
      If bOIDFldExist = False Then
        pFieldsEdit = pFields
        pFieldsEdit.AddField(CreateField(OIDFldName, ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID, "object identifer"))
      End If
      If bShpFldExist = False Then
        pFieldsEdit = pFields
        pFieldsEdit.AddField(CreateGeometryField(geomType, GridSize, 0, bHasM, bHasZ, SpatialRef, ShpFldName))
      End If

      ' set up the class extension
      If (pCLSEXT Is Nothing) Then
        pCLSEXT = Nothing
      End If

      ' find the shape field
      Dim strShapeFld As String
      For i = 0 To pFields.FieldCount - 1
        If pFields.Field(i).Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then
          strShapeFld = pFields.Field(i).Name
        End If
      Next
      pFeatureClass = pFDS.CreateFeatureClass(strName, pFields, pCLSID, pCLSEXT, featType, strShapeFld, strConfigWord)
      pClassSchemaEdit = pFeatureClass
      pClassSchemaEdit.AlterAliasName(strName)
    Catch ex As Exception
      pFeatureClass = Nothing
    End Try

    Return pFeatureClass
  End Function

  Public Shared Function CreateIFieldsForFeatureClass(ByVal featType As ESRI.ArcGIS.Geodatabase.esriFeatureType, Optional ByVal geomType As ESRI.ArcGIS.Geometry.esriGeometryType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint, _
  Optional ByVal pFields As ESRI.ArcGIS.Geodatabase.IFields = Nothing, Optional ByVal pCLSID As ESRI.ArcGIS.esriSystem.UID = Nothing, _
  Optional ByVal pCLSEXT As ESRI.ArcGIS.esriSystem.UID = Nothing, Optional ByVal strConfigWord As String = "", _
  Optional ByVal OIDFldName As String = "OID", Optional ByVal ShpFldName As String = "Shape", _
  Optional ByVal SpatialRef As ISpatialReference = Nothing, Optional ByVal bHasM As Boolean = False, _
  Optional ByVal bHasZ As Boolean = False, Optional ByVal GridSize As Double = 0) As IFields
    '*****************************************************************
    ' Copyright, 2004 ESRI, All Rights Reserved.
    '*****************************************************************
    'Description:
    'History: ye 02-12-2004 @ 10:14:46
    '*****************************************************************
    Try
      If geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryAny Then
        geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint
      End If
      If (pCLSID Is Nothing) Then
        pCLSID = Nothing
        pCLSID = New UID
        If featType = 0 Then
          featType = ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple 'esriFTSimple
        End If
        Select Case featType
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple
            pCLSID.Value = "esriGeoDatabase.Feature"
            If geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryLine Then geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleJunction
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint
            pCLSID.Value = "esriGeoDatabase.SimpleJunctionFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTComplexJunction
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint
            pCLSID.Value = "esriGeoDatabase.ComplexJunctionFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleEdge
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline
            pCLSID.Value = "esriGeoDatabase.SimpleEdgeFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTComplexEdge
            geomType = ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline
            pCLSID.Value = "esriGeoDatabase.ComplexEdgeFeature"
          Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTAnnotation

        End Select
      End If

      ' set up a simple fields collection
      Dim pFieldsEdit As ESRI.ArcGIS.Geodatabase.IFieldsEdit
      If (pFields Is Nothing) Then
        pFieldsEdit = New ESRI.ArcGIS.Geodatabase.Fields  'esriGeoDatabase.Fields
        pFieldsEdit.AddField(CreateGeometryField(geomType, GridSize, 0, bHasM, bHasZ, SpatialRef, ShpFldName))
        pFieldsEdit.AddField(CreateField(OIDFldName, ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID, "object identifer"))
        pFields = pFieldsEdit
      End If

      '..Make sure OID field and ShapeField exist in the pFields
      Dim pField As IField
      Dim bOIDFldExist As Boolean
      Dim bShpFldExist As Boolean

      bShpFldExist = False
      bOIDFldExist = False
      Dim i As Integer

      For i = 0 To pFields.FieldCount - 1 ' pField In pFields
        pField = pFields.Field(i)
        If pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID Then
          bOIDFldExist = True
        End If
        If pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then
          bShpFldExist = True
        End If
        If bOIDFldExist = True And bShpFldExist = True Then
          Exit For
        End If
      Next
      If bOIDFldExist = False Then
        pFieldsEdit = pFields
        pFieldsEdit.AddField(CreateField(OIDFldName, ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID, "object identifer"))
      End If
      If bShpFldExist = False Then
        pFieldsEdit = pFields
        pFieldsEdit.AddField(CreateGeometryField(geomType, GridSize, 0, bHasM, bHasZ, SpatialRef, ShpFldName))
      End If

      ' set up the class extension
      If (pCLSEXT Is Nothing) Then
        pCLSEXT = Nothing
      End If

      ' find the shape field
      Dim strShapeFld As String
      For i = 0 To pFields.FieldCount - 1
        If pFields.Field(i).Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then
          strShapeFld = pFields.Field(i).Name
        End If
      Next
    Catch ex As Exception
      pFields = Nothing
    End Try

    Return pFields
  End Function

  Public Shared Function CreateField(ByVal strName As String, ByVal FieldType As ESRI.ArcGIS.Geodatabase.esriFieldType, _
  Optional ByVal strAliasName As String = "", Optional ByVal geoDef As IGeometryDef = Nothing, _
  Optional ByVal blnNullable As Boolean = True, Optional ByVal intLength As Integer = 10, _
  Optional ByVal intPrecision As Integer = 10) As IField

    Dim pField As IField
    Dim pFieldEdit As IFieldEdit
    Dim pFieldEdit2 As IFieldEdit2
    Try
      pField = New ESRI.ArcGIS.Geodatabase.Field
      pFieldEdit = pField
      pFieldEdit2 = pField
      ' do the manditory values first
      pFieldEdit2.Name_2 = strName
      pFieldEdit2.Type_2 = FieldType
      ' fill in the optional information
      If strAliasName = "" Then
        pFieldEdit.AliasName_2 = strName
      End If
      ' the oid must always contain a value
      If Not FieldType = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID Then
        pFieldEdit.IsNullable_2 = blnNullable
      End If

      If Not FieldType = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then
        pFieldEdit.Length_2 = intLength
        pFieldEdit.Precision_2 = intPrecision
      End If

      If FieldType = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry Then
        If (Not geoDef Is Nothing) Then
          pFieldEdit.GeometryDef_2 = geoDef
        End If
      End If

    Catch ex As Exception
      pField = Nothing
    End Try
    Return pField
  End Function
  Public Shared Function CreateGeometryField(ByVal geomType As ESRI.ArcGIS.Geometry.esriGeometryType, Optional ByVal GridSize As Double = 0, _
  Optional ByVal avgNumPts As Integer = 0, Optional ByVal hasM As Boolean = False, _
  Optional ByVal hasZ As Boolean = False, Optional ByVal SpatialRef As ISpatialReference = Nothing, _
  Optional ByVal ShpFldName As String = "Shape") As IField
    '*****************************************************************
    ' Copyright, 2002 ESRI, All Rights Reserved.
    '*****************************************************************
    'Description: Create a Geometryfield object.
    'History: zye 12-01-2002 @ 14:20:24
    '*****************************************************************

    Dim pGeomDef As IGeometryDef
    Dim pGeomDefEdit As IGeometryDefEdit
    Dim xMin As Double
    Dim yMin As Double
    Dim xMax As Double
    Dim yMax As Double
    Dim dx As Double
    Dim dy As Double
    Dim pField As IField
    Try
      pGeomDef = New ESRI.ArcGIS.Geodatabase.GeometryDef
      pGeomDefEdit = pGeomDef
      If GridSize = 0 Then
        If Not SpatialRef Is Nothing Then
          Select Case True
            Case TypeOf SpatialRef Is IProjectedCoordinateSystem
              SpatialRef.GetDomain(xMin, xMax, yMin, yMax)
              dx = Math.Abs(xMax - xMin)
              dy = Math.Abs(yMax - yMin)
              dx = IIf(dx > dy, dx, dy)
              GridSize = dx / 50
              GridSize = IIf(GridSize > 5000, GridSize, 5000)
            Case TypeOf SpatialRef Is IGeographicCoordinateSystem
              GridSize = 10
            Case TypeOf SpatialRef Is IGeographicCoordinateSystem2
              GridSize = 10
            Case Else
              GridSize = 5000
          End Select
        Else
          GridSize = 5000
        End If
      End If
      With pGeomDefEdit
        .GeometryType_2 = geomType
        .GridCount_2 = 1
        If GridSize <> 0 Then
          .GridSize_2(0) = GridSize
        End If
        If avgNumPts <> 0 Then
          .AvgNumPoints_2 = avgNumPts
        Else
          .AvgNumPoints_2 = 2
        End If
        .HasM_2 = hasM
        .HasZ_2 = hasZ
      End With

      If Not SpatialRef Is Nothing Then
        pGeomDefEdit.SpatialReference_2 = SpatialRef
      End If
      pField = CreateField(ShpFldName, ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry, , pGeomDef)
    Catch ex As Exception
      pField = Nothing
    End Try
    Return pField
  End Function
  Public Shared Function CopyFeatureClass(ByVal pSourceFeatureClass As IFeatureClass, ByVal TargetDataSetName As String, ByVal pTargetWorkSpace As IWorkspace, ByVal pFields As IFields) As IFeatureClass
    '*****************************************************************
    ' Copyright, 2001 ESRI, All Rights Reserved.
    '*****************************************************************
    'Description:
    '..pSourceFeatureClass=FeatureClass to be copied.
    '..sTargetDatasetName=TargetDataset under which the Source is to be copied.
    '..TargetFeatureClassName=TargetFeatureClassName, if="", use pFeatureClassSource.AliasName
    '..pTargetWorkSpace=TargetWorkSpace, if = nothing, use the same WKS as the source.
    '  UseExistingLayer=0  'When target layer exists, prompt user if the layer should be deleted.
    '  =1 'Silently append all the records from source to target.
    '  =2 'silently remove all the existing records in the TargetLayer and copy the recs from source to it.
    'History: zye 10-16-2001 @ 14:49:15
    '*****************************************************************
    Dim pTargetDataset As IFeatureDataset
    Dim pTargetFeatureClass As IFeatureClass
    Dim pID As New UID
    Dim sName As String
    Dim pClone As IClone
    Dim pFWKS As IFeatureWorkspace
    Dim ds As Long = Date.Now.Ticks
    '..Chk to see if the TargetDataset exist.
    Try
      pFWKS = pTargetWorkSpace
      sName = GetBaseName(pSourceFeatureClass.AliasName)
      pTargetFeatureClass = Try2OpenFeatureClass(pTargetWorkSpace, sName)
      If (pTargetFeatureClass Is Nothing) Then
        If TargetDataSetName = "" Then
          pTargetDataset = Nothing
        Else
          '..Chk to see if TargetDataset exist.
          TargetDataSetName = GetBaseName(TargetDataSetName)
          pTargetDataset = GetpDataset(pTargetWorkSpace, TargetDataSetName, ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTFeatureDataset)
          If pTargetDataset Is Nothing Then
            Dim pSpRef As ISpatialReference
            If Not pSourceFeatureClass.FeatureDataset Is Nothing Then
              Dim pGeodataset As IGeoDataset
              pGeodataset = pSourceFeatureClass
              pSpRef = pGeodataset.SpatialReference
              pTargetDataset = CreateDataset(TargetDataSetName, pTargetWorkSpace, pSpRef)
            End If
          End If
        End If
        If (pFields Is Nothing) Then
          pFields = pSourceFeatureClass.Fields
          pClone = pFields
          pFields = pClone.Clone
        End If
        If Not pTargetDataset Is Nothing Then
          pTargetFeatureClass = pTargetDataset.CreateFeatureClass(sName, pFields, pSourceFeatureClass.CLSID, pSourceFeatureClass.EXTCLSID, pSourceFeatureClass.ShapeType, pSourceFeatureClass.ShapeFieldName, "")
        Else
          pTargetFeatureClass = pFWKS.CreateFeatureClass(sName, pFields, pSourceFeatureClass.CLSID, pSourceFeatureClass.EXTCLSID, pSourceFeatureClass.ShapeType, pSourceFeatureClass.ShapeFieldName, "")
        End If
      End If
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("CopyFeatureClass:" & ex.Message & ", " & ex.StackTrace, True, -1, False)
      End If
      pTargetFeatureClass = Nothing
    Finally
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogDSTime) = ApSConfigAHS.DebugType.LogDSTime) Then
        ApSConfigAHS.Write2Log("CopyFeatureClass:", True, ds, False)
      End If

    End Try
    Return pTargetFeatureClass

  End Function
  Public Shared Function CreateDataset(ByVal Name As String, ByVal WorkSpace As IWorkspace, _
    ByVal pSR As ESRI.ArcGIS.Geometry.ISpatialReference) As IFeatureDataset
    '*****************************************************************
    ' Copyright, 2001 ESRI, All Rights Reserved.
    '*****************************************************************
    'Description:  Create a FeatureDataset under the pWorkSpace.
    '  Note: There is a potential problem with Coordinate system.
    '    if pSR is a ProjectedCoordinateSystem, we are ok.
    '    if pSR is a GeographicCoordinateSystem, the code needs modification.
    '  IClone should be the interface to use, such as:
    '     Set pclone = pSR
    '     Set pSRCopy = pclone.Clone
    'History: zye 08-10-2001 @ 15:14:57
    '*****************************************************************
    '..Dim pSpRFc2 As ISpatialReferenceFactory2
    Dim pFD As IFeatureDataset
    Try
      ' if the spatial reference is not passed in, then create an unknown one here
      '..Set pSpRFc2 = New SpatialReferenceEnvironment
      Dim pSRCopy As ISpatialReference
      '..If there is a reference passed in, use it.
      Dim pClone As IClone
      pClone = pSR
      pSRCopy = pClone.Clone
      '..If trying to create pSRCopy failed, then, use the following code.
      If pSRCopy Is Nothing Then
        pSRCopy = New ESRI.ArcGIS.Geometry.UnknownCoordinateSystem
        pSRCopy.SetDomain(-1000000.0#, 2000000.0#, -1000000.0#, 2000000.0#)
        pSRCopy.SetFalseOriginAndUnits(-1000000.0#, -1000000.0#, 1)
        pSRCopy.SetMDomain(0, 21474.83645)
        pSRCopy.SetZDomain(-1000000, 21474.83645)
        pSRCopy.SetZFalseOriginAndUnits(0, 100000)
      End If

      Dim pFeatureWorkspace As ESRI.ArcGIS.Geodatabase.IFeatureWorkspace
      pFeatureWorkspace = WorkSpace
      ' create the feature dataset
      pFD = pFeatureWorkspace.CreateFeatureDataset(Name, pSRCopy)
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("CreateDataset:" & ex.Message & ", " & ex.StackTrace, True, -1, False)
      End If
      pFD = Nothing
    End Try
    Return pFD
  End Function
  Public Shared Function GetpDataset(ByVal pWorkspace As IWorkspace, ByVal strDatasetName As String, ByVal intDataType As ESRI.ArcGIS.Geodatabase.esriDatasetType) As IDataset
    '*****************************************************************
    ' Copyright, 2001 ESRI, All Rights Reserved.
    '*****************************************************************
    'Description: Returns a Dataset of intDataType in the pWorkSpace
    'History: zye 08-03-2001 @ 11:07:50
    '*****************************************************************
    Dim pEnumDataset As IEnumDataset    '..Holds all the datasets under the WorkSpace
    Dim pDataset As IDataset            '..LoopingVariable holding dataset
    Dim pDataSetReturn As IDataset = Nothing       '..The Found dataset.
    Dim UserDataSetName As String
    Dim sBaseName As String
    Try
      pEnumDataset = pWorkspace.Datasets(intDataType)
      UserDataSetName = UCase(strDatasetName)
      sBaseName = GetBaseName(strDatasetName)
      pDataset = pEnumDataset.Next
      Do Until (pDataset Is Nothing)
        '..Debug.Print pDataSet.FullName.NameString & ", " & pDataSet.Name & ", " & pDataSet.Type
        If (UCase(Trim(pDataset.Name)) = UserDataSetName) Or (UCase(Trim(pDataset.Name)) = sBaseName) Then
          pDataSetReturn = pDataset
          Exit Do
        End If
        pDataset = pEnumDataset.Next
      Loop
    Catch ex As Exception
      pDataSetReturn = Nothing
    End Try

    Return pDataSetReturn

  End Function
  ''' <summary>
  ''' Given FromTable, ToTable, create a webfields whose 
  ''' index=fieldindex on the from table, and toIndex = fieldindex in the totable.
  ''' name = fromtable's field name, Alias = totable's field name.
  ''' </summary>
  ''' <param name="FromTable"></param>
  ''' <param name="ToTable"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function MakeApWebFields(ByVal FromTable As ITable, ByVal ToTable As ITable, Optional ByVal bWritableOnly As Boolean = True) As ApWebFields
    Dim pField As IField
    Dim nFlds As Integer
    Dim i As Integer
    Dim ifld As Integer
    Dim pApWebFields As New ApWebFields
    Dim pApWebField As ApWebField
    Dim sName As String
    Dim bCanAdd As Boolean = True
    Try
      nFlds = FromTable.Fields.FieldCount
      For i = 0 To nFlds - 1
        pField = FromTable.Fields.Field(i)
        If (bWritableOnly = True) Then
          If ((pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeBlob) OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry) _
            OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGlobalID) OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGUID) _
            OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeRaster)) Then
            bCanAdd = False
          Else
            bCanAdd = True
          End If
        Else
          bCanAdd = True
        End If
        If bCanAdd = True Then
          sName = pField.Name
          pApWebField = New ApWebField
          pApWebField.Name = sName
          pApWebField.Index = i
          ifld = ToTable.Fields.FindField(sName)
          pApWebField.ToIndex = ifld
          pApWebFields.Add(pApWebField.Name, pApWebField)
        End If
      Next
    Catch ex As Exception
      pApWebFields = Nothing
    End Try
    Return pApWebFields

  End Function
  Public Shared Function CopyFeature(ByVal pRowFrom As IRow, ByVal pRowTo As IRow) As Boolean
    Return CopyFeature(pRowFrom, pRowTo, Nothing)
  End Function
  Public Shared Function CopyFeature(ByVal pRowFrom As IRow, ByVal pRowTo As IRow, _
    ByVal pApWebFields As ApWebFields) As Boolean
    Dim pField As IField
    Dim nFlds As Integer
    Dim i As Integer
    Dim ifld As Integer
    Dim pApWebField As ApWebField
    Dim ds As Long = Date.Now.Ticks
    Dim bCanAdd As Boolean = True
    Dim pFeatureFrom As IFeature
    Dim pFeatureTo As IFeature
    Try
      If pApWebFields Is Nothing Then
        nFlds = pRowFrom.Fields.FieldCount
        For i = 0 To nFlds - 1
          pField = pRowFrom.Fields.Field(i)
          If ((pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeBlob) OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry) _
              OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGlobalID) OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGUID) _
              OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeRaster) OrElse (pField.Type = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID)) Then
            bCanAdd = False
          Else
            bCanAdd = True
          End If
          If (bCanAdd = True) Then
            ifld = pRowTo.Fields.FindField(pField.Name)
            If ifld >= 0 Then
              Try
                pRowTo.Value(ifld) = pRowFrom.Value(i)
              Catch ex As Exception

              End Try
            End If
          End If
        Next
        If (TypeOf pRowFrom Is IFeature) AndAlso (TypeOf pRowTo Is IFeature) Then
          pFeatureFrom = pRowFrom
          pFeatureTo = pRowTo
          pFeatureTo.Shape = pFeatureFrom.Shape
        End If

      Else
        For Each pApWebField In pApWebFields.Values
          If ((pApWebField.Index >= 0) And (pApWebField.ToIndex >= 0)) Then
            Try
              pRowTo.Value(pApWebField.ToIndex) = pRowFrom.Value(pApWebField.Index)
            Catch ex As Exception

            End Try
          End If
        Next
      End If
      bCanAdd = True
    Catch ex As Exception
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("CopyFeature:" & ex.Message & ", " & ex.StackTrace, True, -1, False)
      End If
      bCanAdd = False
    Finally
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogDSTime) = ApSConfigAHS.DebugType.LogDSTime) Then
        ApSConfigAHS.Write2Log("CopyFeature:", True, ds, False)
      End If
    End Try
    Return bCanAdd
  End Function
  Public Overloads Shared Function GetBaseName(ByVal sName As String) As String
    Dim sNames() As String
    Dim sBaseName As String
    Try
      sNames = sName.Split(".")
      sBaseName = sNames(sNames.Length - 1)
    Catch ex As Exception
      sBaseName = sName
    End Try
    Return sBaseName
  End Function
  ''' <summary>
  '''  Parse the date from mm-dd-yyyy to standard yyyy/mm/dd format.
  ''' </summary>
  ''' <param name="sDate"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function ToRegularDate(ByVal sDate As String) As String
    Dim sReturn As String = ""
    Dim sDateN As String
    Dim s() As String
    Dim s1() As String
    Try
      s1 = sDate.Split("T")
      sDateN = s1(0)
      s = sDateN.Split("-")
      If (s.Length = 3) Then
        'nYr = CType(s(0), Integer)
        sReturn = s(1).Trim & "/" & s(2).Trim & "/" & s(0)
      Else
        sReturn = sDateN
      End If
    Catch ex As Exception
      sReturn = sDate
    End Try
    Return sReturn
  End Function
  ''' <summary>
  ''' Args= , _, _startDate, _endDate, ""
  ''' </summary>
  ''' <param name="oNetWork"></param>
  ''' <param name="location"> network & ":" & siteID</param>
  ''' <param name="variable"> network & ":" & varCode</param>
  ''' <param name="startDate"></param>
  ''' <param name="endDate"></param>
  ''' <param name="authToken"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetTSFromWS(ByVal oNetWork As HISNetwork, ByVal location As String, ByVal variable As String, ByVal startDate As String, ByVal endDate As String, ByVal authToken As String) As String
    Dim TSReturn As String
    'Dim wsProxyIID As edu.sdsc.water.NWISInstantaneousIrregularData
    Dim wsProxy As New edu.sdsc.water.NWISDailyValues
    Try
      wsProxy.Url = oNetWork.WebServiceURL
      TSReturn = wsProxy.GetValues(location, variable, startDate, endDate, "")
    Catch ex As Exception
      'Try
      '  wsProxyIID = New edu.sdsc.water.NWISInstantaneousIrregularData
      '  TSReturn = wsProxyIID.GetValues(location, variable, startDate, endDate, "")
      'Catch ex1 As Exception
      '  ApSConfigAHS.Write2Log("GetTSFromWS: " & ex1.Message & ", " & ex1.StackTrace, True, -1, False)
      '  TSReturn = ApSConfigAHS.K_TagError & "Error Accessing Values:" & ex1.Message & ApSConfigAHS.K_TagErrorEnd
      'End Try
      TSReturn = ApSConfigAHS.K_TagError & "Error Accessing Values:" & ex.Message & ApSConfigAHS.K_TagErrorEnd
    End Try
    Return TSReturn
  End Function
  Public Shared Function OpenDBReader(ByVal sCon As String, ByVal sSQL As String) As System.Data.IDataReader
    Dim pDataReader As IDataReader
    Dim pOLEDBCon As OleDb.OleDbConnection
    Dim pOleDBCmd As OleDb.OleDbCommand
    Try
      pOLEDBCon = New OleDb.OleDbConnection
      pOLEDBCon.ConnectionString = sCon
      pOleDBCmd = New OleDb.OleDbCommand
      pOleDBCmd.CommandType = CommandType.Text
      pOleDBCmd.CommandText = sSQL
      pOleDBCmd.Connection = pOLEDBCon
      pOLEDBCon.Open()
      pDataReader = pOleDBCmd.ExecuteReader()
    Catch ex As Exception
      pDataReader = Nothing
    Finally
      If Not pOleDBCmd Is Nothing Then
        pOleDBCmd.Dispose()
      End If
      If Not pOleDBCon Is Nothing Then
        If ((pOleDBCon.State = ConnectionState.Open) OrElse (pOleDBCon.State = ConnectionState.Connecting) OrElse (pOleDBCon.State = ConnectionState.Executing) OrElse (pOleDBCon.State = ConnectionState.Fetching)) Then
          pOLEDBCon.Close()
          pOLEDBCon.Dispose()
        End If
      End If
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogDSTime) = ApSConfigAHS.DebugType.LogDSTime) Then
        'ApSConfigAHS.Write2Log("GetAddToCartDB:", True, ds, False)
      End If
    End Try
    Return pDataReader
  End Function
  ''' <summary>
  '''  returns the value of FieldName, whose username=sUserName
  ''' </summary>
  ''' <param name="sUserName"></param>
  ''' <param name="sFieldName"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function GetUserInfo(ByVal sUserName As String, ByVal sFieldName As String) As String
    Dim sCon As String
    'Dim sSQL As String
    Dim sReturn As String
    Try
      sCon = ConfigurationManager.ConnectionStrings(DB_AppDB).ConnectionString
      'sSQL = "SELECT " & sFieldName & " FROM " & TB_MembershipUsers & " WHERE " & FD_UserName & "='" & sUserName & "'"
      sReturn = GetFieldValue(sCon, TB_MembershipUsers, FD_UserName, "'" & sUserName & "'", FD_Email, True, "")
    Catch ex As Exception
      sReturn = ""
    Finally
    End Try
    Return sReturn
  End Function
  Public Shared Function SendEmail(ByVal sUserName As String, ByVal sMsg As String, ByVal sSubject As String) As String
    Dim sToEmail As String
    Dim pEmail As System.Net.Mail.MailMessage
    Dim pClient As System.Net.Mail.SmtpClient
    Dim pSmtpSect As System.Net.Configuration.SmtpSection
    Dim sHost As String
    Dim sFromEmail As String
    Try
      sToEmail = GetUserInfo(sUserName, FD_Email)
      If sToEmail <> "" Then
        pSmtpSect = ConfigurationManager.GetSection("system.net/mailSettings/smtp")
        If Not pSmtpSect Is Nothing Then
          sHost = pSmtpSect.Network.Host
          sFromEmail = pSmtpSect.From
          pClient = New System.Net.Mail.SmtpClient(sHost)
          pEmail = New System.Net.Mail.MailMessage(sFromEmail, sToEmail, sSubject, sMsg)
          pClient.Send(pEmail)
        End If
      End If
    Catch ex As Exception
      sToEmail = ""
      If ((ApSConfigAHS.WebDebug And ApSConfigAHS.DebugType.LogError) = ApSConfigAHS.DebugType.LogError) Then
        ApSConfigAHS.Write2Log("SendEmail:" & ex.Message & ", " & ex.StackTrace, True, -1, False)
      End If
    Finally
      pSmtpSect = Nothing
    End Try
    Return sToEmail
  End Function

  Public Shared Sub CheckboxSelectAll(ByVal oPage As System.Web.UI.Page, ByVal GridViewName As String, ByVal CheckBoxName As String, ByVal bChecked As Boolean)
    Dim checkbox As CheckBox = Nothing
    Dim gv As GridView = oPage.FindControl(GridViewName)
    Dim i As Integer
    For i = 0 To gv.Rows.Count - 1
      Try
        checkbox = gv.Rows(i).FindControl(CheckBoxName)
        If Not checkbox Is Nothing Then
          checkbox.Checked = bChecked
        End If
      Catch ex As Exception

      End Try
    Next
  End Sub

  Public Shared Function GetCellIndex(ByVal oPage As System.Web.UI.Page, ByVal GridViewName As String, ByVal CellName As String) As Integer
    Dim iIndex As Integer = -1
    Dim gv As GridView
    Dim n As Integer
    Dim sName As String
    Dim sCellName As String
    Try
      sCellName = CellName.ToLower.Trim
      gv = oPage.FindControl(GridViewName)
      If (Not gv Is Nothing) Then
        n = gv.HeaderRow.Cells.Count
        If n > 0 Then
          Dim i As Integer
          For i = 0 To gv.HeaderRow.Cells.Count - 1
            sName = gv.HeaderRow.Cells(i).Text
            If (sName.ToLower.Trim = sCellName) Then
              iIndex = i
              Exit For
            End If
          Next
        End If
      End If
    Catch ex As Exception
      iIndex = -1
    End Try
    Return iIndex
  End Function
  Public Function GetChildNodeByName(ByVal pNode As System.Xml.XmlNode, ByVal NodeName As String) As System.Xml.XmlNode
    Dim pChildNode As System.Xml.XmlNode = Nothing
    Dim pNodeReturn As System.Xml.XmlNode = Nothing
    Try
      pNodeReturn = pNode.SelectSingleNode(NodeName)
      For Each pChildNode In pNode.ChildNodes
        If (pChildNode.Name = NodeName) Then
          pNodeReturn = pChildNode
          Exit For
        End If
      Next
    Catch ex As Exception

    End Try
    Return pNodeReturn
  End Function
  Public Function GetChildNodeByAttributeName(ByVal pNode As System.Xml.XmlNode, ByVal AttributeName As String, ByVal AttributeValue As String) As System.Xml.XmlNode
    Dim pChildNode As System.Xml.XmlNode = Nothing
    Dim pNodeReturn As System.Xml.XmlNode = Nothing
    Dim pAttribute As System.Xml.XmlAttribute
    Try
      For Each pChildNode In pNode.ChildNodes
        Try
          If (pNode.NodeType = System.Xml.XmlNodeType.Element) Or (pNode.NodeType = System.Xml.XmlNodeType.Entity) Then
            For Each pAttribute In pNode.Attributes
              If (pAttribute.Name = AttributeName) And (pAttribute.Value = AttributeValue) Then
                pNodeReturn = pChildNode
                Exit For
              End If
            Next
          End If
        Catch ex As Exception

        End Try
      Next
    Catch ex As Exception

    End Try
    Return pNodeReturn

  End Function

  Public Sub New()
    MyBase.New()
  End Sub
End Class
