diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-25 15:02:04 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-25 15:02:04 -0400 |
| commit | ef6b90b8e6e6c317fcda85a392c79324f91250db (patch) | |
| tree | 570c78c0915d3608399f003038b66d56e5e29e84 /MediaBrowser.LocalMetadata | |
| parent | edbe28d9fc3091121b7e2323fe42d62a70c9e351 (diff) | |
make controller project portable
Diffstat (limited to 'MediaBrowser.LocalMetadata')
28 files changed, 1471 insertions, 30 deletions
diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index f23559e4b..cf95e4629 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -3,7 +3,9 @@ using MediaBrowser.Controller.Providers; using System.IO; using System.Threading; using System.Threading.Tasks; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata { diff --git a/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs index 21b3cedae..651273eb0 100644 --- a/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs @@ -1,7 +1,9 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using System.Collections.Generic; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Images { diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index 716d40d8f..e02326838 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -6,7 +6,9 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Images { diff --git a/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs index 6034008de..6b2056289 100644 --- a/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; using System.IO; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; namespace MediaBrowser.LocalMetadata.Images diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs index 1cec4d305..e4ddb409f 100644 --- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -4,7 +4,9 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Images { diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index ef9160b70..2f7059fec 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -7,7 +7,9 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Images { diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 9a74d6b3e..e88d5e208 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -32,10 +32,6 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> - <Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath> - </Reference> <Reference Include="Patterns.Logging"> <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath> </Reference> @@ -57,6 +53,7 @@ <Compile Include="Images\ImagesByNameImageProvider.cs" /> <Compile Include="Images\InternalMetadataFolderImageProvider.cs" /> <Compile Include="Images\LocalImageProvider.cs" /> + <Compile Include="Parsers\BaseItemXmlParser.cs" /> <Compile Include="Parsers\BoxSetXmlParser.cs" /> <Compile Include="Parsers\EpisodeXmlParser.cs" /> <Compile Include="Parsers\GameSystemXmlParser.cs" /> diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs new file mode 100644 index 000000000..a5d9947f4 --- /dev/null +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -0,0 +1,1393 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Xml; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.LocalMetadata.Parsers +{ + /// <summary> + /// Provides a base class for parsing metadata xml + /// </summary> + /// <typeparam name="T"></typeparam> + public class BaseItemXmlParser<T> + where T : BaseItem + { + /// <summary> + /// The logger + /// </summary> + protected ILogger Logger { get; private set; } + protected IProviderManager ProviderManager { get; private set; } + + private Dictionary<string, string> _validProviderIds; + + /// <summary> + /// Initializes a new instance of the <see cref="BaseItemXmlParser{T}" /> class. + /// </summary> + /// <param name="logger">The logger.</param> + public BaseItemXmlParser(ILogger logger, IProviderManager providerManager) + { + Logger = logger; + ProviderManager = providerManager; + } + + /// <summary> + /// Fetches metadata for an item from one xml file + /// </summary> + /// <param name="item">The item.</param> + /// <param name="metadataFile">The metadata file.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <exception cref="System.ArgumentNullException"></exception> + public void Fetch(MetadataResult<T> item, string metadataFile, CancellationToken cancellationToken) + { + if (item == null) + { + throw new ArgumentNullException(); + } + + if (string.IsNullOrEmpty(metadataFile)) + { + throw new ArgumentNullException(); + } + + var settings = new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + }; + + _validProviderIds = _validProviderIds = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); + + var idInfos = ProviderManager.GetExternalIdInfos(item.Item); + + foreach (var info in idInfos) + { + var id = info.Key + "Id"; + if (!_validProviderIds.ContainsKey(id)) + { + _validProviderIds.Add(id, info.Key); + } + } + + //Additional Mappings + _validProviderIds.Add("IMDB", "Imdb"); + + //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); + Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); + } + + /// <summary> + /// Fetches the specified item. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="metadataFile">The metadata file.</param> + /// <param name="settings">The settings.</param> + /// <param name="encoding">The encoding.</param> + /// <param name="cancellationToken">The cancellation token.</param> + private void Fetch(MetadataResult<T> item, string metadataFile, XmlReaderSettings settings, Encoding encoding, CancellationToken cancellationToken) + { + item.ResetPeople(); + + using (var streamReader = new StreamReader(metadataFile, encoding)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, settings)) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + FetchDataFromXmlNode(reader, item); + } + } + } + } + } + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + /// <summary> + /// Fetches metadata from one Xml Element + /// </summary> + /// <param name="reader">The reader.</param> + /// <param name="itemResult">The item result.</param> + protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult<T> itemResult) + { + var item = itemResult.Item; + + switch (reader.Name) + { + // DateCreated + case "Added": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + DateTime added; + if (DateTime.TryParse(val, out added)) + { + item.DateCreated = added.ToUniversalTime(); + } + else + { + Logger.Warn("Invalid Added value found: " + val); + } + } + break; + } + + case "OriginalTitle": + { + var val = reader.ReadElementContentAsString(); + + var hasOriginalTitle = item as IHasOriginalTitle; + if (hasOriginalTitle != null) + { + if (!string.IsNullOrEmpty(hasOriginalTitle.OriginalTitle)) + { + hasOriginalTitle.OriginalTitle = val; + } + } + break; + } + + case "LocalTitle": + item.Name = reader.ReadElementContentAsString(); + break; + + case "Type": + { + var type = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(type) && !type.Equals("none", StringComparison.OrdinalIgnoreCase)) + { + item.DisplayMediaType = type; + } + + break; + } + + case "CriticRating": + { + var text = reader.ReadElementContentAsString(); + + if (!string.IsNullOrEmpty(text)) + { + float value; + if (float.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + item.CriticRating = value; + } + } + + break; + } + + case "Budget": + { + var text = reader.ReadElementContentAsString(); + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + double value; + if (double.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasBudget.Budget = value; + } + } + + break; + } + + case "Revenue": + { + var text = reader.ReadElementContentAsString(); + var hasBudget = item as IHasBudget; + if (hasBudget != null) + { + double value; + if (double.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasBudget.Revenue = value; + } + } + + break; + } + + case "Metascore": + { + var text = reader.ReadElementContentAsString(); + var hasMetascore = item as IHasMetascore; + if (hasMetascore != null) + { + float value; + if (float.TryParse(text, NumberStyles.Any, _usCulture, out value)) + { + hasMetascore.Metascore = value; + } + } + + break; + } + + case "AwardSummary": + { + var text = reader.ReadElementContentAsString(); + var hasAwards = item as IHasAwards; + if (hasAwards != null) + { + if (!string.IsNullOrWhiteSpace(text)) + { + hasAwards.AwardSummary = text; + } + } + + break; + } + + case "SortTitle": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.ForcedSortName = val; + } + break; + } + + case "Overview": + case "Description": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.Overview = val; + } + + break; + } + + case "ShortOverview": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.ShortOverview = val; + } + + break; + } + + case "CriticRatingSummary": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.CriticRatingSummary = val; + } + + break; + } + + case "Language": + { + var val = reader.ReadElementContentAsString(); + + item.PreferredMetadataLanguage = val; + + break; + } + + case "CountryCode": + { + var val = reader.ReadElementContentAsString(); + + item.PreferredMetadataCountryCode = val; + + break; + } + + case "PlaceOfBirth": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var person = item as Person; + if (person != null) + { + person.ProductionLocations = new List<string> { val }; + } + } + + break; + } + + case "Website": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.HomePageUrl = val; + } + + break; + } + + case "LockedFields": + { + var fields = new List<MetadataFields>(); + + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + var list = val.Split('|').Select(i => + { + MetadataFields field; + + if (Enum.TryParse<MetadataFields>(i, true, out field)) + { + return (MetadataFields?)field; + } + + return null; + + }).Where(i => i.HasValue).Select(i => i.Value); + + fields.AddRange(list); + } + + item.LockedFields = fields; + + break; + } + + case "TagLines": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromTaglinesNode(subtree, item); + } + break; + } + + case "Countries": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromCountriesNode(subtree, item); + } + break; + } + + case "ContentRating": + case "MPAARating": + { + var rating = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(rating)) + { + item.OfficialRating = rating; + } + break; + } + + case "MPAADescription": + { + var rating = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(rating)) + { + item.OfficialRatingDescription = rating; + } + break; + } + + case "CustomRating": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.CustomRating = val; + } + break; + } + + case "RunningTime": + { + var text = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(text)) + { + int runtime; + if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, _usCulture, out runtime)) + { + item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; + } + } + break; + } + + case "AspectRatio": + { + var val = reader.ReadElementContentAsString(); + + var hasAspectRatio = item as IHasAspectRatio; + if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null) + { + hasAspectRatio.AspectRatio = val; + } + break; + } + + case "LockData": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + } + break; + } + + case "Network": + { + foreach (var name in SplitNames(reader.ReadElementContentAsString())) + { + if (string.IsNullOrWhiteSpace(name)) + { + continue; + } + item.AddStudio(name); + } + break; + } + + case "Director": + { + foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.Director })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + itemResult.AddPerson(p); + } + break; + } + case "Writer": + { + foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.Writer })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + itemResult.AddPerson(p); + } + break; + } + + case "Actors": + { + + var actors = reader.ReadInnerXml(); + + if (actors.Contains("<")) + { + // This is one of the mis-named "Actors" full nodes created by MB2 + // Create a reader and pass it to the persons node processor + FetchDataFromPersonsNode(new XmlTextReader(new StringReader("<Persons>" + actors + "</Persons>")), itemResult); + } + else + { + // Old-style piped string + foreach (var p in SplitNames(actors).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.Actor })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + itemResult.AddPerson(p); + } + } + break; + } + + case "GuestStars": + { + foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new Controller.Entities.PersonInfo { Name = v.Trim(), Type = PersonType.GuestStar })) + { + if (string.IsNullOrWhiteSpace(p.Name)) + { + continue; + } + itemResult.AddPerson(p); + } + break; + } + + case "Trailer": + { + var val = reader.ReadElementContentAsString(); + + var hasTrailers = item as IHasTrailers; + if (hasTrailers != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasTrailers.AddTrailerUrl(val, false); + } + } + break; + } + + case "DisplayOrder": + { + var val = reader.ReadElementContentAsString(); + + var hasDisplayOrder = item as IHasDisplayOrder; + if (hasDisplayOrder != null) + { + if (!string.IsNullOrWhiteSpace(val)) + { + hasDisplayOrder.DisplayOrder = val; + } + } + break; + } + + case "Trailers": + { + using (var subtree = reader.ReadSubtree()) + { + var hasTrailers = item as IHasTrailers; + if (hasTrailers != null) + { + FetchDataFromTrailersNode(subtree, hasTrailers); + } + } + break; + } + + case "ProductionYear": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int productionYear; + if (int.TryParse(val, out productionYear) && productionYear > 1850) + { + item.ProductionYear = productionYear; + } + } + + break; + } + + case "Rating": + case "IMDBrating": + { + + var rating = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(rating)) + { + float val; + // All external meta is saving this as '.' for decimal I believe...but just to be sure + if (float.TryParse(rating.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out val)) + { + item.CommunityRating = val; + } + } + break; + } + + case "BirthDate": + case "PremiereDate": + case "FirstAired": + { + var firstAired = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(firstAired)) + { + DateTime airDate; + + if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out airDate) && airDate.Year > 1850) + { + item.PremiereDate = airDate.ToUniversalTime(); + item.ProductionYear = airDate.Year; + } + } + + break; + } + + case "DeathDate": + case "EndDate": + { + var firstAired = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(firstAired)) + { + DateTime airDate; + + if (DateTime.TryParseExact(firstAired, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out airDate) && airDate.Year > 1850) + { + item.EndDate = airDate.ToUniversalTime(); + } + } + + break; + } + + case "VoteCount": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + int num; + + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num)) + { + item.VoteCount = num; + } + } + break; + } + case "CollectionNumber": + var tmdbCollection = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(tmdbCollection)) + { + item.SetProviderId(MetadataProviders.TmdbCollection, tmdbCollection); + } + break; + + case "Genres": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromGenresNode(subtree, item); + } + break; + } + + case "Tags": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromTagsNode(subtree, item); + } + break; + } + + case "PlotKeywords": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromKeywordsNode(subtree, item); + } + break; + } + + case "Persons": + { + using (var subtree = reader.ReadSubtree()) + { + FetchDataFromPersonsNode(subtree, itemResult); + } + break; + } + + case "Studios": + { + using (var subtree = reader.ReadSubtree()) + { + FetchFromStudiosNode(subtree, item); + } + break; + } + + case "Shares": + { + using (var subtree = reader.ReadSubtree()) + { + var hasShares = item as IHasShares; + if (hasShares != null) + { + FetchFromSharesNode(subtree, hasShares); + } + } + break; + } + + case "Format3D": + { + var video = item as Video; + + if (video != null) + { + var val = reader.ReadElementContentAsString(); + + if (string.Equals("HSBS", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.HalfSideBySide; + } + else if (string.Equals("HTAB", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.HalfTopAndBottom; + } + else if (string.Equals("FTAB", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.FullTopAndBottom; + } + else if (string.Equals("FSBS", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.FullSideBySide; + } + else if (string.Equals("MVC", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.MVC; + } + } + break; + } + + default: + { + string readerName = reader.Name; + string providerIdValue; + if (_validProviderIds.TryGetValue(readerName, out providerIdValue)) + { + var id = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(id)) + { + item.SetProviderId(providerIdValue, id); + } + } + else + { + reader.Skip(); + } + + break; + + } + } + } + + private void FetchFromSharesNode(XmlReader reader, IHasShares item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Share": + { + using (var subtree = reader.ReadSubtree()) + { + var share = GetShareFromNode(subtree); + if (share != null) + { + item.Shares.Add(share); + } + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + private Share GetShareFromNode(XmlReader reader) + { + var share = new Share(); + + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "UserId": + { + share.UserId = reader.ReadElementContentAsString(); + break; + } + + case "CanEdit": + { + share.CanEdit = string.Equals(reader.ReadElementContentAsString(), true.ToString(), StringComparison.OrdinalIgnoreCase); + break; + } + + default: + reader.Skip(); + break; + } + } + } + + return share; + } + + private void FetchFromCountriesNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Country": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + /// <summary> + /// Fetches from taglines node. + /// </summary> + /// <param name="reader">The reader.</param> + /// <param name="item">The item.</param> + private void FetchFromTaglinesNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Tagline": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.Tagline = val; + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + /// <summary> + /// Fetches from genres node. + /// </summary> + /// <param name="reader">The reader.</param> + /// <param name="item">The item.</param> + private void FetchFromGenresNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Genre": + { + var genre = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(genre)) + { + item.AddGenre(genre); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + private void FetchFromTagsNode(XmlReader reader, BaseItem item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Tag": + { + var tag = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(tag)) + { + item.AddTag(tag); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + private void FetchFromKeywordsNode(XmlReader reader, BaseItem item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "PlotKeyword": + { + var tag = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(tag)) + { + item.AddKeyword(tag); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + /// <summary> + /// Fetches the data from persons node. + /// </summary> + /// <param name="reader">The reader.</param> + /// <param name="item">The item.</param> + private void FetchDataFromPersonsNode(XmlReader reader, MetadataResult<T> item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Person": + case "Actor": + { + using (var subtree = reader.ReadSubtree()) + { + foreach (var person in GetPersonsFromXmlNode(subtree)) + { + if (string.IsNullOrWhiteSpace(person.Name)) + { + continue; + } + item.AddPerson(person); + } + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + private void FetchDataFromTrailersNode(XmlReader reader, IHasTrailers item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Trailer": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + item.AddTrailerUrl(val, false); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + protected List<ChapterInfo> FetchChaptersFromXmlNode(BaseItem item, XmlReader reader) + { + using (reader) + { + return GetChaptersFromXmlNode(reader) + .Where(i => i.StartPositionTicks >= 0) + .ToList(); + } + } + + private IEnumerable<ChapterInfo> GetChaptersFromXmlNode(XmlReader reader) + { + var chapters = new List<ChapterInfo>(); + + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Chapter": + { + using (var subtree = reader.ReadSubtree()) + { + chapters.Add(GetChapterInfoFromXmlNode(subtree)); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + + return chapters; + } + + private ChapterInfo GetChapterInfoFromXmlNode(XmlReader reader) + { + var chapter = new ChapterInfo(); + + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "StartPositionMs": + { + var val = reader.ReadElementContentAsString(); + + var ms = long.Parse(val, _usCulture); + + chapter.StartPositionTicks = TimeSpan.FromMilliseconds(ms).Ticks; + + break; + } + + case "Name": + { + chapter.Name = reader.ReadElementContentAsString(); + break; + } + + default: + reader.Skip(); + break; + } + } + } + + return chapter; + } + + /// <summary> + /// Fetches from studios node. + /// </summary> + /// <param name="reader">The reader.</param> + /// <param name="item">The item.</param> + private void FetchFromStudiosNode(XmlReader reader, T item) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Studio": + { + var studio = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(studio)) + { + item.AddStudio(studio); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + + /// <summary> + /// Gets the persons from XML node. + /// </summary> + /// <param name="reader">The reader.</param> + /// <returns>IEnumerable{PersonInfo}.</returns> + private IEnumerable<PersonInfo> GetPersonsFromXmlNode(XmlReader reader) + { + var name = string.Empty; + var type = PersonType.Actor; // If type is not specified assume actor + var role = string.Empty; + int? sortOrder = null; + + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Name": + name = reader.ReadElementContentAsString() ?? string.Empty; + break; + + case "Type": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + type = val; + } + break; + } + + case "Role": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + role = val; + } + break; + } + case "SortOrder": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + int intVal; + if (int.TryParse(val, NumberStyles.Integer, _usCulture, out intVal)) + { + sortOrder = intVal; + } + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + + var personInfo = new PersonInfo + { + Name = name.Trim(), + Role = role, + Type = type, + SortOrder = sortOrder + }; + + return new[] { personInfo }; + } + + protected LinkedChild GetLinkedChild(XmlReader reader) + { + reader.MoveToContent(); + + var linkedItem = new LinkedChild + { + Type = LinkedChildType.Manual + }; + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Path": + { + linkedItem.Path = reader.ReadElementContentAsString(); + break; + } + + default: + reader.Skip(); + break; + } + } + } + + // This is valid + if (!string.IsNullOrWhiteSpace(linkedItem.Path)) + { + return linkedItem; + } + + return null; + } + + protected Share GetShare(XmlReader reader) + { + reader.MoveToContent(); + + var item = new Share(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "UserId": + { + item.UserId = reader.ReadElementContentAsString(); + break; + } + + case "CanEdit": + { + item.CanEdit = string.Equals(reader.ReadElementContentAsString(), "true", StringComparison.OrdinalIgnoreCase); + break; + } + + default: + reader.Skip(); + break; + } + } + } + + // This is valid + if (!string.IsNullOrWhiteSpace(item.UserId)) + { + return item; + } + + return null; + } + + + /// <summary> + /// Used to split names of comma or pipe delimeted genres and people + /// </summary> + /// <param name="value">The value.</param> + /// <returns>IEnumerable{System.String}.</returns> + private IEnumerable<string> SplitNames(string value) + { + value = value ?? string.Empty; + + // Only split by comma if there is no pipe in the string + // We have to be careful to not split names like Matthew, Jr. + var separator = value.IndexOf('|') == -1 && value.IndexOf(';') == -1 ? new[] { ',' } : new[] { '|', ';' }; + + value = value.Trim().Trim(separator); + + return string.IsNullOrWhiteSpace(value) ? new string[] { } : Split(value, separator, StringSplitOptions.RemoveEmptyEntries); + } + + /// <summary> + /// Provides an additional overload for string.split + /// </summary> + /// <param name="val">The val.</param> + /// <param name="separators">The separators.</param> + /// <param name="options">The options.</param> + /// <returns>System.String[][].</returns> + private static string[] Split(string val, char[] separators, StringSplitOptions options) + { + return val.Split(separators, options); + } + + } +} diff --git a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs index 71f6d3fe9..698f71e3c 100644 --- a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs @@ -8,7 +8,9 @@ using System.Globalization; using System.IO; using System.Threading; using System.Xml; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Parsers { diff --git a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs index 3acb2b74c..af8c84786 100644 --- a/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs @@ -4,7 +4,9 @@ using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Providers { diff --git a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs index 493df8c6a..29f879cb0 100644 --- a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs @@ -6,7 +6,9 @@ using MediaBrowser.Model.Logging; using System.Collections.Generic; using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Providers { diff --git a/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs index 7ac41e5cc..5322de98f 100644 --- a/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs @@ -1,8 +1,11 @@ using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; +using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; namespace MediaBrowser.LocalMetadata.Providers diff --git a/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs index 942befb83..9f4c662a2 100644 --- a/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs @@ -1,7 +1,9 @@ using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; diff --git a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs index c562df7fb..91371e044 100644 --- a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs @@ -4,7 +4,9 @@ using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Providers { diff --git a/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs index 333ea2823..36c2e1ebe 100644 --- a/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs @@ -4,7 +4,9 @@ using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Providers { diff --git a/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs index 49d8c09cc..0ccd8cbc6 100644 --- a/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs @@ -1,6 +1,8 @@ using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; diff --git a/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs index 2ccb8968b..1fac21c28 100644 --- a/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs @@ -1,8 +1,11 @@ using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; +using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; namespace MediaBrowser.LocalMetadata.Providers diff --git a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs index 149a3142d..4986976bd 100644 --- a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs @@ -4,7 +4,9 @@ using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Providers { diff --git a/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs index 26d3c7539..30530e85d 100644 --- a/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs @@ -1,7 +1,9 @@ using System.IO; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Model.IO; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Providers; using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; diff --git a/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs index 50f3bcda4..a62f606c8 100644 --- a/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs @@ -3,7 +3,9 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.LocalMetadata.Parsers; using MediaBrowser.Model.Logging; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Providers { diff --git a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs index b307ded97..c8a2fec90 100644 --- a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs index 8dad16fc2..2d8576aa3 100644 --- a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs @@ -9,7 +9,9 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs index ddfaedba6..e72cd392c 100644 --- a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs @@ -6,7 +6,9 @@ using System.IO; using System.Security; using System.Text; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs index 5592c068c..4e6703677 100644 --- a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs @@ -7,7 +7,9 @@ using System.IO; using System.Security; using System.Text; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs index 295e64881..a68d9adc2 100644 --- a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs @@ -6,7 +6,9 @@ using System.IO; using System.Security; using System.Text; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs index 8862f9c03..6d9fe21ee 100644 --- a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs @@ -7,7 +7,9 @@ using System.IO; using System.Security; using System.Text; using System.Threading; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs index 314840558..1767b23fe 100644 --- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs @@ -14,7 +14,9 @@ using System.Linq; using System.Security; using System.Text; using System.Xml; -using CommonIO; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.IO; +using MediaBrowser.Model.IO; namespace MediaBrowser.LocalMetadata.Savers { diff --git a/MediaBrowser.LocalMetadata/packages.config b/MediaBrowser.LocalMetadata/packages.config index ccef6d686..79ff26ec6 100644 --- a/MediaBrowser.LocalMetadata/packages.config +++ b/MediaBrowser.LocalMetadata/packages.config @@ -1,5 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="CommonIO" version="1.0.0.9" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> </packages>
\ No newline at end of file |
