private IEnumerable<Property> GetSecurityParameters(RamlDocument ramlDocument, Method method)
		{
			var securityParams = new Collection<Property>();
			if (ramlDocument.SecuritySchemes == null || !ramlDocument.SecuritySchemes.Any())
				return securityParams;

			if ((ramlDocument.SecuredBy == null || !ramlDocument.SecuredBy.Any())
				&& (method.SecuredBy == null || !method.SecuredBy.Any()))
				return securityParams;

			var securedBy = method.SecuredBy != null && method.SecuredBy.Any() ? method.SecuredBy : ramlDocument.SecuredBy;

			if (securedBy == null)
				return securityParams;

			var secured = securedBy.First();

			var dic = ramlDocument.SecuritySchemes.FirstOrDefault(s => s.ContainsKey(secured));
			if (dic == null)
				return securityParams;

			var descriptor = ramlDocument.SecuritySchemes.First(s => s.ContainsKey(secured))[secured].DescribedBy;
			if (descriptor == null || descriptor.QueryParameters == null || !descriptor.QueryParameters.Any())
				return securityParams;

			return QueryParametersParser.ConvertParametersToProperties(descriptor.QueryParameters);
		}
		public Method Build(IDictionary<string, object> dynamicRaml)
		{
			var method = new Method();
			new BasicInfoBuilder().Set(dynamicRaml, method);

			method.Verb = dynamicRaml.ContainsKey("method") ? (string) dynamicRaml["method"] : null;
			method.Headers = dynamicRaml.ContainsKey("headers")
				? new ParametersBuilder(dynamicRaml["headers"] as IDictionary<string, object>).Get()
				: new List<Parameter>();

			method.Responses = dynamicRaml.ContainsKey("responses")
				? new ResponsesBuilder(dynamicRaml["responses"] as IDictionary<string, object>).Get()
				: new List<Response>();

			method.QueryParameters = dynamicRaml.ContainsKey("queryParameters")
				? new ParametersBuilder((IDictionary<string, object>) dynamicRaml["queryParameters"]).GetAsDictionary()
				: null;

			method.Body = dynamicRaml.ContainsKey("body")
				? new BodyBuilder((IDictionary<string, object>) dynamicRaml["body"]).GetAsDictionary()
				: new Dictionary<string, MimeType>();

			method.BaseUriParameters = ParametersBuilder.GetUriParameters(dynamicRaml, "baseUriParameters");
			method.SecuredBy = GetSecuredBy(dynamicRaml);
			method.Protocols = ProtocolsBuilder.Get(dynamicRaml);
			method.Is = GetIs(dynamicRaml);
			method.Description = dynamicRaml.ContainsKey("description") ? (string) dynamicRaml["description"] : null;

			return method;
		}
		private void AddGeneratedMethod(Resource resource, string url, string objectName, Method method, ICollection<string> methodsNames, 
            ICollection<ClientGeneratorMethod> generatorMethods)
		{
			var generatedMethod = BuildClassMethod(url, method, resource);
			if (generatedMethod.ReturnType != "string")
			{
                var returnType = CollectionTypeHelper.GetBaseType(generatedMethod.ReturnType);

			    generatedMethod.ReturnTypeObject = schemaResponseObjects.Values
			        .First(o => o.Name == returnType );

				generatedMethod.OkReturnType = GetOkReturnType(generatedMethod);
			}
			uriParametersGenerator.Generate(resource, url, generatedMethod, uriParameterObjects);

			if (!IsVerbForMethod(method)) return;

			if (methodsNames.Contains(generatedMethod.Name))
				generatedMethod.Name = GetUniqueName(methodsNames, generatedMethod.Name, resource.RelativeUri);

			GetQueryParameters(objectName, method, generatedMethod);

			GetHeaders(objectName, method, generatedMethod);

			GetResponseHeaders(objectName, generatedMethod, method);

			generatorMethods.Add(generatedMethod);
			methodsNames.Add(generatedMethod.Name);
		}
        public static ApiObject GetQueryObject(ClientGeneratorMethod generatedMethod, Method method, string objectName)
        {
            var queryObject = new ApiObject { Name = generatedMethod.Name + objectName + "Query" };
            queryObject.Properties = ParseParameters(method);

            return queryObject;
        }
 public static ApiObject GetHeadersObject(ClientGeneratorMethod generatedMethod, Method method, string objectName)
 {
     return new ApiObject
     {
         Name = generatedMethod.Name + objectName + "Header",
         Properties = ParseHeaders(method)
     };
 }
	    private static string ReplaceReservedParameters(string schema, Method method, string url)
	    {
	        var res = schema.Replace("<<resourcePathName>>", url.Substring(1));
	        res = res.Replace("<<resourcePath>>", url);
	        if (method != null && method.Verb != null)
	            res = res.Replace("<<methodName>>", method.Verb.ToLower());
	        return res;
	    }
		private List<Property> GetProperties(IEnumerable<Response> responses, Resource resource, Method method, string key, string fullUrl)
		{
			var properties = new List<Property>();
			foreach (var response in responses)
			{
				AddProperty(resource, method, key, response, properties, fullUrl);
			}
			return properties;
		}
		public string Parse(string schema, Resource resource, Method method, string fullUrl)
		{
			var url = GetResourcePath(resource, fullUrl);

		    var res = ReplaceReservedParameters(schema, method, url);
            res = ReplaceCustomParameters(resource, res);
		    res = ReplaceParametersWithFunctions(resource, res, url);

			return res;
		}
        public RamlMethodWrapper(Method ramlDocMethod)
        {
            Verb = ramlDocMethod.Verb;

            var methodBody = ramlDocMethod.Body.FirstOrDefault(kvp => kvp.Key.Contains("json"));
            MediaType = methodBody.Key;
            JsonSchema = (MediaType != null) ? methodBody.Value.Schema : null;
            IsMTJson = (JsonSchema != null);

            ramlResponses = parseRAMLResponses(ramlDocMethod.Responses);
        }
	    protected string GetReturnType(string key, Method method, Resource resource, string fullUrl)
		{
			if (!method.Responses.Any(r => r.Body != null && r.Body.Any(b => !string.IsNullOrWhiteSpace(b.Value.Schema))))
				return "string";

			var responses = method.Responses
				.Where(r => r.Body != null && r.Body.Any(b => !string.IsNullOrWhiteSpace(b.Value.Schema)))
				.ToArray();

			var returnType = HandleMultipleSchemaType(responses, resource, method, key, fullUrl);

			if (!string.IsNullOrWhiteSpace(returnType))
				return returnType;

			return "string";
		}
	    private ClientGeneratorMethod BuildClassMethod(string url, Method method, Resource resource)
		{
			var generatedMethod = new ClientGeneratorMethod
			{
				Name = NetNamingMapper.GetMethodName(method.Verb ?? "Get" + resource.RelativeUri),
				ReturnType = GetReturnType(GeneratorServiceHelper.GetKeyForResource(method, resource), method, resource, url),
				Parameter = GetParameter(GeneratorServiceHelper.GetKeyForResource(method, resource), method, resource, url),
				Comment = GetComment(resource, method),
				Url = url,
				Verb = NetNamingMapper.Capitalize(method.Verb),
				Parent = null,
				UseSecurity =
					raml.SecuredBy != null && raml.SecuredBy.Any() ||
					resource.Methods.Any(m => m.Verb == method.Verb && m.SecuredBy != null && m.SecuredBy.Any())
			};
			return generatedMethod;
		}
        protected GeneratorParameter GetParameter(string key, Method method, Resource resource, string fullUrl)
        {
            var schema = GetJsonSchemaOrDefault(method.Body);
            if (schema != null)
            {
                var generatorParameter = GetGeneratorParameterWhenNamed(method, resource, schema, fullUrl);
                if (generatorParameter != null)
                    return generatorParameter;
            }

            if (resource.Type != null && resource.Type.Any() && raml.ResourceTypes.Any(rt => rt.ContainsKey(resource.GetResourceType())))
            {
                var verb = GetResourceTypeVerb(method, resource);
                if (verb != null && verb.Body != null && !string.IsNullOrWhiteSpace(verb.Body.Schema))
                {
                    var generatorParameter = GetGeneratorParameterWhenNamed(method, resource, verb.Body.Schema, fullUrl);
                    if (generatorParameter != null)
                        return generatorParameter;
                }
            }

            if (RequestHasKey(key))
                return GetGeneratorParameterByKey(key);

            var requestKey = key + GeneratorServiceBase.RequestContentSuffix;
            if (RequestHasKey(requestKey))
                return GetGeneratorParameterByKey(requestKey);

            if (linkKeysWithObjectNames.ContainsKey(key))
            {
                var linkedKey = linkKeysWithObjectNames[key];
                if (RequestHasKey(linkedKey))
                    return GetGeneratorParameterByKey(linkedKey);
            }

            if (linkKeysWithObjectNames.ContainsKey(requestKey))
            {
                var linkedKey = linkKeysWithObjectNames[requestKey];
                if (RequestHasKey(linkedKey))
                    return GetGeneratorParameterByKey(linkedKey);
            }

            return new GeneratorParameter {Name = "content", Type = "string"};
        }
        private static IEnumerable<Method> GetMethods(IDictionary<string, object> dynamicRaml, IEnumerable<IDictionary<string, Method>> traits, string defaultMediaType)
        {
            var methods = new Collection<Method>();
            if (!dynamicRaml.ContainsKey("methods"))
                return methods;

            var dynamicMethods = dynamicRaml["methods"] as object[];
            foreach (var dynamicMethod in dynamicMethods)
            {
                Method method = new Method();

                var dictionary = dynamicMethod as IDictionary<string, object>;
                if(dictionary != null)
                    method = new MethodBuilder().Build(dictionary, defaultMediaType);

                methods.Add(method);
            }
            return methods;
        }
		private ControllerMethod BuildControllerMethod(string url, Method method, Resource resource, ControllerObject parent)
		{
			var relativeUri = UrlGeneratorHelper.GetRelativeUri(url, parent.PrefixUri);

			return new ControllerMethod
			{
				Name = NetNamingMapper.GetMethodName(method.Verb ?? "Get" + resource.RelativeUri),
				Parameter = GetParameter(GeneratorServiceHelper.GetKeyForResource(method, resource), method, resource, url),
				UriParameters = uriParametersGenerator.GetUriParameters(resource, url),
				ReturnType = GetReturnType(GeneratorServiceHelper.GetKeyForResource(method, resource), method, resource, url),
				Comment = GetComment(resource, method),
				Url = relativeUri,
				Verb = NetNamingMapper.Capitalize(method.Verb),
				Parent = null,
				UseSecurity =
					raml.SecuredBy != null && raml.SecuredBy.Any() ||
					resource.Methods.Any(m => m.Verb == method.Verb && m.SecuredBy != null && m.SecuredBy.Any()),
				SecurityParameters = GetSecurityParameters(raml, method)
			};
		}
		private string HandleMultipleSchemaType(IEnumerable<Response> responses, Resource resource, Method method, string key, string fullUrl)
		{
			var properties = GetProperties(responses, resource, method, key, fullUrl);

			if (properties.Count == 0)
				return "string";

			if (properties.Count == 1)
				return properties.First().Type;

			// Build a new response object containing all types
			var name = NetNamingMapper.GetObjectName("Multiple" + key);
			var apiObject = new ApiObject
			{
				Name = name,
				Description = "Multiple Response Types " + string.Join(", ", properties.Select(p => p.Name)),
				Properties = properties,
				IsMultiple = true
			};
			schemaResponseObjects.Add(new KeyValuePair<string, ApiObject>(name, apiObject));
			return name;
		}
		private void AddProperty(Resource resource, Method method, string key, Response response, ICollection<Property> properties, string fullUrl)
		{
			var mimeType = GeneratorServiceHelper.GetMimeType(response);
			if (mimeType == null)
				return;

			var type = GetReturnTypeFromResponse(method, resource, mimeType, key, response.Code, fullUrl);
			if (string.IsNullOrWhiteSpace(type))
				return;

			var property = new Property
			               {
                               Name = CollectionTypeHelper.GetBaseType(type),
				               Description = response.Description + " " + mimeType.Description,
				               Example = mimeType.Example,
				               Type = type,
				               StatusCode = (HttpStatusCode) Enum.Parse(typeof (HttpStatusCode), response.Code),
                               JSONSchema = mimeType.Schema == null ? null : mimeType.Schema.Replace(Environment.NewLine, "").Replace("\r\n", "").Replace("\n", "").Replace("\"", "\\\"")
			               };

			properties.Add(property);
		}
		private IEnumerable<Method> GetMethods(ApiDescription api, ICollection<string> verbs)
		{
			var methods = new Collection<Method>();
			foreach (var httpMethod in api.ActionDescriptor.SupportedHttpMethods)
			{
				var verb = httpMethod.Method.ToLowerInvariant();
				if (verbs.Contains(verb)) 
					continue;

				var method = new Method
				             {
					             Description = GetDescription(api),
					             Verb = verb,
					             QueryParameters = GetQueryParameters(api.RelativePath, api.ParameterDescriptions),
					             Body = GetRequestMimeTypes(api),
					             Responses = GetResponses(api.ResponseDescription),
				             };
				methods.Add(method);
                verbs.Add(verb);

                if (SetMethodProperties != null)
                    SetMethodProperties(api, method);

			}
			return methods;
		}
		private void GetResponseHeaders(string objectName, ClientGeneratorMethod generatedMethod, Method method)
		{
			generatedMethod.ResponseHeaders = new Dictionary<HttpStatusCode, ApiObject>();
			foreach (var resp in method.Responses.Where(r => r.Headers != null && r.Headers.Any()))
			{
				var headerObject = HeadersParser.GetHeadersObject(generatedMethod, resp, objectName);
				generatedMethod.ResponseHeaders.Add(ParserHelpers.GetHttpStatusCode(resp.Code), headerObject);
				responseHeadersObjects.Add(headerObject.Name, headerObject);
			}

			if (!generatedMethod.ResponseHeaders.Any())
			{
				generatedMethod.ResponseHeaderType = defaultHeaderType;
			}
			else if (generatedMethod.ResponseHeaders.Count == 1)
			{
				generatedMethod.ResponseHeaderType = ClientGeneratorMethod.ModelsNamespacePrefix + generatedMethod.ResponseHeaders.First().Value.Name;
			}
			else
			{
				CreateMultipleType(generatedMethod);
			}
		}
		private void SerializeMethod(StringBuilder sb, Method method, int indentation)
		{
			sb.AppendLine((method.Verb + ":").Indent(indentation));
            SerializeDescriptionProperty(sb, method.Description, indentation + 2);
			//SerializeType(sb, method.Type, indentation + 2);
			
			if (method.Headers != null)
			{
				sb.AppendLine("headers:".Indent(indentation + 2));
				foreach (var header in method.Headers)
				{
					SerializeParameterProperties(sb, header, indentation + 4);
				}
			}

			SerializeArrayProperty(sb, "is", method.Is, indentation + 2);
			SerializeProtocols(sb, method.Protocols, indentation + 2);
			SerializeArrayProperty(sb, "securedBy", method.SecuredBy, indentation + 2);
			SerializeParameters(sb, "baseUriParameters", method.BaseUriParameters, indentation + 2);
			SerializeParameters(sb, "queryParameters", method.QueryParameters, indentation + 2);
			SerializeBody(sb, method.Body, indentation + 2);
			SerializeResponses(sb, method.Responses, indentation + 2);
			
		}
		private GeneratorParameter GetParameterByParametrizedName(Method method, Resource resource, string schema, string fullUrl)
		{
			GeneratorParameter generatorParameter = null;
			var type = schemaParameterParser.Parse(schema, resource, method, fullUrl);
			if (schemaRequestObjects.Values.Any(o => o.Properties.Any() && o.Name.ToLower() == type.ToLowerInvariant()))
			{
				var apiObject = schemaRequestObjects.Values.First(o => o.Properties.Any() && o.Name.ToLower() == type.ToLowerInvariant());
				generatorParameter = new GeneratorParameter
				                     {
					                     Name = apiObject.Name.ToLower(),
                                         Type = apiObject.IsArray ? CollectionTypeHelper.GetCollectionType(apiObject.Name) : apiObject.Name,
					                     Description = apiObject.Description
				                     };
			}
			return generatorParameter;
		}
	    private string GetReturnTypeFromParameter(Method method, Resource resource, MimeType mimeType, string fullUrl, string returnType)
	    {
	        var type = schemaParameterParser.Parse(mimeType.Schema, resource, method, fullUrl);
	        if (schemaResponseObjects.Values.Any(o => o.Properties.Any() && o.Name.ToLowerInvariant() == type.ToLowerInvariant()))
	        {
	            var apiObject =
	                schemaResponseObjects.Values.First(
	                    o => o.Properties.Any() && o.Name.ToLowerInvariant() == type.ToLowerInvariant());
                returnType = apiObject.IsArray ? CollectionTypeHelper.GetCollectionType(apiObject.Name) : apiObject.Name;
	        }
	        return returnType;
	    }
        private string GetReturnTypeFromResourceType(Method method, Resource resource, string key, string responseCode, string fullUrl)
        {
            var returnType = string.Empty;
            if (resource.Type == null || !resource.Type.Any() ||
                !raml.ResourceTypes.Any(rt => rt.ContainsKey(resource.GetResourceType())))
                return returnType;

            var verb = GetResourceTypeVerb(method, resource);
            if (verb == null || verb.Responses == null
                || !verb.Responses.Any(r => r != null && r.Body != null
                                            && r.Body.Values.Any(m => !string.IsNullOrWhiteSpace(m.Schema))))
                return returnType;

            var response = verb.Responses.FirstOrDefault(r => r.Code == responseCode);
            if (response == null)
                return returnType;

            var resourceTypeMimeType = GeneratorServiceHelper.GetMimeType(response);
            if (resourceTypeMimeType != null)
            {
                returnType = GetReturnTypeFromResponseWithoutCheckingResourceTypes(method, resource, resourceTypeMimeType, key, responseCode, fullUrl);
            }
            return returnType;
        }
        // avois infinite recursion
        private string GetReturnTypeFromResponseWithoutCheckingResourceTypes(Method method, Resource resource, MimeType mimeType, string key, string responseCode, string fullUrl)
        {
            var returnType = GetNamedReturnType(method, resource, mimeType, fullUrl);

            if (!string.IsNullOrWhiteSpace(returnType))
                return returnType;

            if (ResponseHasKey(key))
                return GetReturnTypeFromResponseByKey(key);

            var responseKey = key + ParserHelpers.GetStatusCode(responseCode) + GeneratorServiceBase.ResponseContentSuffix;
            if (ResponseHasKey(responseKey))
                return GetReturnTypeFromResponseByKey(responseKey);

            if (linkKeysWithObjectNames.ContainsKey(key))
            {
                var linkedKey = linkKeysWithObjectNames[key];
                if (ResponseHasKey(linkedKey))
                    return GetReturnTypeFromResponseByKey(linkedKey);
            }

            if (linkKeysWithObjectNames.ContainsKey(responseKey))
            {
                var linkedKey = linkKeysWithObjectNames[responseKey];
                if (ResponseHasKey(linkedKey))
                    return GetReturnTypeFromResponseByKey(linkedKey);
            }

            return returnType;
        }
        private GeneratorParameter GetParameterByParametrizedName(Method method, Resource resource, string schema, string fullUrl)
        {
            GeneratorParameter generatorParameter = null;
            var type = schemaParameterParser.Parse(schema, resource, method, fullUrl);
            if (schemaObjects.Values.Any(o => o.Name.ToLower() == type.ToLowerInvariant()))
            {
                var apiObject = schemaObjects.Values.First(o => o.Name.ToLower() == type.ToLowerInvariant());
                generatorParameter = CreateGeneratorParameter(apiObject);
            }

            if (schemaRequestObjects.Values.Any(o => o.Name.ToLower() == type.ToLowerInvariant()))
            {
                var apiObject = schemaRequestObjects.Values.First(o => o.Name.ToLower() == type.ToLowerInvariant());
                generatorParameter = CreateGeneratorParameter(apiObject);
            }
            return generatorParameter;
        }
        private string GetReturnTypeFromParameter(Method method, Resource resource, MimeType mimeType, string fullUrl, string returnType)
        {
            var type = schemaParameterParser.Parse(mimeType.Schema, resource, method, fullUrl);

            if (schemaObjects.Values.Any(o => o.Name.ToLowerInvariant() == type.ToLowerInvariant()))
            {
                var apiObject = schemaObjects.Values
                    .First(o => o.Name.ToLowerInvariant() == type.ToLowerInvariant());
                return GetTypeFromApiObject(apiObject);
            }

            if (schemaResponseObjects.Values.Any(o => o.Name.ToLowerInvariant() == type.ToLowerInvariant()))
            {
                var apiObject = schemaResponseObjects.Values
                    .First(o => o.Name.ToLowerInvariant() == type.ToLowerInvariant());
                return GetTypeFromApiObject(apiObject);
            }

            return returnType;
        }
 private string GetNamedReturnType(Method method, Resource resource, MimeType mimeType, string fullUrl)
 {
     var returnType = string.Empty;
     if (mimeType.Schema.Contains("<<") && mimeType.Schema.Contains(">>"))
     {
         returnType = GetReturnTypeFromParameter(method, resource, mimeType, fullUrl, returnType);
     }
     else if (!mimeType.Schema.Contains("<") && !mimeType.Schema.Contains("{"))
     {
         returnType = GetReturnTypeFromName(mimeType, returnType);
     }
     return returnType;
 }
 private GeneratorParameter GetGeneratorParameterWhenNamed(Method method, Resource resource,
     string schema, string fullUrl)
 {
     if (schema.Contains("<<") && schema.Contains(">>"))
     {
         var generatorParameter = GetParameterByParametrizedName(method, resource, schema, fullUrl);
         if (generatorParameter != null)
             return generatorParameter;
     }
     else if (!schema.Contains("<") && !schema.Contains("{"))
     {
         var generatorParameter = GetParameterByName(schema);
         if (generatorParameter != null)
             return generatorParameter;
     }
     return null;
 }
        protected bool IsVerbForMethod(Method method)
        {
            if (method.Verb == null)
                return true;

            return method.Verb.ToLower() != "options" && method.Verb.ToLower() != "head" && method.Verb.ToLower() != "trace" && method.Verb.ToLower() != "connect";
        }
 protected Verb GetResourceTypeVerb(Method method, Resource resource)
 {
     var resourceTypes = raml.ResourceTypes.First(rt => rt.ContainsKey(resource.GetResourceType()));
     var resourceType = resourceTypes[resource.GetResourceType()];
     Verb verb;
     switch (method.Verb)
     {
         case "get":
             verb = resourceType.Get;
             break;
         case "delete":
             verb = resourceType.Delete;
             break;
         case "post":
             verb = resourceType.Post;
             break;
         case "put":
             verb = resourceType.Put;
             break;
         case "patch":
             verb = resourceType.Patch;
             break;
         case "options":
             verb = resourceType.Options;
             break;
         default:
             throw new InvalidOperationException("Verb not found " + method.Verb);
     }
     return verb;
 }
		public static IList<Property> ParseParameters(Method method)
		{
			return ConvertParametersToProperties(method.QueryParameters);
		}