private static void SerializeExternal(StringBuilder sb, RamlType ramlType, int indentation)
        {
            if (!string.IsNullOrWhiteSpace(ramlType.External.Schema))
                RamlSerializerHelper.SerializeSchema(sb, "schema", ramlType.External.Schema, indentation + 4);

            if (!string.IsNullOrWhiteSpace(ramlType.External.Xml))
                RamlSerializerHelper.SerializeSchema(sb, "schema", ramlType.External.Xml, indentation + 4);
        }
        public static RamlType GetRamlType(KeyValuePair<string, object> type)
        {
            var key = type.Key;
            var required = true;

            if (key.EndsWith("?"))
            {
                key = key.Substring(0, key.Length - 1);
                required = false;
            }

            var ramlType = new RamlType();
            ramlType.Name = key;
            ramlType.Required = required;

            var simpleProperty = type.Value as string;
            if (simpleProperty != null)
            {
                if (simpleProperty.StartsWith("<"))
                {
                    ramlType.External = new ExternalType
                    {
                        Xml = simpleProperty
                    };
                    return ramlType;
                }
                if (simpleProperty.StartsWith("{"))
                {
                    ramlType.External = new ExternalType
                    {
                        Schema = simpleProperty
                    };
                    return ramlType;
                }

                ramlType.Scalar = GetScalar(type, required);
                return ramlType;
            }

            var dynamicRaml = type.Value as IDictionary<string, object>;
            if (dynamicRaml == null)
                throw new InvalidOperationException("Cannot parse type: " + type.Key);

            var value = (IDictionary<string, object>)type.Value;
            ramlType = new RamlType
            {
                Name = type.Key,
                Type = GetType(value),
                Example = DynamicRamlParser.GetExample(value),
                Facets = DynamicRamlParser.GetDictionaryOrNull<object>(value, "facets"),
                OtherProperties = GetOtherProperties(value),
                Required = GetRequired(value, required)
            };

            SetPropertiesByType(type, ramlType);

            return ramlType;
        }
        private static void SerializeCommonProperties(StringBuilder sb, RamlType ramlType, int indentation)
        {
            RamlSerializerHelper.SerializeProperty(sb, "description", ramlType.Description, indentation + 4);

            RamlSerializerHelper.SerializeProperty(sb, "displayName", ramlType.DisplayName, indentation + 4);

            RamlSerializerHelper.SerializeProperty(sb, "example", ramlType.Example, indentation + 4);

            SerializeFacets(sb, ramlType.Facets, indentation + 4);
        }
        private static void SerializeExamples(StringBuilder sb, RamlType ramlType, int indentation)
        {
            if (ramlType.Examples == null || !ramlType.Examples.Any())
                return;

            sb.Append("examples:".Indent(indentation + 4));
            sb.AppendLine();
            foreach (var example in ramlType.Examples)
            {
                sb.Append("- content: ".Indent(indentation + 8));
                sb.AppendLine();
                sb.Append(example);
                sb.AppendLine();
            }
        }
        private RamlType GetObject(Type type)
        {
            var raml1Type = new RamlType();
            raml1Type.Object = new ObjectType();
            raml1Type.Type = "object";

            if (type.BaseType != null && type.BaseType != typeof(object))
            {
                var parent = GetObject(type.BaseType);
                AddType(type.BaseType, parent);
                raml1Type.Type = GetTypeName(type.BaseType);
            }

            if (GetClassProperties(type).Count(p => p.CanWrite) > 0)
            {
                raml1Type.Object.Properties = GetProperties(type);
            }
            return raml1Type;
        }
        private RamlType GetMap(Type type)
        {
            Type subtype;

            if(IsDictionary(type))
                subtype = type.GetGenericArguments()[1];
            else
                subtype = type.BaseType.GetGenericArguments()[1];

            var subtypeName = GetTypeName(subtype);

            if (Raml1TypeMapper.Map(subtype) != null)
                subtypeName = Raml1TypeMapper.Map(subtype);
            else
                subtypeName = Add(subtype);

            if(string.IsNullOrWhiteSpace(subtypeName))
                return null;

            var raml1Type = new RamlType
            {
                Object = new ObjectType
                {
                    Properties = new Dictionary<string, RamlType>()
                    {
                        {
                            "[]", new RamlType
                            {
                                Type = subtypeName,
                                Required = true
                            }
                        }
                    }
                }
            };

            return raml1Type;
        }
        private RamlType GetEnum(Type type)
        {
            var ramlType = new RamlType
            {
                Type = "string",
                Scalar = new Property { Enum = type.GetEnumNames() } // TODO: check!!
            };

            return ramlType;
        }
        private RamlType GetArrayOfArray(Type subElementType)
        {
            string elementTypeName;
            if (Raml1TypeMapper.Map(subElementType) == null)
                elementTypeName = Add(subElementType);
            else
                elementTypeName = Raml1TypeMapper.Map(subElementType);

            if (string.IsNullOrWhiteSpace(elementTypeName))
                return null;

            var raml1Type = new RamlType
            {
                Array = new ArrayType
                {
                    Items = new RamlType
                    {
                        Array = new ArrayType
                        {
                            Items = new RamlType
                            {
                                Name = GetTypeName(subElementType),
                                Type = elementTypeName
                            }
                        }
                    }
                }
            };

            return raml1Type;
        }
        private void AddType(Type type, RamlType raml1Type)
        {
            var typeName = GetTypeName(type);

            // handle case of different types with same class name
            if (raml1Types.ContainsKey(typeName))
                typeName = GetUniqueName(typeName);

            raml1Types.Add(typeName, raml1Type);
        }
 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 void SerializeObject(StringBuilder sb, RamlType ramlType, int indentation)
 {
     RamlSerializerHelper.SerializeProperty(sb, "maxProperties", ramlType.Object.MaxProperties, indentation + 4);
     RamlSerializerHelper.SerializeProperty(sb, "minProperties", ramlType.Object.MinProperties, indentation + 4);
     RamlSerializerHelper.SerializeProperty(sb, "discriminator", ramlType.Object.Discriminator as string, indentation + 4);
     RamlSerializerHelper.SerializeProperty(sb, "discriminatorValue", ramlType.Object.DiscriminatorValue, indentation + 4);
     SerializeObjectProperties(sb, ramlType.Object.Properties, indentation + 4);
 }
        private static void SetPropertiesByType(KeyValuePair<string, object> pair, RamlType ramlType)
        {
            var dynamicRaml = pair.Value as IDictionary<string, object>;

            if(ramlType == null)
                return;

            if (PrimitiveTypes.Contains(ramlType.Type))
            {
                ramlType.Scalar = GetScalar(pair, ramlType.Required);
                return;
            }

            if (ramlType.Type.StartsWith("{"))
            {
                ramlType.External = new ExternalType {Schema = ramlType.Type};
                return;
            }
            if (ramlType.Type.StartsWith("<"))
            {
                ramlType.External = new ExternalType { Xml = ramlType.Type };
                return;
            }

            if (ramlType.Type == "object")
            {
                ramlType.Object = GetObject(dynamicRaml);
                return;
            }

            if (ramlType.Type == "array" || ramlType.Type.EndsWith("[]"))
            {
                ramlType.Array = GetArray(dynamicRaml, pair.Key);
                return;
            }

            if (ramlTypes.ContainsKey(ramlType.Type))
            {
                // Inheritance or Specialization
                var parentType = ramlTypes[ramlType.Type];

                if (parentType.Scalar != null)
                {
                    ramlType.Scalar = GetScalar(new KeyValuePair<string, object>(ramlType.Name, dynamicRaml), ramlType.Required);
                    return;
                }

                if (parentType.Object != null)
                {
                    ramlType.Object = GetObject(dynamicRaml);
                    return;
                }
            }

            if (ramlType.Type.Contains("|")) // Union Type
            {
                return;
            }

            if (!defferredTypes.ContainsKey(pair.Key))
            {
                defferredTypes.Add(pair.Key, pair.Value);
            }
            else if (dynamicRaml.ContainsKey("properties"))
            {
                ramlType.Object = GetObject(dynamicRaml);
            }
            //throw new InvalidOperationException("Cannot parse type: " + ramlType.Type);
        }
 public void Add(string key, RamlType value)
 {
     dic.Add(key, value);
 }
 private void SerializeScalar(StringBuilder sb, RamlType ramlType, int indentation)
 {
     RamlSerializerHelper.SerializeCommonParameterProperties(sb, ramlType.Scalar, indentation);
     RamlSerializerHelper.SerializeProperty(sb, "multipleOf", ramlType.Scalar.MultipleOf, indentation);
     RamlSerializerHelper.SerializeListProperty(sb, "fileTypes", ramlType.Scalar.FileTypes, indentation);
     SerializeFormat(sb, indentation, ramlType.Scalar.Format);
     SerializeAnnotations(sb, ramlType.Scalar.Annotations, indentation);
 }
 private RamlType GetScalar(Type type)
 {
     var ramlType = new RamlType
     {
         Scalar = new Property
         {
             Type = Raml1TypeMapper.Map(type),
         }
     };
     return ramlType;
 }
 public void Add(string key, RamlType value)
 {
     dic.Add(key, value);
 }
 private void HandleValidationAttributes(RamlType ramlTypeProp, IEnumerable<CustomAttributeData> customAttributes)
 {
     foreach (var attribute in customAttributes)
     {
         HandleValidationAttribute(ramlTypeProp, attribute);
     }
 }
        private void Serialize(StringBuilder sb, string propertyTitle, RamlType ramlType, int indentation)
        {
            sb.AppendFormat("{0}:".Indent(indentation), propertyTitle);
            sb.AppendLine();

            SerializeTypeProperty(sb, indentation, ramlType.Type);
            SerializeCommonProperties(sb, ramlType, indentation);

            SerializeExamples(sb, ramlType, indentation);

            if (ramlType.Scalar != null)
                SerializeScalar(sb, ramlType, indentation);

            if (ramlType.Object != null)
                SerializeObject(sb, ramlType, indentation);

            if (ramlType.Array != null)
                SerializeArray(sb, indentation, ramlType.Array);

            if (ramlType.External != null)
                SerializeExternal(sb, ramlType, indentation);
        }