Skip to content

Commit

Permalink
Merge pull request #1450 from Microsoft/staging
Browse files Browse the repository at this point in the history
Merging into master for 2.0
  • Loading branch information
nmetulev authored Aug 29, 2017
2 parents e684405 + 6e90c75 commit 19dff74
Show file tree
Hide file tree
Showing 612 changed files with 23,543 additions and 8,753 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,11 @@ BundleArtifacts
!/build
/build/tools/GitVersion.CommandLine
AppPackages

# NuGet V3 artifacts
*-packages.config
*.nuget.props
*.nuget.targets
project.lock.json
msbuild.binlog
*.project.lock.json
101 changes: 101 additions & 0 deletions Microsoft.Toolkit.Services/Core/DataProviderBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Toolkit.Services.Exceptions;
using System.Net.Http;

namespace Microsoft.Toolkit.Services
{
/// <summary>
/// Base class for data providers in this library.
/// </summary>
/// <typeparam name="TConfig">Query configuration type for given provider.</typeparam>
public abstract class DataProviderBase<TConfig>
{
/// <summary>
/// Constructor
/// </summary>
public DataProviderBase()
{

}

/// <summary>
/// Load data from provider endpoint.
/// </summary>
/// <typeparam name="TSchema">Strong typed object to parse the response items into.</typeparam>
/// <param name="config">Query configuration.</param>
/// <param name="maxRecords">Upper record limit.</param>
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
/// <param name="parser">Parser to use for results.</param>
/// <returns>Strong typed list of results.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an async method, so nesting generic types is necessary.")]
public async Task<IEnumerable<TSchema>> LoadDataAsync<TSchema>(TConfig config, int maxRecords, int pageIndex, IParser<TSchema> parser)
where TSchema : SchemaBase
{
if (config == null)
{
throw new ConfigNullException();
}

if (parser == null)
{
throw new ParserNullException();
}

ValidateConfig(config);

var result = await GetDataAsync(config, maxRecords, pageIndex, parser);
if (result != null)
{
return result
.Take(maxRecords)
.ToList();
}

return Array.Empty<TSchema>();
}

private static HttpClient httpClient;

/// <summary>
/// Static instance of HttpClient.
/// </summary>
public static HttpClient HttpClient
{
get { return httpClient ?? (httpClient = new HttpClient()); }
set { httpClient = value; }
}

/// <summary>
/// Derived classes will have to implement this method to return provider data
/// </summary>
/// <param name="config">Configuration to use</param>
/// <param name="maxRecords">Maximum number of records to return</param>
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
/// <param name="parser">Parser to use</param>
/// <typeparam name="TSchema">Schema defining data returned</typeparam>
/// <returns>List of data</returns>
protected abstract Task<IEnumerable<TSchema>> GetDataAsync<TSchema>(TConfig config, int maxRecords, int pageIndex, IParser<TSchema> parser)
where TSchema : SchemaBase;

/// <summary>
/// Method provided by derived class to validate specified configuration
/// </summary>
/// <param name="config">Configuration to validate</param>
protected abstract void ValidateConfig(TConfig config);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System.Collections.Generic;
using System.Threading.Tasks;

namespace Microsoft.Toolkit.Services
{
/// <summary>
/// Base class for data providers in this library.
/// </summary>
/// <typeparam name="TConfig">Strong typed query configuration object.</typeparam>
/// <typeparam name="TSchema">Strong typed object to parse the response items into.</typeparam>
public abstract class DataProviderBase<TConfig, TSchema> : DataProviderBase<TConfig>
where TSchema : SchemaBase
{
/// <summary>
/// Load data from provider endpoint.
/// </summary>
/// <param name="config">Query configuration.</param>
/// <param name="maxRecords">Upper record limit.</param>
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
/// <returns>List of strong typed objects.</returns>
public Task<IEnumerable<TSchema>> LoadDataAsync(TConfig config, int maxRecords = 20, int pageIndex = 0)
{
return LoadDataAsync(config, maxRecords, pageIndex, GetDefaultParser(config));
}

/// <summary>
/// Default parser abstract method.
/// </summary>
/// <param name="config">Query configuration object.</param>
/// <returns>Strong typed default parser.</returns>
protected abstract IParser<TSchema> GetDefaultParser(TConfig config);
}
}
101 changes: 101 additions & 0 deletions Microsoft.Toolkit.Services/Core/ExtensionMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Toolkit.Services.Bing;

namespace Microsoft.Toolkit.Services.Core
{
/// <summary>
/// This class offers general purpose methods.
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Regular expression of HTML tags to remove.
/// </summary>
private static readonly Regex RemoveHtmlTagsRegex = new Regex(@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>");

/// <summary>
/// Converts object into string.
/// </summary>
/// <param name="value">Object value.</param>
/// <returns>Returns string value.</returns>
public static string ToSafeString(this object value)
{
return value?.ToString();
}

/// <summary>
/// Decode HTML string.
/// </summary>
/// <param name="htmlText">HTML string.</param>
/// <returns>Returns decoded HTML string.</returns>
public static string DecodeHtml(this string htmlText)
{
if (htmlText == null)
{
return null;
}

var ret = htmlText.FixHtml();

// Remove html tags
ret = RemoveHtmlTagsRegex.Replace(ret, string.Empty);

return WebUtility.HtmlDecode(ret);
}

/// <summary>
/// Converts between country code and country name.
/// </summary>
/// <param name="value">BingCountry enumeration.</param>
/// <returns>Returns country code.</returns>
public static string GetStringValue(this BingCountry value)
{
return GetStringValue((Enum)value);
}

/// <summary>
/// Converts between language code and language name.
/// </summary>
/// <param name="value">BingLanguage enumeration.</param>
/// <returns>Returns language code.</returns>
public static string GetStringValue(this BingLanguage value)
{
return GetStringValue((Enum)value);
}

/// <summary>
/// Converts between enumeration value and string value.
/// </summary>
/// <param name="value">Enumeration.</param>
/// <returns>Returns string value.</returns>
private static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();

FieldInfo fi = type.GetRuntimeField(value.ToString());
StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
if (attrs != null && attrs.Length > 0)
{
output = attrs[0].Value;
}

return output;
}
}
}
40 changes: 40 additions & 0 deletions Microsoft.Toolkit.Services/Core/IDataService{T,U,V}.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System.Collections.Generic;
using System.Threading.Tasks;

namespace Microsoft.Toolkit.Services.Core
{
/// <summary>
/// Generic interface that all deployed service providers implement.
/// </summary>
/// <typeparam name="T">Reference to underlying data service provider.</typeparam>
/// <typeparam name="U">Strongly-typed schema for data returned in list query.</typeparam>
/// <typeparam name="V">Configuration type specifying query parameters.</typeparam>
public interface IDataService<T, U, V>
{
/// <summary>
/// Gets the underlying data service provider.
/// </summary>
T Provider { get; }

/// <summary>
/// Makes a request for a list of data from the given service provider.
/// </summary>
/// <param name="config">Describes the query on the list data request.</param>
/// <param name="maxRecords">Specifies an upper limit to the number of records returned.</param>
/// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
/// <returns>Returns a strongly typed list of results from the service.</returns>
Task<List<U>> RequestAsync(V config, int maxRecords, int pageIndex = 0);
}
}
31 changes: 31 additions & 0 deletions Microsoft.Toolkit.Services/Core/IParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System.Collections.Generic;

namespace Microsoft.Toolkit.Services
{
/// <summary>
/// Parser interface.
/// </summary>
/// <typeparam name="T">Type to parse into.</typeparam>
public interface IParser<out T>
where T : SchemaBase
{
/// <summary>
/// Parse method which all classes must implement.
/// </summary>
/// <param name="data">Data to parse.</param>
/// <returns>Strong typed parsed data.</returns>
IEnumerable<T> Parse(string data);
}
}
Loading

0 comments on commit 19dff74

Please sign in to comment.