protected override void InternalOnAfterWebPartProvision(WebPartProcessingContext provisionContext)
        {
            base.InternalOnAfterWebPartProvision(provisionContext);

            var webPartModel = provisionContext.WebPartDefinition;

            var listItemModelHost = provisionContext.ListItemModelHost;
            var typedDefinition = webPartModel.WithAssertAndCast<ListViewWebPartDefinition>("model", value => value.RequireNotNull());

            var webPartStoreKey = provisionContext.WebPartStoreKey;
            var context = provisionContext.ListItemModelHost.HostWeb.Context;

            var bindContext = XsltListViewWebPartModelHandler.LookupBindContext(listItemModelHost,
                                    typedDefinition.WebUrl, typedDefinition.WebId,
                                    typedDefinition.ListUrl, typedDefinition.ListTitle, typedDefinition.ListId,
                                    typedDefinition.ViewName, typedDefinition.ViewId,
                                    typedDefinition.TitleUrl);

            if (provisionContext.WebPartStoreKey.HasValue
                && provisionContext.WebPartStoreKey.Value != default(Guid))
            {
                var targetWeb = listItemModelHost.HostWeb;

                if (typedDefinition.WebId.HasGuidValue() || !string.IsNullOrEmpty(typedDefinition.WebUrl))
                {
                    targetWeb = new LookupFieldModelHandler()
                                    .GetTargetWeb(this.CurrentClientContext.Site, typedDefinition.WebUrl, typedDefinition.WebId);
                }

                var list = XsltListViewWebPartModelHandler.LookupList(targetWeb, typedDefinition.ListUrl, typedDefinition.ListTitle, typedDefinition.ListId);
                var hiddenView = list.Views.GetById(provisionContext.WebPartStoreKey.Value);

                context.Load(hiddenView, s => s.HtmlSchemaXml);

                context.Load(hiddenView);
                context.ExecuteQueryWithTrace();

                // patching the toolbar value

                if (!string.IsNullOrEmpty(typedDefinition.Toolbar))
                {
                    var htmlSchemaXml = XDocument.Parse(hiddenView.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();
                    }

                    hiddenView.ListViewXml = htmlSchemaXml.Root.GetInnerXmlAsString();

                    hiddenView.Update();
                    context.ExecuteQueryWithTrace();
                }
            }
        }
        public override void DeployModel(object modelHost, DefinitionBase model)
        {
            var definition = model.WithAssertAndCast<FieldDefinition>("model", value => value.RequireNotNull());
            var spObject = GetField(modelHost, definition);

            HostList = ExtractListFromHost(modelHost);
            HostSite = ExtractSiteFromHost(modelHost);

            var assert = ServiceFactory.AssertService.NewAssert(model, definition, spObject);

            ValidateField(assert, spObject, definition);

            var typedField = spObject.Context.CastTo<FieldLookup>(spObject);
            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.LookupWebUrl))
            {

            }
            else
            {
                typedFieldAssert.SkipProperty(m => m.LookupWebUrl, "LookupWebUrl is NULL. Skipping.");
            }

            if (!string.IsNullOrEmpty(typedDefinition.RelationshipDeleteBehavior))
            {
                typedFieldAssert.ShouldBeEqual((p, s, d) =>
                {
                    var srcProp = s.GetExpressionValue(m => m.RelationshipDeleteBehavior);
                    var isValid = s.RelationshipDeleteBehavior == d.RelationshipDeleteBehavior.ToString();

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

            // web url
            if (!string.IsNullOrEmpty(typedDefinition.LookupWebUrl))
            {
                var lookupFieldModelHandler = new LookupFieldModelHandler();
                var targetWeb = lookupFieldModelHandler.GetTargetWeb(HostSite, 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 site = HostSite;
                var context = site.Context;

                var lookupFieldModelHandler = new LookupFieldModelHandler();
                var web = lookupFieldModelHandler.GetTargetWeb(site, typedDefinition);


                context.Load(web);
                context.ExecuteQueryWithTrace();

                var list = web.Lists.GetByTitle(typedDefinition.LookupListTitle);

                context.Load(list);
                context.ExecuteQueryWithTrace();

                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 site = HostSite;
                var context = site.Context;


                var lookupFieldModelHandler = new LookupFieldModelHandler();
                var web = lookupFieldModelHandler.GetTargetWeb(site, typedDefinition);


                context.Load(web);
                context.ExecuteQueryWithTrace();

                var list = web.QueryAndGetListByUrl(UrlUtility.CombineUrl(web.ServerRelativeUrl, typedDefinition.LookupListUrl));

                context.Load(list);
                context.ExecuteQueryWithTrace();

                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 site = HostSite;
                        var context = site.Context;

                        var userInfoList = site.RootWeb.SiteUserInfoList;
                        context.Load(userInfoList);
                        context.ExecuteQueryWithTrace();

                        var isValid = userInfoList.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.DeployModel(modelHost, model);

            var listItemModelHost = modelHost.WithAssertAndCast<ListItemModelHost>("modelHost", value => value.RequireNotNull());
            var definition = model.WithAssertAndCast<ListViewWebPartDefinition>("model", value => value.RequireNotNull());

            var context = listItemModelHost.HostClientContext;

            WithExistingWebPart(listItemModelHost.HostFile, definition, spObject =>
            {
                var assert = ServiceFactory.AssertService
                                           .NewAssert(model, definition, spObject)
                                                 .ShouldNotBeNull(spObject);

                var typedDefinition = definition;

                if (typedDefinition.WebId.HasGuidValue())
                {
                    // TODO
                }
                else
                {
                    assert.SkipProperty(m => m.WebId, "WebId is NULL. Skipping.");
                }

                if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
                {
                    // TODO
                }
                else
                {
                    assert.SkipProperty(m => m.WebUrl, "WebUrl is NULL. Skipping.");
                }

                // list
                if (!string.IsNullOrEmpty(definition.ListTitle))
                {
                    var listId = new Guid(CurrentWebPartXml.GetListViewWebPartProperty("ListId"));
                    var list = LookupList(listItemModelHost, definition);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListTitle);
                        var isValid = list.Id == listId;

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

                if (!string.IsNullOrEmpty(definition.ListUrl))
                {
                    var listId = new Guid(CurrentWebPartXml.GetListViewWebPartProperty("ListId"));
                    var list = LookupList(listItemModelHost, definition);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListUrl);
                        var isValid = list.Id == listId;

                        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 (definition.ListId.HasGuidValue())
                {
                    var listId = new Guid(CurrentWebPartXml.GetListViewWebPartProperty("ListId"));
                    var list = LookupList(listItemModelHost, definition);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListId);
                        var isValid = list.Id == listId;

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

                if (definition.ViewId.HasGuidValue())
                {
                    var list = LookupList(listItemModelHost, definition);
                    var bindContext = LookupBindContext(listItemModelHost, definition);

                    var viewBindingXml = XDocument.Parse(CurrentWebPartXml.GetListViewWebPartProperty("ListViewXml"));
                    var viewId = new Guid(viewBindingXml.Root.GetAttributeValue("Name"));

                    var bindedView = list.Views.GetById(viewId);
                    var targetView = list.Views.GetById(definition.ViewId.Value);

                    context.Load(bindedView, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit);
                    context.Load(targetView, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit);

                    context.ExecuteQueryWithTrace();

                    var isValid = false;

                    // these are two different views, just CAML and field count
                    isValid = (bindedView.ViewFields.Count == targetView.ViewFields.Count)
                              && (bindedView.ViewQuery == targetView.ViewQuery)
                              && (bindedView.RowLimit == targetView.RowLimit);

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

                        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))
                {
                    var list = LookupList(listItemModelHost, definition);
                    var bindContext = LookupBindContext(listItemModelHost, definition);

                    var viewBindingXml = XDocument.Parse(CurrentWebPartXml.GetListViewWebPartProperty("ListViewXml"));
                    var viewId = new Guid(viewBindingXml.Root.GetAttributeValue("Name"));

                    var bindedView = list.Views.GetById(viewId);
                    var targetView = list.Views.GetByTitle(definition.ViewName);

                    context.Load(bindedView, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit);
                    context.Load(targetView, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit);

                    context.ExecuteQueryWithTrace();

                    var isValid = false;

                    // these are two different views, just CAML and field count
                    isValid = (bindedView.ViewFields.Count == targetView.ViewFields.Count)
                              && (bindedView.ViewQuery == targetView.ViewQuery)
                              && (bindedView.RowLimit == targetView.RowLimit);

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

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

                // 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 targetWeb = listItemModelHost.HostWeb;

                        if (typedDefinition.WebId.HasGuidValue() || !string.IsNullOrEmpty(typedDefinition.WebUrl))
                        {
                            targetWeb = new LookupFieldModelHandler()
                                            .GetTargetWeb(this.CurrentClientContext.Site, typedDefinition.WebUrl, typedDefinition.WebId);
                        }

                        var list = XsltListViewWebPartModelHandler.LookupList(targetWeb,
                                        typedDefinition.ListUrl,
                                        typedDefinition.ListTitle,
                                        typedDefinition.WebId);

                        var xmlDefinition = ConvertUtils.ToString(
                            CurrentWebPartXml.Root.Descendants(
                                ((XNamespace)"http://schemas.microsoft.com/WebPart/v2/ListView") + "ListViewXml")
                            .First().Value);

                        var xmlDefinitionDoc = XDocument.Parse(xmlDefinition);

                        var viewId = new Guid(xmlDefinitionDoc.Root.GetAttributeValue("Name"));

                        var hiddenView = list.Views.GetById(viewId);
                        context.Load(hiddenView, v => v.HtmlSchemaXml);
                        context.ExecuteQueryWithTrace();

                        var htmlSchemaXml = XDocument.Parse(hiddenView.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);
                }
            });
        }
        internal static ListBindContext LookupBindContext(ListItemModelHost listItemModelHost,
           string webUrl, Guid? webId,
           string listUrl, string listTitle, Guid? listId,
           string viewTitle, Guid? viewId,
            string webPartTitleUrl
            )
        {
            var result = new ListBindContext
            {

            };

            var web = listItemModelHost.HostWeb;
            var context = listItemModelHost.HostWeb.Context;

            var targetWeb = listItemModelHost.HostWeb;

            if (webId.HasGuidValue() || !string.IsNullOrEmpty(webUrl))
            {
                targetWeb = new LookupFieldModelHandler()
                                .GetTargetWeb(listItemModelHost.HostClientContext.Site,
                                        webUrl, webId);
            }

            var list = LookupList(targetWeb, listUrl, listTitle, listId);

            View view = null;

            if (viewId.HasValue && viewId != default(Guid))
                view = list.Views.GetById(viewId.Value);
            else if (!string.IsNullOrEmpty(viewTitle))
                view = list.Views.GetByTitle(viewTitle);

            context.Load(list, l => l.Id);
            context.Load(list, l => l.DefaultViewUrl);
            context.Load(list, l => l.Title);

            // TODO, https://github.com/SubPointSolutions/spmeta2/issues/765
            // list.DefaultView is not available, so a full fetch for list view is a must for SP2010.

            #if !NET35
            context.Load(list, l => l.DefaultView);
            #endif

            if (view != null)
            {
                context.Load(view);
                context.ExecuteQueryWithTrace();

            #if !NET35
                result.OriginalView = list.DefaultView;
                result.OriginalViewId = list.DefaultView.Id;
            #endif

                result.TargetView = view;
                result.TargetViewId = view.Id;

                result.TitleUrl = view.ServerRelativeUrl;
            }
            else
            {
                context.ExecuteQueryWithTrace();
            }

            result.ListId = list.Id;
            result.List = list;

            if (webPartTitleUrl == null)
            {
                if (string.IsNullOrEmpty(result.TitleUrl))
                    result.TitleUrl = list.DefaultViewUrl;
            }

            #if !NET35
            result.DefaultViewId = list.DefaultView.Id;
            #endif

            return result;
        }
        private List LookupList(ListItemModelHost listItemModelHost, 
            XsltListViewWebPartDefinition wpModel
            , out Guid webId)
        {
            var web = listItemModelHost.HostWeb;
            var context = web.Context;

            if (wpModel.WebId.HasGuidValue() || !string.IsNullOrEmpty(wpModel.WebUrl))
            {
                web = new LookupFieldModelHandler()
                                .GetTargetWeb(listItemModelHost.HostClientContext.Site,
                                        wpModel.WebUrl, wpModel.WebId);

                webId = web.Id;
            }
            else
            {
                context.Load(web);
                context.Load(web, w => w.Id);

                context.ExecuteQueryWithTrace();

                webId = web.Id;
            }

            List list = null;

            if (!string.IsNullOrEmpty(wpModel.ListUrl))
            {
                list = web.QueryAndGetListByUrl(wpModel.ListUrl);
            }
            else if (!string.IsNullOrEmpty(wpModel.ListTitle))
            {
                list = web.Lists.GetByTitle(wpModel.ListTitle);
            }
            else if (wpModel.ListId != default(Guid))
            {
                list = web.Lists.GetById(wpModel.ListId.Value);
            }
            else
            {
                throw new SPMeta2Exception("ListUrl, ListTitle or ListId should be defined.");
            }

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

            var listItemModelHost = modelHost.WithAssertAndCast<ListItemModelHost>("modelHost", value => value.RequireNotNull());
            var definition = model.WithAssertAndCast<XsltListViewWebPartDefinition>("model", value => value.RequireNotNull());

            var web = listItemModelHost.HostWeb;
            var context = web.Context;

            var pageItem = listItemModelHost.HostListItem;

            WithExistingWebPart(listItemModelHost.HostFile, definition, spObject =>
            {
                var assert = ServiceFactory.AssertService
                                           .NewAssert(model, definition, spObject)
                                                 .ShouldNotBeNull(spObject);

                var typedDefinition = definition;

                if (typedDefinition.WebId.HasGuidValue())
                {
                    // TODO
                }
                else
                {
                    assert.SkipProperty(m => m.WebId, "WebId is NULL. Skipping.");
                }

                if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
                {
                           var webId = default(Guid);
                           var bindContext = LookupBindContext(listItemModelHost, typedDefinition, out webId);
                    // web id should be the same

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.WebUrl);
                        var isValid = webId == new  Guid(CurrentWebPartXml.GetWebId());

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

                // list
                if (!string.IsNullOrEmpty(definition.ListTitle))
                {
                    var listId = new Guid(CurrentWebPartXml.GetListId());
                    var list = LookupList(listItemModelHost, definition);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListTitle);
                        var isValid = list.Id == listId;

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

                if (!string.IsNullOrEmpty(definition.ListUrl))
                {
                    var listId = new Guid(CurrentWebPartXml.GetListId());
                    var list = LookupList(listItemModelHost, definition);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListUrl);
                        var isValid = list.Id == listId;

                        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 (definition.ListId.HasGuidValue())
                {
                    var listId = new Guid(CurrentWebPartXml.GetListId());
                    var list = LookupList(listItemModelHost, definition);

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ListId);
                        var isValid = list.Id == listId;

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

                // list view
                if (definition.ViewId.HasGuidValue())
                {
                    var list = LookupList(listItemModelHost, definition);
                    var bindContext = LookupBindContext(listItemModelHost, definition);

                    var viewBindingXml = XDocument.Parse(CurrentWebPartXml.GetProperty("XmlDefinition"));
                    var viewId = new Guid(viewBindingXml.Root.GetAttributeValue("Name"));

                    var bindedView = list.Views.GetById(viewId);
                    var targetView = list.Views.GetById(definition.ViewId.Value);

                    context.Load(bindedView, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit);
                    context.Load(targetView, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit);

                    context.ExecuteQueryWithTrace();

                    var isValid = false;

                    // these are two different views, just CAML and field count
                    isValid = (bindedView.ViewFields.Count == targetView.ViewFields.Count)
                              && (bindedView.ViewQuery == targetView.ViewQuery)
                              && (bindedView.RowLimit == targetView.RowLimit);

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

                        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))
                {
                    var list = LookupList(listItemModelHost, definition);
                    var bindContext = LookupBindContext(listItemModelHost, definition);

                    var viewBindingXml = XDocument.Parse(CurrentWebPartXml.GetProperty("XmlDefinition"));
                    var viewId = new Guid(viewBindingXml.Root.GetAttributeValue("Name"));

                    var bindedView = list.Views.GetById(viewId);
                    var targetView = list.Views.GetByTitle(definition.ViewName);

                    context.Load(bindedView, l => l.BaseViewId, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit, l => l.JSLink);
                    context.Load(targetView, l => l.BaseViewId, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit, l => l.JSLink);

                    context.ExecuteQueryWithTrace();

                    var isValid = false;

                    // these are two different views, just CAML and field count
                    isValid = (bindedView.ViewFields.Count == targetView.ViewFields.Count)
                              && (bindedView.ViewQuery == targetView.ViewQuery)
                              && (bindedView.RowLimit == targetView.RowLimit)
                              && (bindedView.JSLink == targetView.JSLink)
                              && (bindedView.BaseViewId == targetView.BaseViewId);

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

                        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))
                {
                    var list = LookupList(listItemModelHost, definition);
                    var bindContext = LookupBindContext(listItemModelHost, definition);

                    var viewBindingXml = XDocument.Parse(CurrentWebPartXml.GetProperty("XmlDefinition"));
                    var viewId = new Guid(viewBindingXml.Root.GetAttributeValue("Name"));

                    var bindedView = list.Views.GetById(viewId);

                    var views = list.Views;

                    context.Load(views, v => v.Include(r => r.ServerRelativeUrl));
                    context.ExecuteQueryWithTrace();

                    var targetView = views.ToArray()
                                .FirstOrDefault(v => v.ServerRelativeUrl.ToUpper().EndsWith(definition.ViewUrl.ToUpper()));

                    context.Load(bindedView, l => l.BaseViewId, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit, l => l.JSLink);
                    context.Load(targetView, l => l.BaseViewId, l => l.ViewFields, l => l.ViewQuery, l => l.RowLimit, l => l.JSLink);

                    context.ExecuteQueryWithTrace();

                    var isValid = false;

                    // these are two different views, just CAML and field count
                    isValid = (bindedView.ViewFields.Count == targetView.ViewFields.Count)
                              && (bindedView.ViewQuery == targetView.ViewQuery)
                              && (bindedView.RowLimit == targetView.RowLimit)
                              && (bindedView.JSLink == targetView.JSLink)
                              && (bindedView.BaseViewId == targetView.BaseViewId);

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

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

                // jslink
                if (!string.IsNullOrEmpty(definition.JSLink))
                {
                    var jsLinkValue = CurrentWebPartXml.GetJSLink();

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.JSLink);
                        var isValid = definition.JSLink.ToUpper() == jsLinkValue.ToUpper();

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

                // the rest
                if (definition.CacheXslTimeOut.HasValue)
                {
                    var value = ConvertUtils.ToInt(CurrentWebPartXml.GetProperty("CacheXslTimeOut"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.CacheXslTimeOut);
                        var isValid = definition.CacheXslTimeOut == value;

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

                if (definition.CacheXslStorage.HasValue)
                {
                    var value = ConvertUtils.ToBool(CurrentWebPartXml.GetProperty("CacheXslStorage"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.CacheXslStorage);
                        var isValid = definition.CacheXslStorage == value;

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

                if (definition.ShowTimelineIfAvailable.HasValue)
                {
                    var value = ConvertUtils.ToBool(CurrentWebPartXml.GetProperty("ShowTimelineIfAvailable"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.ShowTimelineIfAvailable);
                        var isValid = definition.ShowTimelineIfAvailable == value;

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

                if (definition.InplaceSearchEnabled.HasValue)
                {
                    var value = ConvertUtils.ToBool(CurrentWebPartXml.GetProperty("InplaceSearchEnabled"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.InplaceSearchEnabled);
                        var isValid = definition.InplaceSearchEnabled == value;

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

                if (definition.DisableSaveAsNewViewButton.HasValue)
                {
                    var value = ConvertUtils.ToBool(CurrentWebPartXml.GetProperty("DisableSaveAsNewViewButton"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.DisableSaveAsNewViewButton);
                        var isValid = definition.DisableSaveAsNewViewButton == value;

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

                if (definition.DisableColumnFiltering.HasValue)
                {
                    var value = ConvertUtils.ToBool(CurrentWebPartXml.GetProperty("DisableColumnFiltering"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.DisableColumnFiltering);
                        var isValid = definition.DisableColumnFiltering == value;

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

                if (definition.DisableViewSelectorMenu.HasValue)
                {
                    var value = ConvertUtils.ToBool(CurrentWebPartXml.GetProperty("DisableViewSelectorMenu"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.DisableViewSelectorMenu);
                        var isValid = definition.DisableViewSelectorMenu == value;

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

                if (!string.IsNullOrEmpty(definition.BaseXsltHashKey))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("BaseXsltHashKey"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.BaseXsltHashKey);
                        var isValid = definition.BaseXsltHashKey == value;

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

                if (!string.IsNullOrEmpty(definition.GhostedXslLink))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("GhostedXslLink"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.GhostedXslLink);
                        var isValid = definition.GhostedXslLink == value;

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

                // xsl
                if (!string.IsNullOrEmpty(definition.Xsl))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("Xsl"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.Xsl);
                        var isValid = value
                                        .Replace("\r", string.Empty)
                                        .Replace("\n", string.Empty) ==
                                     definition.Xsl
                                                .Replace("\r", string.Empty)
                                                .Replace("\n", string.Empty);

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

                if (!string.IsNullOrEmpty(definition.XslLink))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("XslLink"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.XslLink);
                        var isValid = definition.XslLink == value;

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

                if (!string.IsNullOrEmpty(definition.GhostedXslLink))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("GhostedXslLink"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.GhostedXslLink);
                        var isValid = definition.GhostedXslLink == value;

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

                // xml
                if (!string.IsNullOrEmpty(definition.XmlDefinition))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("XmlDefinition"));
                    var destXmlAttrs = XDocument.Parse(value).Root.Attributes();

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

                        var srcXmlAttrs = XDocument.Parse(definition.XmlDefinition).Root.Attributes();

                        foreach (var srcAttr in srcXmlAttrs)
                        {
                            var attrName = srcAttr.Name;
                            var attrValue = srcAttr.Value;

                            isValid = destXmlAttrs.FirstOrDefault(a => a.Name == attrName)
                                .Value == attrValue;

                            if (!isValid)
                                break;
                        }

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

                if (!string.IsNullOrEmpty(definition.XmlDefinitionLink))
                {
                    var value = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("XmlDefinitionLink"));

                    assert.ShouldBeEqual((p, s, d) =>
                    {
                        var srcProp = s.GetExpressionValue(m => m.XmlDefinitionLink);
                        var isValid = definition.XmlDefinitionLink == value;

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

                // 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 targetWeb = listItemModelHost.HostWeb;

                        if (typedDefinition.WebId.HasGuidValue() || !string.IsNullOrEmpty(typedDefinition.WebUrl))
                        {
                            targetWeb = new LookupFieldModelHandler()
                                            .GetTargetWeb(this.CurrentClientContext.Site, typedDefinition.WebUrl, typedDefinition.WebId);
                        }

                        var list = XsltListViewWebPartModelHandler.LookupList(targetWeb,
                                        typedDefinition.ListUrl,
                                        typedDefinition.ListTitle,
                                        typedDefinition.WebId);

                        var xmlDefinition = ConvertUtils.ToString(CurrentWebPartXml.GetProperty("XmlDefinition"));
                        var xmlDefinitionDoc = XDocument.Parse(xmlDefinition);

                        var viewId = new Guid(xmlDefinitionDoc.Root.GetAttributeValue("Name"));

                        var hiddenView = list.Views.GetById(viewId);
                        context.Load(hiddenView, v => v.HtmlSchemaXml);
                        context.ExecuteQueryWithTrace();

                        var htmlSchemaXml = XDocument.Parse(hiddenView.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.DeployModel(modelHost, model);

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

            var pageItem = listItemModelHost.HostListItem;

            WithExistingWebPart(listItemModelHost.HostFile, typedDefinition, spObject =>
            {
                var assert = ServiceFactory.AssertService
                                           .NewAssert(model, typedDefinition, spObject)
                                                 .ShouldNotBeNull(spObject);

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

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

                        isValid = s.DataMappings == CurrentWebPartXml.GetProperty("DataMappings");

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

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

                        isValid = s.DataMappingViewFields == CurrentWebPartXml.GetProperty("DataMappingViewFields");

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

                // filter display values

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

                        isValid = s.FilterDisplayValue1 == CurrentWebPartXml.GetProperty("FilterDisplayValue1");

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

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

                        isValid = s.FilterDisplayValue2 == CurrentWebPartXml.GetProperty("FilterDisplayValue2");

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

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

                        isValid = s.FilterDisplayValue3 == CurrentWebPartXml.GetProperty("FilterDisplayValue3");

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

                // filter operator

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

                        isValid = s.FilterOperator1 == CurrentWebPartXml.GetProperty("FilterOperator1");

                        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 == CurrentWebPartXml.GetProperty("FilterOperator2");

                        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 == CurrentWebPartXml.GetProperty("FilterOperator3");

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

                // filter types

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

                        isValid = s.FilterType1 == CurrentWebPartXml.GetProperty("FilterType1");

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

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

                        isValid = s.FilterType2 == CurrentWebPartXml.GetProperty("FilterType2");

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

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

                        isValid = s.FilterType3 == CurrentWebPartXml.GetProperty("FilterType3");

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

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

                        isValid = s.SortBy == CurrentWebPartXml.GetProperty("SortBy");

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

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

                        isValid = s.SortByFieldType == CurrentWebPartXml.GetProperty("SortByFieldType");

                        return new PropertyValidationResult
                        {
                            Tag = p.Tag,
                            Src = srcProp,
                            Dst = null,
                            IsValid = isValid
                        };
                    });
                }
                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 == CurrentWebPartXml.GetProperty("SortByDirection");

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

                // filter values

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

                        isValid = s.FilterValue1 == CurrentWebPartXml.GetProperty("FilterValue1");

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

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

                        isValid = s.FilterValue2 == CurrentWebPartXml.GetProperty("FilterValue2");

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

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

                        isValid = s.FilterValue3 == CurrentWebPartXml.GetProperty("FilterValue3");

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

                // styles

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

                        isValid = s.GroupStyle == CurrentWebPartXml.GetGroupStyle();

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

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

                        isValid = s.ItemStyle == CurrentWebPartXml.GetItemStyle();

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

                if (!string.IsNullOrEmpty(typedDefinition.ItemXslLink))
                    throw new NotImplementedException();
                else
                    assert.SkipProperty(m => m.ItemXslLink, "ItemXslLink is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.MainXslLink))
                    throw new NotImplementedException();
                else
                    assert.SkipProperty(m => m.MainXslLink, "MainXslLink is null or empty, skipping.");

                // list bindings

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

                        isValid = s.WebUrl == CurrentWebPartXml.GetWebUrl();

                        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)
                {
                    throw new NotImplementedException();
                }
                else
                    assert.SkipProperty(m => m.WebId, "WebId is null or empty, skipping.");

                if (typedDefinition.ListGuid.HasGuidValue())
                    throw new NotImplementedException();
                else
                    assert.SkipProperty(m => m.ListGuid, "ListGuid is null or empty, skipping.");

                if (!string.IsNullOrEmpty(typedDefinition.ListName))
                    throw new NotImplementedException();
                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();

                        var targetWeb = webLookup.GetTargetWeb(listItemModelHost.HostSite,
                            typedDefinition.WebUrl,
                            typedDefinition.WebId);

                        var list = targetWeb.QueryAndGetListByUrl(typedDefinition.ListUrl);
                        isValid = CurrentWebPartXml.GetListGuid() == 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.");

                // misc

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

                        isValid = ConvertUtils.ToInt(CurrentWebPartXml.GetProperty("ServerTemplate"))
                                        == typedDefinition.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.");
                }

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

                        isValid = ConvertUtils.ToInt(CurrentWebPartXml.GetProperty("ItemLimit"))
                                        == typedDefinition.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)
                    throw new NotImplementedException();
                else
                    assert.SkipProperty(m => m.PlayMediaInBrowser, "PlayMediaInBrowser is null or empty, skipping.");

                if (typedDefinition.ShowUntargetedItems.HasValue)
                    throw new NotImplementedException();
                else
                    assert.SkipProperty(m => m.ShowUntargetedItems, "ShowUntargetedItems is null or empty, skipping.");

                if (typedDefinition.UseCopyUtil.HasValue)
                    throw new NotImplementedException();
                else
                    assert.SkipProperty(m => m.UseCopyUtil, "UseCopyUtil is null or empty, skipping.");

            });
        }
        internal static ListBindContext LookupBindContext(ListItemModelHost listItemModelHost,
           string webUrl, Guid? webId,
           string listUrl, string listTitle, Guid? listId,
           string viewTitle, Guid? viewId,
            string webPartTitleUrl
            )
        {
            var result = new ListBindContext
            {

            };

            var web = listItemModelHost.HostWeb;
            var context = listItemModelHost.HostWeb.Context;

            var targetWeb = listItemModelHost.HostWeb;

            if (webId.HasGuidValue() || !string.IsNullOrEmpty(webUrl))
            {
                targetWeb = new LookupFieldModelHandler()
                                .GetTargetWeb(listItemModelHost.HostClientContext.Site,
                                        webUrl, webId);
            }

            var list = LookupList(targetWeb, listUrl, listTitle, listId);

            View view = null;

            if (viewId.HasValue && viewId != default(Guid))
                view = list.Views.GetById(viewId.Value);
            else if (!string.IsNullOrEmpty(viewTitle))
                view = list.Views.GetByTitle(viewTitle);

            context.Load(list, l => l.Id);
            context.Load(list, l => l.DefaultViewUrl);
            context.Load(list, l => l.Title);
            context.Load(list, l => l.DefaultView);

            if (view != null)
            {
                context.Load(view);
                context.ExecuteQueryWithTrace();

                result.OriginalView = list.DefaultView;
                result.OriginalViewId = list.DefaultView.Id;

                result.TargetView = view;
                result.TargetViewId = view.Id;

                result.TitleUrl = view.ServerRelativeUrl;
            }
            else
            {
                context.ExecuteQueryWithTrace();
            }

            result.ListId = list.Id;
            result.List = list;

            if (webPartTitleUrl == null)
            {
                if (string.IsNullOrEmpty(result.TitleUrl))
                    result.TitleUrl = list.DefaultViewUrl;
            }

            result.DefaultViewId = list.DefaultView.Id;

            return result;
        }
        protected override string GetWebpartXmlDefinition(ListItemModelHost listItemModelHost, WebPartDefinitionBase webPartModel)
        {
            var typedDefinition = webPartModel.WithAssertAndCast<ContentByQueryWebPartDefinition>("model", value => value.RequireNotNull());
            var wpXml = WebpartXmlExtensions.LoadWebpartXmlDocument(this.ProcessCommonWebpartProperties(BuiltInWebPartTemplates.ContentByQueryWebPart, webPartModel));

            // reset SortBy initially
            // it is set to {8c06beca-0777-48f7-91c7-6da68bc07b69} initially
            //wpXml.SetOrUpdateProperty("SortBy", string.Empty);

            var context = listItemModelHost.HostClientContext;

            // 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 = listItemModelHost
                }).Value;

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

                wpXml.SetOrUpdateProperty("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 = listItemModelHost
                }).Value;

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

                wpXml.SetOrUpdateProperty("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 = listItemModelHost
                }).Value;

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

                wpXml.SetOrUpdateProperty("HeaderXslLink", linkValue);
            }

            // styles
            if (!string.IsNullOrEmpty(typedDefinition.ItemStyle))
                wpXml.SetItemStyle(typedDefinition.ItemStyle);

            if (!string.IsNullOrEmpty(typedDefinition.GroupStyle))
                wpXml.SetGroupStyle(typedDefinition.GroupStyle);

            // cache settings
            if (typedDefinition.UseCache.HasValue)
                wpXml.SetUseCache(typedDefinition.UseCache.ToString());

            if (typedDefinition.CacheXslStorage.HasValue)
                wpXml.SetOrUpdateProperty("CacheXslStorage", typedDefinition.CacheXslStorage.ToString());

            if (typedDefinition.CacheXslTimeOut.HasValue)
                wpXml.SetOrUpdateProperty("CacheXslTimeOut", typedDefinition.CacheXslTimeOut.ToString());

            // item limit
            if (typedDefinition.ItemLimit.HasValue)
                wpXml.SetOrUpdateProperty("ItemLimit", typedDefinition.ItemLimit.ToString());

            // mappings
            if (!string.IsNullOrEmpty(typedDefinition.DataMappings))
                wpXml.SetOrUpdateProperty("DataMappings", typedDefinition.DataMappings);

            if (!string.IsNullOrEmpty(typedDefinition.DataMappingViewFields))
                wpXml.SetOrUpdateProperty("DataMappingViewFields", typedDefinition.DataMappingViewFields);

            // misc
            if (typedDefinition.ShowUntargetedItems.HasValue)
                wpXml.SetOrUpdateProperty("ShowUntargetedItems", typedDefinition.ShowUntargetedItems.ToString());

            if (typedDefinition.PlayMediaInBrowser.HasValue)
                wpXml.SetOrUpdateProperty("PlayMediaInBrowser", typedDefinition.PlayMediaInBrowser.ToString());

            // FilterTypeXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterType1))
                wpXml.SetOrUpdateProperty("FilterType1", typedDefinition.FilterType1);

            if (!string.IsNullOrEmpty(typedDefinition.FilterType2))
                wpXml.SetOrUpdateProperty("FilterType2", typedDefinition.FilterType2);

            if (!string.IsNullOrEmpty(typedDefinition.FilterType3))
                wpXml.SetOrUpdateProperty("FilterType3", typedDefinition.FilterType3);

            // FilterFieldXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterField1))
                wpXml.SetOrUpdateProperty("FilterField1", typedDefinition.FilterField1);

            if (!string.IsNullOrEmpty(typedDefinition.FilterField2))
                wpXml.SetOrUpdateProperty("FilterField2", typedDefinition.FilterField2);

            if (!string.IsNullOrEmpty(typedDefinition.FilterField3))
                wpXml.SetOrUpdateProperty("FilterField3", typedDefinition.FilterField3);

            // FilterXXXIsCustomValue
            if (typedDefinition.Filter1IsCustomValue.HasValue)
                wpXml.SetOrUpdateProperty("Filter1IsCustomValue", typedDefinition.Filter1IsCustomValue.ToString());

            if (typedDefinition.Filter2IsCustomValue.HasValue)
                wpXml.SetOrUpdateProperty("Filter2IsCustomValue", typedDefinition.Filter2IsCustomValue.ToString());

            if (typedDefinition.Filter3IsCustomValue.HasValue)
                wpXml.SetOrUpdateProperty("Filter3IsCustomValue", typedDefinition.Filter3IsCustomValue.ToString());

            // FilterValueXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterValue1))
                wpXml.SetOrUpdateProperty("FilterValue1", typedDefinition.FilterValue1);

            if (!string.IsNullOrEmpty(typedDefinition.FilterValue2))
                wpXml.SetOrUpdateProperty("FilterValue2", typedDefinition.FilterValue2);

            if (!string.IsNullOrEmpty(typedDefinition.FilterValue3))
                wpXml.SetOrUpdateProperty("FilterValue3", typedDefinition.FilterValue3);

            var filterChainingOperatorType = "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+FilterChainingOperator, Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";

            if (!string.IsNullOrEmpty(typedDefinition.Filter1ChainingOperator))
                wpXml.SetTypedProperty("Filter1ChainingOperator", typedDefinition.Filter1ChainingOperator, filterChainingOperatorType);

            if (!string.IsNullOrEmpty(typedDefinition.Filter2ChainingOperator))
                wpXml.SetTypedProperty("Filter2ChainingOperator", typedDefinition.Filter2ChainingOperator, filterChainingOperatorType);

            // sorting
            if (!string.IsNullOrEmpty(typedDefinition.SortBy))
                wpXml.SetOrUpdateProperty("SortBy", typedDefinition.SortBy);

            if (!string.IsNullOrEmpty(typedDefinition.SortByDirection))
                wpXml.SetTypedProperty("SortByDirection", typedDefinition.SortByDirection, "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+SortDirection, Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

            if (!string.IsNullOrEmpty(typedDefinition.SortByFieldType))
                wpXml.SetOrUpdateProperty("SortByFieldType", typedDefinition.SortByFieldType);

            if (!string.IsNullOrEmpty(typedDefinition.GroupByDirection))
                wpXml.SetTypedProperty("GroupByDirection", typedDefinition.GroupByDirection, "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+SortDirection, Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

            var filterOperatorType = "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+FilterFieldQueryOperator, Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";

            // FilterOperatorXXX
            if (!string.IsNullOrEmpty(typedDefinition.FilterOperator1))
                wpXml.SetTypedProperty("FilterOperator1", typedDefinition.FilterOperator1, filterOperatorType);

            if (!string.IsNullOrEmpty(typedDefinition.FilterOperator2))
                wpXml.SetTypedProperty("FilterOperator2", typedDefinition.FilterOperator2, filterOperatorType);

            if (!string.IsNullOrEmpty(typedDefinition.FilterOperator3))
                wpXml.SetTypedProperty("FilterOperator3", typedDefinition.FilterOperator3, filterOperatorType);

            // FilterDisplayValueXXX

            if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue1))
                wpXml.SetOrUpdateProperty("FilterDisplayValue1", typedDefinition.FilterDisplayValue1);

            if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue2))
                wpXml.SetOrUpdateProperty("FilterDisplayValue2", typedDefinition.FilterDisplayValue2);

            if (!string.IsNullOrEmpty(typedDefinition.FilterDisplayValue3))
                wpXml.SetOrUpdateProperty("FilterDisplayValue3", typedDefinition.FilterDisplayValue3);

            // bindings
            if (typedDefinition.ServerTemplate.HasValue)
                wpXml.SetOrUpdateProperty("ServerTemplate", typedDefinition.ServerTemplate.ToString());

            if (!string.IsNullOrEmpty(typedDefinition.ContentTypeName))
                wpXml.SetOrUpdateProperty("ContentTypeName", typedDefinition.ContentTypeName);

            if (!string.IsNullOrEmpty(typedDefinition.ContentTypeBeginsWithId))
                wpXml.SetOrUpdateProperty("ContentTypeBeginsWithId", typedDefinition.ContentTypeBeginsWithId);

            if (typedDefinition.ListId.HasGuidValue())
                wpXml.SetTypedProperty("ListId", typedDefinition.ListId.Value.ToString("D"), "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart+FilterChainingOperator, Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

            if (typedDefinition.ListGuid.HasGuidValue())
                wpXml.SetOrUpdateProperty("ListGuid", typedDefinition.ListGuid.Value.ToString("D"));

            if (!string.IsNullOrEmpty(typedDefinition.ListName))
            {
                // ServerTemplate

                var webLookup = new LookupFieldModelHandler();

                var targetWeb = webLookup.GetTargetWeb(listItemModelHost.HostSite,
                    typedDefinition.WebUrl,
                    typedDefinition.WebId);

                var list = targetWeb.QueryAndGetListByTitle(typedDefinition.ListName);
                wpXml.SetOrUpdateProperty("ListGuid", list.Id.ToString("D"));

            #if !NET35
                var folder = list.RootFolder;

                context.Load(folder, f => f.Properties);
                context.ExecuteQueryWithTrace();

                var serverTemplate = ConvertUtils.ToString(list.RootFolder.Properties["vti_listservertemplate"]);

                if (string.IsNullOrEmpty(serverTemplate))
                {
                    throw new SPMeta2Exception(
                        string.Format("Cannot find vti_listservertemplate property for the list name:[{0}]",
                        typedDefinition.ListName));
                }

                wpXml.SetOrUpdateProperty("ServerTemplate", serverTemplate);
            #endif
            }

            if (!string.IsNullOrEmpty(typedDefinition.ListUrl))
            {
                var webLookup = new LookupFieldModelHandler();

                var targetWeb = webLookup.GetTargetWeb(listItemModelHost.HostSite,
                    typedDefinition.WebUrl,
                    typedDefinition.WebId);

                var list = targetWeb.QueryAndGetListByUrl(typedDefinition.ListUrl);
                wpXml.SetOrUpdateProperty("ListGuid", list.Id.ToString("D"));

            #if !NET35
                var folder = list.RootFolder;

                context.Load(folder, f => f.Properties);
                context.ExecuteQueryWithTrace();

                var serverTemplate = ConvertUtils.ToString(list.RootFolder.Properties["vti_listservertemplate"]);

                if (string.IsNullOrEmpty(serverTemplate))
                {
                    throw new SPMeta2Exception(
                        string.Format("Cannot find vti_listservertemplate property for the list url:[{0}]",
                        typedDefinition.ListUrl));
                }

                wpXml.SetOrUpdateProperty("ServerTemplate", serverTemplate);
            #endif
            }

            if (!string.IsNullOrEmpty(typedDefinition.WebUrl))
                wpXml.SetOrUpdateProperty("WebUrl", typedDefinition.WebUrl);

            // overrides
            if (!string.IsNullOrEmpty(typedDefinition.ListsOverride))
                wpXml.SetOrUpdateProperty("ListsOverride", typedDefinition.ListsOverride);

            if (!string.IsNullOrEmpty(typedDefinition.ViewFieldsOverride))
                wpXml.SetOrUpdateProperty("ViewFieldsOverride", typedDefinition.ViewFieldsOverride);

            if (!string.IsNullOrEmpty(typedDefinition.QueryOverride))
                wpXml.SetOrUpdateProperty("QueryOverride", typedDefinition.QueryOverride);

            if (!string.IsNullOrEmpty(typedDefinition.CommonViewFields))
                wpXml.SetOrUpdateProperty("CommonViewFields", typedDefinition.CommonViewFields);

            if (typedDefinition.FilterByAudience.HasValue)
                wpXml.SetOrUpdateProperty("FilterByAudience", typedDefinition.FilterByAudience.ToString());

            return wpXml.ToString();
        }