public override void DeployModel(object modelHost, DefinitionBase model)
        {
            var props = model.GetType()
                             .GetProperties()
                             .Where(p => p.GetCustomAttributes(typeof(ExpectRequired), true).Any());

            var requiredPropsGroups = props
                             .GroupBy(g => (g.GetCustomAttributes(typeof(ExpectRequired), true).First() as ExpectRequired).GroupName);

            foreach (var group in requiredPropsGroups)
            {
                // all set is requred
                if (string.IsNullOrEmpty(group.Key))
                {
                    var isAllValid = AllOfThem(model, group.ToList());

                    if (!isAllValid)
                        throw new Exception("Not all of them");
                }
                else
                {
                    // skip 'Web part content' for typed web part definitions
                    //  a big todo

                    if (group.Key == "Web part content" && (model.GetType() != typeof(WebPartDefinition)))
                        continue;

                    var oneOfThem = OneOfThem(model, group.ToList());

                    if (!oneOfThem)
                        throw new Exception("Not one of them");
                }
            }
        }
        public override void DeployModel(object modelHost, DefinitionBase model)
        {
            //var aggregateException = new c();
            var exceptions = new List<SPMeta2ModelValidationException>();

            var props = ReflectionUtils.GetPropertiesWithCustomAttribute<ExpectRequired>(model, true);

            var requiredPropsGroups = props
                             .GroupBy(g => (g.GetCustomAttributes(typeof(ExpectRequired), true).First() as ExpectRequired).GroupName);

            foreach (var group in requiredPropsGroups)
            {
                // all set is requred
                if (string.IsNullOrEmpty(group.Key))
                {
                    var isAllValid = AllOfThem(model, group.ToList());

                    if (isAllValid.Count > 0)
                    {
                        exceptions.AddRange(isAllValid);
                    }
                }
                else
                {
                    // skip 'Web part content' for typed web part definitions
                    //  a big todo

                    if (group.Key == "Web part content" && (model.GetType() != typeof(WebPartDefinition)))
                        continue;

                    var oneOfThem = OneOfThem(model, group.ToList());

                    if (!oneOfThem)
                    {
                        var ex = new SPMeta2ModelValidationException(
                            string.Format("One of the properties with [{0}] attribute should be set. Definition:[{1}]",
                            group.Key, model))
                        {
                            Definition = model
                        };

                        exceptions.Add(ex);
                    }
                }
            }

            if (exceptions.Count > 0)
            {
                throw new SPMeta2AggregateException("Required properties validation error", 
                    exceptions.OfType<Exception>());
            }
        }
        public string GetDefinitionIdentityKey(DefinitionBase def)
        {
            var result = string.Empty;

            var definitionType = def.GetType();

            var isSingleIdenity = definitionType.GetCustomAttributes(typeof(SingletonIdentityAttribute), true).Any();
            var isInstanceIdentity = !definitionType.GetCustomAttributes(typeof(SingletonIdentityAttribute), true).Any();

            if (isSingleIdenity)
            {
                throw new SPMeta2ReverseException("isSingleIdenity is true. Was not implemented yet");
            }

            if (isInstanceIdentity)
            {
                var props = definitionType.GetProperties();

                var identityKeyNames = props
                    .Where(p => p.GetCustomAttributes(typeof(IdentityKeyAttribute), true).Any())
                    .Select(p => p.Name)
                    .OrderBy(s => s)
                    .ToList();

                // url gets transformed by SharePoint to the full one
                // so that lookup by identity won't work
                // rely only on title for the time being
                if (def is NavigationNodeDefinitionBase)
                {
                    identityKeyNames.Remove("Url");
                }

                // skipping list view URLs fro the tiime being
                if (def is ListViewDefinition)
                {
                    identityKeyNames.Remove("Url");
                }

                foreach (var keyName in identityKeyNames)
                {
                    var prop = props.FirstOrDefault(p => p.Name == keyName);
                    var keyValue = ConvertUtils.ToString(prop.GetValue(def, null));

                    result += keyValue;
                }

            }

            return result;
        }