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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 74 - (hide annotations) (download)
Sat Mar 9 11:06:39 2013 UTC (6 years, 10 months ago) by william
File size: 17466 byte(s)

1 william 36 using System;
2     using System.Collections.Generic;
3     using System.Linq;
4     using System.Text;
5     using libxmltv.Interfaces;
6 william 46 using System.ComponentModel;
7 william 54 using System.Windows.Forms;
8     using System.Threading;
9 william 56 using System.Reflection;
10     using System.Globalization;
11     using System.Diagnostics;
12 william 73 using System.Xml.Linq;
13 william 36
14     namespace libxmltv.Core
15     {
16 william 49 [Serializable]
17 william 56 internal class XMLTVRuntimeInstance : MarshalByRefObject,
18     IXMLTVRuntimeInstance,
19     ISerializer<XMLTVRuntimeInstance>,
20     IGetCreatedInstanceEvent,
21     ISetCreatedInstanceEvent,
22     IDestroyInstance,
23     IRuntimeInstanceLoader<XMLTVRuntimeInstance>
24 william 36 {
25 william 56 [NonSerialized]
26 william 54 Thread worker;
27 william 72 public XMLTVRuntimeInstance() { init(); }
28     public XMLTVRuntimeInstance(string xmlfile) : this(xmlfile, null) { }
29     public XMLTVRuntimeInstance(string xmlfile, EventHandler<EventArgs> handler)
30     : this()
31 william 56 {
32 william 72 this.OnInstanceCreated += handler;
33     worker = new Thread(new ParameterizedThreadStart(CreateInstance)); worker.Start(xmlfile);
34 william 56 }
35 william 72 private void CreateInstance(object xmlfile)
36 william 54 {
37 william 72 using (XMLTVInstance instance = new XMLTVInstance(xmlfile.ToString()))
38 william 45 {
39 william 72 this.LoadFromInstance(instance.GetInstance());
40     OnCreatedInstance(this, new EventArgs());
41 william 45 }
42     }
43 william 72
44     private void OnCreatedInstance(object sender, EventArgs e)
45     {
46     if (OnInstanceCreated != null) { OnInstanceCreated.Invoke(sender, e); }
47     }
48 william 36
49 william 72 private void init()
50     {
51 william 73 this.Source = new List<IXMLTVSource>();
52     this.Channels = new List<IXMLTVChannel>();
53     this.Programs = new List<IXMLTVProgram>();
54 william 72 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 william 56 private string _XmlDoc;
71 william 73 public string XmlDoc { get { return _XmlDoc; } set { _XmlDoc = value; } }
72     private List<IXMLTVSource> _Source;
73     public List<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 william 72 #endregion
79     #region IOnInstanceCreated members
80 william 56 [NonSerialized]
81     private EventHandler<EventArgs> _OnInstanceCreated;
82     public EventHandler<EventArgs> OnInstanceCreated { get { return _OnInstanceCreated; } set { _OnInstanceCreated = value; } }
83 william 72 #endregion
84     #region IGetCreatedInstanceEvent members
85 william 54 public EventHandler<EventArgs> GetOnInstanceCreated() { return OnInstanceCreated; }
86 william 72 #endregion
87     #region ISetCreatedInstanceEvent members
88 william 54 public void SetOnInstanceCreated(EventHandler<EventArgs> event_instance) { OnInstanceCreated = event_instance; }
89 william 72 #endregion
90     #region ISerializer<XMLTVRuntimeInstance> members
91     public IXMLTVSerializer<XMLTVRuntimeInstance> Serializer { get { return new XMLTVSerializer<XMLTVRuntimeInstance>(this); } }
92     #endregion
93     #region IDestroyInstance member
94 william 54 public void DestroyInstance()
95 william 46 {
96 william 55 xmltv_logger.Debug.WriteLine("Destoying Instance of: '{0}'", this.GetType().Name);
97 william 54 this.IsAborting = true;
98     if (worker == null)
99 william 46 {
100 william 55 xmltv_logger.Debug.WriteLine("Unable to destroy instance of: '{0}' - worker thread is null", this.GetType().Name);
101 william 54 return;
102 william 46 }
103 william 54 else
104     {
105     if (worker.IsAlive)
106     {
107 william 55 xmltv_logger.Verbose.Debug.WriteLine("Requesting Instance to Abort...");
108 william 72 while (worker.IsAlive) { worker.Abort(); Application.DoEvents(); }
109 william 54 }
110 william 72 else { xmltv_logger.Debug.WriteLine("Instance of: '{0}'- already destroyed.", this.GetType().Name); }
111 william 54 }
112 william 46 }
113 william 72 #endregion
114     #region IRuntimeInstanceLoader<XMLTVRuntimeInstance> member
115 william 56 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 william 72 CloneFromInstance(ref instance);
122     xmltv_logger.Debug.WriteLine("Loading from instance...");
123     if (this.Source != null)
124 william 56 {
125 william 73 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Created by '{1}' - original source file: '{2}'", this.Source.FirstOrDefault().SourceName, this.Source.FirstOrDefault().GeneratorName, this.XmlFile_FullName);
126 william 56 }
127     else
128     {
129 william 72 xmltv_logger.Error.WriteLine("Source Property is null.");
130     throw new NullReferenceException("Source Property is null.");
131 william 56 }
132 william 72 if (this.Channels != null)
133 william 56 {
134 william 73 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.FirstOrDefault().SourceName);
135 william 56 }
136     else
137     {
138 william 72 xmltv_logger.Error.WriteLine("Channels Property is null.");
139     throw new NullReferenceException("Channels Property is null.");
140 william 56 }
141 william 72 if (this.Programs != null)
142 william 56 {
143 william 73 xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}'", this.Programs.Count, this.Source.FirstOrDefault().SourceName);
144 william 56 }
145     else
146     {
147 william 72 xmltv_logger.Error.WriteLine("Programs Property is null.");
148     throw new NullReferenceException("Programs Property is null.");
149 william 56 }
150 william 72 xmltv_logger.Debug.WriteLine("Loaded from instance...");
151 william 56 return instance;
152     }
153 william 72 #endregion
154     #region CloneFromInstance
155 william 56 private void CloneFromInstance(ref XMLTVRuntimeInstance instance)
156     {
157 william 72 xmltv_logger.Debug.WriteLine("Cloning from instance...");
158 william 56 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 william 72 if (field.IsNotSerialized) { continue; }
166     var f = instance.GetType().GetField(field.Name, flags);
167     var v = f.GetValue(instance);
168     if (v != null)
169 william 56 {
170 william 72 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 william 56 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 william 72 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 william 56 }
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 william 72 xmltv_logger.Debug.WriteLine("Cloned from instance...");
215 william 56 }
216 william 72 #endregion
217 william 36 }
218    
219 william 72 internal class XMLTVInstance : IGetInstance<XMLTVRuntimeInstance>, IDisposable
220 william 36 {
221 william 73 public void Dispose()
222     {
223     //throw new NotImplementedException();
224     }
225    
226 william 72 private XMLTVRuntimeInstance gInstance;
227     public XMLTVRuntimeInstance GetInstance() { return gInstance; }
228     public XMLTVInstance(string xmlfile)
229     {
230     try
231     {
232     CreateLoader(xmlfile);
233 william 73 CreateParser();
234 william 72 }
235     catch (Exception ex)
236     {
237     xmltv_logger.Error.WriteLine(ex.ToString());
238     }
239 william 36 }
240    
241 william 72 private void CreateLoader(string xml_file)
242 william 36 {
243 william 72 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 william 36 }
275 william 73 private void CreateParser()
276 william 36 {
277 william 73 var doc = XDocument.Parse(this.GetInstance().XmlDoc);
278 william 74 var root_element = doc.Root;
279    
280     CreateHandlerForRootNode(root_element);
281 william 72
282 william 73 var nodes = doc.Root.Elements().ToList();
283 william 74 foreach(var node in nodes)
284     {
285     if (!CreateHandlerForNode(node))
286     {
287     xmltv_logger.Verbose.Debug.WriteLine("Unable to create handler for node: '{0}'", node.Name.ToString());
288     }
289     }
290 william 36 }
291 william 44
292 william 73
293 william 74 private void CreateHandlerForRootNode(XElement root)
294     {
295     if (root == null) { throw new NullReferenceException("Root element is null"); }
296     if (root.Name == null) { throw new NullReferenceException("Root element's Name is null"); }
297     var root_name = root.Name.ToString();
298     xmltv_logger.Verbose.Debug.WriteLine("Creating handler for root: '{0}'", root_name.ToString());
299 william 73 object raw_instance = null;
300     BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
301     CultureInfo culture = CultureInfo.CurrentCulture;
302     Assembly asm = Assembly.GetExecutingAssembly();
303     var types = asm.GetTypes();
304     Type handler_type = null;
305     foreach (var type in types)
306     {
307     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
308     {
309     try
310     {
311     var handler_prop = type.GetProperty("Handler");
312     if (handler_prop != null)
313     {
314     raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
315     if (raw_instance != null)
316     {
317     object handler_value = handler_prop.GetValue(raw_instance, null);
318 william 74 if (handler_value != null && handler_value.ToString() == root_name)
319 william 73 {
320     handler_type = type;
321     break;
322     }
323     }
324     }
325     }
326     catch (Exception) { }
327     }
328     }
329     if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
330 william 74 xmltv_logger.Verbose.Debug.WriteLine("Created handler for root: '{0}'", root_name.ToString());
331 william 73 raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance }, culture);
332 william 44 }
333 william 72
334 william 74 private bool CreateHandlerForNode(XElement node)
335     {
336     if (node == null) { throw new NullReferenceException("Node element is null"); }
337     if (node.Name == null) { throw new NullReferenceException("Node element's Name is null"); }
338     var node_name = node.Name.ToString();
339    
340     xmltv_logger.Verbose.Debug.WriteLine("Creating handler for node: '{0}'", node_name.ToString());
341     object raw_instance = null;
342     BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
343     CultureInfo culture = CultureInfo.CurrentCulture;
344     Assembly asm = Assembly.GetExecutingAssembly();
345     var types = asm.GetTypes();
346     Type handler_type = null;
347     foreach (var type in types)
348     {
349     if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
350     {
351     try
352     {
353     var handler_prop = type.GetProperty("Handler");
354     if (handler_prop != null)
355     {
356     raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
357     if (raw_instance != null)
358     {
359     object handler_value = handler_prop.GetValue(raw_instance, null);
360     if (handler_value != null && handler_value.ToString() == node_name)
361     {
362     handler_type = type;
363     break;
364     }
365     }
366     }
367     }
368     catch (Exception) { }
369     }
370     }
371     if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
372     xmltv_logger.Verbose.Debug.WriteLine("Created handler for node: '{0}'", node_name.ToString());
373     raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance, node }, culture);
374     return true;
375     }
376 william 72
377 william 36 }
378     }

  ViewVC Help
Powered by ViewVC 1.1.22