1 // Copyright 2021 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package com.google.api.generator.gapic.model; 16 17 import com.google.api.generator.gapic.utils.JavaStyle; 18 import com.google.auto.value.AutoValue; 19 import com.google.common.collect.ImmutableSet; 20 import java.util.LinkedHashMap; 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Set; 24 import java.util.stream.Collectors; 25 import javax.annotation.Nullable; 26 27 @AutoValue 28 public abstract class HttpBindings { 29 public enum HttpVerb { 30 GET, 31 PUT, 32 POST, 33 DELETE, 34 PATCH, 35 } 36 37 @AutoValue 38 public abstract static class HttpBinding implements Comparable<HttpBinding> { 39 40 // The fully qualified name of the field. e.g. request.complex_object.another_object.name name()41 public abstract String name(); 42 lowerCamelName()43 abstract String lowerCamelName(); 44 45 // An object that contains all info of the leaf level field 46 @Nullable field()47 public abstract Field field(); 48 isOptional()49 public boolean isOptional() { 50 return field() != null && field().isProto3Optional(); 51 } 52 isRepeated()53 public boolean isRepeated() { 54 return field() != null && field().isRepeated(); 55 } 56 isEnum()57 public boolean isEnum() { 58 return field() != null && field().isEnum(); 59 } 60 61 @Nullable valuePattern()62 public abstract String valuePattern(); 63 builder()64 public static HttpBindings.HttpBinding.Builder builder() { 65 return new AutoValue_HttpBindings_HttpBinding.Builder(); 66 } 67 68 @AutoValue.Builder 69 public abstract static class Builder { 70 setName(String name)71 public abstract HttpBindings.HttpBinding.Builder setName(String name); 72 setField(Field field)73 public abstract HttpBindings.HttpBinding.Builder setField(Field field); 74 setLowerCamelName(String lowerCamelName)75 abstract HttpBindings.HttpBinding.Builder setLowerCamelName(String lowerCamelName); 76 setValuePattern(String valuePattern)77 public abstract HttpBindings.HttpBinding.Builder setValuePattern(String valuePattern); 78 name()79 abstract String name(); 80 autoBuild()81 abstract HttpBindings.HttpBinding autoBuild(); 82 build()83 public HttpBindings.HttpBinding build() { 84 setLowerCamelName(JavaStyle.toLowerCamelCase(name())); 85 return autoBuild(); 86 } 87 } 88 89 // Do not forget to keep it in sync with equals() implementation. 90 @Override compareTo(HttpBinding o)91 public int compareTo(HttpBinding o) { 92 int res = name().compareTo(o.name()); 93 return res == 0 ? Boolean.compare(isOptional(), o.isOptional()) : res; 94 } 95 } 96 httpVerb()97 public abstract HttpVerb httpVerb(); 98 pattern()99 public abstract String pattern(); 100 additionalPatterns()101 public abstract List<String> additionalPatterns(); 102 pathParameters()103 public abstract Set<HttpBinding> pathParameters(); 104 queryParameters()105 public abstract Set<HttpBinding> queryParameters(); 106 bodyParameters()107 public abstract Set<HttpBinding> bodyParameters(); 108 isAsteriskBody()109 public abstract boolean isAsteriskBody(); 110 builder()111 public static HttpBindings.Builder builder() { 112 return new AutoValue_HttpBindings.Builder() 113 .setPathParameters(ImmutableSet.of()) 114 .setQueryParameters(ImmutableSet.of()) 115 .setBodyParameters(ImmutableSet.of()); 116 } 117 118 // Protobuf fields and template patterns follow snake_case style. When translated into actual Java 119 // class fields and URL respectively, those must be converted to lowerCamelCase. 120 // For example: 121 // in .proto file: "/global/instanceTemplates/{instance_template=*}" 122 // in .java file: "/global/instanceTemplates/{instanceTemplate=*}" lowerCamelPattern()123 public String lowerCamelPattern() { 124 return lowerCamelPattern(pattern(), pathParameters()); 125 } 126 lowerCamelAdditionalPatterns()127 public List<String> lowerCamelAdditionalPatterns() { 128 return additionalPatterns().stream() 129 .map(a -> lowerCamelPattern(a, pathParameters())) 130 .collect(Collectors.toList()); 131 } 132 lowerCamelPattern(String originalPattern, Set<HttpBinding> pathParameters)133 private static String lowerCamelPattern(String originalPattern, Set<HttpBinding> pathParameters) { 134 String lowerCamelPattern = originalPattern; 135 for (HttpBinding pathParam : pathParameters) { 136 lowerCamelPattern = 137 lowerCamelPattern.replaceAll( 138 "\\{" + pathParam.name(), "{" + JavaStyle.toLowerCamelCase(pathParam.name())); 139 } 140 return lowerCamelPattern; 141 } 142 getPathParametersValuePatterns()143 public Map<String, String> getPathParametersValuePatterns() { 144 Map<String, String> valuePatterns = new LinkedHashMap<>(); 145 for (HttpBinding pathParameter : pathParameters()) { 146 valuePatterns.put(pathParameter.lowerCamelName(), pathParameter.valuePattern()); 147 } 148 return valuePatterns; 149 } 150 151 @AutoValue.Builder 152 public abstract static class Builder { setHttpVerb(HttpVerb httpVerb)153 public abstract HttpBindings.Builder setHttpVerb(HttpVerb httpVerb); 154 setPattern(String pattern)155 public abstract HttpBindings.Builder setPattern(String pattern); 156 setAdditionalPatterns(List<String> additionalPatterns)157 public abstract HttpBindings.Builder setAdditionalPatterns(List<String> additionalPatterns); 158 pattern()159 abstract String pattern(); 160 setPathParameters(Set<HttpBinding> pathParameters)161 public abstract HttpBindings.Builder setPathParameters(Set<HttpBinding> pathParameters); 162 setQueryParameters(Set<HttpBinding> queryParameters)163 public abstract HttpBindings.Builder setQueryParameters(Set<HttpBinding> queryParameters); 164 setBodyParameters(Set<HttpBinding> bodyParameters)165 public abstract HttpBindings.Builder setBodyParameters(Set<HttpBinding> bodyParameters); 166 setIsAsteriskBody(boolean asteriskBody)167 public abstract HttpBindings.Builder setIsAsteriskBody(boolean asteriskBody); 168 autoBuild()169 public abstract HttpBindings autoBuild(); 170 build()171 public HttpBindings build() { 172 if ("".equals(pattern())) { 173 throw new IllegalArgumentException("pattern cannot be empty"); 174 } 175 return autoBuild(); 176 } 177 } 178 } 179