'*****************************************************************
'Copyright © 2006 ESRI. All Rights Reserved.
'*****************************************************************
'Description: Class wrapping the Project
'  It has the capablity to read/load from xml configuration.
'  Implements IMenuType so that the MenuType value can be queried 
'  by whoever needs the info.
'History: z.ye @6/21/2006 4:50:10 PM
'*****************************************************************
Imports System.Xml
Imports System.Reflection
Imports System.Runtime.InteropServices
<Serializable()> Public Class ApWebField
  Implements ICloneable
  Private Const _LoadXMLNode As String = "LoadXMLNode"   'Child Objects need to have LoadXMLNode method:LoadXMLNode(System.XmlNode)
  Private Const _ToXMLNode As String = "ToXMLNode"   'Child Objects need to have LoadXMLNode method:LoadXMLNode(System.XmlNode)
  Private Const _Name As String = "Name"   'Child object need to have Name property = the Name of the parent property refrencing the child object
  Private Const _TagName As String = "TagName"
  Private mName As String = ""
  Private mTagName As String = ""
  Private mDesc As String = ""
  Private mAlias As String = ""
  Private mType As Integer
  Private mIndex As Integer
  Private mToIndex As Integer
  Private mMenuType As Integer     '..MenuType=1,2,4,8 etc.
  Private mExtraParams As String   'params may need
  Private mAllowEdit As Integer = 1   '..Allows editing. 0 = not allow, 1=allow
  Private mLUTable As String
  Private mLUKeyField As String
  Private mLUDispField As String
  Private mValue As String
  Private mApWebFields As ApWebFields
  Private mHISNetworks As HISNetworks
  Private mFieldOrder As Integer = -1     '..Start from 0 (0 based)
  Private bConstValue As Boolean = False
  Public Property ConstValue() As Boolean
    Get
      Return bConstValue
    End Get
    Set(ByVal value As Boolean)
      bConstValue = value
    End Set
  End Property
  Public Property FieldOrder() As Integer
    Get
      Return mFieldOrder
    End Get
    Set(ByVal value As Integer)
      mFieldOrder = value
    End Set
  End Property
  Public Property HISNetworks() As HISNetworks
    Get
      Return mHISNetworks
    End Get
    Set(ByVal Value As HISNetworks)
      mHISNetworks = Value
    End Set
  End Property

  Public Property Value() As String
    Get
      Return mValue
    End Get
    Set(ByVal sValue As String)
      mValue = sValue
    End Set
  End Property
  Public Property AllowEdit() As Integer
    Get
      Return mAllowEdit
    End Get
    Set(ByVal Value As Integer)
      mAllowEdit = Value
    End Set
  End Property
  Public Property LUTable() As String
    Get
      Return mLUTable
    End Get
    Set(ByVal Value As String)
      mLUTable = Value
    End Set
  End Property
  Public Property LUKeyField() As String
    Get
      Return mLUKeyField
    End Get
    Set(ByVal Value As String)
      mLUKeyField = Value
    End Set
  End Property
  Public Property LUDispField() As String
    Get
      Return mLUDispField
    End Get
    Set(ByVal Value As String)
      mLUDispField = Value
    End Set
  End Property
  Public Property Index() As Integer
    Get
      Return mIndex
    End Get
    Set(ByVal Value As Integer)
      mIndex = Value
    End Set
  End Property
  Public Property ToIndex() As Integer
    Get
      Return mToIndex
    End Get
    Set(ByVal Value As Integer)
      mToIndex = Value
    End Set
  End Property

  Public Property ApWebFields() As ApWebFields
    Get
      Return mApWebFields
    End Get
    Set(ByVal Value As ApWebFields)
      mApWebFields = Value
    End Set
  End Property
  Public Property ExtraParams() As String
    Get
      Return mExtraParams
    End Get
    Set(ByVal Value As String)
      mExtraParams = Value
    End Set
  End Property
  Public Property Desc() As String
    Get
      If mDesc = "" Then
        mDesc = Name
      End If
      Return mDesc
    End Get
    Set(ByVal Value As String)
      mDesc = Value
    End Set
  End Property
  Public Property FieldAlias() As String
    Get
      If mAlias = "" Then
        mAlias = Name
      End If
      Return mAlias
    End Get
    Set(ByVal Value As String)
      mAlias = Value
    End Set
  End Property

  Public Property Name() As String
    Get
      If mName = "" Then
        mName = mTagName
      End If
      Return mName
    End Get
    Set(ByVal Value As String)
      mName = Value
    End Set
  End Property

  Public Property TagName() As String
    Get
      If mTagName = "" Then
        mTagName = mName
      End If
      Return mTagName
    End Get
    Set(ByVal Value As String)
      mTagName = Value
    End Set
  End Property
  Public ReadOnly Property Order() As Integer
    Get
      Return mType * 10 + mMenuType
    End Get
  End Property
  Public Property Type() As Integer
    Get
      Return mType
    End Get
    Set(ByVal Value As Integer)
      mType = Value
    End Set
  End Property
  ''' -----------------------------------------------------------------------------
  ''' <summary>
  '''  Write the layer to an xmlnode.
  ''' </summary>
  ''' <param name="pXMLDoc">xmlDocument</param>
  ''' <param name="pNodeParent">xmlnode - the node this layer node will append under</param>
  ''' <returns>xmlnode</returns>
  ''' <remarks>
  ''' </remarks>
  ''' <history>
  ''' 	[ye]	4/21/2006	Created
  ''' </history>
  ''' -----------------------------------------------------------------------------
  Public Function ToXMLNode(ByRef pXMLDoc As XmlDocument, ByVal pNodeParent As XmlNode) As XmlNode
    Dim pNode As XmlNode
    Dim pElem As XmlElement
    Dim pAttribute As XmlAttribute
    Dim pMembers() As System.Reflection.MemberInfo
    Dim pMemberInfo As System.Reflection.MemberInfo
    Dim pFieldInfo As System.Reflection.FieldInfo
    Dim pPropInfo As System.Reflection.PropertyInfo
    Dim pType As Type
    Dim sName As String
    Dim nType As System.Reflection.MemberTypes
    Dim s As String = ""
    Dim bOk As Boolean
    Dim o As Object = Nothing
    Try
      pElem = pXMLDoc.CreateElement([GetType].Name)
      Try
        pMembers = Me.GetType().GetMembers
        pType = Me.GetType
        For Each pMemberInfo In pMembers
          sName = pMemberInfo.Name
          nType = pMemberInfo.MemberType
          If pMemberInfo.MemberType = Reflection.MemberTypes.Property Or pMemberInfo.MemberType = MemberTypes.Field Then
            Try
              If pMemberInfo.MemberType = Reflection.MemberTypes.Property Then
                pPropInfo = Me.GetType.GetProperty(sName)
                o = pPropInfo.GetValue(Me, Nothing)  ' pType.InvokeMember(pMemberInfo.Name, Reflection.BindingFlags.GetProperty, Nothing, Me, Nothing, Nothing)
              ElseIf pMemberInfo.MemberType = Reflection.MemberTypes.Field Then
                pFieldInfo = Me.GetType.GetField(sName)
                o = pFieldInfo.GetValue(Me)
              End If
              bOk = ApSConfigAHS.IsTypeObject(o, s)
              If bOk = False Then
                pAttribute = pXMLDoc.CreateAttribute(sName)
                pAttribute.Value = s
                pElem.Attributes.Append(pAttribute)
              Else
                If Not o Is Nothing Then
                  Dim pMethodInfo As System.Reflection.MethodInfo
                  Dim oVals(1) As Object
                  pNode = pElem
                  pMethodInfo = o.GetType.GetMethod(_ToXMLNode)
                  If Not pMethodInfo Is Nothing Then
                    oVals(0) = pXMLDoc
                    oVals(1) = pNode
                    pMethodInfo.Invoke(o, BindingFlags.Instance, Nothing, oVals, Nothing)
                  End If
                End If
              End If
            Catch ex As Exception
              'MsgBox("1. " & ex.ToString)
            End Try

          End If
        Next
      Catch ex As Exception
        'MsgBox("2. " & ex.ToString)
      End Try
      '..Get all the properties that is not object and add them as attributes for the 
      '..Get all the object properties of the layer and add it as child node.
      pNode = pElem
      If Not pNodeParent Is Nothing Then
        pNodeParent.AppendChild(pNode)
      Else
        pXMLDoc.AppendChild(pNode)
      End If
    Catch ex As Exception
      pNode = Nothing
    End Try
    Return pNode
  End Function
  ''' -----------------------------------------------------------------------------
  ''' <summary>
  '''   Load properties from an xml node.
  ''' </summary>
  ''' <param name="pNode"></param>
  ''' <returns>true - if ok, false if not</returns>
  ''' <remarks>
  ''' </remarks>
  ''' <history>
  ''' 	[ye]	4/12/2006	Created
  ''' </history>
  ''' -----------------------------------------------------------------------------
  Public Function LoadXMLNode(ByVal pNode As XmlNode) As Boolean
    Dim pAttribute As XmlAttribute
    Dim pPropInfo As System.Reflection.PropertyInfo
    Dim pType As Type
    Dim oVals(0) As Object
    Dim intVals(0) As Integer
    Dim pChildNode As XmlNode
    Dim bOk As Boolean
    Dim pFieldInfo As System.Reflection.FieldInfo
    Dim pMethodInfo As System.Reflection.MethodInfo
    Try
      pType = Me.GetType
      For Each pAttribute In pNode.Attributes
        Try
          pPropInfo = Me.GetType.GetProperty(pAttribute.Name)
          oVals(0) = pAttribute.Value
          If Not pPropInfo Is Nothing Then
            If pPropInfo.CanWrite = True Then
              Try
                Select Case pPropInfo.PropertyType.Name
                  Case "Object"
                    pType.InvokeMember(pAttribute.Name, BindingFlags.Default Or BindingFlags.SetProperty, Nothing, Me, oVals, Nothing)
                  Case "String"
                    pPropInfo.SetValue(Me, CType(pAttribute.Value, String), Nothing)
                  Case "Int32", "Int16", "Integer", "Int64"
                    pPropInfo.SetValue(Me, CInt(pAttribute.Value), Nothing)
                  Case "Single"
                    pPropInfo.SetValue(Me, CType(pAttribute.Value, Single), Nothing)
                  Case "Double", "Decimal"
                    pPropInfo.SetValue(Me, CType(pAttribute.Value, Double), Nothing)
                  Case "String"
                    pPropInfo.SetValue(Me, pAttribute.Value, Nothing)
                  Case "DateTime"
                    pPropInfo.SetValue(Me, CType(pAttribute.Value, DateTime), Nothing)
                  Case "Boolean"
                    pPropInfo.SetValue(Me, CType(pAttribute.Value, Boolean), Nothing)
                End Select
                'System.Diagnostics.Debug.WriteLine(pPropInfo.Name & ", " & pPropInfo.GetSetMethod.Name & ", " & pPropInfo.GetHashCode & ", " & (pPropInfo.GetType.Equals(GetType(Integer))) & ", " & pPropInfo.GetType.Name)
              Catch ex As Exception
                'pPropInfo.SetValue(Me, CInt(pAttribute.Value), Nothing)
              End Try
            End If
          Else
            pFieldInfo = Me.GetType.GetField(pAttribute.Name)
            If Not pFieldInfo Is Nothing Then
              Try
                Select Case pFieldInfo.FieldType.Name
                  Case "Object"
                    pType.InvokeMember(pAttribute.Name, BindingFlags.Default Or BindingFlags.SetField, Nothing, Me, oVals, Nothing)
                  Case "String"
                    pFieldInfo.SetValue(Me, CType(pAttribute.Value, String))
                  Case "Int32", "Int16", "Integer", "Int64"
                    pFieldInfo.SetValue(Me, CInt(pAttribute.Value))
                  Case "Single"
                    pFieldInfo.SetValue(Me, CType(pAttribute.Value, Single))
                  Case "Double", "Decimal"
                    pFieldInfo.SetValue(Me, CType(pAttribute.Value, Double))
                  Case "String"
                    pFieldInfo.SetValue(Me, pAttribute.Value)
                  Case "DateTime"
                    pFieldInfo.SetValue(Me, CType(pAttribute.Value, DateTime))
                  Case "Boolean"
                    pFieldInfo.SetValue(Me, CType(pAttribute.Value, Boolean))
                End Select
              Catch ex As Exception

              End Try
            End If
          End If
        Catch ex As Exception
          System.Diagnostics.Debug.WriteLine(ex.ToString)
        End Try
      Next
      Dim oChild As Object
      Dim sName As String
      If pNode.HasChildNodes = True Then
        For Each pChildNode In pNode.ChildNodes
          Try
            oChild = Activator.CreateInstance(System.Type.GetType(pChildNode.Name))
          Catch ex As Exception
            oChild = Activator.CreateInstance(System.Type.GetType(ApSConfigAHS.getAppNameBase() & "." & pChildNode.Name))
          End Try
          If Not oChild Is Nothing Then
            pMethodInfo = oChild.GetType.GetMethod(_LoadXMLNode)   '  "LoadXMLNode")
            If Not pMethodInfo Is Nothing Then
              oVals(0) = pChildNode
              pMethodInfo.Invoke(oChild, BindingFlags.Instance, Nothing, oVals, Nothing)
              pPropInfo = oChild.GetType.GetProperty(_Name)   '"Name")
              If Not pPropInfo Is Nothing Then
                sName = pPropInfo.GetValue(oChild, Nothing)
                pPropInfo = Me.GetType.GetProperty(sName)
                If Not pPropInfo Is Nothing Then
                  oVals(0) = oChild
                  pType.InvokeMember(sName, BindingFlags.Default Or BindingFlags.SetProperty, Nothing, Me, oVals, Nothing)
                End If
              End If
            End If
          End If
        Next
      End If
      bOk = True
    Catch ex As Exception
      bOk = False
    End Try
    Return bOk
  End Function
  Public Shadows Function ToString() As String
    Return Me.Desc
  End Function
  Public Property Text() As String
    Get
      If Me.Desc = "" Then
        Me.Desc = Me.Value
      End If
      Return Me.Desc
    End Get
    Set(ByVal Value As String)
      Desc = Value
    End Set
  End Property

  Public Function Clone() As Object Implements System.ICloneable.Clone
    Dim pField As ApWebField = New ApWebField
    With pField
      .Name = Me.Name
      .TagName = Me.TagName
      .FieldAlias = Me.FieldAlias
      .Desc = Me.Desc
      .Index = Me.Index
      .Value = Me.Value
      .ApWebFields = Me.ApWebFields
      .AllowEdit = Me.AllowEdit
      .Type = Me.Type
      .LUKeyField = Me.LUKeyField
      .LUTable = Me.LUTable
      .LUDispField = Me.LUDispField
      .Text = Me.Text
      .Value = Me.Value
    End With
    Return pField
  End Function
  Public Sub New()

  End Sub
End Class
