protected override void ProcessWebpartProperties(WebPart webpartInstance, WebPartDefinition webpartModel)
        {
            base.ProcessWebpartProperties(webpartInstance, webpartModel);

            var typedWebpart = webpartInstance.WithAssertAndCast<ListViewWebPart>("webpartInstance", value => value.RequireNotNull());
            var typedModel = webpartModel.WithAssertAndCast<ListViewWebPartDefinition>("webpartModel", value => value.RequireNotNull());

            var web = _host.SPLimitedWebPartManager.Web;

            var targetWeb = web;

            if (!string.IsNullOrEmpty(typedModel.WebUrl) || typedModel.WebId.HasGuidValue())
                targetWeb = new LookupFieldModelHandler().GetTargetWeb(web.Site, typedModel.WebUrl, typedModel.WebId);

            var list = XsltListViewWebPartModelHandler.GetTargetList(targetWeb, typedModel.ListTitle, typedModel.ListUrl, typedModel.ListId);

            typedWebpart.ListName = list.ID.ToString();
            typedWebpart.ListId = list.ID;

            // view check
            if (list != null)
            {
                SPView view = null;

                if (typedModel.ViewId.HasGuidValue())
                    view = list.Views[typedModel.ViewId.Value];
                else if (!string.IsNullOrEmpty(typedModel.ViewName))
                    view = list.Views[typedModel.ViewName];

                if (view != null)
                {
                    typedWebpart.ViewGuid = view.ID.ToString("B").ToUpperInvariant();
                    typedWebpart.TitleUrl = view.ServerRelativeUrl;
                }
            }

            // able to 'reset', if NULL or use list-view based URLs
            if (!string.IsNullOrEmpty(typedModel.TitleUrl))
                typedWebpart.TitleUrl = typedModel.TitleUrl;
        }
        public override void DeployModel(object modelHost, DefinitionBase model)
        {
            // base validation
            base.DeployModel(modelHost, model);

            // web specific validation
            var host = modelHost.WithAssertAndCast<WebpartPageModelHost>("modelHost", value => value.RequireNotNull());
            var definition = model.WithAssertAndCast<ListViewWebPartDefinition>("model", value => value.RequireNotNull());

            WebPartExtensions.WithExistingWebPart(host.HostFile, definition, (spWebPartManager, spObject) =>
            {
                var web = spWebPartManager.Web;
                var typedObject = spObject as ListViewWebPart;

                var assert = ServiceFactory.AssertService
                    .NewAssert(definition, typedObject)
                    .ShouldNotBeNull(typedObject);

                var typedDefinition = definition;
                var targetWeb = web;

                // web url
                if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
                {
                    var lookupFieldModelHandler = new LookupFieldModelHandler();
                    targetWeb = lookupFieldModelHandler.GetTargetWeb(web.Site,
                                definition.WebUrl, definition.WebId);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.WebUrl);

                        var isValid = d.WebId == targetWeb.ID;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.WebUrl, "WebUrl is NULL. Skipping.");
                }

                if (typedDefinition.WebId.HasGuidValue())
                {
                    var lookupFieldModelHandler = new LookupFieldModelHandler();
                    targetWeb = lookupFieldModelHandler.GetTargetWeb(web.Site,
                                definition.WebUrl, definition.WebId);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.WebId);

                        var isValid = d.WebId == targetWeb.ID;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.WebId, "WebId is NULL. Skipping.");
                }

                var targetList = web.Lists[typedObject.ListId];

                var hasList = !string.IsNullOrEmpty(definition.ListTitle) ||
                              !string.IsNullOrEmpty(definition.ListUrl) ||
                              definition.ListId.HasValue;
                var hasView = !string.IsNullOrEmpty(definition.ViewName) ||
                              !string.IsNullOrEmpty(definition.ViewUrl) ||
                              definition.ViewId.HasValue; ;

                // list
                if (!string.IsNullOrEmpty(definition.ListTitle))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListTitle);
                        var dstProp = d.GetExpressionValue(o => o.ListId);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = targetList.ID == (Guid)dstProp.Value
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ListTitle, "ListTitle is null or empty. Skipping.");
                }

                if (!string.IsNullOrEmpty(definition.ListUrl))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListUrl);
                        var dstProp = d.GetExpressionValue(o => o.ListId);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = targetList.ID == (Guid)dstProp.Value
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ListUrl, "ListUrl is null or empty. Skipping.");
                }

                if (definition.ListId.HasValue && definition.ListId != default(Guid))
                {
                    assert.ShouldBeEqual(m => m.ListId, o => o.ListId);
                }
                else
                {
                    assert.SkipProperty(m => m.ListId, "ListId is null or empty. Skipping.");
                }

                // view
                if (definition.ViewId.HasValue)
                {
                    // web part gonna have hidden view
                    // so validation is a bit tricky, done by other properties

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcView = targetList.Views[s.ViewId.Value];
                        var dstView = targetList.Views[new Guid(typedObject.ViewGuid)];

                        var srcProp = s.GetExpressionValue(m => m.ViewId);
                        var dstProp = d.GetExpressionValue(o => o.ViewGuid);

                        var isValid = srcView.ViewFields.Count == dstView.ViewFields.Count
                                      && srcView.Query == dstView.Query;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ViewId, "ViewId is null or empty. Skipping.");
                }

                if (!string.IsNullOrEmpty(definition.ViewName))
                {
                    // web part gonna have hidden view
                    // so validation is a bit tricky, done by other properties

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcView = targetList.Views[s.ViewName];
                        var dstView = targetList.Views[new Guid(typedObject.ViewGuid)];

                        var srcProp = s.GetExpressionValue(m => m.ViewName);
                        var dstProp = d.GetExpressionValue(o => o.ViewGuid);

                        var isValid = srcView.ViewFields.Count == dstView.ViewFields.Count
                                      && srcView.Query == dstView.Query;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ViewName, "ViewName is null or empty. Skipping.");
                }

                if (!string.IsNullOrEmpty(definition.ViewUrl))
                {
                    // web part gonna have hidden view
                    // so validation is a bit tricky, done by other properties

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcView = targetList.Views.OfType<SPView>()
                                        .FirstOrDefault(v => v.ServerRelativeUrl.ToUpper().EndsWith(s.ViewUrl.ToUpper()));

                        var dstView = targetList.Views[new Guid(typedObject.ViewGuid)];

                        var srcProp = s.GetExpressionValue(m => m.ViewUrl);
                        var dstProp = d.GetExpressionValue(o => o.ViewGuid);

                        var isValid = srcView.ViewFields.Count == dstView.ViewFields.Count
                                      && srcView.Query == dstView.Query;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ViewUrl, "ViewName is null or empty. Skipping.");
                }

                //  title link
                if (string.IsNullOrEmpty(definition.TitleUrl))
                {
                    // list?
                    if (hasView)
                    {
                        assert.ShouldBeEqual((p, s, d) =>
                        {
                            var srcProp = s.GetExpressionValue(m => m.TitleUrl);
                            SPView srcView = null;

                            if (s.ViewId.HasValue && s.ViewId != default(Guid))
                                srcView = targetList.Views[s.ViewId.Value];
                            else if (!string.IsNullOrEmpty(s.ViewName))
                                srcView = targetList.Views[s.ViewName];
                            else if (!string.IsNullOrEmpty(s.ViewUrl))
                            {
                                srcView = targetList.Views.OfType<SPView>()
                                    .FirstOrDefault(v => v.ServerRelativeUrl.ToUpper().EndsWith(s.ViewUrl.ToUpper()));
                            }

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = srcView.ServerRelativeUrl.StartsWith(typedObject.TitleUrl)
                            };
                        });
                    }
                    else if (hasList)
                    {
                        assert.ShouldBeEqual((p, s, d) =>
                        {
                            var srcProp = s.GetExpressionValue(m => m.TitleUrl);

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = targetList.DefaultViewUrl.StartsWith(typedObject.TitleUrl)
                            };
                        });
                    }
                }
                else
                {
                    assert.ShouldBeEqual(m => m.TitleUrl, o => o.TitleUrl);
                }

                // skip it, it will be part of the .Toolbar validation
                assert.SkipProperty(m => m.ToolbarShowAlways, "");

                if (!string.IsNullOrEmpty(definition.Toolbar))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var list = XsltListViewWebPartModelHandler.GetTargetList(targetWeb,
                                        typedDefinition.ListTitle,
                                        typedDefinition.ListUrl,
                                        typedDefinition.ListId);

                        var targetView = list.Views[Guid.Parse((spObject as ListViewWebPart).ViewGuid)];
                        var htmlSchemaXml = XDocument.Parse(targetView.HtmlSchemaXml);

                        var useShowAlwaysValue =
                                     (typedDefinition.Toolbar.ToUpper() == BuiltInToolbarType.Standard.ToUpper())
                                     && typedDefinition.ToolbarShowAlways.HasValue
                                     && typedDefinition.ToolbarShowAlways.Value;

                        var toolbarNode = htmlSchemaXml.Root
                            .Descendants("Toolbar")
                            .FirstOrDefault();

                        // NONE? the node might not be there
                        if ((typedDefinition.Toolbar.ToUpper() == BuiltInToolbarType.None.ToUpper())
                            && (toolbarNode == null))
                        {
                            var srcProp = s.GetExpressionValue(m => m.Toolbar);

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = true
                            };
                        }
                        else
                        {
                            var toolBarValue = toolbarNode.GetAttributeValue("Type");

                            var srcProp = s.GetExpressionValue(m => m.Toolbar);
                            var isValid = toolBarValue.ToUpper() == definition.Toolbar.ToUpper();

                            if (useShowAlwaysValue)
                            {
                                var showAlwaysValue = toolbarNode.GetAttributeValue("ShowAlways");
                                isValid = isValid && (showAlwaysValue.ToUpper() == "TRUE");
                            }

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = isValid
                            };
                        }
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.Toolbar);
                }
            });
        }
        protected override void ProcessWebpartProperties(WebPart webpartInstance, WebPartDefinition webpartModel)
        {
            base.ProcessWebpartProperties(webpartInstance, webpartModel);

            var typedWebpart = webpartInstance.WithAssertAndCast<XsltListViewWebPart>("webpartInstance", value => value.RequireNotNull());
            var typedModel = webpartModel.WithAssertAndCast<XsltListViewWebPartDefinition>("webpartModel", value => value.RequireNotNull());

            var web = _host.SPLimitedWebPartManager.Web;

            // bind list
            var targetWeb = web;

            if (!string.IsNullOrEmpty(typedModel.WebUrl) || typedModel.WebId.HasGuidValue())
                targetWeb = new LookupFieldModelHandler().GetTargetWeb(web.Site, typedModel.WebUrl, typedModel.WebId);

            var list = GetTargetList(targetWeb, typedModel.ListTitle, typedModel.ListUrl, typedModel.ListId);

            if (list != null)
            {
                typedWebpart.ListName = list.ID.ToString("B").ToUpperInvariant();
                typedWebpart.TitleUrl = list.DefaultViewUrl;
            }

            // view check
            if (list != null)
            {
                SPView srcView = null;

                if (typedModel.ViewId.HasValue && typedModel.ViewId != default(Guid))
                    srcView = list.Views[typedModel.ViewId.Value];
                else if (!string.IsNullOrEmpty(typedModel.ViewName))
                    srcView = list.Views[typedModel.ViewName];

                if (srcView != null)
                {
                    if (!string.IsNullOrEmpty(typedWebpart.ViewGuid))
                    {
                        // update hidden view, otherwise we can have weird SharePoint exception
                        // https://github.com/SubPointSolutions/spmeta2/issues/487

                        var hiddenView = list.Views[new Guid(typedWebpart.ViewGuid)];

                        hiddenView.SetViewXml(srcView.GetViewXml());
                     
                        hiddenView.Update();
                    }
                    else
                    {
                        typedWebpart.ViewGuid = srcView.ID.ToString("B").ToUpperInvariant();
                    }

                    typedWebpart.TitleUrl = srcView.ServerRelativeUrl;
                }
            }

            // able to 'reset', if NULL or use list-view based URLs
            if (!string.IsNullOrEmpty(typedModel.TitleUrl))
                typedWebpart.TitleUrl = typedModel.TitleUrl;

            // weird, but it must be set to avoid null-ref exceptions
            typedWebpart.GhostedXslLink = "main.xsl";

#if !NET35
            // rest
            typedWebpart.JSLink = typedModel.JSLink;
#endif

            if (typedModel.CacheXslStorage.HasValue)
                typedWebpart.CacheXslStorage = typedModel.CacheXslStorage.Value;

            if (typedModel.CacheXslTimeOut.HasValue)
                typedWebpart.CacheXslTimeOut = typedModel.CacheXslTimeOut.Value;

#if !NET35
            if (typedModel.ShowTimelineIfAvailable.HasValue)
                typedWebpart.ShowTimelineIfAvailable = typedModel.ShowTimelineIfAvailable.Value;
#endif

            if (!string.IsNullOrEmpty(typedModel.Xsl))
            {
                typedWebpart.Xsl = typedModel.Xsl;
            }

            if (!string.IsNullOrEmpty(typedModel.XslLink))
            {
                var urlValue = typedModel.XslLink;

                typedWebpart.XslLink = urlValue;
            }

            if (!string.IsNullOrEmpty(typedModel.XmlDefinition))
            {
                typedWebpart.XmlDefinition = typedModel.XmlDefinition;
            }

            if (!string.IsNullOrEmpty(typedModel.XmlDefinitionLink))
            {
                var urlValue = typedModel.XmlDefinitionLink;
                typedWebpart.XmlDefinitionLink = urlValue;
            }

            if (!string.IsNullOrEmpty(typedModel.GhostedXslLink))
            {
                var urlValue = typedModel.GhostedXslLink;
                typedWebpart.GhostedXslLink = urlValue;
            }

            if (!string.IsNullOrEmpty(typedModel.BaseXsltHashKey))
                typedWebpart.BaseXsltHashKey = typedModel.BaseXsltHashKey;

            if (typedModel.DisableColumnFiltering.HasValue)
                typedWebpart.DisableColumnFiltering = typedModel.DisableColumnFiltering.Value;

#if !NET35
            if (typedModel.DisableSaveAsNewViewButton.HasValue)
                typedWebpart.DisableSaveAsNewViewButton = typedModel.DisableSaveAsNewViewButton.Value;

            if (typedModel.DisableViewSelectorMenu.HasValue)
                typedWebpart.DisableViewSelectorMenu = typedModel.DisableViewSelectorMenu.Value;

            if (typedModel.InplaceSearchEnabled.HasValue)
                typedWebpart.InplaceSearchEnabled = typedModel.InplaceSearchEnabled.Value;
#endif
        }
        protected override void OnAfterDeployModel(WebpartPageModelHost host, WebPartDefinition definition)
        {
            var typedDefinition = definition.WithAssertAndCast<ListViewWebPartDefinition>("webpartModel", value => value.RequireNotNull());

            if (!string.IsNullOrEmpty(typedDefinition.Toolbar))
            {
                var existingWebPart = host.SPLimitedWebPartManager
                    .WebParts
                    .OfType<System.Web.UI.WebControls.WebParts.WebPart>()
                    .FirstOrDefault(wp => !string.IsNullOrEmpty(wp.ID) &&
                                          wp.ID.ToUpper() == definition.Id.ToUpper());

                if (existingWebPart != null)
                {
                    // patching up the view -> ToolbarType
                    var xsltWebPart = existingWebPart as ListViewWebPart;

                    if (xsltWebPart != null)
                    {
                        if (!string.IsNullOrEmpty(xsltWebPart.ViewGuid))
                        {
                            var targetWeb = new LookupFieldModelHandler().GetTargetWeb(
                                            host.PageListItem.Web.Site,
                                            typedDefinition.WebUrl,
                                            typedDefinition.WebId);

                            var list = XsltListViewWebPartModelHandler.GetTargetList(targetWeb,
                                            typedDefinition.ListTitle,
                                            typedDefinition.ListUrl,
                                            typedDefinition.ListId);

                            var targetView = list.Views[ConvertUtils.ToGuid(xsltWebPart.ViewGuid).Value];

                            // fixing up the Toolbar
                            if (!string.IsNullOrEmpty(typedDefinition.Toolbar))
                            {
                                var htmlSchemaXml = XDocument.Parse(targetView.HtmlSchemaXml);

                                var useShowAlwaysValue =
                                    (typedDefinition.Toolbar.ToUpper() == BuiltInToolbarType.Standard.ToUpper())
                                    && typedDefinition.ToolbarShowAlways.HasValue
                                    && typedDefinition.ToolbarShowAlways.Value;

                                var toolbarNode = htmlSchemaXml.Root
                                    .Descendants("Toolbar")
                                    .FirstOrDefault();

                                if (toolbarNode == null)
                                {
                                    toolbarNode = new XElement("Toolbar");
                                    htmlSchemaXml.Root.Add(toolbarNode);
                                }

                                toolbarNode.SetAttributeValue("Type", typedDefinition.Toolbar);

                                if (useShowAlwaysValue)
                                {
                                    toolbarNode.SetAttributeValue("ShowAlways", "TRUE");
                                }
                                else
                                {
                                    XAttribute attr = toolbarNode.Attribute("ShowAlways");
                                    if (attr != null && string.IsNullOrEmpty(attr.Value))
                                        attr.Remove();
                                }

                                var field = targetView.GetType()
                                    .GetProperty("ListViewXml",
                                        BindingFlags.NonPublic | BindingFlags.Instance);

                                if (field != null)
                                {
                                    field.SetValue(targetView, htmlSchemaXml.Root.GetInnerXmlAsString(), null);
                                }
                            }

                            targetView.Update();
                        }
                    }
                }
            }
        }
        protected override void ProcessWebpartProperties(WebPart webpartInstance, WebPartDefinition definition)
        {
            base.ProcessWebpartProperties(webpartInstance, definition);

            var typedWebpart = webpartInstance.WithAssertAndCast<ContentByQueryWebPart>("webpartInstance", value => value.RequireNotNull());
            var typedDefinition = definition.WithAssertAndCast<ContentByQueryWebPartDefinition>("webpartModel", value => value.RequireNotNull());

            // xslt links
            if (!string.IsNullOrEmpty(typedDefinition.MainXslLink))
            {
                var linkValue = typedDefinition.MainXslLink;

                TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Original MainXslLink: [{0}]", linkValue);

                linkValue = TokenReplacementService.ReplaceTokens(new TokenReplacementContext
                {
                    Value = linkValue,
                    Context = CurrentHost.HostFile.Web
                }).Value;

                TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Token replaced MainXslLink: [{0}]", linkValue);

                typedWebpart.MainXslLink = linkValue;
            }

            if (!string.IsNullOrEmpty(typedDefinition.ItemXslLink))
            {
                var linkValue = typedDefinition.ItemXslLink;

                TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Original ItemXslLink: [{0}]", linkValue);

                linkValue = TokenReplacementService.ReplaceTokens(new TokenReplacementContext
                {
                    Value = linkValue,
                    Context = CurrentHost.HostFile.Web
                }).Value;

                TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Token replaced ItemXslLink: [{0}]", linkValue);

                typedWebpart.ItemXslLink = linkValue;
            }

            if (!string.IsNullOrEmpty(typedDefinition.HeaderXslLink))
            {
                var linkValue = typedDefinition.HeaderXslLink;

                TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Original HeaderXslLink: [{0}]", linkValue);

                linkValue = TokenReplacementService.ReplaceTokens(new TokenReplacementContext
                {
                    Value = linkValue,
                    Context = CurrentHost.HostFile.Web
                }).Value;

                TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Token replaced HeaderXslLink: [{0}]", linkValue);

                typedWebpart.HeaderXslLink = linkValue;
            }

            // styles
            if (!string.IsNullOrEmpty(typedDefinition.ItemStyle))
                typedWebpart.ItemStyle = typedDefinition.ItemStyle;

            if (!string.IsNullOrEmpty(typedDefinition.GroupStyle))
                typedWebpart.GroupStyle = typedDefinition.GroupStyle;

            // cache settings
            if (typedDefinition.UseCache.HasValue)
                typedWebpart.UseCache = typedDefinition.UseCache.Value;

            if (typedDefinition.CacheXslStorage.HasValue)
                typedWebpart.CacheXslStorage = typedDefinition.CacheXslStorage.Value;

            if (typedDefinition.CacheXslTimeOut.HasValue)
                typedWebpart.CacheXslTimeOut = typedDefinition.CacheXslTimeOut.Value;

            // item limit
            if (typedDefinition.ItemLimit.HasValue)
                typedWebpart.ItemLimit = typedDefinition.ItemLimit.Value;

            // mappings
            if (!string.IsNullOrEmpty(typedDefinition.DataMappings))
                typedWebpart.DataMappings = typedDefinition.DataMappings;

            if (!string.IsNullOrEmpty(typedDefinition.DataMappingViewFields))
                typedWebpart.DataMappingViewFields = typedDefinition.DataMappingViewFields;

            // misc
            if (typedDefinition.ShowUntargetedItems.HasValue)
                typedWebpart.ShowUntargetedItems = typedDefinition.ShowUntargetedItems.Value;

            if (typedDefinition.PlayMediaInBrowser.HasValue)
                typedWebpart.PlayMediaInBrowser = typedDefinition.PlayMediaInBrowser.Value;

            if (typedDefinition.UseCopyUtil.HasValue)
                typedWebpart.UseCopyUtil = typedDefinition.UseCopyUtil.Value;

            // FilterTypeXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterType1))
                typedWebpart.FilterType1 = typedDefinition.FilterType1;

            if (!string.IsNullOrEmpty(typedDefinition.FilterType2))
                typedWebpart.FilterType2 = typedDefinition.FilterType2;

            if (!string.IsNullOrEmpty(typedDefinition.FilterType3))
                typedWebpart.FilterType3 = typedDefinition.FilterType3;

            // FilterFieldXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterField1))
                typedWebpart.FilterField1 = typedDefinition.FilterField1;

            if (!string.IsNullOrEmpty(typedDefinition.FilterField2))
                typedWebpart.FilterField2 = typedDefinition.FilterField2;

            if (!string.IsNullOrEmpty(typedDefinition.FilterField3))
                typedWebpart.FilterField3 = typedDefinition.FilterField3;

            // FilterXXXIsCustomValue
            if (typedDefinition.Filter1IsCustomValue.HasValue)
                typedWebpart.Filter1IsCustomValue = typedDefinition.Filter1IsCustomValue.Value;

            if (typedDefinition.Filter2IsCustomValue.HasValue)
                typedWebpart.Filter2IsCustomValue = typedDefinition.Filter2IsCustomValue.Value;

            if (typedDefinition.Filter3IsCustomValue.HasValue)
                typedWebpart.Filter3IsCustomValue = typedDefinition.Filter3IsCustomValue.Value;

            // FilterValueXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterValue1))
                typedWebpart.FilterValue1 = typedDefinition.FilterValue1;

            if (!string.IsNullOrEmpty(typedDefinition.FilterValue2))
                typedWebpart.FilterValue2 = typedDefinition.FilterValue2;

            if (!string.IsNullOrEmpty(typedDefinition.FilterValue3))
                typedWebpart.FilterValue3 = typedDefinition.FilterValue3;

            if (!string.IsNullOrEmpty(typedDefinition.Filter1ChainingOperator))
            {
                typedWebpart.Filter1ChainingOperator = (ContentByQueryWebPart.FilterChainingOperator)
                   Enum.Parse(typeof(ContentByQueryWebPart.FilterChainingOperator), typedDefinition.Filter1ChainingOperator);
            }

            if (!string.IsNullOrEmpty(typedDefinition.Filter2ChainingOperator))
            {
                typedWebpart.Filter2ChainingOperator = (ContentByQueryWebPart.FilterChainingOperator)
                   Enum.Parse(typeof(ContentByQueryWebPart.FilterChainingOperator), typedDefinition.Filter2ChainingOperator);
            }

            // sorting
            if (!string.IsNullOrEmpty(typedDefinition.SortBy))
                typedWebpart.SortBy = typedDefinition.SortBy;

            if (!string.IsNullOrEmpty(typedDefinition.SortByDirection))
                typedWebpart.SortByDirection = (ContentByQueryWebPart.SortDirection)
                    Enum.Parse(typeof(ContentByQueryWebPart.SortDirection), typedDefinition.SortByDirection);

            if (!string.IsNullOrEmpty(typedDefinition.SortByFieldType))
                typedWebpart.SortByFieldType = typedDefinition.SortByFieldType;

            if (!string.IsNullOrEmpty(typedDefinition.GroupByDirection))
            {
                typedWebpart.GroupByDirection = (ContentByQueryWebPart.SortDirection)
                    Enum.Parse(typeof(ContentByQueryWebPart.SortDirection), typedDefinition.GroupByDirection);
            }

            // FilterOperatorXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterOperator1))
            {
                typedWebpart.FilterOperator1 = (ContentByQueryWebPart.FilterFieldQueryOperator)
                    Enum.Parse(typeof(ContentByQueryWebPart.FilterFieldQueryOperator), typedDefinition.FilterOperator1);
            }

            if (!string.IsNullOrEmpty(typedDefinition.FilterOperator2))
            {
                typedWebpart.FilterOperator2 = (ContentByQueryWebPart.FilterFieldQueryOperator)
                    Enum.Parse(typeof(ContentByQueryWebPart.FilterFieldQueryOperator), typedDefinition.FilterOperator2);
            }

            if (!string.IsNullOrEmpty(typedDefinition.FilterOperator3))
            {
                typedWebpart.FilterOperator3 = (ContentByQueryWebPart.FilterFieldQueryOperator)
                    Enum.Parse(typeof(ContentByQueryWebPart.FilterFieldQueryOperator), typedDefinition.FilterOperator3);
            }

            // FilterDisplayValueXXX

            if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue1))
                typedWebpart.FilterDisplayValue1 = typedDefinition.FilterDisplayValue1;

            if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue2))
                typedWebpart.FilterDisplayValue2 = typedDefinition.FilterDisplayValue2;

            if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue3))
                typedWebpart.FilterDisplayValue3 = typedDefinition.FilterDisplayValue3;

            // bindings
            if (typedDefinition.ServerTemplate.HasValue)
                typedWebpart.ServerTemplate = typedDefinition.ServerTemplate.ToString();

            if (!string.IsNullOrEmpty(typedDefinition.ContentTypeName))
                typedWebpart.ContentTypeName = typedDefinition.ContentTypeName;

            if (!string.IsNullOrEmpty(typedDefinition.ContentTypeBeginsWithId))
                typedWebpart.ContentTypeBeginsWithId = typedDefinition.ContentTypeBeginsWithId;

            if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
            {
                // go with OOTB one, no changes are required

                //var webLookup = new LookupFieldModelHandler();

                //using (var targetWeb = webLookup.GetTargetWeb(CurrentHost.HostFile.Web.Site,
                //    typedDefinition.WebUrl,
                //    typedDefinition.WebId))
                //{
                //    typedWebpart.WebUrl = targetWeb.ServerRelativeUrl;
                //}

                typedWebpart.WebUrl = typedDefinition.WebUrl;
            }

            #region list URL

            if (typedDefinition.ListId.HasGuidValue())
            {
                //typedWebpart.ListId = typedDefinition.ListId.Value;
                // fallback to ListGuid

                typedWebpart.ListGuid = typedDefinition.ListId.Value.ToString("D");
            }

            if (typedDefinition.ListGuid.HasGuidValue())
            {
                typedWebpart.ListGuid = typedDefinition.ListGuid.Value.ToString("D");
            }

            if (!string.IsNullOrEmpty(typedDefinition.ListName))
            {
                // lookup from the target web
                // fallback to ListGuid

                var webLookup = new LookupFieldModelHandler();

                using (var targetWeb = webLookup.GetTargetWeb(CurrentHost.HostFile.Web.Site,
                    typedDefinition.WebUrl,
                    typedDefinition.WebId))
                {
                    var list = targetWeb.Lists[typedDefinition.ListName];
                    typedWebpart.ListGuid = list.ID.ToString("D");
                }
            }

            if (!string.IsNullOrEmpty(typedDefinition.ListUrl))
            {
                // lookup from the target web
                // fallback to ListGuid

                var webLookup = new LookupFieldModelHandler();

                using (var targetWeb = webLookup.GetTargetWeb(CurrentHost.HostFile.Web.Site,
                    typedDefinition.WebUrl,
                    typedDefinition.WebId))
                {
                    var listUrl = SPUrlUtility.CombineUrl(targetWeb.ServerRelativeUrl, typedDefinition.ListUrl);
                    var list = targetWeb.GetList(listUrl);

                    typedWebpart.ListGuid = list.ID.ToString("D");
                }
            }

            #endregion

            // overrides
            if (!string.IsNullOrEmpty(typedDefinition.ListsOverride))
                typedWebpart.ListsOverride = typedDefinition.ListsOverride;

            if (!string.IsNullOrEmpty(typedDefinition.ViewFieldsOverride))
                typedWebpart.ViewFieldsOverride = typedDefinition.ViewFieldsOverride;

            if (!string.IsNullOrEmpty(typedDefinition.QueryOverride))
                typedWebpart.QueryOverride = typedDefinition.QueryOverride;

            if (!string.IsNullOrEmpty(typedDefinition.CommonViewFields))
                typedWebpart.CommonViewFields = typedDefinition.CommonViewFields;

            if (typedDefinition.FilterByAudience.HasValue)
                typedWebpart.FilterByAudience = typedDefinition.FilterByAudience.Value;
        }
        public override void DeployModel(object modelHost, DefinitionBase model)
        {
            ModelHost = modelHost;

            var definition = model.WithAssertAndCast<FieldDefinition>("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 SPFieldLookup;
            var typedDefinition = model.WithAssertAndCast<LookupFieldDefinition>("model", value => value.RequireNotNull());

            var typedFieldAssert = ServiceFactory.AssertService.NewAssert(model, typedDefinition, typedField);

            typedFieldAssert.ShouldBeEqual(m => m.AllowMultipleValues, o => o.AllowMultipleValues);

            if (typedDefinition.LookupWebId.HasValue)
            {
                typedFieldAssert.ShouldBeEqual(m => m.LookupWebId, o => o.LookupWebId);
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupWebId, "LookupWebId is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.RelationshipDeleteBehavior))
            {
                typedFieldAssert.ShouldBeEqual(m => m.RelationshipDeleteBehavior, o => o.GetRelationshipDeleteBehavior());
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.RelationshipDeleteBehavior, "RelationshipDeleteBehavior is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.RelationshipDeleteBehavior))
            {
                typedFieldAssert.ShouldBeEqual(m => m.RelationshipDeleteBehavior, o => o.GetRelationshipDeleteBehavior());
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.RelationshipDeleteBehavior, "RelationshipDeleteBehavior is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.RelationshipDeleteBehavior))
            {
                typedFieldAssert.ShouldBeEqual(m => m.RelationshipDeleteBehavior, o => o.GetRelationshipDeleteBehavior());
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.RelationshipDeleteBehavior, "RelationshipDeleteBehavior is NULL. Skipping.");
            }

            if (typedDefinition.CountRelated.HasValue)
            {
                typedFieldAssert.ShouldBeEqual(m => m.CountRelated, o => o.CountRelated);
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.CountRelated, "CountRelated is NULL. Skipping.");
            }

            // web url
            if (!string.IsNullOrEmpty(typedDefinition.LookupWebUrl))
            {
                var lookupFieldModelHandler = new LookupFieldModelHandler();
                var targetWeb = lookupFieldModelHandler.GetTargetWeb(GetCurrentSite(), typedDefinition);

                typedFieldAssert.ShouldBeEqual((p, s, d) =>
                {
                    var srcProp = s.GetExpressionValue(m => m.LookupWebUrl);

                    var isValid = d.LookupWebId == targetWeb.ID;

                    return new PropertyValidationResult
                    {
                        Tag = p.Tag,
                        Src = srcProp,
                        Dst = null,
                        IsValid = isValid
                    };
                });
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupWebUrl, "LookupWebUrl is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.LookupListTitle))
            {
                var lookupFieldModelHandler = new LookupFieldModelHandler();

                var targetWeb = lookupFieldModelHandler.GetTargetWeb(GetCurrentSite(), typedDefinition);
                var list = targetWeb.Lists[typedDefinition.LookupListTitle];

                typedFieldAssert.ShouldBeEqual((p, s, d) =>
                {
                    var srcProp = s.GetExpressionValue(m => m.LookupListTitle);

                    var isValid = list.ID == new Guid(typedField.LookupList);

                    return new PropertyValidationResult
                    {
                        Tag = p.Tag,
                        Src = srcProp,
                        Dst = null,
                        IsValid = isValid
                    };
                });
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupListTitle, "LookupListTitle is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.LookupListUrl))
            {
                var lookupFieldModelHandler = new LookupFieldModelHandler();

                var targetWeb = lookupFieldModelHandler.GetTargetWeb(GetCurrentSite(), typedDefinition);
                var list = targetWeb.GetList(SPUrlUtility.CombineUrl(targetWeb.ServerRelativeUrl, typedDefinition.LookupListUrl));

                typedFieldAssert.ShouldBeEqual((p, s, d) =>
                {
                    var srcProp = s.GetExpressionValue(m => m.LookupListUrl);

                    var isValid = list.ID == new Guid(typedField.LookupList);

                    return new PropertyValidationResult
                    {
                        Tag = p.Tag,
                        Src = srcProp,
                        Dst = null,
                        IsValid = isValid
                    };
                });
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupListUrl, "LookupListUrl is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.LookupList))
            {
                if (typedDefinition.LookupList.ToUpper() == "USERINFO")
                {
                    typedFieldAssert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.LookupList);

                        var isValid = GetCurrentSite().RootWeb.SiteUserInfoList.ID == new Guid(typedField.LookupList);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    typedFieldAssert.ShouldBeEqual(m => m.LookupList, o => o.LookupList);
                }
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupList, "LookupList is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.LookupField))
            {
                typedFieldAssert.ShouldBeEqual(m => m.LookupField, o => o.LookupField);
            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupField, "LookupField is NULL. Skipping.");
            }
        }
        public override void DeployModel(object modelHost, DefinitionBase model)
        {
            // base validation
            base.DeployModel(modelHost, model);

            // web specific validation
            var host = modelHost.WithAssertAndCast<WebpartPageModelHost>("modelHost", value => value.RequireNotNull());
            var definition = model.WithAssertAndCast<XsltListViewWebPartDefinition>("model", value => value.RequireNotNull());

            //var item = host.PageListItem;

            WebPartExtensions.WithExistingWebPart(host.HostFile, definition, (spWebPartManager, spObject) =>
            {
                var web = spWebPartManager.Web;
                var typedObject = spObject as XsltListViewWebPart;

                var assert = ServiceFactory.AssertService
                    .NewAssert(definition, typedObject)
                    .ShouldNotBeNull(typedObject);

                var typedDefinition = definition;
                var targetWeb = web;

                // web url
                if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
                {
                    var lookupFieldModelHandler = new LookupFieldModelHandler();
                    targetWeb = lookupFieldModelHandler.GetTargetWeb(web.Site,
                                definition.WebUrl, definition.WebId);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.WebUrl);

                        var isValid = d.WebId == targetWeb.ID;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.WebUrl, "WebUrl is NULL. Skipping.");
                }

                if (typedDefinition.WebId.HasGuidValue())
                {
                    var lookupFieldModelHandler = new LookupFieldModelHandler();
                    targetWeb = lookupFieldModelHandler.GetTargetWeb(web.Site,
                                definition.WebUrl, definition.WebId);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.WebId);

                        var isValid = d.WebId == targetWeb.ID;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.WebId, "WebId is NULL. Skipping.");
                }

                var targetList = web.Lists[typedObject.ListId];

                var hasList = !string.IsNullOrEmpty(definition.ListTitle) ||
                              !string.IsNullOrEmpty(definition.ListUrl) ||
                              definition.ListId.HasValue;
                var hasView = !string.IsNullOrEmpty(definition.ViewName) ||
                              definition.ViewId.HasValue; ;

                if (definition.CacheXslStorage.HasValue)
                    assert.ShouldBeEqual(m => m.CacheXslStorage, o => o.CacheXslStorage);
                else
                    assert.SkipProperty(m => m.CacheXslStorage, "CacheXslStorage is null or empty.");

                if (definition.CacheXslTimeOut.HasValue)
                    assert.ShouldBeEqual(m => m.CacheXslTimeOut, o => o.CacheXslTimeOut);
                else
                    assert.SkipProperty(m => m.CacheXslTimeOut, "CacheXslTimeOut is null or empty.");

                if (definition.ShowTimelineIfAvailable.HasValue)
                    assert.ShouldBeEqual(m => m.ShowTimelineIfAvailable, o => o.ShowTimelineIfAvailable);
                else
                    assert.SkipProperty(m => m.ShowTimelineIfAvailable, "ShowTimelineIfAvailable is null or empty.");

                // list
                if (!string.IsNullOrEmpty(definition.ListTitle))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListTitle);
                        var dstProp = d.GetExpressionValue(o => o.ListId);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = targetList.ID == (Guid)dstProp.Value
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ListTitle, "ListTitle is null or empty. Skipping.");
                }

                if (!string.IsNullOrEmpty(definition.ListUrl))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListUrl);
                        var dstProp = d.GetExpressionValue(o => o.ListId);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = targetList.ID == (Guid)dstProp.Value
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ListUrl, "ListUrl is null or empty. Skipping.");
                }

                if (definition.ListId.HasValue && definition.ListId != default(Guid))
                {
                    assert.ShouldBeEqual(m => m.ListId, o => o.ListId);
                }
                else
                {
                    assert.SkipProperty(m => m.ListId, "ListId is null or empty. Skipping.");
                }

                // view
                if (definition.ViewId.HasValue)
                {
                    // web part gonna have hidden view
                    // so validation is a bit tricky, done by other properties

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcView = targetList.Views[s.ViewId.Value];
                        var dstView = typedObject.View;

                        var srcProp = s.GetExpressionValue(m => m.ViewId);
                        var dstProp = d.GetExpressionValue(o => o.View);

                        var isValid = srcView.ViewFields.Count == dstView.ViewFields.Count
                                      && srcView.Query == dstView.Query;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ViewId, "ViewId is null or empty. Skipping.");
                }

                if (!string.IsNullOrEmpty(definition.ViewName))
                {
                    // web part gonna have hidden view
                    // so validation is a bit tricky, done by other properties

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcView = targetList.Views[s.ViewName];
                        var dstView = typedObject.View;

                        var srcProp = s.GetExpressionValue(m => m.ViewName);
                        var dstProp = d.GetExpressionValue(o => o.View);

                        var isValid = srcView.ViewFields.Count == dstView.ViewFields.Count
                                      && srcView.Query == dstView.Query;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.ViewName, "ViewName is null or empty. Skipping.");
                }

                // JSLink
                assert.ShouldBeEqual(m => m.JSLink, o => o.JSLink);

                if (definition.InplaceSearchEnabled.HasValue)
                    assert.ShouldBeEqual(m => m.InplaceSearchEnabled, o => o.InplaceSearchEnabled);
                else
                    assert.SkipProperty(m => m.InplaceSearchEnabled, "InplaceSearchEnabled is null or empty.");

                if (definition.DisableSaveAsNewViewButton.HasValue)
                    assert.ShouldBeEqual(m => m.DisableSaveAsNewViewButton, o => o.DisableSaveAsNewViewButton);
                else
                    assert.SkipProperty(m => m.DisableSaveAsNewViewButton, "DisableSaveAsNewViewButton is null or empty.");

                if (definition.DisableColumnFiltering.HasValue)
                    assert.ShouldBeEqual(m => m.DisableColumnFiltering, o => o.DisableColumnFiltering);
                else
                    assert.SkipProperty(m => m.DisableColumnFiltering, "DisableColumnFiltering is null or empty.");

                if (definition.DisableViewSelectorMenu.HasValue)
                    assert.ShouldBeEqual(m => m.DisableViewSelectorMenu, o => o.DisableViewSelectorMenu);
                else
                    assert.SkipProperty(m => m.DisableViewSelectorMenu, "DisableViewSelectorMenu is null or empty.");

                // title link
                if (string.IsNullOrEmpty(definition.TitleUrl))
                {
                    // list?
                    if (hasView)
                    {
                        assert.ShouldBeEqual((p, s, d) =>
                        {
                            var srcProp = s.GetExpressionValue(m => m.TitleUrl);
                            var srcView = string.IsNullOrEmpty(s.ViewName) ?
                                targetList.Views[s.ViewId.Value] :
                                targetList.Views[s.ViewName];

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = srcView.ServerRelativeUrl.StartsWith(typedObject.TitleUrl)
                            };
                        });
                    }
                    else if (hasList)
                    {
                        assert.ShouldBeEqual((p, s, d) =>
                        {
                            var srcProp = s.GetExpressionValue(m => m.TitleUrl);

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = targetList.DefaultViewUrl.StartsWith(typedObject.TitleUrl)
                            };
                        });
                    }
                }
                else
                {
                    assert.ShouldBeEqual(m => m.TitleUrl, o => o.TitleUrl);
                }

                if (!string.IsNullOrEmpty(definition.XslLink))
                    assert.ShouldBeEqual(m => m.XslLink, o => o.XslLink);
                else
                    assert.SkipProperty(m => m.XslLink);

                if (!string.IsNullOrEmpty(definition.XmlDefinitionLink))
                    assert.ShouldBeEqual(m => m.XmlDefinitionLink, o => o.XmlDefinitionLink);
                else
                    assert.SkipProperty(m => m.XmlDefinitionLink);

                if (!string.IsNullOrEmpty(definition.GhostedXslLink))
                    assert.ShouldBeEqual(m => m.GhostedXslLink, o => o.GhostedXslLink);
                else
                    assert.SkipProperty(m => m.GhostedXslLink);

                if (!string.IsNullOrEmpty(definition.BaseXsltHashKey))
                    assert.ShouldBeEqual(m => m.BaseXsltHashKey, o => o.BaseXsltHashKey);
                else
                    assert.SkipProperty(m => m.BaseXsltHashKey);

                if (!string.IsNullOrEmpty(definition.XmlDefinition))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.XmlDefinition);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = d.XmlDefinition.Contains("BaseViewID=\"2\"")
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.XmlDefinition);

                if (!string.IsNullOrEmpty(definition.Xsl))
                    assert.ShouldBeEqual(m => m.Xsl, o => o.Xsl);
                else
                    assert.SkipProperty(m => m.Xsl);

                // skip it, it will be part of the .Toolbar validation
                assert.SkipProperty(m => m.ToolbarShowAlways, "");

                if (!string.IsNullOrEmpty(definition.Toolbar))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var targetView = (spObject as XsltListViewWebPart).View;
                        var htmlSchemaXml = XDocument.Parse(targetView.HtmlSchemaXml);

                        var useShowAlwaysValue =
                                     (typedDefinition.Toolbar.ToUpper() == BuiltInToolbarType.Standard.ToUpper())
                                     && typedDefinition.ToolbarShowAlways.HasValue
                                     && typedDefinition.ToolbarShowAlways.Value;

                        var toolbarNode = htmlSchemaXml.Root
                            .Descendants("Toolbar")
                            .FirstOrDefault();

                        // NONE? the node might not be there
                        if ((typedDefinition.Toolbar.ToUpper() == BuiltInToolbarType.None.ToUpper())
                            && (toolbarNode == null))
                        {
                            var srcProp = s.GetExpressionValue(m => m.Toolbar);

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = true
                            };
                        }
                        else
                        {
                            var toolBarValue = toolbarNode.GetAttributeValue("Type");

                            var srcProp = s.GetExpressionValue(m => m.Toolbar);
                            var isValid = toolBarValue.ToUpper() == definition.Toolbar.ToUpper();

                            if (useShowAlwaysValue)
                            {
                                var showAlwaysValue = toolbarNode.GetAttributeValue("ShowAlways");
                                isValid = isValid && (showAlwaysValue.ToUpper() == "TRUE");
                            }

                            return new PropertyValidationResult
                            {
                                Tag = p.Tag,
                                Src = srcProp,
                                Dst = null,
                                IsValid = isValid
                            };
                        }
                    });
                }
                else
                {
                    assert.SkipProperty(m => m.Toolbar);
                }

            });
        }
        public override void DeployModel(object modelHost, DefinitionBase model)
        {
            // base validation
            base.DeployModel(modelHost, model);

            // content editor specific validation

            var host = modelHost.WithAssertAndCast<WebpartPageModelHost>("modelHost", value => value.RequireNotNull());
            var typedDefinition = model.WithAssertAndCast<ContentByQueryWebPartDefinition>("model", value => value.RequireNotNull());

            CurrentHost = host;

            //var item = host.PageListItem;

            WebPartExtensions.WithExistingWebPart(host.HostFile, typedDefinition, (spWebPartManager, spObject) =>
            {
                var typedWebPart = spObject as ContentByQueryWebPart;

                var assert = ServiceFactory.AssertService
                                           .NewAssert(typedDefinition, typedWebPart)
                                           .ShouldNotBeNull(typedWebPart);

                if (!string.IsNullOrEmpty(typedDefinition.ContentTypeBeginsWithId))
                    assert.ShouldBeEqual(m => m.ContentTypeBeginsWithId, o => o.ContentTypeBeginsWithId);
                else
                    assert.SkipProperty(m => m.ContentTypeBeginsWithId, "ContentTypeBeginsWithId is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.DataMappings))
                    assert.ShouldBeEqual(m => m.DataMappings, o => o.DataMappings);
                else
                    assert.SkipProperty(m => m.DataMappings, "DataMappings is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.DataMappingViewFields))
                    assert.ShouldBeEqual(m => m.DataMappingViewFields, o => o.DataMappingViewFields);
                else
                    assert.SkipProperty(m => m.DataMappingViewFields, "DataMappingViewFields is null or empty, skipping.");

                // filter display value 1-2-3
                if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue1))
                    assert.ShouldBeEqual(m => m.FilterDisplayValue1, o => o.FilterDisplayValue1);
                else
                    assert.SkipProperty(m => m.FilterDisplayValue1, "FilterDisplayValue1 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue2))
                    assert.ShouldBeEqual(m => m.FilterDisplayValue2, o => o.FilterDisplayValue2);
                else
                    assert.SkipProperty(m => m.FilterDisplayValue2, "FilterDisplayValue2 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue3))
                    assert.ShouldBeEqual(m => m.FilterDisplayValue3, o => o.FilterDisplayValue3);
                else
                    assert.SkipProperty(m => m.FilterDisplayValue3, "FilterDisplayValue3 is null or empty, skipping.");

                // operators 1-2-3
                if (!string.IsNullOrEmpty(typedDefinition.FilterOperator1))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.FilterOperator1);
                        var isValid = false;

                        isValid = s.FilterOperator1.ToLower() == d.FilterOperator1.ToString().ToLower();

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.FilterOperator1, "FilterOperator1 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterOperator2))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.FilterOperator2);
                        var isValid = false;

                        isValid = s.FilterOperator2.ToLower() == d.FilterOperator2.ToString().ToLower();

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.FilterOperator2, "FilterOperator2 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterOperator3))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.FilterOperator3);
                        var isValid = false;

                        isValid = s.FilterOperator3.ToLower() == d.FilterOperator3.ToString().ToLower();

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.FilterOperator3, "FilterOperator3 is null or empty, skipping.");

                // type 1-2-3
                if (!string.IsNullOrEmpty(typedDefinition.FilterType1))
                    assert.ShouldBeEqual(m => m.FilterType1, o => o.FilterType1);
                else
                    assert.SkipProperty(m => m.FilterType1, "FilterType1 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterType2))
                    assert.ShouldBeEqual(m => m.FilterType2, o => o.FilterType2);
                else
                    assert.SkipProperty(m => m.FilterType2, "FilterType2 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterType3))
                    assert.ShouldBeEqual(m => m.FilterType3, o => o.FilterType3);
                else
                    assert.SkipProperty(m => m.FilterType3, "FilterType3 is null or empty, skipping.");

                // filter values 1-2-3
                if (!string.IsNullOrEmpty(typedDefinition.FilterValue1))
                    assert.ShouldBeEqual(m => m.FilterValue1, o => o.FilterValue1);
                else
                    assert.SkipProperty(m => m.FilterValue1, "FilterValue1 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterValue2))
                    assert.ShouldBeEqual(m => m.FilterValue2, o => o.FilterValue2);
                else
                    assert.SkipProperty(m => m.FilterValue2, "FilterValue2 is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.FilterValue3))
                    assert.ShouldBeEqual(m => m.FilterValue3, o => o.FilterValue3);
                else
                    assert.SkipProperty(m => m.FilterValue3, "FilterValue3 is null or empty, skipping.");

                // sorting

                if (!string.IsNullOrEmpty(typedDefinition.SortBy))
                    assert.ShouldBeEqual(m => m.SortBy, o => o.SortBy);
                else
                    assert.SkipProperty(m => m.SortBy, "SortBy is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.SortByFieldType))
                    assert.ShouldBeEqual(m => m.SortByFieldType, o => o.SortByFieldType);
                else
                    assert.SkipProperty(m => m.SortByFieldType, "SortByFieldType is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.SortByDirection))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.SortByDirection);
                        var isValid = false;

                        isValid = s.SortByDirection.ToLower() == d.SortByDirection.ToString().ToLower();

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.SortByDirection, "SortByDirection is null or empty, skipping.");

                // xslt
                if (!string.IsNullOrEmpty(typedDefinition.GroupStyle))
                    assert.ShouldBeEqual(m => m.GroupStyle, o => o.GroupStyle);
                else
                    assert.SkipProperty(m => m.GroupStyle, "GroupStyle is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.ItemStyle))
                    assert.ShouldBeEqual(m => m.ItemStyle, o => o.ItemStyle);
                else
                    assert.SkipProperty(m => m.ItemStyle, "ItemStyle is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.ItemXslLink))
                {
                    // TODO
                }
                else
                    assert.SkipProperty(m => m.ItemXslLink, "ItemXslLink is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.MainXslLink))
                {
                    // TODO
                }
                else
                    assert.SkipProperty(m => m.MainXslLink, "MainXslLink is null or empty, skipping.");

                // list name/url/id
                if (!string.IsNullOrEmpty(typedDefinition.ListName))
                {
                    // TODO
                }
                else
                    assert.SkipProperty(m => m.ListName, "ListName is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.ListUrl))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListUrl);
                        var isValid = false;

                        // resolve web / url by list URL
                        // check ListId

                        var webLookup = new LookupFieldModelHandler();

                        using (var targetWeb = webLookup.GetTargetWeb(CurrentHost.HostFile.Web.Site,
                                                           typedDefinition.WebUrl,
                                                           typedDefinition.WebId))
                        {
                            var listUrl = SPUrlUtility.CombineUrl(targetWeb.ServerRelativeUrl, typedDefinition.ListUrl);
                            var list = targetWeb.GetList(listUrl);

                            isValid = typedWebPart.ListGuid == list.ID.ToString("D");
                        }

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.ListUrl, "ListUrl is null or empty, skipping.");

                if (typedDefinition.ListGuid.HasValue)
                {
                    // TODO
                }
                else
                    assert.SkipProperty(m => m.ListGuid, "ListGuid is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.WebUrl);
                        var isValid = false;

                        isValid = s.WebUrl == d.WebUrl;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.WebUrl, "WebUrl is null or empty, skipping.");

                if (typedDefinition.WebId.HasValue)
                {
                    // TODO
                }
                else
                    assert.SkipProperty(m => m.WebId, "WebId is null or empty, skipping.");

                // misc

                if (typedDefinition.ItemLimit.HasValue)
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ItemLimit);
                        var isValid = false;

                        isValid = s.ItemLimit == d.ItemLimit;

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.ItemLimit, "ItemLimit is null or empty, skipping.");

                if (typedDefinition.PlayMediaInBrowser.HasValue)
                {
                    assert.ShouldBeEqual(m => m.PlayMediaInBrowser, o => o.PlayMediaInBrowser);
                }
                else
                    assert.SkipProperty(m => m.PlayMediaInBrowser, "PlayMediaInBrowser is null or empty, skipping.");

                if (typedDefinition.ShowUntargetedItems.HasValue)
                {
                    assert.ShouldBeEqual(m => m.ShowUntargetedItems, o => o.ShowUntargetedItems);
                }
                else
                    assert.SkipProperty(m => m.ShowUntargetedItems, "ShowUntargetedItems is null or empty, skipping.");

                if (typedDefinition.UseCopyUtil.HasValue)
                {
                    assert.ShouldBeEqual(m => m.UseCopyUtil, o => o.UseCopyUtil);
                }
                else
                    assert.SkipProperty(m => m.UseCopyUtil, "UseCopyUtil is null or empty, skipping.");

                if (typedDefinition.ServerTemplate.HasValue)
                {
                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ServerTemplate);
                        var isValid = false;

                        isValid = s.ServerTemplate == ConvertUtils.ToInt(d.ServerTemplate);

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                else
                    assert.SkipProperty(m => m.ServerTemplate, "ServerTemplate is null or empty, skipping.");

            });
        }