/[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 78 - (show annotations) (download)
Sat Mar 9 11:36:24 2013 UTC (6 years, 4 months ago) by william
File size: 17832 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 (Exception ex)
236 {
237 xmltv_logger.Error.WriteLine(ex.ToString());
238 }
239 }
240
241 private void CreateLoader(string xml_file)
242 {
243 gInstance = new XMLTVRuntimeInstance();
244 bool bound_to_ctor = false;
245 object raw_instance = null;
246 Assembly asm = Assembly.GetExecutingAssembly();
247 var types = asm.GetTypes();
248
249 foreach (var type in types)
250 {
251 if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
252 {
253 xmltv_logger.Verbose.Debug.WriteLine("Type: '{0}' Base: '{1}'", type.Name, type.BaseType == null ? "none" : type.BaseType.Name);
254
255 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
256 CultureInfo culture = CultureInfo.CurrentCulture;
257 object[] args = new object[] { xml_file, gInstance };
258 try
259 {
260 raw_instance = Activator.CreateInstance(type, flags, null, args, culture);
261 bound_to_ctor = true;
262 }
263 catch (Exception ex)
264 {
265 Debug.WriteLine(ex.ToString());
266 }
267 }
268 }
269 if (!bound_to_ctor) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); }
270 if (raw_instance == null) { throw new NullReferenceException("Found a compatible XMLTV Data Loader, but it returned invalid data."); }
271 IGetInstance<XMLTVRuntimeInstance> getter_instance = (raw_instance as IGetInstance<XMLTVRuntimeInstance>);
272 if (getter_instance != null) { gInstance = getter_instance.GetInstance(); }
273 else { throw new Exception("Found a compatible XMLTV Data Loader, but was unable to obtain the instance holding the data"); }
274 }
275 private void CreateParser()
276 {
277 var doc = XDocument.Parse(this.GetInstance().XmlDoc);
278 var root_element = doc.Root;
279 CreateHandlerForRootNode(root_element);
280 var nodes = doc.Root.Elements().ToList();
281
282 double total_nodes = nodes.Count;
283 double node_index = 0;
284 double progress = 0;
285 foreach(var node in nodes)
286 {
287 if (this.GetInstance().IsAborting)
288 {
289 break;
290 }
291 if (!CreateHandlerForNode(node)) { xmltv_logger.Verbose.Debug.WriteLine("Unable to create handler for node: '{0}'", node.Name.ToString()); }
292 node_index++;
293 progress = 100.0 * (node_index / total_nodes);
294 xmltv_logger.ReportProgress(this, new Enterprise.Logging.ReportProgressEventArgs((int)progress));
295 Application.DoEvents();
296 }
297 }
298
299
300 private void CreateHandlerForRootNode(XElement root)
301 {
302 if (root == null) { throw new NullReferenceException("Root element is null"); }
303 if (root.Name == null) { throw new NullReferenceException("Root element's Name is null"); }
304 var root_name = root.Name.ToString();
305 xmltv_logger.Verbose.Debug.WriteLine("Creating handler for root: '{0}'", root_name.ToString());
306 object raw_instance = null;
307 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
308 CultureInfo culture = CultureInfo.CurrentCulture;
309 Assembly asm = Assembly.GetExecutingAssembly();
310 var types = asm.GetTypes();
311 Type handler_type = null;
312 foreach (var type in types)
313 {
314 if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
315 {
316 try
317 {
318 var handler_prop = type.GetProperty("Handler");
319 if (handler_prop != null)
320 {
321 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
322 if (raw_instance != null)
323 {
324 object handler_value = handler_prop.GetValue(raw_instance, null);
325 if (handler_value != null && handler_value.ToString() == root_name)
326 {
327 handler_type = type;
328 break;
329 }
330 }
331 }
332 }
333 catch (Exception) { }
334 }
335 }
336 if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
337 xmltv_logger.Verbose.Debug.WriteLine("Created handler for root: '{0}'", root_name.ToString());
338 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance }, culture);
339 }
340
341 private bool CreateHandlerForNode(XElement node)
342 {
343 if (node == null) { throw new NullReferenceException("Node element is null"); }
344 if (node.Name == null) { throw new NullReferenceException("Node element's Name is null"); }
345 var node_name = node.Name.ToString();
346
347 xmltv_logger.Verbose.Debug.WriteLine("Creating handler for node: '{0}'", node_name.ToString());
348 object raw_instance = null;
349 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
350 CultureInfo culture = CultureInfo.CurrentCulture;
351 Assembly asm = Assembly.GetExecutingAssembly();
352 var types = asm.GetTypes();
353 Type handler_type = null;
354 foreach (var type in types)
355 {
356 if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
357 {
358 try
359 {
360 var handler_prop = type.GetProperty("Handler");
361 if (handler_prop != null)
362 {
363 raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
364 if (raw_instance != null)
365 {
366 object handler_value = handler_prop.GetValue(raw_instance, null);
367 if (handler_value != null && handler_value.ToString() == node_name)
368 {
369 handler_type = type;
370 break;
371 }
372 }
373 }
374 }
375 catch (Exception) { }
376 }
377 }
378 if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
379 xmltv_logger.Verbose.Debug.WriteLine("Created handler for node: '{0}'", node_name.ToString());
380 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance, node }, culture);
381 return true;
382 }
383
384 }
385 }

  ViewVC Help
Powered by ViewVC 1.1.22