Skip to content

Commit

Permalink
Added a simple "REST" access to the IniConfig, this can be used toget…
Browse files Browse the repository at this point in the history
…her with a HttpListener or a customer url to modify a configuration. (experimental)
  • Loading branch information
Lakritzator committed Sep 22, 2015
1 parent 979ec28 commit 1701388
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 9 deletions.
24 changes: 21 additions & 3 deletions Dapplo.Config.Test/IniConfigTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ public async Task TestIniIndexAccess()
var iniTest = await iniConfig.RegisterAndGetAsync<IIniConfigTest>().ConfigureAwait(false);
// Test ini value retrieval, by checking the Type and return value
var iniValue = iniTest["WindowCornerCutShape"];
Assert.IsTrue(iniValue.ValueType == typeof (IList<int>));
Assert.IsTrue(((IList<int>) iniValue.Value).Count > 0);
Assert.IsTrue(iniValue.ValueType == typeof(IList<int>));
Assert.IsTrue(((IList<int>)iniValue.Value).Count > 0);
}

[TestMethod]
Expand All @@ -126,7 +126,7 @@ public async Task TestIniSectionTryGet()
Assert.IsTrue(iniConfig.TryGet("Test", out section));
IniValue tryGetValue;
Assert.IsTrue(section.TryGetIniValue("WindowCornerCutShape", out tryGetValue));
Assert.IsTrue(((IList<int>) tryGetValue.Value).Count > 0);
Assert.IsTrue(((IList<int>)tryGetValue.Value).Count > 0);
Assert.IsFalse(section.TryGetIniValue("DoesNotExist", out tryGetValue));
}

Expand Down Expand Up @@ -187,5 +187,23 @@ public async Task TestIniWriteRead()
var iniTest2 = iniConfig.Get<IIniConfigTest>();
Assert.AreEqual(TestValueForNonSerialized, iniTest2.NotWritten);
}

[TestMethod]
public async Task TestIniRest()
{
var iniConfig = await InitializeAsync();
var iniTest = await iniConfig.RegisterAndGetAsync<IIniConfigTest>().ConfigureAwait(false);
iniTest.Name = Name;
iniTest.SomeValues.Add("Answer", 42);
var changeNameToRobinKromUri = new Uri("dummy:///IniConfig/write/Dapplo/dapplo/Test/Name/RobinKrom");
Assert.AreEqual(Name, IniConfig.ProcessRestUri(changeNameToRobinKromUri));
Assert.AreEqual("RobinKrom", iniTest.Name);
var removeValueUri = new Uri("dummy:///IniConfig/remove/Dapplo/dapplo/Test/SomeValues/Answer");
IniConfig.ProcessRestUri(removeValueUri);
Assert.IsFalse(iniTest.SomeValues.ContainsKey("NumberOfSongs"));

var addValueUri = new Uri("dummy:///IniConfig/add/Dapplo/dapplo/Test/SomeValues?Hightlight=10&Stop=20");
IniConfig.ProcessRestUri(addValueUri);
}
}
}
2 changes: 2 additions & 0 deletions Dapplo.Config/Dapplo.Config.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web" />
<Reference Include="System.XML" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WindowsBase" />
Expand Down Expand Up @@ -80,6 +81,7 @@
<Compile Include="Support\PropertyInfoExtension.cs" />
<Compile Include="Support\StringExtensions.cs" />
<Compile Include="Support\TypeExtensions.cs" />
<Compile Include="Support\UriExtensions.cs" />
<Compile Include="WindowsRegistry\Implementation\RegistryExtension.cs" />
<Compile Include="WindowsRegistry\RegistryAttribute.cs" />
<Compile Include="WindowsRegistry\RegistryPropertyAttribute.cs" />
Expand Down
102 changes: 102 additions & 0 deletions Dapplo.Config/Ini/IniConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

using Dapplo.Config.Support;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
Expand Down Expand Up @@ -843,5 +844,106 @@ where iniValue.Behavior.Read
// Reset the current sections
FillSections();
}

/// <summary>
/// Process an Rest URI, this can be used to read or write values via e.g. a HttpListener
/// format:
/// schema://hostname:port/IniConfig/Command/Applicationname/Configname/Section/Property/NewValue(optional)?query
/// schema is not important, this can be an application specific thing
/// hostname is not important, this can be an application specific thing
/// port is not important, this can be an application specific thing
/// The command is read/write/add/remove
/// the Applicationname & Configname must be registered by new IniConfig(Applicationname,Configname)
/// The Section is that which is used in the IniSection
/// The property needs to be available
/// NewValue is optional (read) can be used to set the property (write)
/// The query can be used to add or remove values from lists / dictionaries
/// </summary>
/// <param name="restUri"></param>
/// <returns>Value (before write) or actual value with read/add/remove</returns>
public static object ProcessRestUri(Uri restUri)
{
var segments = restUri.Segments.ToList();
if (segments[0] == "/")
{
segments.RemoveAt(0);
}
for(int i=0; i<segments.Count; i++)
{
if (segments[i].EndsWith("/"))
{
segments[i] = segments[i].Remove(segments[i].Length - 1);
}
}
if (segments[0] != "IniConfig")
{
return null;
}
segments.RemoveAt(0);
var command = segments[0];
segments.RemoveAt(0);
var iniConfig = IniConfig.Get(segments[0], segments[1]);
segments.RemoveAt(0);
segments.RemoveAt(0);
var iniSection = iniConfig[segments[0]];
segments.RemoveAt(0);
var iniValue = iniSection[segments[0]];
segments.RemoveAt(0);
var currentValue = iniValue.Value;
switch(command)
{
case "write":

if (segments.Count > 0)
{
if (iniValue.ValueType.IsGenericDirectory() || iniValue.ValueType.IsGenericList())
{
throw new NotSupportedException(string.Format("Can't write to type of {0}, used add/remove", iniValue.ValueType));
}
iniValue.Value = iniValue.Converter.ConvertFromInvariantString(segments[0]);
}
break;
case "read":
// Ignore, as the default logic covers a read
break;
case "remove":
if (iniValue.ValueType.IsGenericDirectory() || iniValue.ValueType.IsGenericList())
{
Type itemType = iniValue.ValueType.GetGenericArguments()[0];
var converter = itemType.GetTypeConverter();
var itemValue = converter.ConvertFromInvariantString(segments[0]);
var removeMethodInfo = iniValue.ValueType.GetMethod("Remove");
removeMethodInfo.Invoke(iniValue.Value, new[] { itemValue });
}
break;
case "add":
if (iniValue.ValueType.IsGenericDirectory())
{
var variables = restUri.QueryToDictionary();
Type keyType = iniValue.ValueType.GetGenericArguments()[0];
var keyConverter = keyType.GetTypeConverter();
Type valueType = iniValue.ValueType.GetGenericArguments()[1];
var valueConverter = valueType.GetTypeConverter();
var addMethodInfo = iniValue.ValueType.GetMethod("Add");
foreach (var key in variables.Keys)
{
var keyObject = keyConverter.ConvertFromInvariantString(key);
var valueObject = valueConverter.ConvertFromInvariantString(variables[key]);
addMethodInfo.Invoke(iniValue.Value, new[] { keyObject, valueObject });
}
} else if (iniValue.ValueType.IsGenericList())
{
Type itemType = iniValue.ValueType.GetGenericArguments()[0];
var converter = itemType.GetTypeConverter();
var itemValue = converter.ConvertFromInvariantString(segments[0]);
var addMethodInfo = iniValue.ValueType.GetMethod("Add");
addMethodInfo.Invoke(iniValue.Value, new[] { itemValue });
}
break;
default:
throw new NotSupportedException(string.Format("Don't know command {0}, there is only read/write/add/remove", command));
}
return currentValue;
}
}
}
6 changes: 0 additions & 6 deletions Dapplo.Config/Ini/IniValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ public string PropertyName
set;
}

public string CleanPropertyName
{
get;
private set;
}

/// <summary>
/// Name of the property in the file, this could be different
/// </summary>
Expand Down
48 changes: 48 additions & 0 deletions Dapplo.Config/Support/UriExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;

namespace Dapplo.Config.Support
{
public static class UriExtensions
{
/// <summary>
/// Create a NameValueCollection from the query part of the uri
/// </summary>
/// <param name="uri"></param>
/// <returns>NameValueCollection</returns>
public static NameValueCollection QueryToNameValues(this Uri uri)
{
if (!string.IsNullOrEmpty(uri.Query))
{
return HttpUtility.ParseQueryString(uri.Query);
}
return new NameValueCollection();
}

/// <summary>
/// Create a IDictionary string,string from the query part of the uri
/// </summary>
/// <param name="uri"></param>
/// <returns>IDictionary string,string</returns>
public static IDictionary<string, string> QueryToDictionary(this Uri uri)
{
var returnValue = new Dictionary<string, string>();
var nameValues = uri.QueryToNameValues();
for(int i=0; i<nameValues.Count; i++) {
var value = nameValues[i];
var key = nameValues.AllKeys[i];
if (returnValue.ContainsKey(key))
{
returnValue[key] = value;
}
else
{
returnValue.Add(key, value);
}
}
return returnValue;
}
}
}

0 comments on commit 1701388

Please sign in to comment.