--- trunk/libxmltv/Core/XMLTVProgram.cs 2013/03/09 12:46:38 85 +++ trunk/libxmltv/Core/XMLTVProgram.cs 2013/03/09 13:51:58 86 @@ -7,6 +7,7 @@ using System.Reflection; using System.IO; using System.Diagnostics; +using System.Globalization; namespace libxmltv.Core { @@ -15,17 +16,13 @@ { public XMLTVProgram() : base(null,XMLTVConstants.PROGRAM_ELEMENT) { - Id = 0; - Start = new DateTime(); - Stop = new DateTime(); - Channel = new XMLTVChannel(); - Title = string.Empty; - SubTitle = string.Empty; - Description = string.Empty; + InternalDictionaryAddKnownProperties(); + } public XMLTVProgram(XMLTVRuntimeInstance instance, XElement node) : base(instance, XMLTVConstants.PROGRAM_ELEMENT) { + InternalDictionaryAddKnownProperties(); try { xmltv_logger.Verbose.Debug.WriteLine("Creating Instance of XMLTVProgram"); Create(node); @@ -35,19 +32,63 @@ catch (IOException ex) { Debug.WriteLine(ex.ToString()); } } #region IXMLTVProgram members - public int Id { get; set; } - public DateTime Start { get; set; } - public DateTime Stop { get; set; } - public IXMLTVChannel Channel { get; set; } - public string Title { get; set; } - public string SubTitle { get; set; } - public string Description { get; set; } + //public int Id { get; set; } + //public DateTime Start { get; set; } + //public DateTime Stop { get; set; } + //public IXMLTVChannel Channel { get; set; } + //public string Title { get; set; } + //public string SubTitle { get; set; } + //public string Description { get; set; } + + private void InternalDictionaryAddKnownProperties() + { + Properties = new Dictionary(); + Properties.Add("Id", 0); + Properties.Add(XMLTVConstants.Programs.ProgramStart, new DateTime()); + Properties.Add(XMLTVConstants.Programs.ProgramStop, new DateTime()); + Properties.Add(XMLTVConstants.Programs.ProgramChannelId, string.Empty); + Properties.Add(XMLTVConstants.Programs.ProgramTitle, string.Empty); + Properties.Add(XMLTVConstants.Programs.ProgramSubTitle, string.Empty); + Properties.Add(XMLTVConstants.Programs.ProgramDescription, string.Empty); + } + + public Dictionary Properties { get; private set; } + + private void InternalDictionaryTestOrThrow() + { + if (Properties == null) { throw new NullReferenceException("Properties collection has not been initialized."); } + if (Properties.Count == 0) { throw new IndexOutOfRangeException("Properties collection has 0 elements."); } + } + private void InternalProperyExistsOrThrow(string name) + { + InternalDictionaryTestOrThrow(); + if (!Properties.ContainsKey(name)) { throw new KeyNotFoundException(string.Format("Property '{0}' does not exist", name)); } + } + public object GetProperty(string name) + { + InternalProperyExistsOrThrow(name); + return Properties[name]; + } + public void SetProperty(string name, object value) + { + InternalProperyExistsOrThrow(name); + Properties[name] = value; + } #endregion public override string ToString() { - return string.Format("{0}: {1} - {2} ({3}) ['{4}' <==> '{5}']", Id, Title, SubTitle, Channel.ToString(), Start.ToString("yyyy/MM/dd hh:mm tt"), Stop.ToString("yyyy/MM/dd hh:mm tt")); + return string.Format("{0}: {1} - {2} ({3}) ['{4}' <==> '{5}']", + GetProperty("Id").ToString(), + GetProperty(XMLTVConstants.Programs.ProgramTitle).ToString(), + GetProperty(XMLTVConstants.Programs.ProgramSubTitle), ToString(), + GetProperty(XMLTVConstants.Programs.ProgramChannelId).ToString(), + ((DateTime)GetProperty(XMLTVConstants.Programs.ProgramStart)).ToString("yyyy/MM/dd hh:mm tt"), + ((DateTime)GetProperty(XMLTVConstants.Programs.ProgramStop)).ToString("yyyy/MM/dd hh:mm tt")); } + + + private void UpdateInstance() { bool found_field = false; @@ -62,7 +103,7 @@ { var list = (List)field.GetValue(this.GetInstance()); - this.Id = list.Count + 1; + this.SetProperty("Id", list.Count + 1); list.Add(this); xmltv_logger.Verbose.Debug.WriteLine("Updating instance with program information: {0}", this.ToString()); field.SetValue(this.GetInstance(), list); @@ -83,61 +124,135 @@ private void Create(XElement node) { - if (node.HasAttributes) + //if (node.HasAttributes) + //{ + // var start = node.Attribute(XMLTVConstants.Programs.ProgramStart); + // this.Start = start == null ? new DateTime() : ParseDate(start.Value); + // if (!this.Start.Equals(new DateTime())) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_start: {0}", start); } + + // var stop = node.Attribute(XMLTVConstants.Programs.ProgramStop); + // this.Stop = stop == null ? new DateTime() : ParseDate(stop.Value); + // if (!this.Stop.Equals(new DateTime())) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_stop: {0}", stop); } + + // var channelid = node.Attribute(XMLTVConstants.Programs.ProgramChannelId); + // if (!string.IsNullOrEmpty(this.Description)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_channelid: {0}", channelid); } + // IXMLTVChannel channel = new XMLTVChannel(); + // string _channelid = channelid == null ? string.Empty : channelid.Value; + // this.Channel = this.GetInstance().Channels.Find(m => m.Id == _channelid); + // if (this.Channel == null) { this.Channel = new XMLTVChannel(); } + // if (!string.IsNullOrEmpty(_channelid)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_channel: {0}", this.Channel.ToString()); } //} + //try + //{ + // var title = node.Descendants(XMLTVConstants.Programs.ProgramTitle).FirstOrDefault(); + // this.Title = title == null ? string.Empty : title.Value; + //} + //catch (Exception) { this.Title = string.Empty; } + //if (!string.IsNullOrEmpty(this.Title)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_title: {0}", this.Title == string.Empty ? "empty" : this.Title); } + //try + //{ + // var subtitle = node.Descendants(XMLTVConstants.Programs.ProgramSubTitle).FirstOrDefault(); + // this.SubTitle = subtitle == null ? string.Empty : subtitle.Value; + //} + //catch (Exception) { this.SubTitle = string.Empty; } + //if (!string.IsNullOrEmpty(this.SubTitle)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_subtitle: {0}", this.SubTitle == string.Empty ? "empty" : this.SubTitle); } + //try + //{ + // var description = node.Descendants(XMLTVConstants.Programs.ProgramDescription).FirstOrDefault(); + // this.Description = description == null ? string.Empty : description.Value; ; + //} + //catch (Exception) { this.Description = string.Empty; } + //if (!string.IsNullOrEmpty(this.Description)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_description: {0}", this.Description == string.Empty ? "empty" : this.Description); } + + //ParseExtraData(node); + + var nodes = node.Elements().ToList(); + foreach (var sub_node in nodes) { - var start = node.Attribute(XMLTVConstants.Programs.ProgramStart); - this.Start = start == null ? new DateTime() : ParseDate(start.Value); - if (!this.Start.Equals(new DateTime())) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_start: {0}", start); } - - var stop = node.Attribute(XMLTVConstants.Programs.ProgramStop); - this.Stop = stop == null ? new DateTime() : ParseDate(stop.Value); - if (!this.Stop.Equals(new DateTime())) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_stop: {0}", stop); } - - var channelid = node.Attribute(XMLTVConstants.Programs.ProgramChannelId); - if (!string.IsNullOrEmpty(this.Description)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_channelid: {0}", channelid); } - IXMLTVChannel channel = new XMLTVChannel(); - string _channelid = channelid == null ? string.Empty : channelid.Value; - this.Channel = this.GetInstance().Channels.Find(m => m.Id == _channelid); - if (this.Channel == null) { this.Channel = new XMLTVChannel(); } - if (!string.IsNullOrEmpty(_channelid)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_channel: {0}", this.Channel.ToString()); } + if (this.GetInstance().IsAborting) + { + break; + } + CreateHandlerForProgramMetaDataNode(sub_node); } + } + private DateTime ParseDate(string timeStamp) + { + DateTime dt = new DateTime(); try { - var title = node.Descendants(XMLTVConstants.Programs.ProgramTitle).FirstOrDefault(); - this.Title = title == null ? string.Empty : title.Value; + dt = DateTime.ParseExact(timeStamp, "yyyyMMddHHmmss zzzz", System.Globalization.CultureInfo.CurrentCulture); } - catch (Exception) { this.Title = string.Empty; } - if (!string.IsNullOrEmpty(this.Title)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_title: {0}", this.Title == string.Empty ? "empty" : this.Title); } - try + catch (Exception ex) { throw ex; } + return dt; + } + + private void CreateHandlerForProgramMetaDataNode(XElement node) + { + Type t = this.GetType(); + Assembly asm = t.Assembly; + var types = asm.GetTypes(); + var classes = types.ToList().FindAll( + m => + m.DeclaringType == t && + m.IsClass && + !m.IsSealed + ); + classes.TrimExcess(); + + object raw_instance = null; + BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + CultureInfo culture = CultureInfo.CurrentCulture; + Type handler_type = null; + foreach (var type in classes) { - var subtitle = node.Descendants(XMLTVConstants.Programs.ProgramSubTitle).FirstOrDefault(); - this.SubTitle = subtitle == null ? string.Empty : subtitle.Value; + 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; } } + 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; + break; + } + } + } + } + } } - catch (Exception) { this.SubTitle = string.Empty; } - if (!string.IsNullOrEmpty(this.SubTitle)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_subtitle: {0}", this.SubTitle == string.Empty ? "empty" : this.SubTitle); } - try + if (handler_type == null) { - var description = node.Descendants(XMLTVConstants.Programs.ProgramDescription).FirstOrDefault(); - this.Description = description == null ? string.Empty : description.Value; ; + 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[] { ' ' })); + xmltv_logger.Verbose.Warn.WriteLine("Ignoring unhandled extra meta-data: {0}", node_text); } - catch (Exception) { this.Description = string.Empty; } - if (!string.IsNullOrEmpty(this.Description)) { xmltv_logger.Verbose.Debug.WriteLine("\tprogram_description: {0}", this.Description == string.Empty ? "empty" : this.Description); } - - //entries.Add(program.Id, program); - //program_index++; - //progress = 100.0 * (program_index / program_count); - //xmltv_logger.ReportProgress(this, new Enterprise.Logging.ReportProgressEventArgs((int)progress)); - //Application.DoEvents(); + raw_instance = Activator.CreateInstance(handler_type, flags, null, new object[] { this, node }, culture); } - private DateTime ParseDate(string timeStamp) + + + + #region sub-classes + private class title : XMLTVBase { - DateTime dt = new DateTime(); - try + public title() : base(null, XMLTVConstants.Programs.ProgramTitle) { } + public title(XMLTVProgram instance, XElement node) + : base(instance, XMLTVConstants.Programs.ProgramTitle) { - dt = DateTime.ParseExact(timeStamp, "yyyyMMddHHmmss zzzz", System.Globalization.CultureInfo.CurrentCulture); } - catch (Exception ex) { throw ex; } - return dt; } + #endregion } }