From 06ff2ebfc2ebaf45a2f90f85850d99f89f4c13a3 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Mon, 27 Feb 2017 22:58:26 +0000 Subject: [PATCH 01/53] + Create SPMeta2.Nintex packages #839 + nitial code move from 75e6582 / 54ca948 / d693494 / 1d85bea --- SPMeta2/SPMeta2.Nintex.CSOM/Class1.cs | 12 --- .../NintexWorkflowModelHandler.cs | 83 +++++++++++++++++++ .../SPMeta2.Nintex.CSOM.csproj | 24 +++++- SPMeta2/SPMeta2.Nintex.SSOM/Class1.cs | 12 --- .../NintexWorkflowModelHandler.cs | 83 +++++++++++++++++++ .../SPMeta2.Nintex.SSOM.csproj | 22 ++++- SPMeta2/SPMeta2.Nintex/Class1.cs | 12 --- SPMeta2/SPMeta2.Nintex/Consts/NintexUrls.cs | 17 ++++ .../Definitions/NintexWorkflowDefinition.cs | 18 ++++ SPMeta2/SPMeta2.Nintex/SPMeta2.Nintex.csproj | 10 ++- .../Syntax/ModelWithNamespaces.cs | 36 ++++++++ 11 files changed, 290 insertions(+), 39 deletions(-) delete mode 100644 SPMeta2/SPMeta2.Nintex.CSOM/Class1.cs create mode 100644 SPMeta2/SPMeta2.Nintex.CSOM/ModelHandlers/NintexWorkflowModelHandler.cs delete mode 100644 SPMeta2/SPMeta2.Nintex.SSOM/Class1.cs create mode 100644 SPMeta2/SPMeta2.Nintex.SSOM/ModelHandlers/NintexWorkflowModelHandler.cs delete mode 100644 SPMeta2/SPMeta2.Nintex/Class1.cs create mode 100644 SPMeta2/SPMeta2.Nintex/Consts/NintexUrls.cs create mode 100644 SPMeta2/SPMeta2.Nintex/Definitions/NintexWorkflowDefinition.cs create mode 100644 SPMeta2/SPMeta2.Nintex/Syntax/ModelWithNamespaces.cs diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/Class1.cs b/SPMeta2/SPMeta2.Nintex.CSOM/Class1.cs deleted file mode 100644 index 0aa2d4e16..000000000 --- a/SPMeta2/SPMeta2.Nintex.CSOM/Class1.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - - -namespace SPMeta2.Nintex.CSOM -{ - public class Class1 - { - } -} diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/ModelHandlers/NintexWorkflowModelHandler.cs b/SPMeta2/SPMeta2.Nintex.CSOM/ModelHandlers/NintexWorkflowModelHandler.cs new file mode 100644 index 000000000..71d2b1265 --- /dev/null +++ b/SPMeta2/SPMeta2.Nintex.CSOM/ModelHandlers/NintexWorkflowModelHandler.cs @@ -0,0 +1,83 @@ +using System; +using System.Text; +using SPMeta2.Common; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.ModelHandlers; +using SPMeta2.Nintex.Consts; +using SPMeta2.Nintex.Definitions; +using SPMeta2.Utils; + +namespace SPMeta2.Nintex.CSOM.ModelHandlers +{ + public class NintexWorkflowModelHandler : ModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(NintexWorkflowDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var workflowDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + // Nintex workflow web service updates current list with 4 versions + // We can't really call SPList.Update for the current list as we have 'Save conflict exception' + // We say 'don't update list' to the parent model host, so we safe and can make other list operations + listModelHost.ShouldUpdateHost = false; + + DeployNintexWorkflow(listModelHost, workflowDefinition); + } + + private void DeployNintexWorkflow(ListModelHost listModelHost, NintexWorkflowDefinition workflowDefinition) + { + var list = listModelHost.HostList; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = workflowDefinition, + ObjectType = typeof(NintexWorkflowDefinition), + ObjectDefinition = workflowDefinition, + ModelHost = list + }); + + // TODO, add NintexWorkflowService web service ref + + //using (var nintexService = new NintexWorkflowService.NintexWorkflowWS()) + //{ + // nintexService.Url = list.ParentWeb.Url + "/" + NintexUrls.WorkflowServiceUrl; + // nintexService.PreAuthenticate = true; + // nintexService.Credentials = System.Net.CredentialCache.DefaultCredentials; + + // var xmlnw = Encoding.UTF8.GetString(workflowDefinition.WorkflowXml); + + // var result = nintexService.PublishFromNWFXml(xmlnw, list.Title, workflowDefinition.WorkflowName, true); + //} + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = workflowDefinition, + ObjectType = typeof(NintexWorkflowDefinition), + ObjectDefinition = workflowDefinition, + ModelHost = list + }); + + } + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/SPMeta2.Nintex.CSOM.csproj b/SPMeta2/SPMeta2.Nintex.CSOM/SPMeta2.Nintex.CSOM.csproj index e141fa8b5..7da2a3ac5 100644 --- a/SPMeta2/SPMeta2.Nintex.CSOM/SPMeta2.Nintex.CSOM.csproj +++ b/SPMeta2/SPMeta2.Nintex.CSOM/SPMeta2.Nintex.CSOM.csproj @@ -30,6 +30,14 @@ 4 + + False + ..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4569.1000\CSOM\Microsoft.SharePoint.Client.dll + + + False + ..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4569.1000\CSOM\Microsoft.SharePoint.Client.Runtime.dll + @@ -39,9 +47,23 @@ - + + + + {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4} + SPMeta2.CSOM + + + {D19B0907-CED5-416A-9D45-0F112990C234} + SPMeta2.Nintex + + + {EE49D3FD-6180-40E6-829F-6831FF89DAC6} + SPMeta2 + + bin\Debug35-$(spRuntime)\ @@ -41,7 +40,6 @@ 4 false bin\Debug40-$(spRuntime)\SPMeta2.CSOM.Standard.XML - bin\Debug45-$(spRuntime)\ @@ -55,9 +53,8 @@ false bin\Debug45-$(spRuntime)\SPMeta2.CSOM.Standard.XML - - - + + bin\Debug\ v4.5 true @@ -80,7 +77,7 @@ True ..\SPMeta2.Dependencies\SharePoint\SP2010 - 14.0.4762.1000\CSOM\Microsoft.SharePoint.Client.dll False - + True ..\SPMeta2.Dependencies\SharePoint\SP2010 - 14.0.4762.1000\CSOM\Microsoft.SharePoint.Client.Runtime.dll @@ -150,7 +147,7 @@ ..\SPMeta2.Dependencies\SharePoint\SP2016 - 16.0.4306.1001\CSOM\Microsoft.SharePoint.Client.WorkflowServices.dll False - + True ..\SPMeta2.Dependencies\SharePoint\SP2016 - 16.0.4306.1001\CSOM\Microsoft.SharePoint.Client.DocumentManagement.dll False @@ -246,7 +243,7 @@ - + @@ -303,6 +300,7 @@ PublishingPageTemplates.resx + diff --git a/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs b/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs new file mode 100644 index 000000000..b6dd91e17 --- /dev/null +++ b/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs @@ -0,0 +1,66 @@ +using SPMeta2.Common; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Services; +using SPMeta2.CSOM.Standard.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHandlers.Fields; +using SPMeta2.Services.Impl; +using SPMeta2.Standard.Definitions; +using SPMeta2.Standard.Definitions.Fields; +using SPMeta2.Services; +using SPMeta2.Interfaces; + + +namespace SPMeta2.CSOM.Standard.Services +{ + public class StandardCSOMIncrementalProvisionService : StandardCSOMProvisionService, IIncrementalProvisionService + { + #region constructors + + public StandardCSOMIncrementalProvisionService() + { + this.SetIncrementalMode(); + } + + #endregion + + #region properties + + protected virtual DefaultIncrementalModelTreeTraverseService TypedModelTreeTraverseService + { + get + { + return ModelTraverseService as DefaultIncrementalModelTreeTraverseService; + } + } + + public ModelHash PreviousModelHash + { + get + { + return TypedModelTreeTraverseService.PreviousModelHash; + } + set + { + TypedModelTreeTraverseService.PreviousModelHash = value; + } + } + public ModelHash CurrentModelHash + { + get + { + return TypedModelTreeTraverseService.CurrentModelHash; + } + set + { + + } + } + + #endregion + + #region methods + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj index 2da4b7c46..196935976 100644 --- a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj +++ b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj @@ -281,6 +281,7 @@ + diff --git a/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs b/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs new file mode 100644 index 000000000..798ec5f2d --- /dev/null +++ b/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs @@ -0,0 +1,72 @@ +using System; +using Microsoft.SharePoint.Client; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using SPMeta2.Services; +using SPMeta2.Utils; +using System.Reflection; +using System.Diagnostics; +using SPMeta2.CSOM.Services.Impl; +using SPMeta2.Exceptions; +using SPMeta2.Services.Impl; +using SPMeta2.Common; +using SPMeta2.Interfaces; + +namespace SPMeta2.CSOM.Services +{ + public class CSOMIncrementalProvisionService : CSOMProvisionService, IIncrementalProvisionService + { + #region constructors + + public CSOMIncrementalProvisionService() + { + this.SetIncrementalMode(); + } + + #endregion + + #region properties + + protected virtual DefaultIncrementalModelTreeTraverseService TypedModelTreeTraverseService + { + get + { + return ModelTraverseService as DefaultIncrementalModelTreeTraverseService; + } + } + + public ModelHash PreviousModelHash + { + get + { + return TypedModelTreeTraverseService.PreviousModelHash; + } + set + { + TypedModelTreeTraverseService.PreviousModelHash = value; + } + } + public ModelHash CurrentModelHash + { + get + { + return TypedModelTreeTraverseService.CurrentModelHash; + } + set + { + + } + } + + #endregion + + #region methods + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Containers/Utils/ContainerTraceUtils.cs b/SPMeta2/SPMeta2.Containers/Utils/ContainerTraceUtils.cs index f5efa42af..7023bce38 100644 --- a/SPMeta2/SPMeta2.Containers/Utils/ContainerTraceUtils.cs +++ b/SPMeta2/SPMeta2.Containers/Utils/ContainerTraceUtils.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Containers.Utils { diff --git a/SPMeta2/SPMeta2.Nintex/Consts/NintexUrls.cs b/SPMeta2/SPMeta2.Nintex/Consts/NintexUrls.cs index 6f0792451..bd915cb11 100644 --- a/SPMeta2/SPMeta2.Nintex/Consts/NintexUrls.cs +++ b/SPMeta2/SPMeta2.Nintex/Consts/NintexUrls.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Nintex.Consts { diff --git a/SPMeta2/SPMeta2.Nintex/Definitions/NintexWorkflowDefinition.cs b/SPMeta2/SPMeta2.Nintex/Definitions/NintexWorkflowDefinition.cs index 321f4cd2b..9cac15074 100644 --- a/SPMeta2/SPMeta2.Nintex/Definitions/NintexWorkflowDefinition.cs +++ b/SPMeta2/SPMeta2.Nintex/Definitions/NintexWorkflowDefinition.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Nintex.Definitions { diff --git a/SPMeta2/SPMeta2.Nintex/Syntax/ModelWithNamespaces.cs b/SPMeta2/SPMeta2.Nintex/Syntax/ModelWithNamespaces.cs index e4e17b0b7..5ee7f3cf5 100644 --- a/SPMeta2/SPMeta2.Nintex/Syntax/ModelWithNamespaces.cs +++ b/SPMeta2/SPMeta2.Nintex/Syntax/ModelWithNamespaces.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + using SPMeta2.Syntax.Default; using SPMeta2.Syntax.Default.Extensions; diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index 9cefec8b9..ca8750bcd 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -1,146 +1,196 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using Microsoft.SharePoint; -using Microsoft.SharePoint.Taxonomy; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Services; -using SPMeta2.CSOM.Standard.ModelHandlers.Fields; -using SPMeta2.CSOM.Standard.Services; -using SPMeta2.ModelHandlers; -using SPMeta2.Models; -using SPMeta2.Services; -using SPMeta2.SSOM.Services; -using SPMeta2.SSOM.Standard.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Standard.Syntax; -using SPMeta2.Syntax.Default; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.Impl.Tests -{ - [TestClass] - public class ModelHandlersTest - { - #region init - - [ClassInitialize] - public static void Init(TestContext context) - { - - } - - [ClassCleanup] - public static void Cleanup() - { - - } - - #endregion - - #region ProvisionServices - - [TestMethod] - [TestCategory("Regression.Impl.ProvisionServices")] - [TestCategory("CI.Core")] - public void Can_CreateFoundationProvisionService() - { - Assert.IsNotNull(new CSOMProvisionService()); - Assert.IsNotNull(new SSOMProvisionService()); - - } - - [TestMethod] - [TestCategory("Regression.Impl.ProvisionServices")] - [TestCategory("CI.Core")] - public void Can_CreateStandardProvisionService() - { - Assert.IsNotNull(new StandardCSOMProvisionService()); - Assert.IsNotNull(new StandardSSOMProvisionService()); - - } - - [TestMethod] - [TestCategory("Regression.Impl.ProvisionServices.CSOM")] - [TestCategory("CI.Core")] - public void EnsureCSOMModelHandlers() - { - var service = new CSOMProvisionService(); - var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.CSOM.ModelHandlers.FieldModelHandler).Assembly); - - foreach (var srcHandlerImplType in modelHandlers) - { - var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); - Assert.IsNotNull(dstHandlerImpl); - } - } - - [TestMethod] - [TestCategory("Regression.Impl.ProvisionServices.CSOM")] - [TestCategory("CI.Core")] - public void EnsureStandardCSOMModelHandlers() - { - var service = new StandardCSOMProvisionService(); - - var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.CSOM.ModelHandlers.FieldModelHandler).Assembly); - var standardModelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.CSOM.Standard.ModelHandlers.Fields.TaxonomyFieldModelHandler).Assembly); - - foreach (var srcHandlerImplType in modelHandlers) - { - var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); - Assert.IsNotNull(dstHandlerImpl); - } - - foreach (var srcHandlerImplType in standardModelHandlers) - { - var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); - Assert.IsNotNull(dstHandlerImpl); - } - } - - - [TestMethod] - [TestCategory("Regression.Impl.ProvisionServices.SSOM")] - [TestCategory("CI.Core")] - public void EnsureSSOMModelHandlers() - { - var service = new SSOMProvisionService(); - var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.SSOM.ModelHandlers.FieldModelHandler).Assembly); - - foreach (var srcHandlerImplType in modelHandlers) - { - var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); - Assert.IsNotNull(dstHandlerImpl); - } - } - - [TestMethod] - [TestCategory("Regression.Impl.ProvisionServices.SSOM")] - [TestCategory("CI.Core")] - public void EnsureStandardSSOMModelHandlers() - { - var service = new StandardSSOMProvisionService(); - - var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.SSOM.ModelHandlers.FieldModelHandler).Assembly); - var standardModelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.SSOM.Standard.ModelHandlers.Fields.TaxonomyFieldModelHandler).Assembly); - - foreach (var srcHandlerImplType in modelHandlers) - { - var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); - Assert.IsNotNull(dstHandlerImpl); - } - - foreach (var srcHandlerImplType in standardModelHandlers) - { - var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); - Assert.IsNotNull(dstHandlerImpl); - } - } - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.SharePoint; +using Microsoft.SharePoint.Taxonomy; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Services; +using SPMeta2.CSOM.Standard.ModelHandlers.Fields; +using SPMeta2.CSOM.Standard.Services; +using SPMeta2.ModelHandlers; +using SPMeta2.Models; +using SPMeta2.Services; +using SPMeta2.SSOM.Services; +using SPMeta2.SSOM.Standard.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Standard.Syntax; +using SPMeta2.Syntax.Default; +using SPMeta2.Utils; +using SPMeta2.Interfaces; + +namespace SPMeta2.Regression.Impl.Tests +{ + [TestClass] + public class ModelHandlersTest + { + #region init + + [ClassInitialize] + public static void Init(TestContext context) + { + + } + + [ClassCleanup] + public static void Cleanup() + { + + } + + #endregion + + #region ProvisionServices + + [TestMethod] + [TestCategory("Regression.Impl.ProvisionServices")] + [TestCategory("CI.Core")] + public void Can_CreateFoundationProvisionService() + { + Assert.IsNotNull(new CSOMProvisionService()); + Assert.IsNotNull(new SSOMProvisionService()); + + } + + [TestMethod] + [TestCategory("Regression.Impl.ProvisionServices")] + [TestCategory("CI.Core")] + public void Can_CreateStandardProvisionService() + { + Assert.IsNotNull(new StandardCSOMProvisionService()); + Assert.IsNotNull(new StandardSSOMProvisionService()); + + } + + [TestMethod] + [TestCategory("Regression.Impl.ProvisionServices.CSOM")] + [TestCategory("CI.Core")] + public void EnsureCSOMModelHandlers() + { + var service = new CSOMProvisionService(); + var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.CSOM.ModelHandlers.FieldModelHandler).Assembly); + + foreach (var srcHandlerImplType in modelHandlers) + { + var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); + Assert.IsNotNull(dstHandlerImpl); + } + } + + [TestMethod] + [TestCategory("Regression.Impl.ProvisionServices.CSOM")] + [TestCategory("CI.Core")] + public void EnsureStandardCSOMModelHandlers() + { + var service = new StandardCSOMProvisionService(); + + var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.CSOM.ModelHandlers.FieldModelHandler).Assembly); + var standardModelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.CSOM.Standard.ModelHandlers.Fields.TaxonomyFieldModelHandler).Assembly); + + foreach (var srcHandlerImplType in modelHandlers) + { + var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); + Assert.IsNotNull(dstHandlerImpl); + } + + foreach (var srcHandlerImplType in standardModelHandlers) + { + var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); + Assert.IsNotNull(dstHandlerImpl); + } + } + + + [TestMethod] + [TestCategory("Regression.Impl.ProvisionServices.SSOM")] + [TestCategory("CI.Core")] + public void EnsureSSOMModelHandlers() + { + var service = new SSOMProvisionService(); + var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.SSOM.ModelHandlers.FieldModelHandler).Assembly); + + foreach (var srcHandlerImplType in modelHandlers) + { + var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); + Assert.IsNotNull(dstHandlerImpl); + } + } + + [TestMethod] + [TestCategory("Regression.Impl.ProvisionServices.SSOM")] + [TestCategory("CI.Core")] + public void EnsureStandardSSOMModelHandlers() + { + var service = new StandardSSOMProvisionService(); + + var modelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.SSOM.ModelHandlers.FieldModelHandler).Assembly); + var standardModelHandlers = ReflectionUtils.GetTypesFromAssembly(typeof(SPMeta2.SSOM.Standard.ModelHandlers.Fields.TaxonomyFieldModelHandler).Assembly); + + foreach (var srcHandlerImplType in modelHandlers) + { + var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); + Assert.IsNotNull(dstHandlerImpl); + } + + foreach (var srcHandlerImplType in standardModelHandlers) + { + var dstHandlerImpl = service.ModelHandlers.Values.FirstOrDefault(h => h.GetType() == srcHandlerImplType); + Assert.IsNotNull(dstHandlerImpl); + } + } + + #endregion + + #region incremental proivision services + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService")] + [TestCategory("CI.Core")] + public void Can_Create_IncrementaProvisionServices() + { + var services = new List(); + + services.Add(new CSOMIncrementalProvisionService()); + services.Add(new StandardCSOMIncrementalProvisionService()); + + services.Add(new SSOMIncrementalProvisionService()); + services.Add(new StandardSSOMIncrementalProvisionService()); + + foreach (var service in services) + { + var incrementalService = service as IIncrementalProvisionService; + + Assert.IsNotNull(incrementalService.PreviousModelHash); + Assert.IsNotNull(incrementalService.CurrentModelHash); + } + } + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService")] + [TestCategory("CI.Core")] + public void Can_Create_IncrementaProvisionServices_With_FluentAPI() + { + var services = new List(); + + services.Add(new CSOMProvisionService()); + services.Add(new StandardCSOMProvisionService()); + + services.Add(new SSOMProvisionService()); + services.Add(new StandardSSOMProvisionService()); + + foreach (var service in services) + { + var incrementalService = service.SetIncrementalMode(); + + var currentModelHash = incrementalService.GetIncrementalModelHash(); + + Assert.IsNotNull(currentModelHash); + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs index d7678dd0c..3101f74f9 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs @@ -76,6 +76,8 @@ public void Can_Create_IncrementalModelTreeTraverseService() } + + #endregion diff --git a/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs b/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs index 5438dda32..7e09c01d4 100644 --- a/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs +++ b/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs @@ -5,7 +5,7 @@ using System.IO; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Regression.Service { diff --git a/SPMeta2/SPMeta2.Regression/Utils/RegressionTrace.cs b/SPMeta2/SPMeta2.Regression/Utils/RegressionTrace.cs index 7e9e8c033..e17e2f727 100644 --- a/SPMeta2/SPMeta2.Regression/Utils/RegressionTrace.cs +++ b/SPMeta2/SPMeta2.Regression/Utils/RegressionTrace.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Regression.Utils { diff --git a/SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj b/SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj index 122a809cd..6c5fd727b 100644 --- a/SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj +++ b/SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj @@ -187,7 +187,7 @@ - + @@ -254,6 +254,7 @@ True PublishingPageTemplates.resx + diff --git a/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs b/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs new file mode 100644 index 000000000..9c2fb006f --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using SPMeta2.SSOM.ModelHandlers; +using SPMeta2.SSOM.Services; +using SPMeta2.SSOM.Standard.ModelHandlers; +using SPMeta2.SSOM.Standard.ModelHandlers.Fields; +using SPMeta2.Standard.Definitions; +using SPMeta2.Standard.Definitions.Fields; + +using SPMeta2.Services; +using SPMeta2.Services.Impl; +using SPMeta2.Common; +using SPMeta2.Interfaces; + +namespace SPMeta2.SSOM.Standard.Services +{ + public class StandardSSOMIncrementalProvisionService : SSOMProvisionService, IIncrementalProvisionService + { + #region constructors + + public StandardSSOMIncrementalProvisionService() + { + this.SetIncrementalMode(); + } + + #endregion + + #region properties + + protected virtual DefaultIncrementalModelTreeTraverseService TypedModelTreeTraverseService + { + get + { + return ModelTraverseService as DefaultIncrementalModelTreeTraverseService; + } + } + + public ModelHash PreviousModelHash + { + get + { + return TypedModelTreeTraverseService.PreviousModelHash; + } + set + { + TypedModelTreeTraverseService.PreviousModelHash = value; + } + } + public ModelHash CurrentModelHash + { + get + { + return TypedModelTreeTraverseService.CurrentModelHash; + } + set + { + + } + } + + #endregion + + #region methods + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj index 213bb891b..6f32aee96 100644 --- a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj +++ b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj @@ -348,6 +348,7 @@ + diff --git a/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs b/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs new file mode 100644 index 000000000..6ce2e1b60 --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs @@ -0,0 +1,69 @@ +using Microsoft.SharePoint; +using Microsoft.SharePoint.Administration; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Interfaces; +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using SPMeta2.Services; +using SPMeta2.Services.Impl; +using SPMeta2.SSOM.ModelHandlers; +using SPMeta2.SSOM.ModelHosts; +using SPMeta2.Utils; +using System; +using System.Reflection; + +namespace SPMeta2.SSOM.Services +{ + public class SSOMIncrementalProvisionService : SSOMProvisionService, IIncrementalProvisionService + { + #region constructors + + public SSOMIncrementalProvisionService() + { + this.SetIncrementalMode(); + } + + #endregion + + #region properties + + protected virtual DefaultIncrementalModelTreeTraverseService TypedModelTreeTraverseService + { + get + { + return ModelTraverseService as DefaultIncrementalModelTreeTraverseService; + } + } + + public ModelHash PreviousModelHash + { + get + { + return TypedModelTreeTraverseService.PreviousModelHash; + } + set + { + TypedModelTreeTraverseService.PreviousModelHash = value; + } + } + public ModelHash CurrentModelHash + { + get + { + return TypedModelTreeTraverseService.CurrentModelHash; + } + set + { + + } + } + + #endregion + + #region methods + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs b/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs new file mode 100644 index 000000000..c84156862 --- /dev/null +++ b/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs @@ -0,0 +1,38 @@ +using SPMeta2.Services.Impl; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SPMeta2.Common +{ + public class IncrementalProvisionConfig + { + #region constructors + + public IncrementalProvisionConfig() + { + PreviousModelHash = new ModelHash(); + } + + #endregion + + #region properties + public ModelHash PreviousModelHash { get; set; } + + public Type CustomModelTreeTraverseServiceType { get; set; } + + #endregion + + public static IncrementalProvisionConfig Default + { + get + { + return new IncrementalProvisionConfig + { + CustomModelTreeTraverseServiceType = typeof(DefaultIncrementalModelTreeTraverseService) + }; + } + } + } +} diff --git a/SPMeta2/SPMeta2/Interfaces/IIncrementalProvisionService.cs b/SPMeta2/SPMeta2/Interfaces/IIncrementalProvisionService.cs new file mode 100644 index 000000000..0d56e5554 --- /dev/null +++ b/SPMeta2/SPMeta2/Interfaces/IIncrementalProvisionService.cs @@ -0,0 +1,21 @@ +using SPMeta2.Common; +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + + +namespace SPMeta2.Interfaces +{ + public interface IIncrementalProvisionService : IProvisionService + { + #region properties + + ModelHash PreviousModelHash { get; set; } + ModelHash CurrentModelHash { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Interfaces/IProvisionService.cs b/SPMeta2/SPMeta2/Interfaces/IProvisionService.cs new file mode 100644 index 000000000..77a0eef76 --- /dev/null +++ b/SPMeta2/SPMeta2/Interfaces/IProvisionService.cs @@ -0,0 +1,20 @@ +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + + +namespace SPMeta2.Interfaces +{ + public interface IProvisionService + { + #region methods + + void DeployModel(ModelHostBase modelHost, ModelNode model); + + #endregion + + } +} diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index 734f07964..a25594938 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -137,6 +137,7 @@ + @@ -350,6 +351,8 @@ + + @@ -399,6 +402,7 @@ + diff --git a/SPMeta2/SPMeta2/ServiceContainer.cs b/SPMeta2/SPMeta2/ServiceContainer.cs index 3392d6944..2f5daf153 100644 --- a/SPMeta2/SPMeta2/ServiceContainer.cs +++ b/SPMeta2/SPMeta2/ServiceContainer.cs @@ -3,6 +3,7 @@ using System.Linq; using SPMeta2.Services; using SPMeta2.Services.Impl; +using SPMeta2.Exceptions; namespace SPMeta2 { @@ -18,12 +19,17 @@ static ServiceContainer() private ServiceContainer() { Services = new Dictionary>(); + ServiceTypes = new Dictionary(); InitServices(); } private void InitServices() { + // types + RegisterServiceType(typeof(ModelTreeTraverseServiceBase), typeof(DefaultModelTreeTraverseService)); + + // service RegisterService(typeof(TraceServiceBase), new TraceSourceService()); RegisterService(typeof(ModelTreeTraverseServiceBase), new DefaultModelTreeTraverseService()); @@ -55,10 +61,52 @@ private void InitServices() public Dictionary> Services { get; set; } + public Dictionary ServiceTypes { get; set; } + #endregion #region methods + + public void RegisterServiceType(Type serviceType, Type implementationType) + { + if (!ServiceTypes.ContainsKey(serviceType)) + ServiceTypes.Add(serviceType, implementationType); + + ServiceTypes[serviceType] = implementationType; + } + + public TServiceType CreateNewService() + where TServiceType : class + { + var type = typeof(TServiceType); + return CreateNewService(type) as TServiceType; + } + + public object CreateNewService(Type serviceType) + { + if (!ServiceTypes.ContainsKey(serviceType)) + throw new SPMeta2Exception(string.Format("Cannot find implementation type for service type:[{0}]", serviceType)); + + return CreateNewInstance(ServiceTypes[serviceType]); + } + + public TInstanceType CreateNewInstance() + where TInstanceType : class + { + return CreateNewInstance(typeof(TInstanceType)) as TInstanceType; + } + + public object CreateNewInstance(Type instanceType) + { + var instance = Activator.CreateInstance(instanceType); + + if (instance == null) + throw new SPMeta2Exception(string.Format("Created instance is null. Service type:[{0}]", instanceType)); + + return instance; + } + public void RegisterService(Type type, object service) { if (!Services.ContainsKey(type)) @@ -124,5 +172,7 @@ public IEnumerable GetServices() public static ServiceContainer Instance { get; set; } #endregion + + } } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index e83bddecf..bb0e18c32 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -28,7 +28,7 @@ public DefaultIncrementalModelTreeTraverseService() #region properties public ModelHash PreviousModelHash { get; set; } - public ModelHash CurrentModelHash { get; set; } + public ModelHash CurrentModelHash { get; private set; } public HashCodeServiceBase _hashService { get; set; } diff --git a/SPMeta2/SPMeta2/Services/ModelServiceBase.cs b/SPMeta2/SPMeta2/Services/ModelServiceBase.cs index 1fe37ada8..0945fcbce 100644 --- a/SPMeta2/SPMeta2/Services/ModelServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/ModelServiceBase.cs @@ -1,399 +1,424 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using SPMeta2.Definitions; -using SPMeta2.Extensions; -using SPMeta2.ModelHandlers; -using SPMeta2.ModelHosts; -using SPMeta2.Models; -using SPMeta2.Services.Impl; -using SPMeta2.Utils; - -namespace SPMeta2.Services -{ - - public class ModelProcessingEventArgs : EventArgs - { - public ModelNode Model { get; set; } - public ModelNode CurrentNode { get; set; } - - public int ProcessedModelNodeCount { get; set; } - - public int TotalModelNodeCount - { - get - { - if (Model == null) - return 0; - - var result = 0; - - Model.WithNodesOfType(n => { result++; }); - - return result; - } - } - } - - /// - /// Base model service class for model provision operations. - /// - public abstract class ModelServiceBase : SPMetaServiceBase - { - #region constructors - - public ModelServiceBase() - { - TraceService = ServiceContainer.Instance.GetService(); - - using (new TraceActivityScope(TraceService, (int)LogEventId.Initialization, - string.Format("Initializing new ModelServiceBase instance of type: [{0}]", GetType()))) - { - ModelHandlers = new Dictionary(); - - // should be a new instance all the time - // ServiceContainer.Instance.GetService(); - ModelTraverseService = new DefaultModelTreeTraverseService(); - - InitModelTraverseService(); - - // default pre-post deployment services - PreDeploymentServices = new List(); - PreDeploymentServices.AddRange(ServiceContainer.Instance.GetServices()); - - PostDeploymentServices = new List(); - PostDeploymentServices.AddRange(ServiceContainer.Instance.GetServices()); - } - } - - - - #endregion - - #region static - - public static void RegisterModelHandlers(ModelServiceBase instance) - where T : ModelHandlerBase - { - RegisterModelHandlers(instance, Assembly.GetExecutingAssembly()); - } - - public static void RegisterModelHandlers(ModelServiceBase instance, Assembly asm) - where T : ModelHandlerBase - { - var traceService = ServiceContainer.Instance.GetService(); - var handlerTypes = ReflectionUtils.GetTypesFromAssembly(asm); - - traceService.VerboseFormat((int)LogEventId.CoreCalls, - "RegisterModelHandlers for service:[{0}] and assembly: [{1}]", +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using SPMeta2.Definitions; +using SPMeta2.Extensions; +using SPMeta2.ModelHandlers; +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using SPMeta2.Services.Impl; +using SPMeta2.Utils; + +namespace SPMeta2.Services +{ + + public class ModelProcessingEventArgs : EventArgs + { + public ModelNode Model { get; set; } + public ModelNode CurrentNode { get; set; } + + public int ProcessedModelNodeCount { get; set; } + + public int TotalModelNodeCount + { + get + { + if (Model == null) + return 0; + + var result = 0; + + Model.WithNodesOfType(n => { result++; }); + + return result; + } + } + } + + /// + /// Base model service class for model provision operations. + /// + public abstract class ModelServiceBase : SPMetaServiceBase + { + #region constructors + + public ModelServiceBase() + { + TraceService = ServiceContainer.Instance.GetService(); + + using (new TraceActivityScope(TraceService, (int)LogEventId.Initialization, + string.Format("Initializing new ModelServiceBase instance of type: [{0}]", GetType()))) + { + ModelHandlers = new Dictionary(); + + // should be a new instance all the time + //// ServiceContainer.Instance.GetService(); + //ModelTraverseService = new DefaultModelTreeTraverseService(); + + + + // default pre-post deployment services + PreDeploymentServices = new List(); + PreDeploymentServices.AddRange(ServiceContainer.Instance.GetServices()); + + PostDeploymentServices = new List(); + PostDeploymentServices.AddRange(ServiceContainer.Instance.GetServices()); + } + } + + #endregion + + #region static + + public static void RegisterModelHandlers(ModelServiceBase instance) + where T : ModelHandlerBase + { + RegisterModelHandlers(instance, Assembly.GetExecutingAssembly()); + } + + public static void RegisterModelHandlers(ModelServiceBase instance, Assembly asm) + where T : ModelHandlerBase + { + var traceService = ServiceContainer.Instance.GetService(); + var handlerTypes = ReflectionUtils.GetTypesFromAssembly(asm); + + traceService.VerboseFormat((int)LogEventId.CoreCalls, + "RegisterModelHandlers for service:[{0}] and assembly: [{1}]", new object[] { instance.GetType(), asm.FullName - }); - - foreach (var handlerType in handlerTypes) - { - var handlerInstance = Activator.CreateInstance(handlerType) as T; - - if (handlerInstance != null) - { - if (!instance.ModelHandlers.ContainsKey(handlerInstance.TargetType)) - { - traceService.VerboseFormat((int)LogEventId.CoreCalls, - "Model handler for type [{0}] has not been registered yet. Registering.", - new object[] { handlerInstance.TargetType }); - - instance.ModelHandlers.Add(handlerInstance.TargetType, handlerInstance); - } - else - { - traceService.VerboseFormat((int)LogEventId.CoreCalls, - "Model handler for type [{0}] has been registered. Skipping.", - new object[] { handlerInstance.TargetType }); - } - } - } - } - - #endregion - - #region properties - - // public ModelWeighServiceBase ModelWeighService { get; set; } - - private readonly List _modelHandlerEvents = new List(); - private ModelNode _activeModelNode = null; - - public ModelTreeTraverseServiceBase ModelTraverseService { get; set; } - - public List PreDeploymentServices { get; set; } - public List PostDeploymentServices { get; set; } - - #endregion - - #region events - - public EventHandler OnModelNodeProcessed; - public EventHandler OnModelNodeProcessing; - - #endregion - - #region methods - - public void RegisterModelHandlers(Assembly assembly) - { - RegisterModelHandlers(assembly); - } - - public void RegisterModelHandlers(Assembly assembly) - where TModelHandlerBase : ModelHandlerBase - { - using (new TraceActivityScope(TraceService, (int)LogEventId.CoreCalls, string.Format("RegisterModelHandlers for assembly:[{0}]", assembly.FullName))) - { - RegisterModelHandlers(this, assembly); - } - } - - public void RegisterModelHandler(ModelHandlerBase modelHandlerType) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, - "RegisterModelHandler of type:[{0}] for target type:[{1}]", + }); + + foreach (var handlerType in handlerTypes) + { + var handlerInstance = Activator.CreateInstance(handlerType) as T; + + if (handlerInstance != null) + { + if (!instance.ModelHandlers.ContainsKey(handlerInstance.TargetType)) + { + traceService.VerboseFormat((int)LogEventId.CoreCalls, + "Model handler for type [{0}] has not been registered yet. Registering.", + new object[] { handlerInstance.TargetType }); + + instance.ModelHandlers.Add(handlerInstance.TargetType, handlerInstance); + } + else + { + traceService.VerboseFormat((int)LogEventId.CoreCalls, + "Model handler for type [{0}] has been registered. Skipping.", + new object[] { handlerInstance.TargetType }); + } + } + } + } + + #endregion + + #region properties + + public Type CustomModelTreeTraverseServiceType { get; set; } + + // public ModelWeighServiceBase ModelWeighService { get; set; } + + private readonly List _modelHandlerEvents = new List(); + private ModelNode _activeModelNode = null; + + private ModelTreeTraverseServiceBase _modelTraverseService; + + public ModelTreeTraverseServiceBase ModelTraverseService + { + get + { + if (_modelTraverseService == null) + { + if (CustomModelTreeTraverseServiceType != null) + { + _modelTraverseService = ServiceContainer.Instance + .CreateNewInstance(CustomModelTreeTraverseServiceType) as ModelTreeTraverseServiceBase; + } + else + { + _modelTraverseService = ServiceContainer.Instance + .CreateNewService(); + } + + InitModelTraverseService(); + } + + return _modelTraverseService; + } + set { } + } + + public List PreDeploymentServices { get; set; } + public List PostDeploymentServices { get; set; } + + #endregion + + #region events + + public EventHandler OnModelNodeProcessed; + public EventHandler OnModelNodeProcessing; + + #endregion + + #region methods + + public void RegisterModelHandlers(Assembly assembly) + { + RegisterModelHandlers(assembly); + } + + public void RegisterModelHandlers(Assembly assembly) + where TModelHandlerBase : ModelHandlerBase + { + using (new TraceActivityScope(TraceService, (int)LogEventId.CoreCalls, string.Format("RegisterModelHandlers for assembly:[{0}]", assembly.FullName))) + { + RegisterModelHandlers(this, assembly); + } + } + + public void RegisterModelHandler(ModelHandlerBase modelHandlerType) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, + "RegisterModelHandler of type:[{0}] for target type:[{1}]", new object[] { modelHandlerType.GetType(), modelHandlerType.TargetType - }); - - if (!ModelHandlers.ContainsKey(modelHandlerType.TargetType)) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, - "Model handler for type [{0}] has not been registered yet. Registering.", - new object[] { modelHandlerType.GetType() }); - - ModelHandlers.Add(modelHandlerType.TargetType, modelHandlerType); - } - else - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, - "Model handler for type [{0}] has been registered. Skipping.", - new object[] { modelHandlerType.GetType() }); - } - } - - public Dictionary ModelHandlers { get; set; } - - #endregion - - #region public API - - public virtual void DeployModel(ModelHostBase modelHost, ModelNode model) - { - RunPreDeploymentServices(modelHost, model); - - EnsureModelHandleEvents(); - ProcessModelDeployment(modelHost, model); - - RunPostDeploymentServices(modelHost, model); - } - - private void RunPostDeploymentServices(ModelHostBase modelHost, ModelNode model) - { - var services = PostDeploymentServices.OrderBy(s => s.Order); - - foreach (var service in services) - service.DeployModel(modelHost, model); - } - - private void RunPreDeploymentServices(ModelHostBase modelHost, ModelNode model) - { - var services = PreDeploymentServices.OrderBy(s => s.Order); - - foreach (var service in services) - service.DeployModel(modelHost, model); - } - - public virtual void RetractModel(ModelHostBase modelHost, ModelNode model) - { - EnsureModelHandleEvents(); - - // TMP, just web model is supported yet - // experimental support yet - // https://github.com/SubPointSolutions/spmeta2/issues/70 - - var modelDefinition = model.Value; - - if (modelDefinition is WebDefinition) - RetractWeb(modelHost, model); - - if (modelDefinition is SiteDefinition) - RetractSite(modelHost, model); - } - - #endregion - - #region protected - - protected virtual ModelHandlerBase ResolveModelHandler(Type modelType) - { - ModelHandlerBase result; - - ModelHandlers.TryGetValue(modelType, out result); - - return result; - } - - private void EnsureModelHandleEvents() - { - using (new TraceMethodActivityScope(TraceService, (int)LogEventId.CoreCalls)) - { - foreach (var modelHandler in ModelHandlers.Values - .Where(modelHandler => !_modelHandlerEvents.Contains(modelHandler))) - { - modelHandler.OnModelEvent += (s, e) => - { - if (e.CurrentModelNode != null) - { - e.CurrentModelNode.InvokeOnModelEvents(e.Object, e.EventType); - e.CurrentModelNode.InvokeOnModelContextEvents(s, e); - } - else if (_activeModelNode != null) - { - _activeModelNode.InvokeOnModelEvents(e.Object, e.EventType); - _activeModelNode.InvokeOnModelContextEvents(s, e); - } - }; - - _modelHandlerEvents.Add(modelHandler); - } - } - } - - public static Func OnResolveNullModelHandler; - - protected virtual ModelHandlerBase ResolveModelHandlerForNode(ModelNode modelNode) - { - var modelDefinition = modelNode.Value as DefinitionBase; - var modelHandler = ResolveModelHandler(modelDefinition.GetType()); - - if (modelHandler == null) - { - if (OnResolveNullModelHandler != null) - return OnResolveNullModelHandler(modelNode); - - TraceService.Error((int)LogEventId.ModelProcessingNullModelHandler, string.Format("Model handler instance is NULL. Throwing ArgumentNullException exception.")); - - throw new ArgumentNullException( - string.Format("Can't find model handler for type:[{0}]. Current ModelService type: [{1}].", - modelDefinition.GetType(), - GetType())); - } - - return modelHandler; - } - - - protected virtual void RaiseOnModelNodeProcessing(object sender, ModelProcessingEventArgs args) - { - if (OnModelNodeProcessing != null) - OnModelNodeProcessing(sender, args); - } - - protected virtual void RaiseOnModelNodeProcessed(object sender, ModelProcessingEventArgs args) - { - if (OnModelNodeProcessed != null) - OnModelNodeProcessed(sender, args); - } - private void InitModelTraverseService() - { - ModelTraverseService.OnModelHandlerResolve += ResolveModelHandlerForNode; - - // these are hack due event propagation mis-disign - ModelTraverseService.OnModelProcessing += (node) => - { - RaiseOnModelNodeProcessing(this, new ModelProcessingEventArgs - { - Model = CurrentModelNode, - CurrentNode = node, - ProcessedModelNodeCount = CurrentModelNodeIndex - }); - - _activeModelNode = node; - }; - - ModelTraverseService.OnModelProcessed += (node) => - { - CurrentModelNodeIndex++; - - RaiseOnModelNodeProcessed(this, new ModelProcessingEventArgs - { - Model = CurrentModelNode, - CurrentNode = node, - ProcessedModelNodeCount = CurrentModelNodeIndex - }); - - _activeModelNode = null; - }; - - // on model fully-partially processed events - ModelTraverseService.OnModelFullyProcessing += (node) => - { - - }; - - ModelTraverseService.OnModelFullyProcessed += (node) => - { - - }; - - ModelTraverseService.OnChildModelsProcessing += (node, type, childNodels) => - { - - }; - - ModelTraverseService.OnChildModelsProcessed += (node, type, childNodels) => - { - - }; - } - - private object CurrentModelHost; - private ModelNode CurrentModelNode; - private int CurrentModelNodeIndex; - - private void ProcessModelDeployment(object modelHost, ModelNode modelNode) - { - CurrentModelNodeIndex = 0; - - CurrentModelHost = modelHost; - CurrentModelNode = modelNode; - - using (new TraceActivityScope(TraceService, (int)LogEventId.ModelProcessing, string.Format("ProcessModelDeployment for model:[{0}]", modelNode.Value.GetType()))) - { - ModelTraverseService.Traverse(modelHost, modelNode); - } - } - - private void RetractSite(object modelHost, ModelNode model) - { - // var siteDefinition = model.Value as SiteDefinition; - // var modelHandler = ResolveModelHandler(siteDefinition.GetType()); - } - - private void RetractWeb(object modelHost, ModelNode model) - { - //var webDefinition = model.Value as WebDefinition; - //var modelHandler = ResolveModelHandler(webDefinition.GetType()); - - //if (modelHandler == null && webDefinition.RequireSelfProcessing) - // throw new ArgumentNullException(string.Format("Can't find model handler for type:[{0}] ", webDefinition.GetType())); - - //modelHandler.RetractModel(modelHost, webDefinition); - } - - #endregion - } - - -} + }); + + if (!ModelHandlers.ContainsKey(modelHandlerType.TargetType)) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, + "Model handler for type [{0}] has not been registered yet. Registering.", + new object[] { modelHandlerType.GetType() }); + + ModelHandlers.Add(modelHandlerType.TargetType, modelHandlerType); + } + else + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, + "Model handler for type [{0}] has been registered. Skipping.", + new object[] { modelHandlerType.GetType() }); + } + } + + public Dictionary ModelHandlers { get; set; } + + #endregion + + #region public API + + public virtual void DeployModel(ModelHostBase modelHost, ModelNode model) + { + RunPreDeploymentServices(modelHost, model); + + EnsureModelHandleEvents(); + ProcessModelDeployment(modelHost, model); + + RunPostDeploymentServices(modelHost, model); + } + + private void RunPostDeploymentServices(ModelHostBase modelHost, ModelNode model) + { + var services = PostDeploymentServices.OrderBy(s => s.Order); + + foreach (var service in services) + service.DeployModel(modelHost, model); + } + + private void RunPreDeploymentServices(ModelHostBase modelHost, ModelNode model) + { + var services = PreDeploymentServices.OrderBy(s => s.Order); + + foreach (var service in services) + service.DeployModel(modelHost, model); + } + + public virtual void RetractModel(ModelHostBase modelHost, ModelNode model) + { + EnsureModelHandleEvents(); + + // TMP, just web model is supported yet + // experimental support yet + // https://github.com/SubPointSolutions/spmeta2/issues/70 + + var modelDefinition = model.Value; + + if (modelDefinition is WebDefinition) + RetractWeb(modelHost, model); + + if (modelDefinition is SiteDefinition) + RetractSite(modelHost, model); + } + + #endregion + + #region protected + + protected virtual ModelHandlerBase ResolveModelHandler(Type modelType) + { + ModelHandlerBase result; + + ModelHandlers.TryGetValue(modelType, out result); + + return result; + } + + private void EnsureModelHandleEvents() + { + using (new TraceMethodActivityScope(TraceService, (int)LogEventId.CoreCalls)) + { + foreach (var modelHandler in ModelHandlers.Values + .Where(modelHandler => !_modelHandlerEvents.Contains(modelHandler))) + { + modelHandler.OnModelEvent += (s, e) => + { + if (e.CurrentModelNode != null) + { + e.CurrentModelNode.InvokeOnModelEvents(e.Object, e.EventType); + e.CurrentModelNode.InvokeOnModelContextEvents(s, e); + } + else if (_activeModelNode != null) + { + _activeModelNode.InvokeOnModelEvents(e.Object, e.EventType); + _activeModelNode.InvokeOnModelContextEvents(s, e); + } + }; + + _modelHandlerEvents.Add(modelHandler); + } + } + } + + public static Func OnResolveNullModelHandler; + + protected virtual ModelHandlerBase ResolveModelHandlerForNode(ModelNode modelNode) + { + var modelDefinition = modelNode.Value as DefinitionBase; + var modelHandler = ResolveModelHandler(modelDefinition.GetType()); + + if (modelHandler == null) + { + if (OnResolveNullModelHandler != null) + return OnResolveNullModelHandler(modelNode); + + TraceService.Error((int)LogEventId.ModelProcessingNullModelHandler, string.Format("Model handler instance is NULL. Throwing ArgumentNullException exception.")); + + throw new ArgumentNullException( + string.Format("Can't find model handler for type:[{0}]. Current ModelService type: [{1}].", + modelDefinition.GetType(), + GetType())); + } + + return modelHandler; + } + + + protected virtual void RaiseOnModelNodeProcessing(object sender, ModelProcessingEventArgs args) + { + if (OnModelNodeProcessing != null) + OnModelNodeProcessing(sender, args); + } + + protected virtual void RaiseOnModelNodeProcessed(object sender, ModelProcessingEventArgs args) + { + if (OnModelNodeProcessed != null) + OnModelNodeProcessed(sender, args); + } + private void InitModelTraverseService() + { + _modelTraverseService.OnModelHandlerResolve += ResolveModelHandlerForNode; + + // these are hack due event propagation mis-disign + _modelTraverseService.OnModelProcessing += (node) => + { + RaiseOnModelNodeProcessing(this, new ModelProcessingEventArgs + { + Model = CurrentModelNode, + CurrentNode = node, + ProcessedModelNodeCount = CurrentModelNodeIndex + }); + + _activeModelNode = node; + }; + + _modelTraverseService.OnModelProcessed += (node) => + { + CurrentModelNodeIndex++; + + RaiseOnModelNodeProcessed(this, new ModelProcessingEventArgs + { + Model = CurrentModelNode, + CurrentNode = node, + ProcessedModelNodeCount = CurrentModelNodeIndex + }); + + _activeModelNode = null; + }; + + // on model fully-partially processed events + _modelTraverseService.OnModelFullyProcessing += (node) => + { + + }; + + _modelTraverseService.OnModelFullyProcessed += (node) => + { + + }; + + _modelTraverseService.OnChildModelsProcessing += (node, type, childNodels) => + { + + }; + + _modelTraverseService.OnChildModelsProcessed += (node, type, childNodels) => + { + + }; + } + + private object CurrentModelHost; + private ModelNode CurrentModelNode; + private int CurrentModelNodeIndex; + + private void ProcessModelDeployment(object modelHost, ModelNode modelNode) + { + CurrentModelNodeIndex = 0; + + CurrentModelHost = modelHost; + CurrentModelNode = modelNode; + + using (new TraceActivityScope(TraceService, (int)LogEventId.ModelProcessing, string.Format("ProcessModelDeployment for model:[{0}]", modelNode.Value.GetType()))) + { + ModelTraverseService.Traverse(modelHost, modelNode); + } + } + + private void RetractSite(object modelHost, ModelNode model) + { + // var siteDefinition = model.Value as SiteDefinition; + // var modelHandler = ResolveModelHandler(siteDefinition.GetType()); + } + + private void RetractWeb(object modelHost, ModelNode model) + { + //var webDefinition = model.Value as WebDefinition; + //var modelHandler = ResolveModelHandler(webDefinition.GetType()); + + //if (modelHandler == null && webDefinition.RequireSelfProcessing) + // throw new ArgumentNullException(string.Format("Can't find model handler for type:[{0}] ", webDefinition.GetType())); + + //modelHandler.RetractModel(modelHost, webDefinition); + } + + #endregion + } + + +} diff --git a/SPMeta2/SPMeta2/Services/ProvisionServiceBase.cs b/SPMeta2/SPMeta2/Services/ProvisionServiceBase.cs index f10ac20af..de978a2aa 100644 --- a/SPMeta2/SPMeta2/Services/ProvisionServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/ProvisionServiceBase.cs @@ -1,61 +1,62 @@ -using SPMeta2.Services.Impl; -using SPMeta2.Services.Impl.Validation; -using SPMeta2.Utils; -using System; -using System.Linq; -using System.Reflection; -using SPMeta2.Definitions; - -namespace SPMeta2.Services -{ - public class ProvisionServiceBase : ModelServiceBase - { - #region constructors - - public ProvisionServiceBase() - { - InitDefaultPreDeploymentServices(); - InitDefaultPostDeploymentServices(); - } - - protected void InitDefaultPostDeploymentServices() - { - InitDefaultPostDeploymentServices(typeof(FieldDefinition).Assembly); - } - - protected void InitDefaultPostDeploymentServices(Assembly assembly) - { - // TODO - } - - protected void InitDefaultPreDeploymentServices() - { - InitDefaultPreDeploymentServices(typeof(FieldDefinition).Assembly); - } - - protected void InitDefaultPreDeploymentServices(Assembly assembly) - { - // adding default required prop validation on definitions - // https://github.com/SubPointSolutions/spmeta2/issues/422 - - var validationServiceTypes = ReflectionUtils.GetTypesFromAssembly(assembly); - - foreach (var validationServiceType in validationServiceTypes) - { - var exists = PreDeploymentServices.Any(s => s.GetType() == validationServiceType); - - if (!exists) - { - var service = Activator.CreateInstance(validationServiceType) as PreDeploymentValidationServiceBase; - - if (service != null) - { - PreDeploymentServices.Add(service); - } - } - } - } - - #endregion - } -} +using SPMeta2.Services.Impl; +using SPMeta2.Services.Impl.Validation; +using SPMeta2.Utils; +using System; +using System.Linq; +using System.Reflection; +using SPMeta2.Definitions; +using SPMeta2.Interfaces; + +namespace SPMeta2.Services +{ + public class ProvisionServiceBase : ModelServiceBase, IProvisionService + { + #region constructors + + public ProvisionServiceBase() + { + InitDefaultPreDeploymentServices(); + InitDefaultPostDeploymentServices(); + } + + protected void InitDefaultPostDeploymentServices() + { + InitDefaultPostDeploymentServices(typeof(FieldDefinition).Assembly); + } + + protected void InitDefaultPostDeploymentServices(Assembly assembly) + { + // TODO + } + + protected void InitDefaultPreDeploymentServices() + { + InitDefaultPreDeploymentServices(typeof(FieldDefinition).Assembly); + } + + protected void InitDefaultPreDeploymentServices(Assembly assembly) + { + // adding default required prop validation on definitions + // https://github.com/SubPointSolutions/spmeta2/issues/422 + + var validationServiceTypes = ReflectionUtils.GetTypesFromAssembly(assembly); + + foreach (var validationServiceType in validationServiceTypes) + { + var exists = PreDeploymentServices.Any(s => s.GetType() == validationServiceType); + + if (!exists) + { + var service = Activator.CreateInstance(validationServiceType) as PreDeploymentValidationServiceBase; + + if (service != null) + { + PreDeploymentServices.Add(service); + } + } + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Services/ProvisionServiceBaseExtensions.cs b/SPMeta2/SPMeta2/Services/ProvisionServiceBaseExtensions.cs new file mode 100644 index 000000000..c44be3732 --- /dev/null +++ b/SPMeta2/SPMeta2/Services/ProvisionServiceBaseExtensions.cs @@ -0,0 +1,69 @@ +using SPMeta2.Services.Impl; +using SPMeta2.Services.Impl.Validation; +using SPMeta2.Utils; +using System; +using System.Linq; +using System.Reflection; +using SPMeta2.Definitions; +using SPMeta2.Common; +using SPMeta2.Exceptions; + +namespace SPMeta2.Services +{ + public static class ProvisionServiceBaseExtensions + { + #region incremental provision + + public static ProvisionServiceBase SetIncrementalMode(this ProvisionServiceBase service) + { + return SetIncrementalMode(service, null); + } + + public static ProvisionServiceBase SetIncrementalMode(this ProvisionServiceBase service, IncrementalProvisionConfig config) + { + if (config == null) + config = IncrementalProvisionConfig.Default; + + if (config.CustomModelTreeTraverseServiceType != null) + service.CustomModelTreeTraverseServiceType = config.CustomModelTreeTraverseServiceType; + else + service.CustomModelTreeTraverseServiceType = typeof(DefaultIncrementalModelTreeTraverseService); + + var typedModelService = service.ModelTraverseService as DefaultIncrementalModelTreeTraverseService; + typedModelService.PreviousModelHash = config.PreviousModelHash ?? new ModelHash(); + + return service; + } + + public static ProvisionServiceBase SetIncrementalModelHash(this ProvisionServiceBase service, ModelHash modelHash) + { + var typedModelService = GetIncrementalModelTraverseService(service); + typedModelService.PreviousModelHash = modelHash; + + return service; + } + + public static ModelHash GetIncrementalModelHash(this ProvisionServiceBase service) + { + var typedModelService = GetIncrementalModelTraverseService(service); + return typedModelService.CurrentModelHash; + } + + #endregion + + #region utils + + private static DefaultIncrementalModelTreeTraverseService GetIncrementalModelTraverseService(this ProvisionServiceBase service) + { + if (!(service.ModelTraverseService is DefaultIncrementalModelTreeTraverseService)) + throw new SPMeta2Exception( + string.Format("provision server isn't set in incremenatl mode. Call .SetIncrementalMode() before calling the current method")); + + var typedModelService = service.ModelTraverseService as DefaultIncrementalModelTreeTraverseService; + + return typedModelService; + } + + #endregion + } +} \ No newline at end of file From 296e347f9f3508f657d3dde604cd3d8f220007fd Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 2 Mar 2017 07:53:13 -0800 Subject: [PATCH 09/53] -> moved NuGet packaging to 1.2.120-beta1 --- SPMeta2/Build/build.json | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index a309399c8..97bc73b71 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.110" + "Version": "1.2.120-beta1" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.110", + "Version": "1.2.120-beta1", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.110" + "Version": "1.2.120-beta1" }, { "Id": "Microsoft.SharePointOnline.CSOM", From ba06bd37cf864574f2ede18c6445aefc7d08dc27 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Thu, 2 Mar 2017 22:56:08 +0000 Subject: [PATCH 10/53] + Implement 'incremental' provision support #553 + Implement fluent API totoggle provision services mode - from defalt to incremental --- ...StandardCSOMincrementalProvisionService.cs | 2 +- .../CSOMIncrementalProvisionService.cs | 2 +- .../Impl/Services/ProvisionServiceTests.cs | 4 +- .../DefaultModelTreeTraverseServiceTests.cs | 338 +--------------- ...ncrementalModelTreeTraverseServiceTests.cs | 378 +++++++++++++++++- .../SPMeta2.Regression.Tests.csproj | 4 +- ...StandardSSOMIncrementalProvisionService.cs | 2 +- .../SSOMIncrementalProvisionService.cs | 2 +- SPMeta2/SPMeta2/SPMeta2.csproj | 2 +- ...rementalProvisionServiceBaseExtensions.cs} | 31 +- SPMeta2/SPMeta2/Services/ModelServiceBase.cs | 2 +- 11 files changed, 417 insertions(+), 350 deletions(-) rename SPMeta2/SPMeta2/Services/{ProvisionServiceBaseExtensions.cs => IncrementalProvisionServiceBaseExtensions.cs} (62%) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs b/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs index b6dd91e17..9ca6bd028 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/Services/StandardCSOMincrementalProvisionService.cs @@ -18,7 +18,7 @@ public class StandardCSOMIncrementalProvisionService : StandardCSOMProvisionServ public StandardCSOMIncrementalProvisionService() { - this.SetIncrementalMode(); + this.SetIncrementalProvisionMode(); } #endregion diff --git a/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs b/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs index 798ec5f2d..b174e66c8 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/CSOMIncrementalProvisionService.cs @@ -24,7 +24,7 @@ public class CSOMIncrementalProvisionService : CSOMProvisionService, IIncrementa public CSOMIncrementalProvisionService() { - this.SetIncrementalMode(); + this.SetIncrementalProvisionMode(); } #endregion diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index ca8750bcd..7ebda6837 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -183,9 +183,9 @@ public void Can_Create_IncrementaProvisionServices_With_FluentAPI() foreach (var service in services) { - var incrementalService = service.SetIncrementalMode(); + var incrementalService = service.SetIncrementalProvisionMode(); - var currentModelHash = incrementalService.GetIncrementalModelHash(); + var currentModelHash = incrementalService.GetIncrementalProvisionModelHash(); Assert.IsNotNull(currentModelHash); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs index 3101f74f9..ec46171a6 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultModelTreeTraverseServiceTests.cs @@ -1,343 +1,23 @@ -using System; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Common; -using SPMeta2.Containers; +using Microsoft.VisualStudio.TestTools.UnitTesting; using SPMeta2.Definitions; -using SPMeta2.Models; -using SPMeta2.Regression.ModelHandlers; using SPMeta2.Services; using SPMeta2.Services.Impl; -using SPMeta2.Syntax.Default; -using System.Collections.Generic; -using SPMeta2.Extensions; -using SPMeta2.Regression.Utils; -using SPMeta2.Containers.Services.Rnd; -using SPMeta2.Containers.Services; -using SPMeta2.Containers.Standard.DefinitionGenerators; -using SPMeta2.Attributes; -using SPMeta2.Standard.Definitions.Fields; -using SPMeta2.Utils; namespace SPMeta2.Regression.Tests.Impl.Services { - public class IncrementalModelPrettyPrintService : DefaultModelPrettyPrintService - { - protected override string GetDefinitionValue(ModelNode modelNode) - { - var shouldDeploy = modelNode.Options.RequireSelfProcessing; - - if (shouldDeploy) - { - return string.Format("[+] {0}", base.GetDefinitionValue(modelNode)); - } - else - { - return string.Format("[-] {0}", base.GetDefinitionValue(modelNode)); - } - } - } - [TestClass] - public class IncrementalModelTreeTraverseServiceTests - { - #region constructors - - public IncrementalModelTreeTraverseServiceTests() - { - ModelPrintService = new IncrementalModelPrettyPrintService(); - - Rnd = new DefaultRandomService(); - - ModelGeneratorService = new ModelGeneratorService(); - ModelGeneratorService.RegisterDefinitionGenerators(typeof(ImageRenditionDefinitionGenerator).Assembly); - } - - #endregion - - #region properties - - public ModelPrintServiceBase ModelPrintService { get; set; } - - public ModelGeneratorService ModelGeneratorService { get; set; } - - public DefaultRandomService Rnd { get; set; } - - #endregion - - #region default - - [TestMethod] - [TestCategory("Regression.Services.IncrementalModelTreeTraverseService")] - [TestCategory("CI.Core")] - public void Can_Create_IncrementalModelTreeTraverseService() - { - var service = new DefaultIncrementalModelTreeTraverseService(); - - } - - - - #endregion - - - - #region non-singlentons - - [TestMethod] - [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] - [TestCategory("CI.Core")] - public void Incremental_Update_NonSingleton_ModelNodes_SameModels() - { - var model = SPMeta2Model.NewSiteModel(site => - { - site.AddRandomField(); - site.AddRandomField(); - site.AddRandomField(); - }); - - var prevModel = model; - var currentModel = model; - - var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); - - firstProvisionService.PreviousModelHash = new ModelHash(); - firstProvisionService.Traverse(null, currentModel); - - var trace = ServiceContainer.Instance.GetService(); - - // check one more with second provision - var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); - - RegressionUtils.WriteLine("Original model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); - - secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; - secondProvisionService.Traverse(null, currentModel); - - RegressionUtils.WriteLine(string.Empty); - RegressionUtils.WriteLine("Provisioned model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); - - // asserts - // should be NONE of the nodes to update on the same model - Assert.AreEqual(0, secondProvisionService.ModelNodesToUpdate.Count); - Assert.AreEqual(GetTotalModelNodeCount(model), secondProvisionService.ModelNodesToSkip.Count); - } - - [TestMethod] - [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.Random")] - [TestCategory("CI.Core")] - public void Incremental_Update_AllDefinitions_As_RandomModels() - { - var spMetaAssembly = typeof(FieldDefinition).Assembly; - var spMetaStandardAssembly = typeof(TaxonomyFieldDefinition).Assembly; - - var allDefinitionTypes = ReflectionUtils.GetTypesFromAssemblies(new[] - { - spMetaAssembly, - spMetaStandardAssembly - }).OrderBy(t => t.Name); - - var allDefinitionTypesCount = allDefinitionTypes.Count(); - var currentDefinitionTypeIndex = 0; - - foreach (var definitionType in allDefinitionTypes) - { - currentDefinitionTypeIndex++; - RegressionUtils.WriteLine(string.Format("[{0}/{1}] Testing definition:[{2}]", - new object[] { - currentDefinitionTypeIndex, - allDefinitionTypesCount, - definitionType.FullName - })); - - var model = GetVeryRandomModel(definitionType, SPObjectModelType.CSOM); - - var prevModel = model; - var currentModel = model; - - var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); - - firstProvisionService.PreviousModelHash = new ModelHash(); - firstProvisionService.Traverse(null, currentModel); - - var trace = ServiceContainer.Instance.GetService(); - - // check one more with second provision - var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); - - RegressionUtils.WriteLine("Original model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); - - secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; - secondProvisionService.Traverse(null, currentModel); - - RegressionUtils.WriteLine(string.Empty); - RegressionUtils.WriteLine("Provisioned model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); - - // asserts - var expectedProvisionNodesCount = 0; - - expectedProvisionNodesCount += secondProvisionService.GetTotalSingleIdentityNodeCount(); - expectedProvisionNodesCount += secondProvisionService.GetTotalIgnoredNodeCount(); - - Assert.AreEqual(expectedProvisionNodesCount, secondProvisionService.ModelNodesToUpdate.Count); - Assert.AreEqual(GetTotalModelNodeCount(model) - expectedProvisionNodesCount, secondProvisionService.ModelNodesToSkip.Count); - } - } - - [TestMethod] - [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] - [TestCategory("CI.Core")] - public void Incremental_Update_NonSingleton_ModelNodes_PlusRandomModelNodes() - { - var model = SPMeta2Model.NewSiteModel(site => - { - site.AddRandomField(); - site.AddRandomField(); - site.AddRandomField(); - }); - - var prevModel = model; - var currentModel = model; - - var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); - - firstProvisionService.PreviousModelHash = new ModelHash(); - firstProvisionService.Traverse(null, currentModel); - - RegressionUtils.WriteLine("Original model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); - - var trace = ServiceContainer.Instance.GetService(); - - ModelNode newField1 = null; - ModelNode newField2 = null; - - // newnodes to add - model.AddRandomField(f => { newField1 = f; }); - model.AddRandomField(f => { newField2 = f; }); - - - - // check one more with second provision - var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); - - secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; - secondProvisionService.Traverse(null, currentModel); - - RegressionUtils.WriteLine(string.Empty); - RegressionUtils.WriteLine("Provisioned model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); - - // asserts - // should be 2 of the nodes to update on the same model - Assert.AreEqual(2, secondProvisionService.ModelNodesToUpdate.Count); - Assert.AreEqual(GetTotalModelNodeCount(model), - secondProvisionService.ModelNodesToSkip.Count + secondProvisionService.ModelNodesToUpdate.Count); - - // new field must be marked as to be updated - Assert.IsTrue(newField1.Options.RequireSelfProcessing); - Assert.IsTrue(newField2.Options.RequireSelfProcessing); - } - - #endregion - - #region utils - - protected ModelNode GetVeryRandomModel(Type definitionType, SPObjectModelType spObjectModelType) - { - var definitionSandbox = ModelGeneratorService.GenerateModelTreeForDefinition(definitionType, spObjectModelType); - var additionalDefinitions = ModelGeneratorService.GetAdditionalDefinitions(definitionType); - - ModelGeneratorService.ComposeModelWithAdditionalDefinitions(definitionSandbox, additionalDefinitions, spObjectModelType); - - // more random definitions - var messyDefinitions = new List(); - - var flatNodes = definitionSandbox.Flatten().ToArray(); - - foreach (var node in flatNodes) - { - if (node.ChildModels.Count == 0) - continue; - - var defType = node.ChildModels[0].Value.GetType(); - var randomFactor = Rnd.Int(5) + 3; - - for (var i = 0; i < randomFactor; i++) - { - node.AddDefinitionNode(ModelGeneratorService.GetRandomDefinition(defType)); - } - } - - return definitionSandbox; - } - - protected int GetTotalModelNodeCount(ModelNode model) - { - if (model == null) - return 0; - - var result = 0; - - model.WithNodesOfType(n => { result++; }); - - return result; - } - - #endregion - } - - public class FakeIncrementalModelTreeTraverseService : DefaultIncrementalModelTreeTraverseService + public class DefaultModelTreeTraverseServiceTests { - #region constructors - public FakeIncrementalModelTreeTraverseService() - { - this.OnModelHandlerResolve += (node => - { - return new EmptyModelhandler(); - }); - - ModelNodesToUpdate = new List(); - ModelNodesToSkip = new List(); - } - #endregion + #region tests - #region properties + //[TestMethod] + //[TestCategory("Regression.Services.DefaultModelTreeTraverseService")] + //[TestCategory("CI.Core")] + //public void ServiceContainer_Should_Have_DefaultServices() + //{ - public List ModelNodesToUpdate { get; set; } - public List ModelNodesToSkip { get; set; } + //} #endregion - - protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNode) - { - // process deployment need - base.OnBeforeDeployModel(modelHost, modelNode); - - if (modelNode.Options.RequireSelfProcessing) - ModelNodesToUpdate.Add(modelNode); - else - ModelNodesToSkip.Add(modelNode); - } - - public int GetTotalSingleIdentityNodeCount() - { - // && RequireSelfProcessing cause root defs such as FarmDefinition must be excluded - // getting only singletons from the actual model, not the root nodes - var result = - ModelNodesToUpdate.Count(n => IsSingletonIdentityDefinition(n.Value) && n.Options.RequireSelfProcessing) - + ModelNodesToSkip.Count(n => IsSingletonIdentityDefinition(n.Value) && n.Options.RequireSelfProcessing); - - return result; - } - - public int GetTotalIgnoredNodeCount() - { - return IgnoredModelNodes.Count(); - } } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs index 4354721ac..b150113b4 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs @@ -1,23 +1,391 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Common; +using SPMeta2.Containers; using SPMeta2.Definitions; +using SPMeta2.Models; +using SPMeta2.Regression.ModelHandlers; using SPMeta2.Services; using SPMeta2.Services.Impl; +using SPMeta2.Syntax.Default; +using System.Collections.Generic; +using SPMeta2.Extensions; +using SPMeta2.Regression.Utils; +using SPMeta2.Containers.Services.Rnd; +using SPMeta2.Containers.Services; +using SPMeta2.Containers.Standard.DefinitionGenerators; +using SPMeta2.Attributes; +using SPMeta2.Standard.Definitions.Fields; +using SPMeta2.Utils; namespace SPMeta2.Regression.Tests.Impl.Services { + public class IncrementalModelPrettyPrintService : DefaultModelPrettyPrintService + { + protected override string GetDefinitionValue(ModelNode modelNode) + { + var shouldDeploy = modelNode.Options.RequireSelfProcessing; + + if (shouldDeploy) + { + return string.Format("[+] {0}", base.GetDefinitionValue(modelNode)); + } + else + { + return string.Format("[-] {0}", base.GetDefinitionValue(modelNode)); + } + } + } + [TestClass] - public class DefaultModelTreeTraverseServiceTests + public class IncrementalModelTreeTraverseServiceTests { - #region tests + #region constructors + + public IncrementalModelTreeTraverseServiceTests() + { + ModelPrintService = new IncrementalModelPrettyPrintService(); + + Rnd = new DefaultRandomService(); + + ModelGeneratorService = new ModelGeneratorService(); + ModelGeneratorService.RegisterDefinitionGenerators(typeof(ImageRenditionDefinitionGenerator).Assembly); + } + + #endregion + + #region properties + + public ModelPrintServiceBase ModelPrintService { get; set; } + + public ModelGeneratorService ModelGeneratorService { get; set; } + + public DefaultRandomService Rnd { get; set; } + + #endregion + + #region default + + [TestMethod] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService")] + [TestCategory("CI.Core")] + public void Can_Create_IncrementalModelTreeTraverseService() + { + var service = new DefaultIncrementalModelTreeTraverseService(); + + } + + + + #endregion + + #region switching the mode + + [TestMethod] + [TestCategory("Regression.Services.ProvisionServiceBase")] + [TestCategory("CI.Core")] + public void Can_Toggle_Incremental_ProvisionServiceMode() + { + var service = new ProvisionServiceBase(); + + // normal mode + Assert.AreEqual(typeof(DefaultModelTreeTraverseService), service.ModelTraverseService.GetType()); + + // incremental provision + service.SetIncrementalProvisionMode(); + Assert.AreEqual(typeof(DefaultIncrementalModelTreeTraverseService), service.ModelTraverseService.GetType()); + + // switching back to normal + service.SetDefaultProvisionMode(); + Assert.AreEqual(typeof(DefaultModelTreeTraverseService), service.ModelTraverseService.GetType()); + + // incremental provision + service.SetIncrementalProvisionMode(); + Assert.AreEqual(typeof(DefaultIncrementalModelTreeTraverseService), service.ModelTraverseService.GetType()); + + // switching back to normal + service.SetDefaultProvisionMode(); + Assert.AreEqual(typeof(DefaultModelTreeTraverseService), service.ModelTraverseService.GetType()); + } + + [TestMethod] + [TestCategory("Regression.Services.ProvisionServiceBase")] + [TestCategory("CI.Core")] + public void Can_Reset_ProvisionServiceMode() + { + var service = new ProvisionServiceBase(); + + // normal mode + Assert.AreEqual(typeof(DefaultModelTreeTraverseService), service.ModelTraverseService.GetType()); + + // incremental provision + service.SetIncrementalProvisionMode(); + Assert.AreEqual(typeof(DefaultIncrementalModelTreeTraverseService), service.ModelTraverseService.GetType()); + + // switching back to normal + service.ResetProvisionMode(); + Assert.AreEqual(typeof(DefaultModelTreeTraverseService), service.ModelTraverseService.GetType()); + } + + #endregion + + #region non-singlentons + + [TestMethod] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] + [TestCategory("CI.Core")] + public void Incremental_Update_NonSingleton_ModelNodes_SameModels() + { + var model = SPMeta2Model.NewSiteModel(site => + { + site.AddRandomField(); + site.AddRandomField(); + site.AddRandomField(); + }); + + var prevModel = model; + var currentModel = model; + + var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); + + firstProvisionService.PreviousModelHash = new ModelHash(); + firstProvisionService.Traverse(null, currentModel); + + var trace = ServiceContainer.Instance.GetService(); + + // check one more with second provision + var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); + + RegressionUtils.WriteLine("Original model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + + secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; + secondProvisionService.Traverse(null, currentModel); + + RegressionUtils.WriteLine(string.Empty); + RegressionUtils.WriteLine("Provisioned model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + + // asserts + // should be NONE of the nodes to update on the same model + Assert.AreEqual(0, secondProvisionService.ModelNodesToUpdate.Count); + Assert.AreEqual(GetTotalModelNodeCount(model), secondProvisionService.ModelNodesToSkip.Count); + } + + [TestMethod] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.Random")] + [TestCategory("CI.Core")] + public void Incremental_Update_AllDefinitions_As_RandomModels() + { + var spMetaAssembly = typeof(FieldDefinition).Assembly; + var spMetaStandardAssembly = typeof(TaxonomyFieldDefinition).Assembly; + + var allDefinitionTypes = ReflectionUtils.GetTypesFromAssemblies(new[] + { + spMetaAssembly, + spMetaStandardAssembly + }).OrderBy(t => t.Name); + + var allDefinitionTypesCount = allDefinitionTypes.Count(); + var currentDefinitionTypeIndex = 0; + + foreach (var definitionType in allDefinitionTypes) + { + currentDefinitionTypeIndex++; + RegressionUtils.WriteLine(string.Format("[{0}/{1}] Testing definition:[{2}]", + new object[] { + currentDefinitionTypeIndex, + allDefinitionTypesCount, + definitionType.FullName + })); + + var model = GetVeryRandomModel(definitionType, SPObjectModelType.CSOM); + + var prevModel = model; + var currentModel = model; + + var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); + + firstProvisionService.PreviousModelHash = new ModelHash(); + firstProvisionService.Traverse(null, currentModel); + + var trace = ServiceContainer.Instance.GetService(); + + // check one more with second provision + var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); + + RegressionUtils.WriteLine("Original model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + + secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; + secondProvisionService.Traverse(null, currentModel); + + RegressionUtils.WriteLine(string.Empty); + RegressionUtils.WriteLine("Provisioned model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + + // asserts + var expectedProvisionNodesCount = 0; + + expectedProvisionNodesCount += secondProvisionService.GetTotalSingleIdentityNodeCount(); + expectedProvisionNodesCount += secondProvisionService.GetTotalIgnoredNodeCount(); + + Assert.AreEqual(expectedProvisionNodesCount, secondProvisionService.ModelNodesToUpdate.Count); + Assert.AreEqual(GetTotalModelNodeCount(model) - expectedProvisionNodesCount, secondProvisionService.ModelNodesToSkip.Count); + } + } [TestMethod] - [TestCategory("Regression.Services.DefaultModelTreeTraverseService")] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] [TestCategory("CI.Core")] - public void ServiceContainer_Should_Have_DefaultServices() + public void Incremental_Update_NonSingleton_ModelNodes_PlusRandomModelNodes() + { + var model = SPMeta2Model.NewSiteModel(site => + { + site.AddRandomField(); + site.AddRandomField(); + site.AddRandomField(); + }); + + var prevModel = model; + var currentModel = model; + + var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); + + firstProvisionService.PreviousModelHash = new ModelHash(); + firstProvisionService.Traverse(null, currentModel); + + RegressionUtils.WriteLine("Original model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + + var trace = ServiceContainer.Instance.GetService(); + + ModelNode newField1 = null; + ModelNode newField2 = null; + + // newnodes to add + model.AddRandomField(f => { newField1 = f; }); + model.AddRandomField(f => { newField2 = f; }); + + + + // check one more with second provision + var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); + + secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; + secondProvisionService.Traverse(null, currentModel); + + RegressionUtils.WriteLine(string.Empty); + RegressionUtils.WriteLine("Provisioned model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + + // asserts + // should be 2 of the nodes to update on the same model + Assert.AreEqual(2, secondProvisionService.ModelNodesToUpdate.Count); + Assert.AreEqual(GetTotalModelNodeCount(model), + secondProvisionService.ModelNodesToSkip.Count + secondProvisionService.ModelNodesToUpdate.Count); + + // new field must be marked as to be updated + Assert.IsTrue(newField1.Options.RequireSelfProcessing); + Assert.IsTrue(newField2.Options.RequireSelfProcessing); + } + + #endregion + + #region utils + + protected ModelNode GetVeryRandomModel(Type definitionType, SPObjectModelType spObjectModelType) + { + var definitionSandbox = ModelGeneratorService.GenerateModelTreeForDefinition(definitionType, spObjectModelType); + var additionalDefinitions = ModelGeneratorService.GetAdditionalDefinitions(definitionType); + + ModelGeneratorService.ComposeModelWithAdditionalDefinitions(definitionSandbox, additionalDefinitions, spObjectModelType); + + // more random definitions + var messyDefinitions = new List(); + + var flatNodes = definitionSandbox.Flatten().ToArray(); + + foreach (var node in flatNodes) + { + if (node.ChildModels.Count == 0) + continue; + + var defType = node.ChildModels[0].Value.GetType(); + var randomFactor = Rnd.Int(5) + 3; + + for (var i = 0; i < randomFactor; i++) + { + node.AddDefinitionNode(ModelGeneratorService.GetRandomDefinition(defType)); + } + } + + return definitionSandbox; + } + + protected int GetTotalModelNodeCount(ModelNode model) { + if (model == null) + return 0; + + var result = 0; + model.WithNodesOfType(n => { result++; }); + + return result; } #endregion } + + public class FakeIncrementalModelTreeTraverseService : DefaultIncrementalModelTreeTraverseService + { + #region constructors + public FakeIncrementalModelTreeTraverseService() + { + this.OnModelHandlerResolve += (node => + { + return new EmptyModelhandler(); + }); + + ModelNodesToUpdate = new List(); + ModelNodesToSkip = new List(); + } + #endregion + + #region properties + + public List ModelNodesToUpdate { get; set; } + public List ModelNodesToSkip { get; set; } + + #endregion + + protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNode) + { + // process deployment need + base.OnBeforeDeployModel(modelHost, modelNode); + + if (modelNode.Options.RequireSelfProcessing) + ModelNodesToUpdate.Add(modelNode); + else + ModelNodesToSkip.Add(modelNode); + } + + public int GetTotalSingleIdentityNodeCount() + { + // && RequireSelfProcessing cause root defs such as FarmDefinition must be excluded + // getting only singletons from the actual model, not the root nodes + var result = + ModelNodesToUpdate.Count(n => IsSingletonIdentityDefinition(n.Value) && n.Options.RequireSelfProcessing) + + ModelNodesToSkip.Count(n => IsSingletonIdentityDefinition(n.Value) && n.Options.RequireSelfProcessing); + + return result; + } + + public int GetTotalIgnoredNodeCount() + { + return IgnoredModelNodes.Count(); + } + } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index e25890a23..49c9ea6d1 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -244,7 +244,7 @@ - + @@ -255,7 +255,7 @@ - + diff --git a/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs b/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs index 9c2fb006f..87082da81 100644 --- a/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs +++ b/SPMeta2/SPMeta2.SSOM.Standard/Services/StandardSSOMIncrementalProvisionService.cs @@ -23,7 +23,7 @@ public class StandardSSOMIncrementalProvisionService : SSOMProvisionService, IIn public StandardSSOMIncrementalProvisionService() { - this.SetIncrementalMode(); + this.SetIncrementalProvisionMode(); } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs b/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs index 6ce2e1b60..b6a74cd63 100644 --- a/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs +++ b/SPMeta2/SPMeta2.SSOM/Services/SSOMIncrementalProvisionService.cs @@ -21,7 +21,7 @@ public class SSOMIncrementalProvisionService : SSOMProvisionService, IIncrementa public SSOMIncrementalProvisionService() { - this.SetIncrementalMode(); + this.SetIncrementalProvisionMode(); } #endregion diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index a25594938..0ffe641e4 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -402,7 +402,7 @@ - + diff --git a/SPMeta2/SPMeta2/Services/ProvisionServiceBaseExtensions.cs b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs similarity index 62% rename from SPMeta2/SPMeta2/Services/ProvisionServiceBaseExtensions.cs rename to SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs index c44be3732..72d9789ba 100644 --- a/SPMeta2/SPMeta2/Services/ProvisionServiceBaseExtensions.cs +++ b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs @@ -10,17 +10,36 @@ namespace SPMeta2.Services { - public static class ProvisionServiceBaseExtensions + public static class IncrementalProvisionServiceBaseExtensions { + #region default provision + + public static ProvisionServiceBase ResetProvisionMode(this ProvisionServiceBase service) + { + return SetDefaultProvisionMode(service); + } + + public static ProvisionServiceBase SetDefaultProvisionMode(this ProvisionServiceBase service) + { + service.CustomModelTreeTraverseServiceType = null; + service.ModelTraverseService = null; + + return service; + } + + #endregion + #region incremental provision - public static ProvisionServiceBase SetIncrementalMode(this ProvisionServiceBase service) + public static ProvisionServiceBase SetIncrementalProvisionMode(this ProvisionServiceBase service) { - return SetIncrementalMode(service, null); + return SetIncrementalProvisionMode(service, null); } - public static ProvisionServiceBase SetIncrementalMode(this ProvisionServiceBase service, IncrementalProvisionConfig config) + public static ProvisionServiceBase SetIncrementalProvisionMode(this ProvisionServiceBase service, IncrementalProvisionConfig config) { + service.ModelTraverseService = null; + if (config == null) config = IncrementalProvisionConfig.Default; @@ -35,7 +54,7 @@ public static ProvisionServiceBase SetIncrementalMode(this ProvisionServiceBase return service; } - public static ProvisionServiceBase SetIncrementalModelHash(this ProvisionServiceBase service, ModelHash modelHash) + public static ProvisionServiceBase SetIncrementalProvisionModelHash(this ProvisionServiceBase service, ModelHash modelHash) { var typedModelService = GetIncrementalModelTraverseService(service); typedModelService.PreviousModelHash = modelHash; @@ -43,7 +62,7 @@ public static ProvisionServiceBase SetIncrementalModelHash(this ProvisionService return service; } - public static ModelHash GetIncrementalModelHash(this ProvisionServiceBase service) + public static ModelHash GetIncrementalProvisionModelHash(this ProvisionServiceBase service) { var typedModelService = GetIncrementalModelTraverseService(service); return typedModelService.CurrentModelHash; diff --git a/SPMeta2/SPMeta2/Services/ModelServiceBase.cs b/SPMeta2/SPMeta2/Services/ModelServiceBase.cs index 0945fcbce..047f6cef7 100644 --- a/SPMeta2/SPMeta2/Services/ModelServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/ModelServiceBase.cs @@ -150,7 +150,7 @@ public ModelTreeTraverseServiceBase ModelTraverseService return _modelTraverseService; } - set { } + set { _modelTraverseService = value; } } public List PreDeploymentServices { get; set; } From db24c9f94ecc668039864093896b7fadb5cd4c15 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 01:21:46 +0000 Subject: [PATCH 11/53] + DefaultModelPrettyPrintService calculates wrong indent string #973 + Implement 'incremental' provision support #553 + Regression tests: all definitions + double deployment and random updates --- .../O365ProvisionRunner.cs | 667 +++++++++--------- .../Consts/EnvironmentConsts.cs | 81 ++- .../Services/ProvisionRunnerBase.cs | 172 ++--- .../Services/RegressionTestService.cs | 16 +- .../Base/SPMeta2RegresionTestBase.cs | 18 + .../Base/SPMeta2RegresionScenarioTestBase.cs | 102 ++- .../Impl/Scenarios/TaxonomyScenariousTest.cs | 495 +++++++------ .../Impl/Scenarios/WebScenariosTest.cs | 49 +- ...ncrementalModelTreeTraverseServiceTests.cs | 19 +- SPMeta2/SPMeta2/SPMeta2.csproj | 1 + ...faultIncrementalModelPrettyPrintService.cs | 25 + ...aultIncrementalModelTreeTraverseService.cs | 14 +- .../Impl/DefaultModelPrettyPrintService.cs | 11 +- 13 files changed, 901 insertions(+), 769 deletions(-) create mode 100644 SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs diff --git a/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs index 92a1c2ef1..2f2e6a5d2 100644 --- a/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs @@ -1,332 +1,359 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Security; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Publishing.Navigation; -using Microsoft.SharePoint.Client.Search.Portability; -using Microsoft.SharePoint.Client.Taxonomy; -using Microsoft.SharePoint.Client.WorkflowServices; -using SPMeta2.Containers.Consts; -using SPMeta2.Containers.Exceptions; -using SPMeta2.Containers.Services; -using SPMeta2.Containers.Utils; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.CSOM.Services; -using SPMeta2.CSOM.Standard.ModelHandlers.Fields; -using SPMeta2.ModelHandlers; -using SPMeta2.Models; -using SPMeta2.Regression.CSOM; -using SPMeta2.Regression.CSOM.Standard.Validation.Fields; -using SPMeta2.Utils; -using SPMeta2.CSOM.Standard.Services; - -namespace SPMeta2.Containers.O365 -{ - /// - /// O365 container runner implementation. - /// - public class O365ProvisionRunner : ProvisionRunnerBase - { - #region constructors - - public O365ProvisionRunner() - { - Name = "O365"; - - SiteUrls = new List(); - WebUrls = new List(); - - LoadEnvironmentConfig(); - InitServices(); - - UserName = RunnerEnvironmentUtils.GetEnvironmentVariable(EnvironmentConsts.O365_UserName); - UserPassword = RunnerEnvironmentUtils.GetEnvironmentVariable(EnvironmentConsts.O365_Password); - } - - private void InitServices() - { - _provisionService = new StandardCSOMProvisionService(); - _validationService = new CSOMValidationService(); - - var csomStandartAsm = typeof(TaxonomyFieldModelHandler).Assembly; - - foreach (var handlerType in ReflectionUtils.GetTypesFromAssembly(csomStandartAsm)) - _provisionService.RegisterModelHandler(Activator.CreateInstance(handlerType) as ModelHandlerBase); - - var csomtandartValidationAsm = typeof(ClientTaxonomyFieldDefinitionValidator).Assembly; - - foreach (var handlerType in ReflectionUtils.GetTypesFromAssembly(csomtandartValidationAsm)) - _validationService.RegisterModelHandler(Activator.CreateInstance(handlerType) as ModelHandlerBase); - - _provisionService.OnModelNodeProcessing += (sender, args) => - { - ContainerTraceUtils.WriteLine( - string.Format("Processing: [{0}/{1}] - [{2:0} %] - [{3}] [{4}]", +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Security; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Publishing.Navigation; +using Microsoft.SharePoint.Client.Search.Portability; +using Microsoft.SharePoint.Client.Taxonomy; +using Microsoft.SharePoint.Client.WorkflowServices; +using SPMeta2.Containers.Consts; +using SPMeta2.Containers.Exceptions; +using SPMeta2.Containers.Services; +using SPMeta2.Containers.Utils; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.CSOM.Services; +using SPMeta2.CSOM.Standard.ModelHandlers.Fields; +using SPMeta2.ModelHandlers; +using SPMeta2.Models; +using SPMeta2.Regression.CSOM; +using SPMeta2.Regression.CSOM.Standard.Validation.Fields; +using SPMeta2.Utils; +using SPMeta2.CSOM.Standard.Services; +using SPMeta2.Services; + +namespace SPMeta2.Containers.O365 +{ + /// + /// O365 container runner implementation. + /// + public class O365ProvisionRunner : ProvisionRunnerBase + { + #region constructors + + public O365ProvisionRunner() + { + Name = "O365"; + + SiteUrls = new List(); + WebUrls = new List(); + + LoadEnvironmentConfig(); + InitServices(); + + UserName = RunnerEnvironmentUtils.GetEnvironmentVariable(EnvironmentConsts.O365_UserName); + UserPassword = RunnerEnvironmentUtils.GetEnvironmentVariable(EnvironmentConsts.O365_Password); + } + + public override ProvisionServiceBase ProvisionService + { + get { return _provisionService; } + } + + private void InitServices() + { + _provisionService = new StandardCSOMProvisionService(); + _validationService = new CSOMValidationService(); + + var csomStandartAsm = typeof(TaxonomyFieldModelHandler).Assembly; + + foreach (var handlerType in ReflectionUtils.GetTypesFromAssembly(csomStandartAsm)) + _provisionService.RegisterModelHandler(Activator.CreateInstance(handlerType) as ModelHandlerBase); + + var csomtandartValidationAsm = typeof(ClientTaxonomyFieldDefinitionValidator).Assembly; + + foreach (var handlerType in ReflectionUtils.GetTypesFromAssembly(csomtandartValidationAsm)) + _validationService.RegisterModelHandler(Activator.CreateInstance(handlerType) as ModelHandlerBase); + + _provisionService.OnModelNodeProcessing += (sender, args) => + { + ContainerTraceUtils.WriteLine( + string.Format("Processing: [{0}/{1}] - [{2:0} %] - [{3}] [{4}]", new object[] { args.ProcessedModelNodeCount, args.TotalModelNodeCount, 100d * (double)args.ProcessedModelNodeCount / (double)args.TotalModelNodeCount, args.CurrentNode.Value.GetType().Name, args.CurrentNode.Value - })); - }; - - _provisionService.OnModelNodeProcessed += (sender, args) => - { - ContainerTraceUtils.WriteLine( - string.Format("Processed: [{0}/{1}] - [{2:0} %] - [{3}] [{4}]", + })); + }; + + _provisionService.OnModelNodeProcessed += (sender, args) => + { + ContainerTraceUtils.WriteLine( + string.Format("Processed: [{0}/{1}] - [{2:0} %] - [{3}] [{4}]", new object[] { args.ProcessedModelNodeCount, args.TotalModelNodeCount, 100d * (double)args.ProcessedModelNodeCount / (double)args.TotalModelNodeCount, args.CurrentNode.Value.GetType().Name, args.CurrentNode.Value - })); - }; - } - - private List RandomBalancedUrls = new List(); - - private void LoadEnvironmentConfig() - { - SiteUrls.Clear(); - SiteUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_SiteUrls)); - - WebUrls.Clear(); - WebUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_WebUrls)); - - WebUrls.Clear(); - WebUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_WebUrls)); - - RandomBalancedUrls.Clear(); - RandomBalancedUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_RandomBalancedUrls)); - } - - #endregion - - #region properties - - /// - /// Target site URLs - /// - public List SiteUrls { get; set; } - - /// - /// Target web URLs - /// - public List WebUrls { get; set; } - - /// - /// User name - /// - public string UserName { get; set; } - - /// - /// User password - /// - public string UserPassword { get; set; } - - private CSOMProvisionService _provisionService; - private CSOMValidationService _validationService; - - - #endregion - - #region methods - - - /// - /// Resolves full name of the target type. - /// - /// - /// - /// - public override string ResolveFullTypeName(string typeName, string assemblyName) - { - var type = typeof(Field); - var workflow = typeof(WorkflowDefinition); - var store = typeof(TermStore); - var publishing = typeof(WebNavigationSettings); - var search = typeof(SearchConfigurationPortability); - - return base.ResolveFullTypeName(typeName, assemblyName); - } - - - public override void DeployFarmModel(ModelNode model) - { - throw new SPMeta2UnsupportedCSOMRunnerException(); - } - - public override void DeployWebApplicationModel(ModelNode model) - { - throw new SPMeta2UnsupportedCSOMRunnerException(); - } - - private Random rnd = new Random(); - - /// - /// Deploys and validates target site model. - /// - /// - public override void DeploySiteModel(ModelNode model) - { - if (RandomBalancedUrls.Count > 0) - { - var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; - SiteOnUrl(model, url); - } - else - { - foreach (var siteUrl in SiteUrls) - { - SiteOnUrl(model, siteUrl); - } - } - } - - private void SiteOnUrl(ModelNode model, string siteUrl) - { - ContainerTraceUtils.WriteLine(string.Format("[INF] Running on site: [{0}]", siteUrl)); - - for (var provisionGeneration = 0; - provisionGeneration < ProvisionGenerationCount; - provisionGeneration++) - { - WithO365Context(siteUrl, context => - { - if (EnableDefinitionProvision) - _provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); - - if (EnableDefinitionValidation) - _validationService.DeployModel(SiteModelHost.FromClientContext(context), model); - }); - } - } - - public override void DeployListModel(ModelNode model) - { - - if (RandomBalancedUrls.Count > 0) - { - var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; - WebOnUrl(model, url); - } - else - { - - foreach (var webUrl in WebUrls) - { - WebOnUrl(model, webUrl); - } - } - } - - private void WebOnUrl(ModelNode model, string webUrl) - { - ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); - - WithO365Context(webUrl, context => - { - for (var provisionGeneration = 0; - provisionGeneration < ProvisionGenerationCount; - provisionGeneration++) - { - if (EnableDefinitionProvision) - _provisionService.DeployModel(WebModelHost.FromClientContext(context), model); - - if (EnableDefinitionValidation) - _validationService.DeployModel(WebModelHost.FromClientContext(context), model); - } - }); - } - - - /// - /// Deploys and validates target web model. - /// - /// - public override void DeployWebModel(ModelNode model) - { - if (RandomBalancedUrls.Count > 0) - { - var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; - WebOnUrl(model, url); - } - else - { - foreach (var webUrl in WebUrls) - { - ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); - - - - for (var provisionGeneration = 0; - provisionGeneration < ProvisionGenerationCount; - provisionGeneration++) - { - WithO365Context(webUrl, context => - { - if (EnableDefinitionProvision) - _provisionService.DeployModel(WebModelHost.FromClientContext(context), model); - - if (EnableDefinitionValidation) - _validationService.DeployModel(WebModelHost.FromClientContext(context), model); - - }); - } - - - } - } - } - - #endregion - - #region utils - - #region static - - private static SecureString GetSecurePasswordString(string password) - { - var securePassword = new SecureString(); - - foreach (var s in password) - securePassword.AppendChar(s); - - return securePassword; - } - - #endregion - - /// - /// Invokes target action under O365 client context. - /// - /// - /// - public void WithO365Context(string siteUrl, Action action) - { - WithO365Context(siteUrl, UserName, UserPassword, action); - } - - /// - /// Invokes target action under O365 client context. - /// - /// - /// - /// - /// - private void WithO365Context(string siteUrl, string userName, string userPassword, Action action) - { - using (var context = new ClientContext(siteUrl)) - { - context.Credentials = new SharePointOnlineCredentials(userName, GetSecurePasswordString(userPassword)); - action(context); - } - } - - - #endregion - } -} + })); + }; + } + + private List RandomBalancedUrls = new List(); + + private void LoadEnvironmentConfig() + { + SiteUrls.Clear(); + SiteUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_SiteUrls)); + + WebUrls.Clear(); + WebUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_WebUrls)); + + WebUrls.Clear(); + WebUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_WebUrls)); + + RandomBalancedUrls.Clear(); + RandomBalancedUrls.AddRange(RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.O365_RandomBalancedUrls)); + } + + #endregion + + #region properties + + /// + /// Target site URLs + /// + public List SiteUrls { get; set; } + + /// + /// Target web URLs + /// + public List WebUrls { get; set; } + + /// + /// User name + /// + public string UserName { get; set; } + + /// + /// User password + /// + public string UserPassword { get; set; } + + private CSOMProvisionService _provisionService; + private CSOMValidationService _validationService; + + + #endregion + + #region methods + + + /// + /// Resolves full name of the target type. + /// + /// + /// + /// + public override string ResolveFullTypeName(string typeName, string assemblyName) + { + var type = typeof(Field); + var workflow = typeof(WorkflowDefinition); + var store = typeof(TermStore); + var publishing = typeof(WebNavigationSettings); + var search = typeof(SearchConfigurationPortability); + + return base.ResolveFullTypeName(typeName, assemblyName); + } + + + public override void DeployFarmModel(ModelNode model) + { + throw new SPMeta2UnsupportedCSOMRunnerException(); + } + + public override void DeployWebApplicationModel(ModelNode model) + { + throw new SPMeta2UnsupportedCSOMRunnerException(); + } + + private Random rnd = new Random(); + + /// + /// Deploys and validates target site model. + /// + /// + public override void DeploySiteModel(ModelNode model) + { + if (RandomBalancedUrls.Count > 0) + { + var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; + SiteOnUrl(model, url); + } + else + { + foreach (var siteUrl in SiteUrls) + { + SiteOnUrl(model, siteUrl); + } + } + } + + private void SiteOnUrl(ModelNode model, string siteUrl) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on site: [{0}]", siteUrl)); + + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) + { + WithO365Context(siteUrl, context => + { + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + _provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + } + + if (EnableDefinitionValidation) + _validationService.DeployModel(SiteModelHost.FromClientContext(context), model); + }); + } + } + + public override void DeployListModel(ModelNode model) + { + + if (RandomBalancedUrls.Count > 0) + { + var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; + WebOnUrl(model, url); + } + else + { + + foreach (var webUrl in WebUrls) + { + WebOnUrl(model, webUrl); + } + } + } + + private void WebOnUrl(ModelNode model, string webUrl) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); + + WithO365Context(webUrl, context => + { + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) + { + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + _provisionService.DeployModel(WebModelHost.FromClientContext(context), model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + } + + if (EnableDefinitionValidation) + _validationService.DeployModel(WebModelHost.FromClientContext(context), model); + } + }); + } + + + /// + /// Deploys and validates target web model. + /// + /// + public override void DeployWebModel(ModelNode model) + { + if (RandomBalancedUrls.Count > 0) + { + var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; + WebOnUrl(model, url); + } + else + { + foreach (var webUrl in WebUrls) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); + + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) + { + WithO365Context(webUrl, context => + { + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + _provisionService.DeployModel(WebModelHost.FromClientContext(context), model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + + } + + if (EnableDefinitionValidation) + _validationService.DeployModel(WebModelHost.FromClientContext(context), model); + + }); + } + } + } + } + + #endregion + + #region utils + + #region static + + private static SecureString GetSecurePasswordString(string password) + { + var securePassword = new SecureString(); + + foreach (var s in password) + securePassword.AppendChar(s); + + return securePassword; + } + + #endregion + + /// + /// Invokes target action under O365 client context. + /// + /// + /// + public void WithO365Context(string siteUrl, Action action) + { + WithO365Context(siteUrl, UserName, UserPassword, action); + } + + /// + /// Invokes target action under O365 client context. + /// + /// + /// + /// + /// + private void WithO365Context(string siteUrl, string userName, string userPassword, Action action) + { + using (var context = new ClientContext(siteUrl)) + { + context.Credentials = new SharePointOnlineCredentials(userName, GetSecurePasswordString(userPassword)); + action(context); + } + } + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Containers/Consts/EnvironmentConsts.cs b/SPMeta2/SPMeta2.Containers/Consts/EnvironmentConsts.cs index 5721538dd..dd31eccfa 100644 --- a/SPMeta2/SPMeta2.Containers/Consts/EnvironmentConsts.cs +++ b/SPMeta2/SPMeta2.Containers/Consts/EnvironmentConsts.cs @@ -1,42 +1,41 @@ -namespace SPMeta2.Containers.Consts -{ - public static class EnvironmentConsts - { - #region properties - - public const string O365_SiteUrls = "SPMeta2_O365_SiteUrls"; - public const string O365_WebUrls = "SPMeta2_O365_WebUrls"; - public const string O365_RandomBalancedUrls = "SPMeta2_O365_RandomBalancedUrls"; - - public const string O365_UserName = "SPMeta2_O365_UserName"; - public const string O365_Password = "SPMeta2_O365_Password"; - - public const string O365_DefaultTestUserLogins = "SPMeta2_O365_DefaultTestUserLogins"; - - - public const string SSOM_WebApplicationUrls = "SPMeta2_SSOM_WebApplicationUrls"; - public const string SSOM_SiteUrls = "SPMeta2_SSOM_SiteUrls"; - public const string SSOM_WebUrls = "SPMeta2_SSOM_WebUrls"; - - public const string CSOM_SiteUrls = "SPMeta2_CSOM_SiteUrls"; - public const string CSOM_WebUrls = "SPMeta2_CSOM_WebUrls"; - public const string CSOM_UserName = "SPMeta2_CSOM_UserName"; - public const string CSOM_Password = "SPMeta2_CSOM_Password"; - - public const string RunnerLibraries = "SPMeta2_RunnerLibraries"; - - public const string DefaultTaxonomyStoreName = "SPMeta2_DefaultTaxonomyStoreName"; - public const string DefaultTaxonomyStoreId = "SPMeta2_DefaultTaxonomyStoreId"; - - public const string DefaultSqlServerName = "SPMeta2_DefaultSqlServerName"; - +namespace SPMeta2.Containers.Consts +{ + public static class EnvironmentConsts + { + #region properties + + public const string O365_SiteUrls = "SPMeta2_O365_SiteUrls"; + public const string O365_WebUrls = "SPMeta2_O365_WebUrls"; + public const string O365_RandomBalancedUrls = "SPMeta2_O365_RandomBalancedUrls"; + + public const string O365_UserName = "SPMeta2_O365_UserName"; + public const string O365_Password = "SPMeta2_O365_Password"; + + public const string O365_DefaultTestUserLogins = "SPMeta2_O365_DefaultTestUserLogins"; + + + public const string SSOM_WebApplicationUrls = "SPMeta2_SSOM_WebApplicationUrls"; + public const string SSOM_SiteUrls = "SPMeta2_SSOM_SiteUrls"; + public const string SSOM_WebUrls = "SPMeta2_SSOM_WebUrls"; + + public const string CSOM_SiteUrls = "SPMeta2_CSOM_SiteUrls"; + public const string CSOM_WebUrls = "SPMeta2_CSOM_WebUrls"; + public const string CSOM_UserName = "SPMeta2_CSOM_UserName"; + public const string CSOM_Password = "SPMeta2_CSOM_Password"; + + public const string RunnerLibraries = "SPMeta2_RunnerLibraries"; + public const string RunnerProvisionMode = "SPMeta2_RunnerProvisionMode"; + + public const string DefaultTaxonomyStoreName = "SPMeta2_DefaultTaxonomyStoreName"; + public const string DefaultTaxonomyStoreId = "SPMeta2_DefaultTaxonomyStoreId"; + + public const string DefaultSqlServerName = "SPMeta2_DefaultSqlServerName"; + public const string DefaultTestUserLogins = "SPMeta2_DefaultTestUserLogins"; - public const string DefaultTestDomainUserEmails = "SPMeta2_DefaultTestDomainUserEmails"; - - public const string DefaultTestADGroups = "SPMeta2_DefaultTestADGroups"; - - - - #endregion - } -} + public const string DefaultTestDomainUserEmails = "SPMeta2_DefaultTestDomainUserEmails"; + + public const string DefaultTestADGroups = "SPMeta2_DefaultTestADGroups"; + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Containers/Services/ProvisionRunnerBase.cs b/SPMeta2/SPMeta2.Containers/Services/ProvisionRunnerBase.cs index 5fe9e07fb..33ea64318 100644 --- a/SPMeta2/SPMeta2.Containers/Services/ProvisionRunnerBase.cs +++ b/SPMeta2/SPMeta2.Containers/Services/ProvisionRunnerBase.cs @@ -1,80 +1,92 @@ -using System; -using System.Linq; -using SPMeta2.Models; - -namespace SPMeta2.Containers.Services -{ - public class ProvisionRunnerBase - { - #region constructors - - public ProvisionRunnerBase() - { - ProvisionGenerationCount = 1; - } - - #endregion - - #region properties - - public string Name { get; set; } - - public bool EnableDefinitionProvision { get; set; } - public bool EnableDefinitionValidation { get; set; } - - public int ProvisionGenerationCount { get; set; } - - #endregion - - #region methods - - public virtual string ResolveFullTypeName(string typeName, string assemblyName) - { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - - var targetAssembly = assemblies.FirstOrDefault(a => a.FullName.Split(',')[0].ToUpper() == assemblyName.ToUpper()); - var targetType = targetAssembly.GetType(typeName); - - return targetType.AssemblyQualifiedName; - } - - public virtual void DeployFarmModel(ModelNode model) - { - throw new NotImplementedException(); - } - - public virtual void DeployWebApplicationModel(ModelNode model) - { - throw new NotImplementedException(); - } - - public virtual void DeploySiteModel(ModelNode model) - { - throw new NotImplementedException(); - } - - public virtual void DeployWebModel(ModelNode model) - { - throw new NotImplementedException(); - } - - public virtual void DeployListModel(ModelNode model) - { - throw new NotImplementedException(); - } - - #endregion - - public virtual void InitLazyRunnerConnection() - { - - } - - public virtual void DisposeLazyRunnerConnection() - { - - } - - - } -} +using System; +using System.Linq; +using SPMeta2.Models; +using SPMeta2.Services; + +namespace SPMeta2.Containers.Services +{ + public class ProvisionRunnerBase + { + #region constructors + + public ProvisionRunnerBase() + { + ProvisionGenerationCount = 1; + } + + #endregion + + #region properties + + public Action OnBeforeDeployModel { get; set; } + public Action OnAfterDeployModel { get; set; } + + public virtual ProvisionServiceBase ProvisionService + { + get + { + throw new NotImplementedException("override this property in ProvisionRunnerBase implementation"); + } + } + + public string Name { get; set; } + + public bool EnableDefinitionProvision { get; set; } + public bool EnableDefinitionValidation { get; set; } + + public int ProvisionGenerationCount { get; set; } + + #endregion + + #region methods + + public virtual string ResolveFullTypeName(string typeName, string assemblyName) + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + var targetAssembly = assemblies.FirstOrDefault(a => a.FullName.Split(',')[0].ToUpper() == assemblyName.ToUpper()); + var targetType = targetAssembly.GetType(typeName); + + return targetType.AssemblyQualifiedName; + } + + public virtual void DeployFarmModel(ModelNode model) + { + throw new NotImplementedException(); + } + + public virtual void DeployWebApplicationModel(ModelNode model) + { + throw new NotImplementedException(); + } + + public virtual void DeploySiteModel(ModelNode model) + { + throw new NotImplementedException(); + } + + public virtual void DeployWebModel(ModelNode model) + { + throw new NotImplementedException(); + } + + public virtual void DeployListModel(ModelNode model) + { + throw new NotImplementedException(); + } + + #endregion + + public virtual void InitLazyRunnerConnection() + { + + } + + public virtual void DisposeLazyRunnerConnection() + { + + } + + + } +} diff --git a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs index af51b7cee..9f0957e98 100644 --- a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs +++ b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs @@ -489,6 +489,9 @@ public void TestModels(IEnumerable models) TestModels(models, false); } + public Action BeforeProvisionRunnerExcecution { get; set; } + public Action AfterProvisionRunnerExcecution { get; set; } + public void TestModels(IEnumerable models, bool deployOnce) { // force XML serialiation @@ -513,6 +516,9 @@ public void TestModels(IEnumerable models, bool deployOnce) { var runner = runnerContext.Runner; + if (BeforeProvisionRunnerExcecution != null) + BeforeProvisionRunnerExcecution(runner); + var omModelType = GetRunnerType(runner); var hooks = GetHooks(model); @@ -535,7 +541,6 @@ public void TestModels(IEnumerable models, bool deployOnce) { throw new SPMeta2NotImplementedException( string.Format("Runner does not support model of type: [{0}]", model.Value.GetType())); - } if (!deployOnce) @@ -546,6 +551,9 @@ public void TestModels(IEnumerable models, bool deployOnce) AssertService.IsFalse(hasMissedOrInvalidProps); } } + + if (AfterProvisionRunnerExcecution != null) + AfterProvisionRunnerExcecution(runner); }); if (!deployOnce) @@ -593,6 +601,9 @@ public ModelNode TestRandomDefinition(Action definitio { var runner = runnerContext.Runner; + if (BeforeProvisionRunnerExcecution != null) + BeforeProvisionRunnerExcecution(runner); + ValidateDefinitionHostRunnerSupport(runner); var omModelType = GetRunnerType(runner); @@ -635,6 +646,9 @@ public ModelNode TestRandomDefinition(Action definitio AssertService.IsFalse(hasMissedOrInvalidProps); } + if (AfterProvisionRunnerExcecution != null) + AfterProvisionRunnerExcecution(runner); + result = definitionSandbox; }); diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs index 5bca64005..91503d719 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs @@ -30,6 +30,7 @@ using SPMeta2.Regression.Tests.Impl.Scenarios.Webparts; using SPMeta2.Services; using System.IO; +using SPMeta2.Containers.Consts; using SPMeta2.Regression.Utils; namespace SPMeta2.Regression.Tests.Base @@ -144,6 +145,23 @@ protected virtual T RndDef(Action action) { return ModelGeneratorService.GetRandomDefinition(action); } + public bool IsIncrementalProvisionMode + { + get + { + var result = false; + + var value = RunnerEnvironmentUtils.GetEnvironmentVariable(EnvironmentConsts.RunnerProvisionMode); + + if (!string.IsNullOrEmpty(value)) + { + if (value.ToLower() == "incremental") + result = true; + } + + return result; + } + } } public class SPMeta2DefinitionRegresionTestBase : SPMeta2RegresionTestCoreBase diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs index 9f6323ca2..4039395ce 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs @@ -1,29 +1,73 @@ -using SPMeta2.Containers.Services; -using SPMeta2.Containers.Services.Rnd; -using SPMeta2.Regression.Tests.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SPMeta2.Exceptions; - - -namespace SPMeta2.Regression.Tests.Impl.Scenarios.Base -{ - public class SPMeta2RegresionScenarioTestBase : SPMeta2ProvisionRegresionTestBase - { - #region constructors - - public SPMeta2RegresionScenarioTestBase() - { - RegressionService.ProvisionGenerationCount = 2; - RegressionService.ShowOnlyFalseResults = false; - } - - #endregion - - - - - } -} +using SPMeta2.Containers.Services; +using SPMeta2.Containers.Services.Rnd; +using SPMeta2.Regression.Tests.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SPMeta2.Common; +using SPMeta2.Containers.Consts; +using SPMeta2.Containers.Utils; +using SPMeta2.Exceptions; +using SPMeta2.Regression.Tests.Impl.Services; +using SPMeta2.Regression.Utils; +using SPMeta2.Services; +using SPMeta2.Services.Impl; + + +namespace SPMeta2.Regression.Tests.Impl.Scenarios.Base +{ + public class SPMeta2RegresionScenarioTestBase : SPMeta2ProvisionRegresionTestBase + { + #region constructors + + public SPMeta2RegresionScenarioTestBase() + { + RegressionService.ProvisionGenerationCount = 2; + RegressionService.ShowOnlyFalseResults = false; + + var isIncrementalProvisionEnabled = IsIncrementalProvisionMode; + + if (isIncrementalProvisionEnabled) + { + RegressionService.BeforeProvisionRunnerExcecution += (runner) => + { + runner.ProvisionService.SetIncrementalProvisionMode(); + + runner.OnBeforeDeployModel += (provisionService, model) => + { + if (PreviousModelHash != null) + provisionService.SetIncrementalProvisionModelHash(PreviousModelHash); + }; + + runner.OnAfterDeployModel += (provisionService, model) => + { + var tracer = new DefaultIncrementalModelPrettyPrintService(); + + RegressionUtils.WriteLine(string.Format("Deployed model with incremental updates:")); + RegressionUtils.WriteLine(Environment.NewLine + tracer.PrintModel(model)); + + PreviousModelHash = provisionService.GetIncrementalProvisionModelHash(); + }; + }; + + RegressionService.AfterProvisionRunnerExcecution += (runner) => + { + + }; + + RegressionService.EnableEventValidation = false; + RegressionService.EnableDefinitionValidation = false; + RegressionService.EnablePropertyValidation = false; + } + } + + #endregion + + #region properties + + public ModelHash PreviousModelHash { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs index d710a6a6d..6d80d61d2 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs @@ -1,249 +1,246 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.BuiltInDefinitions; -using SPMeta2.Containers; -using SPMeta2.Containers.Standard; -using SPMeta2.Regression.Tests.Base; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SPMeta2.Models; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Standard.Syntax; -using SPMeta2.Syntax.Default; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class TaxonomyScenariousTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanupAttribute] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region default - - protected void GenerateTermsTree(ModelNode termSetOrTermNode, int deep, bool cleanGuid) - { - if (deep == 0) - return; - - if (termSetOrTermNode is TaxonomyTermModelNode) - { - (termSetOrTermNode as TaxonomyTermModelNode).AddRandomTerm(term => - { - var termDef = term.Value as TaxonomyTermDefinition; - termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); - - if (cleanGuid) - termDef.Id = null; - - GenerateTermsTree(term, --deep, cleanGuid); - }); - } - else if (termSetOrTermNode is TaxonomyTermSetModelNode) - { - (termSetOrTermNode as TaxonomyTermSetModelNode).AddRandomTerm(term => - { - var termDef = term.Value as TaxonomyTermDefinition; - termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); - - if (cleanGuid) - termDef.Id = null; - - GenerateTermsTree(term, --deep, cleanGuid); - }); - } - - - } - - protected ModelNode GenerateTermTaxonomyTree(int deep, bool cleanGuid) - { - var model = SPMeta2Model - .NewSiteModel(site => - { - site - .AddRandomTermStore(store => - { - store - .AddRandomTermGroup(group => - { - group - .AddRandomTermSet(termSet => - { - GenerateTermsTree(termSet, deep, cleanGuid); - }); - }); - }); - }); - - return model; - } - - #region term tree, clean ID - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Named_Tree_Level_1() - { - var model = GenerateTermTaxonomyTree(1, true); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Named_Tree_Level_2() - { - var model = GenerateTermTaxonomyTree(2, true); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Named_Tree_Level_3() - { - var model = GenerateTermTaxonomyTree(3, true); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Named_Tree_Level_4() - { - var model = GenerateTermTaxonomyTree(4, true); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Named_Tree_Level_5() - { - var model = GenerateTermTaxonomyTree(5, true); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Named_Tree_Level_6() - { - var model = GenerateTermTaxonomyTree(6, true); - TestModel(model); - } - - #endregion - - #region term tree, non empty ID - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Id_Tree_Level_1() - { - var model = GenerateTermTaxonomyTree(1, false); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Id_Tree_Level_2() - { - var model = GenerateTermTaxonomyTree(2, false); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Id_Tree_Level_3() - { - var model = GenerateTermTaxonomyTree(3, false); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Id_Tree_Level_4() - { - var model = GenerateTermTaxonomyTree(4, false); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Id_Tree_Level_5() - { - var model = GenerateTermTaxonomyTree(5, false); - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] - public void CanDeploy_TaxonomyTerm_Id_Tree_Level_6() - { - var model = GenerateTermTaxonomyTree(6, false); - TestModel(model); - } - - #endregion - - [TestMethod] - [TestCategory("Regression.Scenarios.Taxonomy")] - public void CanDeploy_TaxonomyHierarchy() - { - var model = SPMeta2Model - .NewSiteModel(site => - { - site - .AddRandomTermStore(store => - { - store - .AddRandomTermGroup(group => - { - group - .AddRandomTermSet(termSet => - { - termSet - .AddRandomTerm() - .AddRandomTerm() - .AddRandomTerm() - .AddRandomTerm(); - }) - .AddRandomTermSet(termSet => - { - termSet - .AddRandomTerm() - .AddRandomTerm(); - }); - }) - .AddRandomTermGroup(group => - { - group - .AddRandomTermSet(termSet => - { - termSet - .AddRandomTerm() - .AddRandomTerm(); - }); - }); - }); - }); - - TestModel(model); - } - - - #endregion - } -} +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.BuiltInDefinitions; +using SPMeta2.Containers; +using SPMeta2.Containers.Standard; +using SPMeta2.Regression.Tests.Base; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SPMeta2.Models; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Standard.Syntax; +using SPMeta2.Syntax.Default; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class TaxonomyScenariousTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanupAttribute] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region default + + protected void GenerateTermsTree(ModelNode termSetOrTermNode, int deep, bool cleanGuid) + { + if (deep == 0) + return; + + if (termSetOrTermNode is TaxonomyTermModelNode) + { + (termSetOrTermNode as TaxonomyTermModelNode).AddRandomTerm(term => + { + var termDef = term.Value as TaxonomyTermDefinition; + termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); + + if (cleanGuid) + termDef.Id = null; + + GenerateTermsTree(term, --deep, cleanGuid); + }); + } + else if (termSetOrTermNode is TaxonomyTermSetModelNode) + { + (termSetOrTermNode as TaxonomyTermSetModelNode).AddRandomTerm(term => + { + var termDef = term.Value as TaxonomyTermDefinition; + termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); + + if (cleanGuid) + termDef.Id = null; + + GenerateTermsTree(term, --deep, cleanGuid); + }); + } + + + } + + protected ModelNode GenerateTermTaxonomyTree(int deep, bool cleanGuid) + { + var model = SPMeta2Model + .NewSiteModel(site => + { + site + .AddRandomTermStore(store => + { + store + .AddRandomTermGroup(group => + { + group + .AddRandomTermSet(termSet => + { + GenerateTermsTree(termSet, deep, cleanGuid); + }); + }); + }); + }); + + return model; + } + + #region term tree, clean ID + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Named_Tree_Level_1() + { + var model = GenerateTermTaxonomyTree(1, true); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Named_Tree_Level_2() + { + var model = GenerateTermTaxonomyTree(2, true); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Named_Tree_Level_3() + { + var model = GenerateTermTaxonomyTree(3, true); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Named_Tree_Level_4() + { + var model = GenerateTermTaxonomyTree(4, true); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Named_Tree_Level_5() + { + var model = GenerateTermTaxonomyTree(5, true); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Named_Tree_Level_6() + { + var model = GenerateTermTaxonomyTree(6, true); + TestModel(model); + } + + #endregion + + #region term tree, non empty ID + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Id_Tree_Level_1() + { + var model = GenerateTermTaxonomyTree(1, false); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Id_Tree_Level_2() + { + var model = GenerateTermTaxonomyTree(2, false); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Id_Tree_Level_3() + { + var model = GenerateTermTaxonomyTree(3, false); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Id_Tree_Level_4() + { + var model = GenerateTermTaxonomyTree(4, false); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Id_Tree_Level_5() + { + var model = GenerateTermTaxonomyTree(5, false); + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy.Hierarchy")] + public void CanDeploy_TaxonomyTerm_Id_Tree_Level_6() + { + var model = GenerateTermTaxonomyTree(6, false); + TestModel(model); + } + + #endregion + + [TestMethod] + [TestCategory("Regression.Scenarios.Taxonomy")] + public void CanDeploy_TaxonomyHierarchy() + { + var model = SPMeta2Model.NewSiteModel(site => + { + site.AddRandomTermStore(store => + { + store.AddRandomTermGroup(group => + { + group + .AddRandomTermSet(termSet => + { + termSet + .AddRandomTerm() + .AddRandomTerm() + .AddRandomTerm() + .AddRandomTerm(); + }) + .AddRandomTermSet(termSet => + { + termSet + .AddRandomTerm() + .AddRandomTerm(); + }); + }) + .AddRandomTermGroup(group => + { + group + .AddRandomTermSet(termSet => + { + termSet + .AddRandomTerm() + .AddRandomTerm(); + }); + }); + }); + }); + + TestModel(model); + } + + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebScenariosTest.cs index 9d87bdf51..119c352e3 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebScenariosTest.cs @@ -245,31 +245,30 @@ public void CanDeploy_PublishingSite_CMS() [TestCategory("Regression.Scenarios.Webs")] public void CanDeploy_WebHierarchy() { - var model = SPMeta2Model - .NewWebModel(web => - { - web - .AddWeb(RegWebs.Archive) - .AddWeb(RegWebs.Blog) - .AddWeb(RegWebs.CIO, cioWeb => - { - cioWeb - .AddWeb(RegWebs.CIOBlog); - }) - .AddWeb(RegWebs.Departments, departmentsWeb => - { - departmentsWeb - .AddWeb(RegWebs.HR) - .AddWeb(RegWebs.IT) - .AddWeb(RegWebs.Delivery) - .AddWeb(RegWebs.Sales) - .AddWeb(RegWebs.PR); - }) - .AddWeb(RegWebs.Projects) - .AddWeb(RegWebs.Wiki) - .AddWeb(RegWebs.FAQ); - - }); + var model = SPMeta2Model.NewWebModel(web => + { + web + .AddWeb(RegWebs.Archive) + .AddWeb(RegWebs.Blog) + .AddWeb(RegWebs.CIO, cioWeb => + { + cioWeb + .AddWeb(RegWebs.CIOBlog); + }) + .AddWeb(RegWebs.Departments, departmentsWeb => + { + departmentsWeb + .AddWeb(RegWebs.HR) + .AddWeb(RegWebs.IT) + .AddWeb(RegWebs.Delivery) + .AddWeb(RegWebs.Sales) + .AddWeb(RegWebs.PR); + }) + .AddWeb(RegWebs.Projects) + .AddWeb(RegWebs.Wiki) + .AddWeb(RegWebs.FAQ); + + }); TestModel(model); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs index b150113b4..df4dbecf1 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs @@ -21,22 +21,7 @@ namespace SPMeta2.Regression.Tests.Impl.Services { - public class IncrementalModelPrettyPrintService : DefaultModelPrettyPrintService - { - protected override string GetDefinitionValue(ModelNode modelNode) - { - var shouldDeploy = modelNode.Options.RequireSelfProcessing; - - if (shouldDeploy) - { - return string.Format("[+] {0}", base.GetDefinitionValue(modelNode)); - } - else - { - return string.Format("[-] {0}", base.GetDefinitionValue(modelNode)); - } - } - } + [TestClass] public class IncrementalModelTreeTraverseServiceTests @@ -45,7 +30,7 @@ public class IncrementalModelTreeTraverseServiceTests public IncrementalModelTreeTraverseServiceTests() { - ModelPrintService = new IncrementalModelPrettyPrintService(); + ModelPrintService = new DefaultIncrementalModelPrettyPrintService(); Rnd = new DefaultRandomService(); diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index 0ffe641e4..8921aaa3e 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -362,6 +362,7 @@ + diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs new file mode 100644 index 000000000..06b9cf13b --- /dev/null +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SPMeta2.Models; + +namespace SPMeta2.Services.Impl +{ + public class DefaultIncrementalModelPrettyPrintService : DefaultModelPrettyPrintService + { + #region methods + + protected override string GetCurrentIntent(ModelNode modelNode, string currentIndent) + { + var shouldDeploy = modelNode.Options.RequireSelfProcessing; + + if (shouldDeploy) + return string.Format("[+] {0}", currentIndent); + + return string.Format("[-] {0}", currentIndent); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index bb0e18c32..c62a5d973 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -21,6 +21,9 @@ public DefaultIncrementalModelTreeTraverseService() CurrentModelHash = new ModelHash(); IgnoredModelNodes = new List(); + + DefaultDefinitionFullPathSeparator = "/"; + DefaultDefinitionIdentityKeySeparator = ";"; } #endregion @@ -30,10 +33,13 @@ public DefaultIncrementalModelTreeTraverseService() public ModelHash PreviousModelHash { get; set; } public ModelHash CurrentModelHash { get; private set; } - public HashCodeServiceBase _hashService { get; set; } + protected HashCodeServiceBase _hashService { get; set; } protected List IgnoredModelNodes { get; private set; } + protected string DefaultDefinitionFullPathSeparator { get; set; } + protected string DefaultDefinitionIdentityKeySeparator { get; set; } + #endregion #region methods @@ -78,7 +84,7 @@ protected virtual string GetDefinitionIdentityKey(DefinitionBase definition) identityKeyValues.Add(keyName, keyValue); } - var resultIdentityKey = string.Join(";", + var resultIdentityKey = string.Join(DefaultDefinitionIdentityKeySeparator, identityKeyValues.Select(v => string.Format("{0}:{1}", v.Key, v.Value)).ToArray()); return resultIdentityKey; @@ -98,11 +104,11 @@ protected virtual string GetDefinitionFullPath(bool asHash) if (asHash) { - result = string.Join("/", currentDefinitions.Select(p => GetHashString(GetDefinitionIdentityKey(p))).ToArray()); + result = string.Join(DefaultDefinitionFullPathSeparator, currentDefinitions.Select(p => GetHashString(GetDefinitionIdentityKey(p))).ToArray()); } else { - result = string.Join("/", currentDefinitions.Select(p => GetDefinitionIdentityKey(p)).ToArray()); + result = string.Join(DefaultDefinitionFullPathSeparator, currentDefinitions.Select(p => GetDefinitionIdentityKey(p)).ToArray()); // full path is 'hash(identitykey)/hash(identitykey)/hash(identitykey)' } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultModelPrettyPrintService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultModelPrettyPrintService.cs index 27ef768d2..8dd319ad8 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultModelPrettyPrintService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultModelPrettyPrintService.cs @@ -30,7 +30,7 @@ public override string PrintModel(ModelNode modelNode) { var result = new StringBuilder(); - result.AppendFormat("{0}{1}", GetDefinitionValue(modelNode), NewLineString); + result.AppendFormat("{0}{1}{2}", GetCurrentIntent(modelNode, string.Empty), GetDefinitionValue(modelNode), NewLineString); WalkModelNodes(modelNode, result, IndentString); @@ -45,12 +45,17 @@ protected virtual void WalkModelNodes(ModelNode model, StringBuilder result, str { foreach (var modelNode in modelNodeGroup) { - result.AppendFormat("{0}{1}{2}", indent, GetDefinitionValue(modelNode), NewLineString); - WalkModelNodes(modelNode, result, IndentString + IndentString); + result.AppendFormat("{0}{1}{2}", GetCurrentIntent(modelNode, indent), GetDefinitionValue(modelNode), NewLineString); + WalkModelNodes(modelNode, result, indent + IndentString); } } } + protected virtual string GetCurrentIntent(ModelNode modelNode, string currentIndent) + { + return currentIndent; + } + protected virtual string GetDefinitionValue(ModelNode modelNode) { return modelNode.Value != null From 6c941847db9c960983e8a10174a4ad402222ca11 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 03:14:13 +0000 Subject: [PATCH 12/53] + Implement 'incremental' provision support #553 + more testing and various fixes --- .../Services/RegressionTestService.cs | 34 +- .../Base/SPMeta2RegresionTestBase.cs | 6 +- .../Base/SPMeta2RegresionScenarioTestBase.cs | 2 + ...ncrementalModelTreeTraverseServiceTests.cs | 4 +- SPMeta2/SPMeta2/Models/ModelNode.cs | 814 +++++++++--------- ...faultIncrementalModelPrettyPrintService.cs | 11 +- ...aultIncrementalModelTreeTraverseService.cs | 37 +- .../Impl/DefaultModelTreeTraverseService.cs | 21 +- 8 files changed, 507 insertions(+), 422 deletions(-) diff --git a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs index 9f0957e98..5c59442d1 100644 --- a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs +++ b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs @@ -520,12 +520,20 @@ public void TestModels(IEnumerable models, bool deployOnce) BeforeProvisionRunnerExcecution(runner); var omModelType = GetRunnerType(runner); - var hooks = GetHooks(model); + var hooks = new List(); - foreach (var hook in hooks) - hook.Tag = runner.Name; + if (!deployOnce) + { + if (this.EnableDefinitionValidation) + { + hooks = GetHooks(model); - allHooks.AddRange(hooks); + foreach (var hook in hooks) + hook.Tag = runner.Name; + + allHooks.AddRange(hooks); + } + } if (model.Value.GetType() == typeof(FarmDefinition)) runner.DeployFarmModel(model); @@ -619,14 +627,22 @@ public ModelNode TestRandomDefinition(Action definitio definitionSetup(def as TDefinition); } - var hooks = GetHooks(definitionSandbox); + var hooks = new List(); - foreach (var hook in hooks) - hook.Tag = runner.Name; + if (this.EnableDefinitionValidation) + { + hooks = GetHooks(definitionSandbox); - GetSerializedAndRestoredModels(definitionSandbox); + foreach (var hook in hooks) + hook.Tag = runner.Name; - allHooks.AddRange(hooks); + GetSerializedAndRestoredModels(definitionSandbox); + allHooks.AddRange(hooks); + } + else + { + GetSerializedAndRestoredModels(definitionSandbox); + } if (definitionSandbox.Value.GetType() == typeof(FarmDefinition)) runner.DeployFarmModel(definitionSandbox); diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs index 91503d719..057fdfcaf 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs @@ -479,10 +479,14 @@ private void ProcessPropertyUpdateValidation(IEnumerable models) { foreach (var model in models) { + var localModel = model; + model.WithNodesOfType(node => { var def = node.Value; - ProcessDefinitionsPropertyUpdateValidation(def); + + if (node != localModel) + ProcessDefinitionsPropertyUpdateValidation(def); }); } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs index 4039395ce..601da6f64 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs @@ -59,6 +59,8 @@ public SPMeta2RegresionScenarioTestBase() RegressionService.EnableEventValidation = false; RegressionService.EnableDefinitionValidation = false; RegressionService.EnablePropertyValidation = false; + + EnablePropertyUpdateValidation = true; } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs index df4dbecf1..ab87598f9 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs @@ -346,10 +346,10 @@ public FakeIncrementalModelTreeTraverseService() #endregion - protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNode) + protected override void OnBeforeDeployModelNode(object modelHost, ModelNode modelNode) { // process deployment need - base.OnBeforeDeployModel(modelHost, modelNode); + base.OnBeforeDeployModelNode(modelHost, modelNode); if (modelNode.Options.RequireSelfProcessing) ModelNodesToUpdate.Add(modelNode); diff --git a/SPMeta2/SPMeta2/Models/ModelNode.cs b/SPMeta2/SPMeta2/Models/ModelNode.cs index 45ae57b5b..94611efb8 100644 --- a/SPMeta2/SPMeta2/Models/ModelNode.cs +++ b/SPMeta2/SPMeta2/Models/ModelNode.cs @@ -1,404 +1,410 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Runtime.Serialization; -using System.Xml.Serialization; -using SPMeta2.Common; -using SPMeta2.Definitions; -using SPMeta2.Exceptions; -using SPMeta2.Services; - -namespace SPMeta2.Models -{ - /// - /// Internal usage only. - /// - public enum ModelNodeState - { - /// - /// Model node has not been changed. - /// - None, - - /// - /// Model node is being processed. - /// - Processing, - - /// - /// Model node has been processed. - /// - Processed - } - - /// - /// Allows to adjust particular mode node processing behaviour. - /// - [Serializable] - [DataContract] - public class ModelNodeOptions - { - #region constructors - - public ModelNodeOptions() - { - RequireSelfProcessing = true; - } - - #endregion - - #region properties - - /// - /// Indicates of model node needs to be processed by model handler. - /// - - [DataMember] - public bool RequireSelfProcessing { get; set; } - - #endregion - - #region static - - - public static ModelNodeOptions New() - { - return new ModelNodeOptions(); - } - - #endregion - } - - public static class ModelNodeOptionsSyntax - { - public static ModelNodeOptions NoSelfProcessing(this ModelNodeOptions options) - { - options.RequireSelfProcessing = false; - - return options; - } - } - - /// - /// Base tree model node implementation. - /// - [Serializable] - [DataContract] - public class ModelNode - { - #region constructors - - public ModelNode() - { - - ChildModels = new Collection(); - Options = new ModelNodeOptions(); - - PropertyBag = new List(); - - InitDataMemberIgnorableProperties(); - } - - private void InitDataMemberIgnorableProperties() - { - TraceService = ServiceContainer.Instance.GetService(); - - ModelEvents = new Dictionary>(); - ModelContextEvents = new Dictionary>(); - } - - #endregion - - #region properties - - #region properties - - [XmlIgnore] - [IgnoreDataMember] - public string ObjectType - { - get { return GetType().Name; } - set - { - - } - } - - #endregion - - /// - /// Allows to adjust particular mode node processing behaviour. - /// - [DataMember] - public ModelNodeOptions Options { get; set; } - - /// - /// A property bag to be used for any 'custom' properties attached to ModelNode. - /// - [DataMember] - - public List PropertyBag { get; set; } - - [DataMember] - public DefinitionBase Value { get; set; } - - [DataMember] - public Collection ChildModels { get; set; } - - [XmlIgnore] - [IgnoreDataMember] - public Dictionary> ModelEvents { get; set; } - - [XmlIgnore] - [IgnoreDataMember] - public Dictionary> ModelContextEvents { get; set; } - - [XmlIgnore] - [IgnoreDataMember] - public ModelNodeState State { get; set; } - - [XmlIgnore] - [NonSerialized] - [IgnoreDataMember] - protected TraceServiceBase TraceService; - - #endregion - - [OnDeserialized] - void OnDeserialized(StreamingContext context) - { - // https://github.com/SubPointSolutions/spmeta2/issues/697 - // serialization would set all [IgnoreDataMember] as nulls - // so we need to sestore them to normal state as we would go in constructor - - InitDataMemberIgnorableProperties(); - } - - #region events support - - public delegate void TmpAction(object arg1, object arg2); - - public virtual void InvokeOnModelContextEvents(object sender, ModelEventArgs eventArgs) - { - var objectType = typeof(object); - var eventType = eventArgs.EventType; - - // type.. can be null, so? - var spObjectType = eventArgs.ObjectType; - - if (!ModelContextEvents.ContainsKey(eventType)) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Cannot find ModelContextEvents for eventType: [{0}]", eventType); - return; - } - else - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Calling ModelContextEvents for eventType: [{0}]", eventType); - } - - var targetEvents = ModelContextEvents[eventType]; - - // yea, yea.. - foreach (MulticastDelegate action in targetEvents) - { - var modelContextType = typeof(OnCreatingContext<,>); - - var nonDefinition = new Type[] { spObjectType, typeof(DefinitionBase) }; - var withDefinition = new Type[] { spObjectType, eventArgs.ObjectDefinition.GetType() }; - var nonObjectDefinition = new Type[] { objectType, typeof(DefinitionBase) }; - var withObjectDefinition = new Type[] { objectType, eventArgs.ObjectDefinition.GetType() }; - - var modelNonDefInstanceType = modelContextType.MakeGenericType(nonDefinition); - var modelWithDefInstanceType = modelContextType.MakeGenericType(withDefinition); - var modelNonObjectDefInstanceType = modelContextType.MakeGenericType(nonObjectDefinition); - var modelWithObjectDefInstanceType = modelContextType.MakeGenericType(withObjectDefinition); - - object modelContextInstance = null; - - if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelNonDefInstanceType)) - { - modelContextInstance = Activator.CreateInstance(modelNonDefInstanceType); - } - else if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelWithDefInstanceType)) - { - modelContextInstance = Activator.CreateInstance(modelWithDefInstanceType); - } - else if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelNonObjectDefInstanceType)) - { - modelContextInstance = Activator.CreateInstance(modelNonObjectDefInstanceType); - } - else if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelWithObjectDefInstanceType)) - { - modelContextInstance = Activator.CreateInstance(modelWithObjectDefInstanceType); - } - - if (modelContextInstance == null) - { - TraceService.ErrorFormat((int)LogEventId.ModelTreeModelContextEventIsNull, - "Cannot find model content instance for method: [{0}]. Throwing SPMeta2Exception.", action.Method); - - throw new SPMeta2Exception("Cannot find a proper ModelContextEvents overload"); - } - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [Model]: [{0}]", eventArgs.Model); - SetProperty(modelContextInstance, "Model", eventArgs.Model); - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [CurrentModelNode]: [{0}]", eventArgs.CurrentModelNode); - SetProperty(modelContextInstance, "CurrentModelNode", eventArgs.CurrentModelNode); - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [Object]: [{0}]", eventArgs.Object); - SetProperty(modelContextInstance, "Object", eventArgs.Object); - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [ObjectDefinition]: [{0}]", eventArgs.ObjectDefinition); - SetProperty(modelContextInstance, "ObjectDefinition", eventArgs.ObjectDefinition); - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [ModelHost]: [{0}]", eventArgs.ModelHost); - SetProperty(modelContextInstance, "ModelHost", eventArgs.ModelHost); - - TraceService.Verbose((int)LogEventId.CoreCalls, "Invoking event."); - action.DynamicInvoke(modelContextInstance); - } - } - - private static void SetProperty(object obj, string propName, object propValue) - { - var propertyInfo = obj.GetType().GetProperty(propName); - propertyInfo.SetValue(obj, propValue, null); - } - - public virtual void InvokeOnModelEvents(object rawObject, ModelEventType eventType) - { - if (!ModelEvents.ContainsKey(eventType)) return; - - var targetEvents = ModelEvents[eventType]; - - // yeap, shity yet - foreach (MulticastDelegate action in targetEvents) - action.DynamicInvoke(Value, rawObject); - } - - public virtual void RegisterModelUpdateEvents( - Action onUpdating, Action onUpdated) - { - RegisterModelUpdatingEvent(onUpdating); - RegisterModelUpdatedEvent(onUpdated); - } - - public virtual void RegisterModelUpdatingEvent(Action action) - { - RegisterModelEvent(ModelEventType.OnUpdating, action); - } - - public virtual void RegisterModelUpdatedEvent(Action action) - { - RegisterModelEvent(ModelEventType.OnUpdated, action); - } - - public virtual void RegisterModelEvent(ModelEventType actionType, Action action) - { - if (action == null) return; - - if (!ModelEvents.ContainsKey(actionType)) - ModelEvents.Add(actionType, new List()); - - ModelEvents[actionType].Add(action); - } - - public virtual void RegisterModelContextEvent( - ModelEventType actionType, - Action> action) - where TDefinitionType : DefinitionBase - { - if (action == null) return; - - if (!ModelContextEvents.ContainsKey(actionType)) - ModelContextEvents.Add(actionType, new List()); - - ModelContextEvents[actionType].Add(action); - } - - #endregion - - #region methods - - public override string ToString() - { - return Value != null - ? string.Format("Node value: [{0}] - {1}", Value.GetType().Name, Value) - : base.ToString(); - } - - #endregion - } - - /// - /// Internal usage only. - /// Indicates the strategy for the provision exception handling. - /// - public enum ContinuationOptions - { - /// - /// Throw an exception - /// - StopAndThrowException, - - /// - /// Silently continue. - /// - Continue, - - /// - /// Silently stop. - /// - Stop, - } - - /// - /// Model creaeting/creating context. - /// - /// - /// - public class OnCreatingContext - where TDefinitionType : DefinitionBase - { - /// - /// Typed SharePoint object instance. - /// - public TObjectType Object { get; set; } - - /// - /// Current model definition. - /// - public TDefinitionType ObjectDefinition { get; set; } - - /// - /// Current model, the root node. - /// - public ModelNode Model { get; set; } - - - /// - /// Current model host. - /// - public object ModelHost { get; set; } - - /// - /// Current model node. - /// - public ModelNode CurrentModelNode { get; set; } - - /// - /// Exception handling options. - /// - public ContinuationOptions ContinuationOption { get; set; } - -#if !NET35 - - /// - /// Aggregated exception, if any. - /// - public AggregateException Error { get; set; } - -#endif - } -} +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using System.Xml.Serialization; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Exceptions; +using SPMeta2.Services; + +namespace SPMeta2.Models +{ + /// + /// Internal usage only. + /// + public enum ModelNodeState + { + /// + /// Model node has not been changed. + /// + None, + + /// + /// Model node is being processed. + /// + Processing, + + /// + /// Model node has been processed. + /// + Processed + } + + /// + /// Allows to adjust particular mode node processing behaviour. + /// + [Serializable] + [DataContract] + public class ModelNodeOptions + { + #region constructors + + public ModelNodeOptions() + { + RequireSelfProcessing = true; + } + + #endregion + + #region properties + + /// + /// Indicates of model node needs to be processed by model handler. + /// + + [DataMember] + public bool RequireSelfProcessing { get; set; } + + #endregion + + #region static + + + public static ModelNodeOptions New() + { + return new ModelNodeOptions(); + } + + #endregion + } + + public static class ModelNodeOptionsSyntax + { + public static ModelNodeOptions NoSelfProcessing(this ModelNodeOptions options) + { + options.RequireSelfProcessing = false; + + return options; + } + } + + /// + /// Base tree model node implementation. + /// + [Serializable] + [DataContract] + public class ModelNode + { + #region constructors + + public ModelNode() + { + + ChildModels = new Collection(); + Options = new ModelNodeOptions(); + + PropertyBag = new List(); + NonPersistentPropertyBag = new List(); + + InitDataMemberIgnorableProperties(); + } + + private void InitDataMemberIgnorableProperties() + { + TraceService = ServiceContainer.Instance.GetService(); + + ModelEvents = new Dictionary>(); + ModelContextEvents = new Dictionary>(); + + NonPersistentPropertyBag = new List(); + } + + #endregion + + #region properties + + #region properties + + [XmlIgnore] + [IgnoreDataMember] + public string ObjectType + { + get { return GetType().Name; } + set + { + + } + } + + #endregion + + /// + /// Allows to adjust particular mode node processing behaviour. + /// + [DataMember] + public ModelNodeOptions Options { get; set; } + + /// + /// A property bag to be used for any 'custom' properties attached to ModelNode. + /// + [DataMember] + + public List PropertyBag { get; set; } + + [IgnoreDataMember] + public List NonPersistentPropertyBag { get; set; } + + [DataMember] + public DefinitionBase Value { get; set; } + + [DataMember] + public Collection ChildModels { get; set; } + + [XmlIgnore] + [IgnoreDataMember] + public Dictionary> ModelEvents { get; set; } + + [XmlIgnore] + [IgnoreDataMember] + public Dictionary> ModelContextEvents { get; set; } + + [XmlIgnore] + [IgnoreDataMember] + public ModelNodeState State { get; set; } + + [XmlIgnore] + [NonSerialized] + [IgnoreDataMember] + protected TraceServiceBase TraceService; + + #endregion + + [OnDeserialized] + void OnDeserialized(StreamingContext context) + { + // https://github.com/SubPointSolutions/spmeta2/issues/697 + // serialization would set all [IgnoreDataMember] as nulls + // so we need to sestore them to normal state as we would go in constructor + + InitDataMemberIgnorableProperties(); + } + + #region events support + + public delegate void TmpAction(object arg1, object arg2); + + public virtual void InvokeOnModelContextEvents(object sender, ModelEventArgs eventArgs) + { + var objectType = typeof(object); + var eventType = eventArgs.EventType; + + // type.. can be null, so? + var spObjectType = eventArgs.ObjectType; + + if (!ModelContextEvents.ContainsKey(eventType)) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Cannot find ModelContextEvents for eventType: [{0}]", eventType); + return; + } + else + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Calling ModelContextEvents for eventType: [{0}]", eventType); + } + + var targetEvents = ModelContextEvents[eventType]; + + // yea, yea.. + foreach (MulticastDelegate action in targetEvents) + { + var modelContextType = typeof(OnCreatingContext<,>); + + var nonDefinition = new Type[] { spObjectType, typeof(DefinitionBase) }; + var withDefinition = new Type[] { spObjectType, eventArgs.ObjectDefinition.GetType() }; + var nonObjectDefinition = new Type[] { objectType, typeof(DefinitionBase) }; + var withObjectDefinition = new Type[] { objectType, eventArgs.ObjectDefinition.GetType() }; + + var modelNonDefInstanceType = modelContextType.MakeGenericType(nonDefinition); + var modelWithDefInstanceType = modelContextType.MakeGenericType(withDefinition); + var modelNonObjectDefInstanceType = modelContextType.MakeGenericType(nonObjectDefinition); + var modelWithObjectDefInstanceType = modelContextType.MakeGenericType(withObjectDefinition); + + object modelContextInstance = null; + + if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelNonDefInstanceType)) + { + modelContextInstance = Activator.CreateInstance(modelNonDefInstanceType); + } + else if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelWithDefInstanceType)) + { + modelContextInstance = Activator.CreateInstance(modelWithDefInstanceType); + } + else if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelNonObjectDefInstanceType)) + { + modelContextInstance = Activator.CreateInstance(modelNonObjectDefInstanceType); + } + else if (action.Method.GetParameters()[0].ParameterType.IsAssignableFrom(modelWithObjectDefInstanceType)) + { + modelContextInstance = Activator.CreateInstance(modelWithObjectDefInstanceType); + } + + if (modelContextInstance == null) + { + TraceService.ErrorFormat((int)LogEventId.ModelTreeModelContextEventIsNull, + "Cannot find model content instance for method: [{0}]. Throwing SPMeta2Exception.", action.Method); + + throw new SPMeta2Exception("Cannot find a proper ModelContextEvents overload"); + } + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [Model]: [{0}]", eventArgs.Model); + SetProperty(modelContextInstance, "Model", eventArgs.Model); + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [CurrentModelNode]: [{0}]", eventArgs.CurrentModelNode); + SetProperty(modelContextInstance, "CurrentModelNode", eventArgs.CurrentModelNode); + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [Object]: [{0}]", eventArgs.Object); + SetProperty(modelContextInstance, "Object", eventArgs.Object); + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [ObjectDefinition]: [{0}]", eventArgs.ObjectDefinition); + SetProperty(modelContextInstance, "ObjectDefinition", eventArgs.ObjectDefinition); + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Setting property: [ModelHost]: [{0}]", eventArgs.ModelHost); + SetProperty(modelContextInstance, "ModelHost", eventArgs.ModelHost); + + TraceService.Verbose((int)LogEventId.CoreCalls, "Invoking event."); + action.DynamicInvoke(modelContextInstance); + } + } + + private static void SetProperty(object obj, string propName, object propValue) + { + var propertyInfo = obj.GetType().GetProperty(propName); + propertyInfo.SetValue(obj, propValue, null); + } + + public virtual void InvokeOnModelEvents(object rawObject, ModelEventType eventType) + { + if (!ModelEvents.ContainsKey(eventType)) return; + + var targetEvents = ModelEvents[eventType]; + + // yeap, shity yet + foreach (MulticastDelegate action in targetEvents) + action.DynamicInvoke(Value, rawObject); + } + + public virtual void RegisterModelUpdateEvents( + Action onUpdating, Action onUpdated) + { + RegisterModelUpdatingEvent(onUpdating); + RegisterModelUpdatedEvent(onUpdated); + } + + public virtual void RegisterModelUpdatingEvent(Action action) + { + RegisterModelEvent(ModelEventType.OnUpdating, action); + } + + public virtual void RegisterModelUpdatedEvent(Action action) + { + RegisterModelEvent(ModelEventType.OnUpdated, action); + } + + public virtual void RegisterModelEvent(ModelEventType actionType, Action action) + { + if (action == null) return; + + if (!ModelEvents.ContainsKey(actionType)) + ModelEvents.Add(actionType, new List()); + + ModelEvents[actionType].Add(action); + } + + public virtual void RegisterModelContextEvent( + ModelEventType actionType, + Action> action) + where TDefinitionType : DefinitionBase + { + if (action == null) return; + + if (!ModelContextEvents.ContainsKey(actionType)) + ModelContextEvents.Add(actionType, new List()); + + ModelContextEvents[actionType].Add(action); + } + + #endregion + + #region methods + + public override string ToString() + { + return Value != null + ? string.Format("Node value: [{0}] - {1}", Value.GetType().Name, Value) + : base.ToString(); + } + + #endregion + } + + /// + /// Internal usage only. + /// Indicates the strategy for the provision exception handling. + /// + public enum ContinuationOptions + { + /// + /// Throw an exception + /// + StopAndThrowException, + + /// + /// Silently continue. + /// + Continue, + + /// + /// Silently stop. + /// + Stop, + } + + /// + /// Model creaeting/creating context. + /// + /// + /// + public class OnCreatingContext + where TDefinitionType : DefinitionBase + { + /// + /// Typed SharePoint object instance. + /// + public TObjectType Object { get; set; } + + /// + /// Current model definition. + /// + public TDefinitionType ObjectDefinition { get; set; } + + /// + /// Current model, the root node. + /// + public ModelNode Model { get; set; } + + + /// + /// Current model host. + /// + public object ModelHost { get; set; } + + /// + /// Current model node. + /// + public ModelNode CurrentModelNode { get; set; } + + /// + /// Exception handling options. + /// + public ContinuationOptions ContinuationOption { get; set; } + +#if !NET35 + + /// + /// Aggregated exception, if any. + /// + public AggregateException Error { get; set; } + +#endif + } +} diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs index 06b9cf13b..a6aa26190 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using SPMeta2.Models; +using SPMeta2.Utils; namespace SPMeta2.Services.Impl { @@ -12,9 +13,15 @@ public class DefaultIncrementalModelPrettyPrintService : DefaultModelPrettyPrint protected override string GetCurrentIntent(ModelNode modelNode, string currentIndent) { - var shouldDeploy = modelNode.Options.RequireSelfProcessing; + bool? shouldDeploy = false; - if (shouldDeploy) + var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag + .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + + if (incrementalRequireSelfProcessingValue != null) + shouldDeploy = ConvertUtils.ToBoolWithDefault(incrementalRequireSelfProcessingValue.Value, false); + + if (shouldDeploy.Value) return string.Format("[+] {0}", currentIndent); return string.Format("[-] {0}", currentIndent); diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index c62a5d973..b81519101 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -115,8 +115,13 @@ protected virtual string GetDefinitionFullPath(bool asHash) return result; } - protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNode) + protected override void OnBeforeDeployModelNode(object modelHost, ModelNode modelNode) { + // temporary measure + // we need to restoreoriginal value of .RequireSelfProcessing to avoid any model changes + // set 'ProcessedRequireSelfProcessingValue' in property bag for the further + OriginalRequireSelfProcessingValue = modelNode.Options.RequireSelfProcessing; + // lookup node and definition in model state // mark as modelNode.Options.RequireSelfProcessing true/false based on state @@ -200,8 +205,29 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod } - protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode) + protected override void OnAfterDeployModelNode(object modelHost, ModelNode modelNode) { + var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag + .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + + if (incrementalRequireSelfProcessingValue == null) + { + incrementalRequireSelfProcessingValue = new PropertyBagValue + { + Name = "_sys.IncrementalRequireSelfProcessingValue", + Value = modelNode.Options.RequireSelfProcessing.ToString() + }; + + modelNode.NonPersistentPropertyBag.Add(incrementalRequireSelfProcessingValue); + } + else + { + incrementalRequireSelfProcessingValue.Value = modelNode.Options.RequireSelfProcessing.ToString(); + } + + // restore model state + modelNode.Options.RequireSelfProcessing = OriginalRequireSelfProcessingValue; + var currentModelNode = modelNode; var currentDefinition = modelNode.Value; @@ -233,6 +259,11 @@ protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode }); } + protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNode) + { + CurrentModelHash = new ModelHash(); + } + protected virtual ModelHash GetPreviousModelHash() { if (PreviousModelHash != null) @@ -245,5 +276,7 @@ protected virtual ModelHash GetPreviousModelHash() } #endregion + + public bool OriginalRequireSelfProcessingValue { get; set; } } } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs index 1d8c85e09..9706b4edf 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs @@ -52,10 +52,24 @@ protected virtual void OnAfterDeployModel(object modelHost, ModelNode modelNode) } + + protected virtual void OnBeforeDeployModelNode(object modelHost, ModelNode modelNode) + { + + } + + protected virtual void OnAfterDeployModelNode(object modelHost, ModelNode modelNode) + { + + } + public override void Traverse(object modelHost, ModelNode modelNode) { try { + if (CurrentModelPath.Count == 0) + OnBeforeDeployModel(modelHost, modelNode); + CurrentModelPath.Push(modelNode); var modelDefinition = modelNode.Value as DefinitionBase; @@ -73,7 +87,7 @@ public override void Traverse(object modelHost, ModelNode modelNode) if (OnModelProcessing != null) OnModelProcessing(modelNode); - OnBeforeDeployModel(modelHost, modelNode); + OnBeforeDeployModelNode(modelHost, modelNode); //var requireselfProcessing = modelDefinition.RequireSelfProcessing || modelNode.Options.RequireSelfProcessing; var requireselfProcessing = modelNode.Options.RequireSelfProcessing; @@ -112,7 +126,7 @@ public override void Traverse(object modelHost, ModelNode modelNode) if (OnModelProcessed != null) OnModelProcessed(modelNode); - OnAfterDeployModel(modelHost, modelNode); + OnAfterDeployModelNode(modelHost, modelNode); var childModelTypes = GetSortedChildModelTypes(modelNode); @@ -195,6 +209,9 @@ public override void Traverse(object modelHost, ModelNode modelNode) finally { CurrentModelPath.Pop(); + + if (CurrentModelPath.Count == 0) + OnAfterDeployModel(modelHost, modelNode); } } From fc17cbf0e43a984540b0b7162334953a3bcc0874 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 04:59:27 +0000 Subject: [PATCH 13/53] + Implement 'incremental' provision support #553 + Persistence storage base service + Persistence storage 'file system' implementation, tests --- .../Impl/Services/ProvisionServiceTests.cs | 106 ++++++++++++++--- .../SSOM/SSOMTokenReplacementServiceTests.cs | 19 +-- .../Base/SPMeta2RegresionScenarioTestBase.cs | 3 +- ...ncrementalModelTreeTraverseServiceTests.cs | 23 +++- .../Common/IncrementalProvisionConfig.cs | 7 ++ SPMeta2/SPMeta2/Common/ModelHash.cs | 18 +++ SPMeta2/SPMeta2/SPMeta2.csproj | 2 + .../DefaultFileSystemPersistenceStorage.cs | 66 +++++++++++ ...aultIncrementalModelTreeTraverseService.cs | 108 +++++++++++++++++- .../Impl/DefaultModelTreeTraverseService.cs | 3 +- ...crementalProvisionServiceBaseExtensions.cs | 2 + .../Services/PersistenceStorageServiceBase.cs | 18 +++ 12 files changed, 338 insertions(+), 37 deletions(-) create mode 100644 SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs create mode 100644 SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index 7ebda6837..1ba85cef0 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -1,28 +1,25 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; +using System.Collections.Generic; using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using Microsoft.SharePoint; -using Microsoft.SharePoint.Taxonomy; using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.Common; using SPMeta2.CSOM.Services; -using SPMeta2.CSOM.Standard.ModelHandlers.Fields; using SPMeta2.CSOM.Standard.Services; +using SPMeta2.Interfaces; using SPMeta2.ModelHandlers; -using SPMeta2.Models; using SPMeta2.Services; using SPMeta2.SSOM.Services; using SPMeta2.SSOM.Standard.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Standard.Syntax; -using SPMeta2.Syntax.Default; using SPMeta2.Utils; -using SPMeta2.Interfaces; +using SPMeta2.Containers.CSOM; +using SPMeta2.Services.Impl; +using SPMeta2.Syntax.Default; +using SPMeta2.Containers.O365; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Exceptions; +using System; -namespace SPMeta2.Regression.Impl.Tests +namespace SPMeta2.Regression.Impl.Tests.Impl.Services { [TestClass] public class ModelHandlersTest @@ -149,7 +146,7 @@ public void EnsureStandardSSOMModelHandlers() [TestMethod] [TestCategory("Regression.Impl.IncrementalProvisionService")] [TestCategory("CI.Core")] - public void Can_Create_IncrementaProvisionServices() + public void Can_Create_IncrementalProvisionServices() { var services = new List(); @@ -171,7 +168,7 @@ public void Can_Create_IncrementaProvisionServices() [TestMethod] [TestCategory("Regression.Impl.IncrementalProvisionService")] [TestCategory("CI.Core")] - public void Can_Create_IncrementaProvisionServices_With_FluentAPI() + public void Can_Create_IncrementalProvisionServices_With_FluentAPI() { var services = new List(); @@ -191,6 +188,81 @@ public void Can_Create_IncrementaProvisionServices_With_FluentAPI() } } + + + #endregion + + #region persistence storage + + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] + [TestCategory("CI.Core")] + [ExpectedException(typeof(SPMeta2Exception))] + public void Can_Provision_Incrementally_With_NoIncrementalModelId() + { + var provisionRunner = new O365ProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.PersistenceStorages.Add(new DefaultFileSystemPersistenceStorage()); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + provisionRunner.SiteUrls.ForEach(siteUrl => + { + var model = SPMeta2Model.NewSiteModel(site => { }); + + provisionRunner.WithO365Context(siteUrl, context => + { + provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + }); + }); + } + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] + [TestCategory("CI.Core")] + public void Can_Provision_Incrementally_With_FileSystemStorage() + { + var provisionRunner = new O365ProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.PersistenceStorages.Add(new DefaultFileSystemPersistenceStorage()); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + provisionRunner.SiteUrls.ForEach(siteUrl => + { + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + var incrementalRequireSelfProcessingValue = model.NonPersistentPropertyBag + .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + + if (incrementalRequireSelfProcessingValue == null) + { + incrementalRequireSelfProcessingValue = new PropertyBagValue + { + Name = "_sys.IncrementalProvision.PersistenceStorageModelId", + Value = incrementalModelId + }; + + model.PropertyBag.Add(incrementalRequireSelfProcessingValue); + } + + provisionRunner.WithO365Context(siteUrl, context => + { + provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + }); + }); + } + #endregion } } diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SSOM/SSOMTokenReplacementServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SSOM/SSOMTokenReplacementServiceTests.cs index 1aa171ed8..7c09852bd 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SSOM/SSOMTokenReplacementServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SSOM/SSOMTokenReplacementServiceTests.cs @@ -1,23 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.CSOM.Services; -using SPMeta2.Services; -using System.Reflection; -using Microsoft.SharePoint; -using Microsoft.SharePoint.Client; -using SPMeta2.Containers.CSOM; -using SPMeta2.Containers.Services; -using SPMeta2.CSOM.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; using SPMeta2.Containers.SSOM; using SPMeta2.Regression.Impl.Tests.Impl.Services.Base; +using SPMeta2.Services; using SPMeta2.SSOM.Services; -namespace SPMeta2.Regression.Impl.Tests.Impl.Services +namespace SPMeta2.Regression.Impl.Tests.Impl.Services.SSOM { [TestClass] diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs index 601da6f64..b14f1bb14 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs @@ -32,7 +32,8 @@ public SPMeta2RegresionScenarioTestBase() { RegressionService.BeforeProvisionRunnerExcecution += (runner) => { - runner.ProvisionService.SetIncrementalProvisionMode(); + var config = new IncrementalProvisionConfig(); + runner.ProvisionService.SetIncrementalProvisionMode(config); runner.OnBeforeDeployModel += (provisionService, model) => { diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs index ab87598f9..06b200d67 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs @@ -10,6 +10,7 @@ using SPMeta2.Services.Impl; using SPMeta2.Syntax.Default; using System.Collections.Generic; +using System.Text; using SPMeta2.Extensions; using SPMeta2.Regression.Utils; using SPMeta2.Containers.Services.Rnd; @@ -21,7 +22,7 @@ namespace SPMeta2.Regression.Tests.Impl.Services { - + [TestClass] public class IncrementalModelTreeTraverseServiceTests @@ -206,6 +207,24 @@ public void Incremental_Update_AllDefinitions_As_RandomModels() secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; secondProvisionService.Traverse(null, currentModel); + // trace size of the model hash + amount if the aritfacts + var modelNodesCount = 0; + model.WithNodesOfType(n => { modelNodesCount++; }); + + var serializer = ServiceContainer.Instance.GetService(); + serializer.RegisterKnownTypes(new[] + { + typeof(ModelHash), + typeof(ModelNodeHash) + }); + + var data = Encoding.UTF8.GetBytes(serializer.Serialize(firstProvisionService.CurrentModelHash)); + + var persistanceFileService = new DefaultFileSystemPersistenceStorage(); + persistanceFileService.SaveObject( + string.Format("incremental_state_m2.regression-artifact-{1}-{0}", definitionType.Name, modelNodesCount), + data); + RegressionUtils.WriteLine(string.Empty); RegressionUtils.WriteLine("Provisioned model:"); RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); @@ -278,6 +297,8 @@ public void Incremental_Update_NonSingleton_ModelNodes_PlusRandomModelNodes() #endregion + + #region utils protected ModelNode GetVeryRandomModel(Type definitionType, SPObjectModelType spObjectModelType) diff --git a/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs b/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs index c84156862..178f56006 100644 --- a/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs +++ b/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs @@ -3,9 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using SPMeta2.Services; namespace SPMeta2.Common { + + + public class IncrementalProvisionConfig { #region constructors @@ -13,6 +17,7 @@ public class IncrementalProvisionConfig public IncrementalProvisionConfig() { PreviousModelHash = new ModelHash(); + PersistenceStorages = new List(); } #endregion @@ -22,6 +27,8 @@ public IncrementalProvisionConfig() public Type CustomModelTreeTraverseServiceType { get; set; } + public List PersistenceStorages { get; set; } + #endregion public static IncrementalProvisionConfig Default diff --git a/SPMeta2/SPMeta2/Common/ModelHash.cs b/SPMeta2/SPMeta2/Common/ModelHash.cs index 312184326..67368f5bc 100644 --- a/SPMeta2/SPMeta2/Common/ModelHash.cs +++ b/SPMeta2/SPMeta2/Common/ModelHash.cs @@ -31,6 +31,15 @@ public ModelHash() public List ModelNodes { get; set; } #endregion + + #region override + + public override string ToString() + { + return string.Format("Model hash:[{0}] nodes count:[{1}]", Hash, ModelNodes.Count); + } + + #endregion } @@ -56,6 +65,15 @@ public class ModelNodeHash public string DefinitionIdentityKeyHash { get; set; } #endregion + + #region override + + public override string ToString() + { + return string.Format("Identity key:[{0}] Definition hash:[{1}]", DefinitionIdentityKey, DefinitionHash); + } + + #endregion } //[DataContract] diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index 8921aaa3e..f9093eed5 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -362,6 +362,7 @@ + @@ -399,6 +400,7 @@ + diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs new file mode 100644 index 000000000..199a7e634 --- /dev/null +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SPMeta2.Services.Impl +{ + public class DefaultFileSystemPersistenceStorage : PersistenceStorageServiceBase + { + #region constructors + + public DefaultFileSystemPersistenceStorage() + : this(DefaultFolderPath) + { + + } + + public DefaultFileSystemPersistenceStorage(string folderPath) + { + CurrentFolderPath = folderPath; + } + + #endregion + + #region static + + static DefaultFileSystemPersistenceStorage() + { + var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SPMeta2"); + DefaultFolderPath = path; + } + + public static string DefaultFolderPath { get; set; } + public string CurrentFolderPath { get; set; } + + #endregion + + #region methods + + public override byte[] LoadObject(string objectId) + { + var fileName = string.Format("{0}.state", objectId); + var filePath = Path.Combine(CurrentFolderPath, fileName); + + if (File.Exists(filePath)) + return File.ReadAllBytes(filePath); + + return null; + } + + public override void SaveObject(string objectId, byte[] data) + { + Directory.CreateDirectory(CurrentFolderPath); + + var fileName = string.Format("{0}.state", objectId); + var filePath = Path.Combine(CurrentFolderPath, fileName); + + File.WriteAllBytes(filePath, data); + } + #endregion + + + } +} diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index b81519101..8da895974 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -8,6 +8,7 @@ using SPMeta2.Exceptions; using SPMeta2.Models; using SPMeta2.Utils; +using SPMeta2.Syntax.Default; namespace SPMeta2.Services.Impl { @@ -30,6 +31,8 @@ public DefaultIncrementalModelTreeTraverseService() #region properties + public IncrementalProvisionConfig Configuration { get; set; } + public ModelHash PreviousModelHash { get; set; } public ModelHash CurrentModelHash { get; private set; } @@ -261,7 +264,110 @@ protected override void OnAfterDeployModelNode(object modelHost, ModelNode model protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNode) { + base.OnBeforeDeployModel(modelHost, modelNode); + + // clean up current model hash CurrentModelHash = new ModelHash(); + + // restore previous one + if (Configuration != null && Configuration.PersistenceStorages.Count() > 0) + { + TraceService.Information(0, "Model hash restore: found [{0}] storage impl in Configuration.PersistenceStorages. Automatic model hash management is used"); + + var modelIdProperty = modelNode.PropertyBag.FirstOrDefault(p => p.Name == "_sys.IncrementalProvision.PersistenceStorageModelId"); + + if (modelIdProperty == null) + throw new SPMeta2Exception("IncrementalProvisionModelId is not set. Either clean PersistenceStorages and handle model hash persistence manually or set .PersistenceStorageModelId"); + + var modelId = modelIdProperty.Value; + var objectId = string.Format("incremental_state_{0}", modelId); + + var serializer = ServiceContainer.Instance.GetService(); + serializer.RegisterKnownTypes(new[] + { + typeof(ModelHash), + typeof(ModelNodeHash) + }); + + foreach (var storage in Configuration.PersistenceStorages) + { + TraceService.Information(0, string.Format("Restoring model hash with object id:[{0}] using storage impl [{1}]", + objectId, storage.GetType())); + + var data = storage.LoadObject(objectId); + + if (data != null) + { + var dataString = Encoding.UTF8.GetString(data); + var dataObject = serializer.Deserialize(typeof(ModelHash), dataString) as ModelHash; + + if (dataObject != null) + { + PreviousModelHash = dataObject; + + TraceService.Information(0, string.Format("Restored model hash with object id:[{0}] using storage impl [{1}]", + objectId, storage.GetType())); + break; + } + } + else + { + TraceService.Information(0, string.Format("Restored model hash with object id:[{0}] using storage impl [{1}]", + objectId, storage.GetType())); + } + } + + TraceService.Information(0, string.Format("Coudn't restore model hash with object id:[{0}]. Either first provision is user or storage is wrong.", objectId)); + } + else + { + TraceService.Information(0, "Model hash restore: can't find any persistence storage impl in Configuration.PersistenceStorages. Assuming manual model hash management is used"); + } + } + + protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode) + { + base.OnAfterDeployModel(modelHost, modelNode); + + // save model hash to a persistan storages + if (Configuration != null && Configuration.PersistenceStorages.Count() > 0) + { + TraceService.Information(0, "Model hash save: found [{0}] storage impl in Configuration.PersistenceStorages. Automatic model hash management is used"); + + var modelIdProperty = + modelNode.PropertyBag.FirstOrDefault( + p => p.Name == "_sys.IncrementalProvision.PersistenceStorageModelId"); + + if (modelIdProperty == null) + throw new SPMeta2Exception( + "IncrementalProvisionModelId is not set. Either clean PersistenceStorages and handle model hash persistence manually or set .PersistenceStorageModelId"); + + var modelId = modelIdProperty.Value; + + var objectId = string.Format("incremental_state_{0}", modelId); + + var serializer = ServiceContainer.Instance.GetService(); + serializer.RegisterKnownTypes(new[] + { + typeof(ModelHash), + typeof(ModelNodeHash) + }); + + var data = Encoding.UTF8.GetBytes(serializer.Serialize(CurrentModelHash)); + + foreach (var storage in Configuration.PersistenceStorages) + { + TraceService.Information(0, string.Format("Saving model hash with object id:[{0}] using storage impl [{1}]. Size:[{2}] bytes", + objectId, storage.GetType(), data.LongLength)); + + + storage.SaveObject(objectId, data); + } + } + else + { + TraceService.Information(0, "Model hash save: can't find any persistence storage impl in Configuration.PersistenceStorages. Assuming manual model hash management is used"); + } } protected virtual ModelHash GetPreviousModelHash() @@ -277,6 +383,6 @@ protected virtual ModelHash GetPreviousModelHash() #endregion - public bool OriginalRequireSelfProcessingValue { get; set; } + protected bool OriginalRequireSelfProcessingValue { get; set; } } } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs index 9706b4edf..010b66e37 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs @@ -208,7 +208,8 @@ public override void Traverse(object modelHost, ModelNode modelNode) } finally { - CurrentModelPath.Pop(); + if (CurrentModelPath.Count != 0) + CurrentModelPath.Pop(); if (CurrentModelPath.Count == 0) OnAfterDeployModel(modelHost, modelNode); diff --git a/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs index 72d9789ba..321aa9f68 100644 --- a/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs +++ b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs @@ -51,6 +51,8 @@ public static ProvisionServiceBase SetIncrementalProvisionMode(this ProvisionSer var typedModelService = service.ModelTraverseService as DefaultIncrementalModelTreeTraverseService; typedModelService.PreviousModelHash = config.PreviousModelHash ?? new ModelHash(); + typedModelService.Configuration = config; + return service; } diff --git a/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs b/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs new file mode 100644 index 000000000..a19b86ae2 --- /dev/null +++ b/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SPMeta2.Services +{ + public abstract class PersistenceStorageServiceBase + { + #region methods + + public abstract byte[] LoadObject(string objectId); + public abstract void SaveObject(string objectId, byte[] data); + + #endregion + } +} From 85ff65a832180b06e90a43a0985ff801236796d7 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 05:18:52 +0000 Subject: [PATCH 14/53] + build fix --- .../Services/Impl/DefaultFileSystemPersistenceStorage.cs | 2 +- SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs index 199a7e634..6b68beb30 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultFileSystemPersistenceStorage.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Services.Impl { diff --git a/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs b/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs index a19b86ae2..040743bfa 100644 --- a/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Services { From d6439feac2ede564c59f1ba5cfd9c8993dbeac27 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 05:48:57 +0000 Subject: [PATCH 15/53] + Implement 'incremental' provision support #553 + Persistence storage base service + Persistence storage 'file system' implementation, tests + Persistence storage CSOM - DefaultCSOMWebPropertyBagStorage --- SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj | 1 + .../Impl/DefaultCSOMWebPropertyBagStorage.cs | 78 +++++++++++++++++++ .../Impl/Services/ProvisionServiceTests.cs | 48 +++++++++--- .../SPMeta2/Extensions/ModelNodeExtensions.cs | 27 +++++++ ...aultIncrementalModelTreeTraverseService.cs | 10 ++- 5 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs diff --git a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj index 196935976..65a800580 100644 --- a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj +++ b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj @@ -287,6 +287,7 @@ + diff --git a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs new file mode 100644 index 000000000..2f6b88f47 --- /dev/null +++ b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.SharePoint.Client; +using SPMeta2.CSOM.Extensions; +using SPMeta2.Services; +using SPMeta2.Services.Impl; +using SPMeta2.Utils; + +namespace SPMeta2.CSOM.Services.Impl +{ + public class DefaultCSOMWebPropertyBagStorage : PersistenceStorageServiceBase + { + #region constructors + + public DefaultCSOMWebPropertyBagStorage(Web web) + { + // follow CSOM PropertyModelHandler implementation + // codebase is better be merged later + + CurrentWeb = web; + CurrentContext = web.Context; + } + + #endregion + + #region properties + + protected Web CurrentWeb { get; private set; } + protected ClientRuntimeContext CurrentContext { get; private set; } + + #endregion + + + #region methods + + protected PropertyValues ExtractProperties() + { + var result = CurrentWeb.AllProperties; + + CurrentContext.Load(result); + CurrentContext.ExecuteQueryWithTrace(); + + return result; + } + + public override byte[] LoadObject(string objectId) + { + var key = objectId; + + var properties = ExtractProperties(); + var currentValue = properties.FieldValues.ContainsKey(key) ? properties[key] : null; + + var dataString = ConvertUtils.ToString(currentValue); + + if (!string.IsNullOrEmpty(dataString)) + return Encoding.UTF8.GetBytes(dataString); + + return null; + } + + public override void SaveObject(string objectId, byte[] data) + { + var key = objectId; + + var properties = ExtractProperties(); + var dataString = Encoding.UTF8.GetString(data); + + properties[key] = dataString; + + CurrentWeb.Update(); + CurrentContext.ExecuteQueryWithTrace(); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index 1ba85cef0..01d6702a1 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -18,6 +18,8 @@ using SPMeta2.Definitions; using SPMeta2.Exceptions; using System; +using SPMeta2.CSOM.Services.Impl; +using SPMeta2.Extensions; namespace SPMeta2.Regression.Impl.Tests.Impl.Services { @@ -242,23 +244,47 @@ public void Can_Provision_Incrementally_With_FileSystemStorage() }); - var incrementalRequireSelfProcessingValue = model.NonPersistentPropertyBag - .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + model.SetIncrementalProvisionModelId(incrementalModelId); - if (incrementalRequireSelfProcessingValue == null) + provisionRunner.WithO365Context(siteUrl, context => { - incrementalRequireSelfProcessingValue = new PropertyBagValue - { - Name = "_sys.IncrementalProvision.PersistenceStorageModelId", - Value = incrementalModelId - }; + provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + }); + }); + } - model.PropertyBag.Add(incrementalRequireSelfProcessingValue); - } + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] + [TestCategory("CI.Core")] + public void Can_Provision_Incrementally_With_CSOMWebPropertyBagStorage() + { + var provisionRunner = new O365ProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + provisionRunner.SiteUrls.ForEach(siteUrl => + { provisionRunner.WithO365Context(siteUrl, context => { - provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.PersistenceStorages.Add( + new DefaultCSOMWebPropertyBagStorage(context.Web)); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + + provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + } }); }); } diff --git a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs index 48539e7ad..0331b4b12 100644 --- a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs +++ b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs @@ -5,6 +5,7 @@ using SPMeta2.Definitions; using SPMeta2.Models; using SPMeta2.Services; +using SPMeta2.Syntax.Default; namespace SPMeta2.Extensions { @@ -234,5 +235,31 @@ public static ModelValidationResultSet Validate(this M } #endregion + + #region incremental provision + + + public static TModelNode SetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) + where TModelNode : ModelNode + { + var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag + .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + + if (incrementalRequireSelfProcessingValue == null) + { + incrementalRequireSelfProcessingValue = new PropertyBagValue + { + Name = "_sys.IncrementalProvision.PersistenceStorageModelId", + Value = modelId + }; + + modelNode.PropertyBag.Add(incrementalRequireSelfProcessingValue); + } + + incrementalRequireSelfProcessingValue.Value = modelId; + + return modelNode; + } + #endregion } } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index 8da895974..99f59a458 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -25,6 +25,8 @@ public DefaultIncrementalModelTreeTraverseService() DefaultDefinitionFullPathSeparator = "/"; DefaultDefinitionIdentityKeySeparator = ";"; + + DefaultPersistenceModelIdPrefix = "spmeta2.incremental_state"; } #endregion @@ -43,6 +45,9 @@ public DefaultIncrementalModelTreeTraverseService() protected string DefaultDefinitionFullPathSeparator { get; set; } protected string DefaultDefinitionIdentityKeySeparator { get; set; } + public string DefaultPersistenceModelIdPrefix { get; set; } + + #endregion #region methods @@ -280,7 +285,7 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod throw new SPMeta2Exception("IncrementalProvisionModelId is not set. Either clean PersistenceStorages and handle model hash persistence manually or set .PersistenceStorageModelId"); var modelId = modelIdProperty.Value; - var objectId = string.Format("incremental_state_{0}", modelId); + var objectId = string.Format("{0}.{1}", DefaultPersistenceModelIdPrefix, modelId); var serializer = ServiceContainer.Instance.GetService(); serializer.RegisterKnownTypes(new[] @@ -343,8 +348,7 @@ protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode "IncrementalProvisionModelId is not set. Either clean PersistenceStorages and handle model hash persistence manually or set .PersistenceStorageModelId"); var modelId = modelIdProperty.Value; - - var objectId = string.Format("incremental_state_{0}", modelId); + var objectId = string.Format("{0}.{1}", DefaultPersistenceModelIdPrefix, modelId); var serializer = ServiceContainer.Instance.GetService(); serializer.RegisterKnownTypes(new[] From 0cdde490aa557a81311565129b771a80b00cad02 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 05:50:47 +0000 Subject: [PATCH 16/53] + ci build fix --- .../Impl/Services/ProvisionServiceTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index 01d6702a1..ebfe203e5 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -255,7 +255,7 @@ public void Can_Provision_Incrementally_With_FileSystemStorage() [TestMethod] [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] - [TestCategory("CI.Core")] + [TestCategory("CI.Core.O365")] public void Can_Provision_Incrementally_With_CSOMWebPropertyBagStorage() { var provisionRunner = new O365ProvisionRunner(); From 7aef4f8398895961e8bd1af9970ab5b5cbbf674c Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 06:16:45 +0000 Subject: [PATCH 17/53] + Implement 'incremental' provision support #553 + Persistence storage SSOM - DefaultSSOMWebPropertyBagStorage + Persistence storage SSOM - DefaultSSOMWebApplicationPropertyBagStorage + Persistence storage SSOM - DefaultSSOMFarmPropertyBagStorage --- .../Impl/Services/ProvisionServiceTests.cs | 83 +++++++++++++++++-- .../ModelHandlers/PropertyModelHandler.cs | 2 - SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj | 3 + .../Impl/DefaultSSOMFarmPropertyBagStorage.cs | 68 +++++++++++++++ ...ultSSOMWebApplicationPropertyBagStorage.cs | 68 +++++++++++++++ .../Impl/DefaultSSOMWebPropertyBagStorage.cs | 67 +++++++++++++++ .../SPMeta2/Extensions/ModelNodeExtensions.cs | 25 +++++- 7 files changed, 307 insertions(+), 9 deletions(-) create mode 100644 SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs create mode 100644 SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs create mode 100644 SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index ebfe203e5..5be6815d8 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -14,12 +14,13 @@ using SPMeta2.Services.Impl; using SPMeta2.Syntax.Default; using SPMeta2.Containers.O365; -using SPMeta2.CSOM.ModelHosts; using SPMeta2.Definitions; using SPMeta2.Exceptions; using System; +using SPMeta2.Containers.SSOM; using SPMeta2.CSOM.Services.Impl; using SPMeta2.Extensions; +using SPMeta2.SSOM.Services.Impl; namespace SPMeta2.Regression.Impl.Tests.Impl.Services { @@ -217,14 +218,14 @@ public void Can_Provision_Incrementally_With_NoIncrementalModelId() provisionRunner.WithO365Context(siteUrl, context => { - provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + provisionService.DeployModel(SPMeta2.CSOM.ModelHosts.SiteModelHost.FromClientContext(context), model); }); }); } [TestMethod] [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] - [TestCategory("CI.Core")] + [TestCategory("CI.Core.O365")] public void Can_Provision_Incrementally_With_FileSystemStorage() { var provisionRunner = new O365ProvisionRunner(); @@ -248,7 +249,7 @@ public void Can_Provision_Incrementally_With_FileSystemStorage() provisionRunner.WithO365Context(siteUrl, context => { - provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + provisionService.DeployModel(SPMeta2.CSOM.ModelHosts.SiteModelHost.FromClientContext(context), model); }); }); } @@ -283,7 +284,79 @@ public void Can_Provision_Incrementally_With_CSOMWebPropertyBagStorage() model.SetIncrementalProvisionModelId(incrementalModelId); - provisionService.DeployModel(SiteModelHost.FromClientContext(context), model); + provisionService.DeployModel(SPMeta2.CSOM.ModelHosts.SiteModelHost.FromClientContext(context), model); + } + }); + }); + } + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] + [TestCategory("CI.Core.SharePoint")] + public void Can_Provision_Incrementally_With_SSOMWebPropertyBagStorage() + { + var provisionRunner = new SSOMProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + provisionRunner.SiteUrls.ForEach(siteUrl => + { + provisionRunner.WithSSOMSiteAndWebContext((spSite, spWeb) => + { + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.PersistenceStorages.Add( + new DefaultSSOMWebPropertyBagStorage(spWeb)); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + + provisionService.DeployModel(SPMeta2.SSOM.ModelHosts.WebModelHost.FromWeb(spWeb), model); + } + }); + }); + } + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] + [TestCategory("CI.Core.SharePoint")] + public void Can_Provision_Incrementally_With_SSOMWebApplicationPropertyBagStorage() + { + var provisionRunner = new SSOMProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + provisionRunner.WebApplicationUrls.ForEach(url => + { + provisionRunner.WithSSOMWebApplicationContext(url, spWebApp => + { + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.PersistenceStorages.Add( + new DefaultSSOMWebApplicationPropertyBagStorage(spWebApp)); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + + provisionService.DeployModel(SPMeta2.SSOM.ModelHosts.WebApplicationModelHost.FromWebApplication(spWebApp), model); } }); }); diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/PropertyModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/PropertyModelHandler.cs index 8463ebf51..6bd1084e0 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/PropertyModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/PropertyModelHandler.cs @@ -137,7 +137,5 @@ protected virtual void DeployProperty(object modelHost, Hashtable properties, Pr } #endregion - - } } diff --git a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj index 6f32aee96..ca668fca8 100644 --- a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj +++ b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj @@ -343,6 +343,9 @@ True PublishingPageTemplates.resx + + + diff --git a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs new file mode 100644 index 000000000..e63fa3059 --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs @@ -0,0 +1,68 @@ +using SPMeta2.Services; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Security.Policy; +using System.Text; + +using Microsoft.SharePoint; +using Microsoft.SharePoint.Administration; +using SPMeta2.Utils; + +namespace SPMeta2.SSOM.Services.Impl +{ + public class DefaultSSOMFarmPropertyBagStorage : PersistenceStorageServiceBase + { + #region consturctors + + public DefaultSSOMFarmPropertyBagStorage(SPFarm farm) + { + CurrentFarm = farm; + } + + #endregion + + #region properties + + public SPFarm CurrentFarm { get; set; } + + #endregion + + #region methods + + protected Hashtable ExtractProperties() + { + return CurrentFarm.Properties; + } + + public override byte[] LoadObject(string objectId) + { + var key = objectId; + + var properties = ExtractProperties(); + var currentValue = properties[key]; + + var dataString = ConvertUtils.ToString(currentValue); + + if (!string.IsNullOrEmpty(dataString)) + return Encoding.UTF8.GetBytes(dataString); + + return null; + } + + public override void SaveObject(string objectId, byte[] data) + { + var key = objectId; + + var properties = ExtractProperties(); + var dataString = Encoding.UTF8.GetString(data); + + properties[key] = dataString; + + CurrentFarm.Update(); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs new file mode 100644 index 000000000..a8985daa0 --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs @@ -0,0 +1,68 @@ +using SPMeta2.Services; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Security.Policy; +using System.Text; + +using Microsoft.SharePoint; +using Microsoft.SharePoint.Administration; +using SPMeta2.Utils; + +namespace SPMeta2.SSOM.Services.Impl +{ + public class DefaultSSOMWebApplicationPropertyBagStorage : PersistenceStorageServiceBase + { + #region consturctors + + public DefaultSSOMWebApplicationPropertyBagStorage(SPWebApplication webApplication) + { + CurrentWebApplication = webApplication; + } + + #endregion + + #region properties + + public SPWebApplication CurrentWebApplication { get; set; } + + #endregion + + #region methods + + protected Hashtable ExtractProperties() + { + return CurrentWebApplication.Properties; + } + + public override byte[] LoadObject(string objectId) + { + var key = objectId; + + var properties = ExtractProperties(); + var currentValue = properties[key]; + + var dataString = ConvertUtils.ToString(currentValue); + + if (!string.IsNullOrEmpty(dataString)) + return Encoding.UTF8.GetBytes(dataString); + + return null; + } + + public override void SaveObject(string objectId, byte[] data) + { + var key = objectId; + + var properties = ExtractProperties(); + var dataString = Encoding.UTF8.GetString(data); + + properties[key] = dataString; + + CurrentWebApplication.Update(); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs new file mode 100644 index 000000000..ccd3efdfb --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs @@ -0,0 +1,67 @@ +using SPMeta2.Services; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Security.Policy; +using System.Text; + +using Microsoft.SharePoint; +using SPMeta2.Utils; + +namespace SPMeta2.SSOM.Services.Impl +{ + public class DefaultSSOMWebPropertyBagStorage : PersistenceStorageServiceBase + { + #region consturctors + + public DefaultSSOMWebPropertyBagStorage(SPWeb web) + { + CurrentWeb = web; + } + + #endregion + + #region properties + + public SPWeb CurrentWeb { get; set; } + + #endregion + + #region methods + + protected Hashtable ExtractProperties() + { + return CurrentWeb.AllProperties; + } + + public override byte[] LoadObject(string objectId) + { + var key = objectId; + + var properties = ExtractProperties(); + var currentValue = properties[key]; + + var dataString = ConvertUtils.ToString(currentValue); + + if (!string.IsNullOrEmpty(dataString)) + return Encoding.UTF8.GetBytes(dataString); + + return null; + } + + public override void SaveObject(string objectId, byte[] data) + { + var key = objectId; + + var properties = ExtractProperties(); + var dataString = Encoding.UTF8.GetString(data); + + properties[key] = dataString; + + CurrentWeb.Update(); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs index 0331b4b12..2b32e43f4 100644 --- a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs +++ b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs @@ -239,11 +239,11 @@ public static ModelValidationResultSet Validate(this M #region incremental provision - public static TModelNode SetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) + private static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) where TModelNode : ModelNode { var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag - .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); if (incrementalRequireSelfProcessingValue == null) { @@ -260,6 +260,27 @@ public static TModelNode SetIncrementalProvisionModelId(this TModelN return modelNode; } + + public static FarmModelNode SetIncrementalProvisionModelId(this FarmModelNode modelNode, string modelId) + { + return InternalSetIncrementalProvisionModelId(modelNode, modelId); + } + + public static WebApplicationModelNode SetIncrementalProvisionModelId(this WebApplicationModelNode modelNode, string modelId) + { + return InternalSetIncrementalProvisionModelId(modelNode, modelId); + } + + public static SiteModelNode SetIncrementalProvisionModelId(this SiteModelNode modelNode, string modelId) + { + return InternalSetIncrementalProvisionModelId(modelNode, modelId); + } + + public static WebModelNode SetIncrementalProvisionModelId(this WebModelNode modelNode, string modelId) + { + return InternalSetIncrementalProvisionModelId(modelNode, modelId); + } + #endregion } } From c4cfe0acac8240e913cac220078d7e6bd9835096 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 07:07:41 +0000 Subject: [PATCH 18/53] + Implement 'incremental' provision support #553 + Add option for persistence storage auto-detection --- .../Impl/DefaultCSOMWebPropertyBagStorage.cs | 50 +++++- .../Impl/Services/ProvisionServiceTests.cs | 168 ++++++++++++++++++ ...harePointPersistenceStorageServiceTests.cs | 62 +++++++ .../SPMeta2.Regression.Impl.Tests.csproj | 1 + .../Impl/DefaultSSOMFarmPropertyBagStorage.cs | 29 ++- ...ultSSOMWebApplicationPropertyBagStorage.cs | 30 +++- .../Impl/DefaultSSOMWebPropertyBagStorage.cs | 46 ++++- .../Common/IncrementalProvisionConfig.cs | 38 +++- ...aultIncrementalModelTreeTraverseService.cs | 32 +++- .../Services/PersistenceStorageServiceBase.cs | 6 + 10 files changed, 451 insertions(+), 11 deletions(-) create mode 100644 SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SharePointPersistenceStorageServiceTests.cs diff --git a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs index 2f6b88f47..60e554a0b 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultCSOMWebPropertyBagStorage.cs @@ -4,16 +4,24 @@ using System.Text; using Microsoft.SharePoint.Client; using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Exceptions; using SPMeta2.Services; using SPMeta2.Services.Impl; using SPMeta2.Utils; namespace SPMeta2.CSOM.Services.Impl { - public class DefaultCSOMWebPropertyBagStorage : PersistenceStorageServiceBase + public class DefaultCSOMWebPropertyBagStorage : SharePointPersistenceStorageServiceBase { #region constructors + public DefaultCSOMWebPropertyBagStorage() + { + + } + public DefaultCSOMWebPropertyBagStorage(Web web) { // follow CSOM PropertyModelHandler implementation @@ -30,6 +38,20 @@ public DefaultCSOMWebPropertyBagStorage(Web web) protected Web CurrentWeb { get; private set; } protected ClientRuntimeContext CurrentContext { get; private set; } + public override List TargetDefinitionTypes + { + get + { + var result = new List(); + + result.Add(typeof(SiteDefinition)); + result.Add(typeof(WebDefinition)); + + return result; + } + set { } + } + #endregion @@ -73,6 +95,32 @@ public override void SaveObject(string objectId, byte[] data) CurrentContext.ExecuteQueryWithTrace(); } + public override void InitialiseFromModelHost(object modelHost) + { + var csomModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + + if (csomModelHost is WebModelHost) + { + var webModelHost = csomModelHost as WebModelHost; + + this.CurrentWeb = webModelHost.HostWeb; + this.CurrentContext = webModelHost.HostWeb.Context; + } + else if (csomModelHost is SiteModelHost) + { + var webModelHost = csomModelHost as SiteModelHost; + + this.CurrentWeb = webModelHost.HostWeb; + this.CurrentContext = webModelHost.HostWeb.Context; + } + else + { + throw new SPMeta2Exception(string.Format("Unsuported model host type:[{0}]", modelHost.GetType())); + } + } + #endregion + + } } diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index 5be6815d8..38dfe1103 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -254,6 +254,8 @@ public void Can_Provision_Incrementally_With_FileSystemStorage() }); } + + [TestMethod] [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] [TestCategory("CI.Core.O365")] @@ -362,6 +364,172 @@ public void Can_Provision_Incrementally_With_SSOMWebApplicationPropertyBagStorag }); } + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage")] + [TestCategory("CI.Core.SharePoint")] + public void Can_Provision_Incrementally_With_SSOMFarmPropertyBagStorage() + { + var provisionRunner = new SSOMProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + provisionRunner.WithSSOMFarmContext(farm => + { + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.PersistenceStorages.Add(new DefaultSSOMFarmPropertyBagStorage(farm)); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + provisionService.DeployModel(SPMeta2.SSOM.ModelHosts.FarmModelHost.FromFarm(farm), model); + } + }); + } + + + #endregion + + #region storate auto detection + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage.AutoDetection")] + [TestCategory("CI.Core.O365")] + public void Can_Provision_Incrementally_With_AutoDetection_As_CSOM() + { + var provisionRunner = new O365ProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.AutoDetectSharePointPersistenceStorage = true; + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + provisionRunner.SiteUrls.ForEach(siteUrl => + { + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + provisionRunner.WithO365Context(siteUrl, context => + { + provisionService.DeployModel(SPMeta2.CSOM.ModelHosts.SiteModelHost.FromClientContext(context), model); + }); + }); + + provisionRunner.WebUrls.ForEach(siteUrl => + { + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + var model = SPMeta2Model.NewWebModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + provisionRunner.WithO365Context(siteUrl, context => + { + provisionService.DeployModel(SPMeta2.CSOM.ModelHosts.WebModelHost.FromClientContext(context), model); + }); + }); + } + + [TestMethod] + [TestCategory("Regression.Impl.IncrementalProvisionService.PersistenceStorage.AutoDetection")] + [TestCategory("CI.Core.SharePoint")] + public void Can_Provision_Incrementally_With_AutoDetection_As_SSOM() + { + var provisionRunner = new SSOMProvisionRunner(); + var provisionService = provisionRunner.ProvisionService; + + var incrementalModelId = "m2.regression." + Guid.NewGuid().ToString("N"); + + provisionRunner.WithSSOMFarmContext(farm => + { + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.AutoDetectSharePointPersistenceStorage = true; + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + + provisionService.DeployModel(SPMeta2.SSOM.ModelHosts.FarmModelHost.FromFarm(farm), model); + } + }); + + + provisionRunner.WebApplicationUrls.ForEach(url => + { + provisionRunner.WithSSOMWebApplicationContext(url, spWebApp => + { + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.AutoDetectSharePointPersistenceStorage = true; + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + + provisionService.DeployModel(SPMeta2.SSOM.ModelHosts.WebApplicationModelHost.FromWebApplication(spWebApp), model); + } + }); + }); + + provisionRunner.SiteUrls.ForEach(siteUrl => + { + provisionRunner.WithSSOMSiteAndWebContext((spSite, spWeb) => + { + for (var i = 0; i < 3; i++) + { + var incrementalProvisionConfig = new IncrementalProvisionConfig(); + incrementalProvisionConfig.AutoDetectSharePointPersistenceStorage = true; + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + + var model = SPMeta2Model.NewSiteModel(site => + { + + }); + + model.SetIncrementalProvisionModelId(incrementalModelId); + + + provisionService.DeployModel(SPMeta2.SSOM.ModelHosts.WebModelHost.FromWeb(spWeb), model); + } + }); + }); + } + #endregion } } diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SharePointPersistenceStorageServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SharePointPersistenceStorageServiceTests.cs new file mode 100644 index 000000000..33f834d2c --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/SharePointPersistenceStorageServiceTests.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Common; +using SPMeta2.CSOM.Services; +using SPMeta2.CSOM.Standard.Services; +using SPMeta2.Interfaces; +using SPMeta2.ModelHandlers; +using SPMeta2.Services; +using SPMeta2.SSOM.Services; +using SPMeta2.SSOM.Standard.Services; +using SPMeta2.Utils; +using SPMeta2.Containers.CSOM; +using SPMeta2.Services.Impl; +using SPMeta2.Syntax.Default; +using SPMeta2.Containers.O365; +using SPMeta2.Definitions; +using SPMeta2.Exceptions; +using System; +using SPMeta2.Containers.SSOM; +using SPMeta2.CSOM.Services.Impl; +using SPMeta2.Extensions; +using SPMeta2.SSOM.Services.Impl; + +namespace SPMeta2.Regression.Impl.Tests.Impl.Services +{ + [TestClass] + public class SharePointPersistenceStorageServiceTests + { + #region init + + [ClassInitialize] + public static void Init(TestContext context) + { + + } + + [ClassCleanup] + public static void Cleanup() + { + + } + + #endregion + + #region test + + [TestMethod] + [TestCategory("Regression.Impl.SharePointPersistenceStorageServiceTests")] + [TestCategory("CI.Core")] + public void Can_SharePointPersistenceStorageServices() + { + Assert.IsNotNull(new DefaultCSOMWebPropertyBagStorage()); + + Assert.IsNotNull(new DefaultSSOMFarmPropertyBagStorage()); + Assert.IsNotNull(new DefaultSSOMWebApplicationPropertyBagStorage()); + Assert.IsNotNull(new DefaultSSOMWebPropertyBagStorage()); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/SPMeta2.Regression.Impl.Tests.csproj b/SPMeta2/SPMeta2.Regression.Impl.Tests/SPMeta2.Regression.Impl.Tests.csproj index 567d385b6..538c36e39 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/SPMeta2.Regression.Impl.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/SPMeta2.Regression.Impl.Tests.csproj @@ -222,6 +222,7 @@ + diff --git a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs index e63fa3059..c4a571ec1 100644 --- a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs +++ b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMFarmPropertyBagStorage.cs @@ -8,14 +8,21 @@ using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; +using SPMeta2.Definitions; using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; namespace SPMeta2.SSOM.Services.Impl { - public class DefaultSSOMFarmPropertyBagStorage : PersistenceStorageServiceBase + public class DefaultSSOMFarmPropertyBagStorage : SharePointPersistenceStorageServiceBase { #region consturctors + public DefaultSSOMFarmPropertyBagStorage() + { + + } + public DefaultSSOMFarmPropertyBagStorage(SPFarm farm) { CurrentFarm = farm; @@ -27,6 +34,19 @@ public DefaultSSOMFarmPropertyBagStorage(SPFarm farm) public SPFarm CurrentFarm { get; set; } + public override List TargetDefinitionTypes + { + get + { + var result = new List(); + + result.Add(typeof(FarmDefinition)); + + return result; + } + set { } + } + #endregion #region methods @@ -63,6 +83,13 @@ public override void SaveObject(string objectId, byte[] data) CurrentFarm.Update(); } + public override void InitialiseFromModelHost(object modelHost) + { + var typedModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + + this.CurrentFarm = typedModelHost.HostFarm; + } + #endregion } } diff --git a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs index a8985daa0..8234ebbbc 100644 --- a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs +++ b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebApplicationPropertyBagStorage.cs @@ -8,14 +8,21 @@ using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; +using SPMeta2.Definitions; +using SPMeta2.SSOM.ModelHosts; using SPMeta2.Utils; namespace SPMeta2.SSOM.Services.Impl { - public class DefaultSSOMWebApplicationPropertyBagStorage : PersistenceStorageServiceBase + public class DefaultSSOMWebApplicationPropertyBagStorage : SharePointPersistenceStorageServiceBase { #region consturctors + public DefaultSSOMWebApplicationPropertyBagStorage() + { + + } + public DefaultSSOMWebApplicationPropertyBagStorage(SPWebApplication webApplication) { CurrentWebApplication = webApplication; @@ -27,6 +34,20 @@ public DefaultSSOMWebApplicationPropertyBagStorage(SPWebApplication webApplicati public SPWebApplication CurrentWebApplication { get; set; } + public override List TargetDefinitionTypes + { + get + { + var result = new List(); + + result.Add(typeof(WebApplicationDefinition)); + + return result; + } + set { } + } + + #endregion #region methods @@ -63,6 +84,13 @@ public override void SaveObject(string objectId, byte[] data) CurrentWebApplication.Update(); } + public override void InitialiseFromModelHost(object modelHost) + { + var typedModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + + this.CurrentWebApplication = typedModelHost.HostWebApplication; + } + #endregion } } diff --git a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs index ccd3efdfb..4a1ca3476 100644 --- a/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs +++ b/SPMeta2/SPMeta2.SSOM/Services/Impl/DefaultSSOMWebPropertyBagStorage.cs @@ -7,14 +7,22 @@ using System.Text; using Microsoft.SharePoint; +using SPMeta2.Definitions; +using SPMeta2.SSOM.ModelHosts; using SPMeta2.Utils; +using SPMeta2.Exceptions; namespace SPMeta2.SSOM.Services.Impl { - public class DefaultSSOMWebPropertyBagStorage : PersistenceStorageServiceBase + public class DefaultSSOMWebPropertyBagStorage : SharePointPersistenceStorageServiceBase { #region consturctors + public DefaultSSOMWebPropertyBagStorage() + { + + } + public DefaultSSOMWebPropertyBagStorage(SPWeb web) { CurrentWeb = web; @@ -35,6 +43,20 @@ protected Hashtable ExtractProperties() return CurrentWeb.AllProperties; } + public override List TargetDefinitionTypes + { + get + { + var result = new List(); + + result.Add(typeof(SiteDefinition)); + result.Add(typeof(WebDefinition)); + + return result; + } + set { } + } + public override byte[] LoadObject(string objectId) { var key = objectId; @@ -62,6 +84,28 @@ public override void SaveObject(string objectId, byte[] data) CurrentWeb.Update(); } + public override void InitialiseFromModelHost(object modelHost) + { + var csomModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + + if (csomModelHost is WebModelHost) + { + var webModelHost = csomModelHost as WebModelHost; + + this.CurrentWeb = webModelHost.HostWeb; + } + else if (csomModelHost is SiteModelHost) + { + var webModelHost = csomModelHost as SiteModelHost; + + this.CurrentWeb = webModelHost.HostSite.RootWeb; + } + else + { + throw new SPMeta2Exception(string.Format("Unsuported model host type:[{0}]", modelHost.GetType())); + } + } + #endregion } } diff --git a/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs b/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs index 178f56006..7790f9322 100644 --- a/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs +++ b/SPMeta2/SPMeta2/Common/IncrementalProvisionConfig.cs @@ -18,11 +18,15 @@ public IncrementalProvisionConfig() { PreviousModelHash = new ModelHash(); PersistenceStorages = new List(); + + AutoDetectSharePointPersistenceStorage = false; } #endregion #region properties + + public bool AutoDetectSharePointPersistenceStorage { get; set; } public ModelHash PreviousModelHash { get; set; } public Type CustomModelTreeTraverseServiceType { get; set; } @@ -35,10 +39,42 @@ public static IncrementalProvisionConfig Default { get { - return new IncrementalProvisionConfig + var config = new IncrementalProvisionConfig { CustomModelTreeTraverseServiceType = typeof(DefaultIncrementalModelTreeTraverseService) }; + + return config; + } + } + + public static IncrementalProvisionConfig DefaultFileSystem + { + get + { + var config = new IncrementalProvisionConfig + { + CustomModelTreeTraverseServiceType = typeof(DefaultIncrementalModelTreeTraverseService) + }; + + config.PersistenceStorages.Add(new DefaultFileSystemPersistenceStorage()); + + return config; + } + } + + public static IncrementalProvisionConfig DefaultSharePoint + { + get + { + var config = new IncrementalProvisionConfig + { + CustomModelTreeTraverseServiceType = typeof(DefaultIncrementalModelTreeTraverseService) + }; + + config.AutoDetectSharePointPersistenceStorage = true; + + return config; } } } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index 99f59a458..11823b508 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -274,8 +274,10 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod // clean up current model hash CurrentModelHash = new ModelHash(); + var storages = ResolvePersistenceStorages(modelHost, modelNode); + // restore previous one - if (Configuration != null && Configuration.PersistenceStorages.Count() > 0) + if (Configuration != null && storages.Count() > 0) { TraceService.Information(0, "Model hash restore: found [{0}] storage impl in Configuration.PersistenceStorages. Automatic model hash management is used"); @@ -294,7 +296,9 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod typeof(ModelNodeHash) }); - foreach (var storage in Configuration.PersistenceStorages) + + + foreach (var storage in storages) { TraceService.Information(0, string.Format("Restoring model hash with object id:[{0}] using storage impl [{1}]", objectId, storage.GetType())); @@ -335,7 +339,9 @@ protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode base.OnAfterDeployModel(modelHost, modelNode); // save model hash to a persistan storages - if (Configuration != null && Configuration.PersistenceStorages.Count() > 0) + var storages = ResolvePersistenceStorages(modelHost, modelNode); + + if (Configuration != null && storages.Count() > 0) { TraceService.Information(0, "Model hash save: found [{0}] storage impl in Configuration.PersistenceStorages. Automatic model hash management is used"); @@ -359,18 +365,17 @@ protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode var data = Encoding.UTF8.GetBytes(serializer.Serialize(CurrentModelHash)); - foreach (var storage in Configuration.PersistenceStorages) + foreach (var storage in storages) { TraceService.Information(0, string.Format("Saving model hash with object id:[{0}] using storage impl [{1}]. Size:[{2}] bytes", objectId, storage.GetType(), data.LongLength)); - storage.SaveObject(objectId, data); } } else { - TraceService.Information(0, "Model hash save: can't find any persistence storage impl in Configuration.PersistenceStorages. Assuming manual model hash management is used"); + TraceService.Information(0, "Model hash save: can't find any persistence storage impl in Configuration... Assuming manual model hash management is used"); } } @@ -385,6 +390,21 @@ protected virtual ModelHash GetPreviousModelHash() throw new SPMeta2Exception(".CurrentModelHash must be set"); } + // AutoDetectSharePointPersistenceStorage + + protected virtual List ResolvePersistenceStorages(object modelHost, ModelNode modelNode) + { + if (Configuration == null) + return new List(); + + if (Configuration.AutoDetectSharePointPersistenceStorage) + { + throw new SPMeta2NotImplementedException("Auto detection for SharePoint storage is not implemented yet"); + } + + return Configuration.PersistenceStorages; + } + #endregion protected bool OriginalRequireSelfProcessingValue { get; set; } diff --git a/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs b/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs index 040743bfa..c2d9c53df 100644 --- a/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/PersistenceStorageServiceBase.cs @@ -15,4 +15,10 @@ public abstract class PersistenceStorageServiceBase #endregion } + + public abstract class SharePointPersistenceStorageServiceBase : PersistenceStorageServiceBase + { + public abstract void InitialiseFromModelHost(object modelHost); + public abstract List TargetDefinitionTypes { get; set; } + } } From 2b2509c5e4d9a537f1a5d5dbf37df1696cf691a2 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Fri, 3 Mar 2017 07:31:00 +0000 Subject: [PATCH 19/53] + Implement 'incremental' provision support #553 + Add option for persistence storage auto-detection --- .../SPMeta2.CSOM/ModelHosts/CSOMModelHost.cs | 52 +++--- .../Services/CSOMProvisionService.cs | 3 + .../CSOMProvisionRunner.cs | 6 + .../O365v16ProvisionRunner.cs | 5 + .../SSOMProvisionRunner.cs | 6 + .../ModelHosts/SSOMModelHostBase.cs | 10 +- .../Services/SSOMProvisionService.cs | 6 + SPMeta2/SPMeta2/ModelHosts/ModelHostBase.cs | 169 +++++++++--------- ...aultIncrementalModelTreeTraverseService.cs | 49 ++++- 9 files changed, 201 insertions(+), 105 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/CSOMModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/CSOMModelHost.cs index 384d3dfa0..0a000cc84 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/CSOMModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/CSOMModelHost.cs @@ -1,21 +1,31 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.SharePoint.Client; -using SPMeta2.ModelHosts; - -namespace SPMeta2.CSOM.ModelHosts -{ - public abstract class CSOMModelHostBase : ModelHostBase - { - #region properties - - public ClientContext HostClientContext { get; set; } - - public Site HostSite { get; set; } - public Web HostWeb { get; set; } - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.SharePoint.Client; +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.ModelHosts +{ + public abstract class CSOMModelHostBase : ModelHostBase + { + #region constructors + + public CSOMModelHostBase() + { + IsCSOM = true; + IsSSOM = false; + } + + #endregion + + #region properties + + public ClientContext HostClientContext { get; set; } + + public Site HostSite { get; set; } + public Web HostWeb { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/Services/CSOMProvisionService.cs b/SPMeta2/SPMeta2.CSOM/Services/CSOMProvisionService.cs index 054e4b416..e1554bdaa 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/CSOMProvisionService.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/CSOMProvisionService.cs @@ -24,6 +24,9 @@ public CSOMProvisionService() ServiceContainer.Instance.RegisterService(typeof(CSOMTokenReplacementService), new CSOMTokenReplacementService()); ServiceContainer.Instance.RegisterService(typeof(CSOMLocalizationService), new CSOMLocalizationService()); + // default sharepoint persistence storage impl + ServiceContainer.Instance.RegisterService(typeof(SharePointPersistenceStorageServiceBase), new DefaultCSOMWebPropertyBagStorage()); + // Align CSOM throttling setting with MS recommendations, open up API #849 // https://github.com/SubPointSolutions/spmeta2/issues/849 diff --git a/SPMeta2/SPMeta2.Containers.CSOM/CSOMProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.CSOM/CSOMProvisionRunner.cs index b45ac5b8b..778f66027 100644 --- a/SPMeta2/SPMeta2.Containers.CSOM/CSOMProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.CSOM/CSOMProvisionRunner.cs @@ -27,6 +27,7 @@ using SPMeta2.CSOM.Extensions; using SPMeta2.ModelHosts; +using SPMeta2.Services; namespace SPMeta2.Containers.CSOM { @@ -48,6 +49,11 @@ public CSOMProvisionRunner() UserPassword = RunnerEnvironmentUtils.GetEnvironmentVariable(EnvironmentConsts.CSOM_Password); } + public override ProvisionServiceBase ProvisionService + { + get { return _provisionService; } + } + private void InitServices() { //_provisionService = new CSOMProvisionService(); diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index 2e72fa930..a9cdee267 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -17,6 +17,7 @@ using SPMeta2.Models; using SPMeta2.Regression.CSOM; using SPMeta2.Regression.CSOM.Standard.Validation.Fields; +using SPMeta2.Services; using SPMeta2.Utils; namespace SPMeta2.Containers.O365v16 @@ -120,6 +121,10 @@ private void LoadEnvironmentConfig() private CSOMProvisionService _provisionService; private CSOMValidationService _validationService; + public override ProvisionServiceBase ProvisionService + { + get { return _provisionService; } + } #endregion diff --git a/SPMeta2/SPMeta2.Containers.SSOM/SSOMProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.SSOM/SSOMProvisionRunner.cs index 1fe297c7f..5d8ea1ed7 100644 --- a/SPMeta2/SPMeta2.Containers.SSOM/SSOMProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.SSOM/SSOMProvisionRunner.cs @@ -32,6 +32,7 @@ using SPMeta2.SSOM.Standard.Services; using SPMeta2.ModelHosts; using SPMeta2.Exceptions; +using SPMeta2.Services; namespace SPMeta2.Containers.SSOM { @@ -132,6 +133,11 @@ private void LoadEnvironmentConfig() #region properties + public override ProvisionServiceBase ProvisionService + { + get { return _provisionService; } + } + public List WebApplicationUrls { get; set; } public List SiteUrls { get; set; } public List WebUrls { get; set; } diff --git a/SPMeta2/SPMeta2.SSOM/ModelHosts/SSOMModelHostBase.cs b/SPMeta2/SPMeta2.SSOM/ModelHosts/SSOMModelHostBase.cs index 024490e11..dd102a3d2 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHosts/SSOMModelHostBase.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHosts/SSOMModelHostBase.cs @@ -9,6 +9,14 @@ namespace SPMeta2.SSOM.ModelHosts { public class SSOMModelHostBase : ModelHostBase { - + #region constructors + + public SSOMModelHostBase() + { + IsCSOM = false; + IsSSOM = true; + } + + #endregion } } diff --git a/SPMeta2/SPMeta2.SSOM/Services/SSOMProvisionService.cs b/SPMeta2/SPMeta2.SSOM/Services/SSOMProvisionService.cs index 98074f448..c8f84a63b 100644 --- a/SPMeta2/SPMeta2.SSOM/Services/SSOMProvisionService.cs +++ b/SPMeta2/SPMeta2.SSOM/Services/SSOMProvisionService.cs @@ -9,6 +9,7 @@ using SPMeta2.Utils; using System; using System.Reflection; +using SPMeta2.SSOM.Services.Impl; namespace SPMeta2.SSOM.Services { @@ -23,6 +24,11 @@ public SSOMProvisionService() ServiceContainer.Instance.RegisterService(typeof(SSOMListViewLookupService), new SSOMListViewLookupService()); + // default sharepoint persistence storage impl + ServiceContainer.Instance.RegisterService(typeof(SharePointPersistenceStorageServiceBase), new DefaultSSOMWebPropertyBagStorage()); + ServiceContainer.Instance.RegisterService(typeof(SharePointPersistenceStorageServiceBase), new DefaultSSOMWebApplicationPropertyBagStorage()); + ServiceContainer.Instance.RegisterService(typeof(SharePointPersistenceStorageServiceBase), new DefaultSSOMFarmPropertyBagStorage()); + RegisterModelHandlers(); //CheckSharePointRuntimeVersion(); diff --git a/SPMeta2/SPMeta2/ModelHosts/ModelHostBase.cs b/SPMeta2/SPMeta2/ModelHosts/ModelHostBase.cs index 0fa40bb78..fee53a548 100644 --- a/SPMeta2/SPMeta2/ModelHosts/ModelHostBase.cs +++ b/SPMeta2/SPMeta2/ModelHosts/ModelHostBase.cs @@ -1,82 +1,87 @@ -using System; - -namespace SPMeta2.ModelHosts -{ - /// - /// Base model host for provision flow. - /// - public class ModelHostBase : ICloneable - { - #region constructors - - public ModelHostBase() - { - ShouldUpdateHost = true; - } - - #endregion - - #region static - - public static ModelHostBase Inherit(ModelHostBase modelHost) - { - return Inherit(modelHost); - } - - public static T Inherit(ModelHostBase modelHost) - where T : ModelHostBase, new() - { - return Inherit(modelHost, null); - } - - public static T Inherit(ModelHostBase modelHost, Action action) - where T : ModelHostBase, new() - { - var source = modelHost.Clone() as ModelHostBase; - var result = new T(); - - CopyProperties(source, result); - - if (action != null) - action(result); - - return result; - } - - internal static void CopyProperties(object source, object target) - { - var customerType = target.GetType(); - foreach (var prop in source.GetType().GetProperties()) - { - var propGetter = prop.GetGetMethod(); - - var targetProperty = customerType.GetProperty(prop.Name); - - if (targetProperty != null) - { - var propSetter = customerType.GetProperty(prop.Name).GetSetMethod(); - var valueToSet = propGetter.Invoke(source, null); - - propSetter.Invoke(target, new[] { valueToSet }); - } - } - } - - #endregion - - #region properties - - public bool ShouldUpdateHost { get; set; } - - #endregion - - #region methods - - public object Clone() - { - return MemberwiseClone(); - } - - #endregion - } -} +using System; + +namespace SPMeta2.ModelHosts +{ + /// + /// Base model host for provision flow. + /// + public class ModelHostBase : ICloneable + { + #region constructors + + public ModelHostBase() + { + ShouldUpdateHost = true; + + IsCSOM = false; + IsSSOM = false; + } + + #endregion + + #region static + + public static ModelHostBase Inherit(ModelHostBase modelHost) + { + return Inherit(modelHost); + } + + public static T Inherit(ModelHostBase modelHost) + where T : ModelHostBase, new() + { + return Inherit(modelHost, null); + } + + public static T Inherit(ModelHostBase modelHost, Action action) + where T : ModelHostBase, new() + { + var source = modelHost.Clone() as ModelHostBase; + var result = new T(); + + CopyProperties(source, result); + + if (action != null) + action(result); + + return result; + } + + internal static void CopyProperties(object source, object target) + { + var customerType = target.GetType(); + foreach (var prop in source.GetType().GetProperties()) + { + var propGetter = prop.GetGetMethod(); + + var targetProperty = customerType.GetProperty(prop.Name); + + if (targetProperty != null) + { + var propSetter = customerType.GetProperty(prop.Name).GetSetMethod(); + var valueToSet = propGetter.Invoke(source, null); + + propSetter.Invoke(target, new[] { valueToSet }); + } + } + } + + #endregion + + #region properties + + public bool IsSSOM { get; set; } + public bool IsCSOM { get; set; } + public bool ShouldUpdateHost { get; set; } + + #endregion + + #region methods + + public object Clone() + { + return MemberwiseClone(); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index 11823b508..9b7c16080 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -9,6 +9,7 @@ using SPMeta2.Models; using SPMeta2.Utils; using SPMeta2.Syntax.Default; +using SPMeta2.ModelHosts; namespace SPMeta2.Services.Impl { @@ -399,7 +400,53 @@ protected virtual List ResolvePersistenceStorages if (Configuration.AutoDetectSharePointPersistenceStorage) { - throw new SPMeta2NotImplementedException("Auto detection for SharePoint storage is not implemented yet"); + var rootModelNodeType = modelNode.Value.GetType(); + + TraceService.InformationFormat(0, "Detecting SharePoint persistence storage implementation for root definitin type:[{0}]", rootModelNodeType); + + var currentStorageServices = ServiceContainer.Instance.GetServices(); + SharePointPersistenceStorageServiceBase targetService = null; + + var typedModelHost = modelHost.WithAssertAndCast("modelHost", v => v.RequireNotNull()); + + foreach (var service in currentStorageServices) + { + if (service.TargetDefinitionTypes.Contains(rootModelNodeType)) + { + var serviceTypeName = service.GetType().Name; + + // cause it could be multiple service registrations here by both CSOM and SSOM + // we need to know the context coming from the top and then resolve correct service for the API + if (typedModelHost.IsSSOM && serviceTypeName.Contains("SSOM")) + { + targetService = service; + break; + } + + if (typedModelHost.IsCSOM && serviceTypeName.Contains("CSOM")) + { + targetService = service; + break; + } + } + } + + if (targetService == null) + { + throw new SPMeta2Exception( + string.Format("Coudn't find SharePoint persistence storage implementation for root definitin type:[{0}]", + rootModelNodeType)); + } + + TraceService.InformationFormat(0, "Initialilize persistence storage [{0}] with model host", targetService.GetType()); + targetService.InitialiseFromModelHost(modelHost); + + TraceService.Information(0, "Returning persistence storage implementation"); + + var result = new List(); + + result.Add(targetService); + return result; } return Configuration.PersistenceStorages; From 2eea5c425ec32fd7ea753e67daae133ac51c1c57 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Fri, 3 Mar 2017 03:27:22 -0800 Subject: [PATCH 20/53] + Implement 'incremental' provision support #553 + Can_Provision_Incrementally_With_AutoDetection_As_SSOM fixes --- .../Impl/Services/ProvisionServiceTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs index 38dfe1103..d4167e3ab 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/Services/ProvisionServiceTests.cs @@ -468,7 +468,7 @@ public void Can_Provision_Incrementally_With_AutoDetection_As_SSOM() provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); - var model = SPMeta2Model.NewSiteModel(site => + var model = SPMeta2Model.NewFarmModel(site => { }); @@ -492,7 +492,7 @@ public void Can_Provision_Incrementally_With_AutoDetection_As_SSOM() provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); - var model = SPMeta2Model.NewSiteModel(site => + var model = SPMeta2Model.NewWebApplicationModel(site => { }); From 386030661bb9e36b9800dab9d6ffe15a0f487fd3 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Fri, 3 Mar 2017 03:31:05 -0800 Subject: [PATCH 21/53] + solution clean up --- .gitignore | 1 + .../ContentTypeBehaviours.cs | 60 -------- .../FieldBehaviours.cs | 101 -------------- .../Properties/AssemblyInfo.cs | 36 ----- .../SPMeta2.CSOM.Behaviours.csproj | 130 ------------------ .../SPMeta2.CSOM.Behaviours.vsdoc | 7 - SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.snk | Bin 596 -> 0 bytes .../SPMeta2.CSOM.Behaviours/WebBehaviours.cs | 32 ----- .../WorkflowSubscriptionBehaviours.cs | 38 ----- 9 files changed, 1 insertion(+), 404 deletions(-) delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/ContentTypeBehaviours.cs delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/FieldBehaviours.cs delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/Properties/AssemblyInfo.cs delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.csproj delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.vsdoc delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.snk delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/WebBehaviours.cs delete mode 100644 SPMeta2/SPMeta2.CSOM.Behaviours/WorkflowSubscriptionBehaviours.cs diff --git a/.gitignore b/.gitignore index 336afb2a4..bbcbc6239 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # M2 docs index and refs *.sample-ref +*.ncrunchsolution # User-specific files *.suo diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/ContentTypeBehaviours.cs b/SPMeta2/SPMeta2.CSOM.Behaviours/ContentTypeBehaviours.cs deleted file mode 100644 index cb3f1c3e5..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/ContentTypeBehaviours.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.WorkflowServices; - -namespace SPMeta2.CSOM.Behaviours -{ - public static class ContentTypeBehaviours - { - #region common extensions - - /// - /// Setup the same url for NewFormUrl/DisplayFormUrl/EditFormUrl - /// - /// - /// - /// - public static ContentType MakeCustomFormUrl(this ContentType contentType, string url) - { - MakeNewFormUrl(contentType, url); - MakeDisplayFormUrl(contentType, url); - MakeEditFormUrl(contentType, url); - - return contentType; - } - - public static ContentType MakeNewFormUrl(this ContentType contentType, string url) - { - contentType.NewFormUrl = url; - - return contentType; - } - - public static ContentType MakeDisplayFormUrl(this ContentType contentType, string url) - { - contentType.DisplayFormUrl = url; - - return contentType; - } - - public static ContentType MakeEditFormUrl(this ContentType contentType, string url) - { - contentType.EditFormUrl = url; - - return contentType; - } - - public static ContentType MakeDocumentTemplate(this ContentType contentType, string serverRelativeUrl) - { - contentType.DocumentTemplate = serverRelativeUrl; - - return contentType; - } - - #endregion - } -} diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/FieldBehaviours.cs b/SPMeta2/SPMeta2.CSOM.Behaviours/FieldBehaviours.cs deleted file mode 100644 index 6ecd534d0..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/FieldBehaviours.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.WorkflowServices; - -namespace SPMeta2.CSOM.Behaviours -{ - public static class FieldBehaviours - { - #region common extensions - - public static Field MakeChoices(this Field field, IEnumerable choices) - { - return MakeChoices(field, choices, true); - } - - public static Field MakeChoices(this Field field, IEnumerable choiceValues, bool cleanOldChoice = true) - { - var choiceField = field as FieldChoice; - - if (choiceField != null) - { - var tmpChoices = new List(); - - if (!cleanOldChoice) - tmpChoices.AddRange(choiceField.Choices); - - foreach (var choiceValue in choiceValues) - if (!tmpChoices.Contains(choiceValue)) - tmpChoices.Add(choiceValue); - - choiceField.Choices = tmpChoices.ToArray(); - } - - return field; - } - - public static Field MakeDefaultValue(this Field field, string value) - { - field.DefaultValue = value; - - return field; - } - - public static Field MakeTitle(this Field field, string title) - { - field.Title = title; - - return field; - } - - public static Field MakeLookupConnectionToList(this Field field, Guid webId, Guid listId) - { - return MakeLookupConnectionToList(field, webId, listId, "Title"); - } - - public static Field MakeLookupConnectionToList(this Field field, Guid webId, Guid listId, string showFieldName) - { - var lookupField = field as FieldLookup; - - if (lookupField != null && string.IsNullOrEmpty(lookupField.LookupList)) - { - lookupField.LookupWebId = webId; - lookupField.LookupList = listId.ToString(); - lookupField.LookupField = showFieldName; - } - - return field; - } - - public static Field MakeNotRequired(this Field field) - { - return MakeRequired(field, false); - } - - public static Field MakeRequired(this Field field) - { - return MakeRequired(field, true); - } - - public static Field MakeRequired(this Field field, bool isRequired) - { - field.Required = isRequired; - - return field; - } - - public static Field MakeHidden(this Field field, bool isRequired) - { - field.MakeNotRequired(); - field.Hidden = true; - - return field; - } - - #endregion - } -} diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM.Behaviours/Properties/AssemblyInfo.cs deleted file mode 100644 index cf1738eb5..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.CSOM.Behaviours")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.CSOM.Behaviours")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("3603d0e4-09d6-459e-bf7a-c10f8ae27838")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.csproj b/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.csproj deleted file mode 100644 index 49efa2726..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.csproj +++ /dev/null @@ -1,130 +0,0 @@ - - - - - Debug - AnyCPU - {5D604B9F-4A28-424D-AB1D-D5F4B7CBE848} - Library - Properties - SPMeta2.CSOM.Behaviours - SPMeta2.CSOM.Behaviours - v4.5 - 512 - SAK - SAK - SAK - SAK - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - bin\Debug40-$(spRuntime)\ - v4.0 - true - full - false - DEBUG;TRACE - prompt - 4 - false - bin\Debug40-$(spRuntime)\SPMeta2.CSOM.Behaviours.XML - - - bin\Debug45-$(spRuntime)\ - v4.5 - true - full - false - DEBUG;TRACE - prompt - 4 - false - bin\Debug45-$(spRuntime)\SPMeta2.CSOM.Behaviours.XML - - - true - - - SPMeta2.snk - - - bin\Debug40-$(spRuntime)\ - - - true - bin\Debug45-$(spRuntime)\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - False - ..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4569.1000\CSOM\Microsoft.SharePoint.Client.dll - - - False - ..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4569.1000\CSOM\Microsoft.SharePoint.Client.Runtime.dll - - - False - ..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4569.1000\CSOM\Microsoft.SharePoint.Client.WorkflowServices.dll - - - - False - ..\SPMeta2.Dependencies\SharePoint\O365 - 16.0.2617.1200\Microsoft.SharePoint.Client.dll - - - False - ..\SPMeta2.Dependencies\SharePoint\O365 - 16.0.2617.1200\Microsoft.SharePoint.Client.Runtime.dll - - - False - ..\SPMeta2.Dependencies\SharePoint\O365 - 16.0.2617.1200\Microsoft.SharePoint.Client.WorkflowServices.dll - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.vsdoc b/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.vsdoc deleted file mode 100644 index 9ffff5e7f..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.CSOM.Behaviours.vsdoc +++ /dev/null @@ -1,7 +0,0 @@ - - - - default - - - diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.snk b/SPMeta2/SPMeta2.CSOM.Behaviours/SPMeta2.snk deleted file mode 100644 index cb00f713d0da938ec1ee42b99940b8a7429bd6ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa500975x-4^rHyWhFAbd*wEg*{zWKi2|fa&LX zBUh<9opGfBrz%SzQPsUMkNNGL%0cLi71_ZuzU|+nkw)+a^&SbQL52-(BE-1KgS#Tl zmzi4izTg1--a{>%iatd|(wU9&-uOUr2v ze<)Rm(xL#fo9!aR4CejORSsZ2gu>X@yC0Tcy#50$`n5)dEn z*h-BA!ekefa7nHd>#mD*(EIBdV%;SeJR2f@K`g)$_j<&yT}Mb(S-$|_pZwrKMCUZ$ zO>d)`nV6x|aM~jU`lqJ))3IDl##S2opwbr^Yd7jDhUsvsV5{c%x<>@uZsKw^yhOon z3_|Q4xs=fG^n(^%+`ZlV7YI%f^A{gGPPkpnFR@M^vy~U_oWRvA=cCCgkL^O3Xs!%G i4LdxRU7h*VxHL?FL55V8ahnQGqcM*HG1b<7jV%Tih8}hR diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/WebBehaviours.cs b/SPMeta2/SPMeta2.CSOM.Behaviours/WebBehaviours.cs deleted file mode 100644 index a930a879f..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/WebBehaviours.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client; - -namespace SPMeta2.CSOM.Behaviours -{ - public static class WebBehaviours - { - #region methods - - public static Web MakeWelcomePage(this Web web, string webRelativeUrl) - { - var webContex = web.Context; - var url = webRelativeUrl.TrimStart(new char[] { '\\', '/' }); - - webContex.Load(web, r => r.RootFolder); - webContex.Load(web, r => r.ServerRelativeUrl); - - webContex.ExecuteQuery(); - - web.RootFolder.WelcomePage = url; - web.RootFolder.Update(); - - return web; - } - - #endregion - } -} diff --git a/SPMeta2/SPMeta2.CSOM.Behaviours/WorkflowSubscriptionBehaviours.cs b/SPMeta2/SPMeta2.CSOM.Behaviours/WorkflowSubscriptionBehaviours.cs deleted file mode 100644 index 0326b0cea..000000000 --- a/SPMeta2/SPMeta2.CSOM.Behaviours/WorkflowSubscriptionBehaviours.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.WorkflowServices; - -namespace SPMeta2.CSOM.Behaviours -{ - public static class WorkflowSubscriptionBehaviours - { - #region common extensions - - public static WorkflowSubscription MakeHistoryListId(this WorkflowSubscription workflowSubscription, Guid historyListId) - { - workflowSubscription.SetProperty("HistoryListId", historyListId.ToString()); - return workflowSubscription; - } - - public static WorkflowSubscription MakeTaskListId(this WorkflowSubscription workflowSubscription, Guid taskListId) - { - workflowSubscription.SetProperty("TaskListId", taskListId.ToString()); - return workflowSubscription; - } - - public static WorkflowSubscription MakeListId(this WorkflowSubscription workflowSubscription, Guid listId) - { - workflowSubscription.SetProperty("ListId", listId.ToString()); - workflowSubscription.SetProperty("Microsoft.SharePoint.ActivationProperties.ListId", listId.ToString()); - - return workflowSubscription; - } - - - #endregion - } -} From b89bea1d25a458d1057ca4347c44b3e486af0df0 Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Sun, 5 Mar 2017 23:32:11 +0000 Subject: [PATCH 22/53] + moved build to cakebuild 0.1.0-beta1 --- SPMeta2/Build/build.json | 2 +- SPMeta2/Build/build.ps1 | 11 +++++++++-- SPMeta2/Build/tools/packages.config | 2 +- SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/Index.md | 2 +- .../Views/SPMeta2/kb/kb-m2-000001.md | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index 97bc73b71..bd7f8dd5f 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -2,7 +2,7 @@ "defaultSolutionDirectory": "./../../", "defaultSolutionFilePath": "./../../SPMeta2.sln", - "defaultDocsBuildEnabled" : false, + "defaultDocsBuildEnabled" : true, "defaultDocsViewFolder" : "SPMeta2/SubPointSolutions.Docs/Views/SPMeta2", "defaultDocsRepoFolder" : "m2-m2", diff --git a/SPMeta2/Build/build.ps1 b/SPMeta2/Build/build.ps1 index 0521f4760..119747b2e 100644 --- a/SPMeta2/Build/build.ps1 +++ b/SPMeta2/Build/build.ps1 @@ -4,7 +4,6 @@ # Feel free to change this file to fit your needs. ########################################################################## - <# .SYNOPSIS @@ -160,12 +159,20 @@ if(-Not $SkipToolPackageRestore.IsPresent) { Set-Location $TOOLS_DIR # Check for changes in packages.config and remove installed tools if true. + <# [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { Write-Verbose -Message "Missing or changed package.config hash..." Remove-Item * -Recurse -Exclude packages.config,nuget.exe } + #> + [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) + if((!(Test-Path $PACKAGES_CONFIG_MD5))) { + Write-Verbose -Message "Missing or changed package.config hash..." + throw "Missing or changed package.config hash..." + #Remove-Item * -Recurse -Exclude packages.config,nuget.exe + } Write-Verbose -Message "Restoring tools from NuGet..." $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" @@ -189,4 +196,4 @@ if (!(Test-Path $CAKE_EXE)) { # Start Cake Write-Host "Running build script..." Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" -exit $LASTEXITCODE \ No newline at end of file +exit $LASTEXITCODE diff --git a/SPMeta2/Build/tools/packages.config b/SPMeta2/Build/tools/packages.config index 174a33d77..e5d5b8e40 100644 --- a/SPMeta2/Build/tools/packages.config +++ b/SPMeta2/Build/tools/packages.config @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/Index.md b/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/Index.md index e28db1e2d..ab75296cf 100644 --- a/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/Index.md +++ b/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/Index.md @@ -8,7 +8,7 @@ TileLink: true TileLinkOrder: 5 TileDescription: 'Hassle-free SharePoint artifact provisioning framework for SP2010, SP2013 and O365.' --- -## Welcome to M2 (also known as SPMeta2) +## Welcome to SPMeta2 SPMeta2 is a hassle-free fluent API for code-based SharePoint artefact provisioning. It offers a consistent provisioning API via SSOM/CSOM for SharePoin 2010, 2013 and O365. diff --git a/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/kb/kb-m2-000001.md b/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/kb/kb-m2-000001.md index e2ccd4825..06b3c46af 100644 --- a/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/kb/kb-m2-000001.md +++ b/SPMeta2/SubPointSolutions.Docs/Views/SPMeta2/kb/kb-m2-000001.md @@ -7,7 +7,7 @@ Order: 1001 ### Problem Visual Studio keep teeling "XXX" does not contain a definition for "YYY", for instance: -* "SPMeta2.Syntax.Default.SiteModel" does not contain a definition for "AddTaxonomyTermStore" +* "SPMeta2.Syntax.Default.SiteModel" does not contain a definition for "AddTaxonomyTermStore" ## Explanation M2 has lots of extension methods over various namespaces, and VS can do a better job on resolving these methods and namespaces. That's why sometimes the code can't be complied and VS does not suggest anything at all. From dbcb79669b1d950edd62660793b1a0639b3a25ec Mon Sep 17 00:00:00 2001 From: "support@subpointsolutions.com" Date: Sun, 5 Mar 2017 23:47:28 +0000 Subject: [PATCH 23/53] + docs build fox --- SPMeta2/Build/build.json | 2 +- SPMeta2/Build/tools/packages.config.md5sum | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index bd7f8dd5f..6f6386083 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -211,7 +211,7 @@ "defaultChocolateyPackagesDirectory": "./build-artifact-cli-packages", "defaultNuspecVersion": "0.1.0", - "defaultDocsViewFolder" : "SubPointSolutions.Docs/Views/SPMeta2", + "defaultDocsViewFolder" : "SPMeta2/SubPointSolutions.Docs/Views/SPMeta2", "defaultDocsRepoFolder" : "m2-m2", "defaultDocsBranch" : "wyam-dev", "defaultDocsFileExtensions" : [ diff --git a/SPMeta2/Build/tools/packages.config.md5sum b/SPMeta2/Build/tools/packages.config.md5sum index f96b10c5b..7ef7fbb5a 100644 --- a/SPMeta2/Build/tools/packages.config.md5sum +++ b/SPMeta2/Build/tools/packages.config.md5sum @@ -1 +1 @@ -1E-30-75-ED-E8-A0-8E-6E-ED-7C-7F-40-98-54-8D-A7 +1E-62-29-E0-92-F7-45-50-B7-75-44-21-29-0B-0C-48 From bc152cb629c5e47ad889d46821424aa86506434a Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sun, 12 Mar 2017 01:00:50 -0800 Subject: [PATCH 24/53] + Incremental provision seems to ignore content type field links #976 --- SPMeta2/Build/tools/packages.config | 2 +- .../Impl/ModelNodes/ModelNodesTests.cs | 87 +++++++++++++++++ ...ncrementalModelTreeTraverseServiceTests.cs | 73 ++++++++++---- .../SPMeta2.Regression.Tests.csproj | 1 + .../DefaultModelNodePropertyBagValue.cs | 21 ++++ SPMeta2/SPMeta2/Common/ModelHash.cs | 3 +- .../SPMeta2/Extensions/ModelNodeExtensions.cs | 97 ++++++++++++++++--- SPMeta2/SPMeta2/SPMeta2.csproj | 1 + ...faultIncrementalModelPrettyPrintService.cs | 12 +-- ...aultIncrementalModelTreeTraverseService.cs | 41 +++----- 10 files changed, 271 insertions(+), 67 deletions(-) create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Impl/ModelNodes/ModelNodesTests.cs create mode 100644 SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs diff --git a/SPMeta2/Build/tools/packages.config b/SPMeta2/Build/tools/packages.config index e5d5b8e40..2da95bd96 100644 --- a/SPMeta2/Build/tools/packages.config +++ b/SPMeta2/Build/tools/packages.config @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelNodes/ModelNodesTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelNodes/ModelNodesTests.cs new file mode 100644 index 000000000..d2d4eb426 --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelNodes/ModelNodesTests.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Text; + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Attributes.Capabilities; +using SPMeta2.Attributes.Identity; +using SPMeta2.Attributes.Regression; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Models; +using SPMeta2.Standard.Definitions.Fields; +using SPMeta2.Syntax.Default; +using SPMeta2.Utils; +using SPMeta2.Standard.Definitions; +using SPMeta2.Regression.Tests.Config; +using SPMeta2.Services; +using SPMeta2.Containers.Utils; +using SPMeta2.Standard.Definitions.Webparts; +using SPMeta2.Regression.Utils; +using SPMeta2.Containers.Services.Rnd; +using SPMeta2.Containers.Services; + +using SPMeta2.Extensions; + +namespace SPMeta2.Regression.Tests.Impl.Definitions +{ + [TestClass] + public class ModelNodesTests + { + #region constructors + + public ModelNodesTests() + { + Rnd = new DefaultRandomService(); + } + + #endregion + + #region properties + + public RandomService Rnd { get; set; } + + #endregion + + #region tests + + [TestMethod] + [TestCategory("CI.Core")] + [TestCategory("Regression.ModelNodes.ExtensionMethods")] + public void Can_Use_ModelNode_SetPropertyBagValue() + { + var modelNode = new ModelNode(); + + var name = Rnd.String(); + var value = Rnd.String(); + + modelNode.SetPropertyBagValue(name, value); + + Assert.AreEqual(value, modelNode.GetPropertyBagValue(name)); + Assert.AreEqual(value, modelNode.PropertyBag.FirstOrDefault(p => p.Name == name).Value); + } + + [TestMethod] + [TestCategory("CI.Core")] + [TestCategory("Regression.ModelNodes.ExtensionMethods")] + public void Can_Use_ModelNode_SetNonPersistentPropertyBagValue() + { + var modelNode = new ModelNode(); + + var name = Rnd.String(); + var value = Rnd.String(); + + modelNode.SetNonPersistentPropertyBagValue(name, value); + + Assert.AreEqual(value, modelNode.GetNonPersistentPropertyBagValue(name)); + Assert.AreEqual(value, modelNode.NonPersistentPropertyBag.FirstOrDefault(p => p.Name == name).Value); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs index 06b200d67..af70e0ab9 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs @@ -59,11 +59,8 @@ public IncrementalModelTreeTraverseServiceTests() public void Can_Create_IncrementalModelTreeTraverseService() { var service = new DefaultIncrementalModelTreeTraverseService(); - } - - #endregion #region switching the mode @@ -118,18 +115,8 @@ public void Can_Reset_ProvisionServiceMode() #region non-singlentons - [TestMethod] - [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] - [TestCategory("CI.Core")] - public void Incremental_Update_NonSingleton_ModelNodes_SameModels() + public void Internal_Incremental_Update_NonSingleton_ModelNodes_SameModels(ModelNode model) { - var model = SPMeta2Model.NewSiteModel(site => - { - site.AddRandomField(); - site.AddRandomField(); - site.AddRandomField(); - }); - var prevModel = model; var currentModel = model; @@ -157,6 +144,57 @@ public void Incremental_Update_NonSingleton_ModelNodes_SameModels() // should be NONE of the nodes to update on the same model Assert.AreEqual(0, secondProvisionService.ModelNodesToUpdate.Count); Assert.AreEqual(GetTotalModelNodeCount(model), secondProvisionService.ModelNodesToSkip.Count); + + RegressionUtils.WriteLine("Current model hash:"); + RegressionUtils.WriteLine(Environment.NewLine + secondProvisionService.CurrentModelHash); + + foreach (var modelNodeHash in secondProvisionService.CurrentModelHash.ModelNodes) + { + RegressionUtils.WriteLine(string.Format("- {0}", modelNodeHash.ToString())); + } + } + + [TestMethod] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] + [TestCategory("CI.Core")] + public void Incremental_Update_NonSingleton_ModelNodes_Two_Level_Model() + { + var contentTypeCounts = Rnd.Int(3) + 3; + var fieldLinksCount = Rnd.Int(3) + 3; + + var model = SPMeta2Model.NewSiteModel(site => + { + for (var ctIndex = 0; ctIndex < contentTypeCounts; ctIndex++) + { + site.AddRandomContentType(contentType => + { + for (var flIndex = 0; flIndex < fieldLinksCount; flIndex++) + { + contentType.AddContentTypeFieldLink(new ContentTypeFieldLinkDefinition + { + FieldId = Rnd.Guid() + }); + } + }); + } + }); + + Internal_Incremental_Update_NonSingleton_ModelNodes_SameModels(model); + } + + [TestMethod] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.NonSingleton")] + [TestCategory("CI.Core")] + public void Incremental_Update_NonSingleton_ModelNodes_SameModels() + { + var model = SPMeta2Model.NewSiteModel(site => + { + site.AddRandomField(); + site.AddRandomField(); + site.AddRandomField(); + }); + + Internal_Incremental_Update_NonSingleton_ModelNodes_SameModels(model); } [TestMethod] @@ -272,8 +310,6 @@ public void Incremental_Update_NonSingleton_ModelNodes_PlusRandomModelNodes() model.AddRandomField(f => { newField1 = f; }); model.AddRandomField(f => { newField2 = f; }); - - // check one more with second provision var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); @@ -293,12 +329,13 @@ public void Incremental_Update_NonSingleton_ModelNodes_PlusRandomModelNodes() // new field must be marked as to be updated Assert.IsTrue(newField1.Options.RequireSelfProcessing); Assert.IsTrue(newField2.Options.RequireSelfProcessing); + + RegressionUtils.WriteLine("Current model hash:"); + RegressionUtils.WriteLine(Environment.NewLine + secondProvisionService.CurrentModelHash); } #endregion - - #region utils protected ModelNode GetVeryRandomModel(Type definitionType, SPObjectModelType spObjectModelType) diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index 49c9ea6d1..f4c024c49 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -169,6 +169,7 @@ + diff --git a/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs b/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs new file mode 100644 index 000000000..b3d10a3f3 --- /dev/null +++ b/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SPMeta2.Common +{ + public static class DefaultModelNodePropertyBagValue + { + public static class Sys + { + public static class IncrementalProvision + { + public static string PersistenceStorageModelId = "_sys.IncrementalProvision.PersistenceStorageModelId"; + } + + public static string IncrementalRequireSelfProcessingValue = "_sys.IncrementalRequireSelfProcessingValue"; + } + } +} diff --git a/SPMeta2/SPMeta2/Common/ModelHash.cs b/SPMeta2/SPMeta2/Common/ModelHash.cs index 67368f5bc..9f40903cc 100644 --- a/SPMeta2/SPMeta2/Common/ModelHash.cs +++ b/SPMeta2/SPMeta2/Common/ModelHash.cs @@ -70,7 +70,8 @@ public class ModelNodeHash public override string ToString() { - return string.Format("Identity key:[{0}] Definition hash:[{1}]", DefinitionIdentityKey, DefinitionHash); + return string.Format("Definition hash:[{0}] Full path hash:[{1}] Identity key hash:[{2}]", + DefinitionHash, DefinitionFullPathHash, DefinitionIdentityKeyHash); } #endregion diff --git a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs index 2b32e43f4..9dda48707 100644 --- a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs +++ b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs @@ -6,6 +6,8 @@ using SPMeta2.Models; using SPMeta2.Services; using SPMeta2.Syntax.Default; +using SPMeta2.Common; +using SPMeta2.Utils; namespace SPMeta2.Extensions { @@ -236,27 +238,96 @@ public static ModelValidationResultSet Validate(this M #endregion - #region incremental provision - + #region model node properties - private static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) - where TModelNode : ModelNode + internal static void InternalSetPropertyBagValue(List values, + string name, + string value) { - var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag - .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); + var currentValue = values.FirstOrDefault(p => !string.IsNullOrEmpty(p.Name) + && p.Name.ToUpper() == name.ToUpper()); - if (incrementalRequireSelfProcessingValue == null) + if (currentValue == null) { - incrementalRequireSelfProcessingValue = new PropertyBagValue + currentValue = new PropertyBagValue { - Name = "_sys.IncrementalProvision.PersistenceStorageModelId", - Value = modelId + Name = name, + Value = value }; - modelNode.PropertyBag.Add(incrementalRequireSelfProcessingValue); + values.Add(currentValue); + } + + currentValue.Value = value; + } + + internal static string InternalGetPropertyBagValue(List values, + string name) + { + var currentValue = values.FirstOrDefault(p => !string.IsNullOrEmpty(p.Name) + && p.Name.ToUpper() == name.ToUpper()); + + if (currentValue != null) + { + return currentValue.Value; } - incrementalRequireSelfProcessingValue.Value = modelId; + return null; + } + + public static TModelNode SetNonPersistentPropertyBagValue(this TModelNode modelNode, + string name, + string value) + where TModelNode : ModelNode + { + InternalSetPropertyBagValue(modelNode.NonPersistentPropertyBag, name, value); + + return modelNode; + } + + + public static string GetNonPersistentPropertyBagValue(this TModelNode modelNode, + string name) + where TModelNode : ModelNode + { + return InternalGetPropertyBagValue(modelNode.NonPersistentPropertyBag, name); + } + public static TModelNode SetPropertyBagValue(this TModelNode modelNode, + string name, + string value) + where TModelNode : ModelNode + { + InternalSetPropertyBagValue(modelNode.PropertyBag, name, value); + + return modelNode; + } + + public static string GetPropertyBagValue(this TModelNode modelNode, + string name) + where TModelNode : ModelNode + { + return InternalGetPropertyBagValue(modelNode.PropertyBag, name); + } + + #endregion + + #region incremental provision + + public static bool GetIncrementalRequireSelfProcessingValue(this TModelNode modelNode) + where TModelNode : ModelNode + { + var incrementalRequireSelfProcessingValue = modelNode.GetNonPersistentPropertyBagValue(DefaultModelNodePropertyBagValue.Sys.IncrementalRequireSelfProcessingValue); + + if (incrementalRequireSelfProcessingValue != null) + return ConvertUtils.ToBoolWithDefault(incrementalRequireSelfProcessingValue, false); + + return false; + } + + private static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) + where TModelNode : ModelNode + { + modelNode.SetPropertyBagValue(DefaultModelNodePropertyBagValue.Sys.IncrementalProvision.PersistenceStorageModelId, modelId); return modelNode; } @@ -282,5 +353,7 @@ public static WebModelNode SetIncrementalProvisionModelId(this WebModelNode mode } #endregion + + } } diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index f9093eed5..69e0f8216 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -141,6 +141,7 @@ + diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs index a6aa26190..44287264a 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelPrettyPrintService.cs @@ -4,6 +4,8 @@ using System.Text; using SPMeta2.Models; using SPMeta2.Utils; +using SPMeta2.Extensions; +using SPMeta2.Common; namespace SPMeta2.Services.Impl { @@ -13,15 +15,9 @@ public class DefaultIncrementalModelPrettyPrintService : DefaultModelPrettyPrint protected override string GetCurrentIntent(ModelNode modelNode, string currentIndent) { - bool? shouldDeploy = false; + var shouldDeployAsIncremental = modelNode.GetIncrementalRequireSelfProcessingValue(); - var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag - .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); - - if (incrementalRequireSelfProcessingValue != null) - shouldDeploy = ConvertUtils.ToBoolWithDefault(incrementalRequireSelfProcessingValue.Value, false); - - if (shouldDeploy.Value) + if (shouldDeployAsIncremental) return string.Format("[+] {0}", currentIndent); return string.Format("[-] {0}", currentIndent); diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index 9b7c16080..eec015f2a 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -10,6 +10,7 @@ using SPMeta2.Utils; using SPMeta2.Syntax.Default; using SPMeta2.ModelHosts; +using SPMeta2.Extensions; namespace SPMeta2.Services.Impl { @@ -143,12 +144,16 @@ protected override void OnBeforeDeployModelNode(object modelHost, ModelNode mode if (isSingleIdentity) { - TraceService.Information(0, "Detected singleton definition. Incremental update for such definitions isn't supported yet. Skipping."); + TraceService.InformationFormat(0, + "Detected singleton definition [{0}]. Incremental update for such definitions isn't supported yet. Skipping.", + currentDefinition); return; } else { - TraceService.Information(0, "Calculating hashes for node and definition"); + TraceService.InformationFormat(0, + "Calculating hashes for node and definition:[{0}]", + currentDefinition); } //var currentNodeHashHash = HashService.GetHashCode(currentModelNode); @@ -216,23 +221,9 @@ protected override void OnBeforeDeployModelNode(object modelHost, ModelNode mode protected override void OnAfterDeployModelNode(object modelHost, ModelNode modelNode) { - var incrementalRequireSelfProcessingValue = modelNode.NonPersistentPropertyBag - .FirstOrDefault(p => p.Name == "_sys.IncrementalRequireSelfProcessingValue"); - - if (incrementalRequireSelfProcessingValue == null) - { - incrementalRequireSelfProcessingValue = new PropertyBagValue - { - Name = "_sys.IncrementalRequireSelfProcessingValue", - Value = modelNode.Options.RequireSelfProcessing.ToString() - }; - - modelNode.NonPersistentPropertyBag.Add(incrementalRequireSelfProcessingValue); - } - else - { - incrementalRequireSelfProcessingValue.Value = modelNode.Options.RequireSelfProcessing.ToString(); - } + var incrementalRequireSelfProcessingValue = modelNode.SetNonPersistentPropertyBagValue( + DefaultModelNodePropertyBagValue.Sys.IncrementalRequireSelfProcessingValue, + modelNode.Options.RequireSelfProcessing.ToString()); // restore model state modelNode.Options.RequireSelfProcessing = OriginalRequireSelfProcessingValue; @@ -282,12 +273,12 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod { TraceService.Information(0, "Model hash restore: found [{0}] storage impl in Configuration.PersistenceStorages. Automatic model hash management is used"); - var modelIdProperty = modelNode.PropertyBag.FirstOrDefault(p => p.Name == "_sys.IncrementalProvision.PersistenceStorageModelId"); + var modelIdProperty = modelNode.GetPropertyBagValue(DefaultModelNodePropertyBagValue.Sys.IncrementalProvision.PersistenceStorageModelId); if (modelIdProperty == null) throw new SPMeta2Exception("IncrementalProvisionModelId is not set. Either clean PersistenceStorages and handle model hash persistence manually or set .PersistenceStorageModelId"); - var modelId = modelIdProperty.Value; + var modelId = modelIdProperty; var objectId = string.Format("{0}.{1}", DefaultPersistenceModelIdPrefix, modelId); var serializer = ServiceContainer.Instance.GetService(); @@ -297,8 +288,6 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod typeof(ModelNodeHash) }); - - foreach (var storage in storages) { TraceService.Information(0, string.Format("Restoring model hash with object id:[{0}] using storage impl [{1}]", @@ -346,15 +335,13 @@ protected override void OnAfterDeployModel(object modelHost, ModelNode modelNode { TraceService.Information(0, "Model hash save: found [{0}] storage impl in Configuration.PersistenceStorages. Automatic model hash management is used"); - var modelIdProperty = - modelNode.PropertyBag.FirstOrDefault( - p => p.Name == "_sys.IncrementalProvision.PersistenceStorageModelId"); + var modelIdProperty = modelNode.GetPropertyBagValue(DefaultModelNodePropertyBagValue.Sys.IncrementalProvision.PersistenceStorageModelId); if (modelIdProperty == null) throw new SPMeta2Exception( "IncrementalProvisionModelId is not set. Either clean PersistenceStorages and handle model hash persistence manually or set .PersistenceStorageModelId"); - var modelId = modelIdProperty.Value; + var modelId = modelIdProperty; var objectId = string.Format("{0}.{1}", DefaultPersistenceModelIdPrefix, modelId); var serializer = ServiceContainer.Instance.GetService(); From 29c8c2f10195e38c67ec538edb56ea1937aec0b0 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sun, 12 Mar 2017 01:16:48 -0800 Subject: [PATCH 25/53] + SPMeta2 v1.2.120, March 2017 --- SPMeta2/Build/build.json | 56 +++++++++---------- SPMeta2/Build/tools/packages.config.md5sum | 2 +- .../DefaultModelNodePropertyBagValue.cs | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index 6f6386083..edd634db8 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta1" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta1", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta1" + "Version": "1.2.120" }, { "Id": "Microsoft.SharePointOnline.CSOM", diff --git a/SPMeta2/Build/tools/packages.config.md5sum b/SPMeta2/Build/tools/packages.config.md5sum index 7ef7fbb5a..8b81cf99a 100644 --- a/SPMeta2/Build/tools/packages.config.md5sum +++ b/SPMeta2/Build/tools/packages.config.md5sum @@ -1 +1 @@ -1E-62-29-E0-92-F7-45-50-B7-75-44-21-29-0B-0C-48 +93-A8-F9-3B-FF-40-99-D5-E4-C1-E0-AF-32-14-3A-BB diff --git a/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs b/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs index b3d10a3f3..3ec9c820b 100644 --- a/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs +++ b/SPMeta2/SPMeta2/Common/DefaultModelNodePropertyBagValue.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.Common { From c890e527e9a1f33bd90cad61d252cd3c49760a0c Mon Sep 17 00:00:00 2001 From: Support Date: Tue, 14 Mar 2017 00:18:50 +1100 Subject: [PATCH 26/53] + SPMeta2 v1.2.120-beta2, March 2017 --- SPMeta2/Build/build.json | 56 +- .../Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.CSOM/Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Nintex/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.O365/Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- ...ncrementalModelTreeTraverseServiceTests.cs | 117 ++-- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Service/RegressionTraceService.cs | 6 - .../Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.SSOM/Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2/Properties/AssemblyInfo.cs | 2 +- ...aultIncrementalModelTreeTraverseService.cs | 184 +++++- .../Services/Impl/TraceSourceService.cs | 313 ++++++---- SPMeta2/SPMeta2/Services/TraceServiceBase.cs | 573 ++++++++++-------- SPMeta2/SPMeta2/Utils/ReflectionUtils.cs | 63 +- SPMeta2/SPMeta2/Utils/ToStringResult.cs | 179 +++--- 31 files changed, 971 insertions(+), 566 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index edd634db8..a55fb72b3 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120" + "Version": "1.2.120-beta2" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120", + "Version": "1.2.120-beta2", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120" + "Version": "1.2.120-beta2" }, { "Id": "Microsoft.SharePointOnline.CSOM", diff --git a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs index d88382c87..571a310c6 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs index 75fde9e07..4ad56025f 100644 --- a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs index e92283faa..148f95cee 100644 --- a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.17072.1315")] \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs index e055afa8b..04629b7f0 100644 --- a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs index 378e4f09b..4fa2c1be7 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.17072.1315")] \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs index ecc8e56ad..1bd424888 100644 --- a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs index 4c7b6594b..232949144 100644 --- a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs index b7ba1f92e..01d722c17 100644 --- a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs index e25d3b120..666f454ad 100644 --- a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17061.0922")] +[assembly: AssemblyFileVersion("1.0.17072.1315")] diff --git a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs index 0b9b6d342..554550114 100644 --- a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17061.0922")] +[assembly: AssemblyFileVersion("1.0.17072.1315")] diff --git a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs index 98555211d..04b15c3af 100644 --- a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17061.0922")] +[assembly: AssemblyFileVersion("1.0.17072.1315")] diff --git a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs index f472b4d8b..e8abbb241 100644 --- a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs index d4cefa77f..e244e4cb4 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs index 1f02f80ef..99e14828a 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs index e3dfa7c82..c2f3cdcba 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs index a4ae303ca..24a6507c2 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs index a0e9cf4f3..11da0bfc4 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs index af70e0ab9..1ceaf020c 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/IncrementalModelTreeTraverseServiceTests.cs @@ -200,8 +200,32 @@ public void Incremental_Update_NonSingleton_ModelNodes_SameModels() [TestMethod] [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.Random")] [TestCategory("CI.Core")] - public void Incremental_Update_AllDefinitions_As_RandomModels() + public void Incremental_Update_AllDefinitions_As_RandomModels_NoCache() { + Incremental_Update_AllDefinitions_As_RandomModels_Internal(service => + { + service.EnableCaching = false; + }, true, 1); + } + + [TestMethod] + [TestCategory("Regression.Services.IncrementalModelTreeTraverseService.Random")] + [TestCategory("CI.Core")] + public void Incremental_Update_AllDefinitions_As_RandomModels_WithCache() + { + Incremental_Update_AllDefinitions_As_RandomModels_Internal(service => + { + + }, true, 1); + } + + public void Incremental_Update_AllDefinitions_As_RandomModels_Internal( + Action configureService, + bool silentMode, + int iterationCount) + { + var m2logService = ServiceContainer.Instance.GetService(); + var spMetaAssembly = typeof(FieldDefinition).Assembly; var spMetaStandardAssembly = typeof(TaxonomyFieldDefinition).Assembly; @@ -214,67 +238,86 @@ public void Incremental_Update_AllDefinitions_As_RandomModels() var allDefinitionTypesCount = allDefinitionTypes.Count(); var currentDefinitionTypeIndex = 0; - foreach (var definitionType in allDefinitionTypes) + for (int it = 0; it < iterationCount; it++) { - currentDefinitionTypeIndex++; - RegressionUtils.WriteLine(string.Format("[{0}/{1}] Testing definition:[{2}]", - new object[] { + foreach (var definitionType in allDefinitionTypes) + { + currentDefinitionTypeIndex++; + + if (!silentMode) + { + RegressionUtils.WriteLine(string.Format("[{0}/{1}] Testing definition:[{2}]", + new object[] { currentDefinitionTypeIndex, allDefinitionTypesCount, definitionType.FullName })); + } - var model = GetVeryRandomModel(definitionType, SPObjectModelType.CSOM); + var model = GetVeryRandomModel(definitionType, SPObjectModelType.CSOM); - var prevModel = model; - var currentModel = model; + var prevModel = model; + var currentModel = model; - var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); + var firstProvisionService = new FakeIncrementalModelTreeTraverseService(); - firstProvisionService.PreviousModelHash = new ModelHash(); - firstProvisionService.Traverse(null, currentModel); + if (configureService != null) + configureService(firstProvisionService); - var trace = ServiceContainer.Instance.GetService(); + firstProvisionService.PreviousModelHash = new ModelHash(); + firstProvisionService.Traverse(null, currentModel); - // check one more with second provision - var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); + var trace = ServiceContainer.Instance.GetService(); - RegressionUtils.WriteLine("Original model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + // check one more with second provision + var secondProvisionService = new FakeIncrementalModelTreeTraverseService(); - secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; - secondProvisionService.Traverse(null, currentModel); + if (configureService != null) + configureService(secondProvisionService); - // trace size of the model hash + amount if the aritfacts - var modelNodesCount = 0; - model.WithNodesOfType(n => { modelNodesCount++; }); + if (!silentMode) + { + RegressionUtils.WriteLine("Original model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + } + + secondProvisionService.PreviousModelHash = firstProvisionService.CurrentModelHash; + secondProvisionService.Traverse(null, currentModel); + + // trace size of the model hash + amount if the aritfacts + var modelNodesCount = 0; + model.WithNodesOfType(n => { modelNodesCount++; }); - var serializer = ServiceContainer.Instance.GetService(); - serializer.RegisterKnownTypes(new[] + var serializer = ServiceContainer.Instance.GetService(); + serializer.RegisterKnownTypes(new[] { typeof(ModelHash), typeof(ModelNodeHash) }); - var data = Encoding.UTF8.GetBytes(serializer.Serialize(firstProvisionService.CurrentModelHash)); + var data = Encoding.UTF8.GetBytes(serializer.Serialize(firstProvisionService.CurrentModelHash)); - var persistanceFileService = new DefaultFileSystemPersistenceStorage(); - persistanceFileService.SaveObject( - string.Format("incremental_state_m2.regression-artifact-{1}-{0}", definitionType.Name, modelNodesCount), - data); + var persistanceFileService = new DefaultFileSystemPersistenceStorage(); + persistanceFileService.SaveObject( + string.Format("incremental_state_m2.regression-artifact-{1}-{0}", definitionType.Name, modelNodesCount), + data); - RegressionUtils.WriteLine(string.Empty); - RegressionUtils.WriteLine("Provisioned model:"); - RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + if (!silentMode) + { + RegressionUtils.WriteLine(string.Empty); + RegressionUtils.WriteLine("Provisioned model:"); + RegressionUtils.WriteLine(ModelPrintService.PrintModel(currentModel)); + } - // asserts - var expectedProvisionNodesCount = 0; + // asserts + var expectedProvisionNodesCount = 0; - expectedProvisionNodesCount += secondProvisionService.GetTotalSingleIdentityNodeCount(); - expectedProvisionNodesCount += secondProvisionService.GetTotalIgnoredNodeCount(); + expectedProvisionNodesCount += secondProvisionService.GetTotalSingleIdentityNodeCount(); + expectedProvisionNodesCount += secondProvisionService.GetTotalIgnoredNodeCount(); - Assert.AreEqual(expectedProvisionNodesCount, secondProvisionService.ModelNodesToUpdate.Count); - Assert.AreEqual(GetTotalModelNodeCount(model) - expectedProvisionNodesCount, secondProvisionService.ModelNodesToSkip.Count); + Assert.AreEqual(expectedProvisionNodesCount, secondProvisionService.ModelNodesToUpdate.Count); + Assert.AreEqual(GetTotalModelNodeCount(model) - expectedProvisionNodesCount, secondProvisionService.ModelNodesToSkip.Count); + } } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs index 38527d69f..263e53b7c 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs index af2977bd0..ffd213fc1 100644 --- a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17061.0922")] +[assembly: AssemblyFileVersion("1.0.17072.1315")] diff --git a/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs b/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs index 7e09c01d4..87324cd11 100644 --- a/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs +++ b/SPMeta2/SPMeta2.Regression/Service/RegressionTraceService.cs @@ -43,12 +43,6 @@ protected enum Level #region props - public bool IsVerboseEnabled { get; set; } - public bool IsInformationEnabled { get; set; } - public bool IsWarningEnabled { get; set; } - public bool IsErrorEnabled { get; set; } - public bool IsCriticalEnabled { get; set; } - public string LogFilePath { get; set; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs index 53bcde344..25108a6a0 100644 --- a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs index a5c86bb24..23dfc580a 100644 --- a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs index cf6edd763..de382df44 100644 --- a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs index fc6660a93..062632853 100644 --- a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17061.0922")] +[assembly: AssemblyFileVersion("1.2.17072.1315")] diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs index eec015f2a..e825f98b0 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultIncrementalModelTreeTraverseService.cs @@ -29,12 +29,18 @@ public DefaultIncrementalModelTreeTraverseService() DefaultDefinitionIdentityKeySeparator = ";"; DefaultPersistenceModelIdPrefix = "spmeta2.incremental_state"; + + EnableCaching = true; } #endregion #region properties + public bool EnableCaching { get; set; } + + protected bool OriginalRequireSelfProcessingValue { get; set; } + public IncrementalProvisionConfig Configuration { get; set; } public ModelHash PreviousModelHash { get; set; } @@ -49,55 +55,182 @@ public DefaultIncrementalModelTreeTraverseService() public string DefaultPersistenceModelIdPrefix { get; set; } - #endregion #region methods protected string GetHashString(object value) { - return _hashService.GetHashCode(value); + if (EnableCaching) + { + if (!_cache4Object2Hash.ContainsKey(value)) + { + var hash = _hashService.GetHashCode(value); + + TraceService.VerboseFormat(0, + "GetHashString() - cold hit, adding value to cache:[{0}] -> [{1}]", + new object[] { value, hash }, + null); + + _cache4Object2Hash.Add(value, hash); + } + else + { + var hash = _cache4Object2Hash[value]; + + TraceService.VerboseFormat(0, + "GetHashString() - hot hit, returning value from cache:[{0}] -> [{1}]", + new object[] { value, hash }, + null); + } + + return _cache4Object2Hash[value]; + } + else + { + var hash = _hashService.GetHashCode(value); + + TraceService.VerboseFormat(0, + "GetHashString() - hot hit, returning value from cache:[{0}] -> [{1}]", + new object[] { value, hash }, + null); + + return hash; + } } protected virtual bool IsSingletonIdentityDefinition(DefinitionBase definition) { var definitionType = definition.GetType(); - var isInstanceIdentity = definitionType.GetCustomAttributes(typeof(SingletonIdentityAttribute), true).Any(); - return isInstanceIdentity; + if (EnableCaching) + { + if (!_cache4SingletonIdentityTypes.ContainsKey(definitionType)) + { + var isInstanceIdentity = definitionType.GetCustomAttributes(typeof(SingletonIdentityAttribute), true).Any(); + + TraceService.VerboseFormat(0, + "IsSingletonIdentityDefinition() - cold hit, adding value to cache:[{0}] -> [{1}]", + new object[] { definitionType, isInstanceIdentity }, + null); + + _cache4SingletonIdentityTypes.Add(definitionType, isInstanceIdentity); + } + else + { + var isInstanceIdentity = _cache4SingletonIdentityTypes[definitionType]; + + TraceService.VerboseFormat(0, + "IsSingletonIdentityDefinition() - hot hit, returning value from cache:[{0}] -> [{1}]", + new object[] { definitionType, isInstanceIdentity }, + null); + + } + + return _cache4SingletonIdentityTypes[definitionType]; + } + else + { + var isInstanceIdentity = definitionType.GetCustomAttributes(typeof(SingletonIdentityAttribute), true).Any(); + + TraceService.VerboseFormat(0, + "IsSingletonIdentityDefinition() - no caching. Returning value:[{0}] -> [{1}]", + new object[] { definitionType, isInstanceIdentity }, + null); + + return isInstanceIdentity; + } } - protected virtual string GetDefinitionIdentityKey(DefinitionBase definition) + protected virtual void ClearCaches() { - var definitionType = definition.GetType(); + // don't need to clear that one + // can reuse Type->Boolean mapping + // _cache4SingletonIdentityTypes.Clear(); - var isInstanceIdentity = IsSingletonIdentityDefinition(definition); + // clear identity keys for definitions + _cache4DefinitionIdentityKey.Clear(); - if (isInstanceIdentity) + // clear actual object cache - Object->Hash + _cache4Object2Hash.Clear(); + } + + protected Dictionary _cache4DefinitionIdentityKey = new Dictionary(); + protected Dictionary _cache4SingletonIdentityTypes = new Dictionary(); + protected Dictionary _cache4Object2Hash = new Dictionary(); + + protected virtual string GetDefinitionIdentityKey(DefinitionBase definitionValue) + { + Func calculateDefinitionIdentityKey = (definition) => { - throw new SPMeta2Exception(string.Format( - "definitions of type:[{0}] don't support incremental updates yet", - definitionType)); - } + var definitionType = definition.GetType(); + + var isInstanceIdentity = IsSingletonIdentityDefinition(definition); + + if (isInstanceIdentity) + { + throw new SPMeta2Exception(string.Format( + "definitions of type:[{0}] don't support incremental updates yet", + definitionType)); + } + + var keyProperties = definitionType.GetProperties() + .Where(p => p.GetCustomAttributes(typeof(IdentityKeyAttribute), true).Any()) + .OrderBy(p => p.Name); + + var identityKeyValues = new Dictionary(); + + foreach (var keyProp in keyProperties) + { + var keyName = keyProp.Name; + var keyValue = ConvertUtils.ToString(ReflectionUtils.GetPropertyValue(definition, keyProp.Name)); - var keyProperties = definitionType.GetProperties() - .Where(p => p.GetCustomAttributes(typeof(IdentityKeyAttribute), true).Any()) - .OrderBy(p => p.Name); + identityKeyValues.Add(keyName, keyValue); + } + + var resultIdentityKey = string.Join(DefaultDefinitionIdentityKeySeparator, + identityKeyValues.Select(v => string.Format("{0}:{1}", v.Key, v.Value)).ToArray()); - var identityKeyValues = new Dictionary(); + return resultIdentityKey; + }; - foreach (var keyProp in keyProperties) + if (EnableCaching) { - var keyName = keyProp.Name; - var keyValue = ConvertUtils.ToString(ReflectionUtils.GetPropertyValue(definition, keyProp.Name)); + if (!_cache4DefinitionIdentityKey.ContainsKey(definitionValue)) + { + var resultIdentityKey = calculateDefinitionIdentityKey(definitionValue); + + TraceService.VerboseFormat(0, + "GetDefinitionIdentityKey() - cold hit, adding value to cache:[{0}] -> [{1}]", + new object[] { definitionValue, resultIdentityKey }, + null); + + + _cache4DefinitionIdentityKey.Add(definitionValue, resultIdentityKey); + } + else + { + var resultIdentityKey = _cache4DefinitionIdentityKey[definitionValue]; - identityKeyValues.Add(keyName, keyValue); + TraceService.VerboseFormat(0, + "GetDefinitionIdentityKey() - hot hit, returning value from cache:[{0}] -> [{1}]", + new object[] { definitionValue, resultIdentityKey }, + null); + } + + return _cache4DefinitionIdentityKey[definitionValue]; } + else + { + var resultIdentityKey = calculateDefinitionIdentityKey(definitionValue); - var resultIdentityKey = string.Join(DefaultDefinitionIdentityKeySeparator, - identityKeyValues.Select(v => string.Format("{0}:{1}", v.Key, v.Value)).ToArray()); + TraceService.VerboseFormat(0, + "GetDefinitionIdentityKey() - no caching. Returning value:[{0}] -> [{1}]", + new object[] { definitionValue, resultIdentityKey }, + null); - return resultIdentityKey; + return resultIdentityKey; + } } protected virtual string GetDefinitionFullPath(bool asHash) @@ -265,6 +398,9 @@ protected override void OnBeforeDeployModel(object modelHost, ModelNode modelNod // clean up current model hash CurrentModelHash = new ModelHash(); + ClearCaches(); + + TraceService.InformationFormat(0, "Starting incremental provision with EnableCaching = {0}", EnableCaching); var storages = ResolvePersistenceStorages(modelHost, modelNode); @@ -440,7 +576,5 @@ protected virtual List ResolvePersistenceStorages } #endregion - - protected bool OriginalRequireSelfProcessingValue { get; set; } } } diff --git a/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs b/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs index 9616b606f..dcb685e9b 100644 --- a/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs @@ -1,114 +1,199 @@ -using System; -using System.Diagnostics; -using SPMeta2.Utils; - -namespace SPMeta2.Services.Impl -{ - public class TraceSourceService : TraceServiceBase - { - #region properties - - public TraceSourceService() - : this("SPMeta2") - { - } - - public TraceSourceService(string traceSourceName) - { - TraceSource = new TraceSource(traceSourceName); - } - - #endregion - - #region properties - - public TraceSource TraceSource; - - #endregion - - #region methods - - public override void Critical(int id, object message, Exception exception) - { - TraceEvent(id, TraceEventType.Critical, message, exception); - } - - public override void Error(int id, object message, Exception exception) - { - TraceEvent(id, TraceEventType.Error, message, exception); - } - - public override void Warning(int id, object message, Exception exception) - { - TraceEvent(id, TraceEventType.Warning, message, exception); - } - - public override void Information(int id, object message, Exception exception) - { - TraceEvent(id, TraceEventType.Information, message, exception); - } - - public override void Verbose(int id, object message, Exception exception) - { - TraceEvent(id, TraceEventType.Verbose, message, exception); - } - - #endregion - - #region utils - - protected virtual void TraceEvent(int id, TraceEventType messageType, object message, Exception exception) - { - var traceString = string.Empty; - var messageString = message == null ? string.Empty : message.ToString(); - - if (exception != null) - { - var subMessage = messageString; - - if (!subMessage.EndsWith(".")) - subMessage += "."; - - traceString = string.Format("{0} Exception: [{1}]", subMessage, exception); - } - else - { - var subMessage = messageString; - - if (!subMessage.EndsWith(".")) - subMessage += "."; - - traceString = string.Format("{0}", subMessage); - } - - TraceSource.TraceEvent(messageType, id, traceString); - TraceSource.Flush(); - } - - #endregion - - public override void TraceActivityStart(int id, object message) - { - TraceSource.TraceEvent(TraceEventType.Start, id, ConvertUtils.ToString(message)); - } - - public override void TraceActivityStop(int id, object message) - { - TraceSource.TraceEvent(TraceEventType.Stop, id, ConvertUtils.ToString(message)); - } - - public override void TraceActivityTransfer(int id, object message, Guid relatedActivityId) - { - TraceSource.TraceTransfer(id, ConvertUtils.ToString(message), relatedActivityId); - } - - public override Guid CurrentActivityId - { - get - { - return Trace.CorrelationManager.ActivityId; - } - set { Trace.CorrelationManager.ActivityId = value; } - } - } -} +using System; +using System.Diagnostics; +using SPMeta2.Utils; + +namespace SPMeta2.Services.Impl +{ + public class TraceSourceService : TraceServiceBase + { + #region properties + + public TraceSourceService() + : this("SPMeta2") + { + } + + public TraceSourceService(string traceSourceName) + { + TraceSource = new TraceSource(traceSourceName); + } + + #endregion + + #region properties + + public TraceSource TraceSource; + + public override bool IsCriticalEnabled + { + get + { + return ((TraceSource.Switch.Level & SourceLevels.Critical) == SourceLevels.Critical); + } + set + { + + } + } + + public override bool IsErrorEnabled + { + get + { + return ((TraceSource.Switch.Level & SourceLevels.Error) == SourceLevels.Error); + } + set + { + + } + } + + public override bool IsInformationEnabled + { + get + { + return ((TraceSource.Switch.Level & SourceLevels.Information) == SourceLevels.Information); + } + set + { + + } + } + + public override bool IsVerboseEnabled + { + get + { + return ((TraceSource.Switch.Level & SourceLevels.Verbose) == SourceLevels.Verbose); + } + set + { + + } + } + + public override bool IsWarningEnabled + { + get + { + return ((TraceSource.Switch.Level & SourceLevels.Warning) == SourceLevels.Warning); + } + set + { + + } + } + + #endregion + + #region methods + + public override void Critical(int id, object message, Exception exception) + { + if (IsCriticalEnabled) + { + TraceEvent(id, TraceEventType.Critical, message, exception); + } + } + + public override void Error(int id, object message, Exception exception) + { + if (IsErrorEnabled) + { + TraceEvent(id, TraceEventType.Error, message, exception); + } + } + + public override void Warning(int id, object message, Exception exception) + { + if (IsWarningEnabled) + { + TraceEvent(id, TraceEventType.Warning, message, exception); + } + } + + public override void Information(int id, object message, Exception exception) + { + if (IsInformationEnabled) + { + TraceEvent(id, TraceEventType.Information, message, exception); + } + } + + public override void Verbose(int id, object message, Exception exception) + { + if (IsVerboseEnabled) + { + TraceEvent(id, TraceEventType.Verbose, message, exception); + } + } + + #endregion + + #region utils + + protected virtual void TraceEvent(int id, TraceEventType messageType, object message, Exception exception) + { + var traceString = string.Empty; + var messageString = message == null ? string.Empty : message.ToString(); + + if (exception != null) + { + var subMessage = messageString; + + if (!subMessage.EndsWith(".")) + subMessage += "."; + + traceString = string.Format("{0} Exception: [{1}]", subMessage, exception); + } + else + { + var subMessage = messageString; + + if (!subMessage.EndsWith(".")) + subMessage += "."; + + traceString = string.Format("{0}", subMessage); + } + + TraceSource.TraceEvent(messageType, id, traceString); + + + if (AutoFlush) + { + TraceSource.Flush(); + } + } + + #endregion + + public override void Flush() + { + TraceSource.Flush(); + } + + public override void TraceActivityStart(int id, object message) + { + TraceSource.TraceEvent(TraceEventType.Start, id, ConvertUtils.ToString(message)); + } + + public override void TraceActivityStop(int id, object message) + { + TraceSource.TraceEvent(TraceEventType.Stop, id, ConvertUtils.ToString(message)); + } + + public override void TraceActivityTransfer(int id, object message, Guid relatedActivityId) + { + TraceSource.TraceTransfer(id, ConvertUtils.ToString(message), relatedActivityId); + } + + public override Guid CurrentActivityId + { + get + { + return Trace.CorrelationManager.ActivityId; + } + set { Trace.CorrelationManager.ActivityId = value; } + } + } +} diff --git a/SPMeta2/SPMeta2/Services/TraceServiceBase.cs b/SPMeta2/SPMeta2/Services/TraceServiceBase.cs index 5ae363d82..1dddf36ca 100644 --- a/SPMeta2/SPMeta2/Services/TraceServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/TraceServiceBase.cs @@ -1,248 +1,325 @@ -using System; -using System.Diagnostics; - -namespace SPMeta2.Services -{ - public abstract class TraceServiceBase - { - #region methods - - public virtual void Critical(int id, object message) - { - Critical(id, message, null); - } - - public abstract void Critical(int id, object message, Exception exception); - - public virtual void Error(int id, object message) - { - Error(id, message, null); - } - - public abstract void Error(int id, object message, Exception exception); - - public virtual void Warning(int id, object message) - { - Warning(id, message, null); - } - - public abstract void Warning(int id, object message, Exception exception); - - public virtual void Information(int id, object message) - { - Information(id, message, null); - } - - public abstract void Information(int id, object message, Exception exception); - - public virtual void Verbose(int id, object message) - { - Verbose(id, message, null); - } - - public abstract void Verbose(int id, object message, Exception exception); - - public abstract void TraceActivityStart(int id, object message); - public abstract void TraceActivityStop(int id, object message); - public abstract void TraceActivityTransfer(int id, object message, Guid relatedActivityId); - - public abstract Guid CurrentActivityId - { - get; - set; - } - - #endregion - } - - public static class TraceServiceBaseExtensions - { - #region information - - public static void InformationFormat(this TraceServiceBase traceService, int id, object message, object parameter) - { - InformationFormat(traceService, id, message, new object[] { parameter }); - } - - public static void InformationFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) - { - InformationFormat(traceService, id, message, parameters, null); - } - - public static void InformationFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) - { - if (message is string) - { - traceService.Information(id, string.Format(message as string, parameters), exception); - } - else - { - traceService.Information(id, message, exception); - } - } - - #endregion - - - #region warning - - public static void WarningFormat(this TraceServiceBase traceService, int id, object message, object parameter) - { - WarningFormat(traceService, id, message, new object[] { parameter }); - } - - public static void WarningFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) - { - WarningFormat(traceService, id, message, parameters, null); - } - - public static void WarningFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) - { - if (message is string) - { - traceService.Warning(id, string.Format(message as string, parameters), exception); - } - else - { - traceService.Warning(id, message, exception); - } - } - - #endregion - - #region verbose - - public static void VerboseFormat(this TraceServiceBase traceService, int id, object message, object parameter) - { - if (parameter == null) - VerboseFormat(traceService, id, message, new object[] { }); - else - VerboseFormat(traceService, id, message, new object[] { parameter }); - } - - public static void VerboseFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) - { - if (parameters == null) - VerboseFormat(traceService, id, message, new object[] { }, null); - else - VerboseFormat(traceService, id, message, parameters, null); - } - - public static void VerboseFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) - { - if (message is string && parameters != null && parameters.Length > 0) - { - traceService.Verbose(id, string.Format(message as string, parameters), exception); - } - else - { - traceService.Verbose(id, message, exception); - } - } - - #endregion - - #region error - - public static void ErrorFormat(this TraceServiceBase traceService, int id, object message, object parameter) - { - if (parameter == null) - ErrorFormat(traceService, id, message, new object[] { }); - else - ErrorFormat(traceService, id, message, new object[] { parameter }); - } - - public static void ErrorFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) - { - if (parameters == null) - ErrorFormat(traceService, id, message, new object[] { }, null); - else - ErrorFormat(traceService, id, message, parameters, null); - } - - public static void ErrorFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) - { - if (message is string && parameters != null && parameters.Length > 0) - { - traceService.Error(id, string.Format(message as string, parameters), exception); - } - else - { - traceService.Error(id, message, exception); - } - } - - #endregion - - } - - public class TraceMethodActivityScope : TraceActivityScope - { - public TraceMethodActivityScope(TraceServiceBase traceService, int eventId) - : base(traceService, eventId, new StackFrame(1).GetMethod().Name) - { - - } - } - - public class TraceActivityScope : IDisposable - { - #region constructors - - public TraceActivityScope(TraceServiceBase traceService, int eventId, string message) : - this(traceService, eventId, - string.Format("Starting: [{0}]", message), - string.Format("Ending: [{0}]", message)) - { - - } - - public TraceActivityScope(TraceServiceBase traceService, int eventId, string startMessage, string endMessage) - { - TraceService = traceService; - - var activityId = Guid.NewGuid(); - EventId = eventId; - - EndMessage = endMessage; - OldActivityId = TraceService.CurrentActivityId; - - TraceService.TraceActivityTransfer(eventId, startMessage, activityId); - TraceService.CurrentActivityId = activityId; - TraceService.TraceActivityStart(eventId, startMessage); - } - - #endregion - - #region properties - - public string EndMessage { get; set; } - - public Guid OldActivityId { get; set; } - public int EventId { get; set; } - - public TraceServiceBase TraceService { get; set; } - - #endregion - - #region methods - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - TraceService.TraceActivityStop(EventId, EndMessage); - TraceService.TraceActivityTransfer(EventId, EndMessage, OldActivityId); - TraceService.CurrentActivityId = OldActivityId; - } - } - - #endregion - } -} +using System; +using System.Diagnostics; + +namespace SPMeta2.Services +{ + public abstract class TraceServiceBase + { + #region constructors + + public TraceServiceBase() + { + // backward compatibility, always enabled but false for verbose + // inherited classes should override these returning true-false as per setup + + // some of the extension methods AND actual methods of the trace service implementation use + // use these flags to avoid String.Format() calculations before even hitting .Log() methods + + // that is a trade off due to performance implications over .ToString() calls on ModelNodes/DefinitionBase + // such classes use .ToString() override with reflection which is extremely slow + + IsCriticalEnabled = true; + IsErrorEnabled = true; + IsWarningEnabled = true; + IsInformationEnabled = true; + IsVerboseEnabled = false; + + AutoFlush = true; + } + + #endregion + + #region properties + + public virtual bool IsCriticalEnabled { get; set; } + public virtual bool IsErrorEnabled { get; set; } + + public virtual bool IsWarningEnabled { get; set; } + public virtual bool IsInformationEnabled { get; set; } + + public virtual bool IsVerboseEnabled { get; set; } + + public bool AutoFlush { get; set; } + + #endregion + + #region methods + + public virtual void Flush() + { + + } + + public virtual void Critical(int id, object message) + { + Critical(id, message, null); + } + + public abstract void Critical(int id, object message, Exception exception); + + public virtual void Error(int id, object message) + { + Error(id, message, null); + } + + public abstract void Error(int id, object message, Exception exception); + + public virtual void Warning(int id, object message) + { + Warning(id, message, null); + } + + public abstract void Warning(int id, object message, Exception exception); + + public virtual void Information(int id, object message) + { + Information(id, message, null); + } + + public abstract void Information(int id, object message, Exception exception); + + public virtual void Verbose(int id, object message) + { + Verbose(id, message, null); + } + + public abstract void Verbose(int id, object message, Exception exception); + + public abstract void TraceActivityStart(int id, object message); + public abstract void TraceActivityStop(int id, object message); + public abstract void TraceActivityTransfer(int id, object message, Guid relatedActivityId); + + public abstract Guid CurrentActivityId + { + get; + set; + } + + #endregion + } + + public static class TraceServiceBaseExtensions + { + #region information + + public static void InformationFormat(this TraceServiceBase traceService, int id, object message, object parameter) + { + if (traceService != null && traceService.IsInformationEnabled) + { + InformationFormat(traceService, id, message, new object[] { parameter }); + } + } + + public static void InformationFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) + { + if (traceService != null && traceService.IsInformationEnabled) + { + InformationFormat(traceService, id, message, parameters, null); + } + } + + public static void InformationFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) + { + if (traceService != null && traceService.IsInformationEnabled) + { + if (message is string) + { + traceService.Information(id, string.Format(message as string, parameters), exception); + } + else + { + traceService.Information(id, message, exception); + } + } + } + + #endregion + + #region warning + + public static void WarningFormat(this TraceServiceBase traceService, int id, object message, object parameter) + { + if (traceService != null && traceService.IsWarningEnabled) + { + WarningFormat(traceService, id, message, new object[] { parameter }); + } + } + + public static void WarningFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) + { + if (traceService != null && traceService.IsWarningEnabled) + { + WarningFormat(traceService, id, message, parameters, null); + } + } + + public static void WarningFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) + { + if (traceService != null && traceService.IsWarningEnabled) + { + if (message is string) + { + traceService.Warning(id, string.Format(message as string, parameters), exception); + } + else + { + traceService.Warning(id, message, exception); + } + } + } + + #endregion + + #region verbose + + public static void VerboseFormat(this TraceServiceBase traceService, int id, object message, object parameter) + { + if (traceService != null && traceService.IsVerboseEnabled) + { + if (parameter == null) + VerboseFormat(traceService, id, message, new object[] { }); + else + VerboseFormat(traceService, id, message, new object[] { parameter }); + } + } + + public static void VerboseFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) + { + if (traceService != null && traceService.IsVerboseEnabled) + { + if (parameters == null) + VerboseFormat(traceService, id, message, new object[] { }, null); + else + VerboseFormat(traceService, id, message, parameters, null); + } + } + + public static void VerboseFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) + { + if (traceService != null && traceService.IsVerboseEnabled) + { + if (message is string && parameters != null && parameters.Length > 0) + { + traceService.Verbose(id, string.Format(message as string, parameters), exception); + } + else + { + traceService.Verbose(id, message, exception); + } + } + } + + #endregion + + #region error + + public static void ErrorFormat(this TraceServiceBase traceService, int id, object message, object parameter) + { + if (traceService != null && traceService.IsErrorEnabled) + { + if (parameter == null) + ErrorFormat(traceService, id, message, new object[] { }); + else + ErrorFormat(traceService, id, message, new object[] { parameter }); + } + } + + public static void ErrorFormat(this TraceServiceBase traceService, int id, object message, object[] parameters) + { + if (traceService != null && traceService.IsErrorEnabled) + { + if (parameters == null) + ErrorFormat(traceService, id, message, new object[] { }, null); + else + ErrorFormat(traceService, id, message, parameters, null); + } + } + + public static void ErrorFormat(this TraceServiceBase traceService, int id, object message, object[] parameters, Exception exception) + { + if (traceService != null && traceService.IsErrorEnabled) + { + if (message is string && parameters != null && parameters.Length > 0) + { + traceService.Error(id, string.Format(message as string, parameters), exception); + } + else + { + traceService.Error(id, message, exception); + } + } + } + + #endregion + } + + public class TraceMethodActivityScope : TraceActivityScope + { + public TraceMethodActivityScope(TraceServiceBase traceService, int eventId) + : base(traceService, eventId, new StackFrame(1).GetMethod().Name) + { + + } + } + + public class TraceActivityScope : IDisposable + { + #region constructors + + public TraceActivityScope(TraceServiceBase traceService, int eventId, string message) : + this(traceService, eventId, + string.Format("Starting: [{0}]", message), + string.Format("Ending: [{0}]", message)) + { + + } + + public TraceActivityScope(TraceServiceBase traceService, int eventId, string startMessage, string endMessage) + { + TraceService = traceService; + + var activityId = Guid.NewGuid(); + EventId = eventId; + + EndMessage = endMessage; + OldActivityId = TraceService.CurrentActivityId; + + TraceService.TraceActivityTransfer(eventId, startMessage, activityId); + TraceService.CurrentActivityId = activityId; + TraceService.TraceActivityStart(eventId, startMessage); + } + + #endregion + + #region properties + + public string EndMessage { get; set; } + + public Guid OldActivityId { get; set; } + public int EventId { get; set; } + + public TraceServiceBase TraceService { get; set; } + + #endregion + + #region methods + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + TraceService.TraceActivityStop(EventId, EndMessage); + TraceService.TraceActivityTransfer(EventId, EndMessage, OldActivityId); + TraceService.CurrentActivityId = OldActivityId; + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs b/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs index fbdc7e247..60ff6dbcc 100644 --- a/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs +++ b/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs @@ -116,6 +116,14 @@ public static IEnumerable GetTypesFromAssemblies(IEnumerable typeof(TType).IsAssignableFrom(t) && !t.IsAbstract); } + private static Dictionary _cache4GetExpressionValueAsMethodCallExpression = new Dictionary(); + private static Dictionary _cache4GetExpressionValueAsUnaryExpression = new Dictionary(); + private static Dictionary _cache4GetExpressionValueAsMemberExpression = new Dictionary(); + + private static Dictionary> _cache4FastGetters = new Dictionary>(); + + + public static PropResult GetExpressionValue(this TSource source, Expression> exp) { @@ -124,7 +132,15 @@ public static PropResult GetExpressionValue(this TSource sou if (exp.Body is MethodCallExpression) { var member = exp.Body as MethodCallExpression; - var methodResult = Expression.Lambda(member, exp.Parameters.ToArray()).Compile().DynamicInvoke(source); + + if (!_cache4GetExpressionValueAsMethodCallExpression.ContainsKey(exp)) + { + var compiledLambda = Expression.Lambda(member, exp.Parameters.ToArray()).Compile(); + _cache4GetExpressionValueAsMethodCallExpression.Add(exp, compiledLambda); + } + + //var methodResult = compiledLambda.DynamicInvoke(source); + var methodResult = _cache4GetExpressionValueAsMethodCallExpression[exp].DynamicInvoke(source); var result = new PropResult(); @@ -138,7 +154,15 @@ public static PropResult GetExpressionValue(this TSource sou if (exp.Body is UnaryExpression) { var member = exp.Body as UnaryExpression; - var methodResult = Expression.Lambda(member, exp.Parameters.ToArray()).Compile().DynamicInvoke(source); + + if (!_cache4GetExpressionValueAsUnaryExpression.ContainsKey(exp)) + { + var compiledLambda = Expression.Lambda(member, exp.Parameters.ToArray()).Compile(); + _cache4GetExpressionValueAsUnaryExpression.Add(exp, compiledLambda); + } + + //var methodResult = compiledLambda.DynamicInvoke(source); + var methodResult = _cache4GetExpressionValueAsUnaryExpression[exp].DynamicInvoke(source); var result = new PropResult(); @@ -157,7 +181,26 @@ public static PropResult GetExpressionValue(this TSource sou var result = new PropResult(); result.Name = propInfo.Name; - result.Value = propInfo.GetValue(source, null); + + if (!_cache4FastGetters.ContainsKey(type)) + _cache4FastGetters.Add(type, new Dictionary()); + + var _cache4FastGettersFunctions = _cache4FastGetters[type]; + + if (!_cache4FastGettersFunctions.ContainsKey(propInfo)) + { + var fastGetter = BuildUntypedGetter(propInfo); + _cache4FastGettersFunctions.Add(propInfo, fastGetter); + } + else + { + + } + + var value = _cache4FastGettersFunctions[propInfo].DynamicInvoke(source); + //result.Value = propInfo.GetValue(source, null); + result.Value = value; + result.ObjectType = source.GetType(); return result; @@ -166,7 +209,21 @@ public static PropResult GetExpressionValue(this TSource sou throw new NotImplementedException("GetExpressionValue"); } + public static Func BuildUntypedGetter(PropertyInfo propertyInfo) + { + var targetType = propertyInfo.DeclaringType; + var methodInfo = propertyInfo.GetGetMethod(); + var returnType = methodInfo.ReturnType; + + var exTarget = Expression.Parameter(targetType, "t"); + var exBody = Expression.Call(exTarget, methodInfo); + var exBody2 = Expression.Convert(exBody, typeof(object)); + var lambda = Expression.Lambda>(exBody2, exTarget); + + var action = lambda.Compile(); + return action; + } public static object GetPropertyValue(object obj, string propName) { var prop = obj.GetType().GetProperties(BindingFlags.Instance | diff --git a/SPMeta2/SPMeta2/Utils/ToStringResult.cs b/SPMeta2/SPMeta2/Utils/ToStringResult.cs index 2b3ab011f..e3f4d2f05 100644 --- a/SPMeta2/SPMeta2/Utils/ToStringResult.cs +++ b/SPMeta2/SPMeta2/Utils/ToStringResult.cs @@ -1,82 +1,97 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq.Expressions; - -namespace SPMeta2.Utils -{ - public class ToStringResult - { - public ToStringResult(TType obj) - : this(obj, string.Empty) - { - - } - - public ToStringResult(TType obj, string initialString) - { - SrcObject = obj; - Values = new Dictionary(); - - InitialString = initialString; - } - - public static ToStringResult New(TType obj) - { - return new ToStringResult(obj); - } - - public override string ToString() - { - var result = new List(); - - foreach (var key in Values.Keys) - result.Add(string.Format("{0}:[{1}]", key, Values[key])); - - if (!string.IsNullOrEmpty(InitialString)) - return InitialString + " " + string.Join(" ", result.ToArray()); - - return string.Join(" ", result.ToArray()); - } - - public string InitialString { get; set; } - public TType SrcObject { get; set; } - public Dictionary Values { get; set; } - - public ToStringResult AddPropertyValue(Expression> exp) - { - var srcProp = SrcObject.GetExpressionValue(exp); - - var key = srcProp.Name; - var value = srcProp.Value; - - var valueString = string.Empty; - - if (value is IEnumerable && !(value is string)) - { - var enumerableValues = new List(); - - var enumerator = (value as IEnumerable).GetEnumerator(); - - while (enumerator.MoveNext()) - { - if (enumerator.Current != null) - enumerableValues.Add(enumerator.Current.ToString()); - else - enumerableValues.Add(string.Empty); - } - - valueString = string.Join("|", enumerableValues.ToArray()); - } - else - { - valueString = value == null ? string.Empty : value.ToString(); - } - - if (!Values.ContainsKey(key)) - Values.Add(key, valueString); - - return this; - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq.Expressions; + +namespace SPMeta2.Utils +{ + public class ToStringResult + { + #region constructors + public ToStringResult(TType obj) + : this(obj, string.Empty) + { + + } + + public ToStringResult(TType obj, string initialString) + { + SrcObject = obj; + Values = new Dictionary(); + + InitialString = initialString; + } + + #endregion + + #region static + + public static ToStringResult New(TType obj) + { + return new ToStringResult(obj); + } + + #endregion + + #region properties + + public string InitialString { get; set; } + public TType SrcObject { get; set; } + public Dictionary Values { get; set; } + + #endregion + + #region methods + + public override string ToString() + { + var result = new List(); + + foreach (var key in Values.Keys) + result.Add(string.Format("{0}:[{1}]", key, Values[key])); + + if (!string.IsNullOrEmpty(InitialString)) + return InitialString + " " + string.Join(" ", result.ToArray()); + + return string.Join(" ", result.ToArray()); + } + + public ToStringResult AddPropertyValue(Expression> exp) + { + var srcProp = SrcObject.GetExpressionValue(exp); + + var key = srcProp.Name; + var value = srcProp.Value; + + var valueString = string.Empty; + + if (value is IEnumerable && !(value is string)) + { + var enumerableValues = new List(); + + var enumerator = (value as IEnumerable).GetEnumerator(); + + while (enumerator.MoveNext()) + { + if (enumerator.Current != null) + enumerableValues.Add(enumerator.Current.ToString()); + else + enumerableValues.Add(string.Empty); + } + + valueString = string.Join("|", enumerableValues.ToArray()); + } + else + { + valueString = value == null ? string.Empty : value.ToString(); + } + + if (!Values.ContainsKey(key)) + Values.Add(key, valueString); + + return this; + } + + #endregion + } +} From 3a86def805f490fbd3edf1bc508dd00261e7ec14 Mon Sep 17 00:00:00 2001 From: Support Date: Fri, 17 Mar 2017 00:50:41 +1100 Subject: [PATCH 27/53] + Incremental provision real time trace problems #978 +Migrated to CakeBuildTools 0.1.0-beta5, March 2017 --- SPMeta2/Build/tools/packages.config | 2 +- .../Services/Impl/DefaultModelTreeTraverseService.cs | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/SPMeta2/Build/tools/packages.config b/SPMeta2/Build/tools/packages.config index 2da95bd96..f9cef174f 100644 --- a/SPMeta2/Build/tools/packages.config +++ b/SPMeta2/Build/tools/packages.config @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs index 010b66e37..07eb8985c 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultModelTreeTraverseService.cs @@ -84,11 +84,11 @@ public override void Traverse(object modelHost, ModelNode modelNode) TraceService.VerboseFormat((int)LogEventId.ModelProcessing, "Raising OnModelProcessing for model: [{0}].", modelNode); + OnBeforeDeployModelNode(modelHost, modelNode); + if (OnModelProcessing != null) OnModelProcessing(modelNode); - OnBeforeDeployModelNode(modelHost, modelNode); - //var requireselfProcessing = modelDefinition.RequireSelfProcessing || modelNode.Options.RequireSelfProcessing; var requireselfProcessing = modelNode.Options.RequireSelfProcessing; @@ -123,11 +123,14 @@ public override void Traverse(object modelHost, ModelNode modelNode) TraceService.VerboseFormat((int)LogEventId.ModelProcessing, "Raising OnModelProcessed for model: [{0}].", modelNode); + // call up before OnModelProcessed + // Incremental provision real time trace problems #978 + // https://github.com/SubPointSolutions/spmeta2/issues/978 + OnAfterDeployModelNode(modelHost, modelNode); + if (OnModelProcessed != null) OnModelProcessed(modelNode); - OnAfterDeployModelNode(modelHost, modelNode); - var childModelTypes = GetSortedChildModelTypes(modelNode); foreach (var childModelType in childModelTypes) From 96a07de4de5c5f8e8b8d1cbd37ced10f295999af Mon Sep 17 00:00:00 2001 From: Support Date: Fri, 17 Mar 2017 00:57:41 +1100 Subject: [PATCH 28/53] + 1.2.120-beta3 + appveyor/ci fixes --- SPMeta2/Build/build.json | 56 ++++++++++++++++++++-------------------- appveyor.yml | 5 ++-- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index a55fb72b3..749169913 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta2", + "Version": "1.2.120-beta3", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta2" + "Version": "1.2.120-beta3" }, { "Id": "Microsoft.SharePointOnline.CSOM", diff --git a/appveyor.yml b/appveyor.yml index c072f3bed..52af2c217 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,8 @@ test: off clone_folder: c:\prj\m2 build_script: - - ps: c:\prj\m2\SPMeta2\Build\build.ps1 -Verbosity Minimal -Target "Default-CI" + - ps: c:\prj\m2\SPMeta2\Build\build.ps1 -Target "Default-CI" artifacts: - - path: '**\*.nupkg' \ No newline at end of file + - path: '**\build-artifact-nuget-packages\*.nupkg' + - path: '**\build-artifact-cli-packages\*.nupkg' \ No newline at end of file From 85dce4a6681b696c8d2d2673dab2d4de734e09c2 Mon Sep 17 00:00:00 2001 From: Support Date: Fri, 17 Mar 2017 01:08:51 +1100 Subject: [PATCH 29/53] + 1.2.120-beta3 + appveyor/ci fixes + release notes template --- SPMeta2/Build/Build.csproj | 1 + SPMeta2/Build/github-release-notes.chtml | 33 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 SPMeta2/Build/github-release-notes.chtml diff --git a/SPMeta2/Build/Build.csproj b/SPMeta2/Build/Build.csproj index 35cf0f3e5..f58b1776c 100644 --- a/SPMeta2/Build/Build.csproj +++ b/SPMeta2/Build/Build.csproj @@ -47,6 +47,7 @@ + diff --git a/SPMeta2/Build/github-release-notes.chtml b/SPMeta2/Build/github-release-notes.chtml new file mode 100644 index 000000000..8ff5cea54 --- /dev/null +++ b/SPMeta2/Build/github-release-notes.chtml @@ -0,0 +1,33 @@ +## What's new in @Model.ReleaseTitle @Model.ReleaseVersion, @Model.ReleaseMonthAndYear + +@if(!System.String.IsNullOrEmpty(Model.AssemblyFileVersion)) +{ + +AssemblyFileVersion: @Model.AssemblyFileVersion + +} + +@foreach(var releaseGroup in Model.ReleaseIssueGroups){ + +var items = releaseGroup.Issues; +var label = releaseGroup.Label; +var labelTitle = releaseGroup.LabelTitle; + +if (items.Count > 0) +{ + +### @labelTitle +@foreach (var item in items) +{ +* #@item.Number, @item.Title +} + +} +} + +### Feature requests, support and contributions +This project is a part of the [SPMeta2 ecosystem](http://subpointsolutions.com). In case you have unexpected issues, feedback or keen to see new features, please join [Yammer Community](https://www.yammer.com/spmeta2feedback), check out [documentation](http://docs.subpointsolutions.com/spmeta2/) or post your feedback or issues directly at [GitHub issue tracker](https://github.com/SubPointSolutions/spmeta2/issues). Enterprise support and SLA is [available upon request](http://subpointsolutions.com/services/). + +* [Yammer Community](https://www.yammer.com/spmeta2feedback) +* [@Model.ProjectName documentation](http://docs.subpointsolutions.com/spmeta2/) +* [GitHub issue tracker](https://github.com/SubPointSolutions/spmeta2/issues) \ No newline at end of file From a2f2766764f031e19f5b6b0c3f78a61c5502b247 Mon Sep 17 00:00:00 2001 From: Support Date: Fri, 17 Mar 2017 02:26:28 +1100 Subject: [PATCH 30/53] + build update -> 1.2.120-beta4 --- SPMeta2/Build/build.json | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index 749169913..2ce2da3d1 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta3", + "Version": "1.2.120-beta4", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta3" + "Version": "1.2.120-beta4" }, { "Id": "Microsoft.SharePointOnline.CSOM", From f42fa6d3b32e44dd969394e1ddc2be1457a9d615 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Mon, 20 Mar 2017 06:05:31 -0700 Subject: [PATCH 31/53] + .AddWorkflowAssociation() should support list scoped content types #980 + SSOM impl --- .../Properties/AssemblyInfo.cs | 70 +- .../SPMeta2.CSOM/Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Nintex/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.O365/Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../WorkflowAssociationScenariosTest.cs | 64 ++ .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../Properties/AssemblyInfo.cs | 72 +- .../ContentTypeLinkModelHandler.cs | 298 ++++---- ...kflowSubscriptionDefinitionModelHandler.cs | 636 +++++++++--------- .../WorkflowAssociationModelHandler.cs | 27 +- .../ModelHosts/ContentTypeModelHost.cs | 28 + .../SPMeta2.SSOM/Properties/AssemblyInfo.cs | 72 +- SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj | 1 + .../Properties/AssemblyInfo.cs | 72 +- SPMeta2/SPMeta2/Properties/AssemblyInfo.cs | 70 +- .../ContentTypeLinkDefinitionSyntax.cs | 161 ++--- 30 files changed, 1321 insertions(+), 1196 deletions(-) create mode 100644 SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs diff --git a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs index 571a310c6..d415ea936 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs @@ -1,35 +1,35 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.CSOM.Standard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.CSOM.Standard")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("fe6947ad-76e7-4527-95ec-af15665de77e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.CSOM.Standard")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.CSOM.Standard")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("fe6947ad-76e7-4527-95ec-af15665de77e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs index 4ad56025f..0555bbd09 100644 --- a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.CSOM")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.CSOM")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("86262c4f-31bd-4ff1-898d-aa6d822beae2")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.CSOM")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.CSOM")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("86262c4f-31bd-4ff1-898d-aa6d822beae2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs index 148f95cee..36e1f3717 100644 --- a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.17079.1227")] \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs index 04629b7f0..d6078c9b0 100644 --- a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Containers.O365")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Containers.O365")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("442f862c-63c9-441f-b9b7-6c61d2b0c7ab")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Containers.O365")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Containers.O365")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("442f862c-63c9-441f-b9b7-6c61d2b0c7ab")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs index 4fa2c1be7..da5c7efea 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.17079.1227")] \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs index 1bd424888..e77fe9e57 100644 --- a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Containers.SSOM")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Containers.SSOM")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("02eefcfe-d0c2-4ec2-bc30-df2ff209251c")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Containers.SSOM")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Containers.SSOM")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("02eefcfe-d0c2-4ec2-bc30-df2ff209251c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1254")] diff --git a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs index 232949144..d37656b35 100644 --- a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Containers.Standard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Containers.Standard")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("59df3b79-fb9b-4ab2-bf73-506783411eb7")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Containers.Standard")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Containers.Standard")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("59df3b79-fb9b-4ab2-bf73-506783411eb7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs index 01d722c17..4d6b34d08 100644 --- a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Containers")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Containers")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("556db2b0-71f5-4ef7-b41a-2d54f5224543")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Containers")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Containers")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("556db2b0-71f5-4ef7-b41a-2d54f5224543")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs index 666f454ad..495e20ae1 100644 --- a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17072.1315")] +[assembly: AssemblyFileVersion("1.0.17079.1227")] diff --git a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs index 554550114..b87c409f7 100644 --- a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17072.1315")] +[assembly: AssemblyFileVersion("1.0.17079.1227")] diff --git a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs index 04b15c3af..983fb0fe4 100644 --- a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17072.1315")] +[assembly: AssemblyFileVersion("1.0.17079.1227")] diff --git a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs index e8abbb241..48bb2f621 100644 --- a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.O365")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.O365")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("75a471fc-d881-4df6-82d3-4e92777dd9d3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.O365")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.O365")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("75a471fc-d881-4df6-82d3-4e92777dd9d3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs index e244e4cb4..44a71f312 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression.CSOM.Standard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression.CSOM.Standard")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9744d103-206c-4142-b9bd-bed3fa3e56cc")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression.CSOM.Standard")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression.CSOM.Standard")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9744d103-206c-4142-b9bd-bed3fa3e56cc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs index 99e14828a..1db99efab 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression.CSOM")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression.CSOM")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e05c39d9-c298-473d-98f6-f72f937191da")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression.CSOM")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression.CSOM")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e05c39d9-c298-473d-98f6-f72f937191da")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs index c2f3cdcba..146bd5ffb 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression.Impl.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression.Impl.Tests")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("a1b845b1-6656-4630-b7c7-7fd1cf93b5b9")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression.Impl.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression.Impl.Tests")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a1b845b1-6656-4630-b7c7-7fd1cf93b5b9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1246")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs index 24a6507c2..ab4173853 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression.SSOM.Standard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression.SSOM.Standard")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("7b1bcf2b-b2b0-49c9-bb70-252e28fb9351")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression.SSOM.Standard")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression.SSOM.Standard")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7b1bcf2b-b2b0-49c9-bb70-252e28fb9351")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1254")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs index 11da0bfc4..853435573 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression.SSOM")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression.SSOM")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f7a27fdf-3a35-418d-8ad1-0bf5917ae341")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression.SSOM")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression.SSOM")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f7a27fdf-3a35-418d-8ad1-0bf5917ae341")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1254")] diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs index 2afaa7198..7222c135b 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs @@ -159,6 +159,70 @@ public void CanDeploy_WorkflowAssociation_UnderList() TestModel(model); } + [TestMethod] + [TestCategory("Regression.Scenarios.WorkflowAssociation")] + public void CanDeploy_WorkflowAssociation_UnderContentTypeLink() + { + var contentTypeDef = ModelGeneratorService.GetRandomDefinition(def => + { + + }); + + var taskList = ModelGeneratorService.GetRandomDefinition(def => + { + def.Hidden = true; + def.TemplateType = BuiltInListTemplateTypeId.Tasks; + }); + + var historyList = ModelGeneratorService.GetRandomDefinition(def => + { + def.Hidden = true; + def.TemplateType = BuiltInListTemplateTypeId.WorkflowHistory; + }); + + var workflowDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.TaskListTitle = taskList.Title; + def.HistoryListTitle = historyList.Title; + }); + + // changability + // deploy the same association with different props + var workflowDefChanges = workflowDef.Inherit(def => + { + var value = Rnd.Bool(); + + def.AllowManual = value; + def.AutoStartChange = !value; + def.AutoStartCreate = value; + + def.AssociationData = Rnd.String(); + }); + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddContentType(contentTypeDef); + }); + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddList(taskList); + web.AddList(historyList); + + web.AddRandomList(list => + { + list.AddContentTypeLink(contentTypeDef, contentTypeLink => + { + contentTypeLink.AddWorkflowAssociation(workflowDef); + contentTypeLink.AddWorkflowAssociation(workflowDefChanges); + }); + }); + }); + + TestModel(siteModel, model); + } + + [TestMethod] [TestCategory("Regression.Scenarios.WorkflowAssociation")] public void CanDeploy_WorkflowAssociation_UnderContentType() diff --git a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs index 263e53b7c..a59cad00f 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression.Tests")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9fd4b4ec-2498-4e39-aa14-e1deb62784bc")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression.Tests")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9fd4b4ec-2498-4e39-aa14-e1deb62784bc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1254")] diff --git a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs index ffd213fc1..6ab6dd9fd 100644 --- a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Regression")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Regression")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c339c5d9-93e8-4e25-808b-74b1814b3418")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Regression")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Regression")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c339c5d9-93e8-4e25-808b-74b1814b3418")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.17079.1227")] diff --git a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs index 25108a6a0..4e3c96605 100644 --- a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.SSOM.Standard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.SSOM.Standard")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("7ae34a4c-55fd-44c9-bed8-536ae3bb6b41")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.SSOM.Standard")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.SSOM.Standard")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7ae34a4c-55fd-44c9-bed8-536ae3bb6b41")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1254")] diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs index 4c4662a0d..0baa65d1e 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs @@ -1,145 +1,153 @@ -using System; -using System.Linq; -using Microsoft.SharePoint; -using SPMeta2.Common; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Exceptions; -using SPMeta2.ModelHandlers; -using SPMeta2.Services; -using SPMeta2.Utils; -using SPMeta2.SSOM.ModelHosts; - -namespace SPMeta2.SSOM.ModelHandlers -{ - public class ContentTypeLinkModelHandler : SSOMModelHandlerBase - { - #region methods - - public override Type TargetType - { - get { return typeof(ContentTypeLinkDefinition); } - } - - protected SPContentType GetListContentType(SPList list, ContentTypeLinkDefinition definition) - { - SPContentType result = null; - - if (!string.IsNullOrEmpty(definition.ContentTypeName)) - result = list.ContentTypes[definition.ContentTypeName]; - - if (result == null && !string.IsNullOrEmpty(definition.ContentTypeId)) - { - var linkContenType = new SPContentTypeId(definition.ContentTypeId); - var bestMatch = list.ContentTypes.BestMatch(linkContenType); - - if (bestMatch.IsChildOf(linkContenType)) - result = list.ContentTypes[bestMatch]; - } - - return result; - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var list = listModelHost.HostList; - - var contentType = list.ContentTypes[contentTypeLinkModel.ContentTypeName]; - - action(contentType); - - contentType.Update(false); - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var list = listModelHost.HostList; - - if (list.ContentTypesEnabled) - { - var web = list.ParentWeb; - - var contentTypeId = new SPContentTypeId(contentTypeLinkModel.ContentTypeId); - var targetContentType = web.AvailableContentTypes[contentTypeId]; - - if (targetContentType == null) - { - TraceService.ErrorFormat((int)LogEventId.ModelProvisionCoreCall, - "Cannot find site content type by ID: [{0}]. Throwing SPMeta2Exception.", - contentTypeId); - - throw new SPMeta2Exception(string.Format("Cannot find site content type with ID [{0}].", - contentTypeId)); - } - - var currentListContentType = GetListContentType(list, contentTypeLinkModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentListContentType, - ObjectType = typeof(SPContentType), - ObjectDefinition = contentTypeLinkModel, - ModelHost = modelHost - }); - - if (currentListContentType == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, - "Processing new list content type link"); - - var listCt = list.ContentTypes.Add(targetContentType); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = listCt, - ObjectType = typeof(SPContentType), - ObjectDefinition = contentTypeLinkModel, - ModelHost = modelHost - }); - - //list.Update(); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, - "Processing existing list content type link"); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentListContentType, - ObjectType = typeof(SPContentType), - ObjectDefinition = contentTypeLinkModel, - ModelHost = modelHost - }); - - } - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is FALSE. Provision might break."); - } - } - - #endregion - } -} +using System; +using System.Linq; +using Microsoft.SharePoint; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Exceptions; +using SPMeta2.ModelHandlers; +using SPMeta2.Services; +using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; +using SPMeta2.ModelHosts; + +namespace SPMeta2.SSOM.ModelHandlers +{ + public class ContentTypeLinkModelHandler : SSOMModelHandlerBase + { + #region methods + + public override Type TargetType + { + get { return typeof(ContentTypeLinkDefinition); } + } + + protected SPContentType GetListContentType(SPList list, ContentTypeLinkDefinition definition) + { + SPContentType result = null; + + if (!string.IsNullOrEmpty(definition.ContentTypeName)) + result = list.ContentTypes[definition.ContentTypeName]; + + if (result == null && !string.IsNullOrEmpty(definition.ContentTypeId)) + { + var linkContenType = new SPContentTypeId(definition.ContentTypeId); + var bestMatch = list.ContentTypes.BestMatch(linkContenType); + + if (bestMatch.IsChildOf(linkContenType)) + result = list.ContentTypes[bestMatch]; + } + + return result; + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost as ModelHostBase; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var list = listModelHost.HostList; + + var contentType = list.ContentTypes[contentTypeLinkModel.ContentTypeName]; + + var contentTypeLinkHost = ModelHostBase.Inherit(modelHost, host => + { + host.HostContentType = contentType; + host.HostList = list; + }); + + action(contentTypeLinkHost); + + if (!contentTypeLinkHost.ShouldUpdateHost) + contentType.Update(false); + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var list = listModelHost.HostList; + + if (list.ContentTypesEnabled) + { + var web = list.ParentWeb; + + var contentTypeId = new SPContentTypeId(contentTypeLinkModel.ContentTypeId); + var targetContentType = web.AvailableContentTypes[contentTypeId]; + + if (targetContentType == null) + { + TraceService.ErrorFormat((int)LogEventId.ModelProvisionCoreCall, + "Cannot find site content type by ID: [{0}]. Throwing SPMeta2Exception.", + contentTypeId); + + throw new SPMeta2Exception(string.Format("Cannot find site content type with ID [{0}].", + contentTypeId)); + } + + var currentListContentType = GetListContentType(list, contentTypeLinkModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentListContentType, + ObjectType = typeof(SPContentType), + ObjectDefinition = contentTypeLinkModel, + ModelHost = modelHost + }); + + if (currentListContentType == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, + "Processing new list content type link"); + + var listCt = list.ContentTypes.Add(targetContentType); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = listCt, + ObjectType = typeof(SPContentType), + ObjectDefinition = contentTypeLinkModel, + ModelHost = modelHost + }); + + //list.Update(); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, + "Processing existing list content type link"); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentListContentType, + ObjectType = typeof(SPContentType), + ObjectDefinition = contentTypeLinkModel, + ModelHost = modelHost + }); + + } + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is FALSE. Provision might break."); + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/SP2013WorkflowSubscriptionDefinitionModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/SP2013WorkflowSubscriptionDefinitionModelHandler.cs index c6fa6c767..e6f172420 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/SP2013WorkflowSubscriptionDefinitionModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/SP2013WorkflowSubscriptionDefinitionModelHandler.cs @@ -1,318 +1,318 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint; -using Microsoft.SharePoint.Utilities; -using Microsoft.SharePoint.WorkflowServices; -using SPMeta2.Common; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Exceptions; -using SPMeta2.Services; -using SPMeta2.Utils; -using SPMeta2.SSOM.ModelHosts; - -namespace SPMeta2.SSOM.ModelHandlers -{ - public class SP2013WorkflowSubscriptionDefinitionModelHandler : SSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(SP2013WorkflowSubscriptionDefinition); } - } - - #endregion - - #region methods - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var workflowSubscriptionModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - if (modelHost is ListModelHost) - { - var listModelHost = (modelHost as ListModelHost); - var list = listModelHost.HostList; - - DeployListWorkflowSubscriptionDefinition(listModelHost, list, workflowSubscriptionModel); - } - - else if (modelHost is WebModelHost) - { - var webModelHost = (modelHost as WebModelHost); - var web = webModelHost.HostWeb; - - DeployWebWorkflowSubscriptionDefinition(webModelHost, web, workflowSubscriptionModel); - } - else - { - throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); - } - } - - protected WorkflowSubscription GetCurrentWebWorkflowSubscriptioBySourceId( - object host, - SPWeb web, - Guid eventSourceId, - SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) - { - var workflowServiceManager = new WorkflowServicesManager(web); - var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); - var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByEventSource(eventSourceId); - - return subscriptions.FirstOrDefault(s => s.Name == workflowSubscriptionModel.Name); - } - - - protected WorkflowDefinition GetWorkflowDefinition(object host, - SPWeb web, - SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving workflow definition by DisplayName: [{0}]", workflowSubscriptionModel.WorkflowDisplayName); - var workflowServiceManager = new WorkflowServicesManager(web); - - var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); - var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService(); - var tgtwis = workflowServiceManager.GetWorkflowInstanceService(); - - var publishedWorkflows = workflowDeploymentService.EnumerateDefinitions(true); - - var result = publishedWorkflows.FirstOrDefault(w => w.DisplayName == workflowSubscriptionModel.WorkflowDisplayName); - - if (result == null) - { - TraceService.ErrorFormat((int)LogEventId.ModelProvisionCoreCall, - "Cannot find workflow definition with DisplayName: [{0}]. Provision might break.", - workflowSubscriptionModel.WorkflowDisplayName); - } - - return result; - } - - private void DeployWebWorkflowSubscriptionDefinition( - object host, - SPWeb web, - SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) - { - var workflowServiceManager = new WorkflowServicesManager(web); - - var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); - var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService(); - var tgtwis = workflowServiceManager.GetWorkflowInstanceService(); - - var publishedWorkflows = workflowDeploymentService.EnumerateDefinitions(true); - - var currentWorkflowDefinition = publishedWorkflows.FirstOrDefault(w => w.DisplayName == workflowSubscriptionModel.WorkflowDisplayName); - - if (currentWorkflowDefinition == null) - throw new Exception(string.Format("Cannot lookup workflow definition with display name: [{0}] on web:[{1}]", workflowSubscriptionModel.WorkflowDisplayName, web.Url)); - - // EnumerateSubscriptionsByEventSource() somehow throws an exception - //var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByEventSource(web.ID); - var subscriptions = workflowSubscriptionService.EnumerateSubscriptions().Where(s => s.EventSourceId == web.ID); - - var currentSubscription = subscriptions.FirstOrDefault(s => s.Name == workflowSubscriptionModel.Name); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentSubscription, - ObjectType = typeof(WorkflowSubscription), - ObjectDefinition = workflowSubscriptionModel, - ModelHost = host - }); - - if (currentSubscription == null) - { - var taskList = GetTaskList(web, workflowSubscriptionModel); - var historyList = GetHistoryList(web, workflowSubscriptionModel); - - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new SP2013 workflow subscription"); - - var newSubscription = new WorkflowSubscription(); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Setting subscription properties"); - - newSubscription.Name = workflowSubscriptionModel.Name; - newSubscription.DefinitionId = currentWorkflowDefinition.Id; - - newSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); - newSubscription.EventSourceId = web.ID; - - newSubscription.SetProperty("HistoryListId", historyList.ID.ToString()); - newSubscription.SetProperty("TaskListId", taskList.ID.ToString()); - - newSubscription.SetProperty("WebId", web.ID.ToString()); - newSubscription.SetProperty("Microsoft.SharePoint.ActivationProperties.WebId", web.ID.ToString()); - - MapProperties(newSubscription, workflowSubscriptionModel); - - // to be able to change HistoryListId, TaskListId, ListId - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = newSubscription, - ObjectType = typeof(WorkflowSubscription), - ObjectDefinition = workflowSubscriptionModel, - ModelHost = host - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); - var currentSubscriptionId = workflowSubscriptionService.PublishSubscription(newSubscription); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing SP2013 workflow subscription"); - - currentSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); - - MapProperties(currentSubscription, workflowSubscriptionModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentSubscription, - ObjectType = typeof(WorkflowSubscription), - ObjectDefinition = workflowSubscriptionModel, - ModelHost = host - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); - workflowSubscriptionService.PublishSubscription(currentSubscription); - } - } - - protected virtual void MapProperties(WorkflowSubscription workflow, SP2013WorkflowSubscriptionDefinition definition) - { - foreach (var prop in definition.Properties) - workflow.SetProperty(prop.Name, prop.Value); - } - - private void DeployListWorkflowSubscriptionDefinition( - object host, - SPList list, - SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) - { - var web = list.ParentWeb; - var workflowServiceManager = new WorkflowServicesManager(web); - - var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); - var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService(); - var tgtwis = workflowServiceManager.GetWorkflowInstanceService(); - - var publishedWorkflows = workflowDeploymentService.EnumerateDefinitions(true); - - var currentWorkflowDefinition = publishedWorkflows.FirstOrDefault(w => w.DisplayName == workflowSubscriptionModel.WorkflowDisplayName); - - if (currentWorkflowDefinition == null) - throw new Exception(string.Format("Cannot lookup workflow definition with display name: [{0}] on web:[{1}]", workflowSubscriptionModel.WorkflowDisplayName, web.Url)); - - var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByEventSource(list.ID); - - var currentSubscription = subscriptions.FirstOrDefault(s => s.Name == workflowSubscriptionModel.Name); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentSubscription, - ObjectType = typeof(WorkflowSubscription), - ObjectDefinition = workflowSubscriptionModel, - ModelHost = host - }); - - if (currentSubscription == null) - { - var taskList = GetTaskList(web, workflowSubscriptionModel); - var historyList = GetHistoryList(web, workflowSubscriptionModel); - - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new SP2013 workflow subscription"); - - var newSubscription = new WorkflowSubscription(); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Setting subscription properties"); - - newSubscription.Name = workflowSubscriptionModel.Name; - newSubscription.DefinitionId = currentWorkflowDefinition.Id; - - newSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); - newSubscription.EventSourceId = list.ID; - - newSubscription.SetProperty("HistoryListId", historyList.ID.ToString()); - newSubscription.SetProperty("TaskListId", taskList.ID.ToString()); - - newSubscription.SetProperty("ListId", list.ID.ToString()); - newSubscription.SetProperty("Microsoft.SharePoint.ActivationProperties.ListId", list.ID.ToString()); - - MapProperties(newSubscription, workflowSubscriptionModel); - - - // to be able to change HistoryListId, TaskListId, ListId - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = newSubscription, - ObjectType = typeof(WorkflowSubscription), - ObjectDefinition = workflowSubscriptionModel, - ModelHost = host - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); - var currentSubscriptionId = workflowSubscriptionService.PublishSubscription(newSubscription); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing SP2013 workflow subscription"); - - currentSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); - - MapProperties(currentSubscription, workflowSubscriptionModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentSubscription, - ObjectType = typeof(WorkflowSubscription), - ObjectDefinition = workflowSubscriptionModel, - ModelHost = host - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); - workflowSubscriptionService.PublishSubscription(currentSubscription); - } - } - - protected SPList GetTaskList(SPWeb web, SP2013WorkflowSubscriptionDefinition definition) - { - return web.GetList(SPUrlUtility.CombineUrl(web.ServerRelativeUrl, definition.TaskListUrl)); - } - - protected SPList GetHistoryList(SPWeb web, SP2013WorkflowSubscriptionDefinition definition) - { - return web.GetList(SPUrlUtility.CombineUrl(web.ServerRelativeUrl, definition.HistoryListUrl)); - } - - #endregion - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint; +using Microsoft.SharePoint.Utilities; +using Microsoft.SharePoint.WorkflowServices; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Exceptions; +using SPMeta2.Services; +using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; + +namespace SPMeta2.SSOM.ModelHandlers +{ + public class SP2013WorkflowSubscriptionDefinitionModelHandler : SSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(SP2013WorkflowSubscriptionDefinition); } + } + + #endregion + + #region methods + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var workflowSubscriptionModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + if (modelHost is ListModelHost) + { + var listModelHost = (modelHost as ListModelHost); + var list = listModelHost.HostList; + + DeployListWorkflowSubscriptionDefinition(listModelHost, list, workflowSubscriptionModel); + } + + else if (modelHost is WebModelHost) + { + var webModelHost = (modelHost as WebModelHost); + var web = webModelHost.HostWeb; + + DeployWebWorkflowSubscriptionDefinition(webModelHost, web, workflowSubscriptionModel); + } + else + { + throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); + } + } + + protected WorkflowSubscription GetCurrentWebWorkflowSubscriptioBySourceId( + object host, + SPWeb web, + Guid eventSourceId, + SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) + { + var workflowServiceManager = new WorkflowServicesManager(web); + var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); + var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByEventSource(eventSourceId); + + return subscriptions.FirstOrDefault(s => s.Name == workflowSubscriptionModel.Name); + } + + + protected WorkflowDefinition GetWorkflowDefinition(object host, + SPWeb web, + SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving workflow definition by DisplayName: [{0}]", workflowSubscriptionModel.WorkflowDisplayName); + var workflowServiceManager = new WorkflowServicesManager(web); + + var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); + var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService(); + var tgtwis = workflowServiceManager.GetWorkflowInstanceService(); + + var publishedWorkflows = workflowDeploymentService.EnumerateDefinitions(true); + + var result = publishedWorkflows.FirstOrDefault(w => w.DisplayName == workflowSubscriptionModel.WorkflowDisplayName); + + if (result == null) + { + TraceService.ErrorFormat((int)LogEventId.ModelProvisionCoreCall, + "Cannot find workflow definition with DisplayName: [{0}]. Provision might break.", + workflowSubscriptionModel.WorkflowDisplayName); + } + + return result; + } + + private void DeployWebWorkflowSubscriptionDefinition( + object host, + SPWeb web, + SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) + { + var workflowServiceManager = new WorkflowServicesManager(web); + + var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); + var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService(); + var tgtwis = workflowServiceManager.GetWorkflowInstanceService(); + + var publishedWorkflows = workflowDeploymentService.EnumerateDefinitions(true); + + var currentWorkflowDefinition = publishedWorkflows.FirstOrDefault(w => w.DisplayName == workflowSubscriptionModel.WorkflowDisplayName); + + if (currentWorkflowDefinition == null) + throw new Exception(string.Format("Cannot lookup workflow definition with display name: [{0}] on web:[{1}]", workflowSubscriptionModel.WorkflowDisplayName, web.Url)); + + // EnumerateSubscriptionsByEventSource() somehow throws an exception + //var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByEventSource(web.ID); + var subscriptions = workflowSubscriptionService.EnumerateSubscriptions().Where(s => s.EventSourceId == web.ID); + + var currentSubscription = subscriptions.FirstOrDefault(s => s.Name == workflowSubscriptionModel.Name); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentSubscription, + ObjectType = typeof(WorkflowSubscription), + ObjectDefinition = workflowSubscriptionModel, + ModelHost = host + }); + + if (currentSubscription == null) + { + var taskList = GetTaskList(web, workflowSubscriptionModel); + var historyList = GetHistoryList(web, workflowSubscriptionModel); + + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new SP2013 workflow subscription"); + + var newSubscription = new WorkflowSubscription(); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Setting subscription properties"); + + newSubscription.Name = workflowSubscriptionModel.Name; + newSubscription.DefinitionId = currentWorkflowDefinition.Id; + + newSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); + newSubscription.EventSourceId = web.ID; + + newSubscription.SetProperty("HistoryListId", historyList.ID.ToString()); + newSubscription.SetProperty("TaskListId", taskList.ID.ToString()); + + newSubscription.SetProperty("WebId", web.ID.ToString()); + newSubscription.SetProperty("Microsoft.SharePoint.ActivationProperties.WebId", web.ID.ToString()); + + MapProperties(newSubscription, workflowSubscriptionModel); + + // to be able to change HistoryListId, TaskListId, ListId + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = newSubscription, + ObjectType = typeof(WorkflowSubscription), + ObjectDefinition = workflowSubscriptionModel, + ModelHost = host + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); + var currentSubscriptionId = workflowSubscriptionService.PublishSubscription(newSubscription); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing SP2013 workflow subscription"); + + currentSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); + + MapProperties(currentSubscription, workflowSubscriptionModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentSubscription, + ObjectType = typeof(WorkflowSubscription), + ObjectDefinition = workflowSubscriptionModel, + ModelHost = host + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); + workflowSubscriptionService.PublishSubscription(currentSubscription); + } + } + + protected virtual void MapProperties(WorkflowSubscription workflow, SP2013WorkflowSubscriptionDefinition definition) + { + foreach (var prop in definition.Properties) + workflow.SetProperty(prop.Name, prop.Value); + } + + private void DeployListWorkflowSubscriptionDefinition( + object host, + SPList list, + SP2013WorkflowSubscriptionDefinition workflowSubscriptionModel) + { + var web = list.ParentWeb; + var workflowServiceManager = new WorkflowServicesManager(web); + + var workflowSubscriptionService = workflowServiceManager.GetWorkflowSubscriptionService(); + var workflowDeploymentService = workflowServiceManager.GetWorkflowDeploymentService(); + var tgtwis = workflowServiceManager.GetWorkflowInstanceService(); + + var publishedWorkflows = workflowDeploymentService.EnumerateDefinitions(true); + + var currentWorkflowDefinition = publishedWorkflows.FirstOrDefault(w => w.DisplayName == workflowSubscriptionModel.WorkflowDisplayName); + + if (currentWorkflowDefinition == null) + throw new Exception(string.Format("Cannot lookup workflow definition with display name: [{0}] on web:[{1}]", workflowSubscriptionModel.WorkflowDisplayName, web.Url)); + + var subscriptions = workflowSubscriptionService.EnumerateSubscriptionsByEventSource(list.ID); + + var currentSubscription = subscriptions.FirstOrDefault(s => s.Name == workflowSubscriptionModel.Name); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentSubscription, + ObjectType = typeof(WorkflowSubscription), + ObjectDefinition = workflowSubscriptionModel, + ModelHost = host + }); + + if (currentSubscription == null) + { + var taskList = GetTaskList(web, workflowSubscriptionModel); + var historyList = GetHistoryList(web, workflowSubscriptionModel); + + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new SP2013 workflow subscription"); + + var newSubscription = new WorkflowSubscription(); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Setting subscription properties"); + + newSubscription.Name = workflowSubscriptionModel.Name; + newSubscription.DefinitionId = currentWorkflowDefinition.Id; + + newSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); + newSubscription.EventSourceId = list.ID; + + newSubscription.SetProperty("HistoryListId", historyList.ID.ToString()); + newSubscription.SetProperty("TaskListId", taskList.ID.ToString()); + + newSubscription.SetProperty("ListId", list.ID.ToString()); + newSubscription.SetProperty("Microsoft.SharePoint.ActivationProperties.ListId", list.ID.ToString()); + + MapProperties(newSubscription, workflowSubscriptionModel); + + + // to be able to change HistoryListId, TaskListId, ListId + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = newSubscription, + ObjectType = typeof(WorkflowSubscription), + ObjectDefinition = workflowSubscriptionModel, + ModelHost = host + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); + var currentSubscriptionId = workflowSubscriptionService.PublishSubscription(newSubscription); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing SP2013 workflow subscription"); + + currentSubscription.EventTypes = new List(workflowSubscriptionModel.EventTypes); + + MapProperties(currentSubscription, workflowSubscriptionModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentSubscription, + ObjectType = typeof(WorkflowSubscription), + ObjectDefinition = workflowSubscriptionModel, + ModelHost = host + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling PublishSubscription()"); + workflowSubscriptionService.PublishSubscription(currentSubscription); + } + } + + protected SPList GetTaskList(SPWeb web, SP2013WorkflowSubscriptionDefinition definition) + { + return web.GetList(SPUrlUtility.CombineUrl(web.ServerRelativeUrl, definition.TaskListUrl)); + } + + protected SPList GetHistoryList(SPWeb web, SP2013WorkflowSubscriptionDefinition definition) + { + return web.GetList(SPUrlUtility.CombineUrl(web.ServerRelativeUrl, definition.HistoryListUrl)); + } + + #endregion + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs index c7b0588a9..f82daef77 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs @@ -49,6 +49,12 @@ public override void DeployModel(object modelHost, DefinitionBase model) DeployContentTypeWorkflowAssociationDefinition(contentType, contentType, workflowAssociationModel); } + else if (modelHost is ContentTypeLinkModelHost) + { + var contentType = (modelHost as ContentTypeLinkModelHost).HostContentType; + + DeployContentTypeWorkflowAssociationDefinition(contentType, contentType, workflowAssociationModel); + } else { @@ -56,8 +62,6 @@ public override void DeployModel(object modelHost, DefinitionBase model) } } - - private SPWeb GetWebFromModelHost(object modelHost) { if (modelHost is ListModelHost) @@ -76,6 +80,11 @@ private SPWeb GetWebFromModelHost(object modelHost) return (modelHost as SPContentType).ParentWeb; } + if (modelHost is ContentTypeLinkModelHost) + { + return (modelHost as ContentTypeLinkModelHost).HostWeb; + } + throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); } @@ -103,6 +112,20 @@ protected SPWorkflowAssociation FindExistringWorkflowAssotiation(object modelHos return contentType.WorkflowAssociations .GetAssociationByName(def.Name, web.UICulture); } + if (modelHost is ContentTypeLinkModelHost) + { + var listContentTypeHost = (modelHost as ContentTypeLinkModelHost); + + // don't update content type link within list + if (listContentTypeHost.HostList != null) + listContentTypeHost.ShouldUpdateHost = false; + + var contentType = listContentTypeHost.HostContentType; + var web = contentType.ParentWeb; + + return contentType.WorkflowAssociations + .GetAssociationByName(def.Name, web.UICulture); + } else { throw new SPMeta2NotImplementedException( diff --git a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs new file mode 100644 index 000000000..1acfc55fb --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint; + +namespace SPMeta2.SSOM.ModelHosts +{ + public class ContentTypeLinkModelHost : SSOMModelHostBase + { + #region constructors + + + #endregion + + #region properties + + public SPContentType HostContentType { get; set; } + + #endregion + + + + public SPList HostList { get; set; } + public SPWeb HostWeb { get; set; } + } +} diff --git a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs index 23dfc580a..54ab8e737 100644 --- a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.SSOM")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.SSOM")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("89b2c005-d77d-4f3e-ae97-87b26d834b22")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.SSOM")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.SSOM")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("89b2c005-d77d-4f3e-ae97-87b26d834b22")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1254")] diff --git a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj index ca668fca8..f45593402 100644 --- a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj +++ b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj @@ -335,6 +335,7 @@ + diff --git a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs index de382df44..2a62bdd07 100644 --- a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs @@ -1,36 +1,36 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2.Standard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2.Standard")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("2d8c7179-4223-4a60-a3f4-6b827a2aea21")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2.Standard")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2.Standard")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2d8c7179-4223-4a60-a3f4-6b827a2aea21")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs index 062632853..904477cce 100644 --- a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs @@ -1,35 +1,35 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SPMeta2")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SPMeta2")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("b4f620cf-50f0-4c38-9e1f-538d8525f1c0")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17072.1315")] +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SPMeta2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SPMeta2")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b4f620cf-50f0-4c38-9e1f-538d8525f1c0")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.2.17079.1227")] diff --git a/SPMeta2/SPMeta2/Syntax/Default/ContentTypeLinkDefinitionSyntax.cs b/SPMeta2/SPMeta2/Syntax/Default/ContentTypeLinkDefinitionSyntax.cs index b3f2856d6..d58bcfdc8 100644 --- a/SPMeta2/SPMeta2/Syntax/Default/ContentTypeLinkDefinitionSyntax.cs +++ b/SPMeta2/SPMeta2/Syntax/Default/ContentTypeLinkDefinitionSyntax.cs @@ -1,80 +1,81 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using SPMeta2.Definitions; -using SPMeta2.Models; - -namespace SPMeta2.Syntax.Default -{ - [Serializable] - [DataContract] - public class ContentTypeLinkModelNode : TypedModelNode - , IContentTypeModelNode - { - - } - - public static class ContentTypeLinkDefinitionSyntax - { - #region methods - - public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeLinkDefinition definition) - where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() - { - return AddContentTypeLink(model, definition, null); - } - - public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeLinkDefinition definition, - Action action) - where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() - { - return model.AddTypedDefinitionNode(definition, action); - } - - #endregion - - #region array overload - - public static TModelNode AddContentTypeLinks(this TModelNode model, IEnumerable definitions) - where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() - { - foreach (var definition in definitions) - model.AddDefinitionNode(definition); - - return model; - } - - #endregion - - #region additions - - public static TModelNode AddContentTypeLink(this TModelNode model, string contentTypdId) - where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() - { - return AddContentTypeLink(model, new ContentTypeLinkDefinition - { - ContentTypeId = contentTypdId, - ContentTypeName = string.Empty - }); - } - - public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeDefinition definition) - where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() - { - return AddContentTypeLink(model, definition, null); - } - - public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeDefinition definition, - Action action) - where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() - { - return AddContentTypeLink(model, new ContentTypeLinkDefinition - { - ContentTypeId = definition.GetContentTypeId(), - ContentTypeName = definition.Name - }, action); - } - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using SPMeta2.Definitions; +using SPMeta2.Models; + +namespace SPMeta2.Syntax.Default +{ + [Serializable] + [DataContract] + public class ContentTypeLinkModelNode : TypedModelNode + , IContentTypeModelNode + , IWorkflowAssociationHostModelNode + { + + } + + public static class ContentTypeLinkDefinitionSyntax + { + #region methods + + public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeLinkDefinition definition) + where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() + { + return AddContentTypeLink(model, definition, null); + } + + public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeLinkDefinition definition, + Action action) + where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() + { + return model.AddTypedDefinitionNode(definition, action); + } + + #endregion + + #region array overload + + public static TModelNode AddContentTypeLinks(this TModelNode model, IEnumerable definitions) + where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() + { + foreach (var definition in definitions) + model.AddDefinitionNode(definition); + + return model; + } + + #endregion + + #region additions + + public static TModelNode AddContentTypeLink(this TModelNode model, string contentTypdId) + where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() + { + return AddContentTypeLink(model, new ContentTypeLinkDefinition + { + ContentTypeId = contentTypdId, + ContentTypeName = string.Empty + }); + } + + public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeDefinition definition) + where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() + { + return AddContentTypeLink(model, definition, null); + } + + public static TModelNode AddContentTypeLink(this TModelNode model, ContentTypeDefinition definition, + Action action) + where TModelNode : ModelNode, IContentTypeLinkHostModelNode, new() + { + return AddContentTypeLink(model, new ContentTypeLinkDefinition + { + ContentTypeId = definition.GetContentTypeId(), + ContentTypeName = definition.Name + }, action); + } + + #endregion + } +} From 7c18ecfd86082e5c1cf3629c84b26c902992ca97 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Mon, 20 Mar 2017 06:53:45 -0700 Subject: [PATCH 32/53] + .AddWorkflowAssociation() should support list scoped content types #980 + CSOM support --- .../ContentTypeLinkModelHandler.cs | 32 +++++++++------- .../WorkflowAssociationModelHandler.cs | 37 +++++++++++++++++++ .../ModelHosts/ContentTypeLinkModelHost.cs | 24 ++++++++++++ .../SPMeta2.CSOM/ModelHosts/ListModelHost.cs | 2 +- SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj | 1 + .../WorkflowAssociationScenariosTest.cs | 1 + 6 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs index f0cd1ac7f..1983ec965 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs @@ -8,7 +8,8 @@ using SPMeta2.ModelHandlers; using SPMeta2.Services; using SPMeta2.Utils; -using SPMeta2.CSOM.ModelHosts; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers { @@ -20,8 +21,8 @@ public override Type TargetType } public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; + { + var modelHost = modelHostContext.ModelHost as CSOMModelHostBase; var model = modelHostContext.Model; var childModelType = modelHostContext.ChildModelType; var action = modelHostContext.Action; @@ -33,18 +34,21 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var context = list.Context; context.Load(list, l => l.ContentTypes); - context.ExecuteQueryWithTrace(); - - var listContentType = FindListContentType(list, contentTypeLinkModel); - - action(new ModelHostContext - { - Site = listModelHost.HostSite, - Web = listModelHost.HostWeb, - ContentType = listContentType - }); + context.ExecuteQueryWithTrace(); + + var contentType = FindListContentType(list, contentTypeLinkModel); + + var contentTypeLinkHost = ModelHostBase.Inherit(modelHost, host => + { + host.HostContentType = contentType; + host.HostList = list; + }); + + action(contentTypeLinkHost); + + if (!contentTypeLinkHost.ShouldUpdateHost) + contentType.Update(false); - listContentType.Update(false); context.ExecuteQueryWithTrace(); } diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/WorkflowAssociationModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/WorkflowAssociationModelHandler.cs index 4a43df67c..7dee7edce 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/WorkflowAssociationModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/WorkflowAssociationModelHandler.cs @@ -53,6 +53,22 @@ public override void DeployModel(object modelHost, DefinitionBase model) DeployContentTypeWorkflowAssociationDefinition(modelHost, contentType, workflowAssociationModel); } + else if (modelHost is ContentTypeLinkModelHost) + { + var contentTypeLinkModelHost = (modelHost as ContentTypeLinkModelHost); + + // don't update content type link within list + if (contentTypeLinkModelHost.HostList != null) + contentTypeLinkModelHost.ShouldUpdateHost = false; + + var contentType = contentTypeLinkModelHost.HostContentType; + var web = contentTypeLinkModelHost.HostWeb; + + if (contentTypeLinkModelHost.HostList != null) + contentTypeLinkModelHost.ShouldUpdateHost = false; + + DeployContentTypeWorkflowAssociationDefinition(modelHost, contentType, workflowAssociationModel); + } else { throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); @@ -77,6 +93,14 @@ private Web GetWebFromModelHost(object modelHost) return (modelHost as ModelHostContext).Web; } + if (modelHost is ContentTypeLinkModelHost) + { + var listContentTypeHost = (modelHost as ContentTypeLinkModelHost); + + + return listContentTypeHost.HostWeb; + } + throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); } @@ -121,6 +145,19 @@ protected WorkflowAssociation FindExistringWorkflowAssotiation(object modelHost, return res.FirstOrDefault(); } + if (modelHost is ContentTypeLinkModelHost) + { + var list = (modelHost as ContentTypeLinkModelHost).HostList; + var context = list.Context; + + var defName = def.Name; + + var res = context.LoadQuery(list.WorkflowAssociations.Where(w => w.Name == defName)); + context.ExecuteQueryWithTrace(); + + return res.FirstOrDefault(); + } + throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); } diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs new file mode 100644 index 000000000..e2cea1c1f --- /dev/null +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint; +using Microsoft.SharePoint.Client; + +namespace SPMeta2.CSOM.ModelHosts +{ + public class ContentTypeLinkModelHost : ListModelHost + { + #region constructors + + + #endregion + + #region properties + + public ContentType HostContentType { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ListModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ListModelHost.cs index 758d32d0e..d49f43974 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ListModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ListModelHost.cs @@ -2,7 +2,7 @@ namespace SPMeta2.CSOM.ModelHosts { - public class ListModelHost : CSOMModelHostBase + public class ListModelHost : WebModelHost { #region properties diff --git a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj index 65a800580..08389eca2 100644 --- a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj +++ b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj @@ -257,6 +257,7 @@ + diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs index 7222c135b..25f0464b0 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs @@ -172,6 +172,7 @@ public void CanDeploy_WorkflowAssociation_UnderContentTypeLink() { def.Hidden = true; def.TemplateType = BuiltInListTemplateTypeId.Tasks; + def.ContentTypesEnabled = true; }); var historyList = ModelGeneratorService.GetRandomDefinition(def => From 36de4b4f6c69e6c99b8f29c34cf2dcbe6debbd21 Mon Sep 17 00:00:00 2001 From: Sergei Snitko Date: Wed, 22 Mar 2017 14:03:51 +0300 Subject: [PATCH 33/53] fixed ListItemAllFields error for WebPart Pages not in lists --- .../ModelHandlers/ModuleFileModelHandler.cs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs index 7a1c7996a..5e4afb9a2 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs @@ -102,8 +102,8 @@ private void ProcessWebFolder(FolderModelHost folderHost, ModuleFileDefinition m } else { -#if NET35 - throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); +#if NET35 + throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); #endif #if !NET35 @@ -191,8 +191,8 @@ private void ProcessContentTypeFolder(FolderModelHost folderHost, ModuleFileDefi } else { -#if NET35 - throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); +#if NET35 + throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); #endif #if !NET35 @@ -327,7 +327,13 @@ public static void WithSafeFileOperation(List list, File file, if (file != null) { context.Load(file, f => f.Exists); + context.Load(file, f => f.ListItemAllFields); //SergeiSnitko. Need to be loaded to get if object is null context.ExecuteQueryWithTrace(); + //SergeiSnitko. I don't know all logic based on doesFileHasListItem. So I fill doesFileHasListItem by the real value + //of ListItem existing only if doesFileHasListItem is true. This action helps to prevent exceptions on web part provision + //on the page without ListItem not only under Forms folder (for example Forms/ContentTypeName/videoplayerpage.aspx fires exception) + doesFileHasListItem = doesFileHasListItem ? !(bool)file.ListItemAllFields.ServerObjectIsNull : doesFileHasListItem; + if (file.Exists) { @@ -449,9 +455,9 @@ public static void WithSafeFileOperation(List list, File file, if (list != null && spFile != null && (list.EnableModeration)) { -#if NET35 - // TODO, Approve() method is not exposed - throw new SPMeta2NotImplementedException("Not implemented for SP2010 - https://github.com/SubPointSolutions/spmeta2/issues/771"); +#if NET35 + // TODO, Approve() method is not exposed + throw new SPMeta2NotImplementedException("Not implemented for SP2010 - https://github.com/SubPointSolutions/spmeta2/issues/771"); #endif #if !NET35 @@ -558,8 +564,8 @@ private File ProcessFile(FolderModelHost folderHost, ModuleFileDefinition defini #endif -#if NET35 - var doesFileHasListItem = true; +#if NET35 + var doesFileHasListItem = true; #endif WithSafeFileOperation(list, file, f => @@ -580,8 +586,8 @@ private File ProcessFile(FolderModelHost folderHost, ModuleFileDefinition defini } else { -#if NET35 - throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); +#if NET35 + throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); #endif #if !NET35 From 438bb442ee916b80ea6a3e7ba3acd139fb5f3568 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 04:41:31 -0700 Subject: [PATCH 34/53] + Format="0" when provisioning CalculatedField #969 + 1.2.120-beta4 -> 1.2.120-beta5 --- SPMeta2/Build/build.json | 56 +- .../Fields/CalculatedFieldModelHandler.cs | 203 +++--- .../Utils/FieldSchemaXmlUtils.cs | 539 +++++++-------- .../CalculatedFieldDefinitionValidator.cs | 275 ++++---- .../Fields/CalculatedFieldScenariousTest.cs | 633 ++++++++++-------- .../Impl/Syntax/TypedSyntaxTests.cs | 5 + .../SPMeta2.Regression.Tests.csproj | 1 + .../ExpectUpdatAsDisplayFormatService.cs | 37 + .../Fields/CalculatedFieldModelHandler.cs | 220 +++--- .../Attributes/Regression/ExpectUpdate.cs | 5 + .../Fields/CalculatedFieldDefinition.cs | 249 +++---- 11 files changed, 1192 insertions(+), 1031 deletions(-) create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index 2ce2da3d1..c21e9ae41 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -227,7 +227,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -266,11 +266,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -311,11 +311,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -348,15 +348,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -389,11 +389,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -426,15 +426,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -468,11 +468,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -498,15 +498,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -532,11 +532,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -562,15 +562,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -596,11 +596,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -637,15 +637,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta4", + "Version": "1.2.120-beta5", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta4" + "Version": "1.2.120-beta5" }, { "Id": "Microsoft.SharePointOnline.CSOM", diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs index d0a6a539d..2a17ed55c 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs @@ -1,98 +1,105 @@ -using System; -using System.Xml.Linq; -using Microsoft.SharePoint.Client; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Enumerations; -using SPMeta2.Services; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.ModelHandlers.Fields -{ - public class CalculatedFieldModelHandler : FieldModelHandler - { - #region properties - - public override Type TargetType - { - get { return typeof(CalculatedFieldDefinition); } - } - - protected override Type GetTargetFieldType(FieldDefinition model) - { - return typeof(FieldCalculated); - } - - #endregion - - #region methods - - protected override void ProcessFieldProperties(Field field, FieldDefinition fieldModel) - { - // let base setting be setup - base.ProcessFieldProperties(field, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - var typedField = field.Context.CastTo(field); - - if (!string.IsNullOrEmpty(typedFieldModel.Formula)) - { - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); - - typedField.Formula = typedFieldModel.Formula; - } - - if (!string.IsNullOrEmpty(typedFieldModel.OutputType)) - typedField.OutputType = (FieldType)Enum.Parse(typeof(FieldType), typedFieldModel.OutputType); - } - - protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) - { - base.ProcessSPFieldXElement(fieldTemplate, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - - if (typedFieldModel.CurrencyLocaleId.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); - - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); - - // should be a new XML node - var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); - fieldTemplate.Add(formulaNode); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, (int)Enum.Parse(typeof(DateTimeFieldFormatType), typedFieldModel.DateFormat)); - - if (typedFieldModel.ShowAsPercentage.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); - - if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); - - if (typedFieldModel.FieldReferences.Count > 0) - { - var fieldRefsNode = new XElement("FieldRefs"); - - foreach (var fieldRef in typedFieldModel.FieldReferences) - { - var fieldRefNode = new XElement("FieldRef"); - - fieldRefNode.SetAttribute("Name", fieldRef); - fieldRefsNode.Add(fieldRefNode); - } - - fieldTemplate.Add(fieldRefsNode); - } - } - - #endregion - } -} +using System; +using System.Xml.Linq; +using Microsoft.SharePoint.Client; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Enumerations; +using SPMeta2.Services; +using SPMeta2.Utils; + +namespace SPMeta2.CSOM.ModelHandlers.Fields +{ + public class CalculatedFieldModelHandler : FieldModelHandler + { + #region properties + + public override Type TargetType + { + get { return typeof(CalculatedFieldDefinition); } + } + + protected override Type GetTargetFieldType(FieldDefinition model) + { + return typeof(FieldCalculated); + } + + #endregion + + #region methods + + protected override void ProcessFieldProperties(Field field, FieldDefinition fieldModel) + { + // let base setting be setup + base.ProcessFieldProperties(field, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedField = field.Context.CastTo(field); + + if (!string.IsNullOrEmpty(typedFieldModel.Formula)) + { + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); + + typedField.Formula = typedFieldModel.Formula; + + typedField.DateFormat = (DateTimeFieldFormatType) + Enum.Parse(typeof(DateTimeFieldFormatType), typedFieldModel.DateFormat); + } + + if (!string.IsNullOrEmpty(typedFieldModel.OutputType)) + typedField.OutputType = (FieldType)Enum.Parse(typeof(FieldType), typedFieldModel.OutputType); + } + + protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) + { + base.ProcessSPFieldXElement(fieldTemplate, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + + if (typedFieldModel.CurrencyLocaleId.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); + + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); + + // should be a new XML node + var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); + fieldTemplate.Add(formulaNode); + + // must be enum name, actually + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, typedFieldModel.DateFormat); + + if (typedFieldModel.ShowAsPercentage.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); + + if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); + + fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); + + if (typedFieldModel.FieldReferences.Count > 0) + { + var fieldRefsNode = new XElement("FieldRefs"); + + foreach (var fieldRef in typedFieldModel.FieldReferences) + { + var fieldRefNode = new XElement("FieldRef"); + + fieldRefNode.SetAttribute("Name", fieldRef); + fieldRefsNode.Add(fieldRefNode); + } + + fieldTemplate.Add(fieldRefsNode); + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs b/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs index 3df8ed671..f1173037e 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Utils/FieldSchemaXmlUtils.cs @@ -1,268 +1,271 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using System.Xml.Linq; -using Microsoft.SharePoint.Client; -using SPMeta2.Enumerations; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.CSOM.Utils -{ - internal static class FieldSchemaXmlUtils - { - public static string GetSystemInstanceName(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.SystemInstance)); - } - - public static string GetEntityNamespace(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityNamespace)); - } - - public static string GetEntityName(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityName)); - } - - public static string GetBdcFieldName(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.BdcField)); - } - - public static string GetEditFormat(this Field field) - { - var xml = field.SchemaXml; - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); - } - - public static string GetFriendlyDisplayFormat(this FieldDateTime field) - { - return field.FriendlyDisplayFormat.ToString(); - } - - public static string GetDisplayFormat(this FieldDateTime field) - { - return field.DisplayFormat.ToString(); - } - - public static string GetCalendarType(this FieldDateTime field) - { - return field.DateTimeCalendarType.ToString(); - } - - - - public static IEnumerable GetFieldReferences(this Field field) - { - var xml = field.SchemaXml; - - var result = new List(); - - var fieldRefRootNode = XElement.Parse(xml).Descendants("FieldRefs").FirstOrDefault(); - var fieldRefNodes = fieldRefRootNode.Descendants("FieldRef"); - - foreach (var fieldRefNode in fieldRefNodes) - result.Add(fieldRefNode.GetAttributeValue("Name")); - - return result; - } - - public static string GetOutputType(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ResultType)); - } - - public static string GetDisplayFormatString(this Field field) - { - var value = GetDisplayFormat(field); - - if (value == 0) - return BuiltInNumberFormatTypes.Automatic; - - if (value == 1) - return BuiltInNumberFormatTypes.OneDecimal; - - if (value == 2) - return BuiltInNumberFormatTypes.TwoDecimals; - - if (value == 3) - return BuiltInNumberFormatTypes.ThreeDecimals; - - if (value == 4) - return BuiltInNumberFormatTypes.FourDecimals; - - if (value == 5) - return BuiltInNumberFormatTypes.FiveDecimals; - - - - throw new ArgumentException("BuiltInNumberFormatTypes"); - - } - - - public static int GetDisplayFormat(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; - } - - public static string GetDateFormatString(this Field field) - { - var value = GetDateFormat(field); - - if (value == 0) - return BuiltInDateTimeFieldFormatType.DateOnly; - - if (value == 1) - return BuiltInDateTimeFieldFormatType.DateTime; - - throw new ArgumentException("BuiltInDateTimeFieldFormatType"); - - } - - public static int GetDateFormat(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)).Value; - } - - public static int GetCurrencyLocaleId(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.LCID)).Value; - } - - - - public static bool GetShowAsPercentage(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Percentage)).Value; - } - - public static int GetDecimals(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; - } - - public static string GetDecimalsAsString(this Field field) - { - var xml = field.SchemaXml; - - return GetDecimalsValue(GetDecimals(field)); - } - - private static string GetDecimalsValue(int value) - { - if (value == -1) - return BuiltInNumberFormatTypes.Automatic; - - if (value == 0) - return BuiltInNumberFormatTypes.NoDecimal; - - if (value == 1) - return BuiltInNumberFormatTypes.OneDecimal; - - if (value == 2) - return BuiltInNumberFormatTypes.TwoDecimals; - - if (value == 3) - return BuiltInNumberFormatTypes.ThreeDecimals; - - if (value == 4) - return BuiltInNumberFormatTypes.FourDecimals; - - if (value == 5) - return BuiltInNumberFormatTypes.FiveDecimals; - - throw new ArgumentException("Decimals"); - } - - - public static bool GetRichText(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichText), false); - } - - public static string GetRichTextMode(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichTextMode)); - } - - public static bool GetUnlimitedLengthInDocumentLibrary(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.UnlimitedLengthInDocumentLibrary), false); - } - - public static bool? GetShowInDisplayForm(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInDisplayForm)); - } - - public static bool? GetShowInEditForm(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInEditForm)); - } - - public static bool? GetShowInListSettings(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInListSettings)); - } - - public static bool? GetShowInNewForm(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInNewForm)); - } - - public static bool? GetShowInVersionHistory(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInVersionHistory)); - } - - public static bool? GetShowInViewForms(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInViewForms)); - } - - public static bool? GetAllowDeletion(this Field field) - { - var xml = field.SchemaXml; - - return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.AllowDeletion)); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using System.Xml.Linq; +using Microsoft.SharePoint.Client; +using SPMeta2.Enumerations; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.CSOM.Utils +{ + internal static class FieldSchemaXmlUtils + { + public static string GetSystemInstanceName(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.SystemInstance)); + } + + public static string GetEntityNamespace(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityNamespace)); + } + + public static string GetEntityName(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.EntityName)); + } + + public static string GetBdcFieldName(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.BdcField)); + } + + public static string GetEditFormat(this Field field) + { + var xml = field.SchemaXml; + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); + } + + public static string GetFriendlyDisplayFormat(this FieldDateTime field) + { + return field.FriendlyDisplayFormat.ToString(); + } + + public static string GetDisplayFormat(this FieldDateTime field) + { + return field.DisplayFormat.ToString(); + } + + public static string GetCalendarType(this FieldDateTime field) + { + return field.DateTimeCalendarType.ToString(); + } + + + + public static IEnumerable GetFieldReferences(this Field field) + { + var xml = field.SchemaXml; + + var result = new List(); + + var fieldRefRootNode = XElement.Parse(xml).Descendants("FieldRefs").FirstOrDefault(); + var fieldRefNodes = fieldRefRootNode.Descendants("FieldRef"); + + foreach (var fieldRefNode in fieldRefNodes) + result.Add(fieldRefNode.GetAttributeValue("Name")); + + return result; + } + + public static string GetOutputType(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ResultType)); + } + + public static string GetDisplayFormatString(this Field field) + { + var value = GetDisplayFormat(field); + + if (value == 0) + return BuiltInNumberFormatTypes.Automatic; + + if (value == 1) + return BuiltInNumberFormatTypes.OneDecimal; + + if (value == 2) + return BuiltInNumberFormatTypes.TwoDecimals; + + if (value == 3) + return BuiltInNumberFormatTypes.ThreeDecimals; + + if (value == 4) + return BuiltInNumberFormatTypes.FourDecimals; + + if (value == 5) + return BuiltInNumberFormatTypes.FiveDecimals; + + + + throw new ArgumentException("BuiltInNumberFormatTypes"); + + } + + + public static int GetDisplayFormat(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; + } + + public static string GetDateFormatString(this Field field) + { + var value = GetDateFormat(field); + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateOnly, true) == 0) + return BuiltInDateTimeFieldFormatType.DateOnly; + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateTime, true) == 0) + return BuiltInDateTimeFieldFormatType.DateTime; + + throw new ArgumentException("BuiltInDateTimeFieldFormatType was:" + value); + + } + + public static string GetDateFormat(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); + } + + public static int GetCurrencyLocaleId(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.LCID)).Value; + } + + + + public static bool GetShowAsPercentage(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Percentage)).Value; + } + + public static int GetDecimals(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToInt(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Decimals)).Value; + } + + public static string GetDecimalsAsString(this Field field) + { + var xml = field.SchemaXml; + + return GetDecimalsValue(GetDecimals(field)); + } + + private static string GetDecimalsValue(int value) + { + if (value == -1) + return BuiltInNumberFormatTypes.Automatic; + + if (value == 0) + return BuiltInNumberFormatTypes.NoDecimal; + + if (value == 1) + return BuiltInNumberFormatTypes.OneDecimal; + + if (value == 2) + return BuiltInNumberFormatTypes.TwoDecimals; + + if (value == 3) + return BuiltInNumberFormatTypes.ThreeDecimals; + + if (value == 4) + return BuiltInNumberFormatTypes.FourDecimals; + + if (value == 5) + return BuiltInNumberFormatTypes.FiveDecimals; + + throw new ArgumentException("Decimals"); + } + + + public static bool GetRichText(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichText), false); + } + + public static string GetRichTextMode(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.RichTextMode)); + } + + public static bool GetUnlimitedLengthInDocumentLibrary(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBoolWithDefault(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.UnlimitedLengthInDocumentLibrary), false); + } + + public static bool? GetShowInDisplayForm(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInDisplayForm)); + } + + public static bool? GetShowInEditForm(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInEditForm)); + } + + public static bool? GetShowInListSettings(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInListSettings)); + } + + public static bool? GetShowInNewForm(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInNewForm)); + } + + public static bool? GetShowInVersionHistory(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInVersionHistory)); + } + + public static bool? GetShowInViewForms(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.ShowInViewForms)); + } + + public static bool? GetAllowDeletion(this Field field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToBool(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.AllowDeletion)); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs index fd36ab75a..4779a924f 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/Fields/CalculatedFieldDefinitionValidator.cs @@ -1,120 +1,155 @@ -using System; -using System.Linq; -using SPMeta2.Containers.Assertion; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Utils; -using Microsoft.SharePoint; -using SPMeta2.Containers.Utils; - -namespace SPMeta2.Regression.SSOM.Validation.Fields -{ - public class CalculatedFieldDefinitionValidator : FieldDefinitionValidator - { - public override Type TargetType - { - get - { - return typeof(CalculatedFieldDefinition); - } - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = GetField(modelHost, definition); - - var assert = ServiceFactory.AssertService.NewAssert(model, definition, spObject); - - ValidateField(assert, spObject, definition); - - var typedField = spObject as SPFieldCalculated; - - var typedDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var typedFieldAssert = ServiceFactory.AssertService.NewAssert(model, typedDefinition, typedField); - - typedFieldAssert.ShouldBeEqual(m => m.CurrencyLocaleId, o => o.CurrencyLocaleId); - typedFieldAssert.ShouldBeEqual(m => m.DateFormat, o => o.GetDateFormat()); - - typedFieldAssert.ShouldBeEqual(m => m.OutputType, o => o.GetOutputType()); - // - typedFieldAssert.ShouldBeEqual(m => m.DisplayFormat, o => o.GetDisplayFormat()); - - if (typedDefinition.ShowAsPercentage.HasValue) - typedFieldAssert.ShouldBeEqual(m => m.ShowAsPercentage, o => o.ShowAsPercentage); - else - typedFieldAssert.SkipProperty(m => m.ShowAsPercentage, "ShowAsPercentage is NULL. Skipping."); - - if (!string.IsNullOrEmpty(typedDefinition.Formula)) - typedFieldAssert.ShouldBeEqual(m => m.Formula, o => o.Formula); - else - typedFieldAssert.SkipProperty(m => m.Formula); - - IndentableTrace.WithScope(s => - { - s.WriteLine(string.Format("Formula: Src:[{0}] Dst:[{1}]", typedDefinition.Formula, typedField.Formula)); - }); - - // field refs - if (typedDefinition.FieldReferences.Count > 0) - { - var hasFieldRefs = true; - - if (typedField.FieldReferences != null) - { - foreach (var dstFieldRef in typedField.FieldReferences) - { - if (typedDefinition.FieldReferences.FirstOrDefault(c => c.ToUpper() == dstFieldRef.ToUpper()) == - null) - { - hasFieldRefs = false; - } - } - - if (typedField.FieldReferences.Length == 0) - hasFieldRefs = false; - } - else - { - hasFieldRefs = false; - } - - typedFieldAssert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.FieldReferences); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = hasFieldRefs == true - }; - }); - } - else - { - typedFieldAssert.SkipProperty(m => m.FieldReferences, "FieldReferences.Count == 0. Skipping."); - } - - } - } - - internal static class SPFieldCalculatedUtils - { - public static string GetOutputType(this SPFieldCalculated field) - { - return field.OutputType.ToString(); - } - - public static string GetDisplayFormat(this SPFieldCalculated field) - { - return field.DisplayFormat.ToString(); - } - - public static string GetDateFormat(this SPFieldCalculated field) - { - return field.DateFormat.ToString(); - } - } -} +using System; +using System.Linq; +using SPMeta2.Containers.Assertion; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Utils; +using Microsoft.SharePoint; +using SPMeta2.Containers.Utils; +using System.Xml.Linq; +using SPMeta2.Enumerations; + +namespace SPMeta2.Regression.SSOM.Validation.Fields +{ + public class CalculatedFieldDefinitionValidator : FieldDefinitionValidator + { + public override Type TargetType + { + get + { + return typeof(CalculatedFieldDefinition); + } + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var spObject = GetField(modelHost, definition); + + var assert = ServiceFactory.AssertService.NewAssert(model, definition, spObject); + + ValidateField(assert, spObject, definition); + + var typedField = spObject as SPFieldCalculated; + + var typedDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedFieldAssert = ServiceFactory.AssertService.NewAssert(model, typedDefinition, typedField); + + typedFieldAssert.ShouldBeEqual(m => m.CurrencyLocaleId, o => o.CurrencyLocaleId); + typedFieldAssert.ShouldBeEqual(m => m.DateFormat, o => o.GetDateFormat()); + + + + typedFieldAssert.ShouldBeEqual(m => m.OutputType, o => o.GetOutputType()); + // + typedFieldAssert.ShouldBeEqual(m => m.DisplayFormat, o => o.GetDisplayFormat()); + + if (typedDefinition.ShowAsPercentage.HasValue) + typedFieldAssert.ShouldBeEqual(m => m.ShowAsPercentage, o => o.ShowAsPercentage); + else + typedFieldAssert.SkipProperty(m => m.ShowAsPercentage, "ShowAsPercentage is NULL. Skipping."); + + if (!string.IsNullOrEmpty(typedDefinition.Formula)) + typedFieldAssert.ShouldBeEqual(m => m.Formula, o => o.Formula); + else + typedFieldAssert.SkipProperty(m => m.Formula); + + IndentableTrace.WithScope(s => + { + s.WriteLine(string.Format("Formula: Src:[{0}] Dst:[{1}]", typedDefinition.Formula, typedField.Formula)); + }); + + // field refs + if (typedDefinition.FieldReferences.Count > 0) + { + var hasFieldRefs = true; + + if (typedField.FieldReferences != null) + { + foreach (var dstFieldRef in typedField.FieldReferences) + { + if (typedDefinition.FieldReferences.FirstOrDefault(c => c.ToUpper() == dstFieldRef.ToUpper()) == + null) + { + hasFieldRefs = false; + } + } + + if (typedField.FieldReferences.Length == 0) + hasFieldRefs = false; + } + else + { + hasFieldRefs = false; + } + + typedFieldAssert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.FieldReferences); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = hasFieldRefs == true + }; + }); + } + else + { + typedFieldAssert.SkipProperty(m => m.FieldReferences, "FieldReferences.Count == 0. Skipping."); + } + + } + } + + internal static class SPFieldCalculatedUtils + { + public static string GetOutputType(this SPFieldCalculated field) + { + return field.OutputType.ToString(); + } + + public static string GetDisplayFormat(this SPFieldCalculated field) + { + return field.DisplayFormat.ToString(); + } + + public static string GetDateFormat(this SPFieldCalculated field) + { + var value = field.DateFormat.ToString(); ; + + // also, wihtint expected range + field.GetDateFormatString(); + + return field.DateFormat.ToString(); + } + + public static string GetDateFormatString(this SPField field) + { + var value = GetDateFormat(field); + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateOnly, true) == 0) + return BuiltInDateTimeFieldFormatType.DateOnly; + + if (string.Compare(value, BuiltInDateTimeFieldFormatType.DateTime, true) == 0) + return BuiltInDateTimeFieldFormatType.DateTime; + + throw new ArgumentException("BuiltInDateTimeFieldFormatType was:" + value); + + } + + public static string GetDateFormat(this SPField field) + { + var xml = field.SchemaXml; + + return ConvertUtils.ToString(XElement.Parse(xml).GetAttributeValue(BuiltInFieldAttributes.Format)); + } + } + + +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs index ad83b8c6f..bba778f36 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Fields/CalculatedFieldScenariousTest.cs @@ -1,288 +1,345 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Containers; - -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Enumerations; -using SPMeta2.Exceptions; -using SPMeta2.Models; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using SPMeta2.Syntax.Default; -using SPMeta2.Syntax.Default.Modern; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios.Fields -{ - [TestClass] - public class CalculatedFieldScenariousTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitialize] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanup] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region utils - - protected CalculatedFieldDefinition GetCalculatedFieldDefinition() - { - return GetCalculatedFieldDefinition(null); - } - - protected CalculatedFieldDefinition GetCalculatedFieldDefinition(Action action) - { - var result = ModelGeneratorService.GetRandomDefinition(def => - { - def.ShowInNewForm = true; - def.ShowInEditForm = true; - def.ShowInDisplayForm = true; - - def.ShowInListSettings = true; - - def.Hidden = false; - def.Required = false; - }); - - if (action != null) - action(result); - - return result; - } - - protected FieldDefinition GetRandomFieldWithType(string type) - { - return ModelGeneratorService.GetRandomDefinition(def => - { - def.FieldType = type; - - def.ShowInNewForm = true; - def.ShowInEditForm = true; - def.ShowInDisplayForm = true; - - def.ShowInListSettings = true; - - def.Hidden = false; - def.Required = false; - }); - } - - #endregion - - #region formula changes - - - //[TestMethod] - //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] - //public void CanDeploy_CalculatedSiteField_AndChangeFormula() - //{ - // //RegressionService.EnableDefinitionValidation = false; - // //RegressionService.EnableEventValidation = false; - - // var field = GetCalculatedFieldDefinition(def => - // { - // def.OutputType = BuiltInFieldTypes.Text; - // }); - - // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // field.FieldReferences = new Collection() - // { - // firstTextField.InternalName, - // firstTextField.InternalName, - // firstTextField.InternalName, - - // secondIntField.InternalName, - // secondTextField.InternalName, - // secondNumberField.InternalName - - // }; - - // var siteModel = SPMeta2Model.NewSiteModel(site => - // { - // site.AddField(firstIntField); - // site.AddField(firstTextField); - // site.AddField(firstNumberField); - - // site.AddField(secondIntField); - // site.AddField(secondTextField); - // site.AddField(secondNumberField); - - // site.AddField(field); - // }); - - // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // firstTextField.InternalName, - // firstTextField.InternalName, - // firstTextField.InternalName, - // }); - - // RegressionService.ProvisionGenerationCount = 1; - - // TestModel(siteModel); - // TestModel(siteModel); - - // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // secondIntField.InternalName, - // secondTextField.InternalName, - // secondNumberField.InternalName, - // }); - - // TestModel(siteModel); - // TestModel(siteModel); - //} - - - //[TestMethod] - //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] - //public void CanDeploy_CalculatedFieldToList_AndChangeFormula() - //{ - // RegressionService.ProvisionGenerationCount = 1; - - // var calcField = GetCalculatedFieldDefinition(def => - // { - // def.OutputType = BuiltInFieldTypes.Text; - // }); - - // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); - // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); - // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); - - // var contentTypeWithCalcField = ModelGeneratorService.GetRandomDefinition(def => - // { - // def.Hidden = false; - // def.ParentContentTypeId = BuiltInContentTypeId.Item; - // }); - - // var listWithCalcContentType = ModelGeneratorService.GetRandomDefinition(def => - // { - // def.ContentTypesEnabled = true; - // def.Hidden = false; - // def.TemplateType = BuiltInListTemplateTypeId.GenericList; - // }); - - // calcField.FieldReferences = new Collection() - // { - // firstIntField.InternalName, - // firstTextField.InternalName, - // firstNumberField.InternalName, - - // secondIntField.InternalName, - // secondTextField.InternalName, - // secondNumberField.InternalName, - // "Title" - // }; - - // var siteModel = SPMeta2Model.NewSiteModel(site => - // { - // site.AddField(firstIntField); - // site.AddField(firstTextField); - // site.AddField(firstNumberField); - - // site.AddField(secondIntField); - // site.AddField(secondTextField); - // site.AddField(secondNumberField); - - // site.AddField(calcField); - - // site.AddContentType(contentTypeWithCalcField, contentType => - // { - // contentType - // .AddContentTypeFieldLink(firstIntField) - // .AddContentTypeFieldLink(firstTextField) - // .AddContentTypeFieldLink(firstNumberField) - - // .AddContentTypeFieldLink(secondIntField) - // .AddContentTypeFieldLink(secondTextField) - // .AddContentTypeFieldLink(secondNumberField) - - // .AddContentTypeFieldLink(calcField); - // }); - // }); - - // calcField.Formula = string.Format("=[Title]"); - - // //calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // // new String[] - // // { - // // firstIntField.InternalName, - // // firstNumberField.InternalName, - // // firstTextField.InternalName, - // // }); - - // TestModel(siteModel); - // TestModel(siteModel); - - // var webModel = SPMeta2Model.NewWebModel(web => - // { - // web.AddList(listWithCalcContentType, list => - // { - // list.AddContentTypeLink(contentTypeWithCalcField); - // }); - // }); - - // TestModel(webModel); - // TestModel(webModel); - - // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // firstIntField.InternalName, - // firstNumberField.InternalName, - // firstTextField.InternalName, - // }); - - // var subSiteModel = SPMeta2Model.NewSiteModel(site => - // { - // site.AddField(calcField); - - // //site.AddContentType(contentTypeWithCalcField, contentType => - // //{ - // // contentType - // // .AddContentTypeFieldLink(calcField); - // //}); - // }); - - // TestModel(subSiteModel); - - // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", - // new String[] - // { - // firstIntField.InternalName, - // firstNumberField.InternalName, - // firstTextField.InternalName, - // }); - - // TestModel(siteModel); - // TestModel(siteModel); - //} - - #endregion - } -} +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Containers; + +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Enumerations; +using SPMeta2.Exceptions; +using SPMeta2.Models; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using SPMeta2.Syntax.Default; +using SPMeta2.Syntax.Default.Modern; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios.Fields +{ + [TestClass] + public class CalculatedFieldScenariousTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitialize] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanup] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region utils + + protected CalculatedFieldDefinition GetCalculatedFieldDefinition() + { + return GetCalculatedFieldDefinition(null); + } + + protected CalculatedFieldDefinition GetCalculatedFieldDefinition(Action action) + { + var result = ModelGeneratorService.GetRandomDefinition(def => + { + def.ShowInNewForm = true; + def.ShowInEditForm = true; + def.ShowInDisplayForm = true; + + def.ShowInListSettings = true; + + def.Hidden = false; + def.Required = false; + }); + + if (action != null) + action(result); + + return result; + } + + protected FieldDefinition GetRandomFieldWithType(string type) + { + return ModelGeneratorService.GetRandomDefinition(def => + { + def.FieldType = type; + + def.ShowInNewForm = true; + def.ShowInEditForm = true; + def.ShowInDisplayForm = true; + + def.ShowInListSettings = true; + + def.Hidden = false; + def.Required = false; + }); + } + + #endregion + + [TestMethod] + [TestCategory("Regression.Scenarios.Fields.CalculatedField")] + public void CanDeploy_CalculatedField_OutputType_All() + { + var outputTypes = new[] { + BuiltInFieldTypes.Text, + BuiltInFieldTypes.Number, + BuiltInFieldTypes.Integer, + BuiltInFieldTypes.Currency, + BuiltInFieldTypes.Boolean, + BuiltInFieldTypes.DateTime + }; + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + foreach (var outputType in outputTypes) + { + var field = GetCalculatedFieldDefinition(def => + { + def.DateFormat = BuiltInDateTimeFieldFormatType.DateOnly; + def.OutputType = outputType; + }); + + site.AddCalculatedField(field); + } + }); + + TestModel(siteModel); + TestModel(siteModel); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Fields.CalculatedField")] + public void CanDeploy_CalculatedField_DateFormat_All() + { + var formatTypes = new[] { + BuiltInDateTimeFieldFormatType.DateOnly, + BuiltInDateTimeFieldFormatType.DateTime + }; + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + foreach (var outputType in formatTypes) + { + var field = GetCalculatedFieldDefinition(def => + { + def.DateFormat = outputType; + }); + + site.AddCalculatedField(field); + } + }); + + TestModel(siteModel); + TestModel(siteModel); + } + + #region formula changes + + + //[TestMethod] + //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] + //public void CanDeploy_CalculatedSiteField_AndChangeFormula() + //{ + // //RegressionService.EnableDefinitionValidation = false; + // //RegressionService.EnableEventValidation = false; + + // var field = GetCalculatedFieldDefinition(def => + // { + // def.OutputType = BuiltInFieldTypes.Text; + // }); + + // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // field.FieldReferences = new Collection() + // { + // firstTextField.InternalName, + // firstTextField.InternalName, + // firstTextField.InternalName, + + // secondIntField.InternalName, + // secondTextField.InternalName, + // secondNumberField.InternalName + + // }; + + // var siteModel = SPMeta2Model.NewSiteModel(site => + // { + // site.AddField(firstIntField); + // site.AddField(firstTextField); + // site.AddField(firstNumberField); + + // site.AddField(secondIntField); + // site.AddField(secondTextField); + // site.AddField(secondNumberField); + + // site.AddField(field); + // }); + + // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // firstTextField.InternalName, + // firstTextField.InternalName, + // firstTextField.InternalName, + // }); + + // RegressionService.ProvisionGenerationCount = 1; + + // TestModel(siteModel); + // TestModel(siteModel); + + // field.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // secondIntField.InternalName, + // secondTextField.InternalName, + // secondNumberField.InternalName, + // }); + + // TestModel(siteModel); + // TestModel(siteModel); + //} + + + //[TestMethod] + //[TestCategory("Regression.Scenarios.Fields.CalculatedField")] + //public void CanDeploy_CalculatedFieldToList_AndChangeFormula() + //{ + // RegressionService.ProvisionGenerationCount = 1; + + // var calcField = GetCalculatedFieldDefinition(def => + // { + // def.OutputType = BuiltInFieldTypes.Text; + // }); + + // var firstIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var firstTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var firstNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // var secondIntField = GetRandomFieldWithType(BuiltInFieldTypes.Integer); + // var secondTextField = GetRandomFieldWithType(BuiltInFieldTypes.Text); + // var secondNumberField = GetRandomFieldWithType(BuiltInFieldTypes.Number); + + // var contentTypeWithCalcField = ModelGeneratorService.GetRandomDefinition(def => + // { + // def.Hidden = false; + // def.ParentContentTypeId = BuiltInContentTypeId.Item; + // }); + + // var listWithCalcContentType = ModelGeneratorService.GetRandomDefinition(def => + // { + // def.ContentTypesEnabled = true; + // def.Hidden = false; + // def.TemplateType = BuiltInListTemplateTypeId.GenericList; + // }); + + // calcField.FieldReferences = new Collection() + // { + // firstIntField.InternalName, + // firstTextField.InternalName, + // firstNumberField.InternalName, + + // secondIntField.InternalName, + // secondTextField.InternalName, + // secondNumberField.InternalName, + // "Title" + // }; + + // var siteModel = SPMeta2Model.NewSiteModel(site => + // { + // site.AddField(firstIntField); + // site.AddField(firstTextField); + // site.AddField(firstNumberField); + + // site.AddField(secondIntField); + // site.AddField(secondTextField); + // site.AddField(secondNumberField); + + // site.AddField(calcField); + + // site.AddContentType(contentTypeWithCalcField, contentType => + // { + // contentType + // .AddContentTypeFieldLink(firstIntField) + // .AddContentTypeFieldLink(firstTextField) + // .AddContentTypeFieldLink(firstNumberField) + + // .AddContentTypeFieldLink(secondIntField) + // .AddContentTypeFieldLink(secondTextField) + // .AddContentTypeFieldLink(secondNumberField) + + // .AddContentTypeFieldLink(calcField); + // }); + // }); + + // calcField.Formula = string.Format("=[Title]"); + + // //calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // // new String[] + // // { + // // firstIntField.InternalName, + // // firstNumberField.InternalName, + // // firstTextField.InternalName, + // // }); + + // TestModel(siteModel); + // TestModel(siteModel); + + // var webModel = SPMeta2Model.NewWebModel(web => + // { + // web.AddList(listWithCalcContentType, list => + // { + // list.AddContentTypeLink(contentTypeWithCalcField); + // }); + // }); + + // TestModel(webModel); + // TestModel(webModel); + + // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // firstIntField.InternalName, + // firstNumberField.InternalName, + // firstTextField.InternalName, + // }); + + // var subSiteModel = SPMeta2Model.NewSiteModel(site => + // { + // site.AddField(calcField); + + // //site.AddContentType(contentTypeWithCalcField, contentType => + // //{ + // // contentType + // // .AddContentTypeFieldLink(calcField); + // //}); + // }); + + // TestModel(subSiteModel); + + // calcField.Formula = string.Format("=CONCATENATE([{0}],[{1}],[{2}])", + // new String[] + // { + // firstIntField.InternalName, + // firstNumberField.InternalName, + // firstTextField.InternalName, + // }); + + // TestModel(siteModel); + // TestModel(siteModel); + //} + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs index 22b4031a9..91b7e159a 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Syntax/TypedSyntaxTests.cs @@ -232,6 +232,11 @@ public void CanPassTypedSyntax_WebLevel() .AddProperty(new PropertyDefinition()); + list.AddContentTypeLink(new ContentTypeLinkDefinition(), contentTypeLink => + { + contentTypeLink.AddWorkflowAssociation(new WorkflowAssociationDefinition()); + + }); list.AddUniqueContentTypeOrder(new UniqueContentTypeOrderDefinition()); list.AddHideContentTypeLinks(new HideContentTypeLinksDefinition()); list.AddRemoveContentTypeLinks(new RemoveContentTypeLinksDefinition()); diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index f4c024c49..423dd6f01 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -273,6 +273,7 @@ + diff --git a/SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs b/SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs new file mode 100644 index 000000000..e87f69aac --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Services/ExpectUpdateServices/ExpectUpdatAsDisplayFormatService.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using SPMeta2.Attributes.Regression; +using SPMeta2.Containers.Services; +using SPMeta2.Enumerations; + +namespace SPMeta2.Regression.Tests.Services.ExpectUpdateServices +{ + public class ExpectUpdateAsDateFormatService : ExpectUpdateGenericService + { + public override object GetNewPropValue(ExpectUpdate attr, object obj, PropertyInfo prop) + { + object newValue = null; + + var curentValue = prop.GetValue(obj) as string; + + if (curentValue == BuiltInDateTimeFieldFormatType.DateOnly) + { + newValue = BuiltInDateTimeFieldFormatType.DateTime; + } + if (curentValue == BuiltInDateTimeFieldFormatType.DateTime) + { + newValue = BuiltInDateTimeFieldFormatType.DateOnly; + } + else + { + newValue = RndService.RandomFromArray(new string[]{ + BuiltInDateTimeFieldFormatType.DateOnly, + BuiltInDateTimeFieldFormatType.DateTime + }); + } + + return newValue; + } + } +} diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs index 6dfd81165..07db2780e 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/Fields/CalculatedFieldModelHandler.cs @@ -1,105 +1,115 @@ -using System; -using System.Linq; -using System.Xml.Linq; -using Microsoft.SharePoint; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Fields; -using SPMeta2.Enumerations; -using SPMeta2.Utils; -using SPMeta2.Services; - -namespace SPMeta2.SSOM.ModelHandlers.Fields -{ - public class CalculatedFieldModelHandler : FieldModelHandler - { - #region properties - - public override Type TargetType - { - get { return typeof(CalculatedFieldDefinition); } - } - - protected override Type GetTargetFieldType(FieldDefinition model) - { - return typeof(SPFieldCalculated); - } - - #endregion - - #region methods - - protected override void ProcessFieldProperties(SPField field, FieldDefinition fieldModel) - { - // let base setting be setup - base.ProcessFieldProperties(field, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - var typedField = field as SPFieldCalculated; - - if (!string.IsNullOrEmpty(typedFieldModel.Formula)) - { - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); - - typedField.Formula = typedFieldModel.Formula; - } - - if (typedFieldModel.ShowAsPercentage.HasValue) - typedField.ShowAsPercentage = typedFieldModel.ShowAsPercentage.Value; - - typedField.OutputType = (SPFieldType)Enum.Parse(typeof(SPFieldType), typedFieldModel.OutputType); - } - - protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) - { - base.ProcessSPFieldXElement(fieldTemplate, fieldModel); - - var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); - - if (typedFieldModel.CurrencyLocaleId.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); - - if (!string.IsNullOrEmpty(typedFieldModel.Formula)) - { - // can't really validate it automatically - // Improve CalculatedFieldDefinition with field ref check - // https://github.com/SubPointSolutions/spmeta2/issues/648 - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); - - // should be a new XML node - var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); - fieldTemplate.Add(formulaNode); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, - (int)Enum.Parse(typeof(SPDateTimeFieldFormatType), typedFieldModel.DateFormat)); - } - - if (typedFieldModel.ShowAsPercentage.HasValue) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); - - if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) - fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); - - fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); - - if (typedFieldModel.FieldReferences.Count > 0) - { - var fieldRefsNode = new XElement("FieldRefs"); - - foreach (var fieldRef in typedFieldModel.FieldReferences) - { - var fieldRefNode = new XElement("FieldRef"); - - fieldRefNode.SetAttribute("Name", fieldRef); - fieldRefsNode.Add(fieldRefNode); - } - - fieldTemplate.Add(fieldRefsNode); - } - } - - #endregion - } -} +using System; +using System.Linq; +using System.Xml.Linq; +using Microsoft.SharePoint; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Fields; +using SPMeta2.Enumerations; +using SPMeta2.Utils; +using SPMeta2.Services; + +namespace SPMeta2.SSOM.ModelHandlers.Fields +{ + public class CalculatedFieldModelHandler : FieldModelHandler + { + #region properties + + public override Type TargetType + { + get { return typeof(CalculatedFieldDefinition); } + } + + protected override Type GetTargetFieldType(FieldDefinition model) + { + return typeof(SPFieldCalculated); + } + + #endregion + + #region methods + + protected override void ProcessFieldProperties(SPField field, FieldDefinition fieldModel) + { + // let base setting be setup + base.ProcessFieldProperties(field, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedField = field as SPFieldCalculated; + + if (!string.IsNullOrEmpty(typedFieldModel.Formula)) + { + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Updating formula for a CalculatedField. Ensure FieldReferences are correct."); + + typedField.Formula = typedFieldModel.Formula; + + var dateFormatValue = (SPDateTimeFieldFormatType)Enum.Parse(typeof(SPDateTimeFieldFormatType), typedFieldModel.DateFormat); + + typedField.DateFormat = dateFormatValue; + } + + if (typedFieldModel.ShowAsPercentage.HasValue) + typedField.ShowAsPercentage = typedFieldModel.ShowAsPercentage.Value; + + typedField.OutputType = (SPFieldType)Enum.Parse(typeof(SPFieldType), typedFieldModel.OutputType); + } + + protected override void ProcessSPFieldXElement(XElement fieldTemplate, FieldDefinition fieldModel) + { + base.ProcessSPFieldXElement(fieldTemplate, fieldModel); + + var typedFieldModel = fieldModel.WithAssertAndCast("model", value => value.RequireNotNull()); + + if (typedFieldModel.CurrencyLocaleId.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.LCID, typedFieldModel.CurrencyLocaleId); + + if (!string.IsNullOrEmpty(typedFieldModel.Formula)) + { + // can't really validate it automatically + // Improve CalculatedFieldDefinition with field ref check + // https://github.com/SubPointSolutions/spmeta2/issues/648 + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Crafting formula for a CalculatedField. Ensure FieldReferences are correct."); + + // should be a new XML node + var formulaNode = new XElement(BuiltInFieldAttributes.Formula, typedFieldModel.Formula); + fieldTemplate.Add(formulaNode); + + + // Format="0" when provisioning CalculatedField #969 + // https://github.com/SubPointSolutions/spmeta2/issues/969 + + //fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, + // (int)Enum.Parse(typeof(SPDateTimeFieldFormatType), typedFieldModel.DateFormat)); + + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Format, typedFieldModel.DateFormat); + } + + if (typedFieldModel.ShowAsPercentage.HasValue) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Percentage, typedFieldModel.ShowAsPercentage.Value.ToString().ToUpper()); + + if (!string.IsNullOrEmpty(typedFieldModel.DisplayFormat)) + fieldTemplate.SetAttribute(BuiltInFieldAttributes.Decimals, NumberFieldModelHandler.GetDecimalsValue(typedFieldModel.DisplayFormat)); + + fieldTemplate.SetAttribute(BuiltInFieldAttributes.ResultType, typedFieldModel.OutputType); + + if (typedFieldModel.FieldReferences.Count > 0) + { + var fieldRefsNode = new XElement("FieldRefs"); + + foreach (var fieldRef in typedFieldModel.FieldReferences) + { + var fieldRefNode = new XElement("FieldRef"); + + fieldRefNode.SetAttribute("Name", fieldRef); + fieldRefsNode.Add(fieldRefNode); + } + + fieldTemplate.Add(fieldRefsNode); + } + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs b/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs index 893055e01..7af883f43 100644 --- a/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs +++ b/SPMeta2/SPMeta2/Attributes/Regression/ExpectUpdate.cs @@ -218,4 +218,9 @@ public class ExpectUpdateAsXsltListViewXslLinkUrl : ExpectUpdateAsXsltListView } + public class ExpectUpdateAsDateFormat : ExpectUpdate + { + + } + } diff --git a/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs b/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs index d87415f18..ccc16420f 100644 --- a/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs +++ b/SPMeta2/SPMeta2/Definitions/Fields/CalculatedFieldDefinition.cs @@ -1,124 +1,125 @@ -using System; -using System.Collections.ObjectModel; -using System.Runtime.Serialization; -using SPMeta2.Attributes; -using SPMeta2.Attributes.Regression; -using SPMeta2.Enumerations; -using SPMeta2.Utils; - -namespace SPMeta2.Definitions.Fields -{ - /// - /// Allows to define and deploy calculated field. - /// - /// - [SPObjectType(SPObjectModelType.SSOM, "Microsoft.SharePoint.SPFieldCalculated", "Microsoft.SharePoint")] - [SPObjectType(SPObjectModelType.CSOM, "Microsoft.SharePoint.Client.FieldCalculated", "Microsoft.SharePoint.Client")] - - [DefaultParentHost(typeof(SiteDefinition))] - [DefaultRootHost(typeof(SiteDefinition))] - - [Serializable] - [DataContract] - [ExpectArrayExtensionMethod] - - [ExpectManyInstances] - - public class CalculatedFieldDefinition : FieldDefinition - { - #region constructors - - public CalculatedFieldDefinition() - { - FieldType = BuiltInFieldTypes.Calculated; - FieldReferences = new Collection(); - - DateFormat = BuiltInDateTimeFieldFormatType.DateOnly; - CurrencyLocaleId = 1033; - } - - #endregion - - #region properties - - [ExpectValidation] - [ExpectRequired] - [DataMember] - public override sealed string FieldType { get; set; } - - [ExpectValidation] - [DataMember] - public override string ValidationMessage - { - get { return string.Empty; } - set { } - } - - [ExpectValidation] - [DataMember] - public override string ValidationFormula - { - get { return string.Empty; } - set { } - } - - [ExpectValidation] - [DataMember] - public int? CurrencyLocaleId { get; set; } - - [ExpectValidation] - [DataMember] - public string DateFormat { get; set; } - - [ExpectValidation] - [DataMember] - public string DisplayFormat { get; set; } - - [ExpectValidation] - [ExpectUpdateAsCalculatedFieldFormula] - [DataMember] - [ExpectNullable] - public string Formula { get; set; } - - [ExpectValidation] - [ExpectUpdateAssCalculatedFieldOutputType] - [DataMember] - public string OutputType { get; set; } - - [ExpectValidation] - //[ExpectUpdate] - [DataMember] - public bool? ShowAsPercentage { get; set; } - - [ExpectValidation] - //[ExpectUpdateAssCalculatedFieldReferences] - [DataMember] - public Collection FieldReferences { get; set; } - - [ExpectValidation] - [DataMember] - public override string DefaultValue - { - get - { - // #SPBUG - // Calculated field MUST return string.Empty to avoid setting DefaultValue for field. - // SharePoint drive crazy if calculated field has default value. FieldRefs would be NULL, tons of failures would be there. - return string.Empty; - } - set { } - } - - #endregion - - #region methods - - public override string ToString() - { - return new ToStringResult(this, base.ToString()) - .ToString(); - } - - #endregion - } -} +using System; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using SPMeta2.Attributes; +using SPMeta2.Attributes.Regression; +using SPMeta2.Enumerations; +using SPMeta2.Utils; + +namespace SPMeta2.Definitions.Fields +{ + /// + /// Allows to define and deploy calculated field. + /// + /// + [SPObjectType(SPObjectModelType.SSOM, "Microsoft.SharePoint.SPFieldCalculated", "Microsoft.SharePoint")] + [SPObjectType(SPObjectModelType.CSOM, "Microsoft.SharePoint.Client.FieldCalculated", "Microsoft.SharePoint.Client")] + + [DefaultParentHost(typeof(SiteDefinition))] + [DefaultRootHost(typeof(SiteDefinition))] + + [Serializable] + [DataContract] + [ExpectArrayExtensionMethod] + + [ExpectManyInstances] + + public class CalculatedFieldDefinition : FieldDefinition + { + #region constructors + + public CalculatedFieldDefinition() + { + FieldType = BuiltInFieldTypes.Calculated; + FieldReferences = new Collection(); + + DateFormat = BuiltInDateTimeFieldFormatType.DateOnly; + CurrencyLocaleId = 1033; + } + + #endregion + + #region properties + + [ExpectValidation] + [ExpectRequired] + [DataMember] + public override sealed string FieldType { get; set; } + + [ExpectValidation] + [DataMember] + public override string ValidationMessage + { + get { return string.Empty; } + set { } + } + + [ExpectValidation] + [DataMember] + public override string ValidationFormula + { + get { return string.Empty; } + set { } + } + + [ExpectValidation] + [DataMember] + public int? CurrencyLocaleId { get; set; } + + [ExpectValidation] + [DataMember] + [ExpectUpdateAsDateFormat] + public string DateFormat { get; set; } + + [ExpectValidation] + [DataMember] + public string DisplayFormat { get; set; } + + [ExpectValidation] + [ExpectUpdateAsCalculatedFieldFormula] + [DataMember] + [ExpectNullable] + public string Formula { get; set; } + + [ExpectValidation] + [ExpectUpdateAssCalculatedFieldOutputType] + [DataMember] + public string OutputType { get; set; } + + [ExpectValidation] + //[ExpectUpdate] + [DataMember] + public bool? ShowAsPercentage { get; set; } + + [ExpectValidation] + //[ExpectUpdateAssCalculatedFieldReferences] + [DataMember] + public Collection FieldReferences { get; set; } + + [ExpectValidation] + [DataMember] + public override string DefaultValue + { + get + { + // #SPBUG + // Calculated field MUST return string.Empty to avoid setting DefaultValue for field. + // SharePoint drive crazy if calculated field has default value. FieldRefs would be NULL, tons of failures would be there. + return string.Empty; + } + set { } + } + + #endregion + + #region methods + + public override string ToString() + { + return new ToStringResult(this, base.ToString()) + .ToString(); + } + + #endregion + } +} From 3ce93df4d713c942e1a3cadf88117bd024f21202 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 23:51:13 +1100 Subject: [PATCH 35/53] Revert "fixed ListItemAllFields error for WebPart Pages not in lists" --- .../ModelHandlers/ModuleFileModelHandler.cs | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs index 5e4afb9a2..7a1c7996a 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs @@ -102,8 +102,8 @@ private void ProcessWebFolder(FolderModelHost folderHost, ModuleFileDefinition m } else { -#if NET35 - throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); +#if NET35 + throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); #endif #if !NET35 @@ -191,8 +191,8 @@ private void ProcessContentTypeFolder(FolderModelHost folderHost, ModuleFileDefi } else { -#if NET35 - throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); +#if NET35 + throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); #endif #if !NET35 @@ -327,13 +327,7 @@ public static void WithSafeFileOperation(List list, File file, if (file != null) { context.Load(file, f => f.Exists); - context.Load(file, f => f.ListItemAllFields); //SergeiSnitko. Need to be loaded to get if object is null context.ExecuteQueryWithTrace(); - //SergeiSnitko. I don't know all logic based on doesFileHasListItem. So I fill doesFileHasListItem by the real value - //of ListItem existing only if doesFileHasListItem is true. This action helps to prevent exceptions on web part provision - //on the page without ListItem not only under Forms folder (for example Forms/ContentTypeName/videoplayerpage.aspx fires exception) - doesFileHasListItem = doesFileHasListItem ? !(bool)file.ListItemAllFields.ServerObjectIsNull : doesFileHasListItem; - if (file.Exists) { @@ -455,9 +449,9 @@ public static void WithSafeFileOperation(List list, File file, if (list != null && spFile != null && (list.EnableModeration)) { -#if NET35 - // TODO, Approve() method is not exposed - throw new SPMeta2NotImplementedException("Not implemented for SP2010 - https://github.com/SubPointSolutions/spmeta2/issues/771"); +#if NET35 + // TODO, Approve() method is not exposed + throw new SPMeta2NotImplementedException("Not implemented for SP2010 - https://github.com/SubPointSolutions/spmeta2/issues/771"); #endif #if !NET35 @@ -564,8 +558,8 @@ private File ProcessFile(FolderModelHost folderHost, ModuleFileDefinition defini #endif -#if NET35 - var doesFileHasListItem = true; +#if NET35 + var doesFileHasListItem = true; #endif WithSafeFileOperation(list, file, f => @@ -586,8 +580,8 @@ private File ProcessFile(FolderModelHost folderHost, ModuleFileDefinition defini } else { -#if NET35 - throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); +#if NET35 + throw new SPMeta2Exception(string.Format("SP2010 CSOM implementation does no support file more than {0}. Checkout FileCreationInformation and avialabe Content size.", ContentStreamFileSize)); #endif #if !NET35 From 6195faea6b1706d48dc0ff2d6da1560ef6423de3 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 07:23:01 -0700 Subject: [PATCH 36/53] + fixed ListItemAllFields error for WebPart Pages not in lists #984 + added CanDeploy_WebpartTo_VideoContentType_VideoPlayerPage + CSOM fix, green tests --- .../ModelHandlers/FolderModelHandler.cs | 25 ++- .../ModelHandlers/ModuleFileModelHandler.cs | 6 - .../ModelHandlers/WebPartModelHandler.cs | 6 + .../ModelHosts/FolderModelHost.cs | 54 +++---- .../ModelHosts/ListItemModelHost.cs | 4 +- .../Impl/Scenarios/WebpartScenariosTest.cs | 145 +++++++++++++----- 6 files changed, 170 insertions(+), 70 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs index 438d11eaf..330241166 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs @@ -43,10 +43,33 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var folderModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var folderModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var isSpecialFolderContext = false; + if (folderModelHost.CurrentList != null && folderModelHost.CurrentList.BaseType == BaseType.DocumentLibrary) { var currentFolder = EnsureLibraryFolder(folderModelHost, folderModel); + // preload props to identify 'special folder' + // once done, pass down via model host + if (folderModel.Name.ToLower() == "forms") + { + currentFolder.Context.Load(currentFolder, f => f.Properties); + currentFolder.Context.ExecuteQueryWithTrace(); + + var doesFileHaveListItem = + //Forms folders + !(currentFolder != null + && + (currentFolder.Properties.FieldValues.ContainsKey("vti_winfileattribs") + && + currentFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == + "00000012")); + + isSpecialFolderContext = !doesFileHaveListItem; + + folderModelHost.IsSpecialFolderContext = isSpecialFolderContext; + } + var newContext = ModelHostBase.Inherit(folderModelHost, c => { c.CurrentList = folderModelHost.CurrentList; @@ -383,7 +406,7 @@ private Folder EnsureLibraryFolder(FolderModelHost folderModelHost, FolderDefini var currentFolderItem = currentFolder.ListItemAllFields; // could be NULL, in the /Forms or other hidden folders - if (currentFolderItem != null + if (currentFolderItem != null && currentFolderItem.ServerObjectIsNull != null && !currentFolderItem.ServerObjectIsNull.Value) { diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs index 5e4afb9a2..359de0415 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ModuleFileModelHandler.cs @@ -327,13 +327,7 @@ public static void WithSafeFileOperation(List list, File file, if (file != null) { context.Load(file, f => f.Exists); - context.Load(file, f => f.ListItemAllFields); //SergeiSnitko. Need to be loaded to get if object is null context.ExecuteQueryWithTrace(); - //SergeiSnitko. I don't know all logic based on doesFileHasListItem. So I fill doesFileHasListItem by the real value - //of ListItem existing only if doesFileHasListItem is true. This action helps to prevent exceptions on web part provision - //on the page without ListItem not only under Forms folder (for example Forms/ContentTypeName/videoplayerpage.aspx fires exception) - doesFileHasListItem = doesFileHasListItem ? !(bool)file.ListItemAllFields.ServerObjectIsNull : doesFileHasListItem; - if (file.Exists) { diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs index ff08745f1..0d6e61791 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/WebPartModelHandler.cs @@ -400,6 +400,12 @@ public override void DeployModel(object modelHost, DefinitionBase model) listItemModelHost.HostFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == "00000012")); + // is parent /forms folder or nay other special page? + if (doesFileHasListItem) + { + doesFileHasListItem = !listItemModelHost.IsSpecialFolderContext; + } + #endif #if NET35 diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs index a87f0944c..f3c966c81 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/FolderModelHost.cs @@ -1,26 +1,28 @@ -using Microsoft.SharePoint.Client; - -namespace SPMeta2.CSOM.ModelHosts -{ - public class FolderModelHost : CSOMModelHostBase - { - #region properties - - public List CurrentList { get; set; } - public ListItem CurrentListItem { get; set; } - - public Folder CurrentListFolder { get; set; } - - public Web CurrentWeb { get; set; } - public Folder CurrentWebFolder { get; set; } - - public ContentType CurrentContentType { get; set; } - public Folder CurrentContentTypeFolder { get; set; } - - //public Folder Folder { get; set; } - //public List List { get; set; } - //public Web Web { get; set; } - - #endregion - } -} +using Microsoft.SharePoint.Client; + +namespace SPMeta2.CSOM.ModelHosts +{ + public class FolderModelHost : CSOMModelHostBase + { + #region properties + + public List CurrentList { get; set; } + public ListItem CurrentListItem { get; set; } + + public Folder CurrentListFolder { get; set; } + + public Web CurrentWeb { get; set; } + public Folder CurrentWebFolder { get; set; } + + public ContentType CurrentContentType { get; set; } + public Folder CurrentContentTypeFolder { get; set; } + + //public Folder Folder { get; set; } + //public List List { get; set; } + //public Web Web { get; set; } + + public bool IsSpecialFolderContext { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs index 8b710e0cb..ffab00c29 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ListItemModelHost.cs @@ -17,6 +17,8 @@ public class ListItemModelHost : CSOMModelHostBase #endregion - public List HostList { get; set; } + public List HostList { get; set; } + + public bool IsSpecialFolderContext { get; set; } } } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs index 1f069bb15..0a1288e2d 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs @@ -148,6 +148,7 @@ public void CanDeploy_Random_V3_Webpart_WithAllChrome() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_UploadForm_InLibrary() { var model = SPMeta2Model @@ -170,6 +171,7 @@ public void CanDeploy_WebpartTo_UploadForm_InLibrary() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_OOTBListViews_InLibrary() { var model = SPMeta2Model @@ -205,6 +207,7 @@ public void CanDeploy_WebpartTo_OOTBListViews_InLibrary() } [TestMethod] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] [TestCategory("Regression.Scenarios.Webparts.ListViews")] public void CanDeploy_WebpartTo_CustomListViews_InLibrary() { @@ -244,6 +247,7 @@ public void CanDeploy_WebpartTo_CustomListViews_InLibrary() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_OOTBListViews_InList() { var model = SPMeta2Model @@ -289,6 +293,7 @@ public void CanDeploy_WebpartTo_OOTBListViews_InList() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListViews")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_CustomListViews_InList() { var model = SPMeta2Model @@ -331,6 +336,7 @@ public void CanDeploy_WebpartTo_CustomListViews_InList() [TestMethod] [TestCategory("Regression.Scenarios.Webparts.ListForms")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_ListForm_InLibrary() { var model = SPMeta2Model @@ -361,6 +367,7 @@ public void CanDeploy_WebpartTo_ListForm_InLibrary() } [TestMethod] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] [TestCategory("Regression.Scenarios.Webparts.ListForms")] public void CanDeploy_WebpartTo_ListForm_InList() { @@ -431,7 +438,8 @@ public void CanDeploy_Webpart_With_AuthorizationFilter() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWebpartPage() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WebpartPage() { var model = SPMeta2Model .NewWebModel(web => @@ -461,7 +469,8 @@ public void CanDeploy_WebpartToWebpartPage() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWebpartPage_WithCustomPageLayout() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WebpartPage_WithCustomPageLayout() { var webPartPage1 = ModelGeneratorService.GetRandomDefinition(def => { @@ -538,40 +547,100 @@ public void CanDeploy_Webpart_WithTitleUrl_WithTokens() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToPublishingPageWebPartZone() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_VideoContentType_VideoPlayerPage() { - var siteModel = SPMeta2Model - .NewSiteModel(site => - { - site - .AddSiteFeature(RegSiteFeatures.Publishing); - }); + // aiming to deploy a web part to the following page with in a library + // forms/videocontenttype/videoplayerpage.aspx + + var listDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.ContentTypesEnabled = true; + def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; + }); + + var contentTypeName = "Video"; + var contentTypeLinkDef = new ContentTypeLinkDefinition + { + ContentTypeName = contentTypeName, + ContentTypeId = BuiltInSiteContentTypeId.Video + }; + + var formsFolder = new FolderDefinition + { + Name = "Forms" + }; + + var contentTypeFolder = new FolderDefinition + { + Name = contentTypeName + }; + + var pageDefinition = new WebPartPageDefinition + { + FileName = "videoplayerpage.aspx", + PageLayoutTemplate = BuiltInWebPartPageTemplates.spstd1, + NeedOverride = false + }; + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddList(listDef, list => + { + list.AddContentTypeLink(contentTypeLinkDef); + + list.AddFolder(formsFolder, forms => + { + forms.AddFolder(contentTypeFolder, folder => + { + folder.AddHostWebPartPage(pageDefinition, page => + { + page.AddRandomWebpart(); + page.AddRandomWebpart(); + page.AddRandomWebpart(); + }); + }); + }); + }); + }); + + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.Webparts")] + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_PublishingPageWebPartZone() + { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(RegSiteFeatures.Publishing); + }); TestModel(siteModel); - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddWebFeature(RegWebFeatures.Publishing) - .AddHostList(BuiltInListDefinitions.Pages, list => - { - list - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }) - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }); - }); + var webModel = SPMeta2Model.NewWebModel(web => + { + web + .AddWebFeature(RegWebFeatures.Publishing) + .AddHostList(BuiltInListDefinitions.Pages, list => + { + list + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }) + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }); + }); - }); + }); TestModel(webModel); } @@ -579,7 +648,8 @@ public void CanDeploy_WebpartToPublishingPageWebPartZone() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToPublishingPageContent() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_PublishingPageContent() { var webModel = SPMeta2Model .NewWebModel(web => @@ -656,7 +726,8 @@ public void CanDeploy_WebpartToPublishingPageContent() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWikiPageContent_AsItIs() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WikiPageContent_AsItIs() { // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 @@ -683,7 +754,7 @@ public void CanDeploy_WebpartToWikiPageContent_AsItIs() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_ScriptEditorToWikiPageContent_As_AddToPageContent() + public void CanDeploy_ScriptEditorTo_WikiPageContent_As_AddToPageContent() { // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 @@ -735,7 +806,8 @@ public void CanDeploy_ScriptEditorToWikiPageContent_As_AddToPageContent() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWikiPageContent_As_AddToPageContent() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WikiPageContent_As_AddToPageContent() { // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 @@ -800,7 +872,8 @@ public void CanDeploy_WebpartToWikiPageContent_As_AddToPageContent() [TestMethod] [TestCategory("Regression.Scenarios.Webparts")] - public void CanDeploy_WebpartToWikiPageContent() + [TestCategory("Regression.Scenarios.Webparts.Hosts")] + public void CanDeploy_WebpartTo_WikiPageContent() { var webModel = SPMeta2Model .NewWebModel(web => From 1ffb9de55c5785d2c2cc10728844ec26ad9964ea Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 29 Mar 2017 07:54:28 -0700 Subject: [PATCH 37/53] + NET35 fix --- .../ModelHandlers/FolderModelHandler.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs index 330241166..23e4949cf 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FolderModelHandler.cs @@ -53,18 +53,21 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon // once done, pass down via model host if (folderModel.Name.ToLower() == "forms") { + var doesFileHaveListItem = false; + +#if !NET35 currentFolder.Context.Load(currentFolder, f => f.Properties); currentFolder.Context.ExecuteQueryWithTrace(); - var doesFileHaveListItem = - //Forms folders - !(currentFolder != null - && - (currentFolder.Properties.FieldValues.ContainsKey("vti_winfileattribs") + doesFileHaveListItem = !(currentFolder != null && - currentFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == - "00000012")); + (currentFolder.Properties.FieldValues.ContainsKey("vti_winfileattribs") + && + currentFolder.Properties.FieldValues["vti_winfileattribs"].ToString() == + "00000012")); + +#endif isSpecialFolderContext = !doesFileHaveListItem; folderModelHost.IsSpecialFolderContext = isSpecialFolderContext; From 2e2fef47f2ec91f7d15deb1bc593f2efb5e85a18 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 1 Apr 2017 00:10:15 -0700 Subject: [PATCH 38/53] Regression testing fixes (o365) for the following issues: + Nested terms provisioning in Office 365 fails #995 + TermSet not found #994 --- SPMeta2.sln | 3 +- SPMeta2/Build/build.json | 115 +++++++++++++----- SPMeta2/Build/tools/packages.config.md5sum | 2 +- .../O365v16ProvisionRunner.cs | 1 - .../SPMeta2.Containers.O365v16.csproj | 20 +-- .../Base/SPMeta2RegresionTestBase.cs | 22 +++- .../SPMeta2.Containers.O365.dll.config | 65 ---------- .../SPMeta2.Regression.Tests.csproj | 18 +-- 8 files changed, 111 insertions(+), 135 deletions(-) delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config diff --git a/SPMeta2.sln b/SPMeta2.sln index 24c200434..f26be87a4 100644 --- a/SPMeta2.sln +++ b/SPMeta2.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Provision", "Provision", "{8A0307D3-5564-4034-9DB1-D13FEE1DADD9}" EndProject @@ -236,7 +236,6 @@ Global {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.Build.0 = Debug45|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug|Any CPU.Build.0 = Debug|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index c21e9ae41..e51b4a1ca 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -2,12 +2,12 @@ "defaultSolutionDirectory": "./../../", "defaultSolutionFilePath": "./../../SPMeta2.sln", - "defaultDocsBuildEnabled" : true, + "defaultDocsBuildEnabled": true, - "defaultDocsViewFolder" : "SPMeta2/SubPointSolutions.Docs/Views/SPMeta2", - "defaultDocsRepoFolder" : "m2-m2", - "defaultDocsBranch" : "wyam-dev", - "defaultDocsFileExtensions" : [ + "defaultDocsViewFolder": "SPMeta2/SubPointSolutions.Docs/Views/SPMeta2", + "defaultDocsRepoFolder": "m2-m2", + "defaultDocsBranch": "wyam-dev", + "defaultDocsFileExtensions": [ "*.md", "*.cs", "*.cshtml" @@ -15,11 +15,11 @@ "customProjectBuildProfiles": [ { - "ProfileName" : "SPMeta2: SP2010 + NET35", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2010 + NET35", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -41,11 +41,11 @@ }, { - "ProfileName" : "SPMeta2: SP2013 + NET40", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2013 + NET40", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -67,11 +67,11 @@ }, { - "ProfileName" : "SPMeta2: SP2013 + NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2013 + NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -93,11 +93,11 @@ }, { - "ProfileName" : "SPMeta2: SP2016 + NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2016 + NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -120,8 +120,8 @@ { - "ProfileName" : "SPMeta2: SharePoint Online (O365) + NET40", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SharePoint Online (O365) + NET40", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", @@ -142,9 +142,9 @@ ] }, - { - "ProfileName" : "SPMeta2: SharePoint Online (O365) + NET45", - "ProjectFiles" : [ + { + "ProfileName": "SPMeta2: SharePoint Online (O365) + NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", @@ -166,11 +166,11 @@ }, { - "ProfileName" : "SPMeta2: Regression test containers NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: Regression test containers NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2.Containers.CSOM/SPMeta2.Containers.CSOM.csproj", "SPMeta2/SPMeta2.Containers.SSOM/SPMeta2.Containers.SSOM.csproj", - "SPMeta2/SPMeta2.Containers.O365/SPMeta2.Containers.O365.csproj", + "SPMeta2/SPMeta2.Containers.O365/SPMeta2.Containers.O365.csproj", "SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj" ], "BuildParameters": [ @@ -186,9 +186,67 @@ ] }, + { + "ProfileName": "SPMeta2: Regression CSOM", + "ProjectFiles": [ + "SPMeta2/SPMeta2.Regression.CSOM/SPMeta2.Regression.CSOM.csproj", + "SPMeta2/SPMeta2.Regression.CSOM.Standard/SPMeta2.Regression.CSOM.Standard.csproj" + ], + "BuildParameters": [ + "/p:Configuration=Debug", + "/p:DefineConstants=NET45", + + "/t:Build", + "/p:Platform=AnyCPU", + "/p:WarningLevel=0", + "/verbosity:quiet", + "/clp:ErrorsOnly", + "/nologo" + ] + }, + + { + "ProfileName": "SPMeta2: Regression CSOM NET45", + "ProjectFiles": [ + "SPMeta2/SPMeta2.Regression.CSOM/SPMeta2.Regression.CSOM.csproj", + "SPMeta2/SPMeta2.Regression.CSOM.Standard/SPMeta2.Regression.CSOM.Standard.csproj" + ], + "BuildParameters": [ + "/p:Configuration=Debug", + "/p:DefineConstants=NET45", + + "/t:Build", + "/p:Platform=AnyCPU", + "/p:WarningLevel=0", + "/verbosity:quiet", + "/clp:ErrorsOnly", + "/nologo" + ] + }, + { - "ProfileName" : "SPMeta2: Regression tests NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: Regression CSOM NET45 - v365", + "ProjectFiles": [ + "SPMeta2/SPMeta2.Regression.CSOM/SPMeta2.Regression.CSOM.csproj", + "SPMeta2/SPMeta2.Regression.CSOM.Standard/SPMeta2.Regression.CSOM.Standard.csproj" + ], + "BuildParameters": [ + "/p:spRuntime=365", + "/p:Configuration=Debug45", + "/p:DefineConstants=NET45", + + "/t:Build", + "/p:Platform=AnyCPU", + "/p:WarningLevel=0", + "/verbosity:quiet", + "/clp:ErrorsOnly", + "/nologo" + ] + }, + + { + "ProfileName": "SPMeta2: Regression tests NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj", "SPMeta2/SPMeta2.Regression.Impl.Tests/SPMeta2.Regression.Impl.Tests.csproj", ], @@ -204,8 +262,7 @@ "/nologo" ] } - ] - , + ], "defaultNuGetPackagesDirectory": "./build-artifact-nuget-packages", "defaultChocolateyPackagesDirectory": "./build-artifact-cli-packages", diff --git a/SPMeta2/Build/tools/packages.config.md5sum b/SPMeta2/Build/tools/packages.config.md5sum index 8b81cf99a..95db67f7c 100644 --- a/SPMeta2/Build/tools/packages.config.md5sum +++ b/SPMeta2/Build/tools/packages.config.md5sum @@ -1 +1 @@ -93-A8-F9-3B-FF-40-99-D5-E4-C1-E0-AF-32-14-3A-BB +38-0C-2E-66-B0-3C-49-7B-AD-15-87-FD-A7-2D-0C-44 diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index a9cdee267..0c55f241a 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -261,7 +261,6 @@ private void WithO365Context(string siteUrl, string userName, string userPasswor } } - #endregion } } diff --git a/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj b/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj index 09de2dc46..d68ed3707 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj +++ b/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj @@ -119,28 +119,12 @@ False ..\SPMeta2.Dependencies\SharePoint\O365 - 16.1.5715.1200\NET45\Microsoft.SharePoint.Client.WorkflowServices.dll - - False + ..\SPMeta2.CSOM\bin\Debug45-365\SPMeta2.CSOM.dll - - False + ..\SPMeta2.CSOM.Standard\bin\Debug45-365\SPMeta2.CSOM.Standard.dll - - - True - ..\SPMeta2.CSOM\bin\Debug\SPMeta2.CSOM.dll - False - - - - True - ..\SPMeta2.CSOM\bin\Debug\SPMeta2.CSOM.Standard.dll - False - - - diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs index 057fdfcaf..a8350c568 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs @@ -42,10 +42,15 @@ static SPMeta2RegresionTestCoreBase() AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } + private static string GetFullPath(string path) + { + return Path.GetFullPath(path); + } + static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { var m2runner = Environment.GetEnvironmentVariable("SPMeta2_RunnerLibraries", EnvironmentVariableTarget.Machine); - var baseDir = AppDomain.CurrentDomain.BaseDirectory; + var baseDir = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory); RegressionUtils.WriteLine(string.Format("Resolving custom assembly binding for m2 runner:[{0}]", m2runner)); @@ -81,11 +86,24 @@ static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs ar { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-365")); assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-365")); + + assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-365")); + assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-365")); + + // VS sometimes does not coipy these accorss + // referencing straight to the solution + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM.Standard\bin\Debug45-365\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM\bin\Debug45-365\"))); + + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM\bin\Debug45-365\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM.Standard\bin\Debug45-365\"))); } if (m2runner == "SPMeta2.Containers.O365.dll") + { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-2013")); - assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + } if (m2runner == "SPMeta2.Containers.CSOM.dll") { diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config deleted file mode 100644 index 0a80f5c35..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config +++ /dev/null @@ -1,65 +0,0 @@ - - - - \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index 423dd6f01..16d36594f 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -355,9 +355,8 @@ SPMeta2.Containers.CSOM.dll - Always - + SPMeta2.Containers.O365v16.dll Always @@ -541,18 +540,6 @@ _Dependencies\spmeta2-csom-regression-2013\SPMeta2.Regression.CSOM.dll Always - - SPMeta2.Regression.SSOM.Standard.dll - Always - - - SPMeta2.Regression.SSOM.dll - Always - - - SPMeta2.SSOM.Standard.dll - Always - SPMeta2.SSOM.dll Always @@ -589,9 +576,6 @@ - - Always - Always From cb25f4441eb07c91a6f408d3f8104ef644feb31f Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 09:56:17 -0700 Subject: [PATCH 39/53] + O365 API regression - Nested terms provision fails #995 + O365 API regression - TermSet not found #994 + O365 API regression - Taxonomy Group provision fails #959 + Simplify SPMeta2 regression testing setup #800 --- SPMeta2.sln | 76 +++ SPMeta2/Regression/Properties/AssemblyInfo.cs | 36 ++ SPMeta2/Regression/Regression.csproj | 60 ++ SPMeta2/Regression/_helpers.ps1 | 147 +++++ SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 | 6 + SPMeta2/Regression/_ut_grid_dsc_modules.ps1 | 44 ++ .../_ut_grid_dsc_spmeta2_webapp.ps1 | 117 ++++ .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 290 ++++++++++ SPMeta2/Regression/config.yaml | 65 +++ .../Taxonomy/TaxonomyGroupModelHandler.cs | 485 +++++++++------- .../Taxonomy/TaxonomyTermLabelModelHandler.cs | 250 ++++---- .../Taxonomy/TaxonomyTermModelHandler.cs | 125 +++- .../Taxonomy/TaxonomyTermSetModelHandler.cs | 495 +++++++++------- .../Taxonomy/TaxonomyTermStoreModelHandler.cs | 350 ++++++------ .../DefaultClientRuntimeContextService.cs | 8 + .../O365v16ProvisionRunner.cs | 8 + .../Services/RegressionTestService.cs | 4 + .../ClientTaxonomyGroupDefinitionValidator.cs | 130 ++--- .../ClientTaxonomyTermDefinitionValidator.cs | 364 ++++++------ ...entTaxonomyTermLabelDefinitionValidator.cs | 11 +- ...lientTaxonomyTermSetDefinitionValidator.cs | 8 +- .../SSOM/SSOMListViewLookupServiceTests.cs | 4 + .../Base/SPMeta2RegresionTestBase.cs | 22 +- .../Base/SPMeta2RegresionTestVeryBase.cs | 34 ++ .../Impl/Random/RandomDefinitionTest.cs | 2 +- .../Base/SPMeta2RegresionScenarioTestBase.cs | 2 +- .../Scenarios/FarmSolutionScenariosTest.cs | 2 +- .../Impl/Scenarios/TaxonomyScenariousTest.cs | 4 +- .../100 - Ensure M2 Web Application.ps1 | 13 - .../1000 - Internal.CheckContentTypeSetup.ps1 | 129 ----- .../200 - Configure M2 Test Environment.ps1 | 17 - .../PSScripts/300 - Configure M2 Grid.ps1 | 97 ---- .../PSScripts/_config.ps1 | 120 ---- .../PSScripts/_sys.common.ps1 | 535 ------------------ .../SPMeta2.Regression.Tests.csproj | 19 +- .../SPMeta2.Regression.Tests.dll.config | 6 +- .../SPMeta2/ModelHandlers/ModelHandlerBase.cs | 239 ++++---- SPMeta2/SPMeta2/SPMeta2.csproj | 2 + SPMeta2/SPMeta2/ServiceContainer.cs | 2 + .../Services/Impl/DefaultTryRetryService.cs | 75 +++ .../Services/Impl/TraceSourceService.cs | 10 +- .../SPMeta2/Services/TryRetryServiceBase.cs | 24 + 42 files changed, 2459 insertions(+), 1978 deletions(-) create mode 100644 SPMeta2/Regression/Properties/AssemblyInfo.cs create mode 100644 SPMeta2/Regression/Regression.csproj create mode 100644 SPMeta2/Regression/_helpers.ps1 create mode 100644 SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 create mode 100644 SPMeta2/Regression/_ut_grid_dsc_modules.ps1 create mode 100644 SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 create mode 100644 SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 create mode 100644 SPMeta2/Regression/config.yaml create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 create mode 100644 SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs create mode 100644 SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs diff --git a/SPMeta2.sln b/SPMeta2.sln index f26be87a4..cec2eae20 100644 --- a/SPMeta2.sln +++ b/SPMeta2.sln @@ -121,11 +121,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPMeta2.Nintex.CSOM", "SPMe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPMeta2.Nintex.SSOM", "SPMeta2\SPMeta2.Nintex.SSOM\SPMeta2.Nintex.SSOM.csproj", "{788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Regression", "SPMeta2\Regression\Regression.csproj", "{593FFE45-EFCC-43DC-8AA2-27236DD6160D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug40|Any CPU = Debug40|Any CPU Debug45|Any CPU = Debug45|Any CPU + Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -133,124 +136,166 @@ Global {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Release|Any CPU.Build.0 = Release|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Release|Any CPU.Build.0 = Debug35|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Release|Any CPU.Build.0 = Debug35|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Release|Any CPU.Build.0 = Debug35|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Release|Any CPU.Build.0 = Release|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Release|Any CPU.Build.0 = Debug35|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug|Any CPU.Build.0 = Debug|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Release|Any CPU.Build.0 = Release|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug40|Any CPU.ActiveCfg = Debug45|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug40|Any CPU.Build.0 = Debug45|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Release|Any CPU.ActiveCfg = Debug45|Any CPU + {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Release|Any CPU.Build.0 = Debug45|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug|Any CPU.Build.0 = Debug|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {00E1581F-31D9-493E-AD16-C188AE966458}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00E1581F-31D9-493E-AD16-C188AE966458}.Release|Any CPU.Build.0 = Release|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Release|Any CPU.Build.0 = Debug35|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug|Any CPU.Build.0 = Debug|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Release|Any CPU.Build.0 = Release|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {33B40E92-C649-41FC-B774-53D259801B3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33B40E92-C649-41FC-B774-53D259801B3B}.Release|Any CPU.Build.0 = Release|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug|Any CPU.Build.0 = Debug|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Release|Any CPU.Build.0 = Release|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug|Any CPU.Build.0 = Debug|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {5793019F-7514-4B1F-B31D-A5E472FD034D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5793019F-7514-4B1F-B31D-A5E472FD034D}.Release|Any CPU.Build.0 = Release|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug|Any CPU.Build.0 = Debug|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Release|Any CPU.Build.0 = Release|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Release|Any CPU.Build.0 = Release|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {8B199151-24BC-4C32-B69F-7371B37F33D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B199151-24BC-4C32-B69F-7371B37F33D4}.Release|Any CPU.Build.0 = Release|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug|Any CPU.Build.0 = Debug|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Release|Any CPU.Build.0 = Release|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {E9274D1F-BF08-44CB-9162-35110379D5C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9274D1F-BF08-44CB-9162-35110379D5C0}.Release|Any CPU.Build.0 = Release|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug40|Any CPU.Build.0 = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {7B84193A-251E-47F1-BDD0-EDD85918D307}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B84193A-251E-47F1-BDD0-EDD85918D307}.Release|Any CPU.Build.0 = Release|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug|Any CPU.Build.0 = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug40|Any CPU.Build.0 = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Release|Any CPU.Build.0 = Release|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug40|Any CPU.Build.0 = Debug|Any CPU @@ -258,6 +303,9 @@ Global {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug45|Any CPU.Build.0 = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug45|Any CPU.Deploy.0 = Debug|Any CPU + {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Release|Any CPU.Build.0 = Release|Any CPU + {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Release|Any CPU.Deploy.0 = Release|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug40|Any CPU.Build.0 = Debug|Any CPU @@ -265,11 +313,16 @@ Global {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug45|Any CPU.Build.0 = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug45|Any CPU.Deploy.0 = Debug|Any CPU + {16A7F927-A570-4EB0-90E6-887E676AF42B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16A7F927-A570-4EB0-90E6-887E676AF42B}.Release|Any CPU.Build.0 = Release|Any CPU + {16A7F927-A570-4EB0-90E6-887E676AF42B}.Release|Any CPU.Deploy.0 = Release|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug40|Any CPU.Build.0 = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Release|Any CPU.Build.0 = Release|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug40|Any CPU.Build.0 = Debug|Any CPU @@ -277,40 +330,62 @@ Global {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug45|Any CPU.Build.0 = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug45|Any CPU.Deploy.0 = Debug|Any CPU + {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Release|Any CPU.Build.0 = Release|Any CPU + {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Release|Any CPU.Deploy.0 = Release|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug40|Any CPU.Build.0 = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Release|Any CPU.Build.0 = Release|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug40|Any CPU.Build.0 = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Release|Any CPU.Build.0 = Release|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug40|Any CPU.Build.0 = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Release|Any CPU.Build.0 = Release|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug|Any CPU.Build.0 = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug40|Any CPU.Build.0 = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {D19B0907-CED5-416A-9D45-0F112990C234}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D19B0907-CED5-416A-9D45-0F112990C234}.Release|Any CPU.Build.0 = Release|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug|Any CPU.Build.0 = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug40|Any CPU.Build.0 = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {588FC30F-1C85-410E-AB20-C9741DB28857}.Release|Any CPU.ActiveCfg = Release|Any CPU + {588FC30F-1C85-410E-AB20-C9741DB28857}.Release|Any CPU.Build.0 = Release|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug|Any CPU.Build.0 = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug40|Any CPU.Build.0 = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Release|Any CPU.Build.0 = Release|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug40|Any CPU.Build.0 = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -356,5 +431,6 @@ Global {D19B0907-CED5-416A-9D45-0F112990C234} = {543E02CC-AA4A-4B1F-ABBD-2C88CFAA463C} {588FC30F-1C85-410E-AB20-C9741DB28857} = {543E02CC-AA4A-4B1F-ABBD-2C88CFAA463C} {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3} = {543E02CC-AA4A-4B1F-ABBD-2C88CFAA463C} + {593FFE45-EFCC-43DC-8AA2-27236DD6160D} = {EE9BD842-2CA9-45B2-AB7C-A8EB0353AAB7} EndGlobalSection EndGlobal diff --git a/SPMeta2/Regression/Properties/AssemblyInfo.cs b/SPMeta2/Regression/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5e9584207 --- /dev/null +++ b/SPMeta2/Regression/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Regression")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Regression")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e91860b2-bf5a-4986-8624-4ee1057c7e43")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SPMeta2/Regression/Regression.csproj b/SPMeta2/Regression/Regression.csproj new file mode 100644 index 000000000..4fc9d415d --- /dev/null +++ b/SPMeta2/Regression/Regression.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D} + Library + Properties + Regression + Regression + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SPMeta2/Regression/_helpers.ps1 b/SPMeta2/Regression/_helpers.ps1 new file mode 100644 index 000000000..5cbcb1cc9 --- /dev/null +++ b/SPMeta2/Regression/_helpers.ps1 @@ -0,0 +1,147 @@ + + +function Get-RegressionConfig() { + + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $yamlFilePath + ) + + $yaml = (Get-Content $yamlFilePath -raw) + $config = ConvertFrom-Yaml $yaml + + return $config +} + +if($dsc_configFilePath -eq $null) { + $dsc_configFilePath = "config.yaml" +} + +$dsc_config = Get-RegressionConfig($dsc_configFilePath) +$env_config = $dsc_config.Configuration.Environment +$regression_config = $dsc_config.Configuration.RegressionTests + +$dsc_nodeNames = $dsc_config.Configuration.DSC.NodeNames + +$dsc_RunAsUserName = $dsc_config.Configuration.DSC.RunAs.UserName +$dsc_RunAsUserPassword = $dsc_config.Configuration.DSC.RunAs.UserPassword + +# from env variable? + + +$dsc_RunAsUserSecurePassword = ConvertTo-SecureString $dsc_RunAsUserPassword -AsPlainText -Force +$dsc_RunAsUserCredentials = New-Object System.Management.Automation.PSCredential ($dsc_RunAsUserName, $dsc_RunAsUserSecurePassword) + +$dsc_WebPoolManagedAccountUserName = $dsc_config.Configuration.DSC.WebPoolManagedAccount.UserName +$dsc_WebPoolManagedAccountUserPassword = $dsc_config.Configuration.DSC.WebPoolManagedAccount.UserPassword +$dsc_WebPoolManagedAccountSecurePassword = ConvertTo-SecureString $dsc_WebPoolManagedAccountUserPassword -AsPlainText -Force +$dsc_WebPoolManagedCredentials = New-Object System.Management.Automation.PSCredential ($dsc_WebPoolManagedAccountUserName, $dsc_WebPoolManagedAccountSecurePassword) + +$dsc_SPSetupAccountAccountUserName = $dsc_config.Configuration.DSC.SPSetupAccount.UserName +$dsc_SPSetupAccountAccountUserPassword = $dsc_config.Configuration.DSC.SPSetupAccount.UserPassword +$dsc_SPSetupAccountSecurePassword = ConvertTo-SecureString $dsc_SPSetupAccountAccountUserPassword -AsPlainText -Force +$dsc_SPSetupAccountCredentials = New-Object System.Management.Automation.PSCredential ($dsc_SPSetupAccountAccountUserName, $dsc_SPSetupAccountSecurePassword) + +function Ensure-PowerShellModule { + + foreach($nodeName in $dsc_nodeNames) { + + $moduleName = "PowerShellModule" + $moduleVersion = 0.3 + + Write-Host "Ensuring module [$moduleName] on node:[$nodeName]" -fore green + + Invoke-Command -ScriptBlock { + + function InstallModule($name, $version) { + + $module = Get-Module -ListAvailable | where-object { $_.Name -eq "PowerShellModule" } + + if($module -ne $null -and $module.Version -eq $version) { + + Write-Host "`tModule exists [$name] [$version]" -fore gray + } else { + + Write-Host "`tInstalling module [$name] [$version]" -fore gray + + Find-Module -Name $name -RequiredVersion $version -Repository PSGallery | Install-Module + Get-DscResource -Module $name + } + } + + InstallModule PowerShellModule 0.3 + + } -ComputerName $nodeName + } + +} + +function Apply-Dsc-Configuration { + + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $name, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string[]] $nodeNames, + [Parameter(Mandatory=$false)][object] $config, + [Parameter(Mandatory=$false)][boolean] $isVerbose = $true + ) + + if($config -eq $null) { + $config = @{ + AllNodes = @() + } + } + + + $config.AllNodes[0].RecurseValue = $true + + $config.AllNodes[0].PsDscAllowPlainTextPassword = $true + $config.AllNodes[0].PSDscAllowDomainUser = $true + + Write-Host "Cleaning up DSC config [$name]..." -fore green + Remove-Item $name -Force -Recurse -Confirm:$false -ErrorAction:SilentlyContinue | out-null + + Write-Host "Compiling DSC config [$name] for [$($nodeNames.Count)] nodes..." -fore green + + foreach($nodeName in $nodeNames) { + + Write-Host "`tCompiling DSC config [$name] for node [$nodeName]" -fore Gray + + $config.AllNodes[0].NodeName = $nodeName + + . $name -NodeName $nodeName ` + -RunAsCredential $dsc_RunAsUserCredentials ` + -ConfigurationData $config | out-null + } + + Write-Host "Starting DSC config [$name]..." -fore Green + + if($isVerbose -eq $true) + { + Start-DscConfiguration $name -force ` + -Wait ` + -Verbose + } + else + { + Start-DscConfiguration $name -force ` + -Wait + } + + Write-Host "Testing DSC config [$name]..." -fore Green + $results = Test-DscConfiguration $name + + foreach($result in $results) { + + $node = $result.PSComputerName + $state = $result.InDesiredState + + $color = "Gray" + + if($result.InDesiredState) { + $color = "Gray" + } else { + $color = "Red" + } + + Write-Host "`tNode[$node]`tInDesiredState:[$state]" -fore $color + } +} \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 b/SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 new file mode 100644 index 000000000..f15fcea82 --- /dev/null +++ b/SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 @@ -0,0 +1,6 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +Ensure-PowerShellModule \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_modules.ps1 b/SPMeta2/Regression/_ut_grid_dsc_modules.ps1 new file mode 100644 index 000000000..4dcd817bb --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_dsc_modules.ps1 @@ -0,0 +1,44 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +configuration SPMeta2_DSCModules { + + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + Import-DscResource -ModuleName PowerShellModule -ModuleVersion 0.3 + + Node $NodeName { + + PSModuleResource SharePointDSC { + + Module_Name = "SharePointDSC" + RequiredVersion = "1.6.0.0" + PsDscRunAsCredential = $RunAsCredential + } + + PSModuleResource PowershellYaml { + + Module_Name = "powershell-yaml" + RequiredVersion = "0.1" + PsDscRunAsCredential = $RunAsCredential + DependsOn = "[PSModuleResource]SharePointDSC" + } + + PSModuleResource PSParallel { + + Module_Name = "PSParallel" + RequiredVersion = "2.2.2" + PsDscRunAsCredential = $RunAsCredential + DependsOn = "[PSModuleResource]PowershellYaml" + } + } +} + +Apply-Dsc-Configuration -name SPMeta2_DSCModules ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 new file mode 100644 index 000000000..6a2aaf6f5 --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 @@ -0,0 +1,117 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +Configuration SPMeta2_WebApp +{ + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + Import-DscResource -ModuleName PSDesiredStateConfiguration + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 1.6.0.0 + + $config = $ConfigurationData.AllNodes + + $webApp_Port = $config.WebAppPort + $webApp_isHttps = $config.IsHttps + + $machineName = $NodeName + + if($webApp_isHttps -eq $true) { + $webApp_Url = "https://" + $machineName + } else { + $webApp_Url = "http://" + $machineName + } + + $ensure = 'Present' + + $clean = $config.DeleteWebApplication + + if($clean -eq $true) { + $ensure = 'Absent' + } + + Node $NodeName { + + SPManagedAccount WebAppPoolManagedAccount + { + AccountName = $config.WebPoolManagedAccount.UserName + Account = $config.WebPoolManagedAccount + PsDscRunAsCredential = $config.SPSetupAccount + Ensure = 'Present' + } + + + SPWebApplication WebApp + { + Name = "SPMeta2 Regression Web App - $webApp_Port" + ApplicationPool = "SPMeta2 Regression Web App" + ApplicationPoolAccount = $config.WebPoolManagedAccount.UserName + AllowAnonymous = $false + AuthenticationMethod = "NTLM" + DatabaseName = "SPMeta2_Regression_Content" + Url = $webApp_Url + #HostHeader = "spmeta2.contoso.com" + Port = $webApp_Port + PsDscRunAsCredential = $config.SPSetupAccount + DependsOn = "[SPManagedAccount]WebAppPoolManagedAccount" + Ensure = $ensure + } + + if($ensure -eq 'Present') { + + SPSite RootSite + { + Url = $webApp_Url + ":" + $webApp_Port + OwnerAlias = $config.SPSetupAccount.UserName + Name = "SPMeta2 Regression Root Site" + Template = "STS#0" + PsDscRunAsCredential = $config.SPSetupAccount + DependsOn = "[SPWebApplication]WebApp" + } + + # other site collections + + foreach($url in $config.SiteCollectionUrls) { + + if($url -eq "/") { + continue; + } + + SPSite "SubSite$url" + { + Url = $webApp_Url + ":" + $webApp_Port + $url + OwnerAlias = $config.SPSetupAccount.UserName + Name = "SPMeta2 Regression $url" + Template = "STS#0" + PsDscRunAsCredential = $config.SPSetupAccount + DependsOn = "[SPWebApplication]WebApp" + } + } + } + } +} + +$config = @{ + AllNodes = @( + @{ + WebPoolManagedAccount = $dsc_WebPoolManagedCredentials + SPSetupAccount = $dsc_SPSetupAccountCredentials + + #DeleteWebApplication = $true + + WebAppPort = $env_config.SharePoint.WebApp.Port + + SiteCollectionUrls = $env_config.SharePoint.SiteCollection.Urls + WebUrls = $env_config.SharePoint.Web.Urls + } + ) + } + +Apply-Dsc-Configuration -name SPMeta2_WebApp ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true ` + -config $config diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 new file mode 100644 index 000000000..1515fe21a --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -0,0 +1,290 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" + Write-Host "Loading SharePoint CSOM API" -fore Green + + $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") + + foreach($filePath in $files) { + Write-Host "`tLoading assembly: [$filePath]" + $a = [System.Reflection.Assembly]::LoadFile($filePath) + } + +Configuration SPMeta2_UnitTestSettings_Clean +{ + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + $vars = @( + "SPMeta2_CSOM_SiteUrls" + "SPMeta2_CSOM_WebUrls" + + "SPMeta2_SSOM_WebApplicationUrls" + "SPMeta2_SSOM_SiteUrls" + "SPMeta2_SSOM_WebUrls" + + "SPMeta2_O365_SiteUrls" + "SPMeta2_O365_WebUrls" + "SPMeta2_O365_UserName" + "SPMeta2_O365_Password" + + "SPMeta2_DefaultSqlServerName" + + "SPMeta2_DefaultTaxonomyStoreId" + "SPMeta2_DefaultTaxonomyStoreName" + + "SPMeta2_DefaultTestUserLogins", + "SPMeta2_DefaultTestDomainUserEmails" + + "SPMeta2_DefaultTestADGroups" + + "SPMeta2_RunnerProvisionMode" + ); + + Node $NodeName { + + foreach($var in $vars) { + + $env_resource_name = $var.Replace(".", "_") + + Environment ($env_resource_name + "_Remove") { + Name = $env_resource_name + Ensure = 'Absent' + } + } + + } +} + + +Configuration SPMeta2_UnitTestSettings +{ + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 1.6.0.0 + + $config = $ConfigurationData.AllNodes + $objectModels = $config.ObjectModels + + # SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.O365v16.dll" + + $r_runnerLibraries = @(); + + $onprem = $false + $online = $false + + foreach($objectModel in $objectModels) + { + if("SSOM" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.SSOM.dll"; + $onprem = $true + } + + if("CSOM" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.CSOM.dll"; + $onprem = $true + } + + if("O365" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.O365.dll"; + $online = $true + } + + if("O365v16" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.O365v16.dll"; + $online = $true + } + } + + + + $env_vars = @() + + $env_vars += @{ + Name = "SPMeta2_RunnerLibraries" + Value = [string]::Join(',', $r_runnerLibraries) + } + + $webApp_Url = "http://$NodeName" + ':' + $config.WebAppPort + + # onprem + + $taxonomyStoreName = ""; + $taxonomyStoreId = ""; + + if($onprem -eq $true) { + + $siteUrl = $webApp_Url.TrimEnd('/') + $config.SiteCollectionUrls + Write-Host "Fetching default taxoomy store for SharePoint:[$siteUrl]" -fore Green + + $o365_UserName = $config.OnlineUserName + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreId" + Value = $taxonomyStoreId + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreName" + Value = $taxonomyStoreName + } + } + + if($online -eq $true) { + + $siteUrl = $config.OnlineSiteCollectionUrls; + + Write-Host "Fetching default taxoomy store for O365: [$siteUrl]" -fore Green + + $o365_UserName = $config.OnlineUserName + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) + + $context.Credentials = $credentials + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreId" + Value = $taxonomyStoreId + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreName" + Value = $taxonomyStoreName + } + } + + $env_vars += @{ + Name = "SPMeta2_SSOM_WebApplicationUrls" + Value = $webApp_Url + } + + $env_vars += @{ + Name = "SPMeta2_SSOM_SiteUrls" + Value = [string]::Join(",", ($config.SiteCollectionUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + $env_vars += @{ + Name = "SPMeta2_SSOM_WebUrls" + Value = [string]::Join(",", ($config.WebUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + $env_vars += @{ + Name = "SPMeta2_CSOM_SiteUrls" + Value = [string]::Join(",", ($config.SiteCollectionUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + $env_vars += @{ + Name = "SPMeta2_CSOM_WebUrls" + Value = [string]::Join(",", ($config.WebUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + # online + $env_vars += @{ + Name = "SPMeta2_O365_SiteUrls" + Value = [string]::Join(",", ($config.OnlineSiteCollectionUrls | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_O365_WebUrls" + Value = [string]::Join(",", ($config.OnlineWebUrls | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_O365_UserName" + Value = ($config.OnlineUserName) + } + + + $env_vars += @{ + Name = "SPMeta2_O365_Password" + Value = ($config.OnlineUserPassword) + } + + Node $NodeName { + + foreach($var in $env_vars) { + + $env_resource_name = $var.Name.Replace(".", "_") + + Environment ($env_resource_name) { + Name = $var.Name + Ensure = 'Present' + Value = $var.Value + } + } + } +} + +$config = @{ + AllNodes = @( + @{ + ObjectModels = $regression_config.ObjectModels + + WebAppPort = $env_config.SharePoint.WebApp.Port + + SiteCollectionUrls = $env_config.SharePoint.SiteCollection.Urls + WebUrls = $env_config.SharePoint.Web.Urls + + OnlineSiteCollectionUrls = $env_config.SharePointOnline.SiteCollection.Urls + OnlineWebUrls = $env_config.SharePointOnline.Web.Urls + OnlineUserName = $env_config.SharePointOnline.UserName + OnlineUserPassword = $env_config.SharePointOnline.UserPassword + } + ) + } + +#$dsc_nodeNames = @("dev13") + + +<# +Apply-Dsc-Configuration -name SPMeta2_UnitTestSettings_Clean ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true ` + -config $config +#> + +Apply-Dsc-Configuration -name SPMeta2_UnitTestSettings ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true ` + -config $config diff --git a/SPMeta2/Regression/config.yaml b/SPMeta2/Regression/config.yaml new file mode 100644 index 000000000..261b32709 --- /dev/null +++ b/SPMeta2/Regression/config.yaml @@ -0,0 +1,65 @@ +Configuration: + # describes DSC related settings + DSC: + # account used for DSC RunAs operations + RunAs: + UserName: "dev\\administrator" + UserPassword: "" + # account used SharePoint web app creation process + WebPoolManagedAccount: + UserName: "dev\\administrator" + UserPassword: "" + # account used SharePoint web app, site collection and web creation process + SPSetupAccount: + UserName: "dev\\administrator" + UserPassword: "" + # VM names to run DSC against + NodeNames: + - dev13 + - cloud20 + - cloud21 + - cloud22 + - cloud23 + - cloud24 + - cloud25 + - cloud26 + - cloud27 + + # describes regression environment settings + # SharePoint / SharePoint online web app, site collections and so on + Environment: + SharePoint: + WebApp: + Port: 31442 + IsHttps: false + SiteCollection: + Urls: + - / + #- /sites/spmeta2 + Web: + Urls: + - / + #- /sites/spmeta2 + SharePointOnline: + SiteCollection: + Urls: + - https://spmeta2-regression.sharepoint.com + #- https://spmeta2-regression.sharepoint.com + Web: + Urls: + - https://spmeta2-regression.sharepoint.com + #- https://spmeta2-regression.sharepoint.com + UserName: "ci@ci.com" + UserPassword: "" + + # describes unit tests settings + RegressionTests: + # which tests to run? + # SSOM, CSOM - these are run against SharePoint + # O365 - that's SP2013 CSOM run against SharePoint Online + # O365v16 - that's SharePoint Online packages run against SharePoint Online + ObjectModels: + - SSOM + #- CSOM + #- O365 + #- O365v16 \ No newline at end of file diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs index d9586121c..3b96fca04 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs @@ -1,198 +1,287 @@ -using System; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyGroupModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermGroupDefinition); } - } - - #endregion - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var siteModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployTaxonomyGroup(modelHost, siteModelHost, groupModel); - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - - var storeModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var termStore = storeModelHost.HostTermStore; - var currentGroup = FindGroup(storeModelHost, groupModel); - - action(new TermGroupModelHost - { - HostTermStore = termStore, - HostGroup = currentGroup - }); - } - - protected TermGroup FindSiteCollectionGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) - { - var termStore = storeModelHost.HostTermStore; - var site = storeModelHost.HostSite; - - var context = termStore.Context; - - TermGroup currentGroup = termStore.GetSiteCollectionGroup(site, true); - - context.Load(currentGroup); - context.ExecuteQueryWithTrace(); - return currentGroup; - } - - protected TermGroup FindGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) - { - var termStore = storeModelHost.HostTermStore; - var context = termStore.Context; - - TermGroup currentGroup = null; - - if (groupModel.IsSiteCollectionGroup) - { - currentGroup = FindSiteCollectionGroup(storeModelHost, groupModel); - return currentGroup; - } - - if (groupModel.Id.HasValue) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - currentGroup = termStore.Groups.GetById(groupModel.Id.Value); - context.Load(currentGroup); - } - - using (scope.StartCatch()) - { - - } - } - } - else if (!string.IsNullOrEmpty(groupModel.Name)) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - currentGroup = termStore.Groups.GetByName(groupModel.Name); - context.Load(currentGroup); - } - - using (scope.StartCatch()) - { - - } - } - } - - context.ExecuteQueryWithTrace(); - - if (currentGroup != null && currentGroup.ServerObjectIsNull == false) - { - context.Load(currentGroup, g => g.Id); - context.Load(currentGroup, g => g.Name); - - context.ExecuteQueryWithTrace(); - - return currentGroup; - } - - return null; - } - - private void DeployTaxonomyGroup(object modelHost, TermStoreModelHost siteModelHost, TaxonomyTermGroupDefinition groupModel) - { - var termStore = siteModelHost.HostTermStore; - var currentGroup = FindGroup(siteModelHost, groupModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentGroup, - ObjectType = typeof(TermGroup), - ObjectDefinition = groupModel, - ModelHost = modelHost - }); - - if (currentGroup == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Group"); - - currentGroup = groupModel.Id.HasValue - ? termStore.CreateGroup(groupModel.Name, groupModel.Id.Value) - : termStore.CreateGroup(groupModel.Name, Guid.NewGuid()); - - if (!string.IsNullOrEmpty(groupModel.Description)) - currentGroup.Description = groupModel.Description; - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentGroup, - ObjectType = typeof(TermGroup), - ObjectDefinition = groupModel, - ModelHost = modelHost - }); - - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Group"); - - if (!string.IsNullOrEmpty(groupModel.Description)) - currentGroup.Description = groupModel.Description; - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentGroup, - ObjectType = typeof(TermGroup), - ObjectDefinition = groupModel, - ModelHost = modelHost - }); - } - - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); - } - - #endregion - } -} +using System; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; +using SPMeta2.Exceptions; +using System.Threading; +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyGroupModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermGroupDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var siteModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployTaxonomyGroup(modelHost, siteModelHost, groupModel); + SharePointOnlineWait(siteModelHost, groupModel); + } + + private void SharePointOnlineWait(TermStoreModelHost siteModelHost, TaxonomyTermGroupDefinition groupModel) + { + // wait until the group is there + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + var context = siteModelHost.HostClientContext; + + if (context.Credentials is SharePointOnlineCredentials) + { + var currentGroup = FindGroup(siteModelHost, groupModel); + + if (currentGroup == null) + { + TryRetryService.TryWithRetry(() => + { + currentGroup = FindGroup(siteModelHost, groupModel); + return currentGroup != null; + }); + } + + if (currentGroup == null) + throw new SPMeta2Exception(string.Format("Cannot find a taxonomy group after provision")); + } + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var storeModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var termStore = storeModelHost.HostTermStore; + var currentGroup = FindGroup(storeModelHost, groupModel); + + if (currentGroup == null) + { + TryRetryService.TryWithRetry(() => + { + currentGroup = FindGroup(storeModelHost, groupModel); + return currentGroup != null; + }); + } + + if (currentGroup == null) + throw new SPMeta2Exception(string.Format("Cannot find a taxonomy group after provision")); + + action(ModelHostBase.Inherit(storeModelHost, host => + { + host.HostTermStore = termStore; + host.HostGroup = currentGroup; + })); + } + + protected TermGroup FindSiteCollectionGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) + { + var termStore = storeModelHost.HostTermStore; + var site = storeModelHost.HostSite; + + var context = termStore.Context; + + TermGroup currentGroup = termStore.GetSiteCollectionGroup(site, true); + + context.Load(currentGroup); + context.ExecuteQueryWithTrace(); + return currentGroup; + } + + protected TermGroup FindGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) + { + var termStore = storeModelHost.HostTermStore; + var context = termStore.Context; + + TermGroup currentGroup = null; + + if (groupModel.IsSiteCollectionGroup) + { + currentGroup = FindSiteCollectionGroup(storeModelHost, groupModel); + return currentGroup; + } + + if (groupModel.Id.HasValue) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + currentGroup = termStore.Groups.GetById(groupModel.Id.Value); + context.Load(currentGroup); + } + + using (scope.StartCatch()) + { + + } + } + } + else if (!string.IsNullOrEmpty(groupModel.Name)) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + currentGroup = termStore.Groups.GetByName(groupModel.Name); + context.Load(currentGroup); + } + + using (scope.StartCatch()) + { + + } + } + } + + context.ExecuteQueryWithTrace(); + + if (currentGroup != null + && currentGroup.ServerObjectIsNull.HasValue + && currentGroup.ServerObjectIsNull == false) + { + context.Load(currentGroup, g => g.Id); + context.Load(currentGroup, g => g.Name); + + context.ExecuteQueryWithTrace(); + + return currentGroup; + } + + return null; + } + + private void DeployTaxonomyGroup(object modelHost, TermStoreModelHost siteModelHost, TaxonomyTermGroupDefinition groupModel) + { + var termStore = siteModelHost.HostTermStore; + var currentGroup = FindGroup(siteModelHost, groupModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentGroup, + ObjectType = typeof(TermGroup), + ObjectDefinition = groupModel, + ModelHost = modelHost + }); + + if (currentGroup == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Group"); + + currentGroup = groupModel.Id.HasValue + ? termStore.CreateGroup(groupModel.Name, groupModel.Id.Value) + : termStore.CreateGroup(groupModel.Name, Guid.NewGuid()); + + if (!string.IsNullOrEmpty(groupModel.Description)) + currentGroup.Description = groupModel.Description; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentGroup, + ObjectType = typeof(TermGroup), + ObjectDefinition = groupModel, + ModelHost = modelHost + }); + } + else + { + UpdateExistingTaxonomyGroup(modelHost, groupModel, currentGroup); + } + + termStore.CommitAll(); + + termStore.Groups.RefreshLoad(); + termStore.RefreshLoad(); + + try + { + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 + // https://github.com/SubPointSolutions/spmeta2/issues/959 + + // seems that newly created group might not be available for the time being + // handling that "Group names must be unique." exception + // trying to find the group and only update description + var serverException = e as ServerException; + + if (serverException != null + && serverException.ServerErrorCode == -2147024809) + { + currentGroup = FindGroup(siteModelHost, groupModel); + + if (currentGroup == null) + { + TryRetryService.TryWithRetry(() => + { + currentGroup = FindGroup(siteModelHost, groupModel); + return currentGroup != null; + }); + } + + UpdateExistingTaxonomyGroup(modelHost, groupModel, currentGroup); + + termStore.CommitAll(); + + termStore.Groups.RefreshLoad(); + termStore.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + } + + siteModelHost.ShouldUpdateHost = false; + } + + private void UpdateExistingTaxonomyGroup(object modelHost, TaxonomyTermGroupDefinition groupModel, TermGroup currentGroup) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Group"); + + if (!string.IsNullOrEmpty(groupModel.Description)) + currentGroup.Description = groupModel.Description; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentGroup, + ObjectType = typeof(TermGroup), + ObjectDefinition = groupModel, + ModelHost = modelHost + }); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs index 60ba28309..ff97b578c 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs @@ -1,104 +1,146 @@ -using System; -using System.Linq; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyTermLabelModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermLabelDefinition); } - } - - #endregion - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var termModelHost = modelHost.WithAssertAndCast("model", m => m.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployTermLabel(modelHost, termModelHost, definition); - } - private void DeployTermLabel(object modelHost, TermModelHost termModelHost, TaxonomyTermLabelDefinition labelModel) - { - var termStore = termModelHost.HostTermStore; - var context = termStore.Context; - - var term = termModelHost.HostTerm; - var currentLabel = FindLabelInTerm(term, labelModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentLabel, - ObjectType = typeof(Label), - ObjectDefinition = labelModel, - ModelHost = modelHost - }); - - if (currentLabel == null) - { - TraceService.Verbose((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Label"); - - currentLabel = term.CreateLabel(labelModel.Name, labelModel.LCID, labelModel.IsDefault); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentLabel, - ObjectType = typeof(Label), - ObjectDefinition = labelModel, - ModelHost = modelHost - }); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentLabel, - ObjectType = typeof(Label), - ObjectDefinition = labelModel, - ModelHost = modelHost - }); - } - - termStore.CommitAll(); - context.ExecuteQueryWithTrace(); - } - - protected Label FindLabelInTerm(Term termSet, TaxonomyTermLabelDefinition labelModel) - { - var context = termSet.Context; - var labels = termSet.Labels; - - context.Load(labels); - context.ExecuteQueryWithTrace(); - - return termSet.Labels.ToList().FirstOrDefault(l => l.Value.ToUpper() == labelModel.Name.ToUpper()); - } - - #endregion - } -} +using System; +using System.Linq; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; +using Microsoft.SharePoint.Client; +using SPMeta2.Exceptions; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyTermLabelModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermLabelDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var termModelHost = modelHost.WithAssertAndCast("model", m => m.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployTermLabel(modelHost, termModelHost, definition); + SharePointOnlineWait(termModelHost, definition); + } + + private void SharePointOnlineWait(TermModelHost termModelHost, TaxonomyTermLabelDefinition definition) + { + // wait until the group is there + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + var context = termModelHost.HostClientContext; + + if (context.Credentials is SharePointOnlineCredentials) + { + var term = termModelHost.HostTerm; + var currentLabel = FindLabelInTerm(term, definition); + + if (currentLabel == null) + { + TryRetryService.TryWithRetry(() => + { + currentLabel = FindLabelInTerm(term, definition); + return currentLabel != null; + }); + } + + if (currentLabel == null) + throw new SPMeta2Exception(string.Format("Cannot find a term label after provision")); + } + } + private void DeployTermLabel(object modelHost, TermModelHost termModelHost, TaxonomyTermLabelDefinition labelModel) + { + var termStore = termModelHost.HostTermStore; + var context = termStore.Context; + + var term = termModelHost.HostTerm; + var currentLabel = FindLabelInTerm(term, labelModel); + + var shouldCommitChanges = false; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentLabel, + ObjectType = typeof(Label), + ObjectDefinition = labelModel, + ModelHost = modelHost + }); + + if (currentLabel == null) + { + TraceService.Verbose((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Label"); + + currentLabel = term.CreateLabel(labelModel.Name, labelModel.LCID, labelModel.IsDefault); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentLabel, + ObjectType = typeof(Label), + ObjectDefinition = labelModel, + ModelHost = modelHost + }); + + shouldCommitChanges = true; + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentLabel, + ObjectType = typeof(Label), + ObjectDefinition = labelModel, + ModelHost = modelHost + }); + + shouldCommitChanges = false; + } + + if (shouldCommitChanges) + { + termStore.CommitAll(); + + currentLabel.RefreshLoad(); + term.RefreshLoad(); + + context.ExecuteQueryWithTrace(); + } + } + + protected Label FindLabelInTerm(Term termSet, TaxonomyTermLabelDefinition labelModel) + { + var context = termSet.Context; + var labels = termSet.Labels; + + context.Load(labels); + context.ExecuteQueryWithTrace(); + + return termSet.Labels.ToList().FirstOrDefault(l => l.Value.ToUpper() == labelModel.Name.ToUpper()); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index 681dc19a7..d324103df 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -13,6 +13,7 @@ using SPMeta2.Standard.Definitions.Taxonomy; using SPMeta2.Standard.Utils; using SPMeta2.Utils; +using SPMeta2.ModelHosts; namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy { @@ -63,7 +64,6 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var childModelType = modelHostContext.ChildModelType; var action = modelHostContext.Action; - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); Term currentTerm = null; @@ -71,7 +71,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon TermSet termSet = null; TermStore termStore = null; - TermModelHost localModelHost = new TermModelHost(); + var localModelHost = ModelHostBase.Inherit(modelHost as ModelHostBase, host => + { + + }); if (modelHost is TermModelHost) { @@ -83,6 +86,15 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTerm(h.HostTerm, definition); + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTerm(h.HostTerm, definition); + return currentTerm != null; + }); + } + localModelHost.HostGroup = group; localModelHost.HostTermSet = termSet; localModelHost.HostTerm = currentTerm; @@ -98,6 +110,15 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTermSet(h.HostTermSet, definition); + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTermSet(h.HostTermSet, definition); + return currentTerm != null; + }); + } + localModelHost.HostGroup = group; localModelHost.HostTermSet = termSet; localModelHost.HostTerm = currentTerm; @@ -165,8 +186,51 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode }); } - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); + try + { + termStore.CommitAll(); + currentTerm.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + var serverException = e as ServerException; + + if (serverException != null + && serverException.HResult == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); + + currentTerm = FindTermInTermSet(termSet, termModel); + + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTermSet(termSet, termModel); + return currentTerm != null; + }); + } + + MapTermProperties(currentTerm, termModel, false); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTerm, + ObjectType = typeof(Term), + ObjectDefinition = termModel, + ModelHost = modelHost + }); + + termStore.CommitAll(); + termStore.Context.ExecuteQueryWithTrace(); + } + } } private void MapTermProperties(Term currentTerm, TaxonomyTermDefinition termModel, bool isNewObject) @@ -219,7 +283,7 @@ private void UpdateTermProperties(Term currentTerm, TaxonomyTermDefinition termM { var propName = prop.Name; var propValue = prop.Value; - + var propExist = false; if (isNewObject) @@ -327,8 +391,51 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, }); } - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); + try + { + termStore.CommitAll(); + currentTerm.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + var serverException = e as ServerException; + + if (serverException != null + && serverException.HResult == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); + + currentTerm = FindTermInTerm(termSet, termModel); + + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTerm(termSet, termModel); + return currentTerm != null; + }); + } + + MapTermProperties(currentTerm, termModel, false); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTerm, + ObjectType = typeof(Term), + ObjectDefinition = termModel, + ModelHost = modelHost + }); + + termStore.CommitAll(); + termStore.Context.ExecuteQueryWithTrace(); + } + } } @@ -411,7 +518,9 @@ protected Term FindTermInTermSet(TermSet termSet, TaxonomyTermDefinition termMod result = terms.FirstOrDefault(); } - if (result != null && result.ServerObjectIsNull == false) + if (result != null + && result.ServerObjectIsNull.HasValue + && result.ServerObjectIsNull == false) { context.Load(result); context.ExecuteQueryWithTrace(); diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs index 7b809cfb2..7405e02b1 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs @@ -1,206 +1,289 @@ -using System; -using System.Linq; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyTermSetModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermSetDefinition); } - } - - #endregion - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployTaxonomyTermSet(modelHost, groupModelHost, groupModel); - - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - - var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); - - action(new TermSetModelHost - { - HostGroup = groupModelHost.HostGroup, - HostTermStore = groupModelHost.HostTermStore, - HostTermSet = currentTermSet - }); - } - - private void DeployTaxonomyTermSet(object modelHost, TermGroupModelHost groupModelHost, TaxonomyTermSetDefinition termSetModel) - { - var termStore = groupModelHost.HostTermStore; - var termGroup = groupModelHost.HostGroup; - - var currentTermSet = FindTermSet(termGroup, termSetModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentTermSet, - ObjectType = typeof(TermSet), - ObjectDefinition = termSetModel, - ModelHost = modelHost - }); - - if (currentTermSet == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Set"); - - currentTermSet = termSetModel.Id.HasValue - ? termGroup.CreateTermSet(termSetModel.Name, termSetModel.Id.Value, termSetModel.LCID) - : termGroup.CreateTermSet(termSetModel.Name, Guid.NewGuid(), termSetModel.LCID); - - MapTermSet(currentTermSet, termSetModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentTermSet, - ObjectType = typeof(TermSet), - ObjectDefinition = termSetModel, - ModelHost = modelHost - }); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Set"); - - MapTermSet(currentTermSet, termSetModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentTermSet, - ObjectType = typeof(TermSet), - ObjectDefinition = termSetModel, - ModelHost = modelHost - }); - } - - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); - } - - private static void MapTermSet(TermSet currentTermSet, TaxonomyTermSetDefinition termSetModel) - { - if (!string.IsNullOrEmpty(termSetModel.Description)) - currentTermSet.Description = termSetModel.Description; - - if (!string.IsNullOrEmpty(termSetModel.Contact)) - currentTermSet.Contact = termSetModel.Contact; - - if (!string.IsNullOrEmpty(termSetModel.CustomSortOrder)) - currentTermSet.CustomSortOrder = termSetModel.CustomSortOrder; - - if (termSetModel.IsOpenForTermCreation.HasValue) - currentTermSet.IsOpenForTermCreation = termSetModel.IsOpenForTermCreation.Value; - - if (termSetModel.IsAvailableForTagging.HasValue) - currentTermSet.IsAvailableForTagging = termSetModel.IsAvailableForTagging.Value; - - - foreach (var customProp in termSetModel.CustomProperties.Where(p => p.Override)) - { - currentTermSet.SetCustomProperty(customProp.Name, customProp.Value); - } - } - - protected TermSet FindTermSet(TermGroup termGroup, TaxonomyTermSetDefinition termSetModel) - { - TermSet result = null; - - var context = termGroup.Context; - - context.Load(termGroup.TermSets); - context.ExecuteQueryWithTrace(); - - if (termSetModel.Id.HasValue) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - result = termGroup.TermSets.GetById(termSetModel.Id.Value); - context.Load(result); - } - - using (scope.StartCatch()) - { - - } - } - } - else if (!string.IsNullOrEmpty(termSetModel.Name)) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - result = termGroup.TermSets.GetByName(termSetModel.Name); - context.Load(result); - } - - using (scope.StartCatch()) - { - - } - } - } - - context.ExecuteQueryWithTrace(); - - if (result != null && result.ServerObjectIsNull == false) - { - context.Load(result); - //context.Load(result, g => g.Id); - //context.Load(result, g => g.Name); - - context.ExecuteQueryWithTrace(); - - return result; - } - - return null; - } - - #endregion - } -} +using System; +using System.Linq; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; +using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyTermSetModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermSetDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployTaxonomyTermSet(modelHost, groupModelHost, termSetModel); + SharePointOnlineWait(groupModelHost, termSetModel); + } + + private void SharePointOnlineWait(TermGroupModelHost groupModelHost, TaxonomyTermSetDefinition termSetModel) + { + // wait until the group is there + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + var context = groupModelHost.HostClientContext; + + if (context.Credentials is SharePointOnlineCredentials) + { + var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + + if (currentTermSet == null) + { + TryRetryService.TryWithRetry(() => + { + currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + return currentTermSet != null; + }); + } + + if (currentTermSet == null) + throw new SPMeta2Exception(string.Format("Cannot find a termset after provision")); + } + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + + if (currentTermSet == null) + { + TryRetryService.TryWithRetry(() => + { + currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + return currentTermSet != null; + }); + } + + if (currentTermSet == null) + throw new SPMeta2Exception(string.Format("Cannot find a taxonomy term set after provision")); + + action(ModelHostBase.Inherit(groupModelHost, host => + { + host.HostGroup = groupModelHost.HostGroup; + host.HostTermStore = groupModelHost.HostTermStore; + host.HostTermSet = currentTermSet; + })); + } + + private void DeployTaxonomyTermSet(object modelHost, TermGroupModelHost groupModelHost, TaxonomyTermSetDefinition termSetModel) + { + var termStore = groupModelHost.HostTermStore; + var termGroup = groupModelHost.HostGroup; + + var currentTermSet = FindTermSet(termGroup, termSetModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentTermSet, + ObjectType = typeof(TermSet), + ObjectDefinition = termSetModel, + ModelHost = modelHost + }); + + if (currentTermSet == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Set"); + + currentTermSet = termSetModel.Id.HasValue + ? termGroup.CreateTermSet(termSetModel.Name, termSetModel.Id.Value, termSetModel.LCID) + : termGroup.CreateTermSet(termSetModel.Name, Guid.NewGuid(), termSetModel.LCID); + + MapTermSet(currentTermSet, termSetModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTermSet, + ObjectType = typeof(TermSet), + ObjectDefinition = termSetModel, + ModelHost = modelHost + }); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Set"); + + UpdateExistingTaxonomyTermSet(modelHost, termSetModel, currentTermSet); + } + + termStore.CommitAll(); + + try + { + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 + // https://github.com/SubPointSolutions/spmeta2/issues/959 + + // seems that newly created group might not be available for the time being + // handling that "Group names must be unique." exception + // trying to find the group and only update description + var serverException = e as ServerException; + + if (serverException != null + && serverException.ServerErrorCode == -2146233088) + { + currentTermSet = FindTermSet(termGroup, termSetModel); + + if (currentTermSet == null) + { + TryRetryService.TryWithRetry(() => + { + currentTermSet = FindTermSet(termGroup, termSetModel); + return currentTermSet != null; + }); + } + + UpdateExistingTaxonomyTermSet(modelHost, termSetModel, currentTermSet); + + termStore.CommitAll(); + termStore.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + } + + groupModelHost.ShouldUpdateHost = false; + } + + private void UpdateExistingTaxonomyTermSet(object modelHost, TaxonomyTermSetDefinition termSetModel, TermSet currentTermSet) + { + MapTermSet(currentTermSet, termSetModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTermSet, + ObjectType = typeof(TermSet), + ObjectDefinition = termSetModel, + ModelHost = modelHost + }); + } + + private static void MapTermSet(TermSet currentTermSet, TaxonomyTermSetDefinition termSetModel) + { + if (!string.IsNullOrEmpty(termSetModel.Description)) + currentTermSet.Description = termSetModel.Description; + + if (!string.IsNullOrEmpty(termSetModel.Contact)) + currentTermSet.Contact = termSetModel.Contact; + + if (!string.IsNullOrEmpty(termSetModel.CustomSortOrder)) + currentTermSet.CustomSortOrder = termSetModel.CustomSortOrder; + + if (termSetModel.IsOpenForTermCreation.HasValue) + currentTermSet.IsOpenForTermCreation = termSetModel.IsOpenForTermCreation.Value; + + if (termSetModel.IsAvailableForTagging.HasValue) + currentTermSet.IsAvailableForTagging = termSetModel.IsAvailableForTagging.Value; + + + foreach (var customProp in termSetModel.CustomProperties.Where(p => p.Override)) + { + currentTermSet.SetCustomProperty(customProp.Name, customProp.Value); + } + } + + protected TermSet FindTermSet(TermGroup termGroup, TaxonomyTermSetDefinition termSetModel) + { + TermSet result = null; + + var context = termGroup.Context; + + context.Load(termGroup.TermSets); + context.ExecuteQueryWithTrace(); + + if (termSetModel.Id.HasValue) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + result = termGroup.TermSets.GetById(termSetModel.Id.Value); + context.Load(result); + } + + using (scope.StartCatch()) + { + + } + } + } + else if (!string.IsNullOrEmpty(termSetModel.Name)) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + result = termGroup.TermSets.GetByName(termSetModel.Name); + context.Load(result); + } + + using (scope.StartCatch()) + { + + } + } + } + + context.ExecuteQueryWithTrace(); + + if (result != null + && result.ServerObjectIsNull.HasValue + && result.ServerObjectIsNull == false) + { + context.Load(result); + //context.Load(result, g => g.Id); + //context.Load(result, g => g.Name); + + context.ExecuteQueryWithTrace(); + + return result; + } + + return null; + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs index d3dcf5525..56e0e7278 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs @@ -1,174 +1,176 @@ -using System; -using System.Collections.Generic; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.ModelHosts; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyTermStoreModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermStoreDefinition); } - } - - #endregion - - #region methods - - protected TermStore FindTermStore(SiteModelHost siteModelHost, TaxonomyTermStoreDefinition termStoreModel) - { - return TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, - termStoreModel.Name, - termStoreModel.Id, - termStoreModel.UseDefaultSiteCollectionTermStore); - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - - var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var termStore = FindTermStore(siteModelHost, termStoreModel); - - var termStoreModelHost = ModelHostBase.Inherit(siteModelHost, context => - { - context.HostTermStore = termStore; - }); - - action(termStoreModelHost); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling termStore.CommitAll()"); - - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); - } - - private static Dictionary _storeCache = new Dictionary(); - private static readonly object _storeCacheLock = new object(); - - internal static TermStore FindTermStore(SiteModelHost siteModelHost, - string termStoreName, - Guid? termStoreId, - bool? useDefaultSiteCollectionTermStore) - { - return FindTermStore(siteModelHost.HostSite, termStoreName, termStoreId, useDefaultSiteCollectionTermStore); - } - - internal static TermStore FindTermStore(Site site, - string termStoreName, - Guid? termStoreId, - bool? useDefaultSiteCollectionTermStore) - { - var clientContext = site.Context; - TermStore termStore = null; - - lock (_storeCacheLock) - { - var key = string.Format("{0}-{1}-{2}", - clientContext.GetHashCode(), - clientContext.GetHashCode(), - string.Format("{0}-{1}-{2}", termStoreName, termStoreId, useDefaultSiteCollectionTermStore)) - .ToLower(); - - if (!_storeCache.ContainsKey(key)) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "First call to TermStore with cache key: [{0}]", key); - - var session = TaxonomySession.GetTaxonomySession(clientContext); - var client = clientContext; - - if (useDefaultSiteCollectionTermStore == true) - { - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store as useDefaultSiteCollectionTermStore"); - - termStore = session.GetDefaultSiteCollectionTermStore(); - } - else - { - if (termStoreId.HasValue && termStoreId != default(Guid)) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by ID: [{0}]", termStoreId.Value); - termStore = session.TermStores.GetById(termStoreId.Value); - } - else if (!string.IsNullOrEmpty(termStoreName)) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by Name: [{0}]", termStoreName); - termStore = session.TermStores.GetByName(termStoreName); - } - } - - if (termStore != null) - { - client.Load(termStore, s => s.Id); - client.Load(termStore, s => s.Name); - - client.ExecuteQueryWithTrace(); - } - - - _storeCache.Add(key, termStore); - } - else - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving term store from internal cache with cache key: [{0}]", key); - } - - return _storeCache[key]; - } - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var termStore = TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, - termStoreModel.Name, - termStoreModel.Id, - termStoreModel.UseDefaultSiteCollectionTermStore); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = termStore, - ObjectType = typeof(TermStore), - ObjectDefinition = model, - ModelHost = modelHost - }); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = termStore, - ObjectType = typeof(TermStore), - ObjectDefinition = model, - ModelHost = modelHost - }); - } - - #endregion - } -} +using System; +using System.Collections.Generic; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.ModelHosts; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyTermStoreModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermStoreDefinition); } + } + + #endregion + + #region methods + + protected TermStore FindTermStore(SiteModelHost siteModelHost, TaxonomyTermStoreDefinition termStoreModel) + { + return TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, + termStoreModel.Name, + termStoreModel.Id, + termStoreModel.UseDefaultSiteCollectionTermStore); + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var termStore = FindTermStore(siteModelHost, termStoreModel); + + var termStoreModelHost = ModelHostBase.Inherit(siteModelHost, context => + { + context.HostTermStore = termStore; + }); + + action(termStoreModelHost); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling termStore.CommitAll()"); + + if (termStoreModelHost.ShouldUpdateHost) + { + termStore.CommitAll(); + termStore.Context.ExecuteQueryWithTrace(); + } + } + + private static Dictionary _storeCache = new Dictionary(); + private static readonly object _storeCacheLock = new object(); + + internal static TermStore FindTermStore(SiteModelHost siteModelHost, + string termStoreName, + Guid? termStoreId, + bool? useDefaultSiteCollectionTermStore) + { + return FindTermStore(siteModelHost.HostSite, termStoreName, termStoreId, useDefaultSiteCollectionTermStore); + } + + internal static TermStore FindTermStore(Site site, + string termStoreName, + Guid? termStoreId, + bool? useDefaultSiteCollectionTermStore) + { + var clientContext = site.Context; + TermStore termStore = null; + + lock (_storeCacheLock) + { + var key = string.Format("{0}-{1}-{2}", + clientContext.GetHashCode(), + clientContext.GetHashCode(), + string.Format("{0}-{1}-{2}", termStoreName, termStoreId, useDefaultSiteCollectionTermStore)) + .ToLower(); + + if (!_storeCache.ContainsKey(key)) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "First call to TermStore with cache key: [{0}]", key); + + var session = TaxonomySession.GetTaxonomySession(clientContext); + var client = clientContext; + + if (useDefaultSiteCollectionTermStore == true) + { + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store as useDefaultSiteCollectionTermStore"); + + termStore = session.GetDefaultSiteCollectionTermStore(); + } + else + { + if (termStoreId.HasValue && termStoreId != default(Guid)) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by ID: [{0}]", termStoreId.Value); + termStore = session.TermStores.GetById(termStoreId.Value); + } + else if (!string.IsNullOrEmpty(termStoreName)) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by Name: [{0}]", termStoreName); + termStore = session.TermStores.GetByName(termStoreName); + } + } + + if (termStore != null) + { + client.Load(termStore, s => s.Id); + client.Load(termStore, s => s.Name); + + client.ExecuteQueryWithTrace(); + } + + + _storeCache.Add(key, termStore); + } + else + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving term store from internal cache with cache key: [{0}]", key); + } + + return _storeCache[key]; + } + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var termStore = TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, + termStoreModel.Name, + termStoreModel.Id, + termStoreModel.UseDefaultSiteCollectionTermStore); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = termStore, + ObjectType = typeof(TermStore), + ObjectDefinition = model, + ModelHost = modelHost + }); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = termStore, + ObjectType = typeof(TermStore), + ObjectDefinition = model, + ModelHost = modelHost + }); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs index 008ad148b..26f2a8c06 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs @@ -134,6 +134,14 @@ protected virtual bool ShouldRetryExecuteQuery(Exception ex) //if (ex.HResult == -2146233088) // return true; + if (ex.Message.Contains("Failed to read from or write to database")) + { + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + + return false; + } + // O365 related handling if (IsAllowedHttpWebResponseStatusCode(ex)) return true; diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index 0c55f241a..c0383a96e 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.Diagnostics; using System.Security; @@ -19,6 +20,7 @@ using SPMeta2.Regression.CSOM.Standard.Validation.Fields; using SPMeta2.Services; using SPMeta2.Utils; +using SPMeta2.Exceptions; namespace SPMeta2.Containers.O365v16 { @@ -154,6 +156,9 @@ public override string ResolveFullTypeName(string typeName, string assemblyName) /// public override void DeploySiteModel(ModelNode model) { + if (!SiteUrls.Any()) + throw new SPMeta2Exception("SiteUrls is empty"); + foreach (var siteUrl in SiteUrls) { ContainerTraceUtils.WriteLine(string.Format("[INF] Running on site: [{0}]", siteUrl)); @@ -185,6 +190,9 @@ public override void DeploySiteModel(ModelNode model) /// public override void DeployWebModel(ModelNode model) { + if (!WebUrls.Any()) + throw new SPMeta2Exception("WebUrls is empty"); + foreach (var webUrl in WebUrls) { ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); diff --git a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs index 5c59442d1..31d174353 100644 --- a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs +++ b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs @@ -124,12 +124,16 @@ protected virtual void InitConfig() private bool _hasInit = false; + public static string CurrentProvisionRunnerAsssmbly {get;set;} + protected virtual void InitRunnerImplementations() { if (_hasInit) return; foreach (var asmFileName in ProvisionRunnerAssemblies) { + CurrentProvisionRunnerAsssmbly = asmFileName; + var asmImpl = Assembly.LoadFrom(asmFileName); var types = ReflectionUtils.GetTypesFromAssembly(asmImpl); diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs index dcf58dd53..64f897ce5 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs @@ -1,63 +1,67 @@ -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy -{ - public class TaxonomyGroupDefinitionValidator : TaxonomyGroupModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var termStoreModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var spObject = FindGroup(termStoreModelHost, definition); - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject); - - if (definition.IsSiteCollectionGroup) - { - assert.SkipProperty(m => m.Name, "IsSiteCollectionGroup is TRUE. Skipping Name property validation."); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.IsSiteCollectionGroup); - var group = FindSiteCollectionGroup(termStoreModelHost, definition); - - var isValid = group.IsSiteCollectionGroup; - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - - - } - else - { - assert.SkipProperty(m => m.IsSiteCollectionGroup, "IsSiteCollectionGroup is false. Skipping property."); - assert.ShouldBeEqual(m => m.Name, o => o.Name); - } - - if (!string.IsNullOrEmpty(definition.Description)) - assert.ShouldBeEqual(m => m.Description, o => o.Description); - else - assert.SkipProperty(m => m.Description, "Description is null. Skipping property."); - - if (definition.Id.HasValue) - assert.ShouldBeEqual(m => m.Id, o => o.Id); - else - assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); - } - } -} +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy +{ + public class TaxonomyGroupDefinitionValidator : TaxonomyGroupModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var termStoreModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = FindGroup(termStoreModelHost, definition); + + TryRetryService.TryWithRetry(() => + { + spObject = FindGroup(termStoreModelHost, definition); + return spObject != null; + }); + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject); + + if (definition.IsSiteCollectionGroup) + { + assert.SkipProperty(m => m.Name, "IsSiteCollectionGroup is TRUE. Skipping Name property validation."); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.IsSiteCollectionGroup); + var group = FindSiteCollectionGroup(termStoreModelHost, definition); + + var isValid = group.IsSiteCollectionGroup; + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.IsSiteCollectionGroup, "IsSiteCollectionGroup is false. Skipping property."); + assert.ShouldBeEqual(m => m.Name, o => o.Name); + } + + if (!string.IsNullOrEmpty(definition.Description)) + assert.ShouldBeEqual(m => m.Description, o => o.Description); + else + assert.SkipProperty(m => m.Description, "Description is null. Skipping property."); + + if (definition.Id.HasValue) + assert.ShouldBeEqual(m => m.Id, o => o.Id); + else + assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs index 06b3fe91c..c8c55a814 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs @@ -1,178 +1,186 @@ -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Exceptions; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Standard.Utils; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy -{ - public class TaxonomyTermDefinitionValidator : TaxonomyTermModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - Term spObject = null; - - if (modelHost is TermModelHost) - spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); - else if (modelHost is TermSetModelHost) - spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); - else - { - throw new SPMeta2UnsupportedModelHostException(string.Format("Model host of type: [{0}] is not supported", modelHost.GetType())); - - } - - TermExtensions.CurrentLCID = definition.LCID; - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject) - //.ShouldBeEqual(m => m.Name, o => o.Name) - .ShouldBeEqual(m => m.Description, o => o.GetDefaultLCIDDescription()); - - assert.SkipProperty(m => m.LCID, "LCID is not accessible from OM. Should be alright while provision."); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.Name); - var dstProp = d.GetExpressionValue(m => m.Name); - - var isValid = NormalizeTermName(s.Name) == d.Name; - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = dstProp, - IsValid = isValid - }; - }); - - - - - if (!string.IsNullOrEmpty(definition.CustomSortOrder)) - assert.ShouldBeEqual(m => m.CustomSortOrder, o => o.CustomSortOrder); - else - assert.SkipProperty(m => m.CustomSortOrder); - - if (definition.Id.HasValue) - { - assert.ShouldBeEqual(m => m.Id, o => o.Id); - } - else - { - assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); - } - - if (definition.IsAvailableForTagging.HasValue) - { - assert.ShouldBeEqual(m => m.IsAvailableForTagging, o => o.IsAvailableForTagging); - } - else - { - assert.SkipProperty(m => m.IsAvailableForTagging, "IsAvailableForTagging is null. Skipping property."); - } - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.CustomProperties); - - var isValid = true; - - // missed props, or too much - // should be equal on the first provision - if (s.CustomProperties.Count != d.CustomProperties.Count) - { - isValid = false; - } - - // per prop - foreach (var customProp in s.CustomProperties) - { - if (!d.CustomProperties.ContainsKey(customProp.Name)) - { - isValid = false; - break; - } - - if (d.CustomProperties[customProp.Name] != customProp.Value) - { - isValid = false; - break; - } - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - // Dst = dstProp, - IsValid = isValid - }; - }); - - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.LocalCustomProperties); - - var isValid = true; - - // missed props, or too much - // should be equal on the first provision - if (s.LocalCustomProperties.Count != d.LocalCustomProperties.Count) - { - isValid = false; - } - - // per prop - foreach (var customProp in s.LocalCustomProperties) - { - if (!d.LocalCustomProperties.ContainsKey(customProp.Name)) - { - isValid = false; - break; - } - - if (d.LocalCustomProperties[customProp.Name] != customProp.Value) - { - isValid = false; - break; - } - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - // Dst = dstProp, - IsValid = isValid - }; - }); - } - } - - internal static class TermExtensions - { - public static int CurrentLCID { get; set; } - - public static string GetDefaultLCIDDescription(this Term term) - { - var context = term.Context; - - var resultValue = term.GetDescription(CurrentLCID); - context.ExecuteQueryWithTrace(); - - return resultValue.Value; - } - } -} +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Exceptions; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Standard.Utils; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy +{ + public class TaxonomyTermDefinitionValidator : TaxonomyTermModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + Term spObject = null; + + if (modelHost is TermModelHost) + { + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); + return spObject != null; + }); + } + else if (modelHost is TermSetModelHost) + { + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); + return spObject != null; + }); + } + else + { + throw new SPMeta2UnsupportedModelHostException(string.Format("Model host of type: [{0}] is not supported", modelHost.GetType())); + } + + TermExtensions.CurrentLCID = definition.LCID; + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject) + //.ShouldBeEqual(m => m.Name, o => o.Name) + .ShouldBeEqual(m => m.Description, o => o.GetDefaultLCIDDescription()); + + assert.SkipProperty(m => m.LCID, "LCID is not accessible from OM. Should be alright while provision."); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.Name); + var dstProp = d.GetExpressionValue(m => m.Name); + + var isValid = NormalizeTermName(s.Name) == d.Name; + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = dstProp, + IsValid = isValid + }; + }); + + if (!string.IsNullOrEmpty(definition.CustomSortOrder)) + assert.ShouldBeEqual(m => m.CustomSortOrder, o => o.CustomSortOrder); + else + assert.SkipProperty(m => m.CustomSortOrder); + + if (definition.Id.HasValue) + { + assert.ShouldBeEqual(m => m.Id, o => o.Id); + } + else + { + assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); + } + + if (definition.IsAvailableForTagging.HasValue) + { + assert.ShouldBeEqual(m => m.IsAvailableForTagging, o => o.IsAvailableForTagging); + } + else + { + assert.SkipProperty(m => m.IsAvailableForTagging, "IsAvailableForTagging is null. Skipping property."); + } + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.CustomProperties); + + var isValid = true; + + // missed props, or too much + // should be equal on the first provision + if (s.CustomProperties.Count != d.CustomProperties.Count) + { + isValid = false; + } + + // per prop + foreach (var customProp in s.CustomProperties) + { + if (!d.CustomProperties.ContainsKey(customProp.Name)) + { + isValid = false; + break; + } + + if (d.CustomProperties[customProp.Name] != customProp.Value) + { + isValid = false; + break; + } + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + // Dst = dstProp, + IsValid = isValid + }; + }); + + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.LocalCustomProperties); + + var isValid = true; + + // missed props, or too much + // should be equal on the first provision + if (s.LocalCustomProperties.Count != d.LocalCustomProperties.Count) + { + isValid = false; + } + + // per prop + foreach (var customProp in s.LocalCustomProperties) + { + if (!d.LocalCustomProperties.ContainsKey(customProp.Name)) + { + isValid = false; + break; + } + + if (d.LocalCustomProperties[customProp.Name] != customProp.Value) + { + isValid = false; + break; + } + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + // Dst = dstProp, + IsValid = isValid + }; + }); + } + } + + internal static class TermExtensions + { + public static int CurrentLCID { get; set; } + + public static string GetDefaultLCIDDescription(this Term term) + { + var context = term.Context; + + var resultValue = term.GetDescription(CurrentLCID); + context.ExecuteQueryWithTrace(); + + return resultValue.Value; + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs index 4b8b43749..08a16406a 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs @@ -13,7 +13,16 @@ public override void DeployModel(object modelHost, DefinitionBase model) var termModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + var spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + + if (spObject == null) + { + TryRetryService.TryWithRetry(() => + { + spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + return spObject != null; + }); + } var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs index 4dd3eaa96..cbef364f8 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs @@ -15,7 +15,13 @@ public override void DeployModel(object modelHost, DefinitionBase model) var termGroupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + var spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + + TryRetryService.TryWithRetry(() => + { + spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + return spObject != null; + }); var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs index cec5758e8..77e8c139e 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs @@ -269,8 +269,12 @@ public void Can_Find_ListView_WithInList() var webModel = SPMeta2Model.NewWebModel(rootWeb => { + rootWeb.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit()); + rootWeb.AddWeb(webDef, web => { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit()); + web .AddList(Lists.TestList1, list => { diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs index a8350c568..6bab02951 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs @@ -35,7 +35,7 @@ namespace SPMeta2.Regression.Tests.Base { - public class SPMeta2RegresionTestCoreBase + public class SPMeta2RegresionTestCoreBase : SPMeta2RegresionTestVeryBase { static SPMeta2RegresionTestCoreBase() { @@ -49,7 +49,7 @@ private static string GetFullPath(string path) static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { - var m2runner = Environment.GetEnvironmentVariable("SPMeta2_RunnerLibraries", EnvironmentVariableTarget.Machine); + var m2runner = RegressionTestService.CurrentProvisionRunnerAsssmbly; var baseDir = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory); RegressionUtils.WriteLine(string.Format("Resolving custom assembly binding for m2 runner:[{0}]", m2runner)); @@ -103,12 +103,28 @@ static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs ar { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-2013")); assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + + // VS sometimes does not coipy these accorss + // referencing straight to the solution + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM.Standard\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM\bin\Debug45\"))); + + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM.Standard\bin\Debug45\"))); } if (m2runner == "SPMeta2.Containers.CSOM.dll") { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-2013")); assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + + // VS sometimes does not coipy these accorss + // referencing straight to the solution + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM.Standard\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM\bin\Debug45\"))); + + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM.Standard\bin\Debug45\"))); } foreach (var dir in assemblyDirs) @@ -122,7 +138,7 @@ static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs ar } } - throw new Exception(string.Format("Cannot load custom assembly:[{0}] for assembly:[{1}]", + throw new Exception(string.Format("Cannot load custom assembly:[{0}] for assembly:[{1}]. Rebuild solution via powershell .\build in 'Build' project and run regression again", args.Name, args.RequestingAssembly )); diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs new file mode 100644 index 000000000..6a47eecd1 --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs @@ -0,0 +1,34 @@ +using SPMeta2.Services; +using SPMeta2.Services.Impl; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + + +namespace SPMeta2.Regression.Tests.Base +{ + public class SPMeta2RegresionTestVeryBase + { + static SPMeta2RegresionTestVeryBase() + { + ServiceContainer.Instance.ReplaceService( + typeof(TraceServiceBase), + new TraceableTraceService()); + } + } + + + public class TraceableTraceService : TraceSourceService + { + protected override void TraceEvent(int id, System.Diagnostics.TraceEventType messageType, object message, Exception exception) + { + base.TraceEvent(id, messageType, message, exception); + + var traceString = GetTraceEventString(id, messageType, message, exception); + + Trace.WriteLine(traceString); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs index 2ad097068..bd9782694 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs @@ -98,7 +98,7 @@ public RandomDefinitionTest() EnablePropertyNullableValidation = true; PropertyNullableGenerationCount = 1; - RegressionService.ShowOnlyFalseResults = false; + RegressionService.ShowOnlyFalseResults = true; } #region common diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs index b14f1bb14..81dfbf8ed 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs @@ -24,7 +24,7 @@ public class SPMeta2RegresionScenarioTestBase : SPMeta2ProvisionRegresionTestBas public SPMeta2RegresionScenarioTestBase() { RegressionService.ProvisionGenerationCount = 2; - RegressionService.ShowOnlyFalseResults = false; + RegressionService.ShowOnlyFalseResults = true; var isIncrementalProvisionEnabled = IsIncrementalProvisionMode; diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs index a8ef17614..ae63b9162 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs @@ -26,7 +26,7 @@ public class FarmSolutionScenariosTest : SPMeta2RegresionScenarioTestBase public FarmSolutionScenariosTest() { RegressionService.ProvisionGenerationCount = 1; - RegressionService.ShowOnlyFalseResults = false; + RegressionService.ShowOnlyFalseResults = true; } #endregion diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs index 6d80d61d2..71691627a 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs @@ -46,7 +46,7 @@ protected void GenerateTermsTree(ModelNode termSetOrTermNode, int deep, bool cle (termSetOrTermNode as TaxonomyTermModelNode).AddRandomTerm(term => { var termDef = term.Value as TaxonomyTermDefinition; - termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); + termDef.Name = string.Format("il{0}_{1}", deep, termDef.Name); if (cleanGuid) termDef.Id = null; @@ -59,7 +59,7 @@ protected void GenerateTermsTree(ModelNode termSetOrTermNode, int deep, bool cle (termSetOrTermNode as TaxonomyTermSetModelNode).AddRandomTerm(term => { var termDef = term.Value as TaxonomyTermDefinition; - termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); + termDef.Name = string.Format("il{0}_{1}", deep, termDef.Name); if (cleanGuid) termDef.Id = null; diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 deleted file mode 100644 index 68c65af02..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -cls cd "$PSScriptRoot" . "$PSScriptRoot\_config.ps1" -. "$PSScriptRoot\_sys.common.ps1" - -Write-Host "Ensuring M2 test web application with the following settings:" -fore Green -M2ShowSettings $g_M2WebAppSettings - -Write-Host "Ensuring M2 test web application with the following settings:" -fore Green - -$g_M2WebAppSettings.ShouldRecreateWebApplicaiton = $true -$g_M2WebAppSettings.ShouldRecreateSiteCollection = $true - -EnsureSPMeta2SandboxWebApplication $g_M2WebAppSettings.ShouldRecreateWebApplicaiton -EnsureSPMeta2SandboxSiteCollections $g_M2WebAppSettings.ShouldRecreateSiteCollection \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 deleted file mode 100644 index fcac18fd2..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 +++ /dev/null @@ -1,129 +0,0 @@ -cls - -Write-Host "Loading SharePoint API" - -$ver = $host | select version -if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} -if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) { - Add-PSSnapin "Microsoft.SharePoint.PowerShell" -} - -# checks that Pages and Docs are configured correctly - -$rootWebUrl = "http://dev42:9299/sites/parliament-web-3" -$web = Get-SPWeb $rootWebUrl - -if($web -eq $null) { - return -} - -function isContentTypeHidden($list, $name) { - - $result = $true - - $cts = $list.RootFolder.ContentTypeOrder - foreach($ct in $cts) { - - if($ct.Name -eq $name) { - $result = $false - } - } - - return $result - -} - -function hasContentType($list, $name) { - - $result = $false - - $cts = $list.ContentTypes - - foreach($ct in $cts) { - - if($ct.Name -eq $name) { - $result = $true - } - } - - return $result - -} - -function CheckPagesLibraryContentTypes($web) { - - $isValid = $true - - $pages = $web.Lists["Pages"] - # should have 'Welcome Page' hidden - - - $isValid = $true - - $isValid = $isValid -and ((isContentTypeHidden $pages "Welcome Page") -eq $true) - $isValid = $isValid -and ((hasContentType $pages "Welcome Page") -eq $true) - $isValid = $isValid -and ((hasContentType $pages "Article Page") -eq $false) - $isValid = $isValid -and ((hasContentType $pages "Page") -eq $false) - - - - if($isValid -eq $true) { - Write-Host "`t`t[+] Page content types" -fore green - } else { - Write-Host "`t`t[-] Page content types " -fore red - } - #RETURN $isValid -} - - -function CheckDocumentaLibraryContentTypes($web) { - - $isValid = $true - - $pages = $web.Lists["Pages"] - # should have 'Welcome Page' hidden - - - $isValid = $true - - $isValid = $isValid -and ((hasContentType $pages "Document") -eq $false) - - - if($isValid -eq $true) { - Write-Host "`t`t[+] Document content types" -fore green - } else { - Write-Host "`t`t[-] Document content types" -fore red - $errors++ - #exit - } - - #RETURN $isValid -} - -function ProcessWeb($web) { - # Write-Host $web.ServerRelativeUrl - - - CheckPagesLibraryContentTypes $web - CheckDocumentaLibraryContentTypes $web -} - -function ProcessSPWebRecursively([Microsoft.SharePoint.SPWeb] $web) -{ - Write-Host "Processing web: [$($web.Url)]" -fore Gray - - ProcessWeb($web) - - $subwebs = $web.GetSubwebsForCurrentUser() - - foreach($subweb in $subwebs) - { - ProcessSPWebRecursively($subweb) - $subweb.Dispose() - } -} - -Write-Host "Processing web: [$webUrl] with all subwebs" -fore Green -ProcessSPWebRecursively $web - -Write-Host "Done" \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 deleted file mode 100644 index bfb0d0bc5..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -cls - -cd "$PSScriptRoot" - -$PSScriptRoot - -. "$PSScriptRoot\_config.ps1" -. "$PSScriptRoot\_sys.common.ps1" - -Write-Host "Configuring M2 test environment with the following settings:" -fore Green -M2ShowSettings $g_M2TestEnvironment - -# CSOM, SSOM, O365 -#SetupSPMeta2RegressionTestEnvironment "SSOM" -#SetupSPMeta2RegressionTestEnvironment "CSOM" -#SetupSPMeta2RegressionTestEnvironment "O365" -SetupSPMeta2RegressionTestEnvironment "O365v16" \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 deleted file mode 100644 index 11ebbb607..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 +++ /dev/null @@ -1,97 +0,0 @@ -cls - -$s_runnerLibrary = "SPMeta2.Containers.CSOM.dll" -#$s_runnerLibrary = "SPMeta2.Containers.SSOM.dll" - -$s_username = [System.Environment]::GetEnvironmentVariable("SPMeta2_Grid_UserName", "Machine") -$s_password = [System.Environment]::GetEnvironmentVariable("SPMeta2_Grid_UserPassword", "Machine") -$s_nodeList = [System.Environment]::GetEnvironmentVariable("SPMeta2_Grid_Nodes", "Machine") - -$s_passwordSecure = $s_password | convertto-securestring -Force -AsPlainText - -$s_cred = new-object -typename System.Management.Automation.PSCredential ` - -argumentlist $s_username, $s_passwordSecure - -$s_nodes = $s_nodeList.Split(',') - -Configuration M2GridRunnerLibrariesClean { - - param( - $nodeName, - $runnerLibraries - ) - - Import-DscResource –ModuleName 'PSDesiredStateConfiguration' - - Node $nodeName { - - Environment RunnerLibraryRemove { - Name = "SPMeta2_RunnerLibraries" - Ensure = 'Absent' - } - } - - Node $nodeName { - - Environment SPMeta2_SSOM_WebApplicationUrlsRemove { - Name = "SPMeta2_SSOM_WebApplicationUrls" - Ensure = 'Absent' - } - } -} - -Configuration M2GridRunnerLibraries { - - param( - $nodeName, - $runnerLibraries, - $webAppUrls - ) - - Import-DscResource –ModuleName 'PSDesiredStateConfiguration' - - Node $nodeName { - - Environment RunnerLibrary { - Name = "SPMeta2_RunnerLibraries" - Ensure = 'Present' - Value = $runnerLibraries - } - } - - Node $nodeName { - - Environment SPMeta2_SSOM_WebApplicationUrls { - Name = "SPMeta2_SSOM_WebApplicationUrls" - Ensure = 'Present' - Value = $webAppUrls - } - } -} - -Remove-item M2GridRunnerLibrariesClean -Force -Recurse -Confirm:$false -Remove-item M2GridRunnerLibraries -Force -Recurse -Confirm:$false - -foreach($node in $s_nodes) { - - Write-Host "Compiling DSC for node [$node] and library:[$s_runnerLibrary]" -fore green - - M2GridRunnerLibrariesClean -nodeName $node ` - -runnerLibraries $s_runnerLibrary | out-null - - M2GridRunnerLibraries -nodeName $node ` - -webAppUrls ("http://" + $node + ":31417") ` - -runnerLibraries $s_runnerLibrary | out-null -} - -Write-Host "Applying DSC with library:[$s_runnerLibrary ]" -fore green - -Start-DscConfiguration M2GridRunnerLibrariesClean -Credential $s_cred ` - -Wait ` - -Verbose - -Start-DscConfiguration M2GridRunnerLibraries -Credential $s_cred ` - -Wait ` - -Verbose - - diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 deleted file mode 100644 index 1b6b77efc..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 +++ /dev/null @@ -1,120 +0,0 @@ -Add-Type -TypeDefinition @" - public enum EnvironmentType - { - SSOM, - CSOM, - O365, - O365v16 - } -"@ - -# defines configs for new 'sandbox' web application -$g_M2WebAppSettings = New-Object PSObject -Property @{ - - # -- GLOBAL SETTINGS -- - # current machine/domain name - MachineName = [Environment]::MachineName - DomainName = [Environment]::UserDomainName - - # sql server address - SqlServerMachineName = [Environment]::MachineName - - # -- WEB APP SETTINGS -- - # should web app or site be recreated - - ShouldRecreateWebApplicaiton = $true - - # port and ap account for the web app - WebApplicationPort = 31415 - WebApplicationPoolAccountName = "$([Environment]::UserDomainName)\sp_farm" - - - # -- SITE COLLECTION SETTINGS -- - # should site colleciton be recreated - - ShouldRecreateSiteCollection = $true - SiteCollectionTemplate = "BLANKINTERNET#0" - SiteCollectionLCID = 1033 - SiteCollectionOwner = "$([Environment]::UserDomainName)\$([Environment]::UserName)" - SiteCollectionAdministrators = @( - "$([Environment]::UserDomainName)\administrator", - "$([Environment]::UserDomainName)\sp_admin", - "$([Environment]::UserDomainName)\sp_farm" - ) -} - -# defines config for the regression test -$g_M2TestEnvironment = New-Object PSObject -Property @{ - - # -- GLOBAL SETTINGS -- - # current environment type - # CSOM, SSOM or O365 - EnvironmentType = "SSOM" - - #O365 specific settings - O365UserName = "support@subpointsolutions.com" - O365UserPassword = "su1sbhsbhu8wxvKQ" - - O365SiteUrls = @( - "https://subpointsolutions.sharepoint.com/sites/calc-col" - ) - - O365WebUrls = @( - "https://subpointsolutions.sharepoint.com/sites/calc-col" - ) - - RandomBalancedUrls = @( - -) - - O365DefaultTestUserLogins = @( - "" - ) - - - # CSOM specific settings - CSOMWebApplicationUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - #"http://$([Environment]::MachineName)" - #"http://portal" - ) - - CSOMSiteUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - #"http://$([Environment]::MachineName)" - #"http://portal" - ) - - CSOMWebUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - #"http://$([Environment]::MachineName)" - #"http://portal" - ) - - # SSOM specific settings - SSOMWebApplicationUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - ) - - SSOMSiteUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - ) - - SSOMWebUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - ) - - OO365TestLogins = @( - "" - ) - - OnPremTestActiveDirectoryLogins = @( - "$([Environment]::UserDomainName)\administrator", - "$([Environment]::UserDomainName)\sp_admin", - "$([Environment]::UserDomainName)\sp_farm" - ) - - OnPremTestActiveDirectoryGroups = @( - "$([Environment]::UserDomainName)\test-g1" - ) -} \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 deleted file mode 100644 index ae5897948..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 +++ /dev/null @@ -1,535 +0,0 @@ -. "$PSScriptRoot\_config.ps1" - -Write-Host "Loading SharePoint API" -fore Green -$ver = $host | select version -if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} -if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) { - Add-PSSnapin "Microsoft.SharePoint.PowerShell" -} - - -function M2ShowSettings($obj) { - - $props = $obj | Get-Member -type NoteProperty - - foreach($prop in $props) { - $value=$obj."$($prop.Name)" - Write-Host "`t[$($prop.Name)]:`t[$value]" -fore Gray - } -} - -#script setting -$g_script_RecreateWebApp = $g_M2WebAppSettings.ShouldRecreateWebApplicaiton -$g_script_RecreateSiteCollections = $g_M2WebAppSettings.ShouldRecreateSiteCollection - -#global settings -$g_port = $g_M2WebAppSettings.WebApplicationPort - -$g_machineName = $g_M2WebAppSettings.MachineName -$g_DomainName = $g_M2WebAppSettings.DomainName -$g_webAppDatabaseServerName = $g_M2WebAppSettings.SqlServerMachineName - -# web app settings - - $g_webAppUrl = $g_machineName + ":" + $g_port; - - $g_webAppName = "SPMeta2 Sandbox - $g_port" - $g_webAppPool = "$g_machineName - $g_port" - $g_webAppHostHeader = $g_machineName - $g_webAppPort = $g_port - - # should be managed account - $g_webAppAppPoolAccount = $g_M2WebAppSettings.WebApplicationPoolAccountName - - #$g_webAppDatabaseServerName = $g_machineName - $g_webAppDatabaseName = "WSS_Content_$g_port" - -# site settings - - $g_siteCollectionOwner = $g_M2WebAppSettings.SiteCollectionOwner - - $g_siteCollectionTemplate = $g_M2WebAppSettings.SiteCollectionTemplate - $g_siteCollectionLanguage = $g_M2WebAppSettings.SiteCollectionLCID - - $g_siteUrls = @() - $g_siteUrls += ("http://" + $g_machineName + ":" + $g_port); - $g_siteUrls += ("http://" + $g_machineName + ":" + $g_port + "/sites/m2"); - -# subweb settings - - $g_webTemplate = "STS#0" - - - $g_siteRelativeWebUrls = @() - $g_siteRelativeWebUrls += "/first" - $g_siteRelativeWebUrls += "/first/second" - $g_siteRelativeWebUrls += "/first/second/third" - - -# creates a new web app -function CreateWebApplication() -{ - $WebAppName = $g_webAppName - $WebAppAppPool = $g_webAppPool - - $WebAppHostHeader = $g_webAppHostHeader - $WebAppPort = $g_webAppPort - - $WebAppAppPoolAccount = $g_webAppAppPoolAccount - $WebAppDatabaseName = $g_webAppDatabaseName - $WebAppDatabaseServer = $g_webAppDatabaseServerName - - $WebAppName - $WebAppPort - $WebAppHostHeader - $WebAppAppPool - (Get-SPManagedAccount $WebAppAppPoolAccount) - $WebAppDatabaseName - $WebAppDatabaseServer - - New-SPWebApplication -Name $WebAppName -Port $WebAppPort -HostHeader $WebAppHostHeader -URL $WebAppHostHeader -ApplicationPool $WebAppAppPool -ApplicationPoolAccount (Get-SPManagedAccount $WebAppAppPoolAccount) -DatabaseName $WebAppDatabaseName -DatabaseServer $WebAppDatabaseServer -} - -# ensures security groups on the site -function EnsureSecurityGroup($web, $groupName) { - - $group = $web.SiteGroups[$groupName]; - - if($group -eq $null) { - $web.SiteGroups.Add($groupName, $web.Site.Owner, $web.Site.Owner, $groupName) - $group = $web.SiteGroups[$groupName]; - } - - return $group -} - -# ensures a web app -function EnsureSPMeta2SandboxWebApplication($recreate) { - - $webApp = GetSPMeta2SandboxWebApp $g_webAppUrl - - if($webApp -eq $null) { - - Write-Host "Cannot find web application. at URL:[$g_webAppUrl]. Creating one." -fore yellow - - CreateWebApplication - - } else { - - Write-Host "Web application at URL:[$g_webAppUrl] exists." -fore green - - if($recreate -eq $true) { - if($webApp -ne $null) { - - Write-Host "Deleting web application at URL:[$g_webAppUrl]." -fore yellow - Remove-SPWebApplication $webApp -Confirm:$false - - CreateWebApplication - } - } - - } -} - -function GetSPMeta2SandboxWebApp($url) { - return Get-SPWebApplication | Where-Object { $_.Url.ToUpper().Contains($url.ToUpper()) -eq $true } -} - -function LookupWebSite($url) -{ - $webApp = GetSPMeta2SandboxWebApp $g_webAppUrl - - return $webApp.Sites | Where-Object { $_.Url.ToUpper().EndsWith($url.ToUpper()) -eq $true } -} - -function LookupWeb($site, $url) { - - $web = $site.AllWebs | Where-Object { $_.Url.ToUpper().EndsWith($url.ToUpper()) -eq $true } - - return $web -} - -function CreateWeb( $url) { - - $web = New-SPWeb $url -Template $g_webTemplate - return $web -} - -function CreateSiteCollection($url) { - - $SiteCollectionName = "Root" - $SiteCollectionURL = $url - $SiteCollectionTemplate = $g_siteCollectionTemplate - $SiteCollectionLanguage = $g_siteCollectionLanguage - $SiteCollectionOwner = $g_siteCollectionOwner - - $site = New-SPSite -URL $SiteCollectionURL -OwnerAlias $SiteCollectionOwner -Language $SiteCollectionLanguage -Template $SiteCollectionTemplate -Name $SiteCollectionName - - return $site; -} - -function EnableFeature($web, $id) { - - $f = $web.Features[[guid]$id] - - if($f -eq $null) { - Enable-SPFeature -Identity $id -url $web.Url -Confirm:$false -force - } -} - -function DisableFeature($web, $id) { - - $f = $web.Features[[guid]$id] - - if($f -ne $null) { - Disable-SPFeature -Identity $id -url $web.Url -Confirm:$false -force - } -} - -function EnsureSiteCollectionAdministrators($site, $logins) { - - foreach($login in $logins) { - - Write-Host "`tEnsuring site admin: $login" -ForegroundColor Gray; - - $user = $site.RootWeb.EnsureUser($login); - if($user.IsSiteAdmin -ne $true) - { - $user.IsSiteAdmin = $true; - $user.Update(); - #Write-Host "User is now site collection admin for $site" -ForegroundColor Green; - } - else - { - #Write-Host "User is already site collection admin for $site" -ForegroundColor DarkYellow; - } - - #Write-Host "Current Site Collection Admins for site: " $site.Url " " $site.RootWeb.SiteAdministrators; - } - -} - -function EnsureSPMeta2SandboxSiteCollections($recreate) { - - Write-Host "" - Write-Host "Ensuring sandbox site collections" -fore Green - - $siteUrls = $g_siteUrls - - foreach($url in $siteUrls) { - - $site = LookupWebSite $url - - if($recreate -eq $true) { - - if( $site -ne $null) { - - Write-Host "Deleting site collection [$url]" -fore DarkYellow - - $siteId = $site.ID - - Remove-spsite $siteId -Confirm:$false - - $site = $null - } - } - - if($site -eq $null) { - - Write-Host "Site [$url] does not exist." -fore Gray - Write-Host "Creating site: [$url]" -fore DarkYellow - - $site = CreateSiteCollection $url - } else { - - Write-Host "Site [$url] exists." -fore Gray - - } - - EnsureSiteCollectionAdministrators $site $g_M2WebAppSettings.SiteCollectionAdministrators - EnsureAssociatedGroups $site.RootWeb - - $webUrls = $g_siteRelativeWebUrls - $rootWeb = $site.RootWeb - - # disabling MDS feature - DisableFeature $rootWeb "87294c72-f260-42f3-a41b-981a2ffce37a" - # eabling wiki page lib - EnableFeature $rootWeb "00bfea71-d8fe-4fec-8dad-01c19a6e4053" - - foreach($webUrl in $webUrls) { - - $fullwebUrl = $url + $webUrl - - $web = LookupWeb $site $fullwebUrl - - if($web -eq $null) { - - Write-Host "`tWeb [$fullwebUrl] does not exist." -fore Gray - Write-Host "`tCreating web: [$fullwebUrl]" -fore DarkYellow - - $web = CreateWeb $fullwebUrl - - } else { - - Write-Host "`tWeb [$fullwebUrl] exists." -fore Gray - - } - - Write-Host "Ensuring Associated groups..." - - if($web.HasUniqueRoleAssignments -eq $false) { - $web.RoleDefinitions.BreakInheritance($true,$true); - } - - EnsureAssociatedGroups $web - - DisableFeature $web "87294c72-f260-42f3-a41b-981a2ffce37a" - EnableFeature $web "00bfea71-d8fe-4fec-8dad-01c19a6e4053" - - } - - Write-Host "" - } -} - -function EnsureAssociatedGroups($web) { - - $assOwnerGroup = EnsureSecurityGroup $web "SPMeta2 AssociatedOwnerGroup" - $web.AssociatedOwnerGroup = $assOwnerGroup - - $assMemberGroup = EnsureSecurityGroup $web "SPMeta2 AssociatedMemberGroup" - $web.AssociatedMemberGroup = $assMemberGroup - - $assVisitorGroup = EnsureSecurityGroup $web "SPMeta2 AssociatedVisitorGroup" - $web.AssociatedVisitorGroup = $assVisitorGroup - - $web.Update() - -} - -# test environment settings - -$envType = $g_M2TestEnvironment.EnvironmentType -#$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\O365 - 16.1.3912.1204" -$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\O365 - 16.1.5715.1200\NET45" - -$o365_UserName = $g_M2TestEnvironment.O365UserName -$o365_UserPassword = $g_M2TestEnvironment.O365UserPassword - -$serverName = $g_M2WebAppSettings.MachineName -$sqlServerName = $g_M2WebAppSettings.SqlServerMachineName - -$serverName = [Environment]::MachineName - -function SetSqlServerName($name) -{ - SetEnvironmentVar "SPMeta2_DefaultSqlServerName" $name -} - -function SetTestOnPremTestLogins() -{ - $logins = $g_M2TestEnvironment.OnPremTestActiveDirectoryLogins - $loginsString = [string]::Join(",", $logins); - - SetEnvironmentVar "SPMeta2_DefaultTestUserLogins" $loginsString -} - -function SetTestO365Logins() { - - $logins = $g_M2TestEnvironment.O365DefaultTestUserLogins - $loginsString = [string]::Join(",", $logins); - - SetEnvironmentVar "SPMeta2_DefaultTestUserLogins" $loginsString - -} - -function SetTestOnPremTestADGroups() -{ - $groups = $g_M2TestEnvironment.OnPremTestActiveDirectoryGroups - $groupsString = [string]::Join(",", $groups); - - SetEnvironmentVar "SPMeta2_DefaultTestADGroups" $groupsString -} - -function SetEnvironmentVar($name, $value) { - - Write-Host "`tSetting [$name] - [$value]" -fore Gray - [Environment]::SetEnvironmentVariable($name, $value, "Machine") -} - -function SetSSOMManagedMetadataApplicationParams($siteUrl) { - - $session = Get-SPTaxonomySession -Site $siteUrl - $store = $session.DefaultSiteCollectionTermStore; - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreId" $store.Id - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreName" $store.Name -} - -function SetupSSOMEnvironment() { - - Write-Host "Setting up SSOM environment" -fore Yellow - - - SetTestOnPremTestLogins - SetTestOnPremTestADGroups - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.SSOM.dll" - SetSqlServerName $sqlServerName - - $webAppUrls = $g_M2TestEnvironment.SSOMWebApplicationUrls - $siteUrls = $g_M2TestEnvironment.SSOMSiteUrls - $webUrls = $g_M2TestEnvironment.SSOMWebUrls - - SetSSOMManagedMetadataApplicationParams $siteUrls[0] - - $webAppUrlsValue = $webAppUrls -join ',' - $siteUrlsValue = $siteUrls -join ',' - $webUrlsValue = $webUrls -join ',' - - SetEnvironmentVar "SPMeta2_SSOM_WebApplicationUrls" $webAppUrlsValue - SetEnvironmentVar "SPMeta2_SSOM_SiteUrls" $siteUrlsValue - SetEnvironmentVar "SPMeta2_SSOM_WebUrls" $webUrlsValue -} - -function SetupCSOMEnvironment() { - - - Write-Host "Setting up CSOM environment" -fore Yellow - - SetTestOnPremTestLogins - SetTestOnPremTestADGroups - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.CSOM.dll" - SetSqlServerName $sqlServerName - - $webAppUrls = $g_M2TestEnvironment.CSOMWebApplicationUrls - $siteUrls = $g_M2TestEnvironment.CSOMSiteUrls - $webUrls = $g_M2TestEnvironment.CSOMWebUrls - - SetSSOMManagedMetadataApplicationParams $siteUrls[0] - - $webAppUrlsValue = $webAppUrls -join ',' - $siteUrlsValue = $siteUrls -join ',' - $webUrlsValue = $webUrls -join ',' - - SetEnvironmentVar "SPMeta2_CSOM_SiteUrls" $siteUrlsValue - SetEnvironmentVar "SPMeta2_CSOM_WebUrls" $webUrlsValue - SetEnvironmentVar "SPMeta2_CSOM_UserName" "" - SetEnvironmentVar "SPMeta2_CSOM_Password" "" -} - -function InitO365Runtime() { - $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") - - foreach($filePath in $files) { - Write-Host "`tLoading assembly: [$filePath]" - $a = [System.Reflection.Assembly]::LoadFile($filePath) - } -} - -function SetO365MManagedMetadataApplicationParams($siteUrl) { - - InitO365Runtime - - $secO365_UserPassword = ConvertTo-SecureString $o365_UserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) - - $context.Credentials = $credentials - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreId" $store.Id - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreName" $store.Name -} - -function SetO365RandomBalancedUrls() { - $urls = $g_M2TestEnvironment.RandomBalancedUrls -join ',' - - SetEnvironmentVar "SPMeta2_O365_RandomBalancedUrls" $urls -} - -function SetupO365v16Environment() { - - Write-Host "Setting up O365 environment" -fore Yellow - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.O365v16.dll" - - $o365_siteUrls = $g_M2TestEnvironment.O365SiteUrls - $o365_webUrls = $g_M2TestEnvironment.O365WebUrls - - SetO365MManagedMetadataApplicationParams $o365_siteUrls[0] - - $o365_siteUrlsValue = $o365_siteUrls -join ',' - $o365_webUrlsValue = $o365_webUrls -join ',' - - - SetEnvironmentVar "SPMeta2_O365_SiteUrls" $o365_siteUrlsValue - SetEnvironmentVar "SPMeta2_O365_WebUrls" $o365_webUrlsValue - SetEnvironmentVar "SPMeta2_O365_UserName" $g_M2TestEnvironment.O365UserName - SetEnvironmentVar "SPMeta2_O365_Password" $g_M2TestEnvironment.O365UserPassword -} - -function SetupO365Environment() { - - Write-Host "Setting up O365 environment" -fore Yellow - - SetTestO365Logins - SetO365RandomBalancedUrls - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.O365.dll" - - $o365_siteUrls = $g_M2TestEnvironment.O365SiteUrls - $o365_webUrls = $g_M2TestEnvironment.O365WebUrls - - SetO365MManagedMetadataApplicationParams $o365_siteUrls[0] - - $o365_siteUrlsValue = $o365_siteUrls -join ',' - $o365_webUrlsValue = $o365_webUrls -join ',' - - SetEnvironmentVar "SPMeta2_O365_SiteUrls" $o365_siteUrlsValue - SetEnvironmentVar "SPMeta2_O365_WebUrls" $o365_webUrlsValue - SetEnvironmentVar "SPMeta2_O365_UserName" $g_M2TestEnvironment.O365UserName - SetEnvironmentVar "SPMeta2_O365_Password" $g_M2TestEnvironment.O365UserPassword -} - -function SetupSPMeta2RegressionTestEnvironment($envType) { - - if($envType -eq $null) { - $envType = $g_M2TestEnvironment.EnvironmentType - } - - Write-Host "Setting up [$envType] environment." -fore Green - - switch($envType) - { - "SSOM" { - SetupSSOMEnvironment - } - - "CSOM" { - SetupCSOMEnvironment - } - - "O365" { - SetupO365Environment - } - - "O365v16" { - SetupO365v16Environment - } - } - - Write-Host "Setting up [$envType] environment completed." -fore Green -} diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index 16d36594f..f0d27d060 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -88,6 +88,7 @@ + @@ -355,6 +356,7 @@ SPMeta2.Containers.CSOM.dll + Always SPMeta2.Containers.O365v16.dll @@ -540,6 +542,18 @@ _Dependencies\spmeta2-csom-regression-2013\SPMeta2.Regression.CSOM.dll Always + + SPMeta2.Regression.SSOM.Standard.dll + Always + + + SPMeta2.Regression.SSOM.dll + Always + + + SPMeta2.SSOM.Standard.dll + Always + SPMeta2.SSOM.dll Always @@ -552,8 +566,6 @@ SPMeta2.dll Always - - @@ -573,9 +585,6 @@ - - - Always diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config index f38f061fb..c55a301b3 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config @@ -31,6 +31,7 @@ switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch"> + @@ -41,19 +42,22 @@ initializeData="spmeta2.log"> + diff --git a/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs b/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs index eae4c6e98..9363bc908 100644 --- a/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs +++ b/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs @@ -1,118 +1,121 @@ -using System; -using SPMeta2.Common; -using SPMeta2.Definitions; -using SPMeta2.Services; - -namespace SPMeta2.ModelHandlers -{ - /// - /// Base handler for model provision. - /// - public abstract class ModelHandlerBase - { - #region constructors - - public ModelHandlerBase() - { - TraceService = ServiceContainer.Instance.GetService(); - } - - #endregion - - #region properties - - protected static TraceServiceBase TraceService { get; set; } - - /// - /// Type of the definition which is handled by current model handler. - /// - public abstract Type TargetType { get; } - - #endregion - - #region events - - public EventHandler OnModelEvent; - - #endregion - - #region methods - - /// - /// Handles model provision under particular modelHost. - /// - /// - /// - public virtual void DeployModel(object modelHost, DefinitionBase model) - { - - } - - /// - /// Handles model retraction under particular model host. - /// - /// - /// - public virtual void RetractModel(object modelHost, DefinitionBase model) - { - - } - - /// - /// Resolves a new model host per particular child definition type. - /// - /// - public virtual void WithResolvingModelHost(ModelHostResolveContext context) - { - context.Action(context.ModelHost); - } - - /// - /// Promotes a model event outside of the model handler. - /// - /// - /// - protected void InvokeOnModelEvent(object sender, ModelEventArgs args) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Entering InvokeOnModelEvent with sender: [{0}] and args: [{1}]", - new object[] { sender, args }); - - if (OnModelEvent != null) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, - "OnModelEvent is not NULL. Calling OnModelEvent with sender: [{0}] and args: [{1}]", - new object[] { sender, args }); - - OnModelEvent.Invoke(this, args); - } - else - { - TraceService.Verbose((int)LogEventId.CoreCalls, "OnModelEvent is NULL. Skipping."); - } - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Leaving InvokeOnModelEvent with sender: [{0}] and args: [{1}]", - new object[] { sender, args }); - } - - /// - /// Promotes a model event outside of the model handler. - /// - /// - /// - /// - /// - [Obsolete("Use InvokeOnModelEvents((object sender, ModelEventArgs args) with passing full ModelEventArgs")] - protected void InvokeOnModelEvent(TSPObject rawObject, ModelEventType eventType) - { - InvokeOnModelEvent(this, new ModelEventArgs - { - Object = rawObject, - EventType = eventType - }); - } - - #endregion - - - } -} +using System; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Services.Impl; + +namespace SPMeta2.ModelHandlers +{ + /// + /// Base handler for model provision. + /// + public abstract class ModelHandlerBase + { + #region constructors + + public ModelHandlerBase() + { + TraceService = ServiceContainer.Instance.GetService(); + TryRetryService = ServiceContainer.Instance.GetService() ?? new DefaultTryRetryService(); + } + + #endregion + + #region properties + + protected static TryRetryServiceBase TryRetryService { get; set; } + protected static TraceServiceBase TraceService { get; set; } + + /// + /// Type of the definition which is handled by current model handler. + /// + public abstract Type TargetType { get; } + + #endregion + + #region events + + public EventHandler OnModelEvent; + + #endregion + + #region methods + + /// + /// Handles model provision under particular modelHost. + /// + /// + /// + public virtual void DeployModel(object modelHost, DefinitionBase model) + { + + } + + /// + /// Handles model retraction under particular model host. + /// + /// + /// + public virtual void RetractModel(object modelHost, DefinitionBase model) + { + + } + + /// + /// Resolves a new model host per particular child definition type. + /// + /// + public virtual void WithResolvingModelHost(ModelHostResolveContext context) + { + context.Action(context.ModelHost); + } + + /// + /// Promotes a model event outside of the model handler. + /// + /// + /// + protected void InvokeOnModelEvent(object sender, ModelEventArgs args) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Entering InvokeOnModelEvent with sender: [{0}] and args: [{1}]", + new object[] { sender, args }); + + if (OnModelEvent != null) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, + "OnModelEvent is not NULL. Calling OnModelEvent with sender: [{0}] and args: [{1}]", + new object[] { sender, args }); + + OnModelEvent.Invoke(this, args); + } + else + { + TraceService.Verbose((int)LogEventId.CoreCalls, "OnModelEvent is NULL. Skipping."); + } + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Leaving InvokeOnModelEvent with sender: [{0}] and args: [{1}]", + new object[] { sender, args }); + } + + /// + /// Promotes a model event outside of the model handler. + /// + /// + /// + /// + /// + [Obsolete("Use InvokeOnModelEvents((object sender, ModelEventArgs args) with passing full ModelEventArgs")] + protected void InvokeOnModelEvent(TSPObject rawObject, ModelEventType eventType) + { + InvokeOnModelEvent(this, new ModelEventArgs + { + Object = rawObject, + EventType = eventType + }); + } + + #endregion + + + } +} diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index 69e0f8216..f4388cb1f 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -372,6 +372,7 @@ + @@ -422,6 +423,7 @@ + diff --git a/SPMeta2/SPMeta2/ServiceContainer.cs b/SPMeta2/SPMeta2/ServiceContainer.cs index 2f5daf153..1488763c6 100644 --- a/SPMeta2/SPMeta2/ServiceContainer.cs +++ b/SPMeta2/SPMeta2/ServiceContainer.cs @@ -53,6 +53,8 @@ private void InitServices() RegisterService(typeof(FluentModelValidationServiceBase), new DefaultFluentModelValidationService()); RegisterService(typeof(ModelStatInfoServiceBase), new DefaultModelStatInfoService()); + + RegisterService(typeof(TryRetryServiceBase), new DefaultTryRetryService()); } #endregion diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs new file mode 100644 index 000000000..b63799e35 --- /dev/null +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + + +namespace SPMeta2.Services.Impl +{ + public class DefaultTryRetryService : TryRetryServiceBase + { + #region constructors + + public DefaultTryRetryService() + { + MaxRetryCount = 10; + RetryTimeoutInMilliseconds = 1000; + + DefaultRetryWaiter = (currentRetryIndex, maxRetryIndex, defaultTimeoutInMilliseconds) => + { + Thread.Sleep(defaultTimeoutInMilliseconds); + }; + } + + #endregion + + #region properties + + public int MaxRetryCount { get; set; } + public int RetryTimeoutInMilliseconds { get; set; } + + public Action DefaultRetryWaiter { get; set; } + protected TraceServiceBase TraceService + { + get + { + return ServiceContainer.Instance.GetService(); + } + } + + #endregion + + public override void TryWithRetry(Func action) + { + TryWithRetry(action, MaxRetryCount, RetryTimeoutInMilliseconds); + } + + public override void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds) + { + TryWithRetry(action, maxTryCount, retryTimeoutInMilliseconds, this.DefaultRetryWaiter); + } + + public override void TryWithRetry(Func action, + int maxTryCount, int retryTimeoutInMilliseconds, + Action waiter) + { + var currentTryIndex = 0; + + while (action() != true) + { + TraceService.Warning((int)LogEventId.ModelProvision, + string.Format("Coudn't perform action. Waiting and retrying [{1}/{2}]", + RetryTimeoutInMilliseconds, + currentTryIndex, + MaxRetryCount)); + + if (currentTryIndex > retryTimeoutInMilliseconds) + break; + + waiter(currentTryIndex, maxTryCount, retryTimeoutInMilliseconds); + currentTryIndex++; + } + } + } +} diff --git a/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs b/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs index dcb685e9b..648334f4c 100644 --- a/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs @@ -132,7 +132,7 @@ public override void Verbose(int id, object message, Exception exception) #region utils - protected virtual void TraceEvent(int id, TraceEventType messageType, object message, Exception exception) + protected virtual string GetTraceEventString(int id, TraceEventType messageType, object message, Exception exception) { var traceString = string.Empty; var messageString = message == null ? string.Empty : message.ToString(); @@ -156,8 +156,14 @@ protected virtual void TraceEvent(int id, TraceEventType messageType, object mes traceString = string.Format("{0}", subMessage); } - TraceSource.TraceEvent(messageType, id, traceString); + return traceString; + } + protected virtual void TraceEvent(int id, TraceEventType messageType, object message, Exception exception) + { + var traceString = GetTraceEventString(id, messageType, message, exception); + + TraceSource.TraceEvent(messageType, id, traceString); if (AutoFlush) { diff --git a/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs new file mode 100644 index 000000000..01119f91b --- /dev/null +++ b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + + +namespace SPMeta2.Services +{ + public abstract class TryRetryServiceBase + { + #region properties + + #endregion + + #region methods + + public abstract void TryWithRetry(Func action); + public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds); + public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter); + + #endregion + } +} From e9b6fa651b429bf03d8a24e076d8a07c62d4b68e Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 10:08:53 -0700 Subject: [PATCH 40/53] + Simplify incremental provision usage #1005 --- .../SPMeta2/Extensions/ModelNodeExtensions.cs | 2 +- ...crementalProvisionServiceBaseExtensions.cs | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs index 9dda48707..e9b978142 100644 --- a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs +++ b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs @@ -324,7 +324,7 @@ public static bool GetIncrementalRequireSelfProcessingValue(this TMo return false; } - private static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) + internal static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) where TModelNode : ModelNode { modelNode.SetPropertyBagValue(DefaultModelNodePropertyBagValue.Sys.IncrementalProvision.PersistenceStorageModelId, modelId); diff --git a/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs index 321aa9f68..328e6c857 100644 --- a/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs +++ b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs @@ -7,6 +7,9 @@ using SPMeta2.Definitions; using SPMeta2.Common; using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using SPMeta2.Extensions; namespace SPMeta2.Services { @@ -86,5 +89,64 @@ private static DefaultIncrementalModelTreeTraverseService GetIncrementalModelTra } #endregion + + #region deployment helpers + + /// + /// A shortcut for incremental provision + /// Sets incremental provision mode with AutoDetectSharePointPersistenceStorage = true + /// Once done, reverts back to default provision mode + /// + /// + /// + /// + /// + public static void DeployModelIncrementally(this ProvisionServiceBase provisionService, + ModelHostBase modelHost, + ModelNode model, + string incrementalModelId) + { + DeployModelIncrementally(provisionService, modelHost, model, incrementalModelId, null); + } + + /// + /// A shortcut for incremental provision + /// Sets incremental provision mode with IncrementalProvisionConfig.AutoDetectSharePointPersistenceStorage = true + /// Once done, reverts back to default provision mode + /// Callback on IncrementalProvisionConfig makes it easy to configure IncrementalProvisionConfig instance + /// + /// + /// + /// + /// + /// + public static void DeployModelIncrementally(this ProvisionServiceBase provisionService, + ModelHostBase modelHost, + ModelNode model, + string incrementalModelId, + Action config) + { + try + { + var incrementalProvisionConfig = new IncrementalProvisionConfig + { + AutoDetectSharePointPersistenceStorage = true + }; + + if (config != null) + config(incrementalProvisionConfig); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + model.InternalSetIncrementalProvisionModelId(incrementalModelId); + + provisionService.DeployModel(modelHost, model); + } + finally + { + provisionService.SetDefaultProvisionMode(); + } + } + + #endregion } } \ No newline at end of file From 17d81acdb4763ddce2d731ab699624661c785ba9 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 10:12:40 -0700 Subject: [PATCH 41/53] + NET35 build fix --- .../Taxonomy/TaxonomyTermModelHandler.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index d324103df..99c6fdbb5 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -198,8 +198,10 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode var serverException = e as ServerException; if (serverException != null - && serverException.HResult == -2146233088 - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") +#if !NET35 + && serverException.HResult == -2146233088 +#endif + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); @@ -403,8 +405,10 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, var serverException = e as ServerException; if (serverException != null - && serverException.HResult == -2146233088 - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") +#if !NET35 + && serverException.HResult == -2146233088 +#endif + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); From 2a789fc264571233f5e4f2b7b4f5f73af65a5c2a Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 10:25:22 -0700 Subject: [PATCH 42/53] .NET35 build fix --- .../Taxonomy/TaxonomyTermModelHandler.cs | 12 ++++------ SPMeta2/SPMeta2/Utils/ReflectionUtils.cs | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index 99c6fdbb5..8e79e5764 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -198,10 +198,8 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode var serverException = e as ServerException; if (serverException != null -#if !NET35 - && serverException.HResult == -2146233088 -#endif - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + && ReflectionUtils.GetHResultValue(serverException).Value == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); @@ -405,10 +403,8 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, var serverException = e as ServerException; if (serverException != null -#if !NET35 - && serverException.HResult == -2146233088 -#endif - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + && ReflectionUtils.GetHResultValue(serverException).Value == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); diff --git a/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs b/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs index 60ff6dbcc..8886d8651 100644 --- a/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs +++ b/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs @@ -303,6 +303,29 @@ public static bool HasPropertyPublicSetter(object obj, string propName) return false; } + public static int? GetHResultValue(Exception exception) + { + // .net 4 hack to get HResult + var hResultProp = exception.GetType() + .GetProperty("HResult", + BindingFlags.NonPublic + | BindingFlags.Public + | BindingFlags.Instance + | BindingFlags.Static); + + + if (hResultProp != null) + { + var hResultValue = hResultProp.GetValue(exception, null); + if (hResultValue is int) + { + return (int)hResultValue; + } + } + + return null; + } + #endregion } } From ed5afca68b25c186b389168dc4ac3999a4466902 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 23:15:11 -0700 Subject: [PATCH 43/53] + SSOM regression on content types + Broken field links operation in content types #1006 --- SPMeta2/Regression/Regression.csproj | 1 + .../Regression/_ut_grid_baseline_config.ps1 | 36 ++ SPMeta2/Regression/config.yaml | 15 +- ...ContentTypeFieldLinkDefinitionValidator.cs | 111 +++--- ...ontentTypeFieldLinksDefinitionValidator.cs | 50 +-- ...ontentTypeFieldLinksDefinitionValidator.cs | 6 +- ...ntentTypeFieldsOrderDefinitionValidator.cs | 6 +- .../SecurityGroupDefinitionValidator.cs | 22 +- .../ContentTypeLinkScenariousTest.cs | 334 +++++++++--------- .../Scenarios/DocumentSetScenariosTest.cs | 40 ++- .../Impl/Scenarios/SecurityScenariosTest.cs | 33 +- .../WorkflowAssociationScenariosTest.cs | 54 ++- .../ContentTypeFieldLinkModelHandler.cs | 11 +- .../ContentTypeLinkModelHandler.cs | 2 +- .../ModelHandlers/ContentTypeModelHandler.cs | 6 +- .../HideContentTypeFieldLinksModelHandler.cs | 23 +- ...RemoveContentTypeFieldLinksModelHandler.cs | 23 +- ...niqueContentTypeFieldsOrderModelHandler.cs | 22 +- .../ModelHandlers/ListModelHandler.cs | 7 +- .../WorkflowAssociationModelHandler.cs | 32 +- .../ModelHosts/ContentTypeLinkModelHost.cs | 29 ++ .../ModelHosts/ContentTypeModelHost.cs | 3 +- SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj | 3 +- 23 files changed, 550 insertions(+), 319 deletions(-) create mode 100644 SPMeta2/Regression/_ut_grid_baseline_config.ps1 create mode 100644 SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs diff --git a/SPMeta2/Regression/Regression.csproj b/SPMeta2/Regression/Regression.csproj index 4fc9d415d..0f78e5d1f 100644 --- a/SPMeta2/Regression/Regression.csproj +++ b/SPMeta2/Regression/Regression.csproj @@ -43,6 +43,7 @@ + diff --git a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 new file mode 100644 index 000000000..a66393457 --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 @@ -0,0 +1,36 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +foreach($server in $dsc_nodeNames) { + + Write-Host "Configuring server [$server]" -fore Green + + Invoke-Command -ScriptBlock { + + + Write-Host "Updating SharePoint ULS settings..." + + add-pssnapin microsoft.sharepoint.powershell + Set-SPDiagnosticConfig -LogMaxDiskSpaceUsageEnabled + Set-SPDiagnosticConfig -LogDiskSpaceUsageGB 1 + + Write-Host "Updating SQL settings..." + + [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null + $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server + + #$s.Configuration.MinServerMemory.ConfigValue = 3 * 1024 + $s.Configuration.MaxServerMemory.ConfigValue = 3 * 1024 + $s.Configuration.Alter() + + Write-Host "Restarting services..." + + Restart-Service MSSQLSERVER -Force + Restart-Service sptimerv4 -Force + + iisreset + + } -computer $server +} \ No newline at end of file diff --git a/SPMeta2/Regression/config.yaml b/SPMeta2/Regression/config.yaml index 261b32709..09d9c6568 100644 --- a/SPMeta2/Regression/config.yaml +++ b/SPMeta2/Regression/config.yaml @@ -62,4 +62,17 @@ - SSOM #- CSOM #- O365 - #- O365v16 \ No newline at end of file + #- O365v16 + TestData: + UserLogins: + # test user logins to be used with security related tests + # must not be same account under which tests are run + - dev\user1 + - dev\user2 + ActiveDirectoryGroups: + # test group user logins to be used with security related tests + - dev\group1 + - dev\group2 + DomainUserEmails: + - user1@dev.local + - user2@dev.local \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs index 528c2495a..348f5728f 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs @@ -1,54 +1,57 @@ -using System.Diagnostics; -using Microsoft.SharePoint; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.SSOM.ModelHandlers; -using SPMeta2.Utils; - - -namespace SPMeta2.Regression.SSOM.Validation -{ - public class ContentTypeFieldLinkDefinitionValidator : ContentTypeFieldLinkModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var spModel = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var spObject = FindExistingFieldLink(spModel, definition); - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject); - - //.ShouldBeEqual(m => m.FieldId, o => o.Id); - - if (!string.IsNullOrEmpty(definition.FieldInternalName)) - assert.ShouldBeEqual(m => m.FieldInternalName, o => o.Name); - else - assert.SkipProperty(m => m.FieldInternalName, "FieldInternalName is NULL or empty. Skipping."); - - if (definition.FieldId.HasGuidValue()) - assert.ShouldBeEqual(m => m.FieldId, o => o.Id); - else - assert.SkipProperty(m => m.FieldId, "FieldId is NULL. Skipping."); - - - if (!string.IsNullOrEmpty(definition.DisplayName)) - assert.ShouldBeEqual(m => m.DisplayName, o => o.DisplayName); - else - assert.SkipProperty(m => m.DisplayName, "DisplayName is NULL or empty. Skipping."); - - if (definition.Required.HasValue) - assert.ShouldBeEqual(m => m.Required, o => o.Required); - else - assert.SkipProperty(m => m.Required, "Required is NULL. Skipping."); - - if (definition.Hidden.HasValue) - assert.ShouldBeEqual(m => m.Hidden, o => o.Hidden); - else - assert.SkipProperty(m => m.Hidden, "Hidden is NULL. Skipping."); - } - } -} +using System.Diagnostics; +using Microsoft.SharePoint; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.SSOM.ModelHandlers; +using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; + + +namespace SPMeta2.Regression.SSOM.Validation +{ + public class ContentTypeFieldLinkDefinitionValidator : ContentTypeFieldLinkModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spModel = typedModelhost.HostContentType; + + var spObject = FindExistingFieldLink(spModel, definition); + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject); + + //.ShouldBeEqual(m => m.FieldId, o => o.Id); + + if (!string.IsNullOrEmpty(definition.FieldInternalName)) + assert.ShouldBeEqual(m => m.FieldInternalName, o => o.Name); + else + assert.SkipProperty(m => m.FieldInternalName, "FieldInternalName is NULL or empty. Skipping."); + + if (definition.FieldId.HasGuidValue()) + assert.ShouldBeEqual(m => m.FieldId, o => o.Id); + else + assert.SkipProperty(m => m.FieldId, "FieldId is NULL. Skipping."); + + + if (!string.IsNullOrEmpty(definition.DisplayName)) + assert.ShouldBeEqual(m => m.DisplayName, o => o.DisplayName); + else + assert.SkipProperty(m => m.DisplayName, "DisplayName is NULL or empty. Skipping."); + + if (definition.Required.HasValue) + assert.ShouldBeEqual(m => m.Required, o => o.Required); + else + assert.SkipProperty(m => m.Required, "Required is NULL. Skipping."); + + if (definition.Hidden.HasValue) + assert.ShouldBeEqual(m => m.Hidden, o => o.Hidden); + else + assert.SkipProperty(m => m.Hidden, "Hidden is NULL. Skipping."); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs index 77dc6dda8..ebddd8d46 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs @@ -1,24 +1,26 @@ -using Microsoft.SharePoint; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Definitions.ContentTypes; -using SPMeta2.SSOM.ModelHandlers; -using SPMeta2.SSOM.ModelHandlers.ContentTypes; -using SPMeta2.SSOM.ModelHosts; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.SSOM.Validation.ContentTypes -{ - public class HideContentTypeFieldLinksDefinitionValidator : HideContentTypeFieldLinksModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = modelHost as SPContentType; - - ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject); - } - } -} +using Microsoft.SharePoint; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Definitions.ContentTypes; +using SPMeta2.SSOM.ModelHandlers; +using SPMeta2.SSOM.ModelHandlers.ContentTypes; +using SPMeta2.SSOM.ModelHosts; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.SSOM.Validation.ContentTypes +{ + public class HideContentTypeFieldLinksDefinitionValidator : HideContentTypeFieldLinksModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = typedModelhost.HostContentType; + + ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs index 9018cf506..253238a2f 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs @@ -13,8 +13,10 @@ public class RemoveContentTypeFieldLinksDefinitionValidator : RemoveContentTypeF { public override void DeployModel(object modelHost, DefinitionBase model) { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = modelHost as SPContentType; + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = typedModelhost.HostContentType; ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs index 22ccc324c..50c761abd 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs @@ -16,8 +16,10 @@ public class UniqueContentTypeFieldsOrderDefinitionValidator : UniqueContentType { public override void DeployModel(object modelHost, DefinitionBase model) { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = modelHost as SPContentType; + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = typedModelhost.HostContentType; var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs index 53abbd9e1..7a875bd41 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs @@ -14,6 +14,16 @@ namespace SPMeta2.Regression.SSOM.Validation { public class SecurityGroupDefinitionValidator : SecurityGroupModelHandler { + protected string GetSafeUserLoging(string userLoginString) + { + var result = userLoginString.ToString().ToUpper().Replace("\\", "/"); + + if (result.Contains("|")) + result = result.Split('|')[1]; + + return result; + } + public override void DeployModel(object modelHost, DefinitionBase model) { if (modelHost is SiteModelHost) @@ -61,9 +71,10 @@ public override void DeployModel(object modelHost, DefinitionBase model) var srcProp = s.GetExpressionValue(def => def.Owner); var dstProp = d.GetExpressionValue(ct => ct.GetOwnerLogin()); - var isValid = srcProp.Value.ToString().ToUpper().Replace("\\", "/") == - dstProp.Value.ToString().ToUpper().Replace("\\", "/"); + var srcUserLogin = GetSafeUserLoging(srcProp.Value.ToString()); + var dstsUserLogin = GetSafeUserLoging(dstProp.Value.ToString()); + var isValid = srcUserLogin == dstsUserLogin; return new PropertyValidationResult { @@ -93,8 +104,11 @@ public override void DeployModel(object modelHost, DefinitionBase model) foreach (var userName in userNames) { - if (srcProp.Value.ToString().ToUpper().Replace("\\", "/") == - userName.ToString().ToUpper().Replace("\\", "/")) + + var srcUserLogin = GetSafeUserLoging(srcProp.Value.ToString()); + var dstsUserLogin = GetSafeUserLoging(userName); + + if (srcUserLogin == dstsUserLogin) { isValid = true; break; diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs index 0d796c2ca..b02a60aae 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs @@ -1,162 +1,172 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Regression.Tests.Base; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SPMeta2.Containers; -using SPMeta2.Definitions; -using SPMeta2.Enumerations; -using SPMeta2.Syntax.Default; - - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class ContentTypeLinkScenariousTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanupAttribute] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region default - - [TestMethod] - [TestCategory("Regression.Scenarios.ContentTypeLinks.Scopes")] - public void CanDeploy_ContentTypeLink_With_SiteAndWebContentTypes() - { - var siteContentType = ModelGeneratorService.GetRandomDefinition(); - var webContentType = ModelGeneratorService.GetRandomDefinition(); - - var webList = ModelGeneratorService.GetRandomDefinition(def => - { - def.ContentTypesEnabled = true; - }); - - var siteModel = SPMeta2Model.NewSiteModel(site => - { - site.AddContentType(siteContentType); - }); - - var webModel = SPMeta2Model.NewWebModel(web => - { - web.AddRandomWeb(subWeb => - { - subWeb.AddContentType(webContentType); - - subWeb.AddList(webList, list => - { - list.AddContentTypeLink(siteContentType); - list.AddContentTypeLink(webContentType); - }); - }); - }); - - TestModel(siteModel, webModel); - } - - #endregion - - #region read-only and sealed content types - - [TestMethod] - [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] - public void CanDeploy_ContentTypeLink_As_CTH_Item_ContentType() - { - if (!TestOptions.EnableContentTypeHubTests) - return; - - WithDisabledPropertyUpdateValidation(() => - { - var listDef = ModelGeneratorService.GetRandomDefinition(def => - { - def.TemplateType = BuiltInListTemplateTypeId.GenericList; - def.ContentTypesEnabled = true; - }); - - var ctLinkDef1 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-item-1", - ContentTypeId = "0x01000FF176352927C44BB2DB4FBF2F30E88F" - }; - - var ctLinkDef2 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-item-2", - ContentTypeId = "0x010072398EFE7B102948B9BEE545225CA462" - }; - - var webModel = SPMeta2Model.NewWebModel(web => - { - web.AddList(listDef, list => - { - list.AddContentTypeLink(ctLinkDef1); - //list.AddContentTypeLink(ctLinkDef2); - }); - }); - - TestModel(webModel); - }); - } - - - [TestMethod] - [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] - public void CanDeploy_ContentTypeLink_As_CTH_Document_ContentType() - { - if (!TestOptions.EnableContentTypeHubTests) - return; - - WithDisabledPropertyUpdateValidation(() => - { - var listDef = ModelGeneratorService.GetRandomDefinition(def => - { - def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; - def.ContentTypesEnabled = true; - }); - - var ctLinkDef1 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-doc-1", - ContentTypeId = "0x01010021C1A5D40722E14591426E165F107547" - }; - - var ctLinkDef2 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-doc-2", - ContentTypeId = "0x010100429E2FB078A6984385E2531F073EA963" - }; - - var webModel = SPMeta2Model.NewWebModel(web => - { - web.AddList(listDef, list => - { - list.AddContentTypeLink(ctLinkDef1); - //list.AddContentTypeLink(ctLinkDef2); - }); - }); - - TestModel(webModel); - }); - } - - #endregion - - #region content type hub - - #endregion - } -} +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Regression.Tests.Base; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SPMeta2.Containers; +using SPMeta2.Definitions; +using SPMeta2.Enumerations; +using SPMeta2.Syntax.Default; + + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class ContentTypeLinkScenariousTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanupAttribute] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region default + + [TestMethod] + [TestCategory("Regression.Scenarios.ContentTypeLinks.Scopes")] + public void CanDeploy_ContentTypeLink_With_SiteAndWebContentTypes() + { + var siteContentType = ModelGeneratorService.GetRandomDefinition(); + var webContentType = ModelGeneratorService.GetRandomDefinition(); + + var webList = ModelGeneratorService.GetRandomDefinition(def => + { + def.ContentTypesEnabled = true; + }); + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddContentType(siteContentType); + }); + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(f => + { + f.Enable = true; + })); + + web.AddRandomWeb(subWeb => + { + subWeb.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(f => + { + f.Enable = true; + })); + + subWeb.AddContentType(webContentType); + + subWeb.AddList(webList, list => + { + list.AddContentTypeLink(siteContentType); + list.AddContentTypeLink(webContentType); + }); + }); + }); + + TestModel(siteModel, webModel); + } + + #endregion + + #region read-only and sealed content types + + [TestMethod] + [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] + public void CanDeploy_ContentTypeLink_As_CTH_Item_ContentType() + { + if (!TestOptions.EnableContentTypeHubTests) + return; + + WithDisabledPropertyUpdateValidation(() => + { + var listDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.TemplateType = BuiltInListTemplateTypeId.GenericList; + def.ContentTypesEnabled = true; + }); + + var ctLinkDef1 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-item-1", + ContentTypeId = "0x01000FF176352927C44BB2DB4FBF2F30E88F" + }; + + var ctLinkDef2 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-item-2", + ContentTypeId = "0x010072398EFE7B102948B9BEE545225CA462" + }; + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddList(listDef, list => + { + list.AddContentTypeLink(ctLinkDef1); + //list.AddContentTypeLink(ctLinkDef2); + }); + }); + + TestModel(webModel); + }); + } + + + [TestMethod] + [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] + public void CanDeploy_ContentTypeLink_As_CTH_Document_ContentType() + { + if (!TestOptions.EnableContentTypeHubTests) + return; + + WithDisabledPropertyUpdateValidation(() => + { + var listDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; + def.ContentTypesEnabled = true; + }); + + var ctLinkDef1 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-doc-1", + ContentTypeId = "0x01010021C1A5D40722E14591426E165F107547" + }; + + var ctLinkDef2 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-doc-2", + ContentTypeId = "0x010100429E2FB078A6984385E2531F073EA963" + }; + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddList(listDef, list => + { + list.AddContentTypeLink(ctLinkDef1); + //list.AddContentTypeLink(ctLinkDef2); + }); + }); + + TestModel(webModel); + }); + } + + #endregion + + #region content type hub + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs index fea1d87dc..e18a7ccf5 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs @@ -59,6 +59,14 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeId() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -68,7 +76,7 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeId() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -87,6 +95,14 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeId() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -100,7 +116,7 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeId() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -119,6 +135,14 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeName() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -129,7 +153,7 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeName() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -148,6 +172,14 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeName() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -161,7 +193,7 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeName() }); }); - TestModel(model); + TestModel(siteModel, model); } #endregion diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs index ffe602331..f277d0bac 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs @@ -1163,23 +1163,22 @@ public void CanDeploy_SecurityGroupLink_ByIsAssociatedMemberGroup() { var securityGroup = ModelGeneratorService.GetRandomDefinition(); - var webModel = SPMeta2Model - .NewWebModel(web => - { - web.AddRandomWeb(rndWeb => - { - rndWeb.AddRandomList(rndList => - { - rndList.AddRandomListItem(rndListItem => - { - rndListItem.AddSecurityGroupLink(new SecurityGroupLinkDefinition - { - IsAssociatedMemberGroup = true - }); - }); - }); - }); - }); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddRandomWeb(rndWeb => + { + rndWeb.AddRandomList(rndList => + { + rndList.AddRandomListItem(rndListItem => + { + rndListItem.AddSecurityGroupLink(new SecurityGroupLinkDefinition + { + IsAssociatedMemberGroup = true + }); + }); + }); + }); + }); TestModels(new ModelNode[] { webModel }); diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs index 25f0464b0..1355996e4 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs @@ -97,6 +97,11 @@ public void CanDeploy_WorkflowAssociation_UnderWeb() def.AssociationData = Rnd.String(); }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + AddDefaultWorkflowFeatures(site); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(taskList); @@ -106,7 +111,7 @@ public void CanDeploy_WorkflowAssociation_UnderWeb() web.AddWorkflowAssociation(workflowDefChanges); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -144,6 +149,11 @@ public void CanDeploy_WorkflowAssociation_UnderList() def.AssociationData = Rnd.String(); }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + AddDefaultWorkflowFeatures(site); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(taskList); @@ -156,7 +166,7 @@ public void CanDeploy_WorkflowAssociation_UnderList() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -203,6 +213,7 @@ public void CanDeploy_WorkflowAssociation_UnderContentTypeLink() var siteModel = SPMeta2Model.NewSiteModel(site => { site.AddContentType(contentTypeDef); + AddDefaultWorkflowFeatures(site); }); var model = SPMeta2Model.NewWebModel(web => @@ -223,6 +234,35 @@ public void CanDeploy_WorkflowAssociation_UnderContentTypeLink() TestModel(siteModel, model); } + private void AddDefaultWorkflowFeatures(SiteModelNode site) + { + site.AddSiteFeature(BuiltInSiteFeatures.Workflows.Inherit(f => + { + f.Enable = true; + })); + + site.AddSiteFeature(BuiltInSiteFeatures.SharePoint2007Workflows.Inherit(f => + { + f.Enable = true; + })); + + //site.AddSiteFeature(BuiltInSiteFeatures.DispositionApprovalWorkflow.Inherit(f => + //{ + // f.Enable = true; + //})); + + //site.AddSiteFeature(BuiltInSiteFeatures.PublishingApprovalWorkflow.Inherit(f => + //{ + // f.Enable = true; + //})); + + //site.AddSiteFeature(BuiltInSiteFeatures.ThreeStateWorkflow.Inherit(f => + //{ + // f.Enable = true; + //})); + } + + [TestMethod] [TestCategory("Regression.Scenarios.WorkflowAssociation")] @@ -249,6 +289,11 @@ public void CanDeploy_WorkflowAssociation_UnderContentType() def.HistoryListTitle = historyList.Title; }); + var initialSiteModel = SPMeta2Model.NewSiteModel(site => + { + AddDefaultWorkflowFeatures(site); + }); + // changability // deploy the same association with different props var workflowDefChanges = workflowDef.Inherit(def => @@ -279,7 +324,10 @@ public void CanDeploy_WorkflowAssociation_UnderContentType() }); }); - TestModel(webModel, siteModel); + TestModels(new ModelNode[] { + initialSiteModel, + webModel, + siteModel }); } } } diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs index f8610ed30..adda91ff2 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs @@ -7,7 +7,8 @@ using SPMeta2.Definitions.Base; using SPMeta2.ModelHandlers; using SPMeta2.Services; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; namespace SPMeta2.SSOM.ModelHandlers { @@ -66,9 +67,11 @@ protected SPField FindAvailableField(SPWeb web, ContentTypeFieldLinkDefinition l public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeFieldLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var typedModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeFieldLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var contentType = typedModelHost.HostContentType; var web = contentType.ParentWeb; diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs index 0baa65d1e..0db546618 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs @@ -63,7 +63,7 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon action(contentTypeLinkHost); - if (!contentTypeLinkHost.ShouldUpdateHost) + if (contentTypeLinkHost.ShouldUpdateHost) contentType.Update(false); } diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs index 3b54023c4..39115acaa 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs @@ -10,6 +10,7 @@ using SPMeta2.SSOM.ModelHosts; using SPMeta2.Syntax.Default; using SPMeta2.Utils; +using SPMeta2.ModelHosts; namespace SPMeta2.SSOM.ModelHandlers { @@ -53,7 +54,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon } else { - action(targetContentType); + action(ModelHostBase.Inherit(modelHost as ModelHostBase, host => + { + host.HostContentType = targetContentType; + })); } targetContentType.Update(true); diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs index 2623211e0..b5c02d002 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs @@ -26,15 +26,16 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployHideContentTypeLinks(modelHost, contentType, hideContentTypeFieldLinksDefinition); - } - - private void DeployHideContentTypeLinks(object modelHost, SPContentType contentType, HideContentTypeFieldLinksDefinition hideFieldLinksModel) - { + { + var typedModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployHideContentTypeLinks(modelHost, typedModelHost, hideContentTypeFieldLinksDefinition); + } + + private void DeployHideContentTypeLinks(object modelHost, ContentTypeModelHost contentTypeModelHost, HideContentTypeFieldLinksDefinition hideFieldLinksModel) + { + var contentType = contentTypeModelHost.HostContentType; var fieldLinks = contentType.FieldLinks.OfType().ToList(); InvokeOnModelEvent(this, new ModelEventArgs @@ -76,7 +77,9 @@ private void DeployHideContentTypeLinks(object modelHost, SPContentType contentT ObjectType = typeof(SPContentType), ObjectDefinition = hideFieldLinksModel, ModelHost = modelHost - }); + }); + + contentTypeModelHost.ShouldUpdateHost = true; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs index cc41fd811..4e45548e0 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs @@ -26,15 +26,16 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployHideContentTypeLinks(modelHost, contentType, hideContentTypeFieldLinksDefinition); - } - - private void DeployHideContentTypeLinks(object modelHost, SPContentType contentType, RemoveContentTypeFieldLinksDefinition hideFieldLinksModel) - { + { + var typedModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployHideContentTypeLinks(modelHost, typedModelHost, hideContentTypeFieldLinksDefinition); + } + + private void DeployHideContentTypeLinks(object modelHost, ContentTypeModelHost contentTypeModelHost, RemoveContentTypeFieldLinksDefinition hideFieldLinksModel) + { + var contentType = contentTypeModelHost.HostContentType; var fieldLinks = contentType.FieldLinks.OfType().ToList(); InvokeOnModelEvent(this, new ModelEventArgs @@ -74,7 +75,9 @@ private void DeployHideContentTypeLinks(object modelHost, SPContentType contentT ObjectType = typeof(SPContentType), ObjectDefinition = hideFieldLinksModel, ModelHost = modelHost - }); + }); + + contentTypeModelHost.ShouldUpdateHost = true; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs index 3e2bb948c..cf759bfc6 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs @@ -26,15 +26,17 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); ; - var contentTypeOrderDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployContentTypeOrder(modelHost, contentType, contentTypeOrderDefinition); - } + { + var typedModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); ; + var contentTypeOrderDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployContentTypeOrder(modelHost, typedModelHost, contentTypeOrderDefinition); + } + + private void DeployContentTypeOrder(object modelHost, ContentTypeModelHost contentTypeModellHost, UniqueContentTypeFieldsOrderDefinition reorderFieldLinksModel) + { + var contentType = contentTypeModellHost.HostContentType; - private void DeployContentTypeOrder(object modelHost, SPContentType contentType, UniqueContentTypeFieldsOrderDefinition reorderFieldLinksModel) - { var fieldLinks = contentType.FieldLinks.OfType().ToList(); var fields = contentType.Fields.OfType().ToList(); @@ -84,7 +86,9 @@ private void DeployContentTypeOrder(object modelHost, SPContentType contentType, ObjectType = typeof(SPContentType), ObjectDefinition = reorderFieldLinksModel, ModelHost = modelHost - }); + }); + + contentTypeModellHost.ShouldUpdateHost = true; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs index 8ff788e7e..326b066cc 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs @@ -12,6 +12,7 @@ using SPMeta2.SSOM.ModelHandlers.Base; using SPMeta2.SSOM.ModelHosts; using SPMeta2.Utils; +using SPMeta2.ModelHosts; namespace SPMeta2.SSOM.ModelHandlers { @@ -314,10 +315,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var list = hostList ?? web.GetList(SPUtility.ConcatUrls(web.ServerRelativeUrl, listDefinition.GetListUrl())); #pragma warning restore 618 - var listModelHost = new ListModelHost + var listModelHost = ModelHostBase.Inherit(modelHost as ModelHostBase, host => { - HostList = list - }; + host.HostList = list; + }); if (childModelType == typeof(ModuleFileDefinition)) { diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs index f82daef77..f1d7db862 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs @@ -51,11 +51,19 @@ public override void DeployModel(object modelHost, DefinitionBase model) } else if (modelHost is ContentTypeLinkModelHost) { - var contentType = (modelHost as ContentTypeLinkModelHost).HostContentType; + var contentTypeLinkMpodelHost = (modelHost as ContentTypeLinkModelHost); + var contentType = contentTypeLinkMpodelHost.HostContentType; DeployContentTypeWorkflowAssociationDefinition(contentType, contentType, workflowAssociationModel); + + contentTypeLinkMpodelHost.ShouldUpdateHost = false; } + else if (modelHost is ContentTypeModelHost) + { + var contentType = (modelHost as ContentTypeModelHost).HostContentType; + DeployContentTypeWorkflowAssociationDefinition(contentType, contentType, workflowAssociationModel); + } else { throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); @@ -80,6 +88,12 @@ private SPWeb GetWebFromModelHost(object modelHost) return (modelHost as SPContentType).ParentWeb; } + + if (modelHost is ContentTypeModelHost) + { + return (modelHost as ContentTypeModelHost).HostWeb; + } + if (modelHost is ContentTypeLinkModelHost) { return (modelHost as ContentTypeLinkModelHost).HostWeb; @@ -97,22 +111,22 @@ protected SPWorkflowAssociation FindExistringWorkflowAssotiation(object modelHos return list.WorkflowAssociations .GetAssociationByName(def.Name, list.ParentWeb.UICulture); } - if (modelHost is WebModelHost) + else if (modelHost is WebModelHost) { var web = (modelHost as WebModelHost).HostWeb; return web.WorkflowAssociations .GetAssociationByName(def.Name, web.UICulture); } - if (modelHost is SPContentType) + else if (modelHost is SPContentType) { var contentType = (modelHost as SPContentType); var web = contentType.ParentWeb; return contentType.WorkflowAssociations - .GetAssociationByName(def.Name, web.UICulture); + .GetAssociationByName(def.Name, web.UICulture); } - if (modelHost is ContentTypeLinkModelHost) + else if (modelHost is ContentTypeLinkModelHost) { var listContentTypeHost = (modelHost as ContentTypeLinkModelHost); @@ -126,6 +140,14 @@ protected SPWorkflowAssociation FindExistringWorkflowAssotiation(object modelHos return contentType.WorkflowAssociations .GetAssociationByName(def.Name, web.UICulture); } + else if (modelHost is ContentTypeModelHost) + { + var contentType = (modelHost as ContentTypeModelHost).HostContentType; + var web = contentType.ParentWeb; + + return contentType.WorkflowAssociations + .GetAssociationByName(def.Name, web.UICulture); + } else { throw new SPMeta2NotImplementedException( diff --git a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs new file mode 100644 index 000000000..cf2013f17 --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint; + +namespace SPMeta2.SSOM.ModelHosts +{ + + public class ContentTypeLinkModelHost : ContentTypeModelHost + { + #region constructors + + + #endregion + + #region properties + + + + #endregion + + + + public SPList HostList { get; set; } + + } +} diff --git a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs index 1acfc55fb..8265c5b21 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs @@ -7,7 +7,7 @@ namespace SPMeta2.SSOM.ModelHosts { - public class ContentTypeLinkModelHost : SSOMModelHostBase + public class ContentTypeModelHost : SSOMModelHostBase { #region constructors @@ -22,7 +22,6 @@ public class ContentTypeLinkModelHost : SSOMModelHostBase - public SPList HostList { get; set; } public SPWeb HostWeb { get; set; } } } diff --git a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj index f45593402..8b1438855 100644 --- a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj +++ b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj @@ -325,6 +325,7 @@ + @@ -335,7 +336,7 @@ - + From 5116b68a73d686afd21e0d2ea91dbbf386916a32 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sun, 9 Apr 2017 07:24:21 -0700 Subject: [PATCH 44/53] + CSOM regression on content types + Broken field links operation in content types #1006 --- .../ContentTypeFieldLinkModelHandler.cs | 7 +- .../ContentTypeLinkModelHandler.cs | 381 +++++++++--------- .../ModelHandlers/ContentTypeModelHandler.cs | 8 +- .../ContentTypeFieldLinksModelHandlerBase.cs | 106 ++--- .../HideContentTypeFieldLinksModelHandler.cs | 7 +- ...RemoveContentTypeFieldLinksModelHandler.cs | 7 +- ...niqueContentTypeFieldsOrderModelHandler.cs | 7 +- .../ModelHandlers/FieldModelHandler.cs | 23 +- .../ModelHosts/ContentTypeLinkModelHost.cs | 6 +- .../ModelHosts/ContentTypeModelHost.cs | 18 + SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj | 1 + ...ContentTypeFieldLinkDefinitionValidator.cs | 9 +- 12 files changed, 313 insertions(+), 267 deletions(-) create mode 100644 SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs index 8a64490d6..b74bdce1f 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs @@ -9,6 +9,7 @@ using SPMeta2.ModelHandlers; using SPMeta2.Services; using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers { @@ -121,12 +122,12 @@ protected FieldLink FindExistingFieldLink(ContentType contentType, ContentTypeFi public override void DeployModel(object modelHost, DefinitionBase model) { - var modelHostWrapper = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var modelHostWrapper = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var contentTypeFieldLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); //var site = modelHostWrapper.Site; - var web = modelHostWrapper.Web; - var contentType = modelHostWrapper.ContentType; + var web = modelHostWrapper.HostWeb; + var contentType = modelHostWrapper.HostContentType; var context = contentType.Context; diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs index 1983ec965..e980b76f0 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs @@ -1,39 +1,39 @@ -using System; -using Microsoft.SharePoint.Client; -using SPMeta2.Common; -using SPMeta2.CSOM.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.ModelHandlers; -using SPMeta2.Services; -using SPMeta2.Utils; +using System; +using Microsoft.SharePoint.Client; +using SPMeta2.Common; +using SPMeta2.CSOM.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.ModelHandlers; +using SPMeta2.Services; +using SPMeta2.Utils; using SPMeta2.CSOM.ModelHosts; -using SPMeta2.ModelHosts; - -namespace SPMeta2.CSOM.ModelHandlers -{ - public class ContentTypeLinkModelHandler : CSOMModelHandlerBase - { - public override Type TargetType - { - get { return typeof(ContentTypeLinkDefinition); } - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.ModelHandlers +{ + public class ContentTypeLinkModelHandler : CSOMModelHandlerBase + { + public override Type TargetType + { + get { return typeof(ContentTypeLinkDefinition); } + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) { - var modelHost = modelHostContext.ModelHost as CSOMModelHostBase; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var list = listModelHost.HostList; - var context = list.Context; - - context.Load(list, l => l.ContentTypes); + var modelHost = modelHostContext.ModelHost as CSOMModelHostBase; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var list = listModelHost.HostList; + var context = list.Context; + + context.Load(list, l => l.ContentTypes); context.ExecuteQueryWithTrace(); var contentType = FindListContentType(list, contentTypeLinkModel); @@ -42,163 +42,164 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon { host.HostContentType = contentType; host.HostList = list; + host.ShouldUpdateHost = true; }); action(contentTypeLinkHost); - if (!contentTypeLinkHost.ShouldUpdateHost) - contentType.Update(false); - - context.ExecuteQueryWithTrace(); - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var list = listModelHost.HostList; - - var context = list.Context; - - context.Load(list, l => l.ContentTypesEnabled); - context.ExecuteQueryWithTrace(); - - if (list.ContentTypesEnabled) - { - TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is TRUE. Processing content type link"); - - var web = list.ParentWeb; - - // context.Load(web, w => w.AvailableContentTypes); - context.Load(list, l => l.ContentTypes); - - context.ExecuteQueryWithTrace(); - - var targetContentType = web.AvailableContentTypes.GetById(contentTypeLinkModel.ContentTypeId); - var listContentType = FindListContentType(list, contentTypeLinkModel); - - context.Load(targetContentType); - context.ExecuteQueryWithTrace(); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = listContentType, - ObjectType = typeof(ContentType), - ObjectDefinition = model, - ModelHost = modelHost - }); - - if (targetContentType != null && listContentType == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new list content type link"); - - var ct = list.ContentTypes.Add(new ContentTypeCreationInformation - { - Description = targetContentType.Description, - Group = targetContentType.Group, - Name = targetContentType.Name, - ParentContentType = targetContentType, - }); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = ct, - ObjectType = typeof(ContentType), - ObjectDefinition = model, - ModelHost = modelHost - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "list.Update()"); - list.Update(); - - context.ExecuteQueryWithTrace(); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing list content type link"); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = listContentType, - ObjectType = typeof(ContentType), - ObjectDefinition = model, - ModelHost = modelHost - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "listContentType.Update(false)"); - - // no update is required for content type link - // besides, CTH wouldn't work - - // .AddContentTypeLink() should work well with the read-only content types (Content Type Hub) - // https://github.com/SubPointSolutions/spmeta2/issues/745 - - // listContentType.Update(false); - // context.ExecuteQueryWithTrace(); - } - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is FALSE. Provision might break."); - } - } - - protected ContentType FindListContentType(List list, ContentTypeLinkDefinition contentTypeLinkModel) - { - ContentType result = null; - - // TODO - // https://github.com/SubPointSolutions/spmeta2/issues/68 - - // if content type name was not provided, this fails - // should be re-done by ID and Name - // OOTB content types could be binded by ID, and custom content types might be binded by name - - - // trying to find by name - if (!string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeName)) - { - TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, - "ContentTypeName is not NULL. Trying to find list content type by ContentTypeName: [{0}]", contentTypeLinkModel.ContentTypeName); - - result = list.ContentTypes.FindByName(contentTypeLinkModel.ContentTypeName); - } - - // trying to find by content type id - // will never be resolved, actually - // list content types have different ID - - //if (result == null && !string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeId)) - // result = list.ContentTypes.GetById(contentTypeLinkModel.ContentTypeId); - - // trying to find by beat match - if (result == null) - { - TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, - "Trying to find list content type by ContentTypeId: [{0}]", contentTypeLinkModel.ContentTypeId); - - // No SPContentTypeCollection.BestMatch() method avialable. - // http://officespdev.uservoice.com/forums/224641-general/suggestions/6356289-expose-spcontenttypecollection-bestmatch-for-csom - - // TODO, correct best match impl - foreach (var contentType in list.ContentTypes) - { - if (contentType.Id.ToString().ToUpper().StartsWith(contentTypeLinkModel.ContentTypeId.ToUpper())) - result = contentType; - } - } - - return result; - } - } -} + if (contentTypeLinkHost.ShouldUpdateHost) + contentType.Update(false); + + context.ExecuteQueryWithTrace(); + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var list = listModelHost.HostList; + + var context = list.Context; + + context.Load(list, l => l.ContentTypesEnabled); + context.ExecuteQueryWithTrace(); + + if (list.ContentTypesEnabled) + { + TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is TRUE. Processing content type link"); + + var web = list.ParentWeb; + + // context.Load(web, w => w.AvailableContentTypes); + context.Load(list, l => l.ContentTypes); + + context.ExecuteQueryWithTrace(); + + var targetContentType = web.AvailableContentTypes.GetById(contentTypeLinkModel.ContentTypeId); + var listContentType = FindListContentType(list, contentTypeLinkModel); + + context.Load(targetContentType); + context.ExecuteQueryWithTrace(); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = listContentType, + ObjectType = typeof(ContentType), + ObjectDefinition = model, + ModelHost = modelHost + }); + + if (targetContentType != null && listContentType == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new list content type link"); + + var ct = list.ContentTypes.Add(new ContentTypeCreationInformation + { + Description = targetContentType.Description, + Group = targetContentType.Group, + Name = targetContentType.Name, + ParentContentType = targetContentType, + }); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = ct, + ObjectType = typeof(ContentType), + ObjectDefinition = model, + ModelHost = modelHost + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "list.Update()"); + list.Update(); + + context.ExecuteQueryWithTrace(); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing list content type link"); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = listContentType, + ObjectType = typeof(ContentType), + ObjectDefinition = model, + ModelHost = modelHost + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "listContentType.Update(false)"); + + // no update is required for content type link + // besides, CTH wouldn't work + + // .AddContentTypeLink() should work well with the read-only content types (Content Type Hub) + // https://github.com/SubPointSolutions/spmeta2/issues/745 + + // listContentType.Update(false); + // context.ExecuteQueryWithTrace(); + } + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is FALSE. Provision might break."); + } + } + + protected ContentType FindListContentType(List list, ContentTypeLinkDefinition contentTypeLinkModel) + { + ContentType result = null; + + // TODO + // https://github.com/SubPointSolutions/spmeta2/issues/68 + + // if content type name was not provided, this fails + // should be re-done by ID and Name + // OOTB content types could be binded by ID, and custom content types might be binded by name + + + // trying to find by name + if (!string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeName)) + { + TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, + "ContentTypeName is not NULL. Trying to find list content type by ContentTypeName: [{0}]", contentTypeLinkModel.ContentTypeName); + + result = list.ContentTypes.FindByName(contentTypeLinkModel.ContentTypeName); + } + + // trying to find by content type id + // will never be resolved, actually + // list content types have different ID + + //if (result == null && !string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeId)) + // result = list.ContentTypes.GetById(contentTypeLinkModel.ContentTypeId); + + // trying to find by beat match + if (result == null) + { + TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, + "Trying to find list content type by ContentTypeId: [{0}]", contentTypeLinkModel.ContentTypeId); + + // No SPContentTypeCollection.BestMatch() method avialable. + // http://officespdev.uservoice.com/forums/224641-general/suggestions/6356289-expose-spcontenttypecollection-bestmatch-for-csom + + // TODO, correct best match impl + foreach (var contentType in list.ContentTypes) + { + if (contentType.Id.ToString().ToUpper().StartsWith(contentTypeLinkModel.ContentTypeId.ToUpper())) + result = contentType; + } + } + + return result; + } + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs index 529eea0d6..935fd45dc 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs @@ -117,12 +117,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon } else { - action(new ModelHostContext + action(ModelHostBase.Inherit(mdHHost, host => { - Site = site, - Web = web, - ContentType = currentContentType - }); + host.HostContentType = currentContentType; + })); } TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "Calling currentContentType.Update(true)"); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs index c551cad91..9262f2e29 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs @@ -1,45 +1,61 @@ -using System; -using Microsoft.SharePoint.Client; -using SPMeta2.CSOM.Common; -using SPMeta2.CSOM.ModelHosts; - -namespace SPMeta2.CSOM.ModelHandlers.ContentTypes.Base -{ - public abstract class ContentTypeFieldLinksModelHandlerBase : CSOMModelHandlerBase - { - #region methods - - protected ContentType ExtractContentTypeFromHost(object host) - { - return (host as ModelHostContext).ContentType; - } - - protected Folder ExtractFolderFromHost(object modelHost) - { - if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList.RootFolder; - - if (modelHost is FolderModelHost) - return (modelHost as FolderModelHost).CurrentListFolder; - - throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); - } - - protected List ExtractListFromHost(object modelHost) - { - if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList; - - if (modelHost is FolderModelHost) - { - var host = modelHost as FolderModelHost; - - return host.CurrentList; - } - - throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); - } - - #endregion - } -} +using System; +using Microsoft.SharePoint.Client; +using SPMeta2.CSOM.Common; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Exceptions; + +namespace SPMeta2.CSOM.ModelHandlers.ContentTypes.Base +{ + public abstract class ContentTypeFieldLinksModelHandlerBase : CSOMModelHandlerBase + { + #region methods + + protected ContentType ExtractContentTypeFromHost(object host) + { + if (host is ContentTypeModelHost) + { + return (host as ContentTypeModelHost).HostContentType; + } + else if (host is ContentTypeLinkModelHost) + { + return (host as ContentTypeLinkModelHost).HostContentType; + } + else if (host is ModelHostContext) + { + return (host as ModelHostContext).ContentType; + } + + throw new SPMeta2Exception( + string.Format("Unsupported model host type:[{0}]", + host.GetType())); + } + + protected Folder ExtractFolderFromHost(object modelHost) + { + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList.RootFolder; + + if (modelHost is FolderModelHost) + return (modelHost as FolderModelHost).CurrentListFolder; + + throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); + } + + protected List ExtractListFromHost(object modelHost) + { + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList; + + if (modelHost is FolderModelHost) + { + var host = modelHost as FolderModelHost; + + return host.CurrentList; + } + + throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs index 67bc9a18a..8a04717fe 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs @@ -8,7 +8,8 @@ using SPMeta2.Definitions; using SPMeta2.Definitions.Base; using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers.ContentTypes { @@ -26,8 +27,8 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var contentType = ExtractContentTypeFromHost(contentTypeHost); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs index 74c92c932..d227db80a 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs @@ -8,7 +8,8 @@ using SPMeta2.Definitions; using SPMeta2.Definitions.Base; using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers.ContentTypes { @@ -26,8 +27,8 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var contentType = ExtractContentTypeFromHost(contentTypeHost); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs index f983a1e79..33820c5d8 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs @@ -9,7 +9,8 @@ using SPMeta2.Definitions; using SPMeta2.Definitions.Base; using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers.ContentTypes { @@ -27,8 +28,8 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); var contentTypeOrderDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var contentType = ExtractContentTypeFromHost(modelHost); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs index 03bc1550d..b3c87f8d8 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs @@ -144,26 +144,31 @@ public override void DeployModel(object modelHost, DefinitionBase model) ModelHost = modelHost }); - if (modelHost is SiteModelHost) + if (modelHost is ListModelHost) { - var siteHost = modelHost as SiteModelHost; - context = siteHost.HostSite.Context; + var listHost = modelHost as ListModelHost; + context = listHost.HostList.Context; - currentField = DeploySiteField(siteHost as SiteModelHost, fieldModel); + currentField = DeployListField(modelHost as ListModelHost, fieldModel); } - if (modelHost is WebModelHost) + else if (modelHost is WebModelHost) { var webHost = modelHost as WebModelHost; context = webHost.HostWeb.Context; currentField = DeployWebField(webHost as WebModelHost, fieldModel); } - else if (modelHost is ListModelHost) + + else if (modelHost is SiteModelHost) { - var listHost = modelHost as ListModelHost; - context = listHost.HostList.Context; + var siteHost = modelHost as SiteModelHost; + context = siteHost.HostSite.Context; - currentField = DeployListField(modelHost as ListModelHost, fieldModel); + currentField = DeploySiteField(siteHost as SiteModelHost, fieldModel); + } + else + { + throw new ArgumentException("modelHost needs to be SiteModelHost/WebModelHost/ListModelHost instance."); } object typedField = null; diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs index e2cea1c1f..db650dbcf 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs @@ -8,7 +8,9 @@ namespace SPMeta2.CSOM.ModelHosts { - public class ContentTypeLinkModelHost : ListModelHost + + + public class ContentTypeLinkModelHost : ContentTypeModelHost { #region constructors @@ -17,7 +19,7 @@ public class ContentTypeLinkModelHost : ListModelHost #region properties - public ContentType HostContentType { get; set; } + public List HostList { get; set; } #endregion } diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs new file mode 100644 index 000000000..2de92ef89 --- /dev/null +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs @@ -0,0 +1,18 @@ +using Microsoft.SharePoint.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SPMeta2.CSOM.ModelHosts +{ + public class ContentTypeModelHost : WebModelHost + { + #region properties + + public ContentType HostContentType { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj index 08389eca2..60b42d11b 100644 --- a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj +++ b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj @@ -258,6 +258,7 @@ + diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs index 04e7d6cfc..7b70d79ac 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs @@ -3,7 +3,8 @@ using SPMeta2.CSOM.Common; using SPMeta2.CSOM.ModelHandlers; using SPMeta2.Definitions; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.Regression.CSOM.Validation { @@ -11,11 +12,11 @@ public class ClientContentTypeFieldLinkDefinitionValidator : ContentTypeFieldLin { public override void DeployModel(object modelHost, DefinitionBase model) { - var modelHostContext = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var modelHostContext = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var site = modelHostContext.Site; - var contentType = modelHostContext.ContentType; + var site = modelHostContext.HostSite; + var contentType = modelHostContext.HostContentType; var context = site.Context; From a842b9a768194b806fbdda6d664a238d3b6c2340 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 00:49:16 -0700 Subject: [PATCH 45/53] + CSOM 2013 full regression + CSOM regression on content types + Broken field links operation in content types #1006 --- .../Regression/_ut_grid_baseline_config.ps1 | 112 +++- .../_ut_grid_dsc_spmeta2_webapp.ps1 | 4 +- .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 2 +- .../Taxonomy/TaxonomyGroupModelHandler.cs | 11 +- .../Taxonomy/TaxonomyTermLabelModelHandler.cs | 2 +- .../Taxonomy/TaxonomyTermModelHandler.cs | 20 +- .../Taxonomy/TaxonomyTermSetModelHandler.cs | 10 +- .../BreakRoleInheritanceModelHandler.cs | 14 +- .../ModelHandlers/CSOMModelHandlerBase.cs | 5 + .../ModelHandlers/ListModelHandler.cs | 8 +- .../ModelHosts/ContentTypeModelHost.cs | 2 +- .../Services/CSOMFieldLookupService.cs | 8 +- ...ebNavigationSettingsDefinitionGenerator.cs | 97 ++- .../ClientTaxonomyGroupDefinitionValidator.cs | 12 +- .../ClientTaxonomyTermDefinitionValidator.cs | 28 +- ...entTaxonomyTermLabelDefinitionValidator.cs | 3 +- ...lientTaxonomyTermSetDefinitionValidator.cs | 12 +- ...WorkflowSubscriptionDefinitionValidator.cs | 345 ++++++----- ...ientUserCustomActionDefinitionValidator.cs | 512 ++++++++-------- .../Impl/ModelAPI/SPMeta2ModelTests.cs | 26 +- .../Impl/Scenarios/FieldScenariosTest.cs | 15 +- .../QuickLaunchNavigationNodeScenariosTest.cs | 11 +- .../Scenarios/ReusableItemScenariosTest.cs | 194 +++--- .../Scenarios/SP2013WorkflowScenariosTest.cs | 453 +++++++------- .../Impl/Scenarios/WebpartScenariosTest.cs | 551 ++++++++++-------- .../Services/Impl/DefaultTryRetryService.cs | 4 +- 26 files changed, 1351 insertions(+), 1110 deletions(-) diff --git a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 index a66393457..1b489294a 100644 --- a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 +++ b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 @@ -7,30 +7,114 @@ foreach($server in $dsc_nodeNames) { Write-Host "Configuring server [$server]" -fore Green + $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet + + if($isOnline -eq $true) + { + Write-Host "Server [$server] online. Processing..." -fore Green + Invoke-Command -ScriptBlock { - Write-Host "Updating SharePoint ULS settings..." + function Ensure-ISS-AppPools() { + + Import-Module WebAdministration + + $pools = Get-ChildItem –Path IIS:\AppPools + + foreach($pool in $pools) { + + $name = $pool.Name + $state = $pool.State + + if($state -ne "Started") { + Write-Host "`tStarting [$name] - [$state]" -fore Yellow + Start-WebAppPool -Name $name + } else { + Write-Host "`tStarted [$name] - [$state]" -fore Gray + } + } + + } + + function Restart-SharePoint { + + Write-Host "Restarting services..." + + Restart-Service MSSQLSERVER -Force + Restart-Service sptimerv4 -Force + + iisreset + } + + function Update-SharePoint-ULS() { + Write-Host "Updating SharePoint ULS settings..." - add-pssnapin microsoft.sharepoint.powershell - Set-SPDiagnosticConfig -LogMaxDiskSpaceUsageEnabled - Set-SPDiagnosticConfig -LogDiskSpaceUsageGB 1 + add-pssnapin microsoft.sharepoint.powershell + Set-SPDiagnosticConfig -LogMaxDiskSpaceUsageEnabled + Set-SPDiagnosticConfig -LogDiskSpaceUsageGB 1 + } - Write-Host "Updating SQL settings..." + function Set-MSSQL-Ram($ramInMb) { + Write-Host "Updating SQL settings..." - [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null - $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server + [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null + $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server - #$s.Configuration.MinServerMemory.ConfigValue = 3 * 1024 - $s.Configuration.MaxServerMemory.ConfigValue = 3 * 1024 - $s.Configuration.Alter() + #$s.Configuration.MinServerMemory.ConfigValue = 3 * 1024 + $s.Configuration.MaxServerMemory.ConfigValue = $ramInMb + $s.Configuration.Alter() + } - Write-Host "Restarting services..." + function Ensure-AssociatedGroups() { - Restart-Service MSSQLSERVER -Force - Restart-Service sptimerv4 -Force + Add-PSSnapin Microsoft.SharePoint.PowerShell - iisreset + + $computerName = [environment]::MachineName + + # TODO + + $web = Get-SPWeb ("http://" + $computerName + ":31449") + if ($web.AssociatedVisitorGroup -eq $null) { + Write-Host 'The Visitor Group does not exist. It will be created...' -ForegroundColor DarkYellow + $currentLogin = $web.CurrentUser.LoginName + + if ($web.CurrentUser.IsSiteAdmin -eq $false){ + Write-Host ('The user '+$currentLogin+' needs to be a SiteCollection administrator, to create the default groups.') -ForegroundColor Red + return + } + + $web.CreateDefaultAssociatedGroups($currentLogin, $currentLogin, [System.String].Empty) + Write-Host 'The default Groups have been created.' -ForegroundColor Green + } else { + Write-Host 'The Visitor Group already exists.' -ForegroundColor Green + } + + } + + function Limit-SharePoint-Search() { + Add-PSSnapin Microsoft.SharePoint.PowerShell + + set-SPEnterpriseSearchService -PerformanceLevel Reduced + } + + Ensure-AssociatedGroups + + Update-SharePoint-ULS + Limit-SharePoint-Search + + Set-MSSQL-Ram (6 * 1024) + + Restart-SharePoint + + Ensure-ISS-AppPools + Ensure-ISS-AppPools } -computer $server + } + else + { + Write-Host "Server [$server] is OFFLINE. Skipping Processing..." -fore Yellow + } } \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 index 6a2aaf6f5..78f4ffe43 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 @@ -52,7 +52,7 @@ Configuration SPMeta2_WebApp ApplicationPoolAccount = $config.WebPoolManagedAccount.UserName AllowAnonymous = $false AuthenticationMethod = "NTLM" - DatabaseName = "SPMeta2_Regression_Content" + DatabaseName = "SPMeta2_Regression_Content_$webApp_Port" Url = $webApp_Url #HostHeader = "spmeta2.contoso.com" Port = $webApp_Port @@ -101,7 +101,7 @@ $config = @{ WebPoolManagedAccount = $dsc_WebPoolManagedCredentials SPSetupAccount = $dsc_SPSetupAccountCredentials - #DeleteWebApplication = $true + DeleteWebApplication = $false WebAppPort = $env_config.SharePoint.WebApp.Port diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 index 1515fe21a..5f3be1791 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -3,7 +3,7 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent . "$ScriptDirectory/_helpers.ps1" -$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" +$o365RuntimePath = "$PSScriptRoot\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" Write-Host "Loading SharePoint CSOM API" -fore Green $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs index 3b96fca04..971dcd3d8 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs @@ -44,7 +44,7 @@ private void SharePointOnlineWait(TermStoreModelHost siteModelHost, TaxonomyTerm // TermSet not found #994 var context = siteModelHost.HostClientContext; - if (context.Credentials is SharePointOnlineCredentials) + if (IsSharePointOnlineContext(context)) { var currentGroup = FindGroup(siteModelHost, groupModel); @@ -72,10 +72,12 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var storeModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var context = storeModelHost.HostClientContext; + var termStore = storeModelHost.HostTermStore; var currentGroup = FindGroup(storeModelHost, groupModel); - if (currentGroup == null) + if (currentGroup == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -227,6 +229,11 @@ private void DeployTaxonomyGroup(object modelHost, TermStoreModelHost siteModelH } catch (Exception e) { + var context = siteModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 // https://github.com/SubPointSolutions/spmeta2/issues/959 diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs index ff97b578c..537cff465 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs @@ -43,7 +43,7 @@ private void SharePointOnlineWait(TermModelHost termModelHost, TaxonomyTermLabel // TermSet not found #994 var context = termModelHost.HostClientContext; - if (context.Credentials is SharePointOnlineCredentials) + if (IsSharePointOnlineContext(context)) { var term = termModelHost.HostTerm; var currentLabel = FindLabelInTerm(term, definition); diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index 8e79e5764..025db6f8c 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -86,7 +86,9 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTerm(h.HostTerm, definition); - if (currentTerm == null) + var context = h.HostClientContext; + + if (currentTerm == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -110,7 +112,9 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTermSet(h.HostTermSet, definition); - if (currentTerm == null) + var context = h.HostClientContext; + + if (currentTerm == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -136,6 +140,8 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode var currentTerm = FindTermInTermSet(termSet, termModel); var termName = NormalizeTermName(termModel.Name); + + InvokeOnModelEvent(this, new ModelEventArgs { CurrentModelNode = null, @@ -195,6 +201,11 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode } catch (Exception e) { + var context = groupModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + var serverException = e as ServerException; if (serverException != null @@ -400,6 +411,11 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, } catch (Exception e) { + var context = groupModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + var serverException = e as ServerException; if (serverException != null diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs index 7405e02b1..ab828d87e 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs @@ -44,7 +44,7 @@ private void SharePointOnlineWait(TermGroupModelHost groupModelHost, TaxonomyTer // TermSet not found #994 var context = groupModelHost.HostClientContext; - if (context.Credentials is SharePointOnlineCredentials) + if (IsSharePointOnlineContext(context)) { var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); @@ -72,9 +72,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var context = groupModelHost.HostClientContext; var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); - if (currentTermSet == null) + if (currentTermSet == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -148,6 +149,11 @@ private void DeployTaxonomyTermSet(object modelHost, TermGroupModelHost groupMod } catch (Exception e) { + var context = groupModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 // https://github.com/SubPointSolutions/spmeta2/issues/959 diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs index 4a876db4c..ad53dfc59 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs @@ -20,17 +20,17 @@ internal static class SecurableHelper public static SecurableObject ExtractSecurableObject(object modelHost) { if (modelHost is SecurableObject) - return modelHost as SecurableObject; + return modelHost as SecurableObject; + + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList; + + if (modelHost is WebModelHost) + return (modelHost as WebModelHost).HostWeb; if (modelHost is SiteModelHost) return (modelHost as SiteModelHost).HostSite.RootWeb; - if (modelHost is WebModelHost) - return (modelHost as WebModelHost).HostWeb; - - if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList; - if (modelHost is File) return (modelHost as File).ListItemAllFields; diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs index fc0635dd1..1bde33022 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs @@ -52,6 +52,11 @@ protected virtual object GetPropertyValue(object obj, string propName) return ReflectionUtils.GetPropertyValue(obj, propName); } + protected virtual bool IsSharePointOnlineContext(ClientContext context) + { + return context.Credentials is SharePointOnlineCredentials; + } + #endregion #region localization diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs index 455980e34..31b974e58 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs @@ -38,13 +38,15 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon Web web = null; List hostList = null; - if (modelHost is WebModelHost) - web = (modelHost as WebModelHost).HostWeb; - else if (modelHost is ListModelHost) + if (modelHost is ListModelHost) { web = (modelHost as ListModelHost).HostList.ParentWeb; hostList = (modelHost as ListModelHost).HostList; } + else if (modelHost is WebModelHost) + { + web = (modelHost as WebModelHost).HostWeb; + } else { throw new SPMeta2UnsupportedModelHostException( diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs index 2de92ef89..b64dc791b 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.CSOM.ModelHosts { diff --git a/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs b/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs index f884391c0..e922d9b82 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs @@ -14,12 +14,12 @@ public class CSOMFieldLookupService { public virtual FieldCollection GetFieldCollection(object modelHost) { - if (modelHost is SiteModelHost) - return (modelHost as SiteModelHost).HostSite.RootWeb.Fields; + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList.Fields; else if (modelHost is WebModelHost) return (modelHost as WebModelHost).HostWeb.Fields; - else if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList.Fields; + if (modelHost is SiteModelHost) + return (modelHost as SiteModelHost).HostSite.RootWeb.Fields; throw new SPMeta2Exception("Unsupported model host"); } diff --git a/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs b/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs index ae4be2f51..2128a08c9 100644 --- a/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs +++ b/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs @@ -1,49 +1,48 @@ -using System; -using System.Collections.Generic; -using SPMeta2.Containers.Services.Base; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Enumerations; -using SPMeta2.Standard.Definitions; -using SPMeta2.Syntax.Default; - -namespace SPMeta2.Containers.Standard.DefinitionGenerators -{ - public class WebNavigationSettingsDefinitionGenerator : TypedDefinitionGeneratorServiceBase - { - public override DefinitionBase GenerateRandomDefinition(Action action) - { - return WithEmptyDefinition(def => - { - def.CurrentNavigationSource = BuiltInStandardNavigationSources.PortalProvider; - - def.CurrentNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; - def.CurrentNavigationShowPages = Rnd.Bool(); - def.CurrentNavigationShowSubsites = Rnd.Bool(); - - def.GlobalNavigationSource = BuiltInStandardNavigationSources.PortalProvider; - - def.GlobalNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; - def.GlobalNavigationShowPages = Rnd.Bool(); - def.GlobalNavigationShowSubsites = Rnd.Bool(); - }); - } - - public override IEnumerable GetAdditionalArtifacts() - { - var sitePublishing = BuiltInSiteFeatures.SharePointServerPublishingInfrastructure - .Inherit(f => - { - f.Enable = true; - }); - - var webPublishing = BuiltInWebFeatures.SharePointServerPublishing - .Inherit(f => - { - f.Enable = true; - }); - - return new[] { sitePublishing, webPublishing }; - } - } -} +using System; +using System.Collections.Generic; +using SPMeta2.Containers.Services.Base; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Enumerations; +using SPMeta2.Standard.Definitions; +using SPMeta2.Syntax.Default; + +namespace SPMeta2.Containers.Standard.DefinitionGenerators +{ + public class WebNavigationSettingsDefinitionGenerator : TypedDefinitionGeneratorServiceBase + { + public override DefinitionBase GenerateRandomDefinition(Action action) + { + return WithEmptyDefinition(def => + { + def.CurrentNavigationSource = BuiltInStandardNavigationSources.PortalProvider; + + def.CurrentNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; + def.CurrentNavigationShowPages = Rnd.Bool(); + def.CurrentNavigationShowSubsites = Rnd.Bool(); + + def.GlobalNavigationSource = BuiltInStandardNavigationSources.PortalProvider; + + def.GlobalNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; + def.GlobalNavigationShowPages = Rnd.Bool(); + def.GlobalNavigationShowSubsites = Rnd.Bool(); + }); + } + + public override IEnumerable GetAdditionalArtifacts() + { + var sitePublishing = BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(f => + { + f.Enable = true; + }); + + var webPublishing = BuiltInWebFeatures.SharePointServerPublishing.Inherit(f => + { + f.Enable = true; + f.ForceActivate = true; + }); + + return new[] { sitePublishing, webPublishing }; + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs index 64f897ce5..87690e5d5 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs @@ -15,13 +15,17 @@ public override void DeployModel(object modelHost, DefinitionBase model) var termStoreModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var context = termStoreModelHost.HostClientContext; var spObject = FindGroup(termStoreModelHost, definition); - TryRetryService.TryWithRetry(() => + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindGroup(termStoreModelHost, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindGroup(termStoreModelHost, definition); + return spObject != null; + }); + } var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs index c8c55a814..2c9035c5d 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs @@ -22,19 +22,31 @@ public override void DeployModel(object modelHost, DefinitionBase model) if (modelHost is TermModelHost) { - TryRetryService.TryWithRetry(() => + var context = (modelHost as TermModelHost).HostClientContext; + spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); + + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); + return spObject != null; + }); + } } else if (modelHost is TermSetModelHost) { - TryRetryService.TryWithRetry(() => + var context = (modelHost as TermSetModelHost).HostClientContext; + spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); + + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); + return spObject != null; + }); + } } else { diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs index 08a16406a..6235a92f9 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs @@ -14,8 +14,9 @@ public override void DeployModel(object modelHost, DefinitionBase model) var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + var context = termModelHost.HostClientContext; - if (spObject == null) + if (spObject == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs index cbef364f8..08922822b 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs @@ -16,12 +16,16 @@ public override void DeployModel(object modelHost, DefinitionBase model) var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + var context = termGroupModelHost.HostClientContext; - TryRetryService.TryWithRetry(() => + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindTermSet(termGroupModelHost.HostGroup, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + return spObject != null; + }); + } var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs index b3c60ac9e..f85dfd974 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs @@ -1,172 +1,171 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client.WorkflowServices; -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Utils; -using Microsoft.SharePoint.Client; -using SPMeta2.CSOM.Extensions; - -namespace SPMeta2.Regression.CSOM.Validation -{ - public class ClientSP2013WorkflowSubscriptionDefinitionValidator : SP2013WorkflowSubscriptionDefinitionModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - if (modelHost is WebModelHost) - { - var workflowWebSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var web = workflowWebSubscriptionModelHost.HostWeb; - - var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowWebSubscriptionModelHost, - workflowWebSubscriptionModelHost.HostClientContext, - web, - web.Id, - definition); - - ValidateWorkflowSubscription(modelHost, workflowWebSubscriptionModelHost.HostClientContext, workflowWebSubscriptionModelHost.HostWeb, spObject, definition); - } - - if (modelHost is ListModelHost) - { - var workflowSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var web = workflowSubscriptionModelHost.HostWeb; - var list = workflowSubscriptionModelHost.HostList; - - var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowSubscriptionModelHost, - workflowSubscriptionModelHost.HostClientContext, - list.ParentWeb, - list.Id, - definition); - - ValidateWorkflowSubscription(modelHost, workflowSubscriptionModelHost.HostClientContext, web, spObject, definition); - } - } - - private void ValidateWorkflowSubscription(object modelHost, - ClientContext clientContext, - Web web, - WorkflowSubscription spObject, - SP2013WorkflowSubscriptionDefinition definition) - { - - var spObjectContext = spObject.Context; - - //spObjectContext.Load(spObject); - //spObjectContext.Load(spObject, o => o.PropertyDefinitions); - //spObjectContext.Load(spObject, o => o.EventSourceId); - //spObjectContext.Load(spObject, o => o.EventTypes); - - //spObjectContext.ExecuteQueryWithTrace(); - - #region list accos - - var webContext = web.Context; - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject) - .ShouldBeEqual(m => m.Name, o => o.Name); - - // [FALSE] - [WorkflowDisplayName] - { - var srcProp = s.GetExpressionValue(m => m.EventTypes); - - var hasAllEventTypes = true; - - foreach (var srcEventType in s.EventTypes) - if (!d.EventTypes.Contains(srcEventType)) - hasAllEventTypes = false; - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = hasAllEventTypes - }; - }); - - #endregion - - #region validate DefinitionId - - var workflowDefinition = GetWorkflowDefinition(modelHost, - clientContext, - web, - definition); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.WorkflowDisplayName); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = d.DefinitionId == workflowDefinition.Id - }; - }); - - #endregion - - #region validate task and history list - - var taskListId = new Guid(spObject.PropertyDefinitions["TaskListId"]); - var historyListId = new Guid(spObject.PropertyDefinitions["HistoryListId"]); - - var lists = webContext.LoadQuery(web.Lists.Include(l => l.DefaultViewUrl, l => l.Id)); - webContext.ExecuteQueryWithTrace(); - - var srcTaskList = lists.FirstOrDefault(l => l.Id == taskListId); - var srcHistoryList = lists.FirstOrDefault(l => l.Id == historyListId); - - var dstTaskList = GetTaskList(web, definition); - var dstHistoryList = GetHistoryList(web, definition); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.TaskListUrl); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = srcTaskList.Id == dstTaskList.Id - }; - }); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.HistoryListUrl); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = srcHistoryList.Id == dstHistoryList.Id - }; - }); - - #endregion - +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint.Client.WorkflowServices; +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Utils; +using Microsoft.SharePoint.Client; +using SPMeta2.CSOM.Extensions; + +namespace SPMeta2.Regression.CSOM.Validation +{ + public class ClientSP2013WorkflowSubscriptionDefinitionValidator : SP2013WorkflowSubscriptionDefinitionModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + if (modelHost is ListModelHost) + { + var workflowSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var web = workflowSubscriptionModelHost.HostWeb; + var list = workflowSubscriptionModelHost.HostList; + + var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowSubscriptionModelHost, + workflowSubscriptionModelHost.HostClientContext, + list.ParentWeb, + list.Id, + definition); + + ValidateWorkflowSubscription(modelHost, workflowSubscriptionModelHost.HostClientContext, web, spObject, definition); + } + else if (modelHost is WebModelHost) + { + var workflowWebSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var web = workflowWebSubscriptionModelHost.HostWeb; + + var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowWebSubscriptionModelHost, + workflowWebSubscriptionModelHost.HostClientContext, + web, + web.Id, + definition); + + ValidateWorkflowSubscription(modelHost, workflowWebSubscriptionModelHost.HostClientContext, workflowWebSubscriptionModelHost.HostWeb, spObject, definition); + } + } + + private void ValidateWorkflowSubscription(object modelHost, + ClientContext clientContext, + Web web, + WorkflowSubscription spObject, + SP2013WorkflowSubscriptionDefinition definition) + { + + var spObjectContext = spObject.Context; + + //spObjectContext.Load(spObject); + //spObjectContext.Load(spObject, o => o.PropertyDefinitions); + //spObjectContext.Load(spObject, o => o.EventSourceId); + //spObjectContext.Load(spObject, o => o.EventTypes); + + //spObjectContext.ExecuteQueryWithTrace(); + + #region list accos + + var webContext = web.Context; + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject) + .ShouldBeEqual(m => m.Name, o => o.Name); + + // [FALSE] - [WorkflowDisplayName] + { + var srcProp = s.GetExpressionValue(m => m.EventTypes); + + var hasAllEventTypes = true; + + foreach (var srcEventType in s.EventTypes) + if (!d.EventTypes.Contains(srcEventType)) + hasAllEventTypes = false; + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = hasAllEventTypes + }; + }); + + #endregion + + #region validate DefinitionId + + var workflowDefinition = GetWorkflowDefinition(modelHost, + clientContext, + web, + definition); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.WorkflowDisplayName); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = d.DefinitionId == workflowDefinition.Id + }; + }); + + #endregion + + #region validate task and history list + + var taskListId = new Guid(spObject.PropertyDefinitions["TaskListId"]); + var historyListId = new Guid(spObject.PropertyDefinitions["HistoryListId"]); + + var lists = webContext.LoadQuery(web.Lists.Include(l => l.DefaultViewUrl, l => l.Id)); + webContext.ExecuteQueryWithTrace(); + + var srcTaskList = lists.FirstOrDefault(l => l.Id == taskListId); + var srcHistoryList = lists.FirstOrDefault(l => l.Id == historyListId); + + var dstTaskList = GetTaskList(web, definition); + var dstHistoryList = GetHistoryList(web, definition); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.TaskListUrl); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = srcTaskList.Id == dstTaskList.Id + }; + }); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.HistoryListUrl); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = srcHistoryList.Id == dstHistoryList.Id + }; + }); + + #endregion + #endregion if (definition.Properties.Count() > 0) @@ -206,7 +205,7 @@ private void ValidateWorkflowSubscription(object modelHost, else { assert.SkipProperty(p => p.Properties, ".Properties.Count() = 0. Skipping"); - } - } - } -} + } + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs index 85479abc2..832bb1a25 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs @@ -1,252 +1,266 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client; -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Services; -using SPMeta2.Utils; - - -namespace SPMeta2.Regression.CSOM.Validation -{ - public class ClientUserCustomActionDefinitionValidator : UserCustomActionModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = GetCurrentCustomUserAction(modelHost, definition); - - var assert = ServiceFactory.AssertService - .NewAssert(definition, definition, spObject) - .ShouldBeEqual(m => m.Name, o => o.Name) - .ShouldBeEqual(m => m.Title, o => o.Title) - .ShouldBeEqual(m => m.Description, o => o.Description) - .ShouldBeEqual(m => m.Group, o => o.Group) - .ShouldBeEqual(m => m.Location, o => o.Location) - .ShouldBeEqual(m => m.ScriptSrc, o => o.ScriptSrc) - .ShouldBeEqual(m => m.ScriptBlock, o => o.ScriptBlock) - .ShouldBeEqual(m => m.Sequence, o => o.Sequence) - .ShouldBeEqual(m => m.Url, o => o.Url) - //.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId) - .ShouldBeEqual(m => m.RegistrationType, o => o.GetRegistrationType()); - - var context = spObject.Context; - - var registrationIdIsGuid = ConvertUtils.ToGuid(spObject.RegistrationId); - - if (registrationIdIsGuid.HasValue) - { - // this is list scoped user custom action reg - // skipping validation - assert.SkipProperty(m => m.RegistrationId, "RegistrationId is GUID. List scope user custom action. Skipping validation."); - } - else - { - assert.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId); - } - - if (!string.IsNullOrEmpty(definition.CommandUIExtension)) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.CommandUIExtension); - var dstProp = d.GetExpressionValue(ct => ct.CommandUIExtension); - - var isValid = GetCommandUIString(srcProp.Value.ToString()) == - GetCommandUIString(dstProp.Value.ToString()); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = dstProp, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.CommandUIExtension, "CommandUIExtension is null or empty. Skipping."); - } - - assert - .ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.Rights); - var dstProp = d.GetExpressionValue(ct => ct.Rights); - - var hasCorrectRights = true; - - foreach (var srcRight in s.Rights) - { - var srcPermission = (PermissionKind)Enum.Parse(typeof(PermissionKind), srcRight); - - var tmpRight = d.Rights.Has(srcPermission); - - if (tmpRight == false) - hasCorrectRights = false; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = dstProp, - IsValid = hasCorrectRights - }; - }); - - - +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint.Client; +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Services; +using SPMeta2.Utils; + + +namespace SPMeta2.Regression.CSOM.Validation +{ + public class ClientUserCustomActionDefinitionValidator : UserCustomActionModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var spObject = GetCurrentCustomUserAction(modelHost, definition); + + var shouldCheckRegistrationType = true; + + if (modelHost is ListModelHost) + { + //// skipping setup for List script + //// System.NotSupportedException: Setting this property is not supported. A value of List has already been set and cannot be changed. + shouldCheckRegistrationType = false; + } + + var assert = ServiceFactory.AssertService + .NewAssert(definition, definition, spObject) + .ShouldBeEqual(m => m.Name, o => o.Name) + .ShouldBeEqual(m => m.Title, o => o.Title) + .ShouldBeEqual(m => m.Description, o => o.Description) + .ShouldBeEqual(m => m.Group, o => o.Group) + .ShouldBeEqual(m => m.Location, o => o.Location) + .ShouldBeEqual(m => m.ScriptSrc, o => o.ScriptSrc) + .ShouldBeEqual(m => m.ScriptBlock, o => o.ScriptBlock) + .ShouldBeEqual(m => m.Sequence, o => o.Sequence) + .ShouldBeEqual(m => m.Url, o => o.Url); + //.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId) + //.ShouldBeEqual(m => m.RegistrationType, o => o.GetRegistrationType()); + + if (shouldCheckRegistrationType) + assert.ShouldBeEqual(m => m.RegistrationType, o => o.GetRegistrationType()); + else + assert.SkipProperty(m => m.RegistrationType, "Skipping validation"); + + var context = spObject.Context; + + var registrationIdIsGuid = ConvertUtils.ToGuid(spObject.RegistrationId); + + if (registrationIdIsGuid.HasValue) + { + // this is list scoped user custom action reg + // skipping validation + assert.SkipProperty(m => m.RegistrationId, "RegistrationId is GUID. List scope user custom action. Skipping validation."); + } + else + { + assert.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId); + } + + if (!string.IsNullOrEmpty(definition.CommandUIExtension)) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.CommandUIExtension); + var dstProp = d.GetExpressionValue(ct => ct.CommandUIExtension); + + var isValid = GetCommandUIString(srcProp.Value.ToString()) == + GetCommandUIString(dstProp.Value.ToString()); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = dstProp, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.CommandUIExtension, "CommandUIExtension is null or empty. Skipping."); + } + + assert + .ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.Rights); + var dstProp = d.GetExpressionValue(ct => ct.Rights); + + var hasCorrectRights = true; + + foreach (var srcRight in s.Rights) + { + var srcPermission = (PermissionKind)Enum.Parse(typeof(PermissionKind), srcRight); + + var tmpRight = d.Rights.Has(srcPermission); + + if (tmpRight == false) + hasCorrectRights = false; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = dstProp, + IsValid = hasCorrectRights + }; + }); + + + var supportsLocalization = ReflectionUtils.HasProperties(spObject, new[] { "TitleResource", "DescriptionResource", "CommandUIExtensionResource" - }); - - if (supportsLocalization) - { - if (definition.TitleResource.Any()) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.TitleResource); - var isValid = true; - - foreach (var userResource in s.TitleResource) - { - var culture = LocalizationService.GetUserResourceCultureInfo(userResource); - var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "TitleResource"); - - var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") - .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; - - context.ExecuteQuery(); - - isValid = userResource.Value == value.Value; - - if (!isValid) - break; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.TitleResource, "TitleResource is NULL or empty. Skipping."); - } - - if (definition.DescriptionResource.Any()) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.DescriptionResource); - var isValid = true; - - foreach (var userResource in s.DescriptionResource) - { - var culture = LocalizationService.GetUserResourceCultureInfo(userResource); - var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "DescriptionResource"); - - var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") - .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; - - context.ExecuteQuery(); - - isValid = userResource.Value == value.Value; - - if (!isValid) - break; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is NULL or empty. Skipping."); - } - - if (definition.CommandUIExtensionResource.Any()) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.CommandUIExtensionResource); - var isValid = true; - - foreach (var userResource in s.CommandUIExtensionResource) - { - var culture = LocalizationService.GetUserResourceCultureInfo(userResource); - var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "CommandUIExtensionResource"); - - var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") - .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; - - context.ExecuteQuery(); - - isValid = GetCommandUIString(userResource.Value) == GetCommandUIString(value.Value); - - if (!isValid) - break; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.CommandUIExtensionResource, "DescriptionResource is NULL or empty. Skipping."); - } - - } - else - { - TraceService.Critical((int)LogEventId.ModelProvisionCoreCall, - "CSOM runtime doesn't have Web.TitleResource and Web.DescriptionResource() methods support. Skipping validation."); - - assert.SkipProperty(m => m.TitleResource, "TitleResource is null or empty. Skipping."); - assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is null or empty. Skipping."); - assert.SkipProperty(m => m.CommandUIExtensionResource, "CommandUIExtensionResource is null or empty. Skipping."); - } - } - - protected string GetCommandUIString(string value) - { - return value.Replace(" ", "") - .Replace(Environment.NewLine, "") - .Replace("\n", ""); - } - } - - internal static class SPUserActionHelpers - { - public static string GetRegistrationType(this UserCustomAction action) - { - return action.RegistrationType.ToString(); - } - } -} + }); + + if (supportsLocalization) + { + if (definition.TitleResource.Any()) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.TitleResource); + var isValid = true; + + foreach (var userResource in s.TitleResource) + { + var culture = LocalizationService.GetUserResourceCultureInfo(userResource); + var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "TitleResource"); + + var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") + .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; + + context.ExecuteQuery(); + + isValid = userResource.Value == value.Value; + + if (!isValid) + break; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.TitleResource, "TitleResource is NULL or empty. Skipping."); + } + + if (definition.DescriptionResource.Any()) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.DescriptionResource); + var isValid = true; + + foreach (var userResource in s.DescriptionResource) + { + var culture = LocalizationService.GetUserResourceCultureInfo(userResource); + var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "DescriptionResource"); + + var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") + .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; + + context.ExecuteQuery(); + + isValid = userResource.Value == value.Value; + + if (!isValid) + break; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is NULL or empty. Skipping."); + } + + if (definition.CommandUIExtensionResource.Any()) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.CommandUIExtensionResource); + var isValid = true; + + foreach (var userResource in s.CommandUIExtensionResource) + { + var culture = LocalizationService.GetUserResourceCultureInfo(userResource); + var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "CommandUIExtensionResource"); + + var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") + .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; + + context.ExecuteQuery(); + + isValid = GetCommandUIString(userResource.Value) == GetCommandUIString(value.Value); + + if (!isValid) + break; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.CommandUIExtensionResource, "DescriptionResource is NULL or empty. Skipping."); + } + + } + else + { + TraceService.Critical((int)LogEventId.ModelProvisionCoreCall, + "CSOM runtime doesn't have Web.TitleResource and Web.DescriptionResource() methods support. Skipping validation."); + + assert.SkipProperty(m => m.TitleResource, "TitleResource is null or empty. Skipping."); + assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is null or empty. Skipping."); + assert.SkipProperty(m => m.CommandUIExtensionResource, "CommandUIExtensionResource is null or empty. Skipping."); + } + } + + protected string GetCommandUIString(string value) + { + return value.Replace(" ", "") + .Replace(Environment.NewLine, "") + .Replace("\n", ""); + } + } + + internal static class SPUserActionHelpers + { + public static string GetRegistrationType(this UserCustomAction action) + { + return action.RegistrationType.ToString(); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs index d644950a0..4fe4ce32d 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs @@ -11,6 +11,8 @@ using SPMeta2.Utils; using SPMeta2.Syntax.Default; using SPMeta2.Containers.Utils; +using SPMeta2.Enumerations; +using SPMeta2.Models; namespace SPMeta2.Regression.Tests.Impl.ModelAPI { @@ -91,6 +93,22 @@ public void CanDeploy_ListModel() [TestCategory("Regression.SPMeta2Model")] public void CanDeploy_ListModel_WithFolders() { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + }); + var model = SPMeta2Model.NewListModel(list => { list.AddFolder(ModelGeneratorService.GetRandomDefinition()); @@ -98,7 +116,11 @@ public void CanDeploy_ListModel_WithFolders() list.AddFolder(ModelGeneratorService.GetRandomDefinition()); }); - TestModel(model); + TestModels(new ModelNode[]{ + siteModel, + webModel, + model + }); } #endregion @@ -272,7 +294,7 @@ public void SPMeta2Model_NewSiteModel_Contract() Assert.IsTrue(SPMeta2Model.NewSiteModel(newDefinition).GetType() == expectedType); // new definition with callback - Assert.IsTrue(SPMeta2Model.NewSiteModel(newDefinition, node => { }).GetType() == expectedType); + Assert.IsTrue(SPMeta2Model.NewSiteModel(newDefinition, node => { }).GetType() == expectedType); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs index fb1acc5f9..86dcb06f4 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs @@ -440,14 +440,13 @@ public void CanDeploy_ListScoped_Field() { var field = ModelGeneratorService.GetRandomDefinition(); - var model = SPMeta2Model - .NewWebModel(web => - { - web.AddRandomList(list => - { - list.AddField(field); - }); - }); + var model = SPMeta2Model.NewWebModel(web => + { + web.AddRandomList(list => + { + list.AddField(field); + }); + }); TestModel(model); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs index c1bb1bc64..0945379ca 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs @@ -259,14 +259,13 @@ public void CanDeploy_QuickLaunchNavigationNode_WithSiteCollectionToken() n.Url = string.Format("~sitecollection/{0}.html", Rnd.String()); }); - var model = SPMeta2Model - .NewWebModel(web => + var model = SPMeta2Model.NewWebModel(web => + { + web.AddRandomWeb(rndWeb => { - web.AddRandomWeb(rndWeb => - { - rndWeb.AddQuickLaunchNavigationNode(nav1Node); - }); + rndWeb.AddQuickLaunchNavigationNode(nav1Node); }); + }); TestModel(model); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs index d2b374e38..913e1b764 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs @@ -1,84 +1,110 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.BuiltInDefinitions; -using SPMeta2.Containers; -using SPMeta2.Definitions; -using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Enumerations; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using SPMeta2.Standard.Definitions; -using SPMeta2.Standard.Syntax; -using SPMeta2.Syntax.Default; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class ReusableItemScenariosTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanup] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region tests - - [TestMethod] - [TestCategory("Regression.Scenarios.ReusableItems")] - public void CanDeploy_ReusableItemsToList() - { - var reusableHtml = ModelGeneratorService.GetRandomDefinition(); - var reusableText = ModelGeneratorService.GetRandomDefinition(); - - var model = SPMeta2Model.NewWebModel(web => - { - web.AddHostList(BuiltInListDefinitions.ReusableContent, list => - { - list.AddReusableHTMLItem(reusableHtml); - list.AddReusableTextItem(reusableText); - }); - }); - - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.ReusableItems")] - public void CanDeploy_ReusableItemsToFolder() - { - var reusableHtml = ModelGeneratorService.GetRandomDefinition(); - var reusableText = ModelGeneratorService.GetRandomDefinition(); - - var model = SPMeta2Model.NewWebModel(web => - { - web.AddHostList(BuiltInListDefinitions.ReusableContent, list => - { - list.AddRandomFolder(folder => - { - folder.AddReusableHTMLItem(reusableHtml); - folder.AddReusableTextItem(reusableText); - }); - }); - }); - - TestModel(model); - } - - #endregion - - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.BuiltInDefinitions; +using SPMeta2.Containers; +using SPMeta2.Definitions; +using SPMeta2.Definitions.ContentTypes; +using SPMeta2.Enumerations; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using SPMeta2.Standard.Definitions; +using SPMeta2.Standard.Syntax; +using SPMeta2.Syntax.Default; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class ReusableItemScenariosTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanup] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region tests + + [TestMethod] + [TestCategory("Regression.Scenarios.ReusableItems")] + public void CanDeploy_ReusableItemsToList() + { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); + + var reusableHtml = ModelGeneratorService.GetRandomDefinition(); + var reusableText = ModelGeneratorService.GetRandomDefinition(); + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.ReusableContent, list => + { + list.AddReusableHTMLItem(reusableHtml); + list.AddReusableTextItem(reusableText); + }); + }); + + TestModel(siteModel, model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.ReusableItems")] + public void CanDeploy_ReusableItemsToFolder() + { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); + + var reusableHtml = ModelGeneratorService.GetRandomDefinition(); + var reusableText = ModelGeneratorService.GetRandomDefinition(); + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.ReusableContent, list => + { + list.AddRandomFolder(folder => + { + folder.AddReusableHTMLItem(reusableHtml); + folder.AddReusableTextItem(reusableText); + }); + }); + }); + + TestModel(siteModel, model); + } + + #endregion + + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs index 06b7615e0..d104ce7a3 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs @@ -1,229 +1,228 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.BuiltInDefinitions; -using SPMeta2.Containers; -using SPMeta2.Containers.Standard; - -using SPMeta2.Definitions; -using SPMeta2.Enumerations; -using SPMeta2.Models; -using SPMeta2.Regression.Tests.Definitions; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using SPMeta2.Standard.Definitions; -using SPMeta2.Syntax.Default; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.BuiltInDefinitions; +using SPMeta2.Containers; +using SPMeta2.Containers.Standard; + +using SPMeta2.Definitions; +using SPMeta2.Enumerations; +using SPMeta2.Models; +using SPMeta2.Regression.Tests.Definitions; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using SPMeta2.Standard.Definitions; +using SPMeta2.Syntax.Default; using SPMeta2.Validation.Validators.Relationships; -using SPMeta2.Regression.Tests.Extensions; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class SP2013WorkflowScenariosTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanupAttribute] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region default - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013WebWorkflowAccosiation() - { - var model = SPMeta2Model - .NewWebModel(web => - { - AddWebWorkflow(web); - }); - - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013ListWorkflowAccosiation() - { - var model = SPMeta2Model - .NewWebModel(web => - { - AddListWorkflow(web); - }); - - TestModel(model); - } - - #endregion - - #region list workflow on sub webs - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013ListWorkflowAccosiation_OnHierarchicalWebs() - { - var level1Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l1{0}", Rnd.String()); - }); - - var level2Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l2{0}", Rnd.String()); - }); - - var model = SPMeta2Model - .NewWebModel(web => - { - web - .AddWeb(level1Web, l1w => - { - AddListWorkflow(l1w); - - l1w.AddWeb(level2Web, l2web => - { - AddListWorkflow(l2web); - }); - - }); - - AddListWorkflow(web); - }); - - TestModel(model); - } - - #endregion - - #region web workflow on sub webs - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013WebWorkflowAccosiation_OnHierarchicalWebs() - { - var level1Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l1{0}", Rnd.String()); - }); - - var level2Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l2{0}", Rnd.String()); - }); - - var model = SPMeta2Model - .NewWebModel(web => - { - web - .AddWeb(level1Web, l1w => - { - AddWebWorkflow(l1w); - - l1w.AddWeb(level2Web, l2web => - { - AddWebWorkflow(l2web); - }); - }); - - AddWebWorkflow(web); - }); - - TestModel(model); - - } - - #endregion - - #region utils - - protected ListDefinition GetTaskList() - { - return new ListDefinition - { - Title = Rnd.String(), - TemplateType = BuiltInListTemplateTypeId.Tasks, -#pragma warning disable 618 - Url = Rnd.String() -#pragma warning restore 618 - }; - } - - protected ListDefinition GetHistoryList() - { - return new ListDefinition - { - Title = Rnd.String(), - TemplateType = BuiltInListTemplateTypeId.WorkflowHistory, -#pragma warning disable 618 - Url = Rnd.String() -#pragma warning restore 618 - }; - } - - protected void AddWebWorkflow(WebModelNode web) - { - var workflow = ModelGeneratorService.GetRandomDefinition(); - - var historyList = GetHistoryList(); - var taskList = GetTaskList(); - - web - .AddList(historyList) - .AddList(taskList) - .AddSP2013Workflow(workflow) - .AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition - { - Name = Rnd.String(), - WorkflowDisplayName = workflow.DisplayName, -#pragma warning disable 618 - HistoryListUrl = historyList.GetListUrl(), - TaskListUrl = taskList.GetListUrl() -#pragma warning restore 618 - }); - } - - protected void AddListWorkflow(WebModelNode web) - { - var workflow = ModelGeneratorService.GetRandomDefinition(); - var workflowEnableList = ModelGeneratorService.GetRandomDefinition(); - - var historyList = GetHistoryList(); - var taskList = GetTaskList(); - - web - - .AddList(historyList) - .AddList(taskList) - .AddList(workflowEnableList, list => - { - list.AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition - { - Name = Rnd.String(), - WorkflowDisplayName = workflow.DisplayName, -#pragma warning disable 618 - HistoryListUrl = historyList.GetListUrl(), - TaskListUrl = taskList.GetListUrl() -#pragma warning restore 618 - }); - }) - .AddSP2013Workflow(workflow); - } - - #endregion - } - -} +using SPMeta2.Regression.Tests.Extensions; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class SP2013WorkflowScenariosTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanupAttribute] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region default + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013WebWorkflowAccosiation() + { + var model = SPMeta2Model + .NewWebModel(web => + { + AddWebWorkflow(web); + }); + + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013ListWorkflowAccosiation() + { + var model = SPMeta2Model.NewWebModel(web => + { + AddListWorkflow(web); + }); + + TestModel(model); + } + + #endregion + + #region list workflow on sub webs + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013ListWorkflowAccosiation_OnHierarchicalWebs() + { + var level1Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l1{0}", Rnd.String()); + }); + + var level2Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l2{0}", Rnd.String()); + }); + + var model = SPMeta2Model + .NewWebModel(web => + { + web + .AddWeb(level1Web, l1w => + { + AddListWorkflow(l1w); + + l1w.AddWeb(level2Web, l2web => + { + AddListWorkflow(l2web); + }); + + }); + + AddListWorkflow(web); + }); + + TestModel(model); + } + + #endregion + + #region web workflow on sub webs + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013WebWorkflowAccosiation_OnHierarchicalWebs() + { + var level1Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l1{0}", Rnd.String()); + }); + + var level2Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l2{0}", Rnd.String()); + }); + + var model = SPMeta2Model + .NewWebModel(web => + { + web + .AddWeb(level1Web, l1w => + { + AddWebWorkflow(l1w); + + l1w.AddWeb(level2Web, l2web => + { + AddWebWorkflow(l2web); + }); + }); + + AddWebWorkflow(web); + }); + + TestModel(model); + + } + + #endregion + + #region utils + + protected ListDefinition GetTaskList() + { + return new ListDefinition + { + Title = Rnd.String(), + TemplateType = BuiltInListTemplateTypeId.Tasks, +#pragma warning disable 618 + Url = Rnd.String() +#pragma warning restore 618 + }; + } + + protected ListDefinition GetHistoryList() + { + return new ListDefinition + { + Title = Rnd.String(), + TemplateType = BuiltInListTemplateTypeId.WorkflowHistory, +#pragma warning disable 618 + Url = Rnd.String() +#pragma warning restore 618 + }; + } + + protected void AddWebWorkflow(WebModelNode web) + { + var workflow = ModelGeneratorService.GetRandomDefinition(); + + var historyList = GetHistoryList(); + var taskList = GetTaskList(); + + web + .AddList(historyList) + .AddList(taskList) + .AddSP2013Workflow(workflow) + .AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition + { + Name = Rnd.String(), + WorkflowDisplayName = workflow.DisplayName, +#pragma warning disable 618 + HistoryListUrl = historyList.GetListUrl(), + TaskListUrl = taskList.GetListUrl() +#pragma warning restore 618 + }); + } + + protected void AddListWorkflow(WebModelNode web) + { + var workflow = ModelGeneratorService.GetRandomDefinition(); + var workflowEnableList = ModelGeneratorService.GetRandomDefinition(); + + var historyList = GetHistoryList(); + var taskList = GetTaskList(); + + web + + .AddList(historyList) + .AddList(taskList) + .AddList(workflowEnableList, list => + { + list.AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition + { + Name = Rnd.String(), + WorkflowDisplayName = workflow.DisplayName, +#pragma warning disable 618 + HistoryListUrl = historyList.GetListUrl(), + TaskListUrl = taskList.GetListUrl() +#pragma warning restore 618 + }); + }) + .AddSP2013Workflow(workflow); + } + + #endregion + } + +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs index 0a1288e2d..b9b1a1a66 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs @@ -418,18 +418,22 @@ public void CanDeploy_Webpart_With_AuthorizationFilter() var webModel = SPMeta2Model.NewWebModel(web => { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list.AddRandomWebPartPage(page => { - list.AddRandomWebPartPage(page => + page.AddRandomWebpart(webPart => { - page.AddRandomWebpart(webPart => - { - var wpDef = webPart.Value as WebPartDefinition; - wpDef.AuthorizationFilter = string.Format(";;;;{0}", securityGroupDef.Name); - }); + var wpDef = webPart.Value as WebPartDefinition; + wpDef.AuthorizationFilter = string.Format(";;;;{0}", securityGroupDef.Name); }); }); + }); }); @@ -441,29 +445,32 @@ public void CanDeploy_Webpart_With_AuthorizationFilter() [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_WebpartPage() { - var model = SPMeta2Model - .NewWebModel(web => + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWebPartPage(page => { - list - .AddRandomWebPartPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }) - .AddRandomWebPartPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }); + page + .AddRandomWebpart() + .AddRandomWebpart(); + }) + .AddRandomWebPartPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); }); - }); + }); + TestModel(model); } @@ -484,6 +491,11 @@ public void CanDeploy_WebpartTo_WebpartPage_WithCustomPageLayout() var model = SPMeta2Model.NewWebModel(web => { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); + web.AddHostList(BuiltInListDefinitions.SitePages, list => { list @@ -516,32 +528,35 @@ public void CanDeploy_WebpartTo_WebpartPage_WithCustomPageLayout() [TestCategory("Regression.Scenarios.Webparts")] public void CanDeploy_Webpart_WithTitleUrl_WithTokens() { - var model = SPMeta2Model - .NewWebModel(web => + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWebPartPage(page => { - list - .AddRandomWebPartPage(page => + page + .AddRandomWebpart(w => { - page - .AddRandomWebpart(w => - { - (w.Value as WebPartDefinition).TitleUrl = - string.Format("~sitecollection/{0}.html", Rnd.String()); - }) - .AddRandomWebpart(w => - { - (w.Value as WebPartDefinition).TitleUrl = - string.Format("~site/{0}.html", Rnd.String()); - - }); + (w.Value as WebPartDefinition).TitleUrl = + string.Format("~sitecollection/{0}.html", Rnd.String()); + }) + .AddRandomWebpart(w => + { + (w.Value as WebPartDefinition).TitleUrl = + string.Format("~site/{0}.html", Rnd.String()); + }); }); - }); + }); + TestModel(model); } @@ -621,24 +636,27 @@ public void CanDeploy_WebpartTo_PublishingPageWebPartZone() var webModel = SPMeta2Model.NewWebModel(web => { - web - .AddWebFeature(RegWebFeatures.Publishing) - .AddHostList(BuiltInListDefinitions.Pages, list => - { - list - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }) - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }); - }); + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.Pages, list => + { + list + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }) + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }); + }); }); @@ -651,77 +669,89 @@ public void CanDeploy_WebpartTo_PublishingPageWebPartZone() [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_PublishingPageContent() { - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.Pages, list => - { - list - .AddRandomPublishingPage(page => - { - var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); - var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); - var wpId11 = id_1 - .Replace("g_", string.Empty) - .Replace("_", "-"); + web + .AddHostList(BuiltInListDefinitions.Pages, list => + { + list + .AddRandomPublishingPage(page => + { + var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var wpId22 = id_2 - .Replace("g_", string.Empty) - .Replace("_", "-"); + var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var pageTemplate = new StringBuilder(); + var wpId11 = id_1 + .Replace("g_", string.Empty) + .Replace("_", "-"); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId11); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + var wpId22 = id_2 + .Replace("g_", string.Empty) + .Replace("_", "-"); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat(" SPMeta2 publishing page."); - pageTemplate.AppendFormat("
"); + var pageTemplate = new StringBuilder(); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId22); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId11); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - (page.Value as PublishingPageDefinition).Content = pageTemplate.ToString(); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat(" SPMeta2 publishing page."); + pageTemplate.AppendFormat("
"); - page - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_1; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_2; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_3; - wp.AddToPageContent = true; - }); - }); - }); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId22); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - }); + (page.Value as PublishingPageDefinition).Content = pageTemplate.ToString(); - TestModel(webModel); + page + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_1; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_2; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_3; + wp.AddToPageContent = true; + }); + }); + }); + + }); + + TestModel(siteModel, webModel); } [TestMethod] @@ -732,22 +762,25 @@ public void CanDeploy_WebpartTo_WikiPageContent_AsItIs() // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart() - .AddRandomWebpart(); - }); - }); - }); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart() + .AddRandomWebpart(); + }); + }); + }); TestModel(webModel); } @@ -784,22 +817,26 @@ public void CanDeploy_ScriptEditorTo_WikiPageContent_As_AddToPageContent() Rnd.String()) }; - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page.RegExcludeFromValidation(); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); - page.AddScriptEditorWebPart(scriptEditor1); - page.AddScriptEditorWebPart(scriptEditor2); - }); - }); - }); + web + .AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page.RegExcludeFromValidation(); + + page.AddScriptEditorWebPart(scriptEditor1); + page.AddScriptEditorWebPart(scriptEditor2); + }); + }); + }); TestModel(webModel); } @@ -825,47 +862,50 @@ public void CanDeploy_WebpartTo_WikiPageContent_As_AddToPageContent() ListUrl = BuiltInListDefinitions.SitePages.CustomUrl }; - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page.RegExcludeFromValidation(); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); - page - .AddListViewWebPart(listViewWebPartDef) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - wp.ZoneId = "wpz"; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - wp.ZoneId = "wpz"; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - wp.ZoneId = "wpz"; - wp.AddToPageContent = true; - }) - ; - }); - }); - }); + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page.RegExcludeFromValidation(); + + page + .AddListViewWebPart(listViewWebPartDef) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + wp.ZoneId = "wpz"; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + wp.ZoneId = "wpz"; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + wp.ZoneId = "wpz"; + wp.AddToPageContent = true; + }) + ; + }); + }); + }); TestModel(webModel); } @@ -875,77 +915,80 @@ public void CanDeploy_WebpartTo_WikiPageContent_As_AddToPageContent() [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_WikiPageContent() { - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page.RegExcludeFromValidation(); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); - var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page.RegExcludeFromValidation(); - var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var wpId11 = id_1 - .Replace("g_", string.Empty) - .Replace("_", "-"); + var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var wpId22 = id_2 - .Replace("g_", string.Empty) - .Replace("_", "-"); + var wpId11 = id_1 + .Replace("g_", string.Empty) + .Replace("_", "-"); - var pageTemplate = new StringBuilder(); + var wpId22 = id_2 + .Replace("g_", string.Empty) + .Replace("_", "-"); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId11); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + var pageTemplate = new StringBuilder(); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat(" SPMeta2 wiki page."); - pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId11); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId22); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat(" SPMeta2 wiki page."); + pageTemplate.AppendFormat("
"); - (page.Value as WikiPageDefinition).Content = pageTemplate.ToString(); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId22); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - page - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_1; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_2; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_3; - wp.AddToPageContent = true; - }); - }); - }); + (page.Value as WikiPageDefinition).Content = pageTemplate.ToString(); - }); + page + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_1; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_2; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_3; + wp.AddToPageContent = true; + }); + }); + }); + + }); TestModel(webModel); } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs index b63799e35..ab2ec83a0 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs @@ -60,11 +60,11 @@ public override void TryWithRetry(Func action, { TraceService.Warning((int)LogEventId.ModelProvision, string.Format("Coudn't perform action. Waiting and retrying [{1}/{2}]", - RetryTimeoutInMilliseconds, + retryTimeoutInMilliseconds, currentTryIndex, MaxRetryCount)); - if (currentTryIndex > retryTimeoutInMilliseconds) + if (currentTryIndex > maxTryCount) break; waiter(currentTryIndex, maxTryCount, retryTimeoutInMilliseconds); From 6532589bb7d52381f0095240556366c491b1f349 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 03:49:25 -0700 Subject: [PATCH 46/53] + SSOM 2013 full regression + Broken field links operation in content types #1006 --- SPMeta2/Regression/_helpers.ps1 | 36 ++++++ .../Regression/_ut_grid_baseline_config.ps1 | 104 ++++++++++++++++-- .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 89 ++++++++------- .../ModelHandlers/CSOMModelHandlerBase.cs | 6 + .../Definitions/ContentDatabaseDefinition.cs | 1 + 5 files changed, 182 insertions(+), 54 deletions(-) diff --git a/SPMeta2/Regression/_helpers.ps1 b/SPMeta2/Regression/_helpers.ps1 index 5cbcb1cc9..841319972 100644 --- a/SPMeta2/Regression/_helpers.ps1 +++ b/SPMeta2/Regression/_helpers.ps1 @@ -12,10 +12,46 @@ function Get-RegressionConfig() { return $config } +function Get-EnvironmentVariable($name) { + + $result = [System.Environment]::GetEnvironmentVariable($name) + if($result -ne $null) { return $result; } + + $result = [System.Environment]::GetEnvironmentVariable($name, "Machine") + if($result -ne $null) { return $result; } + + $result = [System.Environment]::GetEnvironmentVariable($name, "Process") + if($result -ne $null) { return $result; } + + $result = [System.Environment]::GetEnvironmentVariable($name, "User") + if($result -ne $null) { return $result; } + + return $null +} + if($dsc_configFilePath -eq $null) { + $dsc_configFilePath = "config.yaml" + + # environment specific? + $environmentSpecificConfigPath = Get-EnvironmentVariable "SPMeta2.Regression.Config.FilePath" + + if( [System.IO.File]::Exists($environmentSpecificConfigPath) -eq $true) { + $dsc_configFilePath = $environmentSpecificConfigPath + Write-Host "Using environment specific config file:[$dsc_configFilePath]" -ForegroundColor Green + } + else { + $dsc_configFilePath = "config.yaml" + Write-Host "Using default config file:[$dsc_configFilePath]" -ForegroundColor Green + + } } +if( [System.IO.File]::Exists($dsc_configFilePath) -eq $false) { + throw "Config file [$dsc_configFilePath] does not exist" +} + + $dsc_config = Get-RegressionConfig($dsc_configFilePath) $env_config = $dsc_config.Configuration.Environment $regression_config = $dsc_config.Configuration.RegressionTests diff --git a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 index 1b489294a..3015fa376 100644 --- a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 +++ b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 @@ -3,18 +3,9 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent . "$ScriptDirectory/_helpers.ps1" -foreach($server in $dsc_nodeNames) { - - Write-Host "Configuring server [$server]" -fore Green - - $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet - - if($isOnline -eq $true) - { - Write-Host "Server [$server] online. Processing..." -fore Green - - Invoke-Command -ScriptBlock { +$isParallerRun = $true +$configScript = { function Ensure-ISS-AppPools() { @@ -98,6 +89,45 @@ foreach($server in $dsc_nodeNames) { set-SPEnterpriseSearchService -PerformanceLevel Reduced } + + function Ensure-SecureStoreApplicationKey() + { + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $passPhrase, + [Parameter(Mandatory=$false)] [ValidateNotNullorEmpty()] [boolean] $force + ) + + Write-Host "Loading SharePoint API..." + Add-PSSnapin Microsoft.SharePoint.PowerShell + + $service = Get-SPserviceApplicationProxy | Where-Object { $_.TypeName -eq "Secure Store Service Application Proxy" } + + + if(($service.Properties["spmeta2.regression"] -eq $null) -or ($force -eq $true) ) + { + Write-Host "Creating new master key with password:[$passPhrase]" -fore Green + + Update-SPSecureStoreMasterKey -ServiceApplicationProxy $service -Passphrase $passPhrase > $null + Start-Sleep 5 + + Update-SPSecureStoreApplicationServerKey -ServiceApplicationProxy $service -Passphrase $passPhrase > $null + Start-Sleep 5 + + $service.Properties["spmeta2.regression"] = 1; + $service.Update() + + Write-Host "Master ket was created." -fore Green + } + else + { + Write-Host "Master key exists." -fore Green + } + } + + $computerName = [environment]::MachineName + + Write-Host "Runing on [$computerName]" + #return Ensure-AssociatedGroups @@ -106,15 +136,65 @@ foreach($server in $dsc_nodeNames) { Set-MSSQL-Ram (6 * 1024) + Ensure-SecureStoreApplicationKey "pass@word1" + Restart-SharePoint Ensure-ISS-AppPools Ensure-ISS-AppPools - } -computer $server +} + +$invokeParallelCmd = get-command -Name "Invoke-Parallel" -ErrorAction SilentlyContinue + +if($isParallerRun -eq $false) { + $invokeParallelCmd = $null +} + +if($invokeParallelCmd -eq $null) { + + Write-Host "Configuring servers [$dsc_nodeNames] sequentially" -fore Green + + foreach($server in $dsc_nodeNames) { + + Write-Host "Configuring server [$server]" -fore Green + + $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet + + if($isOnline -eq $true) + { + Write-Host "Server [$server] online. Processing..." -fore Green + + Invoke-Command -ScriptBlock $configScript -computer $server } else { Write-Host "Server [$server] is OFFLINE. Skipping Processing..." -fore Yellow } +} + +} else { + + Write-Host "Configuring servers [$dsc_nodeNames] in parallel" -fore Green + + $dsc_nodeNames | Invoke-Parallel -ScriptBlock { + + $server = $_ + + Write-Host "Configuring server [$server]" -fore Green + + $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet + + if($isOnline -eq $true) + { + Write-Host "Server [$server] online. Processing..." -fore Green + + Invoke-Command -ScriptBlock $configScript -computer $server + } + else + { + Write-Host "Server [$server] is OFFLINE. Skipping Processing..." -fore Yellow + } + + } } \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 index 5f3be1791..b788b0b45 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -6,11 +6,11 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $o365RuntimePath = "$PSScriptRoot\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" Write-Host "Loading SharePoint CSOM API" -fore Green - $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") - - foreach($filePath in $files) { - Write-Host "`tLoading assembly: [$filePath]" - $a = [System.Reflection.Assembly]::LoadFile($filePath) + $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") + + foreach($filePath in $files) { + Write-Host "`tLoading assembly: [$filePath]" + $a = [System.Reflection.Assembly]::LoadFile($filePath) } Configuration SPMeta2_UnitTestSettings_Clean @@ -126,23 +126,23 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for SharePoint:[$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -162,26 +162,26 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for O365: [$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) - - $context.Credentials = $credentials - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) + + $context.Credentials = $credentials + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -241,6 +241,11 @@ Configuration SPMeta2_UnitTestSettings Value = ($config.OnlineUserPassword) } + $env_vars += @{ + Name = "SPMeta2_DefaultSqlServerName" + Value = $NodeName + } + Node $NodeName { foreach($var in $env_vars) { diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs index 1bde33022..7b4f0738f 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs @@ -54,7 +54,13 @@ protected virtual object GetPropertyValue(object obj, string propName) protected virtual bool IsSharePointOnlineContext(ClientContext context) { +#if NET35 + return false; +#endif + +#if !NET35 return context.Credentials is SharePointOnlineCredentials; +#endif } #endregion diff --git a/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs b/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs index fcf5779fd..eb4328f11 100644 --- a/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs +++ b/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs @@ -42,6 +42,7 @@ public ContentDatabaseDefinition() [ExpectValidation] [DataMember] [IdentityKey] + [ExpectRequired] public string ServerName { get; set; } [ExpectValidation] From b838e0b29fc9c0d749baea091354a83154fba1c3 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 19:33:09 -0700 Subject: [PATCH 47/53] + O365 full regression + CanDeploy_ListModel_WithFolders fix under CSOM API --- .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 108 +++++++++++------- .../O365ProvisionRunner.cs | 68 +++++++++-- .../O365v16ProvisionRunner.cs | 67 +++++++++++ ...ntSetContentsWebPartDefinitionGenerator.cs | Bin 1520 -> 2352 bytes .../ClientSecurityGroupDefinitionValidator.cs | 12 +- .../Scenarios/SecurityGroupScenariosTest.cs | 19 +-- .../DocumentSetContentsWebPartDefinition.cs | Bin 2870 -> 2872 bytes 7 files changed, 213 insertions(+), 61 deletions(-) diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 index b788b0b45..22d0001ee 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -6,11 +6,11 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $o365RuntimePath = "$PSScriptRoot\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" Write-Host "Loading SharePoint CSOM API" -fore Green - $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") - - foreach($filePath in $files) { - Write-Host "`tLoading assembly: [$filePath]" - $a = [System.Reflection.Assembly]::LoadFile($filePath) + $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") + + foreach($filePath in $files) { + Write-Host "`tLoading assembly: [$filePath]" + $a = [System.Reflection.Assembly]::LoadFile($filePath) } Configuration SPMeta2_UnitTestSettings_Clean @@ -126,23 +126,23 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for SharePoint:[$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -162,26 +162,26 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for O365: [$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) - - $context.Credentials = $credentials - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) + + $context.Credentials = $credentials + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -246,6 +246,26 @@ Configuration SPMeta2_UnitTestSettings Value = $NodeName } + $env_vars += @{ + Name = "SPMeta2_O365_DefaultTestUserLogins" + Value = [string]::Join(",", ($config.TestUserLogins | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTestUserLogins" + Value = [string]::Join(",", ($config.TestUserLogins | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTestDomainUserEmails" + Value = [string]::Join(",", ($config.TestDomainUserEmails | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTestADGroups" + Value = [string]::Join(",", ($config.TestActiveDirectoryGroups | Foreach { [string]$_ } ) ) + } + Node $NodeName { foreach($var in $env_vars) { @@ -266,6 +286,10 @@ $config = @{ @{ ObjectModels = $regression_config.ObjectModels + TestUserLogins = $regression_config.TestData.UserLogins + TestActiveDirectoryGroups = $regression_config.TestData.ActiveDirectoryGroups + TestDomainUserEmails = $regression_config.TestData.DomainUserEmails + WebAppPort = $env_config.SharePoint.WebApp.Port SiteCollectionUrls = $env_config.SharePoint.SiteCollection.Urls diff --git a/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs index 2f2e6a5d2..11c227277 100644 --- a/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs @@ -21,6 +21,9 @@ using SPMeta2.Utils; using SPMeta2.CSOM.Standard.Services; using SPMeta2.Services; +using SPMeta2.CSOM.Extensions; +using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; namespace SPMeta2.Containers.O365 { @@ -221,20 +224,67 @@ private void SiteOnUrl(ModelNode model, string siteUrl) public override void DeployListModel(ModelNode model) { - - if (RandomBalancedUrls.Count > 0) + foreach (var webUrl in WebUrls) { - var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; - WebOnUrl(model, url); + ListOnUrl(model, webUrl); } - else - { + } - foreach (var webUrl in WebUrls) + private void ListOnUrl(ModelNode model, string webUrl) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); + + WithO365Context(webUrl, context => + { + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) { - WebOnUrl(model, webUrl); + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _provisionService.DeployModel(listHost, model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + } + + if (EnableDefinitionValidation) + { + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _validationService.DeployModel(listHost, model); + } } - } + }); } private void WebOnUrl(ModelNode model, string webUrl) diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index c0383a96e..6fbc43d90 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -21,6 +21,8 @@ using SPMeta2.Services; using SPMeta2.Utils; using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; +using SPMeta2.CSOM.Extensions; namespace SPMeta2.Containers.O365v16 { @@ -218,6 +220,71 @@ public override void DeployWebModel(ModelNode model) } } + public override void DeployListModel(ModelNode model) + { + foreach (var webUrl in WebUrls) + { + ListOnUrl(model, webUrl); + } + } + + private void ListOnUrl(ModelNode model, string webUrl) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); + + WithO365Context(webUrl, context => + { + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) + { + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _provisionService.DeployModel(listHost, model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + } + + if (EnableDefinitionValidation) + { + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _validationService.DeployModel(listHost, model); + } + } + }); + } + #endregion #region utils diff --git a/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/Webparts/DocumentSetContentsWebPartDefinitionGenerator.cs b/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/Webparts/DocumentSetContentsWebPartDefinitionGenerator.cs index fb7dc80b2ec2b1b6892cda4616d9aa3244c20808..96ab3ada573f6740fd6263da5935d73ff864389b 100644 GIT binary patch delta 477 zcma)&%}T>i5QUHV5mD?y6c@H8;HGW@rAxI?txDHfii?=07_<@6L@h;p1>;@$3NEDX zTnN5`FW@7HzJZ>(7C}Lf%O!Va&Ybxs?=z#h(d0yNTb|uUf*d_WND&k_PHlibGKM{P z*un{pc_M_&#f%bGJ?t`*=$05^akR4JW57g)0Ou^XSnBefvo*W_c(K&AIj^1#cd?Bh z^KhWe*VUU*sW;$i;|xu7c;fGo0aZ=%34-_vOdnOOs={1QSLX8NDYGg2J46h}`v{Lu z64CDP8}OA=6;ZdryU8dPLbS>5>v_>Hr7YX}!_(7!hxAKJy17a?v2GBnB3R0`rkpM< wWa(hM?AP#&AURvtwD!@SRu5KL-I*m@{_B}~HJth$_USj|{qI^A>dCHs0$$Q* { var srcProp = s.GetExpressionValue(def => def.Owner); - var dstProp = d.GetExpressionValue(ct => ct.GetOwnerLogin()); + var dstProp = d.GetExpressionValue(ct => ct.GetOwnerLogin()); + + var srcOwner = dstProp.Value.ToString().ToUpper().Replace("\\", "/"); + var dstOwner = dstProp.Value.ToString().ToUpper().Replace("\\", "/"); var isValid = dstProp.Value.ToString().ToUpper().Replace("\\", "/").EndsWith( - srcProp.Value.ToString().ToUpper().Replace("\\", "/")); + srcProp.Value.ToString().ToUpper().Replace("\\", "/")); + + if (!isValid) + { + isValid = dstOwner.Contains(srcOwner); + } return new PropertyValidationResult { diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs index 0a26be533..21cdb3957 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs @@ -45,6 +45,10 @@ public static void Cleanup() [TestCategory("Regression.Scenarios.SecurityGroup")] public void CanDeploy_SecurityGroup_Under_SecurityGroup() { + // TODO, handle O365 failure + // this ine would fail in O365, that's fine + // must only work onprem with 'AD' groups + var activeDirectoryOrGlobalO365Groups = RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.DefaultTestADGroups); if (activeDirectoryOrGlobalO365Groups.Count() == 0) @@ -58,14 +62,13 @@ public void CanDeploy_SecurityGroup_Under_SecurityGroup() def.Name = randomNestedGroup; }); - var siteModel = SPMeta2Model - .NewSiteModel(site => - { - site.AddSecurityGroup(spGroup, group => - { - group.AddSecurityGroup(domainGroup); - }); - }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSecurityGroup(spGroup, group => + { + group.AddSecurityGroup(domainGroup); + }); + }); TestModels(new ModelNode[] { siteModel }); } diff --git a/SPMeta2/SPMeta2.Standard/Definitions/Webparts/DocumentSetContentsWebPartDefinition.cs b/SPMeta2/SPMeta2.Standard/Definitions/Webparts/DocumentSetContentsWebPartDefinition.cs index 72ebc7824269230cd5d9973859521d2326fd708e..56f86f2e58a42f1d22b6d4194be8b0115e5f195b 100644 GIT binary patch delta 20 bcmdlcwnJ>g7Z&zlhD?SMhSbeJS!~$=P96r* delta 18 ZcmdlXwoPoq7Z%oVhE#^6&A(Y}*#JUb23r6C From d9e8ef2df9fe6aea62340cd8fb6c9f4966972f7e Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 19:49:36 -0700 Subject: [PATCH 48/53] + O365 full regression + TokenReplacementServiceTests fixes --- .../Impl/Services/TokenReplacementServiceTests.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs index 7bbfee9b6..1ad53d901 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs @@ -197,10 +197,14 @@ protected void TestModelAndUrl(ModelNode model, string expectedEndWithUrl) { hasHit = true; - if (e.Result.Value == expectedEndWithUrl) + if (e.Result.Value.EndsWith(expectedEndWithUrl)) { hasCorrectUrl = true; } + else + { + hasCorrectUrl = false; + } }; TestModel(model); From b212f95b7749d78fc2415f15f6fa6d9db159492f Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 20:00:57 -0700 Subject: [PATCH 49/53] + O365 full regression + MasterPageSettingsDefinitionScenariosTest fix --- .../Validation/ClientMasterPageSettingsDefinitionValidator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs index e48412b76..4243772b5 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs @@ -42,7 +42,7 @@ public override void DeployModel(object modelHost, DefinitionBase model) var srcProp = s.GetExpressionValue(def => def.SiteMasterPageUrl); var dstProp = d.GetExpressionValue(def => def.CustomMasterUrl); - var isValid = url == (string)dstProp.Value; + var isValid = ((string)dstProp.Value).EndsWith((string)url); return new PropertyValidationResult { @@ -75,7 +75,7 @@ public override void DeployModel(object modelHost, DefinitionBase model) var srcProp = s.GetExpressionValue(def => def.SystemMasterPageUrl); var dstProp = d.GetExpressionValue(def => def.MasterUrl); - var isValid = (string)url == (string)dstProp.Value; + var isValid = ((string)dstProp.Value).EndsWith((string)url); return new PropertyValidationResult { From 756a032dfff17dabfd76db99f0dfcd6bbaa5cc01 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 12 Apr 2017 19:55:44 -0700 Subject: [PATCH 50/53] + O365 regression + CanDeploy_DocumentLibrary_With_Custom_DocumentTemplateUrl fix --- .../Impl/Scenarios/ListScenariosTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs index 2c2996739..5937f3582 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs @@ -669,7 +669,7 @@ public void CanDeploy_DocumentLibrary_With_Custom_DocumentTemplateUrl() // add a clone second time with the template var listWithDocumentTemplate = randomList.Inherit(); #pragma warning disable 618 - listWithDocumentTemplate.DocumentTemplateUrl = string.Format("/" + randomList.GetListUrl() + "/Forms/" + templateFileName); + listWithDocumentTemplate.DocumentTemplateUrl = string.Format("~sitecollection/" + randomList.GetListUrl() + "/Forms/" + templateFileName); #pragma warning restore 618 web.AddList(listWithDocumentTemplate); From c92c5044c9819c0eb751edd29e4b7ec8811d976e Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 13 Apr 2017 18:50:08 -0700 Subject: [PATCH 51/53] + Add TryRetryService to implement try-retry logic #1010 + Added Regression.Services.DefaultTryRetryService tests + Green O365 regression testing for taxonomy related operations --- .../Services/DefaultTryRetryServiceTests.cs | 185 ++++++++++++++++++ .../Impl/Services/ServiceContainerTests.cs | 4 +- .../SPMeta2.Regression.Tests.csproj | 1 + .../Services/Impl/DefaultTryRetryService.cs | 41 +++- .../SPMeta2/Services/TryRetryServiceBase.cs | 1 + 5 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs new file mode 100644 index 000000000..ed5438414 --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs @@ -0,0 +1,185 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Containers.Services; +using SPMeta2.Containers.Services.Rnd; +using SPMeta2.Definitions; +using SPMeta2.Exceptions; +using SPMeta2.Services.Impl; +using System; + +namespace SPMeta2.Regression.Tests.Impl.Services +{ + [TestClass] + public class DefaultTryRetryServiceTests + { + #region constructors + + public DefaultTryRetryServiceTests() + { + Rnd = new DefaultRandomService(); + } + + #endregion + + #region properties + + public RandomService Rnd { get; set; } + + #endregion + + #region tests + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void CanCreate_DefaultTryRetryService() + { + var service = new DefaultTryRetryService(); + + Assert.IsNotNull(service); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldFail_OnMoreAttempts() + { + var service = new DefaultTryRetryService(); + var currentTryCount = 0; + + ExpectException(() => + { + service.TryWithRetry(() => + { + currentTryCount++; + return false; + }); + }); + + Assert.AreEqual(service.MaxRetryCount, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldWork_On_FirstAttempt() + { + var service = new DefaultTryRetryService(); + + var currentTryCount = 0; + var maxTryCount = Rnd.Int(5) + 1; + + service.TryWithRetry(() => + { + currentTryCount++; + return true; + }, maxTryCount, 50); + + Assert.AreEqual(1, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldWork_On_RandomAttempt() + { + var service = new DefaultTryRetryService(); + + var currentTryCount = 0; + + var maxTryCount = Rnd.Int(5) + 2; + var positiveTryCount = maxTryCount / 2 + 1; + + service.TryWithRetry(() => + { + currentTryCount++; + + if (positiveTryCount == currentTryCount) + return true; + + return false; + + }, maxTryCount, 50); + + Assert.AreEqual(positiveTryCount, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void CanOverride_MaxTryAttempts() + { + var service = new DefaultTryRetryService(); + + var currentTryCount = 0; + var maxTryCount = Rnd.Int(5) + 1; + + ExpectException(() => + { + service.TryWithRetry(() => + { + currentTryCount++; + return false; + }, maxTryCount, 50); + }); + + Assert.AreEqual(maxTryCount, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldFail_OnWrongParameters() + { + var service = new DefaultTryRetryService(); + + ExpectException(() => + { + service.TryWithRetry(null, 1, 50); + }); + + ExpectException(() => + { + service.TryWithRetry(() => + { + return true; + }, 1, 50, null); + }); + + ExpectException(() => + { + service.TryWithRetry(() => + { + return false; + }, -1, 50); + }); + + ExpectException(() => + { + service.TryWithRetry(() => + { + return false; + }, 1, -50); + }); + } + + protected void ExpectException(Action action) + where TException : Exception + { + var hasValidException = false; + var expectedExceptionType = typeof(TException); + + try + { + action(); + } + catch (Exception e) + { + hasValidException = e.GetType() == expectedExceptionType; + } + + Assert.IsTrue(hasValidException); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs index ed28551c9..3b234b6e7 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs @@ -38,7 +38,9 @@ public void ServiceContainer_Should_Have_DefaultServices() typeof(DefaultDiagnosticInfoService), typeof(ModelPrettyPrintServiceBase), - typeof(ModelDotGraphPrintServiceBase) + typeof(ModelDotGraphPrintServiceBase), + + typeof(TryRetryServiceBase) }; foreach (var serviceType in serviceTypes) diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index f0d27d060..f2fd22710 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -258,6 +258,7 @@ + diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs index ab2ec83a0..7b5107214 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs @@ -1,4 +1,5 @@ -using System; +using SPMeta2.Exceptions; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -41,6 +42,11 @@ protected TraceServiceBase TraceService #endregion public override void TryWithRetry(Func action) + { + TryWithRetry(action, MaxRetryCount); + } + + public override void TryWithRetry(Func action, int maxTryCount) { TryWithRetry(action, MaxRetryCount, RetryTimeoutInMilliseconds); } @@ -54,9 +60,12 @@ public override void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter) { - var currentTryIndex = 0; + ValidateParameters(action, maxTryCount, retryTimeoutInMilliseconds, waiter); + + var currentTryIndex = 1; + var actionResult = action(); - while (action() != true) + while (actionResult != true) { TraceService.Warning((int)LogEventId.ModelProvision, string.Format("Coudn't perform action. Waiting and retrying [{1}/{2}]", @@ -64,12 +73,36 @@ public override void TryWithRetry(Func action, currentTryIndex, MaxRetryCount)); - if (currentTryIndex > maxTryCount) + if (currentTryIndex >= maxTryCount) break; waiter(currentTryIndex, maxTryCount, retryTimeoutInMilliseconds); currentTryIndex++; + + actionResult = action(); + } + + if (actionResult != true) + { + throw new SPMeta2Exception(string.Format( + "Error while performing requested action. Tried [{0}] out of [{1}], raising exception", + currentTryIndex, maxTryCount)); } } + + private static void ValidateParameters(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter) + { + if (action == null) + throw new ArgumentNullException("action"); + + if (waiter == null) + throw new ArgumentNullException("waiter"); + + if (maxTryCount <= 0) + throw new ArgumentOutOfRangeException("maxTryCount must be greater than 0"); + + if (retryTimeoutInMilliseconds <= 0) + throw new ArgumentOutOfRangeException("retryTimeoutInMilliseconds must be greater than 0"); + } } } diff --git a/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs index 01119f91b..bb92fa9b4 100644 --- a/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs @@ -16,6 +16,7 @@ public abstract class TryRetryServiceBase #region methods public abstract void TryWithRetry(Func action); + public abstract void TryWithRetry(Func action, int maxTryCount); public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds); public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter); From 4180f8008470e0811a6400ca9cad9ab2fae2ef34 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 13 Apr 2017 21:17:25 -0700 Subject: [PATCH 52/53] SPMeta2 1.2.120, April 2017 --- SPMeta2/Build/build.json | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index e51b4a1ca..5cf940e86 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -284,7 +284,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -323,11 +323,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -368,11 +368,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -405,15 +405,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -446,11 +446,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -483,15 +483,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -525,11 +525,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -555,15 +555,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -589,11 +589,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -619,15 +619,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -653,11 +653,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -694,15 +694,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "Microsoft.SharePointOnline.CSOM", From 9a0d2cf452a8c200158321b2bd7ac64d579cc7c5 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 13 Apr 2017 21:21:29 -0700 Subject: [PATCH 53/53] + SPMeta2 1.2.120, April 2017 + assembly version 1.2.17104.0417 --- SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2/Properties/AssemblyInfo.cs | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs index d415ea936..49e68f197 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs index 0555bbd09..46e9cd6f9 100644 --- a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs index 36e1f3717..11f033529 100644 --- a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.17104.0417")] \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs index d6078c9b0..231fa7c70 100644 --- a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs index e77fe9e57..15deea26d 100644 --- a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs index d37656b35..8c2a30d4f 100644 --- a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs index 4d6b34d08..c21723570 100644 --- a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs index 495e20ae1..66c39bb42 100644 --- a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs index b87c409f7..1ca1da521 100644 --- a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs index 983fb0fe4..f6ac5aa03 100644 --- a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs index 48bb2f621..afd37ea9e 100644 --- a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs index 44a71f312..bc7d8d532 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs index 1db99efab..f8c7b3998 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs index 146bd5ffb..fe8ed4165 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1246")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs index ab4173853..143ef9adf 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs index 853435573..c2c5a9ff4 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs index a59cad00f..9b5cf2a5c 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs index 6ab6dd9fd..91e1ca507 100644 --- a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs index 4e3c96605..bf184884d 100644 --- a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs index 54ab8e737..0d47e1bc1 100644 --- a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs index 2a62bdd07..d8c8808a9 100644 --- a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs index 904477cce..2e0b5dbfd 100644 --- a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")]