--- trunk/libxmltv/Core/XMLTVRuntimeInstance.cs 2013/03/09 10:27:39 73 +++ trunk/libxmltv/Core/XMLTVRuntimeInstance.cs 2013/03/10 15:37:16 111 @@ -48,13 +48,14 @@ private void init() { - this.Source = new List(); + this.Source = new XMLTVSource(); this.Channels = new List(); this.Programs = new List(); this.XmlFile_Name = string.Empty; this.XmlFile_FullName = string.Empty; this.XmlDoc = string.Empty; this.OnInstanceCreated = null; + this.ExtraEntries = new List(); } #region IXMLTVRuntimeInstance members @@ -69,12 +70,15 @@ private string _XmlDoc; public string XmlDoc { get { return _XmlDoc; } set { _XmlDoc = value; } } - private List _Source; - public List Source { get { return _Source; } set { _Source = value; } } + private IXMLTVSource _Source; + public IXMLTVSource Source { get { return _Source; } set { _Source = value; } } private List _Channels; public List Channels { get { return _Channels; } set { _Channels = value; } } private List _Programs; public List Programs { get { return _Programs; } set { _Programs = value; } } + + private List _ExtraEntries; + public List ExtraEntries { get { return _ExtraEntries; } set { _ExtraEntries = value; } } #endregion #region IOnInstanceCreated members [NonSerialized] @@ -118,11 +122,12 @@ { throw new NullReferenceException("Failed to load from instance because the instance is null."); } - CloneFromInstance(ref instance); 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.FirstOrDefault().SourceName, this.Source.FirstOrDefault().GeneratorName, this.XmlFile_FullName); + xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Created by '{1}' - original source file: '{2}'", this.Source.SourceName, this.Source.GeneratorName, this.XmlFile_FullName); } else { @@ -131,7 +136,7 @@ } if (this.Channels != null) { - xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.FirstOrDefault().SourceName); + xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", this.Channels.Count, this.Source.SourceName); } else { @@ -140,14 +145,13 @@ } if (this.Programs != null) { - xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}'", this.Programs.Count, this.Source.FirstOrDefault().SourceName); + 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."); - } - xmltv_logger.Debug.WriteLine("Loaded from instance..."); + } return instance; } #endregion @@ -232,6 +236,7 @@ CreateLoader(xmlfile); CreateParser(); } + catch (ThreadAbortException ex) { Debug.WriteLine(ex.ToString()); } catch (Exception ex) { xmltv_logger.Error.WriteLine(ex.ToString()); @@ -240,33 +245,47 @@ private void CreateLoader(string xml_file) { + xmltv_logger.Verbose.Debug.WriteLine("Creating loader handle"); gInstance = new XMLTVRuntimeInstance(); - bool bound_to_ctor = false; 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)) { - 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; + //xmltv_logger.Verbose.Debug.WriteLine("Type: '{0}' Base: '{1}'", type.Name, type.BaseType == null ? "none" : type.BaseType.Name); object[] args = new object[] { xml_file, gInstance }; - try + var iface = type.GetInterface("IXMLTVHandler", true); + if (iface != null) { - raw_instance = Activator.CreateInstance(type, flags, null, args, culture); - bound_to_ctor = true; - } - catch (Exception ex) - { - Debug.WriteLine(ex.ToString()); + var handler_prop = type.GetProperty("Handler"); + if (handler_prop != null) + { + var ctors = type.GetConstructors(flags); + bool has_string_ctor = false; + foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 1 && ctor.GetParameters()[0].ParameterType == typeof(string)) { has_string_ctor = true; } } + if (!has_string_ctor) { continue; } + raw_instance = Activator.CreateInstance(type, flags, null, new object[] { xml_file}, culture); + if (raw_instance != null) + { + object handler_value = handler_prop.GetValue(raw_instance, null); + if (handler_value != null && handler_value.ToString() == xml_file) + { + handler_type = type; + break; + } + } + } } } } - if (!bound_to_ctor) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); } + if (handler_type == null) { throw new Exception("Unable to find a compatible XMLTV Data Loader."); } + xmltv_logger.Verbose.Debug.WriteLine("Created loader handle"); + raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] {xml_file , gInstance }, culture); if (raw_instance == null) { throw new NullReferenceException("Found a compatible XMLTV Data Loader, but it returned invalid data."); } IGetInstance getter_instance = (raw_instance as IGetInstance); if (getter_instance != null) { gInstance = getter_instance.GetInstance(); } @@ -275,17 +294,34 @@ private void CreateParser() { var doc = XDocument.Parse(this.GetInstance().XmlDoc); - var root_element = doc.Root.Name; - if (root_element == null) { throw new NullReferenceException("Root element is null"); } - CreateRootHandler(root_element.ToString()); - + 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(); + } } - private void CreateRootHandler(string root_element) - { + 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; @@ -295,31 +331,156 @@ foreach (var type in types) { if (type.BaseType != null && type.BaseType == typeof(XMLTVBase)) - { - try + { + var iface = type.GetInterface("IXMLTVHandler", true); + if (iface != null) { var handler_prop = type.GetProperty("Handler"); if (handler_prop != null) { + var ctors = type.GetConstructors(flags); + bool has_default_ctor = false; + foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 0) { has_default_ctor = true; } } + ctors = null; + if (!has_default_ctor) { continue; } 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_element) + if (handler_value != null && handler_value.ToString() == root_name) { handler_type = type; + handler_value = null; + raw_instance = null; + handler_prop = null; + iface = null; break; } - } + handler_value = null; + } + raw_instance = null; } + handler_prop = null; } - catch (Exception) { } + iface = null; } } - if (handler_type == null) { throw new Exception("Unable to find a compatible handler to parse document root."); } + asm = null; + types = null; + if (handler_type == null) + { + StringBuilder node_builder = new StringBuilder(); + node_builder.AppendFormat("<{0} ", root.Name); + if (root.HasAttributes) { foreach (var attribute in root.Attributes()) { node_builder.AppendFormat("{0}=\"{1}\" ", attribute.Name, attribute.Value); } } + string node_text = string.Format("{0}>", node_builder.ToString().TrimEnd(new char[] { ' ' })); + throw new Exception(string.Format("Unable to find a compatible handler to parse node: {0}", node_text)); + } + 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); + raw_instance = null; + flags = 0; + culture = null; } + private bool CreateHandlerForNode(XElement node) + { + 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)) + { + var iface = type.GetInterface("IXMLTVHandler", true); + if (iface != null) + { + var handler_prop = type.GetProperty("Handler"); + if (handler_prop != null) + { + var ctors = type.GetConstructors(flags); + bool has_default_ctor = false; + foreach (var ctor in ctors) { if (ctor.GetParameters().Count() == 0) { has_default_ctor = true; } } + ctors = null; + if (!has_default_ctor) { continue; } + 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.ToString()) + { + handler_type = type; + handler_value = null; + raw_instance = null; + handler_prop = null; + iface = null; + break; + } + handler_value = null; + } + raw_instance = null; + } + handler_prop = null; + } + iface = null; + } + } + asm = null; + types = null; + if (handler_type == null) + { + try + { + raw_instance = Activator.CreateInstance(typeof(UnhandledNodeData), flags, null, new object[] { gInstance, node }, culture); + } + catch (Exception ex) { throw ex; } + + if (raw_instance == null) + { + StringBuilder node_builder = new StringBuilder(); + node_builder.AppendFormat("<{0} ", node.Name); + if (node.HasAttributes) { foreach (var attribute in node.Attributes()) { node_builder.AppendFormat("{0}=\"{1}\" ", attribute.Name, attribute.Value); } } + string node_text = string.Format("{0}>", node_builder.ToString().TrimEnd(new char[] { ' ' })); + throw new Exception(string.Format("Unable to find a compatible handler to parse node: {0}", node_text)); + } + } + else + { + 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); + } + raw_instance = null; + flags = 0; + culture = null; + node = null; + return true; + } + #region UnhandledExtraMetaData + private class UnhandledNodeData : XMLTVBase + { + public UnhandledNodeData() : base(null, null) { } + public UnhandledNodeData(XMLTVRuntimeInstance instance, XElement node) + : base(instance, null) + { + if (node == null) { throw new NullReferenceException("The node instance was null"); } + xmltv_logger.Verbose.Debug.WriteLine("Parsng unhandled node data: {0}", node.Name.ToString()); + if (this.GetInstance() != null) + { + ExtraMetaData data = new ExtraMetaData(node); + instance.ExtraEntries.Add(data); + data = null; + } + node = null; + } + } + #endregion } }