mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-22 20:13:50 +08:00
Removing IMapper (backport)
--HG-- branch : 1.x
This commit is contained in:
@@ -257,6 +257,8 @@
|
||||
<Compile Include="XmlRpc\Models\XRpcMethodCall.cs" />
|
||||
<Compile Include="XmlRpc\Models\XRpcMethodResponse.cs" />
|
||||
<Compile Include="XmlRpc\Models\XRpcStruct.cs" />
|
||||
<Compile Include="XmlRpc\Services\IXmlRpcReader.cs" />
|
||||
<Compile Include="XmlRpc\Services\IXmlRpcWriter.cs" />
|
||||
<Compile Include="XmlRpc\Services\XmlRpcReader.cs" />
|
||||
<Compile Include="XmlRpc\Services\XmlRpcWriter.cs" />
|
||||
<Compile Include="XmlRpc\XmlRpcContext.cs" />
|
||||
|
@@ -5,6 +5,7 @@ using System.Xml.Linq;
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.MetaData.Services;
|
||||
using Orchard.Core.Settings.Metadata.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.Logging;
|
||||
@@ -18,8 +19,7 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
private readonly IRepository<ContentTypeDefinitionRecord> _typeDefinitionRepository;
|
||||
private readonly IRepository<ContentPartDefinitionRecord> _partDefinitionRepository;
|
||||
private readonly IRepository<ContentFieldDefinitionRecord> _fieldDefinitionRepository;
|
||||
private readonly IMapper<XElement, SettingsDictionary> _settingsReader;
|
||||
private readonly IMapper<SettingsDictionary, XElement> _settingsWriter;
|
||||
private readonly ISettingsFormatter _settingsFormatter;
|
||||
|
||||
public ContentDefinitionManager(
|
||||
ICacheManager cacheManager,
|
||||
@@ -27,15 +27,13 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
IRepository<ContentTypeDefinitionRecord> typeDefinitionRepository,
|
||||
IRepository<ContentPartDefinitionRecord> partDefinitionRepository,
|
||||
IRepository<ContentFieldDefinitionRecord> fieldDefinitionRepository,
|
||||
IMapper<XElement, SettingsDictionary> settingsReader,
|
||||
IMapper<SettingsDictionary, XElement> settingsWriter) {
|
||||
ISettingsFormatter settingsFormatter) {
|
||||
_cacheManager = cacheManager;
|
||||
_signals = signals;
|
||||
_typeDefinitionRepository = typeDefinitionRepository;
|
||||
_partDefinitionRepository = partDefinitionRepository;
|
||||
_fieldDefinitionRepository = fieldDefinitionRepository;
|
||||
_settingsReader = settingsReader;
|
||||
_settingsWriter = settingsWriter;
|
||||
_settingsFormatter = settingsFormatter;
|
||||
}
|
||||
|
||||
public ContentTypeDefinition GetTypeDefinition(string name) {
|
||||
@@ -45,6 +43,38 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
});
|
||||
}
|
||||
|
||||
public void DeleteTypeDefinition(string name) {
|
||||
var record = _typeDefinitionRepository.Fetch(x => x.Name == name).SingleOrDefault();
|
||||
|
||||
// deletes the content type record associated
|
||||
if (record != null) {
|
||||
_typeDefinitionRepository.Delete(record);
|
||||
}
|
||||
|
||||
// invalidates the cache
|
||||
TriggerContentDefinitionSignal();
|
||||
}
|
||||
|
||||
public void DeletePartDefinition(string name) {
|
||||
// remove parts from current types
|
||||
var typesWithPart = ListTypeDefinitions().Where(typeDefinition => typeDefinition.Parts.Any(part => part.PartDefinition.Name == name));
|
||||
|
||||
foreach (var typeDefinition in typesWithPart) {
|
||||
this.AlterTypeDefinition(typeDefinition.Name, builder => builder.RemovePart(name));
|
||||
}
|
||||
|
||||
// delete part
|
||||
var record = _partDefinitionRepository.Fetch(x => x.Name == name).SingleOrDefault();
|
||||
|
||||
if (record != null) {
|
||||
_partDefinitionRepository.Delete(record);
|
||||
}
|
||||
|
||||
// invalidates the cache
|
||||
TriggerContentDefinitionSignal();
|
||||
|
||||
}
|
||||
|
||||
public ContentPartDefinition GetPartDefinition(string name) {
|
||||
return _cacheManager.Get(name ?? string.Empty, ctx => {
|
||||
MonitorContentDefinitionSignal(ctx);
|
||||
@@ -83,39 +113,6 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
Apply(contentPartDefinition, Acquire(contentPartDefinition));
|
||||
}
|
||||
|
||||
public void DeleteTypeDefinition(string name) {
|
||||
var record = _typeDefinitionRepository.Fetch(x => x.Name == name).SingleOrDefault();
|
||||
|
||||
// deletes the content type record associated
|
||||
if (record != null) {
|
||||
_typeDefinitionRepository.Delete(record);
|
||||
}
|
||||
|
||||
// invalidates the cache
|
||||
TriggerContentDefinitionSignal();
|
||||
}
|
||||
|
||||
public void DeletePartDefinition(string name) {
|
||||
// remove parts from current types
|
||||
var typesWithPart = ListTypeDefinitions().Where(typeDefinition => typeDefinition.Parts.Any(part => part.PartDefinition.Name == name));
|
||||
|
||||
foreach (var typeDefinition in typesWithPart) {
|
||||
this.AlterTypeDefinition(typeDefinition.Name, builder => builder.RemovePart(name));
|
||||
}
|
||||
|
||||
// delete part
|
||||
var record = _partDefinitionRepository.Fetch(x => x.Name == name).SingleOrDefault();
|
||||
|
||||
if (record != null) {
|
||||
_partDefinitionRepository.Delete(record);
|
||||
}
|
||||
|
||||
// invalidates the cache
|
||||
TriggerContentDefinitionSignal();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void MonitorContentDefinitionSignal(AcquireContext<string> ctx) {
|
||||
ctx.Monitor(_signals.When(ContentDefinitionSignal));
|
||||
}
|
||||
@@ -153,7 +150,7 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
|
||||
private void Apply(ContentTypeDefinition model, ContentTypeDefinitionRecord record) {
|
||||
record.DisplayName = model.DisplayName;
|
||||
record.Settings = _settingsWriter.Map(model.Settings).ToString();
|
||||
record.Settings = _settingsFormatter.Map(model.Settings).ToString();
|
||||
|
||||
var toRemove = record.ContentTypePartDefinitionRecords
|
||||
.Where(partDefinitionRecord => !model.Parts.Any(part => partDefinitionRecord.ContentPartDefinitionRecord.Name == part.PartDefinition.Name))
|
||||
@@ -175,11 +172,11 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
}
|
||||
|
||||
private void Apply(ContentTypePartDefinition model, ContentTypePartDefinitionRecord record) {
|
||||
record.Settings = Compose(_settingsWriter.Map(model.Settings));
|
||||
record.Settings = Compose(_settingsFormatter.Map(model.Settings));
|
||||
}
|
||||
|
||||
private void Apply(ContentPartDefinition model, ContentPartDefinitionRecord record) {
|
||||
record.Settings = _settingsWriter.Map(model.Settings).ToString();
|
||||
record.Settings = _settingsFormatter.Map(model.Settings).ToString();
|
||||
|
||||
var toRemove = record.ContentPartFieldDefinitionRecords
|
||||
.Where(partFieldDefinitionRecord => !model.Fields.Any(partField => partFieldDefinitionRecord.Name == partField.Name))
|
||||
@@ -204,7 +201,7 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
}
|
||||
|
||||
private void Apply(ContentPartFieldDefinition model, ContentPartFieldDefinitionRecord record) {
|
||||
record.Settings = Compose(_settingsWriter.Map(model.Settings));
|
||||
record.Settings = Compose(_settingsFormatter.Map(model.Settings));
|
||||
}
|
||||
|
||||
ContentTypeDefinition Build(ContentTypeDefinitionRecord source) {
|
||||
@@ -212,27 +209,27 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
source.Name,
|
||||
source.DisplayName,
|
||||
source.ContentTypePartDefinitionRecords.Select(Build),
|
||||
_settingsReader.Map(Parse(source.Settings)));
|
||||
_settingsFormatter.Map(Parse(source.Settings)));
|
||||
}
|
||||
|
||||
ContentTypePartDefinition Build(ContentTypePartDefinitionRecord source) {
|
||||
return new ContentTypePartDefinition(
|
||||
Build(source.ContentPartDefinitionRecord),
|
||||
_settingsReader.Map(Parse(source.Settings)));
|
||||
_settingsFormatter.Map(Parse(source.Settings)));
|
||||
}
|
||||
|
||||
ContentPartDefinition Build(ContentPartDefinitionRecord source) {
|
||||
return new ContentPartDefinition(
|
||||
source.Name,
|
||||
source.ContentPartFieldDefinitionRecords.Select(Build),
|
||||
_settingsReader.Map(Parse(source.Settings)));
|
||||
_settingsFormatter.Map(Parse(source.Settings)));
|
||||
}
|
||||
|
||||
ContentPartFieldDefinition Build(ContentPartFieldDefinitionRecord source) {
|
||||
return new ContentPartFieldDefinition(
|
||||
Build(source.ContentFieldDefinitionRecord),
|
||||
source.Name,
|
||||
_settingsReader.Map(Parse(source.Settings)));
|
||||
_settingsFormatter.Map(Parse(source.Settings)));
|
||||
}
|
||||
|
||||
ContentFieldDefinition Build(ContentFieldDefinitionRecord source) {
|
||||
|
@@ -1,17 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Core.XmlRpc.Models;
|
||||
using Orchard.Core.XmlRpc.Services;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Core.XmlRpc.Controllers {
|
||||
public class HomeController : Controller {
|
||||
private readonly IMapper<XRpcMethodResponse, XElement> _writer;
|
||||
private readonly IXmlRpcWriter _writer;
|
||||
private readonly IEnumerable<IXmlRpcHandler> _xmlRpcHandlers;
|
||||
|
||||
public HomeController(
|
||||
IMapper<XRpcMethodResponse, XElement> writer,
|
||||
IXmlRpcWriter writer,
|
||||
IEnumerable<IXmlRpcHandler> xmlRpcHandlers) {
|
||||
_writer = writer;
|
||||
_xmlRpcHandlers = xmlRpcHandlers;
|
||||
@@ -29,7 +29,7 @@ namespace Orchard.Core.XmlRpc.Controllers {
|
||||
if (methodResponse == null)
|
||||
throw new HttpException(500, "TODO: xmlrpc fault");
|
||||
|
||||
var content = _writer.Map(methodResponse).ToString();
|
||||
var content = _writer.MapMethodResponse(methodResponse).ToString();
|
||||
return Content(content, "text/xml");
|
||||
}
|
||||
|
||||
|
@@ -2,32 +2,33 @@
|
||||
using System.Web.Mvc;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Core.XmlRpc.Services;
|
||||
using Orchard.Mvc.ModelBinders;
|
||||
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
|
||||
|
||||
namespace Orchard.Core.XmlRpc.Models {
|
||||
public class ModelBinderProvider : IModelBinderProvider, IModelBinder {
|
||||
private readonly IMapper<XElement, XRpcMethodCall> _mapper;
|
||||
private readonly IXmlRpcReader _mapper;
|
||||
|
||||
public ModelBinderProvider(IMapper<XElement, XRpcMethodCall> mapper) {
|
||||
public ModelBinderProvider(IXmlRpcReader mapper) {
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public IEnumerable<ModelBinderDescriptor> GetModelBinders() {
|
||||
return new[] {
|
||||
new ModelBinderDescriptor {
|
||||
ModelBinder =this,
|
||||
Type=typeof(XRpcMethodCall)
|
||||
ModelBinder = this,
|
||||
Type = typeof(XRpcMethodCall)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
|
||||
//Ah! xmlrpc is a value provider!!!
|
||||
// Ah! xmlrpc is a value provider!!!
|
||||
// TODO: refactor this?
|
||||
using (var xmlReader = XmlReader.Create(controllerContext.HttpContext.Request.InputStream)) {
|
||||
var element = XElement.Load(xmlReader);
|
||||
return _mapper.Map(element);
|
||||
return _mapper.MapToMethodCall(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
37
src/Orchard.Web/Core/XmlRpc/Services/IXmlRpcReader.cs
Normal file
37
src/Orchard.Web/Core/XmlRpc/Services/IXmlRpcReader.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Core.XmlRpc.Models;
|
||||
|
||||
namespace Orchard.Core.XmlRpc.Services {
|
||||
/// <summary>
|
||||
/// Abstraction to read XML and convert it to rpc entities.
|
||||
/// </summary>
|
||||
public interface IXmlRpcReader : IDependency {
|
||||
/// <summary>
|
||||
/// Maps an XML element to a rpc method call.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc method call.</returns>
|
||||
XRpcMethodCall MapToMethodCall(XElement source);
|
||||
|
||||
/// <summary>
|
||||
/// Maps an XML element to rpc data.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc data.</returns>
|
||||
XRpcData MapToData(XElement source);
|
||||
|
||||
/// <summary>
|
||||
/// Maps an XML element to a rpc struct.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc struct.</returns>
|
||||
XRpcStruct MapToStruct(XElement source);
|
||||
|
||||
/// <summary>
|
||||
/// Maps an XML element to a rpc array.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc array.</returns>
|
||||
XRpcArray MapToArray(XElement source);
|
||||
}
|
||||
}
|
37
src/Orchard.Web/Core/XmlRpc/Services/IXmlRpcWriter.cs
Normal file
37
src/Orchard.Web/Core/XmlRpc/Services/IXmlRpcWriter.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Core.XmlRpc.Models;
|
||||
|
||||
namespace Orchard.Core.XmlRpc.Services {
|
||||
/// <summary>
|
||||
/// Abstraction to write XML based on rpc entities.
|
||||
/// </summary>
|
||||
public interface IXmlRpcWriter : IDependency {
|
||||
/// <summary>
|
||||
/// Maps a method response to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcMethodResponse">The method response to be mapped.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
XElement MapMethodResponse(XRpcMethodResponse rpcMethodResponse);
|
||||
|
||||
/// <summary>
|
||||
/// Maps rpc data to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcData">The rpc data.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
XElement MapData(XRpcData rpcData);
|
||||
|
||||
/// <summary>
|
||||
/// Maps a rpc struct to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcStruct">The rpc struct.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
XElement MapStruct(XRpcStruct rpcStruct);
|
||||
|
||||
/// <summary>
|
||||
/// Maps a rpc array to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcArray">The rpc array.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
XElement MapArray(XRpcArray rpcArray);
|
||||
}
|
||||
}
|
@@ -6,91 +6,120 @@ using System.Xml.Linq;
|
||||
using Orchard.Core.XmlRpc.Models;
|
||||
|
||||
namespace Orchard.Core.XmlRpc.Services {
|
||||
public class XmlRpcReader :
|
||||
IMapper<XElement, XRpcMethodCall>,
|
||||
IMapper<XElement, XRpcData>,
|
||||
IMapper<XElement, XRpcStruct>,
|
||||
IMapper<XElement, XRpcArray> {
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction to read XML and convert it to rpc entities.
|
||||
/// </summary>
|
||||
public class XmlRpcReader : IXmlRpcReader {
|
||||
/// <summary>
|
||||
/// Provides the mapping function based on a type name.
|
||||
/// </summary>
|
||||
private readonly IDictionary<string, Func<XElement, XRpcData>> _dispatch;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="XmlRpcReader"/> class.
|
||||
/// </summary>
|
||||
public XmlRpcReader() {
|
||||
_dispatch = new Dictionary<string, Func<XElement, XRpcData>>
|
||||
{
|
||||
{"i4",x=>new XRpcData<int> { Value = (int)x }},
|
||||
{"int", x=>new XRpcData<int> { Value = (int)x }},
|
||||
{"boolean", x=>new XRpcData<bool> { Value = ((string)x=="1") }},
|
||||
{"string", x=>new XRpcData<string> { Value = (string)x }},
|
||||
{"double", x=>new XRpcData<double> { Value = (double)x }},
|
||||
{"dateTime.iso8601", x=> {
|
||||
DateTime parsedDateTime;
|
||||
// try parsing a "normal" datetime string then try what live writer gives us
|
||||
if(!DateTime.TryParse(x.Value, out parsedDateTime)
|
||||
&& !DateTime.TryParseExact(x.Value, "yyyyMMddTHH:mm:ss", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out parsedDateTime)) {
|
||||
parsedDateTime = DateTime.Now;
|
||||
}
|
||||
return new XRpcData<DateTime> {Value = parsedDateTime};
|
||||
}},
|
||||
{"base64", x=>new XRpcData<byte[]> { Value = Convert.FromBase64String((string)x) }},
|
||||
{"struct", x=>XRpcData.For(Map<XRpcStruct>(x))} ,
|
||||
{"array", x=>XRpcData.For(Map<XRpcArray>(x))} ,
|
||||
};
|
||||
{
|
||||
{ "i4", x => new XRpcData<int> { Value = (int)x } },
|
||||
{ "int", x => new XRpcData<int> { Value = (int)x } },
|
||||
{ "boolean", x => new XRpcData<bool> { Value = (string)x == "1" } },
|
||||
{ "string", x => new XRpcData<string> { Value = (string)x } },
|
||||
{ "double", x => new XRpcData<double> { Value = (double)x } },
|
||||
{ "dateTime.iso8601", x => {
|
||||
DateTime parsedDateTime;
|
||||
|
||||
// try parsing a "normal" datetime string then try what live writer gives us
|
||||
if (!DateTime.TryParse(x.Value, out parsedDateTime)
|
||||
&& !DateTime.TryParseExact(x.Value, "yyyyMMddTHH:mm:ss", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out parsedDateTime)) {
|
||||
parsedDateTime = DateTime.Now;
|
||||
}
|
||||
|
||||
return new XRpcData<DateTime> { Value = parsedDateTime };
|
||||
} },
|
||||
{ "base64", x => new XRpcData<byte[]> { Value = Convert.FromBase64String((string)x) } },
|
||||
{ "struct", x => XRpcData.For(MapToStruct(x)) },
|
||||
{ "array", x => XRpcData.For(MapToArray(x)) },
|
||||
};
|
||||
}
|
||||
|
||||
T2 Map<T2>(XElement t1) {
|
||||
return ((IMapper<XElement, T2>)this).Map(t1);
|
||||
}
|
||||
|
||||
XRpcData MapValue(XContainer t1) {
|
||||
var element = t1.Elements().SingleOrDefault();
|
||||
|
||||
Func<XElement, XRpcData> dispatch;
|
||||
if (_dispatch.TryGetValue(element.Name.LocalName, out dispatch) == false)
|
||||
throw new ApplicationException("Unknown XmlRpc value type " + element.Name.LocalName);
|
||||
|
||||
return dispatch(element);
|
||||
}
|
||||
|
||||
XRpcMethodCall IMapper<XElement, XRpcMethodCall>.Map(XElement source) {
|
||||
/// <summary>
|
||||
/// Maps an XML element to a rpc method call.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc method call.</returns>
|
||||
public XRpcMethodCall MapToMethodCall(XElement source) {
|
||||
return new XRpcMethodCall {
|
||||
MethodName = (string)source.Element("methodName"),
|
||||
Params = source.Elements("params").Elements("param").Select(Map<XRpcData>).ToList()
|
||||
Params = source.Elements("params").Elements("param").Select(MapToData).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
XRpcData IMapper<XElement, XRpcData>.Map(XElement source) {
|
||||
/// <summary>
|
||||
/// Maps an XML element to rpc data.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc data.</returns>
|
||||
public XRpcData MapToData(XElement source) {
|
||||
var value = source.Element("value");
|
||||
if (value == null)
|
||||
if (value == null) {
|
||||
return new XRpcData();
|
||||
}
|
||||
|
||||
var element = value.Elements().SingleOrDefault();
|
||||
|
||||
Func<XElement, XRpcData> dispatch;
|
||||
if (_dispatch.TryGetValue(element.Name.LocalName, out dispatch) == false)
|
||||
if (_dispatch.TryGetValue(element.Name.LocalName, out dispatch) == false) {
|
||||
throw new ApplicationException("Unknown XmlRpc value type " + element.Name.LocalName);
|
||||
}
|
||||
|
||||
return dispatch(element);
|
||||
}
|
||||
|
||||
XRpcStruct IMapper<XElement, XRpcStruct>.Map(XElement source) {
|
||||
/// <summary>
|
||||
/// Maps an XML element to a rpc struct.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc struct.</returns>
|
||||
public XRpcStruct MapToStruct(XElement source) {
|
||||
var result = new XRpcStruct();
|
||||
foreach (var member in source.Elements("member")) {
|
||||
result.Members.Add(
|
||||
(string)member.Element("name"),
|
||||
MapValue(member.Element("value")));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
XRpcArray IMapper<XElement, XRpcArray>.Map(XElement source) {
|
||||
/// <summary>
|
||||
/// Maps an XML element to a rpc array.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML element to be mapped.</param>
|
||||
/// <returns>The rpc array.</returns>
|
||||
public XRpcArray MapToArray(XElement source) {
|
||||
var result = new XRpcArray();
|
||||
foreach (var value in source.Elements("data").Elements("value")) {
|
||||
result.Data.Add(MapValue(value));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an XML container to rpc data.
|
||||
/// </summary>
|
||||
/// <param name="source">The XML container to be mapped.</param>
|
||||
/// <returns>The rpc data.</returns>
|
||||
private XRpcData MapValue(XContainer source) {
|
||||
var element = source.Elements().SingleOrDefault();
|
||||
|
||||
Func<XElement, XRpcData> dispatch;
|
||||
if (_dispatch.TryGetValue(element.Name.LocalName, out dispatch) == false) {
|
||||
throw new ApplicationException("Unknown XmlRpc value type " + element.Name.LocalName);
|
||||
}
|
||||
|
||||
return dispatch(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,69 +3,98 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Core.XmlRpc.Models;
|
||||
using Orchard.Validation;
|
||||
|
||||
namespace Orchard.Core.XmlRpc.Services {
|
||||
public class XmlRpcWriter :
|
||||
IMapper<XRpcMethodResponse, XElement>,
|
||||
IMapper<XRpcStruct, XElement>,
|
||||
IMapper<XRpcArray, XElement>,
|
||||
IMapper<XRpcData, XElement> {
|
||||
|
||||
public XmlRpcWriter() {
|
||||
_dispatch = new Dictionary<Type, Func<XRpcData, XElement>>
|
||||
{
|
||||
{typeof(int), p=>new XElement("int", (int)p.Value)},
|
||||
{typeof(bool), p=>new XElement("boolean", (bool)p.Value?"1":"0")},
|
||||
{typeof(string), p=>new XElement("string", p.Value)},
|
||||
{typeof(double), p=>new XElement("double", (double)p.Value)},
|
||||
{typeof(DateTime), p=>new XElement("dateTime.iso8601", ((DateTime)p.Value).ToString("yyyyMMddTHH:mm:ssZ"))},
|
||||
{typeof(DateTime?), p=>new XElement("dateTime.iso8601", ((DateTime?)p.Value).Value.ToString("yyyyMMddTHH:mm:ssZ"))},
|
||||
{typeof(byte[]), p=>new XElement("base64", Convert.ToBase64String((byte[])p.Value))},
|
||||
{typeof(XRpcStruct), p=>Map((XRpcStruct)p.Value)},
|
||||
{typeof(XRpcArray), p=>Map((XRpcArray)p.Value)},
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction to write XML based on rpc entities.
|
||||
/// </summary>
|
||||
public class XmlRpcWriter : IXmlRpcWriter {
|
||||
/// <summary>
|
||||
/// Provides the mapping function based on a type.
|
||||
/// </summary>
|
||||
private readonly IDictionary<Type, Func<XRpcData, XElement>> _dispatch;
|
||||
|
||||
XElement IMapper<XRpcMethodResponse, XElement>.Map(XRpcMethodResponse source) {
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="XmlRpcWriter"/> class.
|
||||
/// </summary>
|
||||
public XmlRpcWriter() {
|
||||
_dispatch = new Dictionary<Type, Func<XRpcData, XElement>>
|
||||
{
|
||||
{ typeof(int), p => new XElement("int", (int)p.Value) },
|
||||
{ typeof(bool), p => new XElement("boolean", (bool)p.Value ? "1" : "0") },
|
||||
{ typeof(string), p => new XElement("string", p.Value) },
|
||||
{ typeof(double), p => new XElement("double", (double)p.Value) },
|
||||
{ typeof(DateTime), p => new XElement("dateTime.iso8601", ((DateTime)p.Value).ToString("yyyyMMddTHH:mm:ssZ")) },
|
||||
{ typeof(DateTime?), p => new XElement("dateTime.iso8601", ((DateTime?)p.Value).Value.ToString("yyyyMMddTHH:mm:ssZ")) },
|
||||
{ typeof(byte[]), p => new XElement("base64", Convert.ToBase64String((byte[])p.Value)) },
|
||||
{ typeof(XRpcStruct), p => MapStruct((XRpcStruct)p.Value) },
|
||||
{ typeof(XRpcArray), p => MapArray((XRpcArray)p.Value) },
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a method response to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcMethodResponse">The method response to be mapped.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
public XElement MapMethodResponse(XRpcMethodResponse rpcMethodResponse) {
|
||||
Argument.ThrowIfNull(rpcMethodResponse, "rpcMethodResponse");
|
||||
|
||||
return new XElement(
|
||||
"methodResponse",
|
||||
new XElement(
|
||||
"params",
|
||||
source.Params.Select(
|
||||
rpcMethodResponse.Params.Select(
|
||||
p => new XElement("param", MapValue(p)))));
|
||||
}
|
||||
|
||||
XElement IMapper<XRpcData, XElement>.Map(XRpcData source) {
|
||||
return new XElement("param", MapValue(source));
|
||||
/// <summary>
|
||||
/// Maps rpc data to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcData">The rpc data.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
public XElement MapData(XRpcData rpcData) {
|
||||
Argument.ThrowIfNull(rpcData, "rpcData");
|
||||
|
||||
return new XElement("param", MapValue(rpcData));
|
||||
}
|
||||
|
||||
XElement IMapper<XRpcStruct, XElement>.Map(XRpcStruct source) {
|
||||
/// <summary>
|
||||
/// Maps a rpc struct to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcStruct">The rpc struct.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
public XElement MapStruct(XRpcStruct rpcStruct) {
|
||||
return new XElement(
|
||||
"struct",
|
||||
source.Members.Select(
|
||||
rpcStruct.Members.Select(
|
||||
kv => new XElement(
|
||||
"member",
|
||||
new XElement("name", kv.Key),
|
||||
MapValue(kv.Value))));
|
||||
}
|
||||
|
||||
XElement IMapper<XRpcArray, XElement>.Map(XRpcArray source) {
|
||||
/// <summary>
|
||||
/// Maps a rpc array to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcArray">The rpc array.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
public XElement MapArray(XRpcArray rpcArray) {
|
||||
return new XElement(
|
||||
"array",
|
||||
new XElement(
|
||||
"data",
|
||||
source.Data.Select(d => MapValue(d))));
|
||||
rpcArray.Data.Select(MapValue)));
|
||||
}
|
||||
|
||||
XElement Map<T>(T t) {
|
||||
return ((IMapper<T, XElement>)this).Map(t);
|
||||
/// <summary>
|
||||
/// Maps rpc data to XML.
|
||||
/// </summary>
|
||||
/// <param name="rpcData">The rpc data.</param>
|
||||
/// <returns>The XML element.</returns>
|
||||
private XElement MapValue(XRpcData rpcData) {
|
||||
return new XElement("value", _dispatch[rpcData.Type](rpcData));
|
||||
}
|
||||
|
||||
private XElement MapValue(XRpcData data) {
|
||||
return new XElement("value", _dispatch[data.Type](data));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user