1 // Copyright 2020 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.composer.comment; 16 17 import com.google.api.generator.engine.ast.CommentStatement; 18 import com.google.api.generator.engine.ast.JavaDocComment; 19 import com.google.api.generator.engine.ast.TypeNode; 20 import com.google.api.generator.gapic.utils.JavaStyle; 21 import com.google.common.base.Preconditions; 22 import java.util.Arrays; 23 import java.util.List; 24 import java.util.Optional; 25 import java.util.stream.Collectors; 26 27 public class SettingsCommentComposer { 28 private static final String COLON = ":"; 29 30 private static final String BUILDER_CLASS_DOC_PATTERN = "Builder for %s."; 31 private static final String CALL_SETTINGS_METHOD_DOC_PATTERN = 32 "Returns the object with the settings used for calls to %s."; 33 private static final String CALL_SETTINGS_BUILDER_METHOD_DOC_PATTERN = 34 "Returns the builder for the settings used for calls to %s."; 35 36 // Class header patterns. 37 private static final String CLASS_HEADER_SUMMARY_PATTERN = 38 "Settings class to configure an instance of {@link %s}."; 39 private static final String CLASS_HEADER_DEFAULT_ADDRESS_PORT_PATTERN = 40 "The default service address (%s) and default port (%d) are used."; 41 private static final String CLASS_HEADER_SAMPLE_CODE_PATTERN = 42 "For example, to set the total timeout of %s to 30 seconds:"; 43 44 private static final String CLASS_HEADER_BUILDER_DESCRIPTION = 45 "The builder of this class is recursive, so contained classes are themselves builders. When" 46 + " build() is called, the tree of builders is called to create the complete settings" 47 + " object."; 48 private static final String CLASS_HEADER_DEFAULTS_DESCRIPTION = 49 "The default instance has everything set to sensible defaults:"; 50 private static final String CLASS_HEADER_DEFAULTS_CREDENTIALS_DESCRIPTION = 51 "Credentials are acquired automatically through Application Default Credentials."; 52 private static final String CLASS_HEADER_DEFAULTS_RETRIES_DESCRIPTION = 53 "Retries are configured for idempotent methods but not for non-idempotent methods."; 54 55 public static final CommentStatement DEFAULT_SCOPES_COMMENT = 56 toSimpleComment("The default scopes of the service."); 57 58 public static final CommentStatement DEFAULT_EXECUTOR_PROVIDER_BUILDER_METHOD_COMMENT = 59 toSimpleComment("Returns a builder for the default ExecutorProvider for this service."); 60 public static final CommentStatement DEFAULT_SERVICE_ENDPOINT_METHOD_COMMENT = 61 toSimpleComment("Returns the default service endpoint."); 62 public static final CommentStatement DEFAULT_SERVICE_MTLS_ENDPOINT_METHOD_COMMENT = 63 toSimpleComment("Returns the default mTLS service endpoint."); 64 public static final CommentStatement DEFAULT_SERVICE_SCOPES_METHOD_COMMENT = 65 toSimpleComment("Returns the default service scopes."); 66 67 public static final CommentStatement DEFAULT_CREDENTIALS_PROVIDER_BUILDER_METHOD_COMMENT = 68 toSimpleComment("Returns a builder for the default credentials for this service."); 69 70 public static final CommentStatement DEFAULT_TRANSPORT_PROVIDER_BUILDER_METHOD_COMMENT = 71 toSimpleComment("Returns a builder for the default ChannelProvider for this service."); 72 73 public static final CommentStatement NEW_BUILDER_METHOD_COMMENT = 74 toSimpleComment("Returns a new builder for this class."); 75 76 public static final CommentStatement TO_BUILDER_METHOD_COMMENT = 77 toSimpleComment("Returns a builder containing all the values of this settings class."); 78 79 public static final List<CommentStatement> APPLY_TO_ALL_UNARY_METHODS_METHOD_COMMENTS = 80 Arrays.asList( 81 JavaDocComment.builder() 82 .addComment( 83 "Applies the given settings updater function to all of the unary API methods" 84 + " in this service.") 85 .addParagraph( 86 "Note: This method does not support applying settings to streaming methods.") 87 .build()) 88 .stream() 89 .map(c -> CommentStatement.withComment(c)) 90 .collect(Collectors.toList()); 91 92 private final CommentStatement newTransportBuilderMethodComment; 93 private final CommentStatement transportProviderBuilderMethodComment; 94 SettingsCommentComposer(String transportPrefix)95 public SettingsCommentComposer(String transportPrefix) { 96 this.newTransportBuilderMethodComment = 97 toSimpleComment(String.format("Returns a new %s builder for this class.", transportPrefix)); 98 this.transportProviderBuilderMethodComment = 99 toSimpleComment( 100 String.format( 101 "Returns a builder for the default %s ChannelProvider for this service.", 102 transportPrefix)); 103 } 104 getNewTransportBuilderMethodComment()105 public CommentStatement getNewTransportBuilderMethodComment() { 106 return newTransportBuilderMethodComment; 107 } 108 getTransportProviderBuilderMethodComment()109 public CommentStatement getTransportProviderBuilderMethodComment() { 110 return transportProviderBuilderMethodComment; 111 } 112 createCallSettingsGetterComment( String javaMethodName, boolean isMethodDeprecated)113 public static CommentStatement createCallSettingsGetterComment( 114 String javaMethodName, boolean isMethodDeprecated) { 115 String methodComment = String.format(CALL_SETTINGS_METHOD_DOC_PATTERN, javaMethodName); 116 return isMethodDeprecated 117 ? toDeprecatedSimpleComment(methodComment) 118 : toSimpleComment(methodComment); 119 } 120 createBuilderClassComment(String outerClassName)121 public static CommentStatement createBuilderClassComment(String outerClassName) { 122 return toSimpleComment(String.format(BUILDER_CLASS_DOC_PATTERN, outerClassName)); 123 } 124 createCallSettingsBuilderGetterComment( String javaMethodName, boolean isMethodDeprecated)125 public static CommentStatement createCallSettingsBuilderGetterComment( 126 String javaMethodName, boolean isMethodDeprecated) { 127 String methodComment = String.format(CALL_SETTINGS_BUILDER_METHOD_DOC_PATTERN, javaMethodName); 128 return isMethodDeprecated 129 ? toDeprecatedSimpleComment(methodComment) 130 : toSimpleComment(methodComment); 131 } 132 createClassHeaderComments( String configuredClassName, String defaultHost, boolean isDeprecated, Optional<String> methodNameOpt, Optional<String> sampleCodeOpt, TypeNode classType)133 public static List<CommentStatement> createClassHeaderComments( 134 String configuredClassName, 135 String defaultHost, 136 boolean isDeprecated, 137 Optional<String> methodNameOpt, 138 Optional<String> sampleCodeOpt, 139 TypeNode classType) { 140 // Split default address and port. 141 int colonIndex = defaultHost.indexOf(COLON); 142 Preconditions.checkState( 143 colonIndex > 0 && colonIndex < defaultHost.length() - 1, 144 String.format( 145 "No valid address and port found for %s, expected a string formatted like" 146 + " localhost:8888", 147 defaultHost)); 148 String defaultAddress = defaultHost.substring(0, colonIndex); 149 int defaultPort = Integer.parseInt(defaultHost.substring(colonIndex + 1)); 150 151 JavaDocComment.Builder javaDocCommentBuilder = 152 JavaDocComment.builder() 153 .addUnescapedComment(String.format(CLASS_HEADER_SUMMARY_PATTERN, configuredClassName)) 154 .addParagraph(CLASS_HEADER_DEFAULTS_DESCRIPTION) 155 .addUnorderedList( 156 Arrays.asList( 157 String.format( 158 CLASS_HEADER_DEFAULT_ADDRESS_PORT_PATTERN, defaultAddress, defaultPort), 159 CLASS_HEADER_DEFAULTS_CREDENTIALS_DESCRIPTION, 160 CLASS_HEADER_DEFAULTS_RETRIES_DESCRIPTION)) 161 .addParagraph(CLASS_HEADER_BUILDER_DESCRIPTION); 162 163 if (methodNameOpt.isPresent() && sampleCodeOpt.isPresent()) { 164 javaDocCommentBuilder = 165 javaDocCommentBuilder 166 .addParagraph( 167 String.format( 168 CLASS_HEADER_SAMPLE_CODE_PATTERN, 169 JavaStyle.toLowerCamelCase(methodNameOpt.get()))) 170 .addSampleCode(sampleCodeOpt.get()); 171 } 172 173 if (isDeprecated) { 174 javaDocCommentBuilder.setDeprecated(CommentComposer.DEPRECATED_CLASS_STRING); 175 } 176 177 return Arrays.asList( 178 CommentComposer.AUTO_GENERATED_CLASS_COMMENT, 179 CommentStatement.withComment(javaDocCommentBuilder.build())); 180 } 181 toSimpleComment(String comment)182 private static CommentStatement toSimpleComment(String comment) { 183 return CommentStatement.withComment(JavaDocComment.withComment(comment)); 184 } 185 toDeprecatedSimpleComment(String comment)186 private static CommentStatement toDeprecatedSimpleComment(String comment) { 187 return CommentStatement.withComment( 188 JavaDocComment.builder() 189 .addComment(comment) 190 .setDeprecated(CommentComposer.DEPRECATED_METHOD_STRING) 191 .build()); 192 } 193 } 194