private static void GenerateChangeDataTypeCommand(ICommandDispatcher dispatcher,MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.DataTypeMatches(updated))
                return;

            dispatcher.Dispatch(new ChangeMetadataDefinitionDataTypeCommand(updated.Identity, updated.DataType));
        }
        public bool NameMatches(MetadataDefinitionResource other)
        {
            if (other == null)
                return false;

            return Equals(Name, other.Name);
        }
        public HttpResponseMessage Create(MetadataDefinitionResource resource)
        {
            _logWriter.Info(String.Format("Beginning of processing creation of Definition : {0}", resource.Name));

            if (resource == null)
            {
                throw new ArgumentEmptyException("resource");
            }

            _logWriter.Debug(resource.ToString());

            if (_metadataDefinitonReadService.FindByIdentity(resource.Identity).Exists)
            {
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Identity already exists. Identities must be unique"));
            }

            return(_metadataDefinitonReadService.FindByName(resource.Name).Fold(x =>
                                                                                Request.CreateErrorResponse(HttpStatusCode.BadRequest, resource.Name + " already exist. Names must be unique"),
                                                                                () =>
            {
                var errors = ValidateResource(resource);
                if (!String.IsNullOrWhiteSpace(errors))
                {
                    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, errors);
                }

                var command = resource.ToCreateCommand();
                _dispatcher.Dispatch(command);

                _logWriter.Info(String.Format("Completion of processing creation of Definition : {0}", resource.Name));

                return Request.CreateResponse(HttpStatusCode.Created);
            }));
        }
        public bool DataTypeMatches(MetadataDefinitionResource other)
        {
            if (other == null)
                return false;

            return Equals(DataType, other.DataType);
        }
        public bool DescriptionMatches(MetadataDefinitionResource other)
        {
            if (other == null)
                return false;

            return Equals(Description, other.Description);
        }
        private static void GenerateValues(ICommandDispatcher dispatcher, MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.ValuesMatch(updated))
                return;

            dispatcher.Dispatch(new UpdateMetadataDefinitionValuesCommand(updated.Identity, updated.Values));
        }
        private static void GenerateUpdateRegexCommand(ICommandDispatcher dispatcher,MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.RegexMatches(updated))
                return;

            dispatcher.Dispatch(new UpdateMetadataDefinitionRegexCommand(updated.Identity,updated.Regex));
        }
        private static void GenerateReLabelDescriptionCommand(ICommandDispatcher dispatcher, MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.DescriptionMatches(updated))
                return;

            dispatcher.Dispatch(new ReLabelMetadataDefinitionDescriptionCommand(updated.Identity, new MetadataDefinitionDescription(updated.Description.Trim())));
        }
        public HttpResponseMessage Create(MetadataDefinitionResource resource)
        {
            _logWriter.Info(String.Format("Beginning of processing creation of Definition : {0}", resource.Name));

            if (resource == null)
                throw new ArgumentEmptyException("resource");

            _logWriter.Debug(resource.ToString());

            if (_metadataDefinitonReadService.FindByIdentity(resource.Identity).Exists)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Identity already exists. Identities must be unique");

            return _metadataDefinitonReadService.FindByName(resource.Name).Fold(x =>
                                                                                Request.CreateErrorResponse(HttpStatusCode.BadRequest, resource.Name + " already exist. Names must be unique"),
                                                                                () =>
                                                                                {
                                                                                    var errors = ValidateResource(resource);
                                                                                    if (!String.IsNullOrWhiteSpace(errors))
                                                                                        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, errors);

                                                                                    var command = resource.ToCreateCommand();
                                                                                    _dispatcher.Dispatch(command);

                                                                                    _logWriter.Info(String.Format("Completion of processing creation of Definition : {0}", resource.Name));

                                                                                    return Request.CreateResponse(HttpStatusCode.Created);
                                                                                });
        }
        public bool NameMatches(MetadataDefinitionResource other)
        {
            if (other == null)
            {
                return(false);
            }

            return(Equals(Name, other.Name));
        }
        public bool DescriptionMatches(MetadataDefinitionResource other)
        {
            if (other == null)
            {
                return(false);
            }

            return(Equals(Description, other.Description));
        }
        public bool DataTypeMatches(MetadataDefinitionResource other)
        {
            if (other == null)
            {
                return(false);
            }

            return(Equals(DataType, other.DataType));
        }
        private static void GenerateReLabelCommand(ICommandDispatcher dispatcher, MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.NameMatches(updated))
            {
                return;
            }

            dispatcher.Dispatch(new ReLabelMetadataDefinitionCommand(updated.Identity, new MetadataDefinitionName(updated.Name.Trim())));
        }
        public bool RegexMatches(MetadataDefinitionResource other)
        {
            if (other == null)
            {
                return(false);
            }

            return(Equals(Regex, other.Regex));
        }
        private static void GenerateValues(ICommandDispatcher dispatcher, MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.ValuesMatch(updated))
            {
                return;
            }

            dispatcher.Dispatch(new UpdateMetadataDefinitionValuesCommand(updated.Identity, updated.Values));
        }
        public static void GenerateCommands(this ICommandDispatcher dispatcher, IMetadataDefinitionReadService readService, MetadataDefinitionResource resource)
        {
            var current = readService.FindByIdentity(resource.Identity);

            current.Foreach(original =>
            {
                GenerateReLabelCommand(dispatcher, original, resource);
                GenerateReLabelDescriptionCommand(dispatcher, original, resource);
                GenerateChangeDataTypeCommand(dispatcher, original, resource);
                GenerateUpdateRegexCommand(dispatcher, original, resource);
                GenerateValues(dispatcher, original, resource);
            });
        }
        public HttpResponseMessage UpdateMetadataDefinition([FromUri] Guid identity, [FromBody] MetadataDefinitionResource resource)
        {
            _logWriter.Info(String.Format("Update request for Metadata Definition : {0}", identity));
            resource.Identity = identity;

            var current        = _metadataDefinitonReadService.FindByIdentity(resource.Identity);
            var matchingByName = _metadataDefinitonReadService.FindByName(resource.Name);

            return(matchingByName.Filter(x => x.Identity != resource.Identity)
                   .Fold(x => Request.CreateErrorResponse(HttpStatusCode.BadRequest, resource.Name + " already exists. Names must be unique"),
                         () => current.Fold(z =>
            {
                _dispatcher.GenerateCommands(_metadataDefinitonReadService, resource);
                return Request.CreateResponse(HttpStatusCode.OK);
            },
                                            () => Request.CreateErrorResponse(HttpStatusCode.NotFound, "Metadata Definition Resource Not Found"))
                         ));
        }
        private string ValidateResource(MetadataDefinitionResource resource)
        {
            var sb = new StringBuilder();

            if (DataTypeBuilder.Create(resource.DataType) != null)
            {
                return(sb.ToString());
            }

            sb.AppendLine("Invalid DataType");
            sb.AppendLine("Valid data type included");

            foreach (var dataType in DataTypeBuilder.GetDataTypes())
            {
                sb.Append(dataType.Value.Tag + ",");
            }

            return(sb.ToString());
        }
        public bool ValuesMatch(MetadataDefinitionResource other)
        {
            if (other == null)
            {
                return(false);
            }

            if (Values == null)
            {
                return(other.Values == null || !other.Values.Any());
            }

            if (other.Values == null)
            {
                return(Values == null || !Values.Any());
            }

            if (Values.Count != other.Values.Count)
            {
                return(false);
            }

            return(Values.Intersect(other.Values).Count() == Values.Count);
        }
        public bool RegexMatches(MetadataDefinitionResource other)
        {
            if (other == null)
                return false;

            return Equals(Regex, other.Regex);
        }
        public bool ValuesMatch(MetadataDefinitionResource other)
        {
            if (other == null)
                return false;

            if (Values == null)
                return other.Values == null || !other.Values.Any();

            if (other.Values == null)
                return Values == null || !Values.Any();

            if (Values.Count != other.Values.Count) return false;

            return Values.Intersect(other.Values).Count() == Values.Count;
        }
        private static void GenerateChangeDataTypeCommand(ICommandDispatcher dispatcher, MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.DataTypeMatches(updated))
            {
                return;
            }

            dispatcher.Dispatch(new ChangeMetadataDefinitionDataTypeCommand(updated.Identity, updated.DataType));
        }
        private static void GenerateUpdateRegexCommand(ICommandDispatcher dispatcher, MetadataDefinitionResource original, MetadataDefinitionResource updated)
        {
            if (original.RegexMatches(updated))
            {
                return;
            }

            dispatcher.Dispatch(new UpdateMetadataDefinitionRegexCommand(updated.Identity, updated.Regex));
        }
        public static void GenerateCommands(this ICommandDispatcher dispatcher, IMetadataDefinitionReadService readService, MetadataDefinitionResource resource)
        {
            var current = readService.FindByIdentity(resource.Identity);

            current.Foreach(original =>
            {
                GenerateReLabelCommand(dispatcher, original, resource);
                GenerateReLabelDescriptionCommand(dispatcher, original, resource);
                GenerateChangeDataTypeCommand(dispatcher, original, resource);
                GenerateUpdateRegexCommand(dispatcher, original, resource);
                GenerateValues(dispatcher, original, resource);
            });
        }
        public static CreateMetadataDefinitionCommand ToCreateCommand(this MetadataDefinitionResource resource)
        {
            var values = (resource.Values == null || !resource.Values.Any()) ? Enumerable.Empty <string>() : resource.Values.Where(x => !string.IsNullOrEmpty(x));

            return(new CreateMetadataDefinitionCommand(resource.Identity.IfGuidEmptyCreateNew(), resource.Name, resource.Description, resource.DataType, resource.Regex, values));
        }
        private string ValidateResource(MetadataDefinitionResource resource)
        {
            var sb = new StringBuilder();
            if (DataTypeBuilder.Create(resource.DataType) != null)
                return sb.ToString();

            sb.AppendLine("Invalid DataType");
            sb.AppendLine("Valid data type included");

            foreach (var dataType in DataTypeBuilder.GetDataTypes())
                sb.Append(dataType.Value.Tag + ",");

            return sb.ToString();
        }