/[xmltv_parser]/trunk/libxmltv/Core/XMLTVRuntimeInstance.cs
ViewVC logotype

Contents of /trunk/libxmltv/Core/XMLTVRuntimeInstance.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 79 - (show annotations) (download)
Sat Mar 9 11:40:15 2013 UTC (7 years, 7 months ago) by william
File size: 17913 byte(s)

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using libxmltv.Interfaces;
6 using System.ComponentModel;
7 using System.Windows.Forms;
8 using System.Threading;
9 using System.Reflection;
10 using System.Globalization;
11 using System.Diagnostics;
12 using System.Xml.Linq;
13
14 namespace libxmltv.Core
15 {
16 [Serializable]
17 internal class XMLTVRuntimeInstance : MarshalByRefObject,
18 IXMLTVRuntimeInstance,
19 ISerializer<XMLTVRuntimeInstance>,
20 IGetCreatedInstanceEvent,
21 ISetCreatedInstanceEvent,
22 IDestroyInstance,
23 IRuntimeInstanceLoader<XMLTVRuntimeInstance>
24 {
25 [NonSerialized]
26 Thread worker;
27 public XMLTVRuntimeInstance() { init(); }
28 public XMLTVRuntimeInstance(string xmlfile) : this(xmlfile, null) { }
29 public XMLTVRuntimeInstance(string xmlfile, EventHandler<EventArgs> handler)
30 : this()
31 {
32 this.OnInstanceCreated += handler;
33 worker = new Thread(new ParameterizedThreadStart(CreateInstance)); worker.Start(xmlfile);
34 }
35 private void CreateInstance(object xmlfile)
36 {
37 using (XMLTVInstance instance = new XMLTVInstance(xmlfile.ToString()))
38 {
39 this.LoadFromInstance(instance.GetInstance());
40 OnCreatedInstance(this, new EventArgs());
41 }
42 }
43
44 private void OnCreatedInstance(object sender, EventArgs e)
45 {
46 if (OnInstanceCreated != null) { OnInstanceCreated.Invoke(sender, e); }
47 }
48
49 private void init()
50 {
51 this.Source = new XMLTVSource();
52 this.Channels = new List<IXMLTVChannel>();
53 this.Programs = new List<IXMLTVProgram>();
54 this.XmlFile_Name = string.Empty;
55 this.XmlFile_FullName = string.Empty;
56 this.XmlDoc = string.Empty;
57 this.OnInstanceCreated = null;
58 }
59
60 #region IXMLTVRuntimeInstance members
61 private bool _IsAborting;
62 public bool IsAborting { get { return _IsAborting; } private set { _IsAborting = value; } }
63
64
65 private string _XmlFile_Name;
66 public string XmlFile_Name { get { return _XmlFile_Name; } set { _XmlFile_Name = value; } }
67 private string _XmlFile_FullName;
68 public string XmlFile_FullName { get { return _XmlFile_FullName; } set { _XmlFile_FullName = value; } }
69
70 private string _XmlDoc;
71 public string XmlDoc { get { return _XmlDoc; } set { _XmlDoc = value; } }
72 private IXMLTVSource _Source;
73 public IXMLTVSource Source { get { return _Source; } set { _Source = value; } }
74 private List<IXMLTVChannel> _Channels;
75 public List<IXMLTVChannel> Channels { get { return _Channels; } set { _Channels = value; } }
76 private List<IXMLTVProgram> _Programs;
77 public List<IXMLTVProgram> Programs { get { return _Programs; } set { _Programs = value; } }
78 #endregion
79 #region IOnInstanceCreated members
80 [NonSerialized]
81 private EventHandler<EventArgs> _OnInstanceCreated;
82 public EventHandler<EventArgs> OnInstanceCreated { get { return _OnInstanceCreated; } set { _OnInstanceCreated = value; } }
83 #endregion
84 #region IGetCreatedInstanceEvent members
85 public EventHandler<EventArgs> GetOnInstanceCreated() { return OnInstanceCreated; }
86 #endregion
87 #region ISetCreatedInstanceEvent members
88 public void SetOnInstanceCreated(EventHandler<EventArgs> event_instance) { OnInstanceCreated = event_instance; }
89 #endregion
90 #region ISerializer<XMLTVRuntimeInstance> members
91 public IXMLTVSerializer<XMLTVRuntimeInstance> Serializer { get { return new XMLTVSerializer<XMLTVRuntimeInstance>(this); } }
92 #endregion
93 #region IDestroyInstance member
94 public void DestroyInstance()
95 {
96 xmltv_logger.Debug.WriteLine("Destoying Instance of: '{0}'", this.GetType().Name);
97 this.IsAborting = true;
98 if (worker == null)
99 {
100 xmltv_logger.Debug.WriteLine("Unable to destroy instance of: '{0}' - worker thread is null", this.GetType().Name);
101 return;
102 }
103 else
104 {
105 if (worker.IsAlive)
106 {
107 xmltv_logger.Verbose.Debug.WriteLine("Requesting Instance to Abort...");
108 while (worker.IsAlive) { worker.Abort(); Application.DoEvents(); }
109 }
110 else { xmltv_logger.Debug.WriteLine("Instance of: '{0}'- already destroyed.", this.GetType().Name); }
111 }
112 }
113 #endregion
114 #region IRuntimeInstanceLoader<XMLTVRuntimeInstance> member
115 public XMLTVRuntimeInstance LoadFromInstance(XMLTVRuntimeInstance instance)
116 {
117 if (instance == null)
118 {
119 throw new NullReferenceException("Failed to load from instance because the instance is null.");
120 }
121 xmltv_logger.Debug.WriteLine("Loading from instance...");
122 CloneFromInstance(ref instance);
123 xmltv_logger.Debug.WriteLine("Loaded from instance...");
124 if (this.Source != null)
125 {
126 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Created by '{1}' - original source file: '{2}'", this.Source.SourceName, this.Source.GeneratorName, this.XmlFile_FullName);
127 }
128 else
129 {
130 xmltv_logger.Error.WriteLine("Source Property is null.");
131 throw new NullReferenceException("Source Property is null.");
132 }
133 if (this.Channels != null)
134 {
135 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.SourceName);
136 }
137 else
138 {
139 xmltv_logger.Error.WriteLine("Channels Property is null.");
140 throw new NullReferenceException("Channels Property is null.");
141 }
142 if (this.Programs != null)
143 {
144 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}'", this.Programs.Count, this.Source.SourceName);
145 }
146 else
147 {
148 xmltv_logger.Error.WriteLine("Programs Property is null.");
149 throw new NullReferenceException("Programs Property is null.");
150 }
151 return instance;
152 }
153 #endregion
154 #region CloneFromInstance
155 private void CloneFromInstance(ref XMLTVRuntimeInstance instance)
156 {
157 xmltv_logger.Debug.WriteLine("Cloning from instance...");
158 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
159 CultureInfo culture = CultureInfo.CurrentCulture;
160 Type t = typeof(XMLTVRuntimeInstance);
161 foreach (var field in t.GetFields(flags))
162 {
163 try
164 {
165 if (field.IsNotSerialized) { continue; }
166 var f = instance.GetType().GetField(field.Name, flags);
167 var v = f.GetValue(instance);
168 if (v != null)
169 {
170 field.SetValue(this, v);
171 }
172 else
173 {
174 xmltv_logger.Debug.WriteLine("Attempted to set field: '{0}' with a null value. The operation was aborted.", f.Name);
175 continue;
176 }
177 }
178 catch (Exception ex)
179 {
180 throw new Exception(string.Format("Unable to copy value for field: '{0}' from instance", field.Name), ex);
181 }
182 }
183 foreach (var property in t.GetProperties(flags))
184 {
185 try
186 {
187 var f = instance.GetType().GetProperty(property.Name);
188 object value = null;
189 try
190 {
191 value = f.GetValue(instance, null);
192 }
193 catch (ArgumentException ex) { if (ex.Message == "Property get method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
194 try
195 {
196 if (value != null)
197 {
198 property.SetValue(this, value, null);
199 }
200 else
201 {
202 xmltv_logger.Debug.WriteLine("Attempted to set property: '{0}' with a null value. The operation was aborted.", f.Name);
203 continue;
204 }
205 }
206 catch (ArgumentException ex) { if (ex.Message == "Property set method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
207
208 }
209 catch (Exception ex)
210 {
211 throw new Exception(string.Format("Unable to copy value for property: '{0}' from instance", property.Name), ex);
212 }
213 }
214 xmltv_logger.Debug.WriteLine("Cloned from instance...");
215 }
216 #endregion
217 }
218
219 internal class XMLTVInstance : IGetInstance<XMLTVRuntimeInstance>, IDisposable
220 {
221 public void Dispose()
222 {
223 //throw new NotImplementedException();
224 }
225
226 private XMLTVRuntimeInstance gInstance;
227 public XMLTVRuntimeInstance GetInstance() { return gInstance; }
228 public XMLTVInstance(string xmlfile)
229 {
230 try
231 {
232 CreateLoader(xmlfile);
233 CreateParser();
234 }
235 catch (ThreadAbortException ex) { Debug.WriteLine(ex.ToString()); }
236 catch (Exception ex)
237 {
238 xmltv_logger.Error.WriteLine(ex.ToString());
239 }
240 }
241
242 private void CreateLoader(string xml_file)
243 {
244 gInstance = new XMLTVRuntimeInstance();
245 bool bound_to_ctor = false;
246 object raw_instance = null;
247 Assembly asm = Assembly.GetExecutingAssembly();
248 var types = asm.GetTypes();
249
250 foreach (var type in types)
251 {
252 if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
253 {
254 xmltv_logger.Verbose.Debug.WriteLine("Type: '{0}' Base: '{1}'", type.Name, type.BaseType == null ? "none" : type.BaseType.Name);
255
256 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
257 CultureInfo culture = CultureInfo.CurrentCulture;
258 object[] args = new object[] { xml_file, gInstance };
259 try
260 {
261 raw_instance = Activator.CreateInstance(type, flags, null, args, culture);
262 bound_to_ctor = true;
263 }
264 catch (Exception ex)
265 {
266 Debug.WriteLine(ex.ToString());
267 }
268 }
269 }
270 if (!bound_to_ctor) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); }
271 if (raw_instance == null) { throw new NullReferenceException("Found a compatible XMLTV Data Loader, but it returned invalid data."); }
272 IGetInstance<XMLTVRuntimeInstance> getter_instance = (raw_instance as IGetInstance<XMLTVRuntimeInstance>);
273 if (getter_instance != null) { gInstance = getter_instance.GetInstance(); }
274 else { throw new Exception("Found a compatible XMLTV Data Loader, but was unable to obtain the instance holding the data"); }
275 }
276 private void CreateParser()
277 {
278 var doc = XDocument.Parse(this.GetInstance().XmlDoc);
279 var root_element = doc.Root;
280 CreateHandlerForRootNode(root_element);
281 var nodes = doc.Root.Elements().ToList();
282
283 double total_nodes = nodes.Count;
284 double node_index = 0;
285 double progress = 0;
286 foreach(var node in nodes)
287 {
288 if (this.GetInstance().IsAborting)
289 {
290 break;
291 }
292 if (!CreateHandlerForNode(node)) { xmltv_logger.Verbose.Debug.WriteLine("Unable to create handler for node: '{0}'", node.Name.ToString()); }
293 node_index++;
294 progress = 100.0 * (node_index / total_nodes);
295 xmltv_logger.ReportProgress(this, new Enterprise.Logging.ReportProgressEventArgs((int)progress));
296 Application.DoEvents();
297 }
298 }
299
300
301 private void CreateHandlerForRootNode(XElement root)
302 {
303 if (root == null) { throw new NullReferenceException("Root element is null"); }
304 if (root.Name == null) { throw new NullReferenceException("Root element's Name is null"); }
305 var root_name = root.Name.ToString();
306 xmltv_logger.Verbose.Debug.WriteLine("Creating handler for root: '{0}'", root_name.ToString());
307 object raw_instance = null;
308 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
309 CultureInfo culture = CultureInfo.CurrentCulture;
310 Assembly asm = Assembly.GetExecutingAssembly();
311 var types = asm.GetTypes();
312 Type handler_type = null;
313 foreach (var type in types)
314 {
315 if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
316 {
317 try
318 {
319 var handler_prop = type.GetProperty("Handler");
320 if (handler_prop != null)
321 {
322 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
323 if (raw_instance != null)
324 {
325 object handler_value = handler_prop.GetValue(raw_instance, null);
326 if (handler_value != null && handler_value.ToString() == root_name)
327 {
328 handler_type = type;
329 break;
330 }
331 }
332 }
333 }
334 catch (Exception) { }
335 }
336 }
337 if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
338 xmltv_logger.Verbose.Debug.WriteLine("Created handler for root: '{0}'", root_name.ToString());
339 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance }, culture);
340 }
341
342 private bool CreateHandlerForNode(XElement node)
343 {
344 if (node == null) { throw new NullReferenceException("Node element is null"); }
345 if (node.Name == null) { throw new NullReferenceException("Node element's Name is null"); }
346 var node_name = node.Name.ToString();
347
348 xmltv_logger.Verbose.Debug.WriteLine("Creating handler for node: '{0}'", node_name.ToString());
349 object raw_instance = null;
350 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
351 CultureInfo culture = CultureInfo.CurrentCulture;
352 Assembly asm = Assembly.GetExecutingAssembly();
353 var types = asm.GetTypes();
354 Type handler_type = null;
355 foreach (var type in types)
356 {
357 if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
358 {
359 try
360 {
361 var handler_prop = type.GetProperty("Handler");
362 if (handler_prop != null)
363 {
364 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
365 if (raw_instance != null)
366 {
367 object handler_value = handler_prop.GetValue(raw_instance, null);
368 if (handler_value != null && handler_value.ToString() == node_name)
369 {
370 handler_type = type;
371 break;
372 }
373 }
374 }
375 }
376 catch (Exception) { }
377 }
378 }
379 if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
380 xmltv_logger.Verbose.Debug.WriteLine("Created handler for node: '{0}'", node_name.ToString());
381 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance, node }, culture);
382 return true;
383 }
384
385 }
386 }

  ViewVC Help
Powered by ViewVC 1.1.22