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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/libxmltv/Core/XMLTVInstance.cs	2013/03/08 04:01:25	46
+++ trunk/libxmltv/Core/XMLTVRuntimeInstance.cs	2013/03/09 11:36:24	78
@@ -4,86 +4,382 @@
 using System.Text;
 using libxmltv.Interfaces;
 using System.ComponentModel;
+using System.Windows.Forms;
+using System.Threading;
+using System.Reflection;
+using System.Globalization;
+using System.Diagnostics;
+using System.Xml.Linq;
 
 namespace libxmltv.Core
 {
-    internal class XMLTVRuntimeInstance : MarshalByRefObject, IXMLTVRuntimeInstance
+    [Serializable]
+    internal class XMLTVRuntimeInstance : MarshalByRefObject, 
+        IXMLTVRuntimeInstance, 
+        ISerializer<XMLTVRuntimeInstance>, 
+        IGetCreatedInstanceEvent, 
+        ISetCreatedInstanceEvent, 
+        IDestroyInstance, 
+        IRuntimeInstanceLoader<XMLTVRuntimeInstance>
     {
+        [NonSerialized]
+        Thread worker;
+        public XMLTVRuntimeInstance() { init(); }
         public XMLTVRuntimeInstance(string xmlfile) : this(xmlfile, null) { }
-        public XMLTVRuntimeInstance(string xmlfile, EventHandler<CancelEventArgs> t) { CreateInstance(xmlfile,t); }
-        private void CreateInstance(string xmlfile, EventHandler<CancelEventArgs> t)
+        public XMLTVRuntimeInstance(string xmlfile, EventHandler<EventArgs> handler)
+            : this()
         {
-            CancelEvent = t;
-            using (Instance = new XMLTVInstance(xmlfile, this))
+            this.OnInstanceCreated += handler;
+            worker = new Thread(new ParameterizedThreadStart(CreateInstance)); worker.Start(xmlfile);
+        }
+        private void CreateInstance(object xmlfile)
+        {
+            using (XMLTVInstance instance = new XMLTVInstance(xmlfile.ToString()))
             {
+                this.LoadFromInstance(instance.GetInstance());
+                OnCreatedInstance(this, new EventArgs());
             }
         }
+        
+        private void OnCreatedInstance(object sender, EventArgs e)
+        {
+            if (OnInstanceCreated != null) { OnInstanceCreated.Invoke(sender, e); }
+        }
 
-        internal XMLTVInstance Instance { get; private set; }
+        private void init()
+        {
+            this.Source = new XMLTVSource();
+            this.Channels = new List<IXMLTVChannel>();
+            this.Programs = new List<IXMLTVProgram>();
+            this.XmlFile_Name = string.Empty;
+            this.XmlFile_FullName = string.Empty;
+            this.XmlDoc = string.Empty;
+            this.OnInstanceCreated = null;
+        }
 
-        #region IXMLTV_LOADER members
-        public System.IO.FileInfo XmlFile { get; set; }
-        public System.Xml.Linq.XDocument XmlDoc { get; set; }
+        #region IXMLTVRuntimeInstance members
+        private bool _IsAborting;
+        public bool IsAborting { get { return _IsAborting; } private set { _IsAborting = value; } }
+
+
+        private string _XmlFile_Name;
+        public string XmlFile_Name { get { return _XmlFile_Name; } set { _XmlFile_Name = value; } }
+        private string _XmlFile_FullName;
+        public string XmlFile_FullName { get { return _XmlFile_FullName; } set { _XmlFile_FullName = value; } }
+
+        private string _XmlDoc;
+        public string XmlDoc { get { return _XmlDoc; } set { _XmlDoc = value; } }
+        private IXMLTVSource _Source;
+        public IXMLTVSource Source { get { return _Source; } set { _Source = value; } }
+        private List<IXMLTVChannel> _Channels;
+        public List<IXMLTVChannel> Channels { get { return _Channels; } set { _Channels = value; } }
+        private List<IXMLTVProgram> _Programs;
+        public List<IXMLTVProgram> Programs { get { return _Programs; } set { _Programs = value; } }
+        #endregion       
+        #region IOnInstanceCreated members
+        [NonSerialized]
+        private EventHandler<EventArgs> _OnInstanceCreated;
+        public EventHandler<EventArgs> OnInstanceCreated { get { return _OnInstanceCreated; } set { _OnInstanceCreated = value; } }
         #endregion
-        #region IXMLTV_PARSER Members
-        public IXMLTVSource Source { get; set; }
-        public Dictionary<string, IXMLTVChannel> Channels { get; set; }
-        public Dictionary<int, IXMLTVProgram> Programs { get; set; }
-        #endregion   
-    
-        //public void Dispose()
-        //{
-        //    IsDisposing = true;
-        //    //throw new NotImplementedException();
-        //}
-        //public bool IsDisposing { get; private set; }
-
-
-        private event EventHandler<CancelEventArgs> CancelEvent = null;
-
-        public bool IsAborting
+        #region IGetCreatedInstanceEvent members
+        public EventHandler<EventArgs> GetOnInstanceCreated() { return OnInstanceCreated; }
+        #endregion
+        #region ISetCreatedInstanceEvent members
+        public void SetOnInstanceCreated(EventHandler<EventArgs> event_instance) { OnInstanceCreated = event_instance; }
+        #endregion
+        #region ISerializer<XMLTVRuntimeInstance> members
+        public IXMLTVSerializer<XMLTVRuntimeInstance> Serializer { get { return new XMLTVSerializer<XMLTVRuntimeInstance>(this); } }
+        #endregion
+        #region IDestroyInstance member
+        public void DestroyInstance()
+        {
+            xmltv_logger.Debug.WriteLine("Destoying Instance of: '{0}'", this.GetType().Name);
+            this.IsAborting = true;
+            if (worker == null)
+            {
+                xmltv_logger.Debug.WriteLine("Unable to destroy instance of: '{0}' - worker thread is null", this.GetType().Name);
+                return;
+            }
+            else
+            {
+                if (worker.IsAlive)
+                {
+                    xmltv_logger.Verbose.Debug.WriteLine("Requesting Instance to Abort...");
+                    while (worker.IsAlive) { worker.Abort(); Application.DoEvents(); }
+                }
+                else { xmltv_logger.Debug.WriteLine("Instance of: '{0}'- already destroyed.", this.GetType().Name); }
+            }
+        }
+        #endregion
+        #region  IRuntimeInstanceLoader<XMLTVRuntimeInstance> member
+        public XMLTVRuntimeInstance LoadFromInstance(XMLTVRuntimeInstance instance)
+        {
+            if (instance == null)
+            {
+                throw new NullReferenceException("Failed to load from instance because the instance is null.");
+            }
+            xmltv_logger.Debug.WriteLine("Loading from instance...");
+            CloneFromInstance(ref instance);            
+            xmltv_logger.Debug.WriteLine("Loaded from instance...");
+            if (this.Source != null)
+            {
+                xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Created by '{1}' - original source file: '{2}'", this.Source.SourceName, this.Source.GeneratorName, this.XmlFile_FullName);
+            }
+            else
+            {
+                xmltv_logger.Error.WriteLine("Source Property is null.");
+                throw new NullReferenceException("Source Property is null.");
+            }
+            if (this.Channels != null)
+            {
+                xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.SourceName);
+            }
+            else
+            {
+                xmltv_logger.Error.WriteLine("Channels Property is null.");
+                throw new NullReferenceException("Channels Property is null.");
+            }
+            if (this.Programs != null)
+            {
+                xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}'", this.Programs.Count, this.Source.SourceName);
+            }
+            else
+            {
+                xmltv_logger.Error.WriteLine("Programs Property is null.");
+                throw new NullReferenceException("Programs Property is null.");
+            }            
+            return instance;
+        }
+        #endregion
+        #region CloneFromInstance
+        private void CloneFromInstance(ref XMLTVRuntimeInstance instance)
         {
-            get
+            xmltv_logger.Debug.WriteLine("Cloning from instance...");
+            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+            CultureInfo culture = CultureInfo.CurrentCulture;
+            Type t = typeof(XMLTVRuntimeInstance);
+            foreach (var field in t.GetFields(flags))
             {
-                if (CancelEvent != null)
+                try
                 {
-                    CancelEventArgs e = new CancelEventArgs();
-                    CancelEvent.Invoke(this, e);
-                    if (e.Cancel)
+                    if (field.IsNotSerialized) { continue; }                    
+                    var f = instance.GetType().GetField(field.Name, flags);                    
+                    var v = f.GetValue(instance);
+                    if (v != null)
+                    {
+                        field.SetValue(this, v);
+                    }
+                    else
                     {
-                        xmltv_logger.Log.Verbose.Debug.WriteLine("Detected Instance abort event...");
+                        xmltv_logger.Debug.WriteLine("Attempted to set field: '{0}' with a null value.  The operation was aborted.", f.Name);
+                        continue;
                     }
-                    return e.Cancel;
                 }
-                return false;
+                catch (Exception ex)
+                {
+                    throw new Exception(string.Format("Unable to copy value for field: '{0}' from instance", field.Name), ex);
+                }
             }
-        }
-
+            foreach (var property in t.GetProperties(flags))
+            {
+                try
+                {
+                    var f = instance.GetType().GetProperty(property.Name);
+                    object value = null;
+                    try
+                    {
+                        value = f.GetValue(instance, null);
+                    }
+                    catch (ArgumentException ex) { if (ex.Message == "Property get method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
+                    try
+                    {
+                        if (value != null)
+                        {
+                            property.SetValue(this, value, null);
+                        }
+                        else
+                        {
+                            xmltv_logger.Debug.WriteLine("Attempted to set property: '{0}' with a null value.  The operation was aborted.", f.Name);
+                            continue;
+                        }
+                    }
+                    catch (ArgumentException ex) { if (ex.Message == "Property set method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } }
 
+                }
+                catch (Exception ex)
+                {
+                    throw new Exception(string.Format("Unable to copy value for property: '{0}' from instance", property.Name), ex);
+                }
+            }
+            xmltv_logger.Debug.WriteLine("Cloned from instance...");
+        }
+        #endregion
     }
 
-    internal class XMLTVInstance : IDisposable
+    internal class XMLTVInstance : IGetInstance<XMLTVRuntimeInstance>, IDisposable
     {
-        public XMLTVInstance(string xmlfile, XMLTVRuntimeInstance instance) 
-        { 
-            CreateLoader(xmlfile, instance);
-            CreateParser(instance);
+        public void Dispose()
+        {
+            //throw new NotImplementedException();
         }
 
-        private void CreateLoader(string xml_file, XMLTVRuntimeInstance instance)
+        private XMLTVRuntimeInstance gInstance;
+        public XMLTVRuntimeInstance GetInstance() { return gInstance; }
+        public XMLTVInstance(string xmlfile) 
         {
-            //XMLTVLoader loader = new XMLTVLoader(xml_file, instance);
-            XMLTVLoader.CreateInstance(xml_file, instance);
+            try
+            {
+                CreateLoader(xmlfile);
+                CreateParser();
+            }
+            catch (Exception ex)
+            {
+                xmltv_logger.Error.WriteLine(ex.ToString());
+            }
         }
-        private void CreateParser(XMLTVRuntimeInstance instance)
+
+        private void CreateLoader(string xml_file)
         {
-            //XMLTVParser parser = new XMLTVParser(instance);
-            XMLTVParser.CreateInstance(instance);
+            gInstance = new XMLTVRuntimeInstance();
+            bool bound_to_ctor = false;
+            object raw_instance = null;
+            Assembly asm = Assembly.GetExecutingAssembly();
+            var types = asm.GetTypes();
+
+            foreach (var type in types)
+            {
+                if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
+                {
+                    xmltv_logger.Verbose.Debug.WriteLine("Type: '{0}' Base: '{1}'", type.Name, type.BaseType == null ? "none" : type.BaseType.Name);
+
+                    BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+                    CultureInfo culture = CultureInfo.CurrentCulture;
+                    object[] args = new object[] { xml_file, gInstance };
+                    try
+                    {
+                        raw_instance = Activator.CreateInstance(type, flags, null, args, culture);
+                        bound_to_ctor = true;
+                    }
+                    catch (Exception ex)
+                    {
+                        Debug.WriteLine(ex.ToString());
+                    }
+                }                
+            }
+            if (!bound_to_ctor) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); }
+            if (raw_instance == null) { throw new NullReferenceException("Found a compatible XMLTV Data Loader, but it returned invalid data."); }
+            IGetInstance<XMLTVRuntimeInstance> getter_instance = (raw_instance as IGetInstance<XMLTVRuntimeInstance>);
+            if (getter_instance != null) { gInstance = getter_instance.GetInstance(); }
+            else { throw new Exception("Found a compatible XMLTV Data Loader, but was unable to obtain the instance holding the data"); }
+        }
+        private void CreateParser()
+        {
+            var doc = XDocument.Parse(this.GetInstance().XmlDoc);
+            var root_element = doc.Root;            
+            CreateHandlerForRootNode(root_element);
+            var nodes = doc.Root.Elements().ToList();
+
+            double total_nodes = nodes.Count;
+            double node_index = 0;
+            double progress = 0;
+            foreach(var node in nodes)
+            {
+                if (this.GetInstance().IsAborting)
+                {
+                    break;
+                }
+                if (!CreateHandlerForNode(node)) { xmltv_logger.Verbose.Debug.WriteLine("Unable to create handler for node: '{0}'", node.Name.ToString()); }
+                node_index++;
+                progress = 100.0 * (node_index / total_nodes);
+                xmltv_logger.ReportProgress(this, new Enterprise.Logging.ReportProgressEventArgs((int)progress));
+                Application.DoEvents();
+            }
         }
 
-        public void Dispose()
+
+        private void CreateHandlerForRootNode(XElement root)
+        {                        
+            if (root == null) { throw new NullReferenceException("Root element is null"); }
+            if (root.Name == null) { throw new NullReferenceException("Root element's Name is null"); }
+            var root_name =  root.Name.ToString();
+            xmltv_logger.Verbose.Debug.WriteLine("Creating handler for root: '{0}'", root_name.ToString());
+            object raw_instance = null;
+            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+            CultureInfo culture = CultureInfo.CurrentCulture;
+            Assembly asm = Assembly.GetExecutingAssembly();
+            var types = asm.GetTypes();
+            Type handler_type = null;
+            foreach (var type in types)
+            {
+                if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
+                {
+                    try
+                    {
+                        var handler_prop = type.GetProperty("Handler");
+                        if (handler_prop != null)
+                        {
+                            raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
+                            if (raw_instance != null)
+                            {
+                                object handler_value = handler_prop.GetValue(raw_instance, null);
+                                if (handler_value != null && handler_value.ToString() == root_name)
+                                {
+                                    handler_type = type;
+                                    break;
+                                }
+                            }                            
+                        }
+                    }
+                    catch (Exception) { }
+                }
+            }
+            if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
+            xmltv_logger.Verbose.Debug.WriteLine("Created handler for root: '{0}'", root_name.ToString());
+            raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance }, culture);
+        }
+
+        private bool CreateHandlerForNode(XElement node)
         {
-            //throw new NotImplementedException();
+            if (node == null) { throw new NullReferenceException("Node element is null"); }
+            if (node.Name == null) { throw new NullReferenceException("Node element's Name is null"); }
+            var node_name = node.Name.ToString();
+
+            xmltv_logger.Verbose.Debug.WriteLine("Creating handler for node: '{0}'", node_name.ToString());
+            object raw_instance = null;
+            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+            CultureInfo culture = CultureInfo.CurrentCulture;
+            Assembly asm = Assembly.GetExecutingAssembly();
+            var types = asm.GetTypes();
+            Type handler_type = null;
+            foreach (var type in types)
+            {
+                if (type.BaseType != null && type.BaseType == typeof(XMLTVBase<XMLTVRuntimeInstance>))
+                {
+                    try
+                    {
+                        var handler_prop = type.GetProperty("Handler");
+                        if (handler_prop != null)
+                        {
+                            raw_instance = Activator.CreateInstance(type, flags, null, new object[0], culture);
+                            if (raw_instance != null)
+                            {
+                                object handler_value = handler_prop.GetValue(raw_instance, null);
+                                if (handler_value != null && handler_value.ToString() == node_name)
+                                {
+                                    handler_type = type;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    catch (Exception) { }
+                }
+            }
+            if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); }
+            xmltv_logger.Verbose.Debug.WriteLine("Created handler for node: '{0}'", node_name.ToString());
+            raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { gInstance, node }, culture);
+            return true;
         }
+        
     }
 }

 

  ViewVC Help
Powered by ViewVC 1.1.22