PageRenderTime 30ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/ProtoXML/ProtoFile.vb

#
Visual Basic | 344 lines | 330 code | 14 blank | 0 comment | 1 complexity | aa985fa624605732e91804d40673cab6 MD5 | raw file
Possible License(s): GPL-2.0
  1. Imports System.Xml
  2. Imports System.Text
  3. Public Class ProtoFile
  4. Implements IProtoXFile
  5. Public Sub New(ByVal NodeName As String)
  6. Me.NodeName = NodeName
  7. End Sub
  8. Public Property Doc As System.Xml.Linq.XDocument = <?xml version="1.0" encoding="UTF-8" standalone="yes"?><tvshow></tvshow> Implements IProtoXFile.Doc
  9. Public Property CacheDoc As System.Xml.Linq.XDocument = <?xml version="1.0" encoding="UTF-8" standalone="yes"?><tvshow></tvshow> Implements IProtoXFile.CacheDoc
  10. Private _node As XElement = Doc.Root
  11. Public Property Node As System.Xml.Linq.XElement Implements IProtoXBase.Node
  12. Get
  13. Return _node
  14. End Get
  15. Set(ByVal value As System.Xml.Linq.XElement)
  16. _node = value
  17. End Set
  18. End Property
  19. Private _cacheNode As XElement = CacheDoc.Root
  20. Public Property CacheNode As System.Xml.Linq.XElement Implements IProtoXBase.CacheNode
  21. Get
  22. Return _cacheNode
  23. End Get
  24. Set(value As System.Xml.Linq.XElement)
  25. _cacheNode = value
  26. End Set
  27. End Property
  28. Public Property NodeName As String Implements IProtoXBase.NodeName
  29. Get
  30. Return _node.Name.ToString
  31. End Get
  32. Set(ByVal value As String)
  33. _node.Name = value
  34. _cacheNode.Name = value
  35. End Set
  36. End Property
  37. Friend Sub AddChildForLoad(ByRef NewChild As IProtoXChild) Implements IProtoXBase.AddChildForLoad
  38. If Me.ChildrenLookup.ContainsKey(NewChild.NodeName) Then
  39. Throw New Exception("Already contains lookup for this node name)")
  40. End If
  41. Me.ChildrenLookup.Add(NewChild.NodeName, NewChild)
  42. End Sub
  43. Friend Property ChildrenLookup As New System.Collections.Generic.Dictionary(Of String, IProtoXChild) Implements IProtoXBase.ChildrenLookup
  44. Public Property IsCache As Boolean
  45. #Region "File Access"
  46. Private _NfoFilePath As String
  47. Public Property NfoFilePath As String Implements IProtoXFile.NfoFilePath
  48. Get
  49. Return _NfoFilePath
  50. End Get
  51. Set(ByVal value As String)
  52. If _NfoFilePath <> value And _NfoFilePath IsNot Nothing Then Me.IsAltered = True
  53. Dim Parts() As String
  54. Parts = value.Split("\")
  55. _FolderPath = Parts(0)
  56. For I = 1 To Parts.GetUpperBound(0) - 1
  57. _FolderPath &= "\" & Parts(I)
  58. Next
  59. _FolderPath &= "\"
  60. _NfoFilePath = value
  61. EditAttribute("NfoPath", _NfoFilePath)
  62. End Set
  63. End Property
  64. Protected Friend Sub EditAttribute(ByVal Name As String, ByVal Value As String)
  65. If Me.Node.Attribute(Name) Is Nothing Then
  66. If Value IsNot Nothing Then
  67. Me.Node.Add(New XAttribute(Name, Value))
  68. Else
  69. Exit Sub
  70. End If
  71. Else
  72. If Value Is Nothing Then
  73. Me.Node.Attribute(Name).Remove()
  74. Exit Sub
  75. End If
  76. End If
  77. Me.Node.Attribute(Name).SetValue(Value)
  78. If Me.CacheNode.Attribute(Name) Is Nothing Then
  79. If Value IsNot Nothing Then
  80. Me.CacheNode.Add(New XAttribute(Name, Value))
  81. Else
  82. Exit Sub
  83. End If
  84. Else
  85. If Value Is Nothing Then
  86. Me.CacheNode.Attribute(Name).Remove()
  87. Exit Sub
  88. End If
  89. End If
  90. Me.CacheNode.Attribute(Name).SetValue(Value)
  91. End Sub
  92. Protected Friend Function GetAttribute(ByVal Name As String) As String
  93. If Me.Node.Attribute(Name) IsNot Nothing Then
  94. Return Me.Node.Attribute(Name).Value
  95. ElseIf Me.CacheNode.Attribute(Name) IsNot Nothing Then
  96. Return Me.CacheNode.Attribute(Name).Value
  97. Else
  98. Return Nothing
  99. End If
  100. End Function
  101. Private _FolderPath As String
  102. Public Property FolderPath As String Implements IProtoXBase.FolderPath
  103. Get
  104. Return _FolderPath
  105. End Get
  106. Set(value As String)
  107. _FolderPath = value
  108. If _NfoFilePath IsNot Nothing Then
  109. _NfoFilePath = IO.Path.Combine(value, IO.Path.GetFileName(_NfoFilePath))
  110. End If
  111. End Set
  112. End Property
  113. Public Overridable Sub Load() Implements IProtoXFile.Load
  114. Me.Load(Me.NfoFilePath)
  115. Me.IsAltered = False
  116. Me.IsCache = False
  117. End Sub
  118. Public Property FailedLoad As Boolean
  119. Public Overridable Sub Load(ByVal Path As String) Implements IProtoXFile.Load
  120. Me.IsAltered = True
  121. Me.CleanDoc()
  122. If IO.File.Exists(Path) Then
  123. Try
  124. Me.Doc = XDocument.Load(Path)
  125. Me.Doc.DescendantNodes.OfType(Of XComment)().Remove()
  126. Catch
  127. FailedLoad = True
  128. Exit Sub
  129. End Try
  130. Else
  131. Exit Sub
  132. End If
  133. LoadDoc()
  134. End Sub
  135. Public Sub LoadXml(ByVal Input As XNode)
  136. Me.Doc = New XDocument(Input)
  137. LoadDoc()
  138. Me.IsAltered = False 'These two properties have been moved here from TvCache.vb:Load() as this function is the
  139. Me.IsCache = True 'only one that uses LoadXml(XNode) so far. Please note if using this. - HueyHQ 27Feb2013
  140. End Sub
  141. Public Sub LoadXml(ByVal Input As String)
  142. Me.IsAltered = True
  143. Me.Doc = XDocument.Parse(Input)
  144. LoadDoc()
  145. End Sub
  146. Protected Overridable Sub LoadDoc()
  147. If Me.Doc.Root Is Nothing Then Throw New Exception("Invalid NFO file")
  148. Me._node = Me.Doc.Root
  149. Dim Root As XElement = Me.Doc.Root
  150. Dim ChildProperty As IProtoXChild
  151. Dim XElementList As New List(Of XElement)
  152. If Root.Name = "multiepisodenfo" Then
  153. For Each episode As XElement In Root.Nodes
  154. For Each Child As XNode In episode.Nodes
  155. If TypeOf Child Is XElement Then
  156. XElementList.Add(Child)
  157. Else
  158. Dim Test As Boolean = False
  159. End If
  160. Next
  161. Next
  162. Else
  163. For Each Child As XNode In Root.Nodes
  164. If TypeOf Child Is XElement Then
  165. XElementList.Add(Child)
  166. Else
  167. Dim Test As Boolean = False
  168. End If
  169. Next
  170. End If
  171. For Each Child As XElement In XElementList
  172. If Me.ChildrenLookup.ContainsKey(Child.Name.ToString.ToLower) Then
  173. ChildProperty = Me.ChildrenLookup.Item(Child.Name.ToString.ToLower)
  174. ChildProperty.ProcessNode(Child)
  175. Dim ChanceToSeeChild As Boolean = True
  176. End If
  177. Next
  178. Me.CleanDoc()
  179. Me.IsCache = False
  180. End Sub
  181. Public Sub DeleteElement(ByVal elementName As String)
  182. CleanNode(Doc.Root, elementName)
  183. 'Me.SurpressAlter = True
  184. End Sub
  185. Public Sub Save() Implements IProtoXFile.Save
  186. Me.IsAltered = False
  187. Me.Save(Me.NfoFilePath)
  188. End Sub
  189. Public Sub Save(ByVal Path As String) Implements IProtoXFile.Save
  190. 'IsAltred shouldn't be set here, Save() isn't called the actual file referenced in NfoFilePath may not match what is in the current file
  191. Me.CleanDoc()
  192. Dim myloop As Boolean = True
  193. Do
  194. If Not DirectCast(Doc.FirstNode, System.Xml.Linq.XElement).FirstAttribute Is Nothing Then
  195. DirectCast(Doc.FirstNode, System.Xml.Linq.XElement).FirstAttribute.Remove() ' Value = "Removed - Now Not Used!"
  196. Else
  197. myloop = False
  198. End If
  199. Loop While myloop
  200. Doc.Save(Path)
  201. 'Dim settings As New XmlWriterSettings()
  202. 'settings.Encoding = New UTF8Encoding(False)
  203. 'settings.Indent = True
  204. 'settings.IndentChars = (ControlChars.Tab)
  205. 'settings.NewLineHandling = NewLineHandling.None
  206. 'Dim writer As XmlWriter = XmlWriter.Create(Path, settings)
  207. 'Doc.Save(writer)
  208. 'writer.Close()
  209. Me.IsCache = False
  210. End Sub
  211. Private Sub CleanDoc()
  212. CleanNode(Doc.Root)
  213. End Sub
  214. Private Sub CleanNode(ByVal Element As XElement, ByVal Optional elementName As String = "")
  215. Dim Cursor As XElement
  216. Dim NextOne As XNode
  217. If Element Is Nothing Then Exit Sub
  218. If Element.FirstNode Is Nothing Then
  219. Element.Remove()
  220. Exit Sub
  221. End If
  222. If Element.FirstNode.NodeType = Xml.XmlNodeType.Text Then
  223. Exit Sub
  224. End If
  225. Cursor = Element.FirstNode
  226. Do
  227. NextOne = Cursor.NextNode
  228. If Cursor.Nodes.Count = 0 AndAlso Cursor.Attributes.Count = 0 OrElse Cursor.Name.LocalName = elementName Then
  229. Cursor.Remove()
  230. Else
  231. CleanNode(Cursor)
  232. End If
  233. Cursor = NextOne
  234. Loop Until Cursor Is Nothing
  235. If Element.Nodes.Count = 0 AndAlso Element.Attributes.Count = 0 Then
  236. Element.Remove()
  237. End If
  238. End Sub
  239. #End Region
  240. Public ReadOnly Property FileContainsReadableXml As Boolean Implements IProtoXFile.FileContainsReadableXml
  241. Get
  242. Try
  243. If Me.FileExists Then
  244. Dim Test As XDocument = XDocument.Load(Me.NfoFilePath)
  245. Else
  246. Return False
  247. End If
  248. Catch ex As Exception
  249. Return False
  250. End Try
  251. Return True
  252. End Get
  253. End Property
  254. Public ReadOnly Property FileExists As Boolean Implements IProtoXFile.FileExists
  255. Get
  256. Return IO.File.Exists(Me.NfoFilePath)
  257. End Get
  258. End Property
  259. Public Sub HandleChildValueChanged(ByRef ProtoChild As ProtoXChildBase) Implements IProtoXBase.HandleChildValueChanged
  260. Me.IsAltered = True
  261. RaiseEvent ValueChanged(ProtoChild)
  262. End Sub
  263. Public Sub RaiseValueChanged(ByRef ProtoChild As ProtoXChildBase) Implements IProtoXBase.RaiseValueChanged
  264. Me.IsAltered = True
  265. RaiseEvent ValueChanged(ProtoChild)
  266. End Sub
  267. Public Event ValueChanged(ByRef ProtoChild As ProtoXChildBase) Implements IProtoXBase.ValueChanged
  268. Public Property IsAltered As Boolean Implements IProtoXBase.IsAltered
  269. Private Property SurpressAlter As Boolean Implements IProtoXBase.SurpressAlter
  270. Public Sub SortNodes()
  271. For Each Item In ChildrenLookup.Values
  272. Item.Node.Remove()
  273. Next
  274. 'Sort decending so that we can add nodes with an order first, and ones without at the bottom
  275. For Each Item In (From Items As IProtoXChild In ChildrenLookup.Values Order By Items.SortIndex Descending)
  276. If Item.SortIndex = -1 Then
  277. Me.Node.Add(Item.Node)
  278. Else
  279. Me.Node.AddFirst(Item.Node)
  280. End If
  281. Next
  282. End Sub
  283. End Class