Removing IMapper (backport)

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2011-10-05 13:59:24 -07:00
parent 7f56999a0b
commit 73d44afb2c
22 changed files with 455 additions and 231 deletions

View File

@@ -1,16 +1,13 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Xml.Linq;
using Autofac; using Autofac;
using Moq; using Moq;
using NHibernate; using NHibernate;
using NUnit.Framework; using NUnit.Framework;
using Orchard.Caching; using Orchard.Caching;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.MetaData.Services; using Orchard.ContentManagement.MetaData.Services;
using Orchard.Core.Settings.Metadata; using Orchard.Core.Settings.Metadata;
using Orchard.Core.Settings.Metadata.Records; using Orchard.Core.Settings.Metadata.Records;
@@ -46,9 +43,7 @@ namespace Orchard.Core.Tests.Settings.Metadata {
builder.RegisterAutoMocking(); builder.RegisterAutoMocking();
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>(); builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterType(typeof(SettingsFormatter)) builder.RegisterType(typeof(SettingsFormatter)).As(typeof(ISettingsFormatter));
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
builder.RegisterType<Signals>().As<ISignals>(); builder.RegisterType<Signals>().As<ISignals>();
builder.RegisterType<StubCacheManager>().As<ICacheManager>(); builder.RegisterType<StubCacheManager>().As<ICacheManager>();
builder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>(); builder.RegisterType<StubParallelCacheContext>().As<IParallelCacheContext>();

View File

@@ -72,8 +72,7 @@ namespace Orchard.Tests.Modules.ImportExport.Services {
builder.RegisterType<StubAppDataFolder>().As<IAppDataFolder>(); builder.RegisterType<StubAppDataFolder>().As<IAppDataFolder>();
builder.RegisterType<Signals>().As<ISignals>(); builder.RegisterType<Signals>().As<ISignals>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterInstance(new Mock<IMapper<SettingsDictionary, XElement>>().Object); builder.RegisterInstance(new Mock<ISettingsFormatter>().Object);
builder.RegisterInstance(new Mock<IMapper<XElement, SettingsDictionary>>().Object);
_session = _sessionFactory.OpenSession(); _session = _sessionFactory.OpenSession();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>(); builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(_session)).As<ISessionLocator>();

View File

@@ -53,9 +53,7 @@ namespace Orchard.Tests.Modules.Users.Controllers {
builder.RegisterType<AccountController>().SingleInstance(); builder.RegisterType<AccountController>().SingleInstance();
builder.RegisterType<SiteService>().As<ISiteService>(); builder.RegisterType<SiteService>().As<ISiteService>();
builder.RegisterType<DefaultContentManager>().As<IContentManager>(); builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType(typeof(SettingsFormatter)) builder.RegisterType(typeof(SettingsFormatter)).As<ISettingsFormatter>();
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>(); builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>(); builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>().InstancePerDependency(); builder.RegisterType<DefaultContentQuery>().As<IContentQuery>().InstancePerDependency();
@@ -70,7 +68,6 @@ namespace Orchard.Tests.Modules.Users.Controllers {
builder.RegisterType<TransactionManager>().As<ITransactionManager>(); builder.RegisterType<TransactionManager>().As<ITransactionManager>();
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>(); builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>(); builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
builder.RegisterType<ShapeTableLocator>().As<IShapeTableLocator>();
builder.RegisterType<StubExtensionManager>().As<IExtensionManager>(); builder.RegisterType<StubExtensionManager>().As<IExtensionManager>();
builder.RegisterType<SiteSettingsPartHandler>().As<IContentHandler>(); builder.RegisterType<SiteSettingsPartHandler>().As<IContentHandler>();
builder.RegisterType<RegistrationSettingsPartHandler>().As<IContentHandler>(); builder.RegisterType<RegistrationSettingsPartHandler>().As<IContentHandler>();

View File

@@ -71,9 +71,7 @@ namespace Orchard.Tests.Modules.Users.Services {
builder.RegisterType<MembershipService>().As<IMembershipService>(); builder.RegisterType<MembershipService>().As<IMembershipService>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>(); builder.RegisterType<DefaultContentQuery>().As<IContentQuery>();
builder.RegisterType<DefaultContentManager>().As<IContentManager>(); builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType(typeof(SettingsFormatter)) builder.RegisterType(typeof(SettingsFormatter)).As<ISettingsFormatter>();
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>(); builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>(); builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<UserPartHandler>().As<IContentHandler>(); builder.RegisterType<UserPartHandler>().As<IContentHandler>();

View File

@@ -76,15 +76,13 @@ namespace Orchard.Tests.Modules.Users.Services {
[SetUp] [SetUp]
public void Init() { public void Init() {
var builder = new ContainerBuilder(); var builder = new ContainerBuilder();
//builder.RegisterModule(new ImplicitCollectionSupportModule());
builder.RegisterType<MembershipService>().As<IMembershipService>(); builder.RegisterType<MembershipService>().As<IMembershipService>();
builder.RegisterType<UserService>().As<IUserService>(); builder.RegisterType<UserService>().As<IUserService>();
builder.RegisterInstance(_clock = new StubClock()).As<IClock>(); builder.RegisterInstance(_clock = new StubClock()).As<IClock>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>(); builder.RegisterType<DefaultContentQuery>().As<IContentQuery>();
builder.RegisterType<DefaultContentManager>().As<IContentManager>(); builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType(typeof(SettingsFormatter)) builder.RegisterType(typeof(SettingsFormatter)).As<ISettingsFormatter>();
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>(); builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>(); builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<UserPartHandler>().As<IContentHandler>(); builder.RegisterType<UserPartHandler>().As<IContentHandler>();

View File

@@ -17,8 +17,8 @@ namespace Orchard.Tests.Modules.XmlRpc.Controllers {
var builder = new ContainerBuilder(); var builder = new ContainerBuilder();
//builder.RegisterModule(new ImplicitCollectionSupportModule()); //builder.RegisterModule(new ImplicitCollectionSupportModule());
builder.RegisterType<HomeController>(); builder.RegisterType<HomeController>();
builder.RegisterType<XmlRpcReader>().As<IMapper<XElement, XRpcMethodCall>>(); builder.RegisterType<XmlRpcReader>().As<IXmlRpcReader>();
builder.RegisterType<XmlRpcWriter>().As<IMapper<XRpcMethodResponse, XElement>>(); builder.RegisterType<XmlRpcWriter>().As<IXmlRpcWriter>();
builder.RegisterInstance(thing1).As<IXmlRpcHandler>(); builder.RegisterInstance(thing1).As<IXmlRpcHandler>();
builder.RegisterInstance(thing2).As<IXmlRpcHandler>(); builder.RegisterInstance(thing2).As<IXmlRpcHandler>();

View File

@@ -17,8 +17,8 @@ namespace Orchard.Tests.Modules.XmlRpc.Controllers {
var builder = new ContainerBuilder(); var builder = new ContainerBuilder();
builder.RegisterType<LiveWriterController>(); builder.RegisterType<LiveWriterController>();
builder.RegisterType<XmlRpcReader>().As<IMapper<XElement, XRpcMethodCall>>(); builder.RegisterType<XmlRpcReader>().As<IXmlRpcReader>();
builder.RegisterType<XmlRpcWriter>().As<IMapper<XRpcMethodResponse, XElement>>(); builder.RegisterType<XmlRpcWriter>().As<IXmlRpcWriter>();
builder.RegisterInstance(thing).As<IXmlRpcHandler>(); builder.RegisterInstance(thing).As<IXmlRpcHandler>();
builder.RegisterInstance(thingToo).As<IXmlRpcHandler>(); builder.RegisterInstance(thingToo).As<IXmlRpcHandler>();

View File

@@ -1,22 +1,16 @@
using System; using System;
using System.Xml.Linq; using System.Xml.Linq;
using NUnit.Framework; using NUnit.Framework;
using Orchard.Core.XmlRpc.Models;
using Orchard.Core.XmlRpc.Services; using Orchard.Core.XmlRpc.Services;
namespace Orchard.Tests.Modules.XmlRpc.Services { namespace Orchard.Tests.Modules.XmlRpc.Services {
[TestFixture] [TestFixture]
public class XmlRpcReaderTests { public class XmlRpcReaderTests {
private IMapper<XElement, XRpcMethodCall> _methodCallMapper; private IXmlRpcReader _xmlRpcReader;
private IMapper<XElement, XRpcStruct> _structMapper;
private IMapper<XElement, XRpcArray> _arrayMapper;
[SetUp] [SetUp]
public void Init() { public void Init() {
var mapper = new XmlRpcReader(); _xmlRpcReader = new XmlRpcReader();
_methodCallMapper = mapper;
_structMapper = mapper;
_arrayMapper = mapper;
} }
[Test] [Test]
@@ -26,7 +20,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
<methodName>hello world</methodName> <methodName>hello world</methodName>
</methodCall>"); </methodCall>");
var methodCall = _methodCallMapper.Map(source); var methodCall = _xmlRpcReader.MapToMethodCall(source);
Assert.That(methodCall, Is.Not.Null); Assert.That(methodCall, Is.Not.Null);
Assert.That(methodCall.MethodName, Is.EqualTo("hello world")); Assert.That(methodCall.MethodName, Is.EqualTo("hello world"));
} }
@@ -48,7 +42,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
</params> </params>
</methodCall>"); </methodCall>");
var methodCall = _methodCallMapper.Map(source); var methodCall = _xmlRpcReader.MapToMethodCall(source);
Assert.That(methodCall, Is.Not.Null); Assert.That(methodCall, Is.Not.Null);
Assert.That(methodCall.Params, Has.Count.EqualTo(8)); Assert.That(methodCall.Params, Has.Count.EqualTo(8));
Assert.That(methodCall.Params[0].Value, Is.EqualTo(-12)); Assert.That(methodCall.Params[0].Value, Is.EqualTo(-12));
@@ -57,7 +51,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
Assert.That(methodCall.Params[3].Value, Is.EqualTo(false)); Assert.That(methodCall.Params[3].Value, Is.EqualTo(false));
Assert.That(methodCall.Params[4].Value, Is.EqualTo("hello world")); Assert.That(methodCall.Params[4].Value, Is.EqualTo("hello world"));
Assert.That(methodCall.Params[5].Value, Is.EqualTo(-12.214)); Assert.That(methodCall.Params[5].Value, Is.EqualTo(-12.214));
Assert.That(methodCall.Params[6].Value, Is.EqualTo(new DateTime(1998,7,17,14,8,55))); Assert.That(methodCall.Params[6].Value, Is.EqualTo(new DateTime(1998, 7, 17, 14, 8, 55)));
Assert.That(methodCall.Params[7].Value, Is.EqualTo(Convert.FromBase64String("eW91IGNhbid0IHJlYWQgdGhpcyE="))); Assert.That(methodCall.Params[7].Value, Is.EqualTo(Convert.FromBase64String("eW91IGNhbid0IHJlYWQgdGhpcyE=")));
} }
@@ -75,7 +69,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
<member><name>eight</name><value><base64>eW91IGNhbid0IHJlYWQgdGhpcyE=</base64></value></member> <member><name>eight</name><value><base64>eW91IGNhbid0IHJlYWQgdGhpcyE=</base64></value></member>
</struct>"); </struct>");
var xmlStruct = _structMapper.Map(source); var xmlStruct = _xmlRpcReader.MapToStruct(source);
Assert.That(xmlStruct["one"], Is.EqualTo(-12)); Assert.That(xmlStruct["one"], Is.EqualTo(-12));
Assert.That(xmlStruct["two"], Is.EqualTo(42)); Assert.That(xmlStruct["two"], Is.EqualTo(42));
Assert.That(xmlStruct["three"], Is.EqualTo(true)); Assert.That(xmlStruct["three"], Is.EqualTo(true));
@@ -94,7 +88,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
<member><name>seven</name><value><dateTime.iso8601>FOO</dateTime.iso8601></value></member> <member><name>seven</name><value><dateTime.iso8601>FOO</dateTime.iso8601></value></member>
</struct>"); </struct>");
var xmlStruct = _structMapper.Map(source); var xmlStruct = _xmlRpcReader.MapToStruct(source);
Assert.That(xmlStruct["seven"], Is.GreaterThan(DateTime.Now.AddSeconds(-1))); Assert.That(xmlStruct["seven"], Is.GreaterThan(DateTime.Now.AddSeconds(-1)));
Assert.That(xmlStruct["seven"], Is.LessThan(DateTime.Now.AddSeconds(1))); Assert.That(xmlStruct["seven"], Is.LessThan(DateTime.Now.AddSeconds(1)));
} }
@@ -112,7 +106,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
</array> </array>
"); ");
var xmlArray = _arrayMapper.Map(source); var xmlArray = _xmlRpcReader.MapToArray(source);
Assert.That(xmlArray.Data, Has.Count.EqualTo(4)); Assert.That(xmlArray.Data, Has.Count.EqualTo(4));
Assert.That(xmlArray[0], Is.EqualTo(12)); Assert.That(xmlArray[0], Is.EqualTo(12));
Assert.That(xmlArray[1], Is.EqualTo("Egypt")); Assert.That(xmlArray[1], Is.EqualTo("Egypt"));

View File

@@ -9,11 +9,10 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
[Test] [Test]
public void MethodResponseWriterShouldSendParametersWithValues() { public void MethodResponseWriterShouldSendParametersWithValues() {
var mapper = new XmlRpcWriter(); var mapper = new XmlRpcWriter();
IMapper<XRpcMethodResponse, XElement> resposeMapper = mapper;
var response = new XRpcMethodResponse(); var response = new XRpcMethodResponse();
response.Params.Add(new XRpcData<int> { Value = 42 }); response.Params.Add(new XRpcData<int> { Value = 42 });
var element = resposeMapper.Map(response); var element = mapper.MapMethodResponse(response);
Assert.That(NoSpace(element.ToString()), Is.EqualTo("<methodResponse><params><param><value><int>42</int></value></param></params></methodResponse>")); Assert.That(NoSpace(element.ToString()), Is.EqualTo("<methodResponse><params><param><value><int>42</int></value></param></params></methodResponse>"));
} }
@@ -21,7 +20,6 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
[Test] [Test]
public void ArrayAndStructShouldWorkAsExpected() { public void ArrayAndStructShouldWorkAsExpected() {
var mapper = new XmlRpcWriter(); var mapper = new XmlRpcWriter();
IMapper<XRpcArray, XElement> arrayMapper = mapper;
var arr = new XRpcArray(); var arr = new XRpcArray();
var structParam = XRpcData.For(new XRpcStruct()); var structParam = XRpcData.For(new XRpcStruct());
@@ -31,7 +29,7 @@ namespace Orchard.Tests.Modules.XmlRpc.Services {
structParam.Value.Members.Add("Hello", XRpcData.For("world")); structParam.Value.Members.Add("Hello", XRpcData.For("world"));
var element = arrayMapper.Map(arr); var element = mapper.MapArray(arr);
Assert.That(NoSpace(element.ToString()), Is.EqualTo(NoSpace(@" Assert.That(NoSpace(element.ToString()), Is.EqualTo(NoSpace(@"
<array><data> <array><data>

View File

@@ -257,6 +257,8 @@
<Compile Include="XmlRpc\Models\XRpcMethodCall.cs" /> <Compile Include="XmlRpc\Models\XRpcMethodCall.cs" />
<Compile Include="XmlRpc\Models\XRpcMethodResponse.cs" /> <Compile Include="XmlRpc\Models\XRpcMethodResponse.cs" />
<Compile Include="XmlRpc\Models\XRpcStruct.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\XmlRpcReader.cs" />
<Compile Include="XmlRpc\Services\XmlRpcWriter.cs" /> <Compile Include="XmlRpc\Services\XmlRpcWriter.cs" />
<Compile Include="XmlRpc\XmlRpcContext.cs" /> <Compile Include="XmlRpc\XmlRpcContext.cs" />

View File

@@ -5,6 +5,7 @@ using System.Xml.Linq;
using Orchard.Caching; using Orchard.Caching;
using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.MetaData.Services;
using Orchard.Core.Settings.Metadata.Records; using Orchard.Core.Settings.Metadata.Records;
using Orchard.Data; using Orchard.Data;
using Orchard.Logging; using Orchard.Logging;
@@ -18,8 +19,7 @@ namespace Orchard.Core.Settings.Metadata {
private readonly IRepository<ContentTypeDefinitionRecord> _typeDefinitionRepository; private readonly IRepository<ContentTypeDefinitionRecord> _typeDefinitionRepository;
private readonly IRepository<ContentPartDefinitionRecord> _partDefinitionRepository; private readonly IRepository<ContentPartDefinitionRecord> _partDefinitionRepository;
private readonly IRepository<ContentFieldDefinitionRecord> _fieldDefinitionRepository; private readonly IRepository<ContentFieldDefinitionRecord> _fieldDefinitionRepository;
private readonly IMapper<XElement, SettingsDictionary> _settingsReader; private readonly ISettingsFormatter _settingsFormatter;
private readonly IMapper<SettingsDictionary, XElement> _settingsWriter;
public ContentDefinitionManager( public ContentDefinitionManager(
ICacheManager cacheManager, ICacheManager cacheManager,
@@ -27,15 +27,13 @@ namespace Orchard.Core.Settings.Metadata {
IRepository<ContentTypeDefinitionRecord> typeDefinitionRepository, IRepository<ContentTypeDefinitionRecord> typeDefinitionRepository,
IRepository<ContentPartDefinitionRecord> partDefinitionRepository, IRepository<ContentPartDefinitionRecord> partDefinitionRepository,
IRepository<ContentFieldDefinitionRecord> fieldDefinitionRepository, IRepository<ContentFieldDefinitionRecord> fieldDefinitionRepository,
IMapper<XElement, SettingsDictionary> settingsReader, ISettingsFormatter settingsFormatter) {
IMapper<SettingsDictionary, XElement> settingsWriter) {
_cacheManager = cacheManager; _cacheManager = cacheManager;
_signals = signals; _signals = signals;
_typeDefinitionRepository = typeDefinitionRepository; _typeDefinitionRepository = typeDefinitionRepository;
_partDefinitionRepository = partDefinitionRepository; _partDefinitionRepository = partDefinitionRepository;
_fieldDefinitionRepository = fieldDefinitionRepository; _fieldDefinitionRepository = fieldDefinitionRepository;
_settingsReader = settingsReader; _settingsFormatter = settingsFormatter;
_settingsWriter = settingsWriter;
} }
public ContentTypeDefinition GetTypeDefinition(string name) { 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) { public ContentPartDefinition GetPartDefinition(string name) {
return _cacheManager.Get(name ?? string.Empty, ctx => { return _cacheManager.Get(name ?? string.Empty, ctx => {
MonitorContentDefinitionSignal(ctx); MonitorContentDefinitionSignal(ctx);
@@ -83,39 +113,6 @@ namespace Orchard.Core.Settings.Metadata {
Apply(contentPartDefinition, Acquire(contentPartDefinition)); 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) { private void MonitorContentDefinitionSignal(AcquireContext<string> ctx) {
ctx.Monitor(_signals.When(ContentDefinitionSignal)); ctx.Monitor(_signals.When(ContentDefinitionSignal));
} }
@@ -153,7 +150,7 @@ namespace Orchard.Core.Settings.Metadata {
private void Apply(ContentTypeDefinition model, ContentTypeDefinitionRecord record) { private void Apply(ContentTypeDefinition model, ContentTypeDefinitionRecord record) {
record.DisplayName = model.DisplayName; record.DisplayName = model.DisplayName;
record.Settings = _settingsWriter.Map(model.Settings).ToString(); record.Settings = _settingsFormatter.Map(model.Settings).ToString();
var toRemove = record.ContentTypePartDefinitionRecords var toRemove = record.ContentTypePartDefinitionRecords
.Where(partDefinitionRecord => !model.Parts.Any(part => partDefinitionRecord.ContentPartDefinitionRecord.Name == part.PartDefinition.Name)) .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) { 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) { 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 var toRemove = record.ContentPartFieldDefinitionRecords
.Where(partFieldDefinitionRecord => !model.Fields.Any(partField => partFieldDefinitionRecord.Name == partField.Name)) .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) { 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) { ContentTypeDefinition Build(ContentTypeDefinitionRecord source) {
@@ -212,27 +209,27 @@ namespace Orchard.Core.Settings.Metadata {
source.Name, source.Name,
source.DisplayName, source.DisplayName,
source.ContentTypePartDefinitionRecords.Select(Build), source.ContentTypePartDefinitionRecords.Select(Build),
_settingsReader.Map(Parse(source.Settings))); _settingsFormatter.Map(Parse(source.Settings)));
} }
ContentTypePartDefinition Build(ContentTypePartDefinitionRecord source) { ContentTypePartDefinition Build(ContentTypePartDefinitionRecord source) {
return new ContentTypePartDefinition( return new ContentTypePartDefinition(
Build(source.ContentPartDefinitionRecord), Build(source.ContentPartDefinitionRecord),
_settingsReader.Map(Parse(source.Settings))); _settingsFormatter.Map(Parse(source.Settings)));
} }
ContentPartDefinition Build(ContentPartDefinitionRecord source) { ContentPartDefinition Build(ContentPartDefinitionRecord source) {
return new ContentPartDefinition( return new ContentPartDefinition(
source.Name, source.Name,
source.ContentPartFieldDefinitionRecords.Select(Build), source.ContentPartFieldDefinitionRecords.Select(Build),
_settingsReader.Map(Parse(source.Settings))); _settingsFormatter.Map(Parse(source.Settings)));
} }
ContentPartFieldDefinition Build(ContentPartFieldDefinitionRecord source) { ContentPartFieldDefinition Build(ContentPartFieldDefinitionRecord source) {
return new ContentPartFieldDefinition( return new ContentPartFieldDefinition(
Build(source.ContentFieldDefinitionRecord), Build(source.ContentFieldDefinitionRecord),
source.Name, source.Name,
_settingsReader.Map(Parse(source.Settings))); _settingsFormatter.Map(Parse(source.Settings)));
} }
ContentFieldDefinition Build(ContentFieldDefinitionRecord source) { ContentFieldDefinition Build(ContentFieldDefinitionRecord source) {

View File

@@ -1,17 +1,17 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using System.Xml.Linq;
using Orchard.Core.XmlRpc.Models; using Orchard.Core.XmlRpc.Models;
using Orchard.Core.XmlRpc.Services;
using Orchard.Logging; using Orchard.Logging;
namespace Orchard.Core.XmlRpc.Controllers { namespace Orchard.Core.XmlRpc.Controllers {
public class HomeController : Controller { public class HomeController : Controller {
private readonly IMapper<XRpcMethodResponse, XElement> _writer; private readonly IXmlRpcWriter _writer;
private readonly IEnumerable<IXmlRpcHandler> _xmlRpcHandlers; private readonly IEnumerable<IXmlRpcHandler> _xmlRpcHandlers;
public HomeController( public HomeController(
IMapper<XRpcMethodResponse, XElement> writer, IXmlRpcWriter writer,
IEnumerable<IXmlRpcHandler> xmlRpcHandlers) { IEnumerable<IXmlRpcHandler> xmlRpcHandlers) {
_writer = writer; _writer = writer;
_xmlRpcHandlers = xmlRpcHandlers; _xmlRpcHandlers = xmlRpcHandlers;
@@ -29,7 +29,7 @@ namespace Orchard.Core.XmlRpc.Controllers {
if (methodResponse == null) if (methodResponse == null)
throw new HttpException(500, "TODO: xmlrpc fault"); throw new HttpException(500, "TODO: xmlrpc fault");
var content = _writer.Map(methodResponse).ToString(); var content = _writer.MapMethodResponse(methodResponse).ToString();
return Content(content, "text/xml"); return Content(content, "text/xml");
} }

View File

@@ -2,32 +2,33 @@
using System.Web.Mvc; using System.Web.Mvc;
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.Core.XmlRpc.Services;
using Orchard.Mvc.ModelBinders; using Orchard.Mvc.ModelBinders;
using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider; using IModelBinderProvider = Orchard.Mvc.ModelBinders.IModelBinderProvider;
namespace Orchard.Core.XmlRpc.Models { namespace Orchard.Core.XmlRpc.Models {
public class ModelBinderProvider : IModelBinderProvider, IModelBinder { 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; _mapper = mapper;
} }
public IEnumerable<ModelBinderDescriptor> GetModelBinders() { public IEnumerable<ModelBinderDescriptor> GetModelBinders() {
return new[] { return new[] {
new ModelBinderDescriptor { new ModelBinderDescriptor {
ModelBinder =this, ModelBinder = this,
Type=typeof(XRpcMethodCall) Type = typeof(XRpcMethodCall)
} }
}; };
} }
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
//Ah! xmlrpc is a value provider!!! // Ah! xmlrpc is a value provider!!!
// TODO: refactor this? // TODO: refactor this?
using (var xmlReader = XmlReader.Create(controllerContext.HttpContext.Request.InputStream)) { using (var xmlReader = XmlReader.Create(controllerContext.HttpContext.Request.InputStream)) {
var element = XElement.Load(xmlReader); var element = XElement.Load(xmlReader);
return _mapper.Map(element); return _mapper.MapToMethodCall(element);
} }
} }
} }

View 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);
}
}

View 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);
}
}

View File

@@ -6,91 +6,120 @@ using System.Xml.Linq;
using Orchard.Core.XmlRpc.Models; using Orchard.Core.XmlRpc.Models;
namespace Orchard.Core.XmlRpc.Services { namespace Orchard.Core.XmlRpc.Services {
public class XmlRpcReader : /// <summary>
IMapper<XElement, XRpcMethodCall>, /// Abstraction to read XML and convert it to rpc entities.
IMapper<XElement, XRpcData>, /// </summary>
IMapper<XElement, XRpcStruct>, public class XmlRpcReader : IXmlRpcReader {
IMapper<XElement, XRpcArray> { /// <summary>
/// Provides the mapping function based on a type name.
/// </summary>
private readonly IDictionary<string, Func<XElement, XRpcData>> _dispatch; private readonly IDictionary<string, Func<XElement, XRpcData>> _dispatch;
/// <summary>
/// Initializes a new instance of the <see cref="XmlRpcReader"/> class.
/// </summary>
public XmlRpcReader() { public XmlRpcReader() {
_dispatch = new Dictionary<string, Func<XElement, XRpcData>> _dispatch = new Dictionary<string, Func<XElement, XRpcData>>
{ {
{"i4",x=>new XRpcData<int> { Value = (int)x }}, { "i4", x => new XRpcData<int> { Value = (int)x } },
{"int", x=>new XRpcData<int> { Value = (int)x }}, { "int", x => new XRpcData<int> { Value = (int)x } },
{"boolean", x=>new XRpcData<bool> { Value = ((string)x=="1") }}, { "boolean", x => new XRpcData<bool> { Value = (string)x == "1" } },
{"string", x=>new XRpcData<string> { Value = (string)x }}, { "string", x => new XRpcData<string> { Value = (string)x } },
{"double", x=>new XRpcData<double> { Value = (double)x }}, { "double", x => new XRpcData<double> { Value = (double)x } },
{"dateTime.iso8601", x=> { { "dateTime.iso8601", x => {
DateTime parsedDateTime; DateTime parsedDateTime;
// try parsing a "normal" datetime string then try what live writer gives us // try parsing a "normal" datetime string then try what live writer gives us
if(!DateTime.TryParse(x.Value, out parsedDateTime) if (!DateTime.TryParse(x.Value, out parsedDateTime)
&& !DateTime.TryParseExact(x.Value, "yyyyMMddTHH:mm:ss", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out parsedDateTime)) { && !DateTime.TryParseExact(x.Value, "yyyyMMddTHH:mm:ss", DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out parsedDateTime)) {
parsedDateTime = DateTime.Now; parsedDateTime = DateTime.Now;
} }
return new XRpcData<DateTime> {Value = parsedDateTime};
}}, return new XRpcData<DateTime> { Value = parsedDateTime };
{"base64", x=>new XRpcData<byte[]> { Value = Convert.FromBase64String((string)x) }}, } },
{"struct", x=>XRpcData.For(Map<XRpcStruct>(x))} , { "base64", x => new XRpcData<byte[]> { Value = Convert.FromBase64String((string)x) } },
{"array", x=>XRpcData.For(Map<XRpcArray>(x))} , { "struct", x => XRpcData.For(MapToStruct(x)) },
{ "array", x => XRpcData.For(MapToArray(x)) },
}; };
} }
T2 Map<T2>(XElement t1) { /// <summary>
return ((IMapper<XElement, T2>)this).Map(t1); /// Maps an XML element to a rpc method call.
} /// </summary>
/// <param name="source">The XML element to be mapped.</param>
XRpcData MapValue(XContainer t1) { /// <returns>The rpc method call.</returns>
var element = t1.Elements().SingleOrDefault(); public XRpcMethodCall MapToMethodCall(XElement source) {
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) {
return new XRpcMethodCall { return new XRpcMethodCall {
MethodName = (string)source.Element("methodName"), MethodName = (string)source.Element("methodName"),
Params = source.Elements("params").Elements("param").Select(Map<XRpcData>).ToList() Params = source.Elements("params").Elements("param").Select(MapToData).ToList()
}; };
} }
/// <summary>
XRpcData IMapper<XElement, XRpcData>.Map(XElement source) { /// 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"); var value = source.Element("value");
if (value == null) if (value == null) {
return new XRpcData(); return new XRpcData();
}
var element = value.Elements().SingleOrDefault(); var element = value.Elements().SingleOrDefault();
Func<XElement, XRpcData> dispatch; 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); throw new ApplicationException("Unknown XmlRpc value type " + element.Name.LocalName);
}
return dispatch(element); 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(); var result = new XRpcStruct();
foreach (var member in source.Elements("member")) { foreach (var member in source.Elements("member")) {
result.Members.Add( result.Members.Add(
(string)member.Element("name"), (string)member.Element("name"),
MapValue(member.Element("value"))); MapValue(member.Element("value")));
} }
return result; return result;
} }
/// <summary>
XRpcArray IMapper<XElement, XRpcArray>.Map(XElement source) { /// 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(); var result = new XRpcArray();
foreach (var value in source.Elements("data").Elements("value")) { foreach (var value in source.Elements("data").Elements("value")) {
result.Data.Add(MapValue(value)); result.Data.Add(MapValue(value));
} }
return result; 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);
}
} }
} }

View File

@@ -3,69 +3,98 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.Core.XmlRpc.Models; using Orchard.Core.XmlRpc.Models;
using Orchard.Validation;
namespace Orchard.Core.XmlRpc.Services { namespace Orchard.Core.XmlRpc.Services {
public class XmlRpcWriter : /// <summary>
IMapper<XRpcMethodResponse, XElement>, /// Abstraction to write XML based on rpc entities.
IMapper<XRpcStruct, XElement>, /// </summary>
IMapper<XRpcArray, XElement>, public class XmlRpcWriter : IXmlRpcWriter {
IMapper<XRpcData, XElement> { /// <summary>
/// Provides the mapping function based on a type.
/// </summary>
private readonly IDictionary<Type, Func<XRpcData, XElement>> _dispatch;
/// <summary>
/// Initializes a new instance of the <see cref="XmlRpcWriter"/> class.
/// </summary>
public XmlRpcWriter() { public XmlRpcWriter() {
_dispatch = new Dictionary<Type, Func<XRpcData, XElement>> _dispatch = new Dictionary<Type, Func<XRpcData, XElement>>
{ {
{typeof(int), p=>new XElement("int", (int)p.Value)}, { typeof(int), p => new XElement("int", (int)p.Value) },
{typeof(bool), p=>new XElement("boolean", (bool)p.Value?"1":"0")}, { typeof(bool), p => new XElement("boolean", (bool)p.Value ? "1" : "0") },
{typeof(string), p=>new XElement("string", p.Value)}, { typeof(string), p => new XElement("string", p.Value) },
{typeof(double), p=>new XElement("double", (double)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).ToString("yyyyMMddTHH:mm:ssZ")) },
{typeof(DateTime?), p=>new XElement("dateTime.iso8601", ((DateTime?)p.Value).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(byte[]), p => new XElement("base64", Convert.ToBase64String((byte[])p.Value)) },
{typeof(XRpcStruct), p=>Map((XRpcStruct)p.Value)}, { typeof(XRpcStruct), p => MapStruct((XRpcStruct)p.Value) },
{typeof(XRpcArray), p=>Map((XRpcArray)p.Value)}, { typeof(XRpcArray), p => MapArray((XRpcArray)p.Value) },
}; };
} }
private readonly IDictionary<Type, Func<XRpcData, XElement>> _dispatch; /// <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");
XElement IMapper<XRpcMethodResponse, XElement>.Map(XRpcMethodResponse source) {
return new XElement( return new XElement(
"methodResponse", "methodResponse",
new XElement( new XElement(
"params", "params",
source.Params.Select( rpcMethodResponse.Params.Select(
p => new XElement("param", MapValue(p))))); p => new XElement("param", MapValue(p)))));
} }
XElement IMapper<XRpcData, XElement>.Map(XRpcData source) { /// <summary>
return new XElement("param", MapValue(source)); /// 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( return new XElement(
"struct", "struct",
source.Members.Select( rpcStruct.Members.Select(
kv => new XElement( kv => new XElement(
"member", "member",
new XElement("name", kv.Key), new XElement("name", kv.Key),
MapValue(kv.Value)))); 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( return new XElement(
"array", "array",
new XElement( new XElement(
"data", "data",
source.Data.Select(d => MapValue(d)))); rpcArray.Data.Select(MapValue)));
} }
XElement Map<T>(T t) { /// <summary>
return ((IMapper<T, XElement>)this).Map(t); /// 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));
}
} }
} }

View File

@@ -2,35 +2,60 @@
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models; using Orchard.Validation;
namespace Orchard.ContentManagement.MetaData.Services { namespace Orchard.ContentManagement.MetaData.Services {
/// <summary>
/// The content definition reader is used to import both content type and content part definitions from a XML format.
/// </summary>
public class ContentDefinitionReader : IContentDefinitionReader { public class ContentDefinitionReader : IContentDefinitionReader {
private readonly IMapper<XElement, SettingsDictionary> _settingsReader; /// <summary>
/// The settings formatter to be used to convert the settings between a XML format and a dictionary.
/// </summary>
private readonly ISettingsFormatter _settingsFormatter;
public ContentDefinitionReader(IMapper<XElement, SettingsDictionary> settingsReader) { /// <summary>
_settingsReader = settingsReader; /// Initializes a new instance of the <see cref="ContentDefinitionReader"/> class.
/// </summary>
/// <param name="settingsFormatter">The settings formatter to be used to convert the settings between a dictionary and an XML format.</param>
public ContentDefinitionReader(ISettingsFormatter settingsFormatter) {
Argument.ThrowIfNull(settingsFormatter, "settingsFormatter");
_settingsFormatter = settingsFormatter;
} }
public void Merge(XElement source, ContentTypeDefinitionBuilder builder) { /// <summary>
builder.Named(XmlConvert.DecodeName(source.Name.LocalName)); /// Merges a given content type definition provided in a XML format into a content type definition builder.
foreach (var setting in _settingsReader.Map(source)) { /// </summary>
builder.WithSetting(setting.Key, setting.Value); /// <param name="element">The XML content type definition.</param>
/// <param name="contentTypeDefinitionBuilder">The content type definition builder.</param>
public void Merge(XElement element, ContentTypeDefinitionBuilder contentTypeDefinitionBuilder) {
Argument.ThrowIfNull(element, "element");
Argument.ThrowIfNull(contentTypeDefinitionBuilder, "contentTypeDefinitionBuilder");
// Merge name
contentTypeDefinitionBuilder.Named(XmlConvert.DecodeName(element.Name.LocalName));
// Merge settings
foreach (var setting in _settingsFormatter.Map(element)) {
contentTypeDefinitionBuilder.WithSetting(setting.Key, setting.Value);
} }
foreach (var iter in source.Elements()) {
// Merge parts
foreach (var iter in element.Elements()) {
var partElement = iter; var partElement = iter;
var partName = XmlConvert.DecodeName(partElement.Name.LocalName); var partName = XmlConvert.DecodeName(partElement.Name.LocalName);
if (partName == "remove") { if (partName == "remove") {
var nameAttribute = partElement.Attribute("name"); var nameAttribute = partElement.Attribute("name");
if (nameAttribute != null) { if (nameAttribute != null) {
builder.RemovePart(nameAttribute.Value); contentTypeDefinitionBuilder.RemovePart(nameAttribute.Value);
} }
} }
else { else {
builder.WithPart( contentTypeDefinitionBuilder.WithPart(
partName, partName,
partBuilder => { partBuilder => {
foreach (var setting in _settingsReader.Map(partElement)) { foreach (var setting in _settingsFormatter.Map(partElement)) {
partBuilder.WithSetting(setting.Key, setting.Value); partBuilder.WithSetting(setting.Key, setting.Value);
} }
}); });
@@ -38,13 +63,25 @@ namespace Orchard.ContentManagement.MetaData.Services {
} }
} }
public void Merge(XElement source, ContentPartDefinitionBuilder builder) { /// <summary>
builder.Named(XmlConvert.DecodeName(source.Name.LocalName)); /// Merges a given content part definition provided in a XML format into a content part definition builder.
foreach (var setting in _settingsReader.Map(source)) { /// </summary>
builder.WithSetting(setting.Key, setting.Value); /// <param name="element">The XML content type definition.</param>
/// <param name="contentPartDefinitionBuilder">The content part definition builder.</param>
public void Merge(XElement element, ContentPartDefinitionBuilder contentPartDefinitionBuilder) {
Argument.ThrowIfNull(element, "element");
Argument.ThrowIfNull(contentPartDefinitionBuilder, "contentPartDefinitionBuilder");
// Merge name
contentPartDefinitionBuilder.Named(XmlConvert.DecodeName(element.Name.LocalName));
// Merge settings
foreach (var setting in _settingsFormatter.Map(element)) {
contentPartDefinitionBuilder.WithSetting(setting.Key, setting.Value);
} }
foreach (var iter in source.Elements()) { // Merge fields
foreach (var iter in element.Elements()) {
var fieldElement = iter; var fieldElement = iter;
var fieldParameters = XmlConvert.DecodeName(fieldElement.Name.LocalName).Split(new[] { '.' }, 2); var fieldParameters = XmlConvert.DecodeName(fieldElement.Name.LocalName).Split(new[] { '.' }, 2);
var fieldName = fieldParameters.FirstOrDefault(); var fieldName = fieldParameters.FirstOrDefault();
@@ -52,15 +89,15 @@ namespace Orchard.ContentManagement.MetaData.Services {
if (fieldName == "remove") { if (fieldName == "remove") {
var nameAttribute = fieldElement.Attribute("name"); var nameAttribute = fieldElement.Attribute("name");
if (nameAttribute != null) { if (nameAttribute != null) {
builder.RemoveField(nameAttribute.Value); contentPartDefinitionBuilder.RemoveField(nameAttribute.Value);
} }
} }
else { else {
builder.WithField( contentPartDefinitionBuilder.WithField(
fieldName, fieldName,
fieldBuilder => { fieldBuilder => {
fieldBuilder.OfType(fieldType); fieldBuilder.OfType(fieldType);
foreach (var setting in _settingsReader.Map(fieldElement)) { foreach (var setting in _settingsFormatter.Map(fieldElement)) {
fieldBuilder.WithSetting(setting.Key, setting.Value); fieldBuilder.WithSetting(setting.Key, setting.Value);
} }
}); });

View File

@@ -1,42 +1,76 @@
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.MetaData.Models;
using Orchard.Validation;
namespace Orchard.ContentManagement.MetaData.Services { namespace Orchard.ContentManagement.MetaData.Services {
/// <summary>
/// The content definition writer is used to export both content type and content part definitions to a XML format.
/// </summary>
public class ContentDefinitionWriter : IContentDefinitionWriter { public class ContentDefinitionWriter : IContentDefinitionWriter {
private readonly IMapper<SettingsDictionary, XElement> _settingsWriter; /// <summary>
/// The settings formatter to be used to convert the settings between a dictionary and an XML format.
/// </summary>
private readonly ISettingsFormatter _settingsFormatter;
public ContentDefinitionWriter(IMapper<SettingsDictionary, XElement> settingsWriter) { /// <summary>
_settingsWriter = settingsWriter; /// Initializes a new instance of the <see cref="ContentDefinitionWriter"/> class.
/// </summary>
/// <param name="settingsFormatter">The settings formatter to be used to convert the settings between a dictionary and an XML format.</param>
public ContentDefinitionWriter(ISettingsFormatter settingsFormatter) {
Argument.ThrowIfNull(settingsFormatter, "settingsFormatter");
_settingsFormatter = settingsFormatter;
} }
public XElement Export(ContentTypeDefinition typeDefinition) { /// <summary>
var typeElement = NewElement(typeDefinition.Name, typeDefinition.Settings); /// Exports a content type definition to a XML format.
if (typeElement.Attribute("DisplayName") == null && typeDefinition.DisplayName != null) { /// </summary>
typeElement.Add(new XAttribute("DisplayName", typeDefinition.DisplayName)); /// <param name="contentTypeDefinition">The type definition to be exported.</param>
/// <returns>The content type definition in an XML format.</returns>
public XElement Export(ContentTypeDefinition contentTypeDefinition) {
Argument.ThrowIfNull(contentTypeDefinition, "typeDefinition");
var typeElement = NewElement(contentTypeDefinition.Name, contentTypeDefinition.Settings);
if (typeElement.Attribute("DisplayName") == null && contentTypeDefinition.DisplayName != null) {
typeElement.Add(new XAttribute("DisplayName", contentTypeDefinition.DisplayName));
} }
foreach(var typePart in typeDefinition.Parts) { foreach (var typePart in contentTypeDefinition.Parts) {
typeElement.Add(NewElement(typePart.PartDefinition.Name, typePart.Settings)); typeElement.Add(NewElement(typePart.PartDefinition.Name, typePart.Settings));
} }
return typeElement; return typeElement;
} }
public XElement Export(ContentPartDefinition partDefinition) { /// <summary>
var partElement = NewElement(partDefinition.Name, partDefinition.Settings); /// Exports a content part definition to a XML format.
foreach(var partField in partDefinition.Fields) { /// </summary>
var attributeName = partField.Name + "." + partField.FieldDefinition.Name; /// <param name="contentPartDefinition">The part definition to be exported.</param>
/// <returns>The content part definition in a XML format.</returns>
public XElement Export(ContentPartDefinition contentPartDefinition) {
Argument.ThrowIfNull(contentPartDefinition, "contentPartDefinition");
var partElement = NewElement(contentPartDefinition.Name, contentPartDefinition.Settings);
foreach (var partField in contentPartDefinition.Fields) {
var attributeName = string.Format("{0}.{1}", partField.Name, partField.FieldDefinition.Name);
var partFieldElement = NewElement(attributeName, partField.Settings); var partFieldElement = NewElement(attributeName, partField.Settings);
partElement.Add(partFieldElement); partElement.Add(partFieldElement);
} }
return partElement; return partElement;
} }
/// <summary>
/// Builds a new XML element with a given name and a settings dictionary.
/// </summary>
/// <param name="name">The name of the element to be mapped to XML.</param>
/// <param name="settings">The settings dictionary to be used as the element's attributes.</param>
/// <returns>The new XML element.</returns>
private XElement NewElement(string name, SettingsDictionary settings) { private XElement NewElement(string name, SettingsDictionary settings) {
var element = new XElement(XmlConvert.EncodeLocalName(name)); XElement element = _settingsFormatter.Map(settings);
foreach(var settingAttribute in _settingsWriter.Map(settings).Attributes()) { element.Name = XmlConvert.EncodeLocalName(name);
element.Add(settingAttribute);
}
return element; return element;
} }
} }

View File

@@ -0,0 +1,23 @@
using System.Xml.Linq;
using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.ContentManagement.MetaData.Services {
/// <summary>
/// Abstraction to manage settings metadata on a content.
/// </summary>
public interface ISettingsFormatter : IDependency {
/// <summary>
/// Maps an XML element to a settings dictionary.
/// </summary>
/// <param name="element">The XML element to be mapped.</param>
/// <returns>The settings dictionary.</returns>
SettingsDictionary Map(XElement element);
/// <summary>
/// Maps a settings dictionary to an XML element.
/// </summary>
/// <param name="settingsDictionary">The settings dictionary.</param>
/// <returns>The XML element.</returns>
XElement Map(SettingsDictionary settingsDictionary);
}
}

View File

@@ -4,22 +4,40 @@ using System.Xml.Linq;
using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.ContentManagement.MetaData.Services { namespace Orchard.ContentManagement.MetaData.Services {
public class SettingsFormatter : /// <summary>
IMapper<XElement, SettingsDictionary>, /// Abstraction to manage settings metadata on a content.
IMapper<SettingsDictionary, XElement> { /// </summary>
public class SettingsFormatter : ISettingsFormatter {
public SettingsDictionary Map(XElement source) { /// <summary>
if (source == null) /// Maps an XML element to a settings dictionary.
/// </summary>
/// <param name="element">The XML element to be mapped.</param>
/// <returns>The settings dictionary.</returns>
public SettingsDictionary Map(XElement element) {
if (element == null) {
return new SettingsDictionary(); return new SettingsDictionary();
return new SettingsDictionary(source.Attributes().ToDictionary(attr => XmlConvert.DecodeName(attr.Name.LocalName), attr => attr.Value));
} }
public XElement Map(SettingsDictionary source) { return new SettingsDictionary(
if (source == null) element.Attributes()
return new XElement("settings"); .ToDictionary(attr => XmlConvert.DecodeName(attr.Name.LocalName), attr => attr.Value));
}
return new XElement("settings", source.Where(kv => kv.Value != null).Select(kv => new XAttribute(XmlConvert.EncodeLocalName(kv.Key), kv.Value))); /// <summary>
/// Maps a settings dictionary to an XML element.
/// </summary>
/// <param name="settingsDictionary">The settings dictionary.</param>
/// <returns>The XML element.</returns>
public XElement Map(SettingsDictionary settingsDictionary) {
if (settingsDictionary == null) {
return new XElement("settings");
}
return new XElement(
"settings",
settingsDictionary
.Where(kv => kv.Value != null)
.Select(kv => new XAttribute(XmlConvert.EncodeLocalName(kv.Key), kv.Value)));
} }
} }
} }

View File

@@ -179,6 +179,7 @@
<Compile Include="ContentManagement\Handlers\TitleAspectHandler.cs" /> <Compile Include="ContentManagement\Handlers\TitleAspectHandler.cs" />
<Compile Include="ContentManagement\IContentBehavior.cs" /> <Compile Include="ContentManagement\IContentBehavior.cs" />
<Compile Include="ContentManagement\ImportContentSession.cs" /> <Compile Include="ContentManagement\ImportContentSession.cs" />
<Compile Include="ContentManagement\MetaData\Services\ISettingsFormatter.cs" />
<Compile Include="ContentManagement\QueryHints.cs" /> <Compile Include="ContentManagement\QueryHints.cs" />
<Compile Include="ContentManagement\Utilities\ComputedField.cs" /> <Compile Include="ContentManagement\Utilities\ComputedField.cs" />
<Compile Include="Data\Conventions\AggregateAttribute.cs" /> <Compile Include="Data\Conventions\AggregateAttribute.cs" />