private static void HandleValidationAttribute(RamlType ramlTypeProp, CustomAttributeData attribute)
        {
            switch (attribute.AttributeType.Name)
            {
            case "MaxLengthAttribute":
                ramlTypeProp.Scalar.MaxLength = (int?)attribute.ConstructorArguments.First().Value;
                break;

            case "MinLengthAttribute":
                ramlTypeProp.Scalar.MinLength = (int?)attribute.ConstructorArguments.First().Value;
                break;

            case "RangeAttribute":
                if (!TypeBuilderHelper.IsMinValue(attribute.ConstructorArguments.First()))
                {
                    ramlTypeProp.Scalar.Minimum = ConvertToNullableDecimal(attribute.ConstructorArguments.First().Value);
                }
                if (!TypeBuilderHelper.IsMaxValue(attribute.ConstructorArguments.Last()))
                {
                    ramlTypeProp.Scalar.Maximum = ConvertToNullableDecimal(attribute.ConstructorArguments.Last().Value);
                }
                break;

            case "EmailAddressAttribute":
                ramlTypeProp.Scalar.Pattern = @"pattern: [^\\s@]+@[^\\s@]+\\.[^\\s@]";
                break;

            case "UrlAttribute":
                ramlTypeProp.Scalar.Pattern = @"pattern: ^(ftp|http|https):\/\/[^ \""]+$";
                break;
                //case "RegularExpressionAttribute":
                //    ramlTypeProp.Scalar.Pattern = "pattern: " + attribute.ConstructorArguments.First().Value;
                //    break;
            }
        }
        private string BuildPropertyCommon(PropertyInfo prop, IEnumerable <CustomAttributeData> customAttributes)
        {
            var name = TypeBuilderHelper.GetPropertyName(prop);

            var res = "\"" + name + "\": { \"type\": " + SchemaTypeMapper.GetAttribute(prop.PropertyType);

            res += HandleRequiredAttribute(prop, customAttributes);

            res += HandleValidationAttributes(customAttributes);
            return(res);
        }
        private static string HandleRequiredAttribute(PropertyInfo prop, IEnumerable <CustomAttributeData> customAttributes)
        {
            var res = string.Empty;

            if (customAttributes.Any(a => a.AttributeType == typeof(RequiredAttribute)))
            {
                res += ", \"required\": true";
            }
            else if (TypeBuilderHelper.IsNullable(prop.PropertyType))
            {
                res += ", \"required\": false";
            }
            return(res);
        }
        private static string GetTypeName(Type type)
        {
            var typeName = type.Name;

            if (IsDictionary(type))
            {
                typeName = type.GetGenericArguments()[1].Name + "Map";
            }

            if (TypeBuilderHelper.IsArrayOrEnumerable(type))
            {
                typeName = "ListOf" + GetTypeName(GetElementType(type));
            }

            return(typeName.Replace("`", string.Empty));
        }
        private IDictionary <string, RamlType> GetProperties(Type type)
        {
            var props = GetClassProperties(type).ToArray();
            var dic   = new Dictionary <string, RamlType>();

            foreach (var prop in props)
            {
                var key      = TypeBuilderHelper.GetPropertyName(prop);
                var ramlType = GetProperty(prop);

                if (ramlType != null)
                {
                    ramlType.Required = !IsOptionalProperty(prop, prop.CustomAttributes);
                    dic.Add(key, ramlType);
                }
            }
            return(dic);
        }
        protected string GetRecursively(Type type, int pad, IEnumerable <CustomAttributeData> customAttributes)
        {
            if (type.IsGenericType && TypeBuilderHelper.IsGenericWebResult(type))
            {
                type = type.GetGenericArguments()[0];
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary <,>))
            {
                return(null);
            }

            if (TypeBuilderHelper.IsArrayOrEnumerable(type))
            {
                var elementType = type.GetElementType() ?? type.GetGenericArguments()[0];

                if (SchemaTypeMapper.Map(elementType) != null)
                {
                    return(GetNestedArraySchemaPrimitiveType(pad, elementType));
                }

                if (elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>))
                {
                    return(GetNestedArraySchema(pad, elementType));
                }

                if (elementType.GetProperties().Count(p => p.CanRead || p.CanWrite) == 0)
                {
                    return(string.Empty);
                }

                return(GetNestedArraySchema(pad, elementType));
            }

            if (type.GetProperties().Count(p => p.CanRead || p.CanWrite) == 0)
            {
                return(string.Empty);
            }

            return(GetNestedObjectSchema(type, pad, customAttributes));
        }
        private string GetOneOfProperty(PropertyInfo prop, IEnumerable <Type> subclasses, int pad)
        {
            var name  = TypeBuilderHelper.GetPropertyName(prop);
            var oneOf = ("\"" + name + "\": {").Indent(pad) + Environment.NewLine;

            oneOf += "\"type\": \"object\",".Indent(pad + 2) + Environment.NewLine;
            oneOf += "\"oneOf\": [".Indent(pad + 2) + Environment.NewLine;
            foreach (var subclass in subclasses.Distinct())
            {
                var className = TypeBuilderHelper.GetClassName(subclass);
                oneOf += ("{ \"$ref\": \"#/definitions/" + className + "\" },").Indent(pad + 4) + Environment.NewLine;
                if (!definitions.ContainsKey(className))
                {
                    definitions.Add(className, subclass);
                }
            }
            oneOf  = oneOf.Substring(0, oneOf.Length - Environment.NewLine.Length - 1) + Environment.NewLine;
            oneOf += "]".Indent(pad + 2) + Environment.NewLine;
            oneOf += "}".Indent(pad) + Environment.NewLine;
            return(oneOf);
        }
        protected string HandleValidationAttribute(CustomAttributeData attribute)
        {
            string res = string.Empty;

            switch (attribute.AttributeType.Name)
            {
            case "MaxLengthAttribute":
                res += ", \"maxLength\": " + attribute.ConstructorArguments.First().Value;
                break;

            case "MinLengthAttribute":
                res += ", \"minLength\": " + attribute.ConstructorArguments.First().Value;
                break;

            case "RangeAttribute":
                if (!TypeBuilderHelper.IsMinValue(attribute.ConstructorArguments.First()))
                {
                    res += ", \"minimum\": " + TypeBuilderHelper.Format(attribute.ConstructorArguments.First());
                }
                if (!TypeBuilderHelper.IsMaxValue(attribute.ConstructorArguments.Last()))
                {
                    res += ", \"maximum\": " + TypeBuilderHelper.Format(attribute.ConstructorArguments.Last());
                }
                break;

            case "EmailAddressAttribute":
                res += @", ""pattern"": ""[^\\s@]+@[^\\s@]+\\.[^\\s@]""";
                break;

            case "UrlAttribute":
                res += @", ""pattern"": ""^(ftp|http|https):\/\/[^ \""]+$""";
                break;
                //case "RegularExpressionAttribute":
                //    res += ", \"pattern\": " + "\"" + attribute.ConstructorArguments.First().Value + "\"";
                //    break;
            }
            return(res);
        }
        public string Get(Type type)
        {
            definitions.Clear();
            Types.Clear();

            string schema;

            if (type.IsGenericType && TypeBuilderHelper.IsGenericWebResult(type))
            {
                type = type.GetGenericArguments()[0];
            }

            if (TypeBuilderHelper.IsArrayOrEnumerable(type))
            {
                var elementType = type.GetElementType() ?? type.GetGenericArguments()[0];
                if (elementType.GetProperties().Count(p => p.CanRead || p.CanWrite) == 0)
                {
                    return(null);
                }

                schema = GetArray(elementType);
            }
            else
            {
                if (type.GetProperties().Count(p => p.CanRead || p.CanWrite) == 0)
                {
                    return(null);
                }

                schema = GetMainObjectSchema(type);
            }

            schema = AddDefinitionsIfAny(schema);

            schema += "}" + Environment.NewLine;

            return(schema);
        }
        protected string HandleNestedTypeProperty(int pad, PropertyInfo prop, string schema, IEnumerable <PropertyInfo> props, IEnumerable <CustomAttributeData> customAttributes)
        {
            var nestedType = GetRecursively(prop.PropertyType, pad + 2, customAttributes);

            if (nestedType == null)
            {
                return(string.Empty);
            }

            if (!string.IsNullOrWhiteSpace(nestedType))
            {
                var name = TypeBuilderHelper.GetPropertyName(prop);
                schema += ("\"" + name + "\":").Indent(pad) + Environment.NewLine;
                schema += nestedType;
            }
            else
            {
                // is it one of ?
                var subclasses = prop.PropertyType.Assembly.GetTypes()
                                 .Where(type => type.IsSubclassOf(prop.PropertyType))
                                 .ToArray();

                if (!subclasses.Any())
                {
                    return(string.Empty);
                }

                schema += GetOneOfProperty(prop, subclasses, pad);
            }

            if (prop != props.Last() && !String.IsNullOrWhiteSpace(schema) && schema.Length > "\r\n".Length)
            {
                schema = schema.Substring(0, schema.Length - "\r\n".Length) + ",\r\n";
            }

            return(schema);
        }
        private RamlType GetProperty(PropertyInfo prop)
        {
            if (prop.PropertyType.GetTypeInfo().IsEnum)
            {
                return(GetEnum(prop.PropertyType));
            }

            if (Raml1TypeMapper.Map(prop.PropertyType) != null)
            {
                return(HandlePrimitiveTypeProperty(prop));
            }

            if (TypeBuilderHelper.IsArrayOrEnumerable(prop.PropertyType))
            {
                return(GetArray(prop.PropertyType));
            }

            if (IsDictionary(prop.PropertyType))
            {
                return(GetMap(prop.PropertyType));
            }

            return(HandleNestedTypeProperty(prop));
        }
 private static bool IsOptionalProperty(PropertyInfo prop, IEnumerable <CustomAttributeData> customAttributes)
 {
     return(customAttributes.All(a => a.AttributeType != typeof(RequiredAttribute)) && TypeBuilderHelper.IsNullable(prop.PropertyType));
 }
        public string Add(Type type)
        {
            var typeName = GetTypeName(type);

            if (types.Contains(type))
            {
                return(typeName);
            }

            RamlType raml1Type;

            if (type.GetTypeInfo().IsGenericType&& TypeBuilderHelper.IsGenericWebResult(type))
            {
                type = type.GetGenericArguments()[0];
            }

            if (TypeBuilderHelper.IsArrayOrEnumerable(type))
            {
                var elementType = GetElementType(type);
                if (TypeBuilderHelper.IsArrayOrEnumerable(elementType))
                {
                    var subElementType = GetElementType(elementType);

                    if (Raml1TypeMapper.Map(subElementType) != null)
                    {
                        return(Raml1TypeMapper.Map(subElementType) + "[][]");
                    }

                    if (!HasPropertiesOrParentType(subElementType))
                    {
                        return(string.Empty);
                    }

                    types.Add(type);

                    raml1Type = GetArrayOfArray(subElementType);
                }
                else
                {
                    if (Raml1TypeMapper.Map(elementType) != null)
                    {
                        return(Raml1TypeMapper.Map(elementType) + "[]");
                    }

                    if (!HasPropertiesOrParentType(elementType))
                    {
                        return(string.Empty);
                    }

                    types.Add(type);

                    raml1Type = GetArray(elementType);
                }
            }
            else if (IsDictionary(type) || IsParentADictionary(type))
            {
                types.Add(type);
                raml1Type = GetMap(type);
            }
            else if (type.GetTypeInfo().IsEnum)
            {
                types.Add(type);
                raml1Type = GetEnum(type);
            }
            else if (Raml1TypeMapper.Map(type) != null)
            {
                //raml1Type = GetScalar(type);
                raml1Type = null;
                typeName  = Raml1TypeMapper.Map(type);
            }
            else
            {
                if (!HasPropertiesOrParentType(type))
                {
                    return(string.Empty);
                }

                types.Add(type);
                raml1Type = GetObject(type);
            }

            if (raml1Type != null)
            {
                AddType(type, raml1Type);
            }

            return(typeName);
        }
 private static string GetEnumProperty(PropertyInfo prop, int pad)
 {
     return(("\"" + TypeBuilderHelper.GetPropertyName(prop) + "\": { ").Indent(pad) + Environment.NewLine
            + ("  \"enum\": [" + string.Join(", ", Enum.GetNames(prop.PropertyType).Select(v => "\"" + v + "\"")) + "]").Indent(pad) + Environment.NewLine
            + "}".Indent(pad));
 }