private SPField FindField(SPFieldCollection fields, ListFieldLinkDefinition listFieldLinkModel)
        {
            if (listFieldLinkModel.FieldId.HasGuidValue())
            {

                return fields
                    .OfType<SPField>()
                    .FirstOrDefault(f => f.Id == listFieldLinkModel.FieldId.Value);
            }

            if (!string.IsNullOrEmpty(listFieldLinkModel.FieldInternalName))
            {
                return fields
                   .OfType<SPField>()
                   .FirstOrDefault(f => f.InternalName.ToUpper() == listFieldLinkModel.FieldInternalName.ToUpper());
            }

            throw new ArgumentException("FieldId or FieldInternalName should be defined");
        }
        private Field FindField(FieldCollection fields, ListFieldLinkDefinition listFieldLinkModel)
        {
            var context = fields.Context;

            var scope = new ExceptionHandlingScope(context);

            Field field = null;

            if (listFieldLinkModel.FieldId.HasGuidValue())
            {
                var id = listFieldLinkModel.FieldId.Value;

                using (scope.StartScope())
                {
                    using (scope.StartTry())
                    {
                        fields.GetById(id);
                    }

                    using (scope.StartCatch())
                    {

                    }
                }
            }
            else if (!string.IsNullOrEmpty(listFieldLinkModel.FieldInternalName))
            {
                var fieldInternalName = listFieldLinkModel.FieldInternalName;

                using (scope.StartScope())
                {
                    using (scope.StartTry())
                    {
                        fields.GetByInternalNameOrTitle(fieldInternalName);
                    }

                    using (scope.StartCatch())
                    {

                    }
                }
            }

            context.ExecuteQueryWithTrace();

            if (!scope.HasException)
            {
                if (listFieldLinkModel.FieldId.HasGuidValue())
                {
                    field = fields.GetById(listFieldLinkModel.FieldId.Value);
                }
                else if (!string.IsNullOrEmpty(listFieldLinkModel.FieldInternalName))
                {
                    field = fields.GetByInternalNameOrTitle(listFieldLinkModel.FieldInternalName);
                }

                context.Load(field);
                context.Load(field, f => f.SchemaXml);

                context.ExecuteQueryWithTrace();
            }

            return field;
        }
 protected Field FindAvailableField(Web web, ListFieldLinkDefinition listFieldLinkModel)
 {
     return FindField(web.AvailableFields, listFieldLinkModel);
 }
 protected Field FindExistingListField(List list, ListFieldLinkDefinition listFieldLinkModel)
 {
     return FindField(list.Fields, listFieldLinkModel);
 }
        private void ProcessListFieldLinkProperties(Field existingListField, ListFieldLinkDefinition listFieldLinkModel)
        {
            if (!string.IsNullOrEmpty(listFieldLinkModel.DisplayName))
                existingListField.Title = listFieldLinkModel.DisplayName;

            if (listFieldLinkModel.Hidden.HasValue)
                existingListField.Hidden = listFieldLinkModel.Hidden.Value;

            if (listFieldLinkModel.Required.HasValue)
                existingListField.Required = listFieldLinkModel.Required.Value;
        }
        private void DeployListFieldLink(object modelHost, List list, ListFieldLinkDefinition listFieldLinkModel)
        {
            var web = list.ParentWeb;

            var context = list.Context;
            var fields = list.Fields;

            context.Load(fields);
            context.ExecuteQueryWithTrace();

            Field existingListField = FindExistingListField(list, listFieldLinkModel);

            InvokeOnModelEvent(this, new ModelEventArgs
            {
                CurrentModelNode = null,
                Model = null,
                EventType = ModelEventType.OnProvisioning,
                Object = existingListField,
                ObjectType = typeof(Field),
                ObjectDefinition = listFieldLinkModel,
                ModelHost = modelHost
            });

            if (existingListField == null)
            {
                TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new list field");

                var siteField = FindAvailableField(web, listFieldLinkModel);

                var addFieldOptions = (AddFieldOptions)(int)listFieldLinkModel.AddFieldOptions;

                Field listField = null;

                // AddToDefaultView || !DefaultValue would use AddFieldAsXml
                // this would change InternalName of the field inside the list

                // The second case, fields.Add(siteField), does not change internal name of the field inside list
                if (addFieldOptions != AddFieldOptions.DefaultValue || listFieldLinkModel.AddToDefaultView)
                    listField = fields.AddFieldAsXml(siteField.SchemaXml, listFieldLinkModel.AddToDefaultView, addFieldOptions);
                else
                    listField = fields.Add(siteField);

                ProcessListFieldLinkProperties(listField, listFieldLinkModel);

                InvokeOnModelEvent(this, new ModelEventArgs
                {
                    CurrentModelNode = null,
                    Model = null,
                    EventType = ModelEventType.OnProvisioned,
                    Object = listField,
                    ObjectType = typeof(Field),
                    ObjectDefinition = listFieldLinkModel,
                    ModelHost = modelHost
                });

                listField.Update();
                context.ExecuteQueryWithTrace();
            }
            else
            {
                TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing list field");

                ProcessListFieldLinkProperties(existingListField, listFieldLinkModel);

                InvokeOnModelEvent(this, new ModelEventArgs
                {
                    CurrentModelNode = null,
                    Model = null,
                    EventType = ModelEventType.OnProvisioned,
                    Object = existingListField,
                    ObjectType = typeof(Field),
                    ObjectDefinition = listFieldLinkModel,
                    ModelHost = modelHost
                });

                existingListField.Update();
                context.ExecuteQueryWithTrace();
            }
        }
 public static ModelNode AddListFieldLink(this ModelNode model, ListFieldLinkDefinition definition, Action<ModelNode> action)
 {
     return model.AddDefinitionNode(definition, action);
 }
 public static ModelNode AddListFieldLink(this ModelNode model, ListFieldLinkDefinition definition)
 {
     return AddListFieldLink(model, definition, null);
 }
        public void CanDeploy_ListFieldLink_AsAddToAllContentTypes()
        {
            var field = ModelGeneratorService.GetRandomDefinition<FieldDefinition>();
            field.AddToDefaultView = true;

            var listFieldLink = new ListFieldLinkDefinition
            {
                FieldId = field.Id,
                AddFieldOptions = BuiltInAddFieldOptions.AddToAllContentTypes,
                AddToDefaultView = true
            };

            var ct_1 = ModelGeneratorService.GetRandomDefinition<ContentTypeDefinition>(def =>
            {
                def.ParentContentTypeId = BuiltInContentTypeId.Item;
            });

            var ct_2 = ModelGeneratorService.GetRandomDefinition<ContentTypeDefinition>(def =>
            {
                def.ParentContentTypeId = BuiltInContentTypeId.Item;
            });

            var ct_3 = ModelGeneratorService.GetRandomDefinition<ContentTypeDefinition>(def =>
            {
                def.ParentContentTypeId = BuiltInContentTypeId.Item;
            });

            var genericList = ModelGeneratorService.GetRandomDefinition<ListDefinition>(def =>
            {
                def.ContentTypesEnabled = true;
                def.TemplateType = BuiltInListTemplateTypeId.GenericList;
            });

            var siteModel = SPMeta2Model
                   .NewSiteModel(site =>
                   {
                       site.AddContentType(ct_1);
                       site.AddContentType(ct_2);
                       site.AddContentType(ct_3);

                       site.AddField(field);
                   });

            var webModel = SPMeta2Model
                   .NewWebModel(web =>
                   {
                       web.AddList(genericList, list =>
                       {
                           list.AddContentTypeLink(ct_1);
                           list.AddContentTypeLink(ct_2);
                           list.AddContentTypeLink(ct_3);

                           list.AddListFieldLink(listFieldLink);
                       });
                   });

            // content types are deployed after fields
            // so, to test AddToAllContentTypes, we need to deploy content type first, and then the rest
            //var fieldLinkModel = SPMeta2Model
            //       .NewWebModel(web =>
            //       {
            //           web.AddHostList(genericList, list =>
            //           {

            //           });
            //       });

            TestModels(new  ModelNode[] { siteModel, webModel });
        }
        public void CanDeploy_ListFieldLink_AsAddToDefaultView()
        {
            var field = ModelGeneratorService.GetRandomDefinition<FieldDefinition>();
            field.AddToDefaultView = true;

            var listFieldLink = new ListFieldLinkDefinition
            {
                FieldId = field.Id,
                AddToDefaultView = true
            };

            var siteModel = SPMeta2Model
                   .NewSiteModel(site =>
                   {
                       site.AddField(field);
                   });

            var webModel = SPMeta2Model
                   .NewWebModel(web =>
                   {
                       web.AddRandomList(list =>
                       {
                           list.AddListFieldLink(listFieldLink);
                       });
                   });

            TestModels(new  ModelNode[] { siteModel, webModel });
        }
        private void DeployListFieldLink(object modelHost, SPList list, ListFieldLinkDefinition listFieldLinkModel)
        {
            var existingListField = FindExistingListField(list, listFieldLinkModel);

            InvokeOnModelEvent(this, new ModelEventArgs
            {
                CurrentModelNode = null,
                Model = null,
                EventType = ModelEventType.OnProvisioning,
                Object = existingListField,
                ObjectType = typeof(SPField),
                ObjectDefinition = listFieldLinkModel,
                ModelHost = modelHost
            });

            if (existingListField == null)
            {
                TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new list field");

                var siteField = FindAvailableField(list.ParentWeb, listFieldLinkModel);
                var addFieldOptions = (SPAddFieldOptions)(int)listFieldLinkModel.AddFieldOptions;

                if ((siteField is SPFieldLookup) &&
                    (siteField as SPFieldLookup).IsDependentLookup)
                {
                    list.Fields.Add(siteField);
                }
                else
                {
                    list.Fields.AddFieldAsXml(siteField.SchemaXml, listFieldLinkModel.AddToDefaultView, addFieldOptions);
                }

                existingListField = list.Fields[siteField.Id];
                ProcessListFieldLinkProperties(existingListField, listFieldLinkModel);

                InvokeOnModelEvent(this, new ModelEventArgs
                {
                    CurrentModelNode = null,
                    Model = null,
                    EventType = ModelEventType.OnProvisioned,
                    Object = existingListField,
                    ObjectType = typeof(SPField),
                    ObjectDefinition = listFieldLinkModel,
                    ModelHost = modelHost
                });

                existingListField.Update(false);
            }
            else
            {
                TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing list field");

                ProcessListFieldLinkProperties(existingListField, listFieldLinkModel);

                InvokeOnModelEvent(this, new ModelEventArgs
                {
                    CurrentModelNode = null,
                    Model = null,
                    EventType = ModelEventType.OnProvisioned,
                    Object = existingListField,
                    ObjectType = typeof(SPField),
                    ObjectDefinition = listFieldLinkModel,
                    ModelHost = modelHost
                });

                existingListField.Update(false);
            }
        }