From 8c579b2cb93b67edc218f5b315cad6716285bb5b Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 19 Jul 2016 12:37:35 -0700 Subject: [PATCH 01/26] Refactoring PHP generation to use the MVVM pattern This was prototyped in https://github.com/googleapis/toolkit/pull/268 for both Java and PHP; the present PR only includes PHP and shared stuff. The MVVM pattern uses the following steps: 1. The Model is converted to a ViewModel, which is a set of classes containing the data to be used when rendering the templates. 2. The snippet engine renders the output using only data from the ViewModel structure. Other changes with the MVVM model: * There is no context object when generating under the MVVM model. All data must be prepared beforehand. * No casing changes are done in templates; all identifiers must be composed and cased correctly inside the view model. There are a number of new utility classes created: * Name: represents an identifier name which is casing-aware. * TypeName: Represents a simple or complex type and keeps track of the aliases for the contributing types. * TypeTable: manages the imports for a set of fully-qualified type names. * SurfaceNamer: provides language-specific names or other strings. There is also a change unrelated to MVVM: * Using TreeSet for auth scopes to give a consistent ordering --- .../com/google/api/codegen/ServiceConfig.java | 4 +- .../google/api/codegen/ServiceMessages.java | 4 + .../gapic/MainGapicProviderFactory.java | 22 +- .../codegen/gapic/ViewModelGapicProvider.java | 121 +++ .../api/codegen/metacode/FieldSetting.java | 7 +- .../codegen/metacode/InitCodeGenerator.java | 21 +- .../api/codegen/metacode/InitCodeLine.java | 4 +- .../codegen/metacode/ListInitCodeLine.java | 7 +- .../api/codegen/metacode/MapInitCodeLine.java | 11 +- .../codegen/metacode/SimpleInitCodeLine.java | 5 +- .../metacode/StructureInitCodeLine.java | 5 +- .../google/api/codegen/php/PhpContext.java | 4 +- .../api/codegen/php/PhpContextCommon.java | 80 -- .../api/codegen/php/PhpDiscoveryContext.java | 11 +- .../google/api/codegen/php/PhpDocConfig.java | 67 -- .../api/codegen/php/PhpGapicContext.java | 362 --------- .../api/codegen/php/PhpSnippetSetRunner.java | 7 +- .../rendering/CommonSnippetSetRunner.java | 48 ++ .../transformer/ApiMethodTransformer.java | 260 +++++++ .../transformer/InitCodeTransformer.java | 232 ++++++ .../transformer/MethodTransformerContext.java | 66 ++ .../transformer/ModelToViewTransformer.java | 31 + .../codegen/transformer/ModelTypeTable.java | 95 +++ .../transformer/PageStreamingTransformer.java | 54 ++ .../transformer/PathTemplateTransformer.java | 107 +++ .../api/codegen/transformer/SurfaceNamer.java | 159 ++++ .../SurfaceTransformerContext.java | 74 ++ .../php/PhpGapicSurfaceTransformer.java | 166 ++++ .../transformer/php/PhpModelTypeTable.java | 239 ++++++ .../transformer/php/PhpSurfaceNamer.java | 89 +++ .../api/codegen/util/CommonRenderingUtil.java | 35 + .../com/google/api/codegen/util/Name.java | 204 +++++ .../api/codegen/util/NameFormatter.java | 66 ++ .../com/google/api/codegen/util/NamePath.java | 80 ++ .../google/api/codegen/util/TypeAlias.java | 58 ++ .../com/google/api/codegen/util/TypeName.java | 106 +++ .../google/api/codegen/util/TypeTable.java | 27 + .../google/api/codegen/util/ViewNamer.java | 75 ++ .../codegen/util/php/PhpNameFormatter.java | 65 ++ .../api/codegen/util/php/PhpTypeTable.java | 168 ++++ .../codegen/viewmodel/ApiMethodDocView.java | 51 ++ .../api/codegen/viewmodel/ApiMethodType.java | 29 + .../api/codegen/viewmodel/ApiMethodView.java | 17 + .../DynamicDefaultableParamView.java | 37 + .../codegen/viewmodel/DynamicXApiView.java | 122 +++ .../codegen/viewmodel/FieldSettingView.java | 39 + .../viewmodel/FormatResourceFunctionView.java | 52 ++ .../viewmodel/FormattedInitValueView.java | 47 ++ .../codegen/viewmodel/InitCodeLineView.java | 17 + .../api/codegen/viewmodel/InitCodeView.java | 40 + .../api/codegen/viewmodel/InitValueView.java | 17 + .../viewmodel/ListInitCodeLineView.java | 50 ++ .../api/codegen/viewmodel/MapEntryView.java | 37 + .../viewmodel/MapInitCodeLineView.java | 52 ++ .../codegen/viewmodel/MapParamDocView.java | 55 ++ .../viewmodel/OptionalArrayMethodView.java | 84 ++ .../PageStreamingDescriptorView.java | 49 ++ .../api/codegen/viewmodel/ParamDocView.java | 17 + .../api/codegen/viewmodel/ParamView.java | 17 + .../viewmodel/ParseResourceFunctionView.java | 53 ++ .../PathTemplateGetterFunctionView.java | 42 + .../codegen/viewmodel/PathTemplateView.java | 37 + .../viewmodel/RequestObjectParamView.java | 53 ++ .../viewmodel/ResourceIdParamView.java | 37 + .../api/codegen/viewmodel/ServiceDocView.java | 47 ++ .../viewmodel/SimpleInitCodeLineView.java | 47 ++ .../viewmodel/SimpleInitValueView.java | 38 + .../codegen/viewmodel/SimpleParamDocView.java | 51 ++ .../viewmodel/StructureInitCodeLineView.java | 52 ++ .../api/codegen/viewmodel/ViewModel.java | 28 + .../api/codegen/java/method_sample.snip | 10 +- .../com/google/api/codegen/php/main.snip | 724 ++++++++---------- .../google/api/codegen/php/method_sample.snip | 191 ++--- .../google/api/codegen/php/mvvm_common.snip | 6 + .../google/api/codegen/py/method_sample.snip | 6 +- .../api/codegen/PhpCodeGeneratorTest.java | 2 +- .../testdata/csharp_wrapper_library.baseline | 4 +- .../codegen/testdata/go_main_library.baseline | 2 +- .../testdata/java_settings_library.baseline | 2 +- .../testdata/nodejs_main_library.baseline | 4 +- .../testdata/php_main_library.baseline | 185 ++--- .../testdata/python_main_library.baseline | 2 +- .../testdata/ruby_main_library.baseline | 4 +- .../google/api/codegen/util/NamePathTest.java | 40 + .../com/google/api/codegen/util/NameTest.java | 87 +++ .../google/api/codegen/util/TypeNameTest.java | 64 ++ 86 files changed, 4687 insertions(+), 1206 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java delete mode 100644 src/main/java/com/google/api/codegen/php/PhpContextCommon.java delete mode 100644 src/main/java/com/google/api/codegen/php/PhpDocConfig.java delete mode 100644 src/main/java/com/google/api/codegen/php/PhpGapicContext.java create mode 100644 src/main/java/com/google/api/codegen/rendering/CommonSnippetSetRunner.java create mode 100644 src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/MethodTransformerContext.java create mode 100644 src/main/java/com/google/api/codegen/transformer/ModelToViewTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java create mode 100644 src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/PathTemplateTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/SurfaceTransformerContext.java create mode 100644 src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java create mode 100644 src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java create mode 100644 src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java create mode 100644 src/main/java/com/google/api/codegen/util/Name.java create mode 100644 src/main/java/com/google/api/codegen/util/NameFormatter.java create mode 100644 src/main/java/com/google/api/codegen/util/NamePath.java create mode 100644 src/main/java/com/google/api/codegen/util/TypeAlias.java create mode 100644 src/main/java/com/google/api/codegen/util/TypeName.java create mode 100644 src/main/java/com/google/api/codegen/util/TypeTable.java create mode 100644 src/main/java/com/google/api/codegen/util/ViewNamer.java create mode 100644 src/main/java/com/google/api/codegen/util/php/PhpNameFormatter.java create mode 100644 src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ApiMethodDocView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ApiMethodType.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ApiMethodView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/FormattedInitValueView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/InitCodeLineView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/InitValueView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/MapEntryView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/MapInitCodeLineView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/MapParamDocView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/OptionalArrayMethodView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ParamDocView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ParamView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ParseResourceFunctionView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/PathTemplateGetterFunctionView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/PathTemplateView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ResourceIdParamView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/SimpleInitCodeLineView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/SimpleInitValueView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/SimpleParamDocView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/StructureInitCodeLineView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ViewModel.java create mode 100644 src/main/resources/com/google/api/codegen/php/mvvm_common.snip create mode 100644 src/test/java/com/google/api/codegen/util/NamePathTest.java create mode 100644 src/test/java/com/google/api/codegen/util/NameTest.java create mode 100644 src/test/java/com/google/api/codegen/util/TypeNameTest.java diff --git a/src/main/java/com/google/api/codegen/ServiceConfig.java b/src/main/java/com/google/api/codegen/ServiceConfig.java index 1f27fefc7a..5cbb3407eb 100644 --- a/src/main/java/com/google/api/codegen/ServiceConfig.java +++ b/src/main/java/com/google/api/codegen/ServiceConfig.java @@ -20,9 +20,9 @@ import com.google.api.tools.framework.model.Interface; import java.util.Arrays; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.TreeSet; /** * Utility class that provides service configuration data from an Interface. @@ -50,7 +50,7 @@ public String getTitle(Interface service) { * Return a list of scopes for authentication. */ public Iterable getAuthScopes(Interface service) { - Set result = new HashSet<>(); + Set result = new TreeSet<>(); Service config = service.getModel().getServiceConfig(); Authentication auth = config.getAuthentication(); for (AuthenticationRule rule : auth.getRulesList()) { diff --git a/src/main/java/com/google/api/codegen/ServiceMessages.java b/src/main/java/com/google/api/codegen/ServiceMessages.java index 75f85d5b13..e76d1b4e05 100644 --- a/src/main/java/com/google/api/codegen/ServiceMessages.java +++ b/src/main/java/com/google/api/codegen/ServiceMessages.java @@ -33,6 +33,10 @@ public class ServiceMessages { * Returns true if the message is the empty message. */ public boolean isEmptyType(TypeRef type) { + return s_isEmptyType(type); + } + + public static boolean s_isEmptyType(TypeRef type) { return type.isMessage() && type.getMessageType().getFullName().equals(Empty.getDescriptor().getFullName()); } diff --git a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java index a043e48358..d8e005de70 100644 --- a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java +++ b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java @@ -15,11 +15,11 @@ package com.google.api.codegen.gapic; import com.google.api.codegen.ApiConfig; -import com.google.api.codegen.clientconfig.ClientConfigGapicContext; import com.google.api.codegen.InterfaceListView; import com.google.api.codegen.InterfaceView; import com.google.api.codegen.ProtoFileView; import com.google.api.codegen.SnippetSetRunner; +import com.google.api.codegen.clientconfig.ClientConfigGapicContext; import com.google.api.codegen.clientconfig.ClientConfigSnippetSetRunner; import com.google.api.codegen.csharp.CSharpCodePathMapper; import com.google.api.codegen.csharp.CSharpGapicContext; @@ -31,23 +31,24 @@ import com.google.api.codegen.java.JavaSnippetSetRunner; import com.google.api.codegen.nodejs.NodeJSGapicContext; import com.google.api.codegen.nodejs.NodeJSSnippetSetRunner; -import com.google.api.codegen.php.PhpGapicContext; -import com.google.api.codegen.php.PhpSnippetSetRunner; import com.google.api.codegen.py.PythonGapicContext; import com.google.api.codegen.py.PythonInterfaceInitializer; import com.google.api.codegen.py.PythonProtoFileInitializer; import com.google.api.codegen.py.PythonSnippetSetRunner; +import com.google.api.codegen.rendering.CommonSnippetSetRunner; import com.google.api.codegen.ruby.RubyGapicContext; import com.google.api.codegen.ruby.RubySnippetSetRunner; +import com.google.api.codegen.transformer.php.PhpGapicSurfaceTransformer; +import com.google.api.codegen.util.CommonRenderingUtil; import com.google.api.tools.framework.model.Interface; import com.google.api.tools.framework.model.Model; import com.google.api.tools.framework.model.ProtoFile; -import org.apache.commons.lang3.NotImplementedException; - import java.util.Arrays; import java.util.List; +import org.apache.commons.lang3.NotImplementedException; + /** * MainGapicProviderFactory creates GapicProvider instances based on an id. */ @@ -173,14 +174,11 @@ public static List> defaultCreate( GapicCodePathMapper phpPathMapper = CommonGapicCodePathMapper.newBuilder().setPrefix("src").build(); GapicProvider provider = - CommonGapicProvider.newBuilder() + ViewModelGapicProvider.newBuilder() .setModel(model) - .setView(new InterfaceView()) - .setContext(new PhpGapicContext(model, apiConfig)) - .setSnippetSetRunner( - new PhpSnippetSetRunner(SnippetSetRunner.SNIPPET_RESOURCE_ROOT)) - .setSnippetFileNames(Arrays.asList("php/main.snip")) - .setCodePathMapper(phpPathMapper) + .setApiConfig(apiConfig) + .setSnippetSetRunner(new CommonSnippetSetRunner(new CommonRenderingUtil())) + .setModelToViewTransformer(new PhpGapicSurfaceTransformer(apiConfig, phpPathMapper)) .build(); GapicCodePathMapper phpClientConfigPathMapper = diff --git a/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java b/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java new file mode 100644 index 0000000000..461feb669d --- /dev/null +++ b/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java @@ -0,0 +1,121 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.gapic; + +import com.google.api.codegen.ApiConfig; +import com.google.api.codegen.rendering.CommonSnippetSetRunner; +import com.google.api.codegen.transformer.ModelToViewTransformer; +import com.google.api.codegen.viewmodel.ViewModel; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Model; +import com.google.api.tools.framework.model.stages.Merged; +import com.google.api.tools.framework.snippet.Doc; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class ViewModelGapicProvider implements GapicProvider { + private final Model model; + private final ApiConfig apiConfig; + private final CommonSnippetSetRunner snippetSetRunner; + private final ModelToViewTransformer modelToViewTransformer; + + private ViewModelGapicProvider( + Model model, + ApiConfig apiConfig, + CommonSnippetSetRunner snippetSetRunner, + ModelToViewTransformer modelToViewTransformer) { + this.model = model; + this.apiConfig = apiConfig; + this.snippetSetRunner = snippetSetRunner; + this.modelToViewTransformer = modelToViewTransformer; + } + + @Override + public List getSnippetFileNames() { + return modelToViewTransformer.getTemplateFileNames(); + } + + @Override + public Map generate() { + return generate(null); + } + + @Override + public Map generate(String snippetFileName) { + // Establish required stage for generation. + model.establishStage(Merged.KEY); + if (model.getDiagCollector().getErrorCount() > 0) { + return null; + } + + List surfaceDocs = modelToViewTransformer.transform(model, apiConfig); + if (model.getDiagCollector().getErrorCount() > 0) { + return null; + } + + Map docs = new TreeMap<>(); + for (ViewModel surfaceDoc : surfaceDocs) { + if (snippetFileName != null && !surfaceDoc.templateFileName().equals(snippetFileName)) { + continue; + } + Doc doc = snippetSetRunner.generate(surfaceDoc); + if (doc == null) { + continue; + } + docs.put(surfaceDoc.outputPath(), doc); + } + + return docs; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + private Model model; + private ApiConfig apiConfig; + private CommonSnippetSetRunner snippetSetRunner; + private ModelToViewTransformer modelToViewTransformer; + + private Builder() {} + + public Builder setModel(Model model) { + this.model = model; + return this; + } + + public Builder setApiConfig(ApiConfig apiConfig) { + this.apiConfig = apiConfig; + return this; + } + + public Builder setSnippetSetRunner(CommonSnippetSetRunner snippetSetRunner) { + this.snippetSetRunner = snippetSetRunner; + return this; + } + + public Builder setModelToViewTransformer(ModelToViewTransformer modelToViewTransformer) { + this.modelToViewTransformer = modelToViewTransformer; + return this; + } + + public ViewModelGapicProvider build() { + return new ViewModelGapicProvider(model, apiConfig, snippetSetRunner, modelToViewTransformer); + } + } +} diff --git a/src/main/java/com/google/api/codegen/metacode/FieldSetting.java b/src/main/java/com/google/api/codegen/metacode/FieldSetting.java index 156b83b59a..0a91099091 100644 --- a/src/main/java/com/google/api/codegen/metacode/FieldSetting.java +++ b/src/main/java/com/google/api/codegen/metacode/FieldSetting.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; import com.google.api.tools.framework.model.TypeRef; import com.google.auto.value.AutoValue; @@ -25,7 +26,7 @@ public abstract class FieldSetting { public static FieldSetting create( - TypeRef type, String fieldName, String identifier, InitValueConfig initValueConfig) { + TypeRef type, Name fieldName, Name identifier, InitValueConfig initValueConfig) { return new AutoValue_FieldSetting(type, fieldName, identifier, initValueConfig); } @@ -37,12 +38,12 @@ public static FieldSetting create( /** * Returns the name of the field in the containing structure. */ - public abstract String getFieldName(); + public abstract Name getFieldName(); /** * Returns the name of the identifier being set on the field. */ - public abstract String getIdentifier(); + public abstract Name getIdentifier(); /** * Returns the InitValueConfig for the original identifier. diff --git a/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java b/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java index 9acee0ecb8..52fd906f63 100644 --- a/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java +++ b/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.Method; import com.google.api.tools.framework.model.TypeRef; @@ -49,7 +50,7 @@ public InitCode generateRequestObjectInitCode( FieldSetting requestField = FieldSetting.create( method.getInputType(), - "request", + Name.from("request"), lastLine.getIdentifier(), lastLine.getInitValueConfig()); List outputFields = Arrays.asList(requestField); @@ -82,14 +83,14 @@ public InitCode generateRequestFieldInitCode( return InitCode.create(initLineSpecs, requestInitCodeLine.getFieldSettings()); } - private String getNewSymbol(String desiredName) { + private Name getNewSymbol(String desiredName) { String actualName = desiredName; int i = 2; while (symbolTable.contains(actualName)) { actualName = desiredName + i; } symbolTable.add(actualName); - return actualName; + return Name.from(actualName); } private InitCodeLine generateSampleCodeInitStructure( @@ -108,7 +109,7 @@ private InitCodeLine generateSampleCodeInitStructure( FieldSetting fieldSetting = FieldSetting.create( field.getType(), - field.getSimpleName(), + Name.from(field.getSimpleName()), subFieldInit.getIdentifier(), subFieldInit.getInitValueConfig()); fieldSettings.add(fieldSetting); @@ -119,13 +120,13 @@ private InitCodeLine generateSampleCodeInitStructure( // get a new symbol for this object after subfields, in order to preserve // numerical ordering in the case of conflicts - String identifier = getNewSymbol(suggestedName); + Name identifier = getNewSymbol(suggestedName); return StructureInitCodeLine.create(typeRef, identifier, fieldSettings); } private InitCodeLine generateSampleCodeInitList( String suggestedName, TypeRef typeRef, List thisFieldInitList) { - List elementIdentifiers = new ArrayList<>(); + List elementIdentifiers = new ArrayList<>(); for (Object elementInitStructure : thisFieldInitList) { String suggestedElementName = suggestedName + "_element"; // Using the Optional cardinality replaces the Repeated cardinality @@ -139,7 +140,7 @@ private InitCodeLine generateSampleCodeInitList( // get a new symbol for this object after elements, in order to preserve // numerical ordering in the case of conflicts - String identifier = getNewSymbol(suggestedName); + Name identifier = getNewSymbol(suggestedName); return ListInitCodeLine.create(typeRef, identifier, elementIdentifiers); } @@ -147,7 +148,7 @@ private InitCodeLine generateSampleCodeInitMap( String suggestedName, TypeRef typeRef, Map thisFieldInitMap) { TypeRef keyTypeRef = typeRef.getMapKeyField().getType(); TypeRef elementType = typeRef.getMapValueField().getType(); - Map elementIdentifierMap = new HashMap(); + Map elementIdentifierMap = new HashMap<>(); for (String keyString : thisFieldInitMap.keySet()) { String validatedKeyString = validateValue(keyTypeRef, keyString); if (validatedKeyString == null) { @@ -173,7 +174,7 @@ private InitCodeLine generateSampleCodeInitMap( // get a new symbol for this object after elements, in order to preserve // numerical ordering in the case of conflicts - String identifier = getNewSymbol(suggestedName); + Name identifier = getNewSymbol(suggestedName); return MapInitCodeLine.create( keyTypeRef, elementType, typeRef, identifier, elementIdentifierMap); } @@ -185,7 +186,7 @@ private InitCodeLine generateSampleCodeInit( // generate the zero value for the type. if (initFieldStructure instanceof InitValueConfig) { InitValueConfig initValueConfig = (InitValueConfig) initFieldStructure; - String identifier = getNewSymbol(suggestedName); + Name identifier = getNewSymbol(suggestedName); if (initValueConfig.hasInitialValue()) { String validatedValue = validateValue(typeRef, initValueConfig.getInitialValue()); if (validatedValue == null) { diff --git a/src/main/java/com/google/api/codegen/metacode/InitCodeLine.java b/src/main/java/com/google/api/codegen/metacode/InitCodeLine.java index da72215e0c..07229b888a 100644 --- a/src/main/java/com/google/api/codegen/metacode/InitCodeLine.java +++ b/src/main/java/com/google/api/codegen/metacode/InitCodeLine.java @@ -14,11 +14,13 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; + /** * InitCodeLine represents the creation of a variable with an initialized value. */ public interface InitCodeLine { - public String getIdentifier(); + public Name getIdentifier(); public InitValueConfig getInitValueConfig(); diff --git a/src/main/java/com/google/api/codegen/metacode/ListInitCodeLine.java b/src/main/java/com/google/api/codegen/metacode/ListInitCodeLine.java index 6db93c38b3..69d27b5445 100644 --- a/src/main/java/com/google/api/codegen/metacode/ListInitCodeLine.java +++ b/src/main/java/com/google/api/codegen/metacode/ListInitCodeLine.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; import com.google.api.tools.framework.model.TypeRef; import com.google.auto.value.AutoValue; @@ -27,16 +28,16 @@ public abstract class ListInitCodeLine implements InitCodeLine { public static ListInitCodeLine create( - TypeRef elementType, String identifier, List elementIdentifiers) { + TypeRef elementType, Name identifier, List elementIdentifiers) { return new AutoValue_ListInitCodeLine(elementType, identifier, elementIdentifiers); } public abstract TypeRef getElementType(); @Override - public abstract String getIdentifier(); + public abstract Name getIdentifier(); - public abstract List getElementIdentifiers(); + public abstract List getElementIdentifiers(); @Override public InitCodeLineType getLineType() { diff --git a/src/main/java/com/google/api/codegen/metacode/MapInitCodeLine.java b/src/main/java/com/google/api/codegen/metacode/MapInitCodeLine.java index 338c989001..6083e2de5a 100644 --- a/src/main/java/com/google/api/codegen/metacode/MapInitCodeLine.java +++ b/src/main/java/com/google/api/codegen/metacode/MapInitCodeLine.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; import com.google.api.tools.framework.model.TypeRef; import com.google.auto.value.AutoValue; @@ -30,8 +31,8 @@ public static MapInitCodeLine create( TypeRef keyType, TypeRef valueType, TypeRef elementType, - String identifier, - Map elementIdentifierMap) { + Name identifier, + Map elementIdentifierMap) { return new AutoValue_MapInitCodeLine( keyType, valueType, elementType, identifier, elementIdentifierMap); } @@ -43,15 +44,15 @@ public static MapInitCodeLine create( public abstract TypeRef getElementType(); @Override - public abstract String getIdentifier(); + public abstract Name getIdentifier(); - public abstract Map getElementIdentifierMap(); + public abstract Map getElementIdentifierMap(); public Iterable getElementIdentifierKeys() { return getElementIdentifierMap().keySet(); } - public String getElementIdentifierValue(String key) { + public Name getElementIdentifierValue(String key) { return getElementIdentifierMap().get(key); } diff --git a/src/main/java/com/google/api/codegen/metacode/SimpleInitCodeLine.java b/src/main/java/com/google/api/codegen/metacode/SimpleInitCodeLine.java index 9a0fa16f0e..562dba9ec9 100644 --- a/src/main/java/com/google/api/codegen/metacode/SimpleInitCodeLine.java +++ b/src/main/java/com/google/api/codegen/metacode/SimpleInitCodeLine.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; import com.google.api.tools.framework.model.TypeRef; import com.google.auto.value.AutoValue; @@ -25,14 +26,14 @@ public abstract class SimpleInitCodeLine implements InitCodeLine { public static SimpleInitCodeLine create( - TypeRef type, String identifier, InitValueConfig initValueConfig) { + TypeRef type, Name identifier, InitValueConfig initValueConfig) { return new AutoValue_SimpleInitCodeLine(type, identifier, initValueConfig); } public abstract TypeRef getType(); @Override - public abstract String getIdentifier(); + public abstract Name getIdentifier(); @Override public abstract InitValueConfig getInitValueConfig(); diff --git a/src/main/java/com/google/api/codegen/metacode/StructureInitCodeLine.java b/src/main/java/com/google/api/codegen/metacode/StructureInitCodeLine.java index 9fda43d0b6..42b1f08f65 100644 --- a/src/main/java/com/google/api/codegen/metacode/StructureInitCodeLine.java +++ b/src/main/java/com/google/api/codegen/metacode/StructureInitCodeLine.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.metacode; +import com.google.api.codegen.util.Name; import com.google.api.tools.framework.model.TypeRef; import com.google.auto.value.AutoValue; @@ -27,14 +28,14 @@ public abstract class StructureInitCodeLine implements InitCodeLine { public static StructureInitCodeLine create( - TypeRef type, String identifier, List fieldSettings) { + TypeRef type, Name identifier, List fieldSettings) { return new AutoValue_StructureInitCodeLine(type, identifier, fieldSettings); } public abstract TypeRef getType(); @Override - public abstract String getIdentifier(); + public abstract Name getIdentifier(); public abstract List getFieldSettings(); diff --git a/src/main/java/com/google/api/codegen/php/PhpContext.java b/src/main/java/com/google/api/codegen/php/PhpContext.java index e9462f4729..ec2bf2266c 100644 --- a/src/main/java/com/google/api/codegen/php/PhpContext.java +++ b/src/main/java/com/google/api/codegen/php/PhpContext.java @@ -14,9 +14,11 @@ */ package com.google.api.codegen.php; +import com.google.api.codegen.util.php.PhpTypeTable; + /** * A PhpContext provides functionality specific to a context in PHP. */ public interface PhpContext { - void resetState(PhpContextCommon phpCommon); + void resetState(PhpTypeTable phpTypeTable); } diff --git a/src/main/java/com/google/api/codegen/php/PhpContextCommon.java b/src/main/java/com/google/api/codegen/php/PhpContextCommon.java deleted file mode 100644 index 1a489182f9..0000000000 --- a/src/main/java/com/google/api/codegen/php/PhpContextCommon.java +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.php; - -import com.google.common.base.Splitter; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class PhpContextCommon { - - /** - * A bi-map from full names to short names indicating the import map. - */ - private final BiMap imports = HashBiMap.create(); - - public String getMinimallyQualifiedName(String fullName, String shortName) { - // Derive a short name if possible - if (imports.containsKey(fullName)) { - // Short name already there. - return imports.get(fullName); - } - if (imports.containsValue(shortName)) { - // Short name clashes, use long name. - return fullName; - } - imports.put(fullName, shortName); - return shortName; - } - - public List getImports() { - // Clean up the imports. - List cleanedImports = new ArrayList<>(); - for (String imported : imports.keySet()) { - cleanedImports.add(imported); - } - Collections.sort(cleanedImports); - return cleanedImports; - } - - public boolean hasImports() { - return !getImports().isEmpty(); - } - - public Iterable getDocLines(String text) { - return getDocLinesWithPrefix(text, ""); - } - - public Iterable getDocLinesWithPrefix(String text, String firstLinePrefix) { - return getDocLinesWithPrefixes(text, firstLinePrefix, ""); - } - - public Iterable getDocLinesWithPrefixes( - String text, String firstLinePrefix, String remainderPrefix) { - // TODO: convert markdown to phpDoc - List result = new ArrayList<>(); - boolean onFirstLine = true; - for (String line : Splitter.on(String.format("%n")).split(text)) { - String linePrefix = onFirstLine ? firstLinePrefix : remainderPrefix; - onFirstLine = false; - result.add(" * " + linePrefix + line); - } - return result; - } -} diff --git a/src/main/java/com/google/api/codegen/php/PhpDiscoveryContext.java b/src/main/java/com/google/api/codegen/php/PhpDiscoveryContext.java index b86e94221f..ba7d179af9 100644 --- a/src/main/java/com/google/api/codegen/php/PhpDiscoveryContext.java +++ b/src/main/java/com/google/api/codegen/php/PhpDiscoveryContext.java @@ -17,6 +17,7 @@ import com.google.api.Service; import com.google.api.codegen.ApiaryConfig; import com.google.api.codegen.DiscoveryContext; +import com.google.api.codegen.util.php.PhpTypeTable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.protobuf.Field; @@ -32,7 +33,7 @@ public class PhpDiscoveryContext extends DiscoveryContext implements PhpContext private static final String GOOGLE_SERVICE_PREFIX = "Google_Service_"; - private PhpContextCommon phpCommon; + private PhpTypeTable phpTypeTable; /** * A map from inferred API package names to renamed counterparts in PHP client libraries. @@ -89,12 +90,12 @@ public PhpDiscoveryContext(Service service, ApiaryConfig apiaryConfig) { } @Override - public void resetState(PhpContextCommon phpCommon) { - this.phpCommon = phpCommon; + public void resetState(PhpTypeTable phpTypeTable) { + this.phpTypeTable = phpTypeTable; } - public PhpContextCommon php() { - return this.phpCommon; + public PhpTypeTable php() { + return this.phpTypeTable; } // Snippet Helpers diff --git a/src/main/java/com/google/api/codegen/php/PhpDocConfig.java b/src/main/java/com/google/api/codegen/php/PhpDocConfig.java deleted file mode 100644 index 1f2732609b..0000000000 --- a/src/main/java/com/google/api/codegen/php/PhpDocConfig.java +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.php; - -import com.google.api.codegen.DocConfig; -import com.google.api.codegen.metacode.InitCode; -import com.google.api.codegen.metacode.InputParameter; -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; - -import javax.annotation.Nullable; - -/** - * Represents the Php documentation settings for an Api method. - */ -@AutoValue -abstract class PhpDocConfig extends DocConfig { - public static PhpDocConfig.Builder newBuilder() { - return new AutoValue_PhpDocConfig.Builder(); - } - - public abstract boolean isPagedVariant(); - - @Override - @Nullable - public abstract ImmutableList getParams(); - - @AutoValue.Builder - abstract static class Builder extends DocConfig.Builder { - - public abstract PhpDocConfig build(); - - public abstract Builder setApiName(String serviceName); - - public abstract Builder setMethodName(String methodName); - - public abstract Builder setPagedVariant(boolean paged); - - public abstract Builder setReturnType(String returnType); - - public abstract Builder setInitCode(InitCode initCode); - - public abstract Builder setParams(ImmutableList params); - - @Override - protected Builder setInitCodeProxy(InitCode initCode) { - return setInitCode(initCode); - } - - @Override - protected Builder setParamsProxy(ImmutableList params) { - return setParams(params); - } - } -} diff --git a/src/main/java/com/google/api/codegen/php/PhpGapicContext.java b/src/main/java/com/google/api/codegen/php/PhpGapicContext.java deleted file mode 100644 index 0e68505ed0..0000000000 --- a/src/main/java/com/google/api/codegen/php/PhpGapicContext.java +++ /dev/null @@ -1,362 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.php; - -import com.google.api.codegen.ApiConfig; -import com.google.api.codegen.GapicContext; -import com.google.api.codegen.metacode.FieldSetting; -import com.google.api.codegen.metacode.InitCode; -import com.google.api.codegen.metacode.InitCodeLine; -import com.google.api.tools.framework.model.Interface; -import com.google.api.tools.framework.model.Method; -import com.google.api.tools.framework.model.Model; -import com.google.api.tools.framework.model.ProtoElement; -import com.google.api.tools.framework.model.ProtoFile; -import com.google.api.tools.framework.model.TypeRef; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; - -/** - * A GapicContext specialized for PHP. - */ -public class PhpGapicContext extends GapicContext implements PhpContext { - /** - * A map from primitive types in proto to PHP counterparts. - */ - private static final ImmutableMap PRIMITIVE_TYPE_MAP = - ImmutableMap.builder() - .put(Type.TYPE_BOOL, "bool") - .put(Type.TYPE_DOUBLE, "float") - .put(Type.TYPE_FLOAT, "float") - .put(Type.TYPE_INT64, "int") - .put(Type.TYPE_UINT64, "int") - .put(Type.TYPE_SINT64, "int") - .put(Type.TYPE_FIXED64, "int") - .put(Type.TYPE_SFIXED64, "int") - .put(Type.TYPE_INT32, "int") - .put(Type.TYPE_UINT32, "int") - .put(Type.TYPE_SINT32, "int") - .put(Type.TYPE_FIXED32, "int") - .put(Type.TYPE_SFIXED32, "int") - .put(Type.TYPE_STRING, "string") - .put(Type.TYPE_BYTES, "string") - .build(); - - /** - * A map from primitive types in proto to zero value in PHP - */ - private static final ImmutableMap PRIMITIVE_ZERO_VALUE = - ImmutableMap.builder() - .put(Type.TYPE_BOOL, "false") - .put(Type.TYPE_DOUBLE, "0.0") - .put(Type.TYPE_FLOAT, "0.0") - .put(Type.TYPE_INT64, "0") - .put(Type.TYPE_UINT64, "0") - .put(Type.TYPE_SINT64, "0") - .put(Type.TYPE_FIXED64, "0") - .put(Type.TYPE_SFIXED64, "0") - .put(Type.TYPE_INT32, "0") - .put(Type.TYPE_UINT32, "0") - .put(Type.TYPE_SINT32, "0") - .put(Type.TYPE_FIXED32, "0") - .put(Type.TYPE_SFIXED32, "0") - .put(Type.TYPE_STRING, "\"\"") - .put(Type.TYPE_BYTES, "\"\"") - .build(); - - private PhpContextCommon phpCommon; - - public PhpGapicContext(Model model, ApiConfig apiConfig) { - super(model, apiConfig); - } - - @Override - public void resetState(PhpContextCommon phpCommon) { - this.phpCommon = phpCommon; - } - - public PhpContextCommon php() { - return phpCommon; - } - - // Snippet Helpers - // =============== - - /** - * Returns the PHP filename which holds the gRPC service definition. - */ - public String getGrpcFilename(Interface service) { - return service.getFile().getProto().getName().replace(".proto", "_services"); - } - - /** - * Returns the name of the gRPC client class. - */ - public String getGrpcClientName(Interface service) { - String fullyQualifiedClientName = service.getFullName().replaceAll("\\.", "\\\\") + "Client"; - return getTypeName(fullyQualifiedClientName); - } - - public String getTypeName(String typeName) { - int lastBackslashIndex = typeName.lastIndexOf('\\'); - if (lastBackslashIndex < 0) { - throw new IllegalArgumentException("expected fully qualified name"); - } - String shortTypeName = typeName.substring(lastBackslashIndex + 1); - return phpCommon.getMinimallyQualifiedName(typeName, shortTypeName); - } - - /** - * Adds the given type name to the import list. Returns an empty string so that the output is not - * affected in snippets. - */ - public String addImport(String typeName) { - // used for its side effect of adding the type to the import list if the short name - // hasn't been imported yet - getTypeName(typeName); - return ""; - } - - /** - * Returns the PHP representation of a reference to a type. - */ - public String typeName(TypeRef type) { - if (type.isMap()) { - return "array"; - } else if (type.isRepeated()) { - return basicTypeName(type) + "[]"; - } else { - return basicTypeName(type); - } - } - - /** - * Returns the PHP representation of a type, without cardinality. If the type is a primitive, - * basicTypeName returns it in unboxed form. - */ - public String basicTypeName(TypeRef type) { - String result = PRIMITIVE_TYPE_MAP.get(type.getKind()); - if (result != null) { - if (result.contains("\\")) { - // Fully qualified type name, use regular type name resolver. Can skip boxing logic - // because those types are already boxed. - return getTypeName(result); - } - return result; - } - switch (type.getKind()) { - case TYPE_MESSAGE: - return getTypeName(type.getMessageType()); - case TYPE_ENUM: - return getTypeName(type.getEnumType()); - default: - throw new IllegalArgumentException("unknown type kind: " + type.getKind()); - } - } - - /** - * Returns the PHP representation of a zero value for that type, to be used in code sample doc. - * - * Parametric types may use the diamond operator, since the return value will be used only in - * initialization. - */ - public String zeroValue(TypeRef type) { - // Don't call getTypeName; we don't need to import these. - if (type.isMap()) { - return "[]"; - } - if (type.isRepeated()) { - return "[]"; - } - if (PRIMITIVE_ZERO_VALUE.containsKey(type.getKind())) { - return PRIMITIVE_ZERO_VALUE.get(type.getKind()); - } - if (type.isMessage()) { - return "new " + typeName(type) + "()"; - } - return "null"; - } - - public String fullyQualifiedName(TypeRef type) { - return type.getMessageType().getFullName().replaceAll("\\.", "\\\\"); - } - - /** - * Gets the full name of the message or enum type in PHP. - */ - public String getTypeName(ProtoElement elem) { - // Construct the fully-qualified PHP class name - int qualifiedPrefixLength = elem.getFile().getFullName().length() + 1; - String shortName = elem.getFullName().substring(qualifiedPrefixLength); - String name = getPhpPackage(elem.getFile()) + "\\" + shortName; - - return phpCommon.getMinimallyQualifiedName(name, shortName); - } - - public String getServiceName(Interface service) { - return service.getFullName(); - } - - /** - * Gets the PHP package for the given proto file. - */ - public String getPhpPackage(ProtoFile file) { - return file.getProto().getPackage().replaceAll("\\.", "\\\\"); - } - - public Method getFirstMethod(Interface service) { - ImmutableList methods = service.getMethods(); - if (methods.size() > 0) { - return methods.get(0); - } - throw new RuntimeException("No methods available."); - } - - public String returnTypeOrEmpty(TypeRef returnType) { - return messages().isEmptyType(returnType) ? "" : typeName(returnType); - } - - public PhpDocConfig.Builder newPhpDocConfigBuilder() { - return PhpDocConfig.newBuilder(); - } - - /** - * Get a Php formatted primitive value, given a primitive type and a string representation of that - * value. The value must be a valid example of that type. Values of type Bool must be either the - * string 'true' or 'false' (other capitalizations are permitted). - */ - public String renderPrimitiveValue(TypeRef type, String value) { - Type primitiveType = type.getKind(); - if (!PRIMITIVE_TYPE_MAP.containsKey(primitiveType)) { - throw new IllegalArgumentException( - "Initial values are only supported for primitive types, got type " - + type - + ", with value " - + value); - } - switch (primitiveType) { - case TYPE_BOOL: - return value.toLowerCase(); - case TYPE_STRING: - case TYPE_BYTES: - return "\"" + value + "\""; - default: - // Types that do not need to be modified (e.g. TYPE_INT32) are handled here - return value; - } - } - - /** - * Determine whether a given InitCodeLine is a method parameter. This is important for map fields - * because flattened map parameters accept an associative array, while map fields on a request - * object must be a sequential array of MapEntry objects. - */ - public boolean initLineIsParameter(InitCode initCode, InitCodeLine initCodeLine) { - for (FieldSetting fieldSetting : initCode.getArgFields()) { - if (initCodeLine.getIdentifier().equals(fieldSetting.getIdentifier())) { - return true; - } - } - return false; - } - - // Constants - // ========= - - /** - * A set of PHP keywords and built-ins. keywords: http://php.net/manual/en/reserved.keywords.php - */ - private static final ImmutableSet KEYWORD_BUILT_IN_SET = - ImmutableSet.builder() - .add( - "__halt_compiler", - "abstract", - "and", - "array", - "as", - "break", - "callable", - "case", - "catch", - "class", - "clone", - "const", - "continue", - "declare", - "default", - "die", - "do", - "echo", - "else", - "elseif", - "empty", - "enddeclare", - "endfor", - "endforeach", - "endif", - "endswitch", - "endwhile", - "eval", - "exit", - "extends", - "final", - "finally", - "for", - "foreach", - "function", - "global", - "goto", - "if", - "implements", - "include", - "include_once", - "instanceof", - "insteadof", - "interface", - "isset", - "list", - "namespace", - "new", - "or", - "print", - "private", - "protected", - "public", - "require", - "require_once", - "return", - "static", - "switch", - "throw", - "trait", - "try", - "unset", - "use", - "var", - "while", - "xor", - "yield", - "__CLASS__", - "__DIR__", - "__FILE__", - "__FUNCTION__", - "__LINE__", - "__METHOD__", - "__NAMESPACE__", - "__TRAIT__") - .build(); -} diff --git a/src/main/java/com/google/api/codegen/php/PhpSnippetSetRunner.java b/src/main/java/com/google/api/codegen/php/PhpSnippetSetRunner.java index 26fdb4ce1c..75fbf9d088 100644 --- a/src/main/java/com/google/api/codegen/php/PhpSnippetSetRunner.java +++ b/src/main/java/com/google/api/codegen/php/PhpSnippetSetRunner.java @@ -17,6 +17,7 @@ import com.google.api.codegen.CodegenContext; import com.google.api.codegen.GeneratedResult; import com.google.api.codegen.SnippetSetRunner; +import com.google.api.codegen.util.php.PhpTypeTable; import com.google.api.tools.framework.snippet.Doc; import com.google.api.tools.framework.snippet.SnippetSet; import com.google.common.collect.ImmutableMap; @@ -48,15 +49,15 @@ public GeneratedResult generate( ImmutableMap.of("context", context)); String outputFilename = snippets.generateFilename(element).prettyPrint(); - PhpContextCommon phpContextCommon = new PhpContextCommon(); + PhpTypeTable phpTypeTable = new PhpTypeTable(); // TODO don't depend on a cast here PhpContext phpContext = (PhpContext) context; - phpContext.resetState(phpContextCommon); + phpContext.resetState(phpTypeTable); Doc body = snippets.generateBody(element); - List cleanedImports = phpContextCommon.getImports(); + List cleanedImports = phpTypeTable.getImports(); Doc result = snippets.generateClass(element, body, cleanedImports); return GeneratedResult.create(result, outputFilename); diff --git a/src/main/java/com/google/api/codegen/rendering/CommonSnippetSetRunner.java b/src/main/java/com/google/api/codegen/rendering/CommonSnippetSetRunner.java new file mode 100644 index 0000000000..4f62f45fbd --- /dev/null +++ b/src/main/java/com/google/api/codegen/rendering/CommonSnippetSetRunner.java @@ -0,0 +1,48 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.rendering; + +import com.google.api.codegen.viewmodel.ViewModel; +import com.google.api.tools.framework.snippet.Doc; +import com.google.api.tools.framework.snippet.SnippetSet; +import com.google.common.collect.ImmutableMap; + +/** + * CommonSnippetSetRunner takes the view model as input and then uses the + * Snippet Set templating engine to generate an output document. + */ +public class CommonSnippetSetRunner { + + private Object utilObject; + + public CommonSnippetSetRunner(Object utilObject) { + this.utilObject = utilObject; + } + + public Doc generate(ViewModel input) { + SurfaceSnippetSet snippets = + SnippetSet.createSnippetInterface( + SurfaceSnippetSet.class, + input.resourceRoot(), + input.templateFileName(), + ImmutableMap.of("util", utilObject)); + + return snippets.generate(input); + } + + private interface SurfaceSnippetSet { + Doc generate(ViewModel input); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java new file mode 100644 index 0000000000..62cd83173f --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -0,0 +1,260 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.ServiceMessages; +import com.google.api.codegen.util.Name; +import com.google.api.codegen.viewmodel.ApiMethodDocView; +import com.google.api.codegen.viewmodel.ApiMethodType; +import com.google.api.codegen.viewmodel.DynamicDefaultableParamView; +import com.google.api.codegen.viewmodel.MapParamDocView; +import com.google.api.codegen.viewmodel.OptionalArrayMethodView; +import com.google.api.codegen.viewmodel.ParamDocView; +import com.google.api.codegen.viewmodel.RequestObjectParamView; +import com.google.api.codegen.viewmodel.SimpleParamDocView; +import com.google.api.tools.framework.model.Field; +import com.google.api.tools.framework.model.TypeRef; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * ApiMethodTransformer generates view objects from method definitions. + */ +public class ApiMethodTransformer { + private InitCodeTransformer initCodeTransformer; + + public ApiMethodTransformer() { + this.initCodeTransformer = new InitCodeTransformer(); + } + + public OptionalArrayMethodView generateOptionalArrayMethod(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + OptionalArrayMethodView.Builder apiMethod = OptionalArrayMethodView.newBuilder(); + + if (context.getMethodConfig().isPageStreaming()) { + apiMethod.type(ApiMethodType.PagedOptionalArrayMethod); + } else { + apiMethod.type(ApiMethodType.OptionalArrayMethod); + } + apiMethod.apiClassName(namer.getApiWrapperClassName(context.getInterface())); + apiMethod.apiVariableName(namer.getApiWrapperVariableName(context.getInterface())); + apiMethod.initCode( + initCodeTransformer.generateInitCode( + context, context.getMethodConfig().getRequiredFields())); + + ApiMethodDocView.Builder docBuilder = ApiMethodDocView.newBuilder(); + + docBuilder.mainDocLines(namer.getDocLines(context.getMethod())); + List paramDocs = + getMethodParamDocs(context, context.getMethodConfig().getRequiredFields()); + paramDocs.add(getOptionalArrayParamDoc(context, context.getMethodConfig().getOptionalFields())); + paramDocs.add(getCallSettingsParamDoc(context)); + docBuilder.paramDocs(paramDocs); + docBuilder.returnTypeName( + namer.getDynamicReturnTypeName( + context.getTypeTable(), context.getMethod(), context.getMethodConfig())); + docBuilder.throwsDocLines(new ArrayList()); + + apiMethod.doc(docBuilder.build()); + + apiMethod.name(namer.getApiMethodName(context.getMethod())); + apiMethod.requestTypeName( + context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getInputType())); + apiMethod.hasReturnValue(!ServiceMessages.s_isEmptyType(context.getMethod().getOutputType())); + apiMethod.key(namer.getMethodKey(context.getMethod())); + apiMethod.grpcMethodName(namer.getGrpcMethodName(context.getMethod())); + + List methodParams = new ArrayList<>(); + for (Field field : context.getMethodConfig().getRequiredFields()) { + methodParams.add(generateDefaultableParam(context, field)); + } + + // TODO create a map TypeRef here instead of an array + // (not done yet because array is sufficient for PHP, and maps are more complex to construct) + TypeRef arrayType = TypeRef.fromPrimitiveName("string").makeRepeated(); + + DynamicDefaultableParamView.Builder optionalArgs = DynamicDefaultableParamView.newBuilder(); + optionalArgs.name(namer.varName(Name.from("optional", "args"))); + optionalArgs.defaultValue(context.getTypeTable().getZeroValueAndSaveNicknameFor(arrayType)); + methodParams.add(optionalArgs.build()); + + DynamicDefaultableParamView.Builder callSettings = DynamicDefaultableParamView.newBuilder(); + callSettings.name(namer.varName(Name.from("call", "settings"))); + callSettings.defaultValue(context.getTypeTable().getZeroValueAndSaveNicknameFor(arrayType)); + methodParams.add(callSettings.build()); + + apiMethod.methodParams(methodParams); + + List requiredRequestObjectParams = new ArrayList<>(); + for (Field field : context.getMethodConfig().getRequiredFields()) { + requiredRequestObjectParams.add(generateRequestObjectParam(context, field)); + } + apiMethod.requiredRequestObjectParams(requiredRequestObjectParams); + + List optionalRequestObjectParams = new ArrayList<>(); + for (Field field : context.getMethodConfig().getOptionalFields()) { + optionalRequestObjectParams.add(generateRequestObjectParam(context, field)); + } + apiMethod.optionalRequestObjectParams(optionalRequestObjectParams); + + return apiMethod.build(); + } + + public DynamicDefaultableParamView generateDefaultableParam( + MethodTransformerContext context, Field field) { + return DynamicDefaultableParamView.newBuilder() + .name(context.getNamer().getVariableName(field)) + .defaultValue("") + .build(); + } + + public RequestObjectParamView generateRequestObjectParam( + MethodTransformerContext context, Field field) { + SurfaceNamer namer = context.getNamer(); + RequestObjectParamView.Builder param = RequestObjectParamView.newBuilder(); + param.name(namer.getVariableName(field)); + if (namer.shouldImportRequestObjectParamType(field)) { + param.elementTypeName( + context.getTypeTable().getAndSaveNicknameForElementType(field.getType())); + param.typeName(context.getTypeTable().getAndSaveNicknameFor(field.getType())); + } else { + param.elementTypeName(SurfaceNamer.NOT_IMPLEMENTED); + param.typeName(SurfaceNamer.NOT_IMPLEMENTED); + } + param.setCallName( + namer.getSetFunctionCallName(field.getType(), Name.from(field.getSimpleName()))); + param.isMap(field.getType().isMap()); + param.isArray(!field.getType().isMap() && field.getType().isRepeated()); + return param.build(); + } + + public List getMethodParamDocs( + MethodTransformerContext context, Iterable fields) { + List allDocs = new ArrayList<>(); + for (Field field : fields) { + SimpleParamDocView.Builder paramDoc = SimpleParamDocView.newBuilder(); + paramDoc.paramName(context.getNamer().getVariableName(field)); + paramDoc.typeName(context.getTypeTable().getAndSaveNicknameFor(field.getType())); + + List docLines = null; + MethodConfig methodConfig = context.getMethodConfig(); + if (methodConfig.isPageStreaming() + && methodConfig.getPageStreaming().hasPageSizeField() + && field.equals(methodConfig.getPageStreaming().getPageSizeField())) { + docLines = + Arrays.asList( + new String[] { + "The maximum number of resources contained in the underlying API", + "response. If page streaming is performed per-resource, this", + "parameter does not affect the return value. If page streaming is", + "performed per-page, this determines the maximum number of", + "resources in a page." + }); + } else { + docLines = context.getNamer().getDocLines(field); + } + + paramDoc.firstLine(docLines.get(0)); + paramDoc.remainingLines(docLines.subList(1, docLines.size())); + + allDocs.add(paramDoc.build()); + } + return allDocs; + } + + public SimpleParamDocView getRequestObjectParamDoc( + MethodTransformerContext context, TypeRef typeRef) { + return SimpleParamDocView.newBuilder() + .paramName("request") + .typeName(context.getTypeTable().getAndSaveNicknameFor(typeRef)) + .firstLine("The request object containing all of the parameters for the API call.") + .remainingLines(Arrays.asList()) + .build(); + } + + public ParamDocView getOptionalArrayParamDoc( + MethodTransformerContext context, Iterable fields) { + MapParamDocView.Builder paramDoc = MapParamDocView.newBuilder(); + + Name optionalArgsName = Name.from("optional", "args"); + + paramDoc.paramName(context.getNamer().varName(optionalArgsName)); + paramDoc.typeName(context.getNamer().getOptionalArrayTypeName()); + + List docLines = null; + if (!fields.iterator().hasNext()) { + String retrySettingsDocText = + String.format( + "Optional. There are no optional parameters for this method yet;\n" + + " this %s parameter reserves a spot for future ones.", + context.getNamer().varReference(optionalArgsName)); + docLines = context.getNamer().getDocLines(retrySettingsDocText); + } else { + docLines = Arrays.asList("Optional."); + } + paramDoc.firstLine(docLines.get(0)); + paramDoc.remainingLines(docLines.subList(1, docLines.size())); + + paramDoc.arrayKeyDocs(getMethodParamDocs(context, fields)); + + return paramDoc.build(); + } + + public ParamDocView getCallSettingsParamDoc(MethodTransformerContext context) { + MapParamDocView.Builder paramDoc = MapParamDocView.newBuilder(); + + paramDoc.paramName(context.getNamer().varName(Name.from("call", "settings"))); + paramDoc.typeName(context.getNamer().getOptionalArrayTypeName()); + paramDoc.firstLine("Optional."); + paramDoc.remainingLines(new ArrayList()); + + List arrayKeyDocs = new ArrayList<>(); + SimpleParamDocView.Builder retrySettingsDoc = SimpleParamDocView.newBuilder(); + retrySettingsDoc.typeName(context.getNamer().getRetrySettingsClassName()); + + Name retrySettingsName = Name.from("retry", "settings"); + Name timeoutMillisName = Name.from("timeout", "millis"); + + retrySettingsDoc.paramName(context.getNamer().varName(retrySettingsName)); + String retrySettingsDocText = + String.format( + "Retry settings to use for this call. If present, then\n%s is ignored.", + context.getNamer().varReference(timeoutMillisName)); + List retrySettingsDocLines = context.getNamer().getDocLines(retrySettingsDocText); + retrySettingsDoc.firstLine(retrySettingsDocLines.get(0)); + retrySettingsDoc.remainingLines(retrySettingsDocLines.subList(1, retrySettingsDocLines.size())); + arrayKeyDocs.add(retrySettingsDoc.build()); + + SimpleParamDocView.Builder timeoutDoc = SimpleParamDocView.newBuilder(); + timeoutDoc.typeName(context.getTypeTable().getAndSaveNicknameFor(TypeRef.of(Type.TYPE_INT32))); + timeoutDoc.paramName(context.getNamer().varName(timeoutMillisName)); + String timeoutMillisDocText = + String.format( + "Timeout to use for this call. Only used if %s\nis not set.", + context.getNamer().varReference(retrySettingsName)); + List timeoutMillisDocLines = context.getNamer().getDocLines(timeoutMillisDocText); + timeoutDoc.firstLine(timeoutMillisDocLines.get(0)); + timeoutDoc.remainingLines(timeoutMillisDocLines.subList(1, timeoutMillisDocLines.size())); + arrayKeyDocs.add(timeoutDoc.build()); + + paramDoc.arrayKeyDocs(arrayKeyDocs); + + return paramDoc.build(); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java b/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java new file mode 100644 index 0000000000..2f113db9a7 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java @@ -0,0 +1,232 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.CollectionConfig; +import com.google.api.codegen.LanguageUtil; +import com.google.api.codegen.metacode.FieldSetting; +import com.google.api.codegen.metacode.FieldStructureParser; +import com.google.api.codegen.metacode.InitCode; +import com.google.api.codegen.metacode.InitCodeGenerator; +import com.google.api.codegen.metacode.InitCodeLine; +import com.google.api.codegen.metacode.InitValueConfig; +import com.google.api.codegen.metacode.ListInitCodeLine; +import com.google.api.codegen.metacode.MapInitCodeLine; +import com.google.api.codegen.metacode.SimpleInitCodeLine; +import com.google.api.codegen.metacode.StructureInitCodeLine; +import com.google.api.codegen.util.Name; +import com.google.api.codegen.viewmodel.FieldSettingView; +import com.google.api.codegen.viewmodel.FormattedInitValueView; +import com.google.api.codegen.viewmodel.InitCodeLineView; +import com.google.api.codegen.viewmodel.InitCodeView; +import com.google.api.codegen.viewmodel.InitValueView; +import com.google.api.codegen.viewmodel.ListInitCodeLineView; +import com.google.api.codegen.viewmodel.MapEntryView; +import com.google.api.codegen.viewmodel.MapInitCodeLineView; +import com.google.api.codegen.viewmodel.SimpleInitCodeLineView; +import com.google.api.codegen.viewmodel.SimpleInitValueView; +import com.google.api.codegen.viewmodel.StructureInitCodeLineView; +import com.google.api.tools.framework.model.Field; +import com.google.api.tools.framework.model.TypeRef; +import com.google.common.collect.ImmutableMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * InitCodeTransformer generates initialization code for a given method and then transforms + * it to a view object which can be rendered by a template engine. + */ +public class InitCodeTransformer { + + public InitCodeView generateInitCode(MethodTransformerContext context, Iterable fields) { + Map initFieldStructure = createInitFieldStructure(context); + InitCodeGenerator generator = new InitCodeGenerator(); + InitCode initCode = + generator.generateRequestFieldInitCode(context.getMethod(), initFieldStructure, fields); + + return InitCodeView.newBuilder() + .lines(generateSurfaceInitCodeLines(context, initCode)) + .fieldSettings(getFieldSettings(context, initCode.getArgFields())) + .build(); + } + + public InitCodeView generateRequestObjectInitCode(MethodTransformerContext context) { + Map initFieldStructure = createInitFieldStructure(context); + InitCodeGenerator generator = new InitCodeGenerator(); + InitCode initCode = + generator.generateRequestObjectInitCode(context.getMethod(), initFieldStructure); + + return InitCodeView.newBuilder() + .lines(generateSurfaceInitCodeLines(context, initCode)) + .fieldSettings(getFieldSettings(context, initCode.getArgFields())) + .build(); + } + + public Map createInitFieldStructure(MethodTransformerContext context) { + Map fieldNamePatterns = context.getMethodConfig().getFieldNamePatterns(); + + ImmutableMap.Builder initValueConfigMap = ImmutableMap.builder(); + for (Map.Entry fieldNamePattern : fieldNamePatterns.entrySet()) { + CollectionConfig collectionConfig = context.getCollectionConfig(fieldNamePattern.getValue()); + String apiWrapperClassName = + context.getNamer().getApiWrapperClassName(context.getInterface()); + InitValueConfig initValueConfig = + InitValueConfig.create(apiWrapperClassName, collectionConfig); + initValueConfigMap.put(fieldNamePattern.getKey(), initValueConfig); + } + Map initFieldStructure = + FieldStructureParser.parseFields( + context.getMethodConfig().getSampleCodeInitFields(), initValueConfigMap.build()); + return initFieldStructure; + } + + public List generateSurfaceInitCodeLines( + MethodTransformerContext context, InitCode initCode) { + List surfaceLines = new ArrayList<>(); + for (InitCodeLine line : initCode.getLines()) { + switch (line.getLineType()) { + case StructureInitLine: + surfaceLines.add(generateStructureInitCodeLine(context, (StructureInitCodeLine) line)); + continue; + case ListInitLine: + surfaceLines.add(generateListInitCodeLine(context, (ListInitCodeLine) line)); + continue; + case SimpleInitLine: + surfaceLines.add(generateSimpleInitCodeLine(context, (SimpleInitCodeLine) line)); + continue; + case MapInitLine: + surfaceLines.add(generateMapInitCodeLine(context, (MapInitCodeLine) line)); + continue; + default: + throw new RuntimeException("unhandled line type: " + line.getLineType()); + } + } + return surfaceLines; + } + + public StructureInitCodeLineView generateStructureInitCodeLine( + MethodTransformerContext context, StructureInitCodeLine line) { + StructureInitCodeLineView.Builder surfaceLine = StructureInitCodeLineView.newBuilder(); + + SurfaceNamer namer = context.getNamer(); + surfaceLine.lineType(line.getLineType()); + surfaceLine.typeName(context.getTypeTable().getAndSaveNicknameFor(line.getType())); + surfaceLine.identifier(namer.getVariableName(line.getIdentifier(), line.getInitValueConfig())); + surfaceLine.fieldSettings(getFieldSettings(context, line.getFieldSettings())); + surfaceLine.initValue(getInitValue(context, line.getType(), line.getInitValueConfig())); + + return surfaceLine.build(); + } + + public ListInitCodeLineView generateListInitCodeLine( + MethodTransformerContext context, ListInitCodeLine line) { + ListInitCodeLineView.Builder surfaceLine = ListInitCodeLineView.newBuilder(); + + SurfaceNamer namer = context.getNamer(); + surfaceLine.lineType(line.getLineType()); + surfaceLine.elementTypeName( + context.getTypeTable().getAndSaveNicknameForElementType(line.getElementType())); + surfaceLine.identifier(namer.getVariableName(line.getIdentifier(), line.getInitValueConfig())); + List elementIdentifiers = new ArrayList<>(); + for (Name identifier : line.getElementIdentifiers()) { + elementIdentifiers.add(namer.varName(identifier)); + } + surfaceLine.elementIdentifiers(elementIdentifiers); + + return surfaceLine.build(); + } + + public SimpleInitCodeLineView generateSimpleInitCodeLine( + MethodTransformerContext context, SimpleInitCodeLine line) { + SimpleInitCodeLineView.Builder surfaceLine = SimpleInitCodeLineView.newBuilder(); + + SurfaceNamer namer = context.getNamer(); + surfaceLine.lineType(line.getLineType()); + surfaceLine.typeName(context.getTypeTable().getAndSaveNicknameFor(line.getType())); + surfaceLine.identifier(namer.getVariableName(line.getIdentifier(), line.getInitValueConfig())); + surfaceLine.initValue(getInitValue(context, line.getType(), line.getInitValueConfig())); + + return surfaceLine.build(); + } + + public InitCodeLineView generateMapInitCodeLine( + MethodTransformerContext context, MapInitCodeLine line) { + MapInitCodeLineView.Builder surfaceLine = MapInitCodeLineView.newBuilder(); + + ModelTypeTable typeTable = context.getTypeTable(); + surfaceLine.lineType(line.getLineType()); + surfaceLine.keyTypeName(typeTable.getAndSaveNicknameFor(line.getKeyType())); + surfaceLine.valueTypeName(typeTable.getAndSaveNicknameFor(line.getValueType())); + surfaceLine.identifier( + context.getNamer().getVariableName(line.getIdentifier(), line.getInitValueConfig())); + List entries = new ArrayList<>(); + for (Map.Entry entry : line.getElementIdentifierMap().entrySet()) { + MapEntryView.Builder mapEntry = MapEntryView.newBuilder(); + mapEntry.key(typeTable.renderPrimitiveValue(line.getKeyType(), entry.getKey())); + mapEntry.value( + context.getNamer().getVariableName(line.getElementIdentifierValue(entry.getKey()), null)); + entries.add(mapEntry.build()); + } + surfaceLine.initEntries(entries); + + return surfaceLine.build(); + } + + public InitValueView getInitValue( + MethodTransformerContext context, TypeRef type, InitValueConfig initValueConfig) { + if (initValueConfig.hasFormattingConfig()) { + FormattedInitValueView.Builder initValue = FormattedInitValueView.newBuilder(); + + initValue.apiWrapperName(context.getNamer().getApiWrapperClassName(context.getInterface())); + initValue.formatFunctionName( + context.getNamer().getFormatFunctionName(initValueConfig.getCollectionConfig())); + List formatFunctionArgs = new ArrayList<>(); + for (String var : initValueConfig.getCollectionConfig().getNameTemplate().vars()) { + formatFunctionArgs.add("\"[" + LanguageUtil.lowerUnderscoreToUpperUnderscore(var) + "]\""); + } + initValue.formatArgs(formatFunctionArgs); + + return initValue.build(); + } else { + SimpleInitValueView.Builder initValue = SimpleInitValueView.newBuilder(); + + if (initValueConfig.hasInitialValue()) { + initValue.initialValue( + context.getTypeTable().renderPrimitiveValue(type, initValueConfig.getInitialValue())); + } else { + initValue.initialValue(context.getTypeTable().getZeroValueAndSaveNicknameFor(type)); + } + + return initValue.build(); + } + } + + public List getFieldSettings( + MethodTransformerContext context, Iterable fieldSettings) { + SurfaceNamer namer = context.getNamer(); + List allSettings = new ArrayList<>(); + for (FieldSetting setting : fieldSettings) { + FieldSettingView.Builder fieldSetting = FieldSettingView.newBuilder(); + fieldSetting.fnSetFunctionCallName( + namer.getSetFunctionCallName(setting.getType(), setting.getFieldName())); + fieldSetting.identifier( + namer.getVariableName(setting.getIdentifier(), setting.getInitValueConfig())); + allSettings.add(fieldSetting.build()); + } + return allSettings; + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/MethodTransformerContext.java b/src/main/java/com/google/api/codegen/transformer/MethodTransformerContext.java new file mode 100644 index 0000000000..4fc9177170 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/MethodTransformerContext.java @@ -0,0 +1,66 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.ApiConfig; +import com.google.api.codegen.CollectionConfig; +import com.google.api.codegen.InterfaceConfig; +import com.google.api.codegen.MethodConfig; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Method; +import com.google.auto.value.AutoValue; + +import java.util.Collection; + +/** + * The context for transforming a method to a view model object. + */ +@AutoValue +public abstract class MethodTransformerContext { + public static MethodTransformerContext create( + Interface interfaze, + ApiConfig apiConfig, + ModelTypeTable typeTable, + SurfaceNamer namer, + Method method, + MethodConfig methodConfig) { + return new AutoValue_MethodTransformerContext( + interfaze, apiConfig, typeTable, namer, method, methodConfig); + } + + public abstract Interface getInterface(); + + public abstract ApiConfig getApiConfig(); + + public abstract ModelTypeTable getTypeTable(); + + public abstract SurfaceNamer getNamer(); + + public abstract Method getMethod(); + + public abstract MethodConfig getMethodConfig(); + + public InterfaceConfig getInterfaceConfig() { + return getApiConfig().getInterfaceConfig(getInterface()); + } + + public Collection getCollectionConfigs() { + return getInterfaceConfig().getCollectionConfigs(); + } + + public CollectionConfig getCollectionConfig(String entityName) { + return getInterfaceConfig().getCollectionConfig(entityName); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/ModelToViewTransformer.java b/src/main/java/com/google/api/codegen/transformer/ModelToViewTransformer.java new file mode 100644 index 0000000000..421309da3f --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ModelToViewTransformer.java @@ -0,0 +1,31 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.ApiConfig; +import com.google.api.codegen.viewmodel.ViewModel; +import com.google.api.tools.framework.model.Model; + +import java.util.List; + +/** + * A ModelToViewTransformer transforms a Model into a list of + * ViewModel instances that can be rendered by a template engine. + */ +public interface ModelToViewTransformer { + List transform(Model model, ApiConfig apiConfig); + + List getTemplateFileNames(); +} diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java new file mode 100644 index 0000000000..91e1549878 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java @@ -0,0 +1,95 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.tools.framework.model.TypeRef; + +import java.util.List; + +/** + * A ModelTypeTable manages the imports for a set of fully-qualified type names, and + * provides helper methods for importing instances of TypeRef. + */ +public interface ModelTypeTable { + + /** + * Creates a new ModelTypeTable of the same concrete type, but with an empty import set. + */ + ModelTypeTable cloneEmpty(); + + /** + * Compute the nickname for the given fullName and save it in the import set. + */ + void saveNicknameFor(String fullName); + + /** + * Get the full name for the given type. + */ + String getFullNameFor(TypeRef type); + + /** + * If the given type is repeated, then returns the contained type; if the type is + * not a repeated type, then returns the boxed form of the type. + */ + String getFullNameForElementType(TypeRef type); + + /** + * Returns the nickname for the given type (without adding the full name to the import set). + */ + String getNicknameFor(TypeRef type); + + /** + * Computes the nickname for the given full name, adds the full name to the import set, + * and returns the nickname. + */ + String getAndSaveNicknameFor(String fullName); + + /** + * Computes the nickname for the given type, adds the full name to the import set, + * and returns the nickname. + */ + String getAndSaveNicknameFor(TypeRef type); + + /** + * This function will compute the nickname for the element type, add the full name to the + * import set, and then return the nickname. If the given type is repeated, then the + * element type is the contained type; if the type is not a repeated type, then the element + * type is the boxed form of the type. + */ + String getAndSaveNicknameForElementType(TypeRef type); + + /** + * Computes the nickname for the given container type name and element type name, + * saves the full names of those types in the import set, and then returns the + * formatted nickname for the type. + */ + String getAndSaveNicknameForContainer(String containerFullName, String elementFullName); + + /** + * Renders the primitive value of the given type. + */ + String renderPrimitiveValue(TypeRef type, String key); + + /** + * If the given type is not implicitly imported, the add it to the import set, then return + * the zero value for that type. + */ + String getZeroValueAndSaveNicknameFor(TypeRef type); + + /** + * Returns the imports accumulated so far. + */ + List getImports(); +} diff --git a/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java b/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java new file mode 100644 index 0000000000..915c5d6f7b --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java @@ -0,0 +1,54 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.PageStreamingConfig; +import com.google.api.codegen.util.Name; +import com.google.api.codegen.viewmodel.PageStreamingDescriptorView; +import com.google.api.tools.framework.model.Method; + +import java.util.ArrayList; +import java.util.List; + +/** + * PageStreamingTransformer generates view objects for page streaming from a service model. + */ +public class PageStreamingTransformer { + + public List generateDescriptors(SurfaceTransformerContext context) { + List descriptors = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + MethodConfig methodConfig = context.getMethodConfig(method); + if (!methodConfig.isPageStreaming()) { + continue; + } + context.getNamer().addPageStreamingDescriptorImports(context.getTypeTable()); + PageStreamingConfig pageStreaming = methodConfig.getPageStreaming(); + + PageStreamingDescriptorView.Builder descriptor = PageStreamingDescriptorView.newBuilder(); + descriptor.varName(context.getNamer().getPageStreamingDescriptorName(method)); + descriptor.requestTokenFieldName(pageStreaming.getRequestTokenField().getSimpleName()); + descriptor.responseTokenFieldName(pageStreaming.getResponseTokenField().getSimpleName()); + descriptor.resourcesFieldName(pageStreaming.getResourcesField().getSimpleName()); + descriptor.methodName(Name.upperCamel(method.getSimpleName()).toLowerCamel()); + + descriptors.add(descriptor.build()); + } + + return descriptors; + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/PathTemplateTransformer.java b/src/main/java/com/google/api/codegen/transformer/PathTemplateTransformer.java new file mode 100644 index 0000000000..c078a976d8 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/PathTemplateTransformer.java @@ -0,0 +1,107 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.CollectionConfig; +import com.google.api.codegen.viewmodel.FormatResourceFunctionView; +import com.google.api.codegen.viewmodel.ParseResourceFunctionView; +import com.google.api.codegen.viewmodel.PathTemplateView; +import com.google.api.codegen.viewmodel.PathTemplateGetterFunctionView; +import com.google.api.codegen.viewmodel.ResourceIdParamView; + +import java.util.ArrayList; +import java.util.List; + +/** + * PathTemplateTransformer generates view objects for path templates from a service model. + */ +public class PathTemplateTransformer { + + public List generatePathTemplates(SurfaceTransformerContext context) { + List pathTemplates = new ArrayList<>(); + + for (CollectionConfig collectionConfig : context.getCollectionConfigs()) { + PathTemplateView.Builder pathTemplate = PathTemplateView.newBuilder(); + pathTemplate.name(context.getNamer().getPathTemplateName(collectionConfig)); + pathTemplate.pattern(collectionConfig.getNamePattern()); + pathTemplates.add(pathTemplate.build()); + } + + return pathTemplates; + } + + public List generateFormatResourceFunctions( + SurfaceTransformerContext context) { + List functions = new ArrayList<>(); + + SurfaceNamer namer = context.getNamer(); + for (CollectionConfig collectionConfig : context.getCollectionConfigs()) { + FormatResourceFunctionView.Builder function = FormatResourceFunctionView.newBuilder(); + function.entityName(collectionConfig.getEntityName()); + function.name(namer.getFormatFunctionName(collectionConfig)); + function.pathTemplateName(namer.getPathTemplateName(collectionConfig)); + function.pathTemplateGetterName(namer.getPathTemplateNameGetter(collectionConfig)); + List resourceIdParams = new ArrayList<>(); + for (String var : collectionConfig.getNameTemplate().vars()) { + ResourceIdParamView param = + ResourceIdParamView.newBuilder().name(namer.getParamName(var)).templateKey(var).build(); + resourceIdParams.add(param); + } + function.resourceIdParams(resourceIdParams); + + functions.add(function.build()); + } + + return functions; + } + + public List generateParseResourceFunctions( + SurfaceTransformerContext context) { + List functions = new ArrayList<>(); + + SurfaceNamer namer = context.getNamer(); + for (CollectionConfig collectionConfig : context.getCollectionConfigs()) { + for (String var : collectionConfig.getNameTemplate().vars()) { + ParseResourceFunctionView.Builder function = ParseResourceFunctionView.newBuilder(); + function.entityName(namer.getEntityName(collectionConfig)); + function.name(namer.getParseFunctionName(var, collectionConfig)); + function.pathTemplateName(namer.getPathTemplateName(collectionConfig)); + function.pathTemplateGetterName(namer.getPathTemplateNameGetter(collectionConfig)); + function.entityNameParamName(namer.getEntityNameParamName(collectionConfig)); + function.outputResourceId(var); + + functions.add(function.build()); + } + } + + return functions; + } + + public List generatePathTemplateGetterFunctions( + SurfaceTransformerContext context) { + List functions = new ArrayList<>(); + + SurfaceNamer namer = context.getNamer(); + for (CollectionConfig collectionConfig : context.getCollectionConfigs()) { + PathTemplateGetterFunctionView.Builder function = PathTemplateGetterFunctionView.newBuilder(); + function.name(namer.getPathTemplateNameGetter(collectionConfig)); + function.pathTemplateName(namer.getPathTemplateName(collectionConfig)); + function.pattern(collectionConfig.getNamePattern()); + functions.add(function.build()); + } + + return functions; + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java new file mode 100644 index 0000000000..ffc679d47f --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -0,0 +1,159 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.CollectionConfig; +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.metacode.InitValueConfig; +import com.google.api.codegen.util.CommonRenderingUtil; +import com.google.api.codegen.util.Name; +import com.google.api.codegen.util.NameFormatter; +import com.google.api.codegen.util.NamePath; +import com.google.api.codegen.util.ViewNamer; +import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; +import com.google.api.tools.framework.model.Field; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.ProtoElement; +import com.google.api.tools.framework.model.TypeRef; + +import java.util.List; + +/** + * A SurfaceNamer provides language-specific names or other strings. + */ +public class SurfaceNamer extends ViewNamer { + public SurfaceNamer(NameFormatter languageNamer) { + super(languageNamer); + } + + public static final String NOT_IMPLEMENTED = "$ NOT IMPLEMENTED $"; + + public String getApiWrapperClassName(Interface interfaze) { + return className(Name.upperCamel(interfaze.getSimpleName(), "Api")); + } + + public String getApiWrapperVariableName(Interface interfaze) { + return varName(Name.upperCamel(interfaze.getSimpleName(), "Api")); + } + + public String getVariableName(Name identifier, InitValueConfig initValueConfig) { + if (initValueConfig == null || !initValueConfig.hasFormattingConfig()) { + return varName(identifier); + } else { + return varName(Name.from("formatted").join(identifier)); + } + } + + public String getSetFunctionCallName(TypeRef type, Name identifier) { + if (type.isMap()) { + return methodName(Name.from("put", "all").join(identifier)); + } else if (type.isRepeated()) { + return methodName(Name.from("add", "all").join(identifier)); + } else { + return methodName(Name.from("set").join(identifier)); + } + } + + public String getPathTemplateName(CollectionConfig collectionConfig) { + return inittedConstantName(Name.from(collectionConfig.getEntityName(), "path", "template")); + } + + public String getPathTemplateNameGetter(CollectionConfig collectionConfig) { + return methodName(Name.from("get", collectionConfig.getEntityName(), "name", "template")); + } + + public String getFormatFunctionName(CollectionConfig collectionConfig) { + return staticFunctionName(Name.from("format", collectionConfig.getEntityName(), "name")); + } + + public String getParseFunctionName(String var, CollectionConfig collectionConfig) { + return staticFunctionName( + Name.from("parse", var, "from", collectionConfig.getEntityName(), "name")); + } + + public String getEntityName(CollectionConfig collectionConfig) { + return varName(Name.from(collectionConfig.getEntityName())); + } + + public String getEntityNameParamName(CollectionConfig collectionConfig) { + return varName(Name.from(collectionConfig.getEntityName(), "name")); + } + + public String getParamName(String var) { + return varName(Name.from(var)); + } + + public String getPageStreamingDescriptorName(Method method) { + return varName(Name.upperCamel(method.getSimpleName(), "PageStreamingDescriptor")); + } + + public void addPageStreamingDescriptorImports(ModelTypeTable typeTable) { + // do nothing + } + + public String getMethodKey(Method method) { + return keyName(Name.upperCamel(method.getSimpleName())); + } + + public String getClientConfigPath(Interface service) { + return SurfaceNamer.NOT_IMPLEMENTED; + } + + public String getGrpcClientTypeName(Interface service) { + NamePath namePath = NamePath.dotted(service.getFullName()); + String className = className(Name.upperCamel(namePath.getHead(), "Client")); + return qualifiedName(namePath.withHead(className)); + } + + public String getApiMethodName(Method method) { + return methodName(Name.upperCamel(method.getSimpleName())); + } + + public String getVariableName(Field field) { + return varName(Name.from(field.getSimpleName())); + } + + public boolean shouldImportRequestObjectParamType(Field field) { + return true; + } + + public List getDocLines(String text) { + return CommonRenderingUtil.getDocLines(text); + } + + public List getDocLines(ProtoElement element) { + return getDocLines(DocumentationUtil.getDescription(element)); + } + + public String getGrpcMethodName(Method method) { + // This might seem silly, but it makes clear what we're dealing with (upper camel). + // This is language-independent because of gRPC conventions. + return Name.upperCamel(method.getSimpleName()).toUpperCamel(); + } + + public String getRetrySettingsClassName() { + return SurfaceNamer.NOT_IMPLEMENTED; + } + + public String getOptionalArrayTypeName() { + return SurfaceNamer.NOT_IMPLEMENTED; + } + + public String getDynamicReturnTypeName( + ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + return SurfaceNamer.NOT_IMPLEMENTED; + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceTransformerContext.java b/src/main/java/com/google/api/codegen/transformer/SurfaceTransformerContext.java new file mode 100644 index 0000000000..e328f515b1 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceTransformerContext.java @@ -0,0 +1,74 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.ApiConfig; +import com.google.api.codegen.CollectionConfig; +import com.google.api.codegen.InterfaceConfig; +import com.google.api.codegen.MethodConfig; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Method; +import com.google.auto.value.AutoValue; + +import java.util.Collection; + +/** + * The context for transforming a model into a view model for a surface. + */ +@AutoValue +public abstract class SurfaceTransformerContext { + public static SurfaceTransformerContext create( + Interface interfaze, ApiConfig apiConfig, ModelTypeTable typeTable, SurfaceNamer namer) { + return new AutoValue_SurfaceTransformerContext(interfaze, apiConfig, typeTable, namer); + } + + public abstract Interface getInterface(); + + public abstract ApiConfig getApiConfig(); + + public abstract ModelTypeTable getTypeTable(); + + public abstract SurfaceNamer getNamer(); + + public SurfaceTransformerContext withNewTypeTable() { + return create(getInterface(), getApiConfig(), getTypeTable().cloneEmpty(), getNamer()); + } + + public InterfaceConfig getInterfaceConfig() { + return getApiConfig().getInterfaceConfig(getInterface()); + } + + public MethodConfig getMethodConfig(Method method) { + return getInterfaceConfig().getMethodConfig(method); + } + + public Collection getCollectionConfigs() { + return getInterfaceConfig().getCollectionConfigs(); + } + + public CollectionConfig getCollectionConfig(String entityName) { + return getInterfaceConfig().getCollectionConfig(entityName); + } + + public MethodTransformerContext asMethodContext(Method method) { + return MethodTransformerContext.create( + getInterface(), + getApiConfig(), + getTypeTable(), + getNamer(), + method, + getMethodConfig(method)); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java new file mode 100644 index 0000000000..6f1acf3e3a --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java @@ -0,0 +1,166 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer.php; + +import com.google.api.codegen.ApiConfig; +import com.google.api.codegen.InterfaceView; +import com.google.api.codegen.ServiceConfig; +import com.google.api.codegen.gapic.GapicCodePathMapper; +import com.google.api.codegen.transformer.ApiMethodTransformer; +import com.google.api.codegen.transformer.ModelToViewTransformer; +import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.PageStreamingTransformer; +import com.google.api.codegen.transformer.PathTemplateTransformer; +import com.google.api.codegen.transformer.SurfaceNamer; +import com.google.api.codegen.transformer.SurfaceTransformerContext; +import com.google.api.codegen.viewmodel.ApiMethodView; +import com.google.api.codegen.viewmodel.DynamicXApiView; +import com.google.api.codegen.viewmodel.ServiceDocView; +import com.google.api.codegen.viewmodel.ViewModel; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.Model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * The ModelToViewTransformer to transform a Model into the standard GAPIC surface in PHP. + */ +public class PhpGapicSurfaceTransformer implements ModelToViewTransformer { + private GapicCodePathMapper pathMapper; + private PathTemplateTransformer pathTemplateTransformer; + private PageStreamingTransformer pageStreamingTransformer; + private ApiMethodTransformer apiMethodTransformer; + + private static final String XAPI_TEMPLATE_FILENAME = "php/main.snip"; + + /** + * Standard constructor. + */ + public PhpGapicSurfaceTransformer(ApiConfig apiConfig, GapicCodePathMapper pathMapper) { + this.pathMapper = pathMapper; + this.pathTemplateTransformer = new PathTemplateTransformer(); + this.pageStreamingTransformer = new PageStreamingTransformer(); + this.apiMethodTransformer = new ApiMethodTransformer(); + } + + @Override + public List getTemplateFileNames() { + return Arrays.asList(XAPI_TEMPLATE_FILENAME); + } + + @Override + public List transform(Model model, ApiConfig apiConfig) { + List surfaceDocs = new ArrayList<>(); + for (Interface service : new InterfaceView().getElementIterable(model)) { + SurfaceTransformerContext context = + SurfaceTransformerContext.create( + service, apiConfig, new PhpModelTypeTable(), new PhpSurfaceNamer()); + + surfaceDocs.addAll(transform(context)); + } + return surfaceDocs; + } + + public List transform(SurfaceTransformerContext context) { + String outputPath = pathMapper.getOutputPath(context.getInterface(), context.getApiConfig()); + SurfaceNamer namer = context.getNamer(); + + List surfaceData = new ArrayList<>(); + + addXApiImports(context); + + List methods = generateApiMethods(context); + + DynamicXApiView.Builder xapiClass = DynamicXApiView.newBuilder(); + + ServiceDocView.Builder serviceDoc = ServiceDocView.newBuilder(); + List docLines = context.getNamer().getDocLines(context.getInterface()); + serviceDoc.firstLine(docLines.get(0)); + serviceDoc.remainingLines(docLines.subList(1, docLines.size())); + serviceDoc.exampleApiMethod(methods.get(0)); + xapiClass.doc(serviceDoc.build()); + + xapiClass.templateFileName(XAPI_TEMPLATE_FILENAME); + xapiClass.protoFilename(context.getInterface().getFile().getSimpleName()); + xapiClass.packageName(context.getApiConfig().getPackageName()); + String name = namer.getApiWrapperClassName(context.getInterface()); + xapiClass.name(name); + ServiceConfig serviceConfig = new ServiceConfig(); + xapiClass.serviceAddress(serviceConfig.getServiceAddress(context.getInterface())); + xapiClass.servicePort(serviceConfig.getServicePort()); + xapiClass.serviceTitle(serviceConfig.getTitle(context.getInterface())); + xapiClass.authScopes(serviceConfig.getAuthScopes(context.getInterface())); + + xapiClass.pathTemplates(pathTemplateTransformer.generatePathTemplates(context)); + xapiClass.formatResourceFunctions( + pathTemplateTransformer.generateFormatResourceFunctions(context)); + xapiClass.parseResourceFunctions( + pathTemplateTransformer.generateParseResourceFunctions(context)); + xapiClass.pathTemplateGetterFunctions( + pathTemplateTransformer.generatePathTemplateGetterFunctions(context)); + xapiClass.pageStreamingDescriptors(pageStreamingTransformer.generateDescriptors(context)); + + xapiClass.methodKeys(generateMethodKeys(context)); + xapiClass.clientConfigPath(namer.getClientConfigPath(context.getInterface())); + xapiClass.interfaceKey(context.getInterface().getFullName()); + String grpcClientTypeName = namer.getGrpcClientTypeName(context.getInterface()); + xapiClass.grpcClientTypeName(context.getTypeTable().getAndSaveNicknameFor(grpcClientTypeName)); + + xapiClass.apiMethods(methods); + + // must be done as the last step to catch all imports + xapiClass.imports(context.getTypeTable().getImports()); + + xapiClass.outputPath(outputPath + "/" + name + ".php"); + + surfaceData.add(xapiClass.build()); + + return surfaceData; + } + + private void addXApiImports(SurfaceTransformerContext context) { + ModelTypeTable typeTable = context.getTypeTable(); + typeTable.saveNicknameFor("Google\\GAX\\AgentHeaderDescriptor"); + typeTable.saveNicknameFor("Google\\GAX\\ApiCallable"); + typeTable.saveNicknameFor("Google\\GAX\\CallSettings"); + typeTable.saveNicknameFor("Google\\GAX\\GrpcBootstrap"); + typeTable.saveNicknameFor("Google\\GAX\\GrpcConstants"); + typeTable.saveNicknameFor("Google\\GAX\\PathTemplate"); + } + + private List generateMethodKeys(SurfaceTransformerContext context) { + List methodKeys = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + methodKeys.add(context.getNamer().getMethodKey(method)); + } + + return methodKeys; + } + + private List generateApiMethods(SurfaceTransformerContext context) { + List apiMethods = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + apiMethods.add( + apiMethodTransformer.generateOptionalArrayMethod(context.asMethodContext(method))); + } + + return apiMethods; + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java new file mode 100644 index 0000000000..81331ef5b3 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java @@ -0,0 +1,239 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer.php; + +import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.php.PhpTypeTable; +import com.google.api.tools.framework.model.ProtoElement; +import com.google.api.tools.framework.model.ProtoFile; +import com.google.api.tools.framework.model.TypeRef; +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; + +import java.util.List; + +import org.apache.commons.lang3.NotImplementedException; + +/** + * The ModelTypeTable for PHP. + */ +public class PhpModelTypeTable implements ModelTypeTable { + private PhpTypeTable phpTypeTable; + + /** + * A map from primitive types in proto to PHP counterparts. + */ + private static final ImmutableMap PRIMITIVE_TYPE_MAP = + ImmutableMap.builder() + .put(Type.TYPE_BOOL, "bool") + .put(Type.TYPE_DOUBLE, "float") + .put(Type.TYPE_FLOAT, "float") + .put(Type.TYPE_INT64, "int") + .put(Type.TYPE_UINT64, "int") + .put(Type.TYPE_SINT64, "int") + .put(Type.TYPE_FIXED64, "int") + .put(Type.TYPE_SFIXED64, "int") + .put(Type.TYPE_INT32, "int") + .put(Type.TYPE_UINT32, "int") + .put(Type.TYPE_SINT32, "int") + .put(Type.TYPE_FIXED32, "int") + .put(Type.TYPE_SFIXED32, "int") + .put(Type.TYPE_STRING, "string") + .put(Type.TYPE_BYTES, "string") + .build(); + + /** + * A map from primitive types in proto to zero value in PHP + */ + private static final ImmutableMap PRIMITIVE_ZERO_VALUE = + ImmutableMap.builder() + .put(Type.TYPE_BOOL, "false") + .put(Type.TYPE_DOUBLE, "0.0") + .put(Type.TYPE_FLOAT, "0.0") + .put(Type.TYPE_INT64, "0") + .put(Type.TYPE_UINT64, "0") + .put(Type.TYPE_SINT64, "0") + .put(Type.TYPE_FIXED64, "0") + .put(Type.TYPE_SFIXED64, "0") + .put(Type.TYPE_INT32, "0") + .put(Type.TYPE_UINT32, "0") + .put(Type.TYPE_SINT32, "0") + .put(Type.TYPE_FIXED32, "0") + .put(Type.TYPE_SFIXED32, "0") + .put(Type.TYPE_STRING, "\"\"") + .put(Type.TYPE_BYTES, "\"\"") + .build(); + + /** + * Standard constructor. + */ + public PhpModelTypeTable() { + phpTypeTable = new PhpTypeTable(); + } + + @Override + public ModelTypeTable cloneEmpty() { + return new PhpModelTypeTable(); + } + + @Override + public String getFullNameFor(TypeRef type) { + return getTypeName(type).getFullName(); + } + + @Override + public String getFullNameForElementType(TypeRef type) { + return getTypeNameForElementType(type).getFullName(); + } + + @Override + public String getNicknameFor(TypeRef type) { + return getTypeName(type).getNickname(); + } + + @Override + public void saveNicknameFor(String fullName) { + getAndSaveNicknameFor(fullName); + } + + @Override + public String getAndSaveNicknameFor(String fullName) { + return phpTypeTable.getAndSaveNicknameFor(fullName); + } + + /** + * Returns the PHP representation of a reference to a type. + */ + @Override + public String getAndSaveNicknameFor(TypeRef type) { + return phpTypeTable.getAndSaveNicknameFor(getTypeName(type)); + } + + private TypeName getTypeName(TypeRef type) { + if (type.isMap()) { + return new TypeName("array"); + } else if (type.isRepeated()) { + TypeName elementTypeName = getTypeNameForElementType(type); + return new TypeName("", "", "%i[]", elementTypeName); + } else { + return getTypeNameForElementType(type); + } + } + + @Override + public String getAndSaveNicknameForElementType(TypeRef type) { + return phpTypeTable.getAndSaveNicknameFor(getTypeNameForElementType(type)); + } + + @Override + public String getAndSaveNicknameForContainer(String containerFullName, String elementFullName) { + throw new NotImplementedException("ModelToPhpTypeTable.getAndSaveNicknameForContainer"); + } + + /** + * Returns the PHP representation of a type, without cardinality. If the type is a primitive, + * importAndGetShortestNameForElementType returns it in unboxed form. + */ + private TypeName getTypeNameForElementType(TypeRef type) { + String primitiveTypeName = PRIMITIVE_TYPE_MAP.get(type.getKind()); + if (primitiveTypeName != null) { + if (primitiveTypeName.contains("\\")) { + // Fully qualified type name, use regular type name resolver. Can skip boxing logic + // because those types are already boxed. + return phpTypeTable.getTypeName(primitiveTypeName); + } else { + return new TypeName(primitiveTypeName); + } + } + switch (type.getKind()) { + case TYPE_MESSAGE: + return getTypeName(type.getMessageType()); + case TYPE_ENUM: + return getTypeName(type.getEnumType()); + default: + throw new IllegalArgumentException("unknown type kind: " + type.getKind()); + } + } + + @Override + public String renderPrimitiveValue(TypeRef type, String value) { + Type primitiveType = type.getKind(); + if (!PRIMITIVE_TYPE_MAP.containsKey(primitiveType)) { + throw new IllegalArgumentException( + "Initial values are only supported for primitive types, got type " + + type + + ", with value " + + value); + } + switch (primitiveType) { + case TYPE_BOOL: + return value.toLowerCase(); + case TYPE_STRING: + case TYPE_BYTES: + return "\"" + value + "\""; + default: + // Types that do not need to be modified (e.g. TYPE_INT32) are handled here + return value; + } + } + + /** + * Returns the PHP representation of a zero value for that type, to be used in code sample doc. + * + * Parametric types may use the diamond operator, since the return value will be used only in + * initialization. + */ + @Override + public String getZeroValueAndSaveNicknameFor(TypeRef type) { + // Don't call getTypeName; we don't need to import these. + if (type.isMap()) { + return "[]"; + } + if (type.isRepeated()) { + return "[]"; + } + if (PRIMITIVE_ZERO_VALUE.containsKey(type.getKind())) { + return PRIMITIVE_ZERO_VALUE.get(type.getKind()); + } + if (type.isMessage()) { + return "new " + getAndSaveNicknameFor(type) + "()"; + } + return "null"; + } + + @Override + public List getImports() { + return phpTypeTable.getImports(); + } + + /** + * Gets the full name of the message or enum type in PHP. + */ + private TypeName getTypeName(ProtoElement elem) { + // Construct the fully-qualified PHP class name + int fullNamePrefixLength = elem.getFile().getFullName().length() + 1; + String nickname = elem.getFullName().substring(fullNamePrefixLength); + String fullName = getPhpPackage(elem.getFile()) + "\\" + nickname; + return new TypeName(fullName, nickname); + } + + /** + * Gets the PHP package for the given proto file. + */ + private static String getPhpPackage(ProtoFile file) { + return file.getProto().getPackage().replaceAll("\\.", "\\\\"); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java new file mode 100644 index 0000000000..f50b32b0e3 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java @@ -0,0 +1,89 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer.php; + +import com.google.api.codegen.CollectionConfig; +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.ServiceMessages; +import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.SurfaceNamer; +import com.google.api.codegen.util.Name; +import com.google.api.codegen.util.php.PhpNameFormatter; +import com.google.api.tools.framework.model.Field; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.TypeRef; + +/** + * The SurfaceNamer for PHP. + */ +public class PhpSurfaceNamer extends SurfaceNamer { + public PhpSurfaceNamer() { + super(new PhpNameFormatter()); + } + + @Override + public String getSetFunctionCallName(TypeRef type, Name identifier) { + if (type.isMap() || type.isRepeated()) { + return methodName(Name.from("add").join(identifier)); + } else { + return methodName(Name.from("set").join(identifier)); + } + } + + @Override + public String getPathTemplateName(CollectionConfig collectionConfig) { + return inittedConstantName(Name.from(collectionConfig.getEntityName(), "name", "template")); + } + + @Override + public void addPageStreamingDescriptorImports(ModelTypeTable typeTable) { + typeTable.saveNicknameFor("Google\\GAX\\PageStreamingDescriptor"); + } + + @Override + public String getClientConfigPath(Interface service) { + return "./resources/" + + Name.upperCamel(service.getSimpleName()).join("client_config").toLowerUnderscore() + + ".json"; + } + + @Override + public boolean shouldImportRequestObjectParamType(Field field) { + return field.getType().isMap(); + } + + @Override + public String getRetrySettingsClassName() { + return "Google\\GAX\\RetrySettings"; + } + + @Override + public String getOptionalArrayTypeName() { + return "array"; + } + + @Override + public String getDynamicReturnTypeName( + ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + if (new ServiceMessages().isEmptyType(method.getOutputType())) { + return ""; + } + if (methodConfig.isPageStreaming()) { + return "Google\\GAX\\PageAccessor"; + } + return typeTable.getFullNameFor(method.getOutputType()); + } +} diff --git a/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java b/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java new file mode 100644 index 0000000000..020635dc4e --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java @@ -0,0 +1,35 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.common.base.Splitter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utility class to process text in the templates. + */ +public class CommonRenderingUtil { + + public static List getDocLines(String text) { + // TODO: convert markdown to phpDoc + List result = new ArrayList<>(); + for (String line : Splitter.on(String.format("%n")).split(text)) { + result.add(line); + } + return result; + } +} diff --git a/src/main/java/com/google/api/codegen/util/Name.java b/src/main/java/com/google/api/codegen/util/Name.java new file mode 100644 index 0000000000..11459cfcdf --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/Name.java @@ -0,0 +1,204 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.api.client.util.Joiner; +import com.google.common.base.CaseFormat; + +import java.util.ArrayList; +import java.util.List; + +/** + * Name represents an identifier name which is casing-aware. + */ +public class Name { + private List namePieces; + + /** + * Creates a Name from a sequence of lower-underscore strings. + * + * @throws IllegalArgumentException if any of the strings contain any characters that are not + * lower case or underscores. + */ + public static Name from(String... pieces) { + List namePieces = new ArrayList<>(); + for (String piece : pieces) { + validateLowerUnderscore(piece); + namePieces.add(new NamePiece(piece, CaseFormat.LOWER_UNDERSCORE)); + } + return new Name(namePieces); + } + + /** + * Creates a Name from a sequence of lower-camel strings. + * + * @throws IllegalArgumentException if any of the strings do not follow the lower-camel format. + */ + public static Name lowerCamel(String... pieces) { + List namePieces = new ArrayList<>(); + for (String piece : pieces) { + validateCamel(piece, false); + namePieces.add(new NamePiece(piece, CaseFormat.LOWER_CAMEL)); + } + return new Name(namePieces); + } + + /** + * Creates a Name from a sequence of upper-camel strings. + * + * @throws IllegalArgumentException if any of the strings do not follow the upper-camel format. + */ + public static Name upperCamel(String... pieces) { + List namePieces = new ArrayList<>(); + for (String piece : pieces) { + validateCamel(piece, true); + namePieces.add(new NamePiece(piece, CaseFormat.UPPER_CAMEL)); + } + return new Name(namePieces); + } + + private static void validateLowerUnderscore(String identifier) { + if (!isLowerUnderscore(identifier)) { + throw new IllegalArgumentException( + "Name: identifier not in lower-underscore: '" + identifier + "'"); + } + } + + private static boolean isLowerUnderscore(String identifier) { + Character underscore = Character.valueOf('_'); + for (Character ch : identifier.toCharArray()) { + if (!Character.isLowerCase(ch) && !ch.equals(underscore)) { + return false; + } + } + return true; + } + + private static void validateCamel(String identifier, boolean upper) { + if (!isCamel(identifier, upper)) { + String casingDescription = "lower camel"; + if (upper) { + casingDescription = "upper camel"; + } + throw new IllegalArgumentException( + "Name: identifier not in " + casingDescription + ": '" + identifier + "'"); + } + } + + private static boolean isCamel(String identifier, boolean upper) { + if (identifier.length() == 0) { + return true; + } + if (upper && !Character.isUpperCase(identifier.charAt(0))) { + return false; + } + if (!upper && !Character.isLowerCase(identifier.charAt(0))) { + return false; + } + for (Character ch : identifier.toCharArray()) { + if (!Character.isLowerCase(ch) && !Character.isUpperCase(ch)) { + return false; + } + } + return true; + } + + private Name(List namePieces) { + this.namePieces = namePieces; + } + + /** + * Returns the identifier in upper-underscore format. + */ + public String toUpperUnderscore() { + return toUnderscore(CaseFormat.UPPER_UNDERSCORE); + } + + /** + * Returns the identifier in lower-underscore format. + */ + public String toLowerUnderscore() { + return toUnderscore(CaseFormat.LOWER_UNDERSCORE); + } + + private String toUnderscore(CaseFormat caseFormat) { + List newPieces = new ArrayList<>(); + for (NamePiece namePiece : namePieces) { + newPieces.add(namePiece.caseFormat.to(caseFormat, namePiece.identifier)); + } + return Joiner.on('_').join(newPieces); + } + + /** + * Returns the identifier in lower-camel format. + */ + public String toLowerCamel() { + return toCamel(CaseFormat.LOWER_CAMEL); + } + + /** + * Returns the identifier in upper-camel format. + */ + public String toUpperCamel() { + return toCamel(CaseFormat.UPPER_CAMEL); + } + + private String toCamel(CaseFormat caseFormat) { + StringBuffer buffer = new StringBuffer(); + boolean firstPiece = true; + for (NamePiece namePiece : namePieces) { + if (firstPiece && caseFormat.equals(CaseFormat.LOWER_CAMEL)) { + buffer.append(namePiece.caseFormat.to(CaseFormat.LOWER_CAMEL, namePiece.identifier)); + } else { + buffer.append(namePiece.caseFormat.to(CaseFormat.UPPER_CAMEL, namePiece.identifier)); + } + firstPiece = false; + } + return buffer.toString(); + } + + /** + * Returns a new Name containing the pieces from this Name plus the given + * identifier added on the end. + */ + public Name join(String identifier) { + validateLowerUnderscore(identifier); + List newPieceList = new ArrayList<>(); + newPieceList.addAll(namePieces); + newPieceList.add(new NamePiece(identifier, CaseFormat.LOWER_UNDERSCORE)); + return new Name(newPieceList); + } + + /** + * Returns a new Name containing the pieces from this Name plus the pieces of the given + * name added on the end. + */ + public Name join(Name rhs) { + List newPieceList = new ArrayList<>(); + newPieceList.addAll(namePieces); + newPieceList.addAll(rhs.namePieces); + return new Name(newPieceList); + } + + private static class NamePiece { + public final String identifier; + public final CaseFormat caseFormat; + + private NamePiece(String identifier, CaseFormat caseFormat) { + this.identifier = identifier; + this.caseFormat = caseFormat; + } + } +} diff --git a/src/main/java/com/google/api/codegen/util/NameFormatter.java b/src/main/java/com/google/api/codegen/util/NameFormatter.java new file mode 100644 index 0000000000..4b394a284b --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/NameFormatter.java @@ -0,0 +1,66 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +/** + * A NameFormatter formats Name objects in using the casing scheme for + * a particular type of identifier in a particular programming language. + */ +public interface NameFormatter { + + /** + * Formats the name as a class name. + */ + String className(Name name); + + /** + * Formats the name as a variable name. + */ + String varName(Name name); + + /** + * Formats the name as a reference to a variable name. + */ + String varReference(Name name); + + /** + * Formats the name as a method name. + */ + String methodName(Name name); + + /** + * Formats the name as a static function name. + */ + String staticFunctionName(Name name); + + /** + * Formats the name as a constant which requires initialization. + * + * It may seem odd that the initialization aspect needs to be distinguished, + * but this is relevant in PHP, where constants with non-trivial initialization + * have to be initialized on first use instead of at declaration time. + */ + String inittedConstantName(Name name); + + /** + * Formats the name as a key name, to be used as a key in a map or hash table. + */ + String keyName(Name name); + + /** + * Formats the name path as a qualified name. + */ + String qualifiedName(NamePath namePath); +} diff --git a/src/main/java/com/google/api/codegen/util/NamePath.java b/src/main/java/com/google/api/codegen/util/NamePath.java new file mode 100644 index 0000000000..e004f23cb0 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/NamePath.java @@ -0,0 +1,80 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.common.base.Joiner; + +import java.util.ArrayList; +import java.util.List; + +/** + * NamePath represents a fully-qualified name, separated by something like + * dots or slashes. + */ +public class NamePath { + private List pathPieces; + + /** + * Create a NamePath that is separated by dots. + */ + public static NamePath dotted(String... pieces) { + List namePieces = new ArrayList<>(); + for (String piece : pieces) { + for (String subPiece : piece.split("\\.")) { + namePieces.add(subPiece); + } + } + if (namePieces.size() == 0) { + throw new IllegalArgumentException("QualifiedName must not be zero length"); + } + return new NamePath(namePieces); + } + + private NamePath(List pathPieces) { + this.pathPieces = pathPieces; + } + + /** + * Create a new NamePath where the head (the last piece) is replaced with the + * given newHead. + */ + public NamePath withHead(String newHead) { + List newPathPieces = new ArrayList<>(); + newPathPieces.addAll(pathPieces); + newPathPieces.set(pathPieces.size() - 1, newHead); + return new NamePath(newPathPieces); + } + + /** + * Returns the head (last piece) of the NamePath. + */ + public String getHead() { + return pathPieces.get(pathPieces.size() - 1); + } + + /** + * Returns the namePath in dotted form. + */ + public String toDotted() { + return Joiner.on(".").join(pathPieces); + } + + /** + * Returns the namePath in backslashed form. + */ + public String toBackslashed() { + return Joiner.on("\\").join(pathPieces); + } +} diff --git a/src/main/java/com/google/api/codegen/util/TypeAlias.java b/src/main/java/com/google/api/codegen/util/TypeAlias.java new file mode 100644 index 0000000000..fbf3af4ce8 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/TypeAlias.java @@ -0,0 +1,58 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.auto.value.AutoValue; + +/** + * TypeAlias represents an alias between a fully-qualified version of a name + * (the "fullName") and a short version of a name (the "nickname"). + */ +@AutoValue +public abstract class TypeAlias { + + /** + * Creates a TypeAlias where the fullName and nickname are the same. + */ + public static TypeAlias create(String name) { + return create(name, name); + } + + /** + * Standard constructor. + */ + public static TypeAlias create(String fullName, String nickname) { + return new AutoValue_TypeAlias(fullName, nickname); + } + + /** + * The full name of the alias. + */ + public abstract String getFullName(); + + /** + * The nickname of the alias. + */ + public abstract String getNickname(); + + /** + * Returns true if the alias needs to be imported to refer to it only + * through the nickname. This will be false if the full name and nickname + * are the same. + */ + public boolean needsImport() { + return !getFullName().equals(getNickname()); + } +} diff --git a/src/main/java/com/google/api/codegen/util/TypeName.java b/src/main/java/com/google/api/codegen/util/TypeName.java new file mode 100644 index 0000000000..552c7e2fdf --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/TypeName.java @@ -0,0 +1,106 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +/** + * Represents a simple or complex type and keeps track of the aliases for the contributing types. + */ +public class TypeName { + private final TypeAlias topLevelAlias; + private final String pattern; + private final List innerTypeNames; + + /** + * Constructs a TypeName where the full name and nickname are the same. + */ + public TypeName(String name) { + this(name, name); + } + + /** + * Standard constructor. + */ + public TypeName(String fullName, String nickname) { + this.topLevelAlias = TypeAlias.create(fullName, nickname); + this.pattern = null; + this.innerTypeNames = Arrays.asList(); + } + + /** + * Constructs a composite TypeName with a special string pattern to render the type, and a list + * of inner TypeName instances that parameterize the type. + * + * @param fullName full name + * @param nickname nickname + * @param pattern Use the pattern %s for self and %i for inner types, one for each inner type + * in the order that they are provided. If this is null, then the type name of + * the outer type is used, and inner type names are ignored. + * @param innerTypeNames + */ + public TypeName(String fullName, String nickname, String pattern, TypeName... innerTypeNames) { + this.topLevelAlias = TypeAlias.create(fullName, nickname); + this.pattern = pattern; + this.innerTypeNames = Arrays.asList(innerTypeNames); + } + + /** + * Renders the fully-qualified name of this type given its pattern. + */ + public String getFullName() { + if (pattern == null) { + return topLevelAlias.getFullName(); + } + String result = StringUtils.replaceOnce(pattern, "%s", topLevelAlias.getFullName()); + for (TypeName innerTypeName : innerTypeNames) { + result = StringUtils.replaceOnce(result, "%i", innerTypeName.getFullName()); + } + return result; + } + + /** + * Renders the short name of this type given its pattern. + */ + public String getNickname() { + if (pattern == null) { + return topLevelAlias.getNickname(); + } + String result = StringUtils.replaceOnce(pattern, "%s", topLevelAlias.getNickname()); + for (TypeName innerTypeName : innerTypeNames) { + result = StringUtils.replaceOnce(result, "%i", innerTypeName.getNickname()); + } + return result; + } + + /** + * Renders the short name of this type given its pattern, and adds any necessary nicknames + * to the given type table. + */ + public String getAndSaveNicknameIn(TypeTable typeTable) { + String topLevelNickname = typeTable.getAndSaveNicknameFor(topLevelAlias); + if (pattern == null) { + return topLevelNickname; + } + String result = StringUtils.replaceOnce(pattern, "%s", topLevelNickname); + for (TypeName innerTypeName : innerTypeNames) { + result = StringUtils.replaceOnce(result, "%i", innerTypeName.getAndSaveNicknameIn(typeTable)); + } + return result; + } +} diff --git a/src/main/java/com/google/api/codegen/util/TypeTable.java b/src/main/java/com/google/api/codegen/util/TypeTable.java new file mode 100644 index 0000000000..4393b81c52 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/TypeTable.java @@ -0,0 +1,27 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +/** + * A type table manages the imports for a set of fully-qualified type names. + */ +public interface TypeTable { + /** + * Determines if the nickname of the given alias can be used, and if so, then + * saves it in the import table and returns it; otherwise (e.g. if there would + * be a clash), returns the full name. + */ + String getAndSaveNicknameFor(TypeAlias alias); +} diff --git a/src/main/java/com/google/api/codegen/util/ViewNamer.java b/src/main/java/com/google/api/codegen/util/ViewNamer.java new file mode 100644 index 0000000000..fcff536738 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/ViewNamer.java @@ -0,0 +1,75 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +/** + * A ViewNamer provides names for specific components of a view. + * + * Naming is composed of two steps: + * + * 1. Composing a Name instance with the name pieces + * 2. Formatting the Name for the particular type of identifier needed. + * + * This class delegates step 2 to the provided name formatter, which generally + * would be a language-specific namer. + */ +public class ViewNamer implements NameFormatter { + + private NameFormatter formatter; + + public ViewNamer(NameFormatter formatter) { + this.formatter = formatter; + } + + @Override + public String className(Name name) { + return formatter.className(name); + } + + @Override + public String varName(Name name) { + return formatter.varName(name); + } + + @Override + public String varReference(Name name) { + return formatter.varReference(name); + } + + @Override + public String methodName(Name name) { + return formatter.methodName(name); + } + + @Override + public String staticFunctionName(Name name) { + return formatter.staticFunctionName(name); + } + + @Override + public String inittedConstantName(Name name) { + return formatter.inittedConstantName(name); + } + + @Override + public String keyName(Name name) { + return formatter.keyName(name); + } + + @Override + public String qualifiedName(NamePath namePath) { + return formatter.qualifiedName(namePath); + } +} diff --git a/src/main/java/com/google/api/codegen/util/php/PhpNameFormatter.java b/src/main/java/com/google/api/codegen/util/php/PhpNameFormatter.java new file mode 100644 index 0000000000..b4de7d029b --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/php/PhpNameFormatter.java @@ -0,0 +1,65 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util.php; + +import com.google.api.codegen.util.Name; +import com.google.api.codegen.util.NameFormatter; +import com.google.api.codegen.util.NamePath; + +/** + * The NameFormatter for PHP. + */ +public class PhpNameFormatter implements NameFormatter { + + @Override + public String className(Name name) { + return name.toUpperCamel(); + } + + @Override + public String varName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String varReference(Name name) { + return "$" + varName(name); + } + + @Override + public String methodName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String staticFunctionName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String inittedConstantName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String keyName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String qualifiedName(NamePath namePath) { + return namePath.toBackslashed(); + } +} diff --git a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java new file mode 100644 index 0000000000..250ad850a7 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java @@ -0,0 +1,168 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util.php; + +import com.google.api.codegen.util.TypeAlias; +import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.TypeTable; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableSet; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * The TypeTable for Java. + */ +public class PhpTypeTable implements TypeTable { + /** + * A bi-map from full names to short names indicating the import map. + */ + private final BiMap imports = HashBiMap.create(); + + public TypeName getTypeName(String fullName) { + int lastBackslashIndex = fullName.lastIndexOf('\\'); + if (lastBackslashIndex < 0) { + throw new IllegalArgumentException("expected fully qualified name"); + } + String nickname = fullName.substring(lastBackslashIndex + 1); + return new TypeName(fullName, nickname); + } + + public String getAndSaveNicknameFor(String fullName) { + return getAndSaveNicknameFor(getTypeName(fullName)); + } + + public String getAndSaveNicknameFor(TypeName typeName) { + return typeName.getAndSaveNicknameIn(this); + } + + @Override + public String getAndSaveNicknameFor(TypeAlias alias) { + if (!alias.needsImport()) { + return alias.getNickname(); + } + // Derive a short name if possible + if (imports.containsKey(alias.getFullName())) { + // Short name already there. + return imports.get(alias.getFullName()); + } + if (imports.containsValue(alias.getNickname())) { + // Short name clashes, use long name. + return alias.getFullName(); + } + imports.put(alias.getFullName(), alias.getNickname()); + return alias.getNickname(); + } + + public List getImports() { + // Clean up the imports. + List cleanedImports = new ArrayList<>(); + for (String imported : imports.keySet()) { + cleanedImports.add(imported); + } + Collections.sort(cleanedImports); + return cleanedImports; + } + + public boolean hasImports() { + return !getImports().isEmpty(); + } + + /** + * A set of PHP keywords and built-ins. keywords: http://php.net/manual/en/reserved.keywords.php + */ + private static final ImmutableSet KEYWORD_BUILT_IN_SET = + ImmutableSet.builder() + .add( + "__halt_compiler", + "abstract", + "and", + "array", + "as", + "break", + "callable", + "case", + "catch", + "class", + "clone", + "const", + "continue", + "declare", + "default", + "die", + "do", + "echo", + "else", + "elseif", + "empty", + "enddeclare", + "endfor", + "endforeach", + "endif", + "endswitch", + "endwhile", + "eval", + "exit", + "extends", + "final", + "finally", + "for", + "foreach", + "function", + "global", + "goto", + "if", + "implements", + "include", + "include_once", + "instanceof", + "insteadof", + "interface", + "isset", + "list", + "namespace", + "new", + "or", + "print", + "private", + "protected", + "public", + "require", + "require_once", + "return", + "static", + "switch", + "throw", + "trait", + "try", + "unset", + "use", + "var", + "while", + "xor", + "yield", + "__CLASS__", + "__DIR__", + "__FILE__", + "__FUNCTION__", + "__LINE__", + "__METHOD__", + "__NAMESPACE__", + "__TRAIT__") + .build(); +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiMethodDocView.java b/src/main/java/com/google/api/codegen/viewmodel/ApiMethodDocView.java new file mode 100644 index 0000000000..47adef5367 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiMethodDocView.java @@ -0,0 +1,51 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +import javax.annotation.Nullable; + +@AutoValue +public abstract class ApiMethodDocView { + + public abstract Iterable mainDocLines(); + + public abstract List paramDocs(); + + public abstract List throwsDocLines(); + + @Nullable + public abstract String returnTypeName(); + + public static Builder newBuilder() { + return new AutoValue_ApiMethodDocView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder mainDocLines(Iterable lines); + + public abstract Builder paramDocs(List docs); + + public abstract Builder throwsDocLines(List lines); + + public abstract Builder returnTypeName(String name); + + public abstract ApiMethodDocView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiMethodType.java b/src/main/java/com/google/api/codegen/viewmodel/ApiMethodType.java new file mode 100644 index 0000000000..4e2e6f741c --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiMethodType.java @@ -0,0 +1,29 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public enum ApiMethodType { + // Java + PagedFlattenedMethod, + PagedRequestObjectMethod, + PagedCallableMethod, + UnpagedListCallableMethod, + FlattenedMethod, + RequestObjectMethod, + CallableMethod, + // PHP + OptionalArrayMethod, + PagedOptionalArrayMethod +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiMethodView.java b/src/main/java/com/google/api/codegen/viewmodel/ApiMethodView.java new file mode 100644 index 0000000000..30ffadba5c --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiMethodView.java @@ -0,0 +1,17 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public interface ApiMethodView {} diff --git a/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java b/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java new file mode 100644 index 0000000000..92b2c7d7cd --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java @@ -0,0 +1,37 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class DynamicDefaultableParamView implements ParamView { + public abstract String name(); + + public abstract String defaultValue(); + + public static Builder newBuilder() { + return new AutoValue_DynamicDefaultableParamView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder name(String name); + + public abstract Builder defaultValue(String value); + + public abstract DynamicDefaultableParamView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java b/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java new file mode 100644 index 0000000000..af0f480c8a --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java @@ -0,0 +1,122 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.SnippetSetRunner; +import com.google.api.codegen.viewmodel.DynamicDefaultableParamView.Builder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class DynamicXApiView implements ViewModel { + public abstract String templateFileName(); + + public abstract String packageName(); + + public abstract String protoFilename(); + + public abstract ServiceDocView doc(); + + public abstract String name(); + + public abstract String serviceAddress(); + + public abstract Integer servicePort(); + + public abstract String serviceTitle(); + + public abstract Iterable authScopes(); + + public abstract List pathTemplates(); + + public abstract List formatResourceFunctions(); + + public abstract List parseResourceFunctions(); + + public abstract List pathTemplateGetterFunctions(); + + public abstract List pageStreamingDescriptors(); + + public abstract List methodKeys(); + + public abstract String clientConfigPath(); + + public abstract String interfaceKey(); + + public abstract String grpcClientTypeName(); + + public abstract List imports(); + + public abstract String outputPath(); + + public abstract List apiMethods(); + + @Override + public String resourceRoot() { + return SnippetSetRunner.SNIPPET_RESOURCE_ROOT; + } + + public static Builder newBuilder() { + return new AutoValue_DynamicXApiView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder templateFileName(String val); + + public abstract Builder packageName(String val); + + public abstract Builder protoFilename(String simpleName); + + public abstract Builder doc(ServiceDocView doc); + + public abstract Builder name(String val); + + public abstract Builder serviceAddress(String val); + + public abstract Builder servicePort(Integer val); + + public abstract Builder serviceTitle(String val); + + public abstract Builder authScopes(Iterable val); + + public abstract Builder pathTemplates(List val); + + public abstract Builder formatResourceFunctions(List val); + + public abstract Builder parseResourceFunctions(List val); + + public abstract Builder pathTemplateGetterFunctions(List val); + + public abstract Builder pageStreamingDescriptors(List val); + + public abstract Builder methodKeys(List val); + + public abstract Builder clientConfigPath(String val); + + public abstract Builder interfaceKey(String val); + + public abstract Builder grpcClientTypeName(String val); + + public abstract Builder imports(List val); + + public abstract Builder outputPath(String val); + + public abstract Builder apiMethods(List val); + + public abstract DynamicXApiView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java b/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java new file mode 100644 index 0000000000..6a8b6d81ec --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java @@ -0,0 +1,39 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.viewmodel.DynamicXApiView.Builder; +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class FieldSettingView { + + public abstract String fnSetFunctionCallName(); + + public abstract String identifier(); + + public static Builder newBuilder() { + return new AutoValue_FieldSettingView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder fnSetFunctionCallName(String val); + + public abstract Builder identifier(String val); + + public abstract FieldSettingView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java b/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java new file mode 100644 index 0000000000..c120dd6c33 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java @@ -0,0 +1,52 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.viewmodel.FieldSettingView.Builder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class FormatResourceFunctionView { + public abstract String entityName(); + + public abstract String name(); + + public abstract List resourceIdParams(); + + public abstract String pathTemplateName(); + + public abstract String pathTemplateGetterName(); + + public static Builder newBuilder() { + return new AutoValue_FormatResourceFunctionView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder entityName(String val); + + public abstract Builder name(String val); + + public abstract Builder resourceIdParams(List val); + + public abstract Builder pathTemplateName(String val); + + public abstract Builder pathTemplateGetterName(String val); + + public abstract FormatResourceFunctionView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/FormattedInitValueView.java b/src/main/java/com/google/api/codegen/viewmodel/FormattedInitValueView.java new file mode 100644 index 0000000000..48b96ed3ce --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/FormattedInitValueView.java @@ -0,0 +1,47 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class FormattedInitValueView implements InitValueView { + public abstract String apiWrapperName(); + + public abstract String formatFunctionName(); + + public abstract List formatArgs(); + + public String type() { + return FormattedInitValueView.class.getSimpleName(); + } + + public static Builder newBuilder() { + return new AutoValue_FormattedInitValueView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder apiWrapperName(String val); + + public abstract Builder formatFunctionName(String val); + + public abstract Builder formatArgs(List val); + + public abstract FormattedInitValueView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/InitCodeLineView.java b/src/main/java/com/google/api/codegen/viewmodel/InitCodeLineView.java new file mode 100644 index 0000000000..5f2a15829f --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/InitCodeLineView.java @@ -0,0 +1,17 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public interface InitCodeLineView {} diff --git a/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java b/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java new file mode 100644 index 0000000000..ac4a66f824 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java @@ -0,0 +1,40 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.viewmodel.FormattedInitValueView.Builder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class InitCodeView { + public abstract List lines(); + + public abstract List fieldSettings(); + + public static Builder newBuilder() { + return new AutoValue_InitCodeView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder lines(List val); + + public abstract Builder fieldSettings(List val); + + public abstract InitCodeView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/InitValueView.java b/src/main/java/com/google/api/codegen/viewmodel/InitValueView.java new file mode 100644 index 0000000000..8410b22b0d --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/InitValueView.java @@ -0,0 +1,17 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public interface InitValueView {} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java b/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java new file mode 100644 index 0000000000..1f87c9d850 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java @@ -0,0 +1,50 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.metacode.InitCodeLineType; +import com.google.api.codegen.viewmodel.InitCodeView.Builder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class ListInitCodeLineView implements InitCodeLineView { + + public abstract InitCodeLineType lineType(); + + public abstract String elementTypeName(); + + public abstract String identifier(); + + public abstract List elementIdentifiers(); + + public static Builder newBuilder() { + return new AutoValue_ListInitCodeLineView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder lineType(InitCodeLineType val); + + public abstract Builder elementTypeName(String val); + + public abstract Builder identifier(String val); + + public abstract Builder elementIdentifiers(List val); + + public abstract ListInitCodeLineView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/MapEntryView.java b/src/main/java/com/google/api/codegen/viewmodel/MapEntryView.java new file mode 100644 index 0000000000..0558bf8f8f --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/MapEntryView.java @@ -0,0 +1,37 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class MapEntryView { + public abstract String key(); + + public abstract String value(); + + public static Builder newBuilder() { + return new AutoValue_MapEntryView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder key(String key); + + public abstract Builder value(String value); + + public abstract MapEntryView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/MapInitCodeLineView.java b/src/main/java/com/google/api/codegen/viewmodel/MapInitCodeLineView.java new file mode 100644 index 0000000000..df81aa7f53 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/MapInitCodeLineView.java @@ -0,0 +1,52 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.metacode.InitCodeLineType; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class MapInitCodeLineView implements InitCodeLineView { + public abstract InitCodeLineType lineType(); + + public abstract String keyTypeName(); + + public abstract String valueTypeName(); + + public abstract String identifier(); + + public abstract List initEntries(); + + public static Builder newBuilder() { + return new AutoValue_MapInitCodeLineView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder lineType(InitCodeLineType val); + + public abstract Builder keyTypeName(String val); + + public abstract Builder valueTypeName(String val); + + public abstract Builder identifier(String val); + + public abstract Builder initEntries(List val); + + public abstract MapInitCodeLineView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/MapParamDocView.java b/src/main/java/com/google/api/codegen/viewmodel/MapParamDocView.java new file mode 100644 index 0000000000..7858c61456 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/MapParamDocView.java @@ -0,0 +1,55 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class MapParamDocView implements ParamDocView { + public abstract String paramName(); + + public abstract String typeName(); + + public abstract String firstLine(); + + public abstract List remainingLines(); + + public abstract List arrayKeyDocs(); + + public String type() { + return MapParamDocView.class.getSimpleName(); + } + + public static Builder newBuilder() { + return new AutoValue_MapParamDocView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder paramName(String val); + + public abstract Builder typeName(String val); + + public abstract Builder firstLine(String val); + + public abstract Builder remainingLines(List val); + + public abstract Builder arrayKeyDocs(List val); + + public abstract MapParamDocView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/OptionalArrayMethodView.java b/src/main/java/com/google/api/codegen/viewmodel/OptionalArrayMethodView.java new file mode 100644 index 0000000000..32ac7a5588 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/OptionalArrayMethodView.java @@ -0,0 +1,84 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class OptionalArrayMethodView implements ApiMethodView { + + public abstract ApiMethodType type(); + + public abstract String apiClassName(); + + public abstract String apiVariableName(); + + public abstract InitCodeView initCode(); + + public abstract ApiMethodDocView doc(); + + public abstract String name(); + + public abstract String requestTypeName(); + + public abstract String key(); + + public abstract String grpcMethodName(); + + public abstract List methodParams(); + + public abstract List requiredRequestObjectParams(); + + public abstract List optionalRequestObjectParams(); + + public abstract boolean hasReturnValue(); + + public static Builder newBuilder() { + return new AutoValue_OptionalArrayMethodView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder type(ApiMethodType val); + + public abstract Builder apiClassName(String val); + + public abstract Builder apiVariableName(String val); + + public abstract Builder initCode(InitCodeView val); + + public abstract Builder doc(ApiMethodDocView val); + + public abstract Builder name(String val); + + public abstract Builder requestTypeName(String val); + + public abstract Builder key(String val); + + public abstract Builder grpcMethodName(String val); + + public abstract Builder methodParams(List val); + + public abstract Builder requiredRequestObjectParams(List val); + + public abstract Builder optionalRequestObjectParams(List val); + + public abstract Builder hasReturnValue(boolean val); + + public abstract OptionalArrayMethodView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorView.java b/src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorView.java new file mode 100644 index 0000000000..90cb13d634 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorView.java @@ -0,0 +1,49 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class PageStreamingDescriptorView { + public abstract String varName(); + + public abstract String requestTokenFieldName(); + + public abstract String responseTokenFieldName(); + + public abstract String resourcesFieldName(); + + public abstract String methodName(); + + public static Builder newBuilder() { + return new AutoValue_PageStreamingDescriptorView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder varName(String val); + + public abstract Builder requestTokenFieldName(String val); + + public abstract Builder responseTokenFieldName(String val); + + public abstract Builder resourcesFieldName(String val); + + public abstract Builder methodName(String val); + + public abstract PageStreamingDescriptorView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ParamDocView.java b/src/main/java/com/google/api/codegen/viewmodel/ParamDocView.java new file mode 100644 index 0000000000..068c3d4efb --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ParamDocView.java @@ -0,0 +1,17 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public interface ParamDocView {} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ParamView.java b/src/main/java/com/google/api/codegen/viewmodel/ParamView.java new file mode 100644 index 0000000000..91e3757ef1 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ParamView.java @@ -0,0 +1,17 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public interface ParamView {} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ParseResourceFunctionView.java b/src/main/java/com/google/api/codegen/viewmodel/ParseResourceFunctionView.java new file mode 100644 index 0000000000..3d60b53678 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ParseResourceFunctionView.java @@ -0,0 +1,53 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class ParseResourceFunctionView { + public abstract String entityName(); + + public abstract String name(); + + public abstract String pathTemplateName(); + + public abstract String pathTemplateGetterName(); + + public abstract String entityNameParamName(); + + public abstract String outputResourceId(); + + public static Builder newBuilder() { + return new AutoValue_ParseResourceFunctionView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder entityName(String val); + + public abstract Builder name(String val); + + public abstract Builder pathTemplateName(String val); + + public abstract Builder pathTemplateGetterName(String val); + + public abstract Builder entityNameParamName(String val); + + public abstract Builder outputResourceId(String val); + + public abstract ParseResourceFunctionView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/PathTemplateGetterFunctionView.java b/src/main/java/com/google/api/codegen/viewmodel/PathTemplateGetterFunctionView.java new file mode 100644 index 0000000000..8806fb2dca --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/PathTemplateGetterFunctionView.java @@ -0,0 +1,42 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class PathTemplateGetterFunctionView { + + public abstract String name(); + + public abstract String pathTemplateName(); + + public abstract String pattern(); + + public static Builder newBuilder() { + return new AutoValue_PathTemplateGetterFunctionView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder name(String val); + + public abstract Builder pathTemplateName(String val); + + public abstract Builder pattern(String val); + + public abstract PathTemplateGetterFunctionView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/PathTemplateView.java b/src/main/java/com/google/api/codegen/viewmodel/PathTemplateView.java new file mode 100644 index 0000000000..25616f0a61 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/PathTemplateView.java @@ -0,0 +1,37 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class PathTemplateView { + public abstract String name(); + + public abstract String pattern(); + + public static Builder newBuilder() { + return new AutoValue_PathTemplateView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder name(String val); + + public abstract Builder pattern(String val); + + public abstract PathTemplateView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java b/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java new file mode 100644 index 0000000000..197d6448ed --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java @@ -0,0 +1,53 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class RequestObjectParamView implements ParamView { + public abstract String name(); + + public abstract String elementTypeName(); + + public abstract String typeName(); + + public abstract String setCallName(); + + public abstract boolean isMap(); + + public abstract boolean isArray(); + + public static Builder newBuilder() { + return new AutoValue_RequestObjectParamView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder name(String val); + + public abstract Builder elementTypeName(String val); + + public abstract Builder typeName(String val); + + public abstract Builder setCallName(String val); + + public abstract Builder isMap(boolean val); + + public abstract Builder isArray(boolean val); + + public abstract RequestObjectParamView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ResourceIdParamView.java b/src/main/java/com/google/api/codegen/viewmodel/ResourceIdParamView.java new file mode 100644 index 0000000000..0c8ae0d346 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ResourceIdParamView.java @@ -0,0 +1,37 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class ResourceIdParamView { + public abstract String name(); + + public abstract String templateKey(); + + public static Builder newBuilder() { + return new AutoValue_ResourceIdParamView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder name(String val); + + public abstract Builder templateKey(String val); + + public abstract ResourceIdParamView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java b/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java new file mode 100644 index 0000000000..6900617279 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java @@ -0,0 +1,47 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.viewmodel.ApiMethodDocView.Builder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +import javax.annotation.Nullable; + +@AutoValue +public abstract class ServiceDocView { + + public abstract String firstLine(); + + public abstract List remainingLines(); + + public abstract ApiMethodView exampleApiMethod(); + + public static Builder newBuilder() { + return new AutoValue_ServiceDocView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder firstLine(String val); + + public abstract Builder remainingLines(List val); + + public abstract Builder exampleApiMethod(ApiMethodView val); + + public abstract ServiceDocView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/SimpleInitCodeLineView.java b/src/main/java/com/google/api/codegen/viewmodel/SimpleInitCodeLineView.java new file mode 100644 index 0000000000..3c76b784fc --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/SimpleInitCodeLineView.java @@ -0,0 +1,47 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.metacode.InitCodeLineType; +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class SimpleInitCodeLineView implements InitCodeLineView { + + public abstract InitCodeLineType lineType(); + + public abstract String typeName(); + + public abstract String identifier(); + + public abstract InitValueView initValue(); + + public static Builder newBuilder() { + return new AutoValue_SimpleInitCodeLineView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder lineType(InitCodeLineType val); + + public abstract Builder typeName(String val); + + public abstract Builder identifier(String val); + + public abstract Builder initValue(InitValueView val); + + public abstract SimpleInitCodeLineView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/SimpleInitValueView.java b/src/main/java/com/google/api/codegen/viewmodel/SimpleInitValueView.java new file mode 100644 index 0000000000..f551fa8c2c --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/SimpleInitValueView.java @@ -0,0 +1,38 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class SimpleInitValueView implements InitValueView { + + public abstract String initialValue(); + + public String type() { + return SimpleInitValueView.class.getSimpleName(); + } + + public static Builder newBuilder() { + return new AutoValue_SimpleInitValueView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder initialValue(String val); + + public abstract SimpleInitValueView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/SimpleParamDocView.java b/src/main/java/com/google/api/codegen/viewmodel/SimpleParamDocView.java new file mode 100644 index 0000000000..08adcec9c2 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/SimpleParamDocView.java @@ -0,0 +1,51 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class SimpleParamDocView implements ParamDocView { + public abstract String paramName(); + + public abstract String typeName(); + + public abstract String firstLine(); + + public abstract List remainingLines(); + + public String type() { + return SimpleParamDocView.class.getSimpleName(); + } + + public static Builder newBuilder() { + return new AutoValue_SimpleParamDocView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder paramName(String val); + + public abstract Builder typeName(String val); + + public abstract Builder firstLine(String val); + + public abstract Builder remainingLines(List val); + + public abstract SimpleParamDocView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StructureInitCodeLineView.java b/src/main/java/com/google/api/codegen/viewmodel/StructureInitCodeLineView.java new file mode 100644 index 0000000000..389226c681 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/StructureInitCodeLineView.java @@ -0,0 +1,52 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.metacode.InitCodeLineType; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class StructureInitCodeLineView implements InitCodeLineView { + public abstract InitCodeLineType lineType(); + + public abstract String typeName(); + + public abstract String identifier(); + + public abstract List fieldSettings(); + + public abstract InitValueView initValue(); + + public static Builder newBuilder() { + return new AutoValue_StructureInitCodeLineView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder lineType(InitCodeLineType val); + + public abstract Builder typeName(String val); + + public abstract Builder identifier(String val); + + public abstract Builder fieldSettings(List val); + + public abstract Builder initValue(InitValueView val); + + public abstract StructureInitCodeLineView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ViewModel.java b/src/main/java/com/google/api/codegen/viewmodel/ViewModel.java new file mode 100644 index 0000000000..fb5bff0cca --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ViewModel.java @@ -0,0 +1,28 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +/** + * Represents a node of a view model that can be rendered by a template + * engine. + */ +public interface ViewModel { + + String resourceRoot(); + + String templateFileName(); + + String outputPath(); +} diff --git a/src/main/resources/com/google/api/codegen/java/method_sample.snip b/src/main/resources/com/google/api/codegen/java/method_sample.snip index c2d955f5ed..990411f966 100644 --- a/src/main/resources/com/google/api/codegen/java/method_sample.snip +++ b/src/main/resources/com/google/api/codegen/java/method_sample.snip @@ -74,7 +74,7 @@ @private initLineStructure(line) {@context.typeName(line.getType)} {@formattedIdentifier(line)} = {@context.typeName(line.getType)}.newBuilder() @join fieldSetting : line.getFieldSettings - @let setCallName = setCallName(fieldSetting.getType, context.lowerUnderscoreToUpperCamel(fieldSetting.getFieldName)) + @let setCallName = setCallName(fieldSetting.getType, fieldSetting.getFieldName.toUpperCamel) {@EMPTY} .{@setCallName}({@formattedIdentifier(fieldSetting)}) @end @end @@ -91,7 +91,7 @@ Map<{@context.basicTypeNameBoxed(line.getKeyType)}, {@context.basicTypeNameBoxed(line.getValueType)}> {@formattedIdentifier(line)} = new HashMap<>(); @join key : line.getElementIdentifierKeys vertical @let identifierValue = line.getElementIdentifierValue(key) - {@formattedIdentifier(line)}.put({@context.renderPrimitiveValue(line.getKeyType, key)}, {@context.lowerUnderscoreToLowerCamel(identifierValue)}); + {@formattedIdentifier(line)}.put({@context.renderPrimitiveValue(line.getKeyType, key)}, {@identifierValue.toLowerCamel}); @end @end @end @@ -99,7 +99,7 @@ # Helper method for initLineList() @private initList(line) @join identifier : line.getElementIdentifiers on ", " - {@context.lowerUnderscoreToLowerCamel(identifier)} + {@identifier.toLowerCamel} @end @end @@ -111,9 +111,9 @@ # Properly format an identifier for this language @private formattedIdentifier(lineOrFieldSetting) @if lineOrFieldSetting.getInitValueConfig.hasFormattingConfig - formatted{@context.lowerUnderscoreToUpperCamel(lineOrFieldSetting.getIdentifier)} + formatted{@lineOrFieldSetting.getIdentifier.toUpperCamel} @else - {@context.lowerUnderscoreToLowerCamel(lineOrFieldSetting.getIdentifier)} + {@lineOrFieldSetting.getIdentifier.toLowerCamel} @end @end diff --git a/src/main/resources/com/google/api/codegen/php/main.snip b/src/main/resources/com/google/api/codegen/php/main.snip index 902c6a55bf..63be79957d 100644 --- a/src/main/resources/com/google/api/codegen/php/main.snip +++ b/src/main/resources/com/google/api/codegen/php/main.snip @@ -1,23 +1,30 @@ -@extends "common.snip" +@extends "php/mvvm_common.snip" @extends "php/method_sample.snip" -@snippet generateFilename(service) - {@context.getApiWrapperName(service)}.php -@end - -@snippet generateClass(service, body, imports) +@snippet generate(xapiClass) '{@pageStreaming.getRequestTokenField.getSimpleName}', - 'responsePageTokenField' => '{@pageStreaming.getResponseTokenField.getSimpleName}', - 'resourceField' => '{@pageStreaming.getResourcesField.getSimpleName}', - ]); - @end - @end - - $pageStreamingDescriptors = [ - @join method : context.messages.filterPageStreamingMethods(interfaceConfig, service.getMethods) - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName) - '{@methodName}' => ${@methodName}PageStreamingDescriptor, - @end - @end - ]; - - return $pageStreamingDescriptors; - } +@private staticFunctions(xapiClass) + @join function : xapiClass.formatResourceFunctions + {@formatResourceFunction(function)} @end -@end - -@private resourceFunctions(service) - @join collectionConfig : context.getApiConfig.getInterfaceConfig(service).getCollectionConfigs() - {@formatResourceFunction(collectionConfig)} + {@""} + @join function : xapiClass.parseResourceFunctions + {@parseResourceFunction(function)} @end - - @join collectionConfig : context.getApiConfig.getInterfaceConfig(service).getCollectionConfigs() - {@parseResourceFunction(collectionConfig)} - @end - - @join collectionConfig : context.getApiConfig.getInterfaceConfig(service).getCollectionConfigs() - {@pathTemplateFunction(collectionConfig)} + {@""} + @join function : xapiClass.pathTemplateGetterFunctions + {@pathTemplateGetterFunction(function)} @end + {@""} + {@pageStreamingDescriptorFunction(xapiClass)} @end -@private formatResourceFunction(collectionConfig) +@private formatResourceFunction(function) /** * Formats a string containing the fully-qualified path to represent - * a {@collectionConfig.getEntityName} resource. + * a {@function.entityName} resource. */ - public static function {@formatResourceFunctionName(collectionConfig)}(\ - {@formatResourceFunctionParams(collectionConfig)}) + public static function {@function.name}(\ + {@formatResourceFunctionParams(function.resourceIdParams)}) { - return self::{@pathTemplateFunctionName(collectionConfig)}()->render([ - {@pathTemplateArgs(collectionConfig)}, + return self::{@function.pathTemplateGetterName}()->render([ + {@pathTemplateArgs(function.resourceIdParams)}, ]); } - + {@""} @end -@private formatResourceFunctionName(collectionConfig) - format{@resourceName(collectionConfig)} +@private formatResourceFunctionParams(resourceIdParams) + @join param : resourceIdParams on ", " + ${@param.name} + @end @end -@private formatResourceFunctionParams(collectionConfig) - @join param : collectionConfig.getNameTemplate.vars() on ", " - ${@context.lowerUnderscoreToLowerCamel(param)} +@private pathTemplateArgs(resourceIdParams) + @join param : resourceIdParams on ",".add(BREAK) + '{@param.templateKey}' => ${@param.name} @end @end -@private pathTemplateArgs(collectionConfig) - @join param : collectionConfig.getNameTemplate.vars() vertical on ", " - '{@param}' => ${@context.lowerUnderscoreToLowerCamel(param)} - @end +@private parseResourceFunction(function) + /** + * Parses the {@function.outputResourceId} from the given fully-qualified path which + * represents a {@function.entityName} resource. + */ + public static function {@function.name}(${@function.entityNameParamName}) + { + return self::{@function.pathTemplateGetterName}()\ + ->match(${@function.entityNameParamName})['{@function.outputResourceId}']; + } + {@""} @end -@private parseResourceFunction(collectionConfig) - @join subField : collectionConfig.getNameTemplate.vars() - @let fieldPath = context.upperCamelToLowerCamel(resourceName(collectionConfig)) - /** - * Parses the {@subField} from the given fully-qualified path which - * represents a {@context.lowerUnderscoreToLowerCamel(collectionConfig.getEntityName)} resource. - */ - public static function \ - parse{@context.lowerUnderscoreToUpperCamel(subField)}From{@resourceName(collectionConfig)}(\ - ${@fieldPath}) - { - return self::{@pathTemplateFunctionName(collectionConfig)}()->match(${@fieldPath})['{@subField}']; - } +@private pathTemplateGetterFunction(function) + private static function {@function.name}() + { + if (self::${@function.pathTemplateName} == null) { + self::${@function.pathTemplateName} = new PathTemplate('{@function.pattern}'); + } - @end - @end + return self::${@function.pathTemplateName}; + } + {@""} @end -@private resourceName(collectionConfig) - {@context.lowerUnderscoreToUpperCamel(collectionConfig.getEntityName)}Name +@private pageStreamingDescriptorFunction(xapiClass) + private static function getPageStreamingDescriptors() + { + @join descriptor : xapiClass.pageStreamingDescriptors + ${@descriptor.varName} = + new PageStreamingDescriptor([ + 'requestPageTokenField' => '{@descriptor.requestTokenFieldName}', + 'responsePageTokenField' => '{@descriptor.responseTokenFieldName}', + 'resourceField' => '{@descriptor.resourcesFieldName}', + ]); + @end + + $pageStreamingDescriptors = [ + @join descriptor : xapiClass.pageStreamingDescriptors + '{@descriptor.methodName}' => ${@descriptor.varName}, + @end + ]; + + return $pageStreamingDescriptors; + } + {@""} @end -@private pathTemplateFunction(collectionConfig) - private static function {@pathTemplateFunctionName(collectionConfig)}() +@private constructor(xapiClass) + // TODO(garrettjones): add channel (when supported in gRPC) + /** + * Constructor. + * + * @@param array $options { + * Optional. Options for configuring the service API wrapper. + * + * @@var string $serviceAddress The domain name of the API remote host. + * Default '{@xapiClass.serviceAddress}'. + * @@var mixed $port The port on which to connect to the remote host. Default {@xapiClass.servicePort}. + * @@var Grpc\ChannelCredentials $sslCreds + * A `ChannelCredentials` for use with an SSL-enabled channel. + * Default: a credentials object returned from + * Grpc\ChannelCredentials::createSsl() + * @@var array $scopes A string array of scopes to use when acquiring credentials. + * Default the scopes for the {@xapiClass.serviceTitle}. + * @@var array $retryingOverride + * An associative array of string => RetryOptions, where the keys + * are method names (e.g. 'createFoo'), that overrides default retrying + * settings. A value of null indicates that the method in question should + * not retry. + * @@var int $timeoutMillis The timeout in milliseconds to use for calls + * that don't use retries. For calls that use retries, + * set the timeout in RetryOptions. + * Default: 30000 (30 seconds) + * @@var string $appName The codename of the calling service. Default 'gax'. + * @@var string $appVersion The version of the calling service. + * Default: the current version of GAX. + * } + */ + public function __construct($options = []) { - if (self::${@pathTemplateConstantName(collectionConfig)} == null) { - self::${@pathTemplateConstantName(collectionConfig)} = new PathTemplate('{@collectionConfig.getNamePattern}'); + $defaultScopes = [ + @join scope : {@xapiClass.authScopes} + '{@scope}', + @end + ]; + $defaultOptions = [ + 'serviceAddress' => self::SERVICE_ADDRESS, + 'port' => self::DEFAULT_SERVICE_PORT, + 'scopes' => $defaultScopes, + 'retryingOverride' => null, + 'timeoutMillis' => self::DEFAULT_TIMEOUT_MILLIS, + 'appName' => 'gax', + 'appVersion' => self::_GAX_VERSION, + ]; + $options = array_merge($defaultOptions, $options); + + $headerDescriptor = new AgentHeaderDescriptor([ + 'clientName' => $options['appName'], + 'clientVersion' => $options['appVersion'], + 'codeGenName' => self::_CODEGEN_NAME, + 'codeGenVersion' => self::_CODEGEN_VERSION, + 'gaxVersion' => self::_GAX_VERSION, + 'phpVersion' => phpversion(), + ]); + + $defaultDescriptors = ['headerDescriptor' => $headerDescriptor]; + $this->descriptors = [ + @join methodKey : xapiClass.methodKeys + '{@methodKey}' => $defaultDescriptors, + @end + ]; + $pageStreamingDescriptors = self::getPageStreamingDescriptors(); + foreach ($pageStreamingDescriptors as $method => $pageStreamingDescriptor) { + $this->descriptors[$method]['pageStreamingDescriptor'] = $pageStreamingDescriptor; } - return self::${@pathTemplateConstantName(collectionConfig)}; + // TODO load the client config in a more package-friendly way + $clientConfigJsonString = file_get_contents('{@xapiClass.clientConfigPath}'); + $clientConfig = json_decode($clientConfigJsonString, true); + $this->defaultCallSettings = + CallSettings::load('{@xapiClass.interfaceKey}', + $clientConfig, + $options['retryingOverride'], + GrpcConstants::getStatusCodeNames(), + $options['timeoutMillis']); + + $this->scopes = $options['scopes']; + + $generatedCreateStub = function ($hostname, $opts) { + return new {@xapiClass.grpcClientTypeName}($hostname, $opts); + }; + $createStubOptions = []; + if (!empty($options['sslCreds'])) { + $createStubOptions['sslCreds'] = $options['sslCreds']; + } + $this->grpcBootstrap = GrpcBootstrap::defaultInstance(); + $this->stub = $this->grpcBootstrap->createStub( + $generatedCreateStub, + $options['serviceAddress'], + $options['port'], + $createStubOptions); } - + {@""} @end -@private constructor(service) - @let className = context.getApiWrapperName(service), \ - jsonBaseName = {@context.upperCamelToLowerUnderscore(service.getSimpleName)}, \ - grpcClientName = context.getGrpcClientName(service) - // TODO(garrettjones): add channel (when supported in gRPC) - /** - * Constructor. - * - * @@param array $options { - * Optional. Options for configuring the service API wrapper. - * - * @@var string $serviceAddress The domain name of the API remote host. - * Default '{@context.getServiceConfig.getServiceAddress(service)}'. - * @@var mixed $port The port on which to connect to the remote host. Default {@context.getServiceConfig.getServicePort()}. - * @@var Grpc\ChannelCredentials $sslCreds - * A `ChannelCredentials` for use with an SSL-enabled channel. - * Default: a credentials object returned from - * Grpc\ChannelCredentials::createSsl() - * @@var array $scopes A string array of scopes to use when acquiring credentials. - * Default the scopes for the {@context.getServiceConfig.getTitle(service)}. - * @@var array $retryingOverride - * An associative array of string => RetryOptions, where the keys - * are method names (e.g. 'createFoo'), that overrides default retrying - * settings. A value of null indicates that the method in question should - * not retry. - * @@var int $timeoutMillis The timeout in milliseconds to use for calls - * that don't use retries. For calls that use retries, - * set the timeout in RetryOptions. - * Default: 30000 (30 seconds) - * @@var string $appName The codename of the calling service. Default 'gax'. - * @@var string $appVersion The version of the calling service. - * Default: the current version of GAX. - * } - */ - public function __construct($options = []) +@private apiMethods(xapiClass) + @join apiMethod : xapiClass.apiMethods + @let coreSampleCode = sampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + public function {@apiMethod.name}({@paramList(apiMethod.methodParams)}) { - $defaultScopes = [ - @join scope : context.getServiceConfig.getAuthScopes(service) - '{@scope}', - @end - ]; - $defaultOptions = [ - 'serviceAddress' => self::SERVICE_ADDRESS, - 'port' => self::DEFAULT_SERVICE_PORT, - 'scopes' => $defaultScopes, - 'retryingOverride' => null, - 'timeoutMillis' => self::DEFAULT_TIMEOUT_MILLIS, - 'appName' => 'gax', - 'appVersion' => self::_GAX_VERSION, - ]; - $options = array_merge($defaultOptions, $options); - - $headerDescriptor = new AgentHeaderDescriptor([ - 'clientName' => $options['appName'], - 'clientVersion' => $options['appVersion'], - 'codeGenName' => self::_CODEGEN_NAME, - 'codeGenVersion' => self::_CODEGEN_VERSION, - 'gaxVersion' => self::_GAX_VERSION, - 'phpVersion' => phpversion(), - ]); - - $defaultDescriptors = ['headerDescriptor' => $headerDescriptor]; - $this->descriptors = [ - @join method : service.getMethods - '{@context.upperCamelToLowerCamel(method.getSimpleName)}' => $defaultDescriptors, - @end - ]; - $pageStreamingDescriptors = self::getPageStreamingDescriptors(); - foreach ($pageStreamingDescriptors as $method => $pageStreamingDescriptor) { - $this->descriptors[$method]['pageStreamingDescriptor'] = $pageStreamingDescriptor; - } + $request = new {@apiMethod.requestTypeName}(); + @join param : apiMethod.requiredRequestObjectParams + {@setRequiredFieldCall(param)} + @end + @join param : apiMethod.optionalRequestObjectParams + {@setOptionalFieldCall(param)} + @end - // TODO load the client config in a more package-friendly way - $clientConfigJsonString = file_get_contents('./resources/{@jsonBaseName}_client_config.json'); - $clientConfig = json_decode($clientConfigJsonString, true); - $this->defaultCallSettings = - CallSettings::load('{@context.getServiceName(service)}', - $clientConfig, - $options['retryingOverride'], - GrpcConstants::getStatusCodeNames(), - $options['timeoutMillis']); - - $this->scopes = $options['scopes']; - - $generatedCreateStub = function ($hostname, $opts) { - return new {@grpcClientName}($hostname, $opts); - }; - $createStubOptions = []; - if (!empty($options['sslCreds'])) { - $createStubOptions['sslCreds'] = $options['sslCreds']; - } - $this->grpcBootstrap = GrpcBootstrap::defaultInstance(); - $this->stub = $this->grpcBootstrap->createStub( - $generatedCreateStub, - $options['serviceAddress'], - $options['port'], - $createStubOptions); - } - @end -@end + $mergedSettings = $this->defaultCallSettings['{@apiMethod.key}']->merge( + new CallSettings($callSettings)); + $callable = ApiCallable::createApiCall( + $this->stub, '{@apiMethod.grpcMethodName}', $mergedSettings, $this->descriptors['{@apiMethod.key}']); -@private apiMethods(service) - @join method : service.getMethods on BREAK.add(BREAK) - @let callableConstant = context.upperCamelToUpperUnderscore(method.getSimpleName), \ - methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - inTypeName = context.typeName(method.getInputType), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - requiredFields = methodConfig.getRequiredFields(), \ - optionalFields = methodConfig.getOptionalFields() - {@methodDoc(service, method)} - public function {@methodName}({@apiMethodParams(requiredFields)}{@commonParams(requiredFields)}) - { - {@requestObjectCreation(inTypeName, requiredFields, optionalFields)} - - $mergedSettings = $this->defaultCallSettings['{@methodName}']->merge( - new CallSettings($callSettings)); - $callable = ApiCallable::createApiCall( - $this->stub, '{@method.getSimpleName}', $mergedSettings, $this->descriptors['{@methodName}']); - - return $callable( - $request, - [], - ['call_credentials_callback' => $this->createCredentialsCallback()]); - } - @end + return $callable( + $request, + [], + ['call_credentials_callback' => $this->createCredentialsCallback()]); + } + {@""} @end @end -@private apiMethodParams(requiredFields) - @join field : requiredFields on ", " - @let paramName = context.lowerUnderscoreToLowerCamel(field.getSimpleName) - ${@paramName} +@private paramList(params) + @join param : params on ", " + @if param.defaultValue + ${@param.name} = {@param.defaultValue} + @else + ${@param.name} @end @end @end -@private commonParams(requiredFields) - @if requiredFields - , $optionalArgs = [], $callSettings = [] +@private setRequiredFieldCall(param) + @if param.isMap + foreach (${@param.name} as $key => $value) { + $request->{@param.setCallName}((new {@param.elementTypeName}())->setKey($key)->setValue($value)); + } @else - $optionalArgs = [], $callSettings = [] - @end -@end - -@private requestObjectCreation(inTypeName, requiredFields, optionalFields) - $request = new {@inTypeName}(); - @join field : requiredFields - {@setRequiredFieldCall(field)} - @end - @join field : optionalFields - {@setOptionalFieldCall(field)} + @if param.isArray + foreach (${@param.name} as $elem) { + $request->{@param.setCallName}($elem); + } + @else + $request->{@param.setCallName}(${@param.name}); + @end @end @end -@private setRequiredFieldCall(field) - @let paramUpperCamel = context.lowerUnderscoreToUpperCamel(field.getSimpleName), \ - paramLowerCamel = context.lowerUnderscoreToLowerCamel(field.getSimpleName) - @if field.getType.isMap - @let fullyQualifiedEntryName = context.fullyQualifiedName(field.getType), \ - entryName = context.getTypeName(fullyQualifiedEntryName) - foreach (${@paramLowerCamel} as $key => $value) { - $request->add{@paramUpperCamel}((new {@entryName}())->setKey($key)->setValue($value)); - } - @end +@private setOptionalFieldCall(param) + if (isset($optionalArgs['{@param.name}'])) { + @if param.isMap + // TODO make this work + putAll... @else - @if field.isRepeated - foreach (${@paramLowerCamel} as $elem) { - $request->add{@paramUpperCamel}($elem); + @if param.isArray + foreach ($optionalArgs['{@param.name}'] as $elem) { + $request->{@param.setCallName}($elem); } @else - $request->set{@paramUpperCamel}(${@paramLowerCamel}); + $request->{@param.setCallName}($optionalArgs['{@param.name}']); @end @end - @end -@end - -@private setOptionalFieldCall(field) - @let paramUpperCamel = context.lowerUnderscoreToUpperCamel(field.getSimpleName), \ - paramLowerCamel = context.lowerUnderscoreToLowerCamel(field.getSimpleName) - if (isset($optionalArgs['{@paramLowerCamel}'])) { - @if field.getType.isMap - // TODO make this work - putAll... - @else - @if field.isRepeated - foreach ($optionalArgs['{@paramLowerCamel}'] as $elem) { - $request->add{@paramUpperCamel}($elem); - } - @else - $request->set{@paramUpperCamel}($optionalArgs['{@paramLowerCamel}']); - @end - @end - } - @end + } @end -@private methodDoc(service, method) +@private methodDoc(apiMethodDoc, methodSampleCode) /** - {@docLinesFromStr(context.getDescription(method))} + @join commentLine : apiMethodDoc.mainDocLines + {@""} * {@commentLine} + @end * * Sample code: * ``` - {@createMethodSampleDoc(service, method)} + @join sampleLine : util.getDocLines(methodSampleCode) + {@""} * {@sampleLine} + @end * ``` - {@requiredArgsDoc(service, method)} - {@optionalArgsDoc(service, method)} - * @@param array $callSettings { - * Optional. - * @@var Google\GAX\RetrySettings $retrySettings - * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @@var int $timeoutMillis - * Timeout to use for this call. Only used if $retrySettings - * is not set. - * } - {@docReturnLine(service, method)} - * @@throws Google\GAX\ApiException if the remote call fails - */ -@end - -@private createMethodSampleDoc(service, method) - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - ApiName = context.getApiWrapperName(service), \ - apiName = context.upperCamelToLowerCamel(ApiName), \ - methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - requiredFields = methodConfig.getRequiredFields() - {@docLinesFromStr(methodSampleDoc(context.newPhpDocConfigBuilder()\ - .setApiName(ApiName) \ - .setMethodName(methodName) \ - .setFieldInitCode(context, service, method, requiredFields) \ - .setPagedVariant(methodConfig.isPageStreaming) \ - .setReturnType(context.returnTypeOrEmpty(method.getOutputType)) \ - .build()))} + @if apiMethodDoc.paramDocs + {@""} * + @join doc : apiMethodDoc.paramDocs + {@paramDoc(doc)} + @end @end -@end - -@snippet docLinesFromStr(str) - @join commentLine : context.php.getDocLines(str) - {@commentLine} + @if apiMethodDoc.returnTypeName + {@""} * + * @@return {@apiMethodDoc.returnTypeName} @end + * + * @@throws Google\GAX\ApiException if the remote call fails + */ + {@""} @end -@private requiredArgsDoc(service, method) - {@""} * - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method) - @join param : methodConfig.getRequiredFields() - @join commentLine : context.php.getDocLinesWithPrefix(context.getDescription(param), requiredParamDocLinePrefix(param)) - {@commentLine} - @end - @end +@private paramDoc(doc) + @switch doc.type + @case "SimpleParamDocView" + {@simpleParamDoc(doc)} + @case "MapParamDocView" + {@mapParamDoc(doc)} + @default + $unhandledCase: {@doc.type}$ @end @end -@private requiredParamDocLinePrefix(param) - @@param {@context.typeName(param.getType)} ${@context.lowerUnderscoreToLowerCamel(param.getSimpleName)} {@""} -@end - -@private optionalArgsDoc(service, method) - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - optionalFields = methodConfig.getOptionalFields() - @if optionalFields - {@""} * @@param array $optionalArgs { - * Optional. - @join param : optionalFields - @if isPageSizeField(param, methodConfig) - {@""} * @@var int ${@context.lowerUnderscoreToLowerCamel(methodConfig.getPageStreaming.getPageSizeField.getSimpleName)} - * The maximum number of resources contained in the underlying API - * response. If page streaming is performed per-resource, this - * parameter does not affect the return value. If page streaming is - * performed per-page, this determines the maximum number of - * resources in a page. - @else - @join commentLine : context.php.getDocLinesWithPrefixes(context.getDescription(param), optionalParamDocLinePrefix(param), " ") - {@commentLine} - @end - @end - @end - * } - @else - {@""} * @@param array $optionalArgs { - * Optional. There are no optional parameters for this method yet; - * this $optionalArgs parameter reserves a spot for future ones. - * } +@private simpleParamDoc(doc) + {@""} * @@param {@doc.typeName} ${@doc.paramName} {@doc.firstLine} + @if doc.remainingLines + @join commentLine : doc.remainingLines + {@""} * {@commentLine} @end @end @end -@private isPageSizeField(param, methodConfig) - @if methodConfig.isPageStreaming - @if methodConfig.getPageStreaming.hasPageSizeField - @if param.equals(methodConfig.getPageStreaming.getPageSizeField) - TRUE - @end +@private mapParamDoc(doc) + {@""} * @@param {@doc.typeName} ${@doc.paramName} { + * {@doc.firstLine} + @if doc.remainingLines + @join commentLine : doc.remainingLines + {@""} * {@commentLine} @end @end -@end - -@private optionalParamDocLinePrefix(param) - {@""} @@var {@context.typeName(param.getType)} ${@context.lowerUnderscoreToLowerCamel(param.getSimpleName)} {@""} -@end - -@private docReturnLine(service, method) - @let qualifiedOutTypeName = context.fullyQualifiedName(method.getOutputType), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - isPageStreaming = methodConfig.isPageStreaming - @if not(context.messages.isEmptyType(method.getOutputType)) - {@""} * - @if isPageStreaming - {@""} * @@return Google\GAX\PageAccessor - @else - {@""} * @@return {@qualifiedOutTypeName} + @if doc.arrayKeyDocs + @join simpleParamDoc : doc.arrayKeyDocs + {@""} * @@var {@simpleParamDoc.typeName} ${@simpleParamDoc.paramName} + * {@simpleParamDoc.firstLine} + @if simpleParamDoc.remainingLines + @join commentLine : simpleParamDoc.remainingLines + {@""} * {@commentLine} + @end @end - @end @end - * + * } @end @private cleanupSection() diff --git a/src/main/resources/com/google/api/codegen/php/method_sample.snip b/src/main/resources/com/google/api/codegen/php/method_sample.snip index fff9f1badf..d689a4cb3c 100644 --- a/src/main/resources/com/google/api/codegen/php/method_sample.snip +++ b/src/main/resources/com/google/api/codegen/php/method_sample.snip @@ -1,153 +1,108 @@ -@snippet methodSampleDoc(docConfig) - @let ApiName = docConfig.getApiName, \ - apiName = context.upperCamelToLowerCamel(ApiName), \ - methodName = docConfig.getMethodName(), \ - returnType = docConfig.getReturnType(), \ - initCodeSpec = docConfig.getInitCode() - try { - ${@apiName} = new {@ApiName}(); - {@initCode(initCodeSpec)} - @if docConfig.isPagedVariant() - foreach ({@methodCallSampleCode(methodName, apiName, initCodeSpec)} as $element) { - // doThingsWith(element); - } - @else - @if returnType - $response = {@methodCallSampleCode(methodName, apiName, initCodeSpec)}; - @else - {@methodCallSampleCode(methodName, apiName, initCodeSpec)}; - @end - @end - } finally { - if (isset(${@apiName})) { - ${@apiName}->close(); - } +@extends "php/mvvm_common.snip" + +@snippet decorateSampleCode(apiMethod, coreSampleCode) + try { + ${@apiMethod.apiVariableName} = new {@apiMethod.apiClassName}(); + {@initCode(apiMethod.initCode)} + {@coreSampleCode} + } finally { + if (isset(${@apiMethod.apiVariableName})) { + ${@apiMethod.apiVariableName}->close(); } - @end -@end - -@private methodCallSampleCode(methodName, apiName, initCodeSpec) - ${@apiName}->{@methodName}({@argList(initCodeSpec.getArgFields)}) + } @end -@private initCode(initCodeSpec) - @join line : initCodeSpec.getLines() - @switch line.getLineType.toString() - @case "StructureInitLine" - {@initLineStructure(line)} - @case "ListInitLine" - {@initLineList(line)} - @case "SimpleInitLine" - {@initLineSimple(line)} - @case "MapInitLine" - {@initLineMap(initCodeSpec, line)} +@snippet sampleCode(apiMethod) + @switch apiMethod.type.toString + @case "OptionalArrayMethod" + {@optionalArrayMethodSampleCode(apiMethod)} + @case "PagedOptionalArrayMethod" + {@pagedOptionalArrayMethodSampleCode(apiMethod)} @default - {@unhandledCase()} + $unhandledCase: {@apiMethod.type.toString}$ @end - @end @end -@private initLineStructure(line) - {@formattedIdentifier(line)} = new {@context.typeName(line.getType)}(); - @join fieldSetting : line.getFieldSettings - @let setCallName = setCallName(fieldSetting) - {@formattedIdentifier(line)}->{@setCallName}({@formattedIdentifier(fieldSetting)}); +@private optionalArrayMethodSampleCode(apiMethod) + @if apiMethod.hasReturnValue + $response = {@methodCallSampleCode(apiMethod)}; + @else + {@methodCallSampleCode(apiMethod)}; @end - @end @end -@private initLineList(line) - {@formattedIdentifier(line)} = [{@initList(line)}]; +@private pagedOptionalArrayMethodSampleCode(apiMethod) + foreach ({@methodCallSampleCode(apiMethod)} as $element) { + // doThingsWith(element); + } @end -@private initList(line) - @join identifier : line.getElementIdentifiers on ", " - {@unformattedIdentifier(identifier)} - @end +@private methodCallSampleCode(apiMethod) + ${@apiMethod.apiVariableName}->{@apiMethod.name}(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) @end -@private initLineMap(initCodeSpec, line) - @if context.initLineIsParameter(initCodeSpec, line) - {@formattedIdentifier(line)} = [{@initMap(line)}]; - @else - {@formattedIdentifier(line)} = []; - @join key : line.getElementIdentifierKeys vertical - @let identifierValue = line.getElementIdentifierValue(key),\ - entryIdentifier = getEntryIdentifier(line), \ - fullyQualifiedEntryName = context.fullyQualifiedName(line.getElementType), \ - entryName = context.getTypeName(fullyQualifiedEntryName) - {@entryIdentifier} = new {@entryName}(); - {@entryIdentifier}->setKey({@context.renderPrimitiveValue(line.getKeyType, key)}); - {@entryIdentifier}->setValue({@unformattedIdentifier(identifierValue)}); - array_push({@formattedIdentifier(line)}, {@entryIdentifier}); - @end +@private sampleMethodCallArgList(fieldSettings) + @join fieldSetting : fieldSettings on ", " + ${@fieldSetting.identifier} @end - @end @end -@private initMap(line) - @join key : line.getElementIdentifierKeys vertical - @let identifierValue = line.getElementIdentifierValue(key),\ - entryIdentifier = getEntryIdentifier(line) - {@context.renderPrimitiveValue(line.getKeyType, key)} => {@unformattedIdentifier(identifierValue)}, +@private initCode(initCodeSpec) + @join line : initCodeSpec.lines + @switch line.lineType.toString + @case "StructureInitLine" + {@initLineStructure(line)} + @case "ListInitLine" + {@initLineList(line)} + @case "MapInitLine" + {@initLineMap(line)} + @case "SimpleInitLine" + {@initLineSimple(line)} + @default + $unhandledCase: {@line.lineType.toString}$ + @end @end - @end -@end - -@private initLineSimple(line) - {@formattedIdentifier(line)} = {@initValue(line)}; @end -@private getEntryIdentifier(lineOrFieldSetting) - {@unformattedIdentifier(lineOrFieldSetting.getIdentifier)}Entry -@end - -@private formattedIdentifier(lineOrFieldSetting) - {@formattedIdentifier(lineOrFieldSetting.getIdentifier, lineOrFieldSetting.getInitValueConfig.hasFormattingConfig)} +@private initLineStructure(line) + ${@line.identifier} = new {@line.typeName}(); + @join fieldSetting : line.fieldSettings + ${@line.identifier}->{@fieldSetting.fnSetFunctionCallName}(${@fieldSetting.identifier}); + @end @end -@private unformattedIdentifier(identifier) - {@formattedIdentifier(identifier, FALSE)} +@private initLineList(line) + ${@line.identifier} = [{@varList(line.elementIdentifiers)}]; @end -@private formattedIdentifier(identifier, isFormatted) - @if isFormatted - $formatted{@context.lowerUnderscoreToUpperCamel(identifier)} - @else - ${@context.lowerUnderscoreToLowerCamel(identifier)} +@snippet varList(args) + @join arg : args on ", " + ${@arg} @end @end -@private initValue(line) - @let metadata = line.getInitValueConfig - @if metadata.hasFormattingConfig() - {@metadata.getApiWrapperName}::{@formatResourceFunctionName(metadata.getCollectionConfig)}({@formatResourceFunctionArgs(metadata.getCollectionConfig)}) - @else - {@context.zeroValue(line.getType)} - @end - @end +@private initLineMap(line) + ${@line.identifier} = [{@keyVarList(line.initEntries)}]; @end -@private formatResourceFunctionArgs(collectionConfig) - @join param : collectionConfig.getNameTemplate.vars() on ", " - "[{@context.lowerUnderscoreToUpperUnderscore(param)}]" +@private keyVarList(mapEntries) + @join mapEntry : mapEntries + {@mapEntry.key} => ${@mapEntry.value}, @end @end -@private formatResourceFunctionName(collectionConfig) - format{@resourceName(collectionConfig)} -@end - -@private resourceName(collectionConfig) - {@context.lowerUnderscoreToUpperCamel(collectionConfig.getEntityName)}Name -@end - -@snippet setCallName(field) - set{@context.lowerUnderscoreToUpperCamel(field.getFieldName)} +@private initLineSimple(line) + ${@line.identifier} = {@renderInitValue(line.initValue)}; @end -@private argList(fieldSettings) - @join fieldSetting : fieldSettings on ", " - {@formattedIdentifier(fieldSetting)} - @end +@private renderInitValue(initValue) + @switch initValue.type + @case "SimpleInitValueView" + {@initValue.initialValue} + @case "FormattedInitValueView" + {@initValue.apiWrapperName}::{@initValue.formatFunctionName}({@argList(initValue.formatArgs)}) + @default + $unhandledCase: {@initValue.type}$ + @end @end diff --git a/src/main/resources/com/google/api/codegen/php/mvvm_common.snip b/src/main/resources/com/google/api/codegen/php/mvvm_common.snip new file mode 100644 index 0000000000..f33115a7c5 --- /dev/null +++ b/src/main/resources/com/google/api/codegen/php/mvvm_common.snip @@ -0,0 +1,6 @@ + +@snippet argList(args) + @join arg : args on ", " + {@arg} + @end +@end diff --git a/src/main/resources/com/google/api/codegen/py/method_sample.snip b/src/main/resources/com/google/api/codegen/py/method_sample.snip index 69d7c44510..a727165a5d 100644 --- a/src/main/resources/com/google/api/codegen/py/method_sample.snip +++ b/src/main/resources/com/google/api/codegen/py/method_sample.snip @@ -85,7 +85,7 @@ # Helper method for initLineList() @private initList(line) @join identifier : line.getElementIdentifiers on ", " - {@identifier} + {@identifier.toLowerUnderscore} @end @end @@ -93,7 +93,7 @@ @private initMap(line) @join key : line.getElementIdentifierKeys vertical on "," @let identifierValue = line.getElementIdentifierValue(key) - {@context.renderPrimitiveValue(line.getKeyType, key)}: {@identifierValue} + {@context.renderPrimitiveValue(line.getKeyType, key)}: {@identifierValue.toLowerUnderscore} @end @end @end @@ -105,7 +105,7 @@ # Properly format an identifier for this language @private formattedIdentifier(lineOrFieldSetting) - {@lineOrFieldSetting.getIdentifier} + {@lineOrFieldSetting.getIdentifier.toLowerUnderscore} @end # Value for simple argument diff --git a/src/test/java/com/google/api/codegen/PhpCodeGeneratorTest.java b/src/test/java/com/google/api/codegen/PhpCodeGeneratorTest.java index fac3abe9f7..ec71910d27 100644 --- a/src/test/java/com/google/api/codegen/PhpCodeGeneratorTest.java +++ b/src/test/java/com/google/api/codegen/PhpCodeGeneratorTest.java @@ -32,7 +32,7 @@ public class PhpCodeGeneratorTest extends GapicTestBase { public PhpCodeGeneratorTest( String name, String idForFactory, String[] gapicConfigFileNames, String snippetName) { super(name, idForFactory, gapicConfigFileNames, snippetName); - getTestDataLocator().addTestDataSource(com.google.api.codegen.php.PhpGapicContext.class, ""); + getTestDataLocator().addTestDataSource(com.google.api.codegen.php.PhpContext.class, ""); } /** diff --git a/src/test/java/com/google/api/codegen/testdata/csharp_wrapper_library.baseline b/src/test/java/com/google/api/codegen/testdata/csharp_wrapper_library.baseline index 1ab4c1e118..4f5e1affae 100644 --- a/src/test/java/com/google/api/codegen/testdata/csharp_wrapper_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/csharp_wrapper_library.baseline @@ -695,13 +695,13 @@ namespace Google.Example.Library.V1 /// /// The default LibraryService scopes are: /// - /// "https://www.googleapis.com/auth/library" /// "https://www.googleapis.com/auth/cloud-platform" + /// "https://www.googleapis.com/auth/library" /// /// public static IReadOnlyList DefaultScopes { get; } = new ReadOnlyCollection(new[] { - "https://www.googleapis.com/auth/library", "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/library", }); /// diff --git a/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline index 437d4d986b..23b6108bbc 100644 --- a/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/go_main_library.baseline @@ -62,8 +62,8 @@ func defaultClientOptions() []option.ClientOption { return []option.ClientOption{ option.WithEndpoint("library-example.googleapis.com:443"), option.WithScopes( - "https://www.googleapis.com/auth/library", "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/library", ), } } diff --git a/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline index 5ffdfc39e5..eec969bec7 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline @@ -110,8 +110,8 @@ public class LibraryServiceSettings extends ServiceApiSettings { * The default scopes of the service. */ public static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() - .add("https://www.googleapis.com/auth/library") .add("https://www.googleapis.com/auth/cloud-platform") + .add("https://www.googleapis.com/auth/library") .build(); /** diff --git a/src/test/java/com/google/api/codegen/testdata/nodejs_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/nodejs_main_library.baseline index 907a8ae3f7..00ed0f8842 100644 --- a/src/test/java/com/google/api/codegen/testdata/nodejs_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/nodejs_main_library.baseline @@ -74,8 +74,8 @@ var BUNDLE_DESCRIPTORS = { * this service. */ var ALL_SCOPES = [ - 'https://www.googleapis.com/auth/library', - 'https://www.googleapis.com/auth/cloud-platform' + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/library' ]; /** diff --git a/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline index 56b1a831b4..6dad061b1b 100644 --- a/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline @@ -42,20 +42,16 @@ use google\example\library\v1\GetBookRequest; use google\example\library\v1\GetShelfRequest; use google\example\library\v1\LibraryServiceClient; use google\example\library\v1\ListBooksRequest; -use google\example\library\v1\ListBooksResponse; use google\example\library\v1\ListShelvesRequest; -use google\example\library\v1\ListShelvesResponse; use google\example\library\v1\ListStringsRequest; -use google\example\library\v1\ListStringsResponse; use google\example\library\v1\MergeShelvesRequest; use google\example\library\v1\MoveBookRequest; use google\example\library\v1\PublishSeriesRequest; -use google\example\library\v1\PublishSeriesResponse; use google\example\library\v1\Shelf; use google\example\library\v1\SomeMessage; use google\example\library\v1\StringBuilder; use google\example\library\v1\UpdateBookIndexRequest; -use google\example\library\v1\UpdateBookIndexRequest\IndexMapEntry; +use google\example\library\v1\UpdateBookIndexRequest.IndexMapEntry; use google\example\library\v1\UpdateBookRequest; use google\protobuf\FieldMask; @@ -142,7 +138,8 @@ class LibraryServiceApi public static function formatBookName($shelf, $book) { return self::getBookNameTemplate()->render([ - 'shelf' => $shelf, 'book' => $book, + 'shelf' => $shelf, + 'book' => $book, ]); } @@ -153,7 +150,8 @@ class LibraryServiceApi public static function formatArchivedBookName($archivePath, $book) { return self::getArchivedBookNameTemplate()->render([ - 'archive_path' => $archivePath, 'book' => $book, + 'archive_path' => $archivePath, + 'book' => $book, ]); } @@ -230,6 +228,7 @@ class LibraryServiceApi return self::$archivedBookNameTemplate; } + private static function getPageStreamingDescriptors() { $listShelvesPageStreamingDescriptor = @@ -293,8 +292,8 @@ class LibraryServiceApi public function __construct($options = []) { $defaultScopes = [ - 'https://www.googleapis.com/auth/library', 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/library', ]; $defaultOptions = [ 'serviceAddress' => self::SERVICE_ADDRESS, @@ -389,11 +388,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -439,15 +438,17 @@ class LibraryServiceApi * @param string $options To test 'options' parameter name conflict. * @param array $optionalArgs { * Optional. - * @var SomeMessage $message Field to verify that message-type query parameter gets flattened. + * @var SomeMessage $message + * Field to verify that message-type query parameter gets flattened. * @var StringBuilder $stringBuilder + * * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -502,11 +503,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -552,11 +553,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -605,11 +606,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -659,11 +660,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -710,14 +711,15 @@ class LibraryServiceApi * @param Book[] $books The books to publish in the series. * @param array $optionalArgs { * Optional. - * @var int $edition The edition of the series + * @var int $edition + * The edition of the series * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -770,11 +772,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -821,19 +823,20 @@ class LibraryServiceApi * @param array $optionalArgs { * Optional. * @var int $pageSize - * The maximum number of resources contained in the underlying API - * response. If page streaming is performed per-resource, this - * parameter does not affect the return value. If page streaming is - * performed per-page, this determines the maximum number of - * resources in a page. - * @var string $filter To test python built-in wrapping. + * The maximum number of resources contained in the underlying API + * response. If page streaming is performed per-resource, this + * parameter does not affect the return value. If page streaming is + * performed per-page, this determines the maximum number of + * resources in a page. + * @var string $filter + * To test python built-in wrapping. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -886,11 +889,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -934,15 +937,17 @@ class LibraryServiceApi * @param Book $book The book to update with. * @param array $optionalArgs { * Optional. - * @var FieldMask $updateMask A field mask to apply, rendered as an HTTP parameter. - * @var google\example\library\v1\FieldMask $physicalMask To test Python import clash resolution. + * @var FieldMask $updateMask + * A field mask to apply, rendered as an HTTP parameter. + * @var google\example\library\v1\FieldMask $physicalMask + * To test Python import clash resolution. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -998,11 +1003,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -1049,19 +1054,20 @@ class LibraryServiceApi * @param array $optionalArgs { * Optional. * @var string $name + * * @var int $pageSize - * The maximum number of resources contained in the underlying API - * response. If page streaming is performed per-resource, this - * parameter does not affect the return value. If page streaming is - * performed per-page, this determines the maximum number of - * resources in a page. + * The maximum number of resources contained in the underlying API + * response. If page streaming is performed per-resource, this + * parameter does not affect the return value. If page streaming is + * performed per-page, this determines the maximum number of + * resources in a page. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -1118,11 +1124,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -1170,11 +1176,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -1207,7 +1213,7 @@ class LibraryServiceApi * try { * $libraryServiceApi = new LibraryServiceApi(); * $formattedName = LibraryServiceApi::formatBookName("[SHELF]", "[BOOK]"); - * $indexName = ""; + * $indexName = "default index"; * $indexMapItem = ""; * $indexMap = ["default_key" => $indexMapItem,]; * $libraryServiceApi->updateBookIndex($formattedName, $indexName, $indexMap); @@ -1226,11 +1232,11 @@ class LibraryServiceApi * this $optionalArgs parameter reserves a spot for future ones. * } * @param array $callSettings { - * Optional. - * @var Google\GAX\RetrySettings $retrySettings + * Optional. + * @var Google\GAX\RetrySettings $retrySettings * Retry settings to use for this call. If present, then - * $timeout is ignored. - * @var int $timeoutMillis + * $timeoutMillis is ignored. + * @var int $timeoutMillis * Timeout to use for this call. Only used if $retrySettings * is not set. * } @@ -1243,7 +1249,7 @@ class LibraryServiceApi $request->setName($name); $request->setIndexName($indexName); foreach ($indexMap as $key => $value) { - $request->addIndexMap((new IndexMapEntry())->setKey($key)->setValue($value)); + $request->addIndexMap((new UpdateBookIndexRequest.IndexMapEntry())->setKey($key)->setValue($value)); } $mergedSettings = $this->defaultCallSettings['updateBookIndex']->merge( @@ -1271,4 +1277,3 @@ class LibraryServiceApi return $this->grpcBootstrap->createCallCredentialsCallback($this->scopes); } } - diff --git a/src/test/java/com/google/api/codegen/testdata/python_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/python_main_library.baseline index 8636aa7692..08561b4125 100644 --- a/src/test/java/com/google/api/codegen/testdata/python_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/python_main_library.baseline @@ -103,8 +103,8 @@ class LibraryServiceApi(object): # The scopes needed to make gRPC calls to all of the methods defined in # this service _ALL_SCOPES = ( - 'https://www.googleapis.com/auth/library', 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/library', ) _SHELF_PATH_TEMPLATE = path_template.PathTemplate( diff --git a/src/test/java/com/google/api/codegen/testdata/ruby_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/ruby_main_library.baseline index cb230c3c22..83ce4b998b 100644 --- a/src/test/java/com/google/api/codegen/testdata/ruby_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/ruby_main_library.baseline @@ -91,8 +91,8 @@ module Library # The scopes needed to make gRPC calls to all of the methods defined in # this service. ALL_SCOPES = [ - 'https://www.googleapis.com/auth/library', - 'https://www.googleapis.com/auth/cloud-platform' + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/library' ].freeze SHELF_PATH_TEMPLATE = Google::Gax::PathTemplate.new( diff --git a/src/test/java/com/google/api/codegen/util/NamePathTest.java b/src/test/java/com/google/api/codegen/util/NamePathTest.java new file mode 100644 index 0000000000..53feaaae47 --- /dev/null +++ b/src/test/java/com/google/api/codegen/util/NamePathTest.java @@ -0,0 +1,40 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.common.truth.Truth; + +import org.junit.Test; + +public class NamePathTest { + + @Test + public void testSingleWord() { + NamePath path = NamePath.dotted("Foo"); + Truth.assertThat(path.toDotted()).isEqualTo("Foo"); + Truth.assertThat(path.toBackslashed()).isEqualTo("Foo"); + Truth.assertThat(path.getHead()).isEqualTo("Foo"); + Truth.assertThat(path.withHead("Bar").toDotted()).isEqualTo("Bar"); + } + + @Test + public void testDottedPath() { + NamePath path = NamePath.dotted("com.google.Foo"); + Truth.assertThat(path.toDotted()).isEqualTo("com.google.Foo"); + Truth.assertThat(path.toBackslashed()).isEqualTo("com\\google\\Foo"); + Truth.assertThat(path.getHead()).isEqualTo("Foo"); + Truth.assertThat(path.withHead("Bar").toDotted()).isEqualTo("com.google.Bar"); + } +} diff --git a/src/test/java/com/google/api/codegen/util/NameTest.java b/src/test/java/com/google/api/codegen/util/NameTest.java new file mode 100644 index 0000000000..5321dd1f45 --- /dev/null +++ b/src/test/java/com/google/api/codegen/util/NameTest.java @@ -0,0 +1,87 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.common.truth.Truth; + +import org.junit.Test; + +public class NameTest { + + @Test + public void testEmpty() { + Name name = Name.from(); + Truth.assertThat(name.toLowerUnderscore()).isEqualTo(""); + Truth.assertThat(name.toUpperUnderscore()).isEqualTo(""); + Truth.assertThat(name.toLowerCamel()).isEqualTo(""); + Truth.assertThat(name.toUpperCamel()).isEqualTo(""); + } + + @Test + public void testSingleWord() { + Name name = Name.from("dog"); + Truth.assertThat(name.toLowerUnderscore()).isEqualTo("dog"); + Truth.assertThat(name.toUpperUnderscore()).isEqualTo("DOG"); + Truth.assertThat(name.toLowerCamel()).isEqualTo("dog"); + Truth.assertThat(name.toUpperCamel()).isEqualTo("Dog"); + } + + @Test + public void testMultipleWords() { + Name name = Name.from("factory_decorator", "delegate_impl"); + Truth.assertThat(name.toLowerUnderscore()).isEqualTo("factory_decorator_delegate_impl"); + Truth.assertThat(name.toUpperUnderscore()).isEqualTo("FACTORY_DECORATOR_DELEGATE_IMPL"); + Truth.assertThat(name.toLowerCamel()).isEqualTo("factoryDecoratorDelegateImpl"); + Truth.assertThat(name.toUpperCamel()).isEqualTo("FactoryDecoratorDelegateImpl"); + } + + @Test + public void testFromLowerCamel() { + Name name = Name.lowerCamel("factoryDecorator", "delegateImpl"); + Truth.assertThat(name.toLowerUnderscore()).isEqualTo("factory_decorator_delegate_impl"); + Truth.assertThat(name.toUpperUnderscore()).isEqualTo("FACTORY_DECORATOR_DELEGATE_IMPL"); + Truth.assertThat(name.toLowerCamel()).isEqualTo("factoryDecoratorDelegateImpl"); + Truth.assertThat(name.toUpperCamel()).isEqualTo("FactoryDecoratorDelegateImpl"); + } + + @Test + public void testFromUpperCamel() { + Name name = Name.upperCamel("FactoryDecorator", "DelegateImpl"); + Truth.assertThat(name.toLowerUnderscore()).isEqualTo("factory_decorator_delegate_impl"); + Truth.assertThat(name.toUpperUnderscore()).isEqualTo("FACTORY_DECORATOR_DELEGATE_IMPL"); + Truth.assertThat(name.toLowerCamel()).isEqualTo("factoryDecoratorDelegateImpl"); + Truth.assertThat(name.toUpperCamel()).isEqualTo("FactoryDecoratorDelegateImpl"); + } + + @Test(expected = IllegalArgumentException.class) + public void illegalLowerUnderscore() { + Name.from("factoryDecorator"); + } + + @Test(expected = IllegalArgumentException.class) + public void illegalUpperUnderscore() { + Name.upperCamel("factory_decorator"); + } + + @Test(expected = IllegalArgumentException.class) + public void illegalLowerCamel() { + Name.lowerCamel("FactoryDecorator"); + } + + @Test(expected = IllegalArgumentException.class) + public void illegalUpperCamel() { + Name.upperCamel("factoryDecorator"); + } +} diff --git a/src/test/java/com/google/api/codegen/util/TypeNameTest.java b/src/test/java/com/google/api/codegen/util/TypeNameTest.java new file mode 100644 index 0000000000..612b8c6765 --- /dev/null +++ b/src/test/java/com/google/api/codegen/util/TypeNameTest.java @@ -0,0 +1,64 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.common.truth.Truth; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +public class TypeNameTest { + + @Test + public void testSimple() { + TypeName typeName = new TypeName("com.google.Foo", "Foo"); + Truth.assertThat(typeName.getFullName()).isEqualTo("com.google.Foo"); + Truth.assertThat(typeName.getNickname()).isEqualTo("Foo"); + MockTypeTable typeTable = new MockTypeTable(); + Truth.assertThat(typeName.getAndSaveNicknameIn(typeTable)).isEqualTo("Foo"); + List expectedImports = Arrays.asList(TypeAlias.create("com.google.Foo", "Foo")); + Truth.assertThat(typeTable.imports).isEqualTo(expectedImports); + } + + @Test + public void testComposite() { + TypeName typeName = new TypeName("com.google.Foo", "Foo"); + TypeName containerTypeName = + new TypeName("com.google.Container", "Container", "%s<%i>", typeName); + Truth.assertThat(containerTypeName.getFullName()) + .isEqualTo("com.google.Container"); + Truth.assertThat(containerTypeName.getNickname()).isEqualTo("Container"); + MockTypeTable typeTable = new MockTypeTable(); + Truth.assertThat(containerTypeName.getAndSaveNicknameIn(typeTable)).isEqualTo("Container"); + List expectedImports = + Arrays.asList( + TypeAlias.create("com.google.Container", "Container"), + TypeAlias.create("com.google.Foo", "Foo")); + Truth.assertThat(typeTable.imports).isEqualTo(expectedImports); + } + + private static class MockTypeTable implements TypeTable { + public List imports = new ArrayList<>(); + + @Override + public String getAndSaveNicknameFor(TypeAlias alias) { + imports.add(alias); + return alias.getNickname(); + } + } +} From 4f0cba2668c9f2996c502d20d8c4e312252f6d21 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 19 Jul 2016 16:27:10 -0700 Subject: [PATCH 02/26] Java MVVM --- .../gapic/MainGapicProviderFactory.java | 20 + .../transformer/ApiMethodTransformer.java | 243 +++ .../api/codegen/transformer/SurfaceNamer.java | 54 + .../java/JavaGapicSurfaceTransformer.java | 260 +++ .../transformer/java/JavaModelTypeTable.java | 288 +++ .../transformer/java/JavaSurfaceNamer.java | 77 + .../codegen/util/java/JavaNameFormatter.java | 65 + .../codegen/util/java/JavaRenderingUtil.java | 52 + .../api/codegen/util/java/JavaTypeTable.java | 136 ++ .../codegen/viewmodel/ApiCallableType.java | 21 + .../codegen/viewmodel/ApiCallableView.java | 49 + .../viewmodel/CallableMethodDetailView.java | 37 + .../codegen/viewmodel/DynamicXApiView.java | 1 - .../codegen/viewmodel/FieldSettingView.java | 1 - .../viewmodel/FormatResourceFunctionView.java | 1 - .../api/codegen/viewmodel/InitCodeView.java | 1 - .../viewmodel/ListInitCodeLineView.java | 1 - .../viewmodel/ListMethodDetailView.java | 33 + .../viewmodel/PathTemplateCheckView.java | 38 + .../RequestObjectMethodDetailView.java | 37 + .../api/codegen/viewmodel/ServiceDocView.java | 3 - .../viewmodel/StaticApiMethodView.java | 106 ++ .../api/codegen/viewmodel/StaticXApiView.java | 81 + .../viewmodel/StaticXSettingsView.java | 69 + .../UnpagedListCallableMethodDetailView.java | 33 + .../google/api/codegen/java/mvvm_common.snip | 12 + .../com/google/api/codegen/java/xapi.snip | 341 ++++ .../google/api/codegen/java/xapi_sample.snip | 131 ++ .../google/api/codegen/java/xsettings.snip | 43 + .../codegen/JavaSurfaceCodeGeneratorTest.java | 57 + .../java_surface_xapi_library.baseline | 1580 +++++++++++++++++ .../java_surface_xsettings_library.baseline | 51 + 32 files changed, 3914 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java create mode 100644 src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java create mode 100644 src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java create mode 100644 src/main/java/com/google/api/codegen/util/java/JavaNameFormatter.java create mode 100644 src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java create mode 100644 src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ApiCallableType.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ApiCallableView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/CallableMethodDetailView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ListMethodDetailView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/PathTemplateCheckView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/RequestObjectMethodDetailView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/UnpagedListCallableMethodDetailView.java create mode 100644 src/main/resources/com/google/api/codegen/java/mvvm_common.snip create mode 100644 src/main/resources/com/google/api/codegen/java/xapi.snip create mode 100644 src/main/resources/com/google/api/codegen/java/xapi_sample.snip create mode 100644 src/main/resources/com/google/api/codegen/java/xsettings.snip create mode 100644 src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java create mode 100644 src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline create mode 100644 src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline diff --git a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java index d8e005de70..01d66701fc 100644 --- a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java +++ b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java @@ -38,8 +38,10 @@ import com.google.api.codegen.rendering.CommonSnippetSetRunner; import com.google.api.codegen.ruby.RubyGapicContext; import com.google.api.codegen.ruby.RubySnippetSetRunner; +import com.google.api.codegen.transformer.java.JavaGapicSurfaceTransformer; import com.google.api.codegen.transformer.php.PhpGapicSurfaceTransformer; import com.google.api.codegen.util.CommonRenderingUtil; +import com.google.api.codegen.util.java.JavaRenderingUtil; import com.google.api.tools.framework.model.Interface; import com.google.api.tools.framework.model.Model; import com.google.api.tools.framework.model.ProtoFile; @@ -64,6 +66,8 @@ public class MainGapicProviderFactory public static final String PYTHON = "python"; public static final String RUBY = "ruby"; + public static final String JAVA_SURFACE = "java_surface"; + /** * Create the GapicProviders based on the given id */ @@ -143,6 +147,22 @@ public static List> defaultCreate( return Arrays.>asList(mainProvider, packageInfoProvider); + } else if (id.equals(JAVA_SURFACE)) { + GapicCodePathMapper javaPathMapper = + CommonGapicCodePathMapper.newBuilder() + .setPrefix("src/main/java") + .setShouldAppendPackage(true) + .build(); + GapicProvider mainProvider = + ViewModelGapicProvider.newBuilder() + .setModel(model) + .setApiConfig(apiConfig) + .setSnippetSetRunner(new CommonSnippetSetRunner(new JavaRenderingUtil())) + .setModelToViewTransformer(new JavaGapicSurfaceTransformer(javaPathMapper)) + .build(); + + return Arrays.>asList(mainProvider); + } else if (id.equals(NODEJS)) { GapicCodePathMapper nodeJSPathMapper = CommonGapicCodePathMapper.newBuilder().setPrefix("lib").build(); diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index 62cd83173f..7e829763d0 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -14,19 +14,30 @@ */ package com.google.api.codegen.transformer; +import com.google.api.codegen.CollectionConfig; import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.PageStreamingConfig; import com.google.api.codegen.ServiceMessages; import com.google.api.codegen.util.Name; import com.google.api.codegen.viewmodel.ApiMethodDocView; import com.google.api.codegen.viewmodel.ApiMethodType; +import com.google.api.codegen.viewmodel.CallableMethodDetailView; import com.google.api.codegen.viewmodel.DynamicDefaultableParamView; +import com.google.api.codegen.viewmodel.ListMethodDetailView; import com.google.api.codegen.viewmodel.MapParamDocView; import com.google.api.codegen.viewmodel.OptionalArrayMethodView; import com.google.api.codegen.viewmodel.ParamDocView; +import com.google.api.codegen.viewmodel.PathTemplateCheckView; +import com.google.api.codegen.viewmodel.RequestObjectMethodDetailView; import com.google.api.codegen.viewmodel.RequestObjectParamView; import com.google.api.codegen.viewmodel.SimpleParamDocView; +import com.google.api.codegen.viewmodel.StaticApiMethodView; +import com.google.api.codegen.viewmodel.StaticApiMethodView.Builder; +import com.google.api.codegen.viewmodel.UnpagedListCallableMethodDetailView; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.TypeRef; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; import java.util.ArrayList; @@ -43,6 +54,238 @@ public ApiMethodTransformer() { this.initCodeTransformer = new InitCodeTransformer(); } + public StaticApiMethodView generatePagedFlattenedMethod( + MethodTransformerContext context, ImmutableList fields) { + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(context.getNamer().getApiMethodName(context.getMethod())); + setListMethodFields(context, methodViewBuilder); + setFlattenedMethodFields(context, fields, methodViewBuilder); + + return methodViewBuilder.type(ApiMethodType.PagedFlattenedMethod).build(); + } + + public StaticApiMethodView generatePagedRequestObjectMethod(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(namer.getApiMethodName(context.getMethod())); + setListMethodFields(context, methodViewBuilder); + setRequestObjectMethodFields( + context, namer.getPagedCallableMethodName(context.getMethod()), methodViewBuilder); + + return methodViewBuilder.type(ApiMethodType.PagedRequestObjectMethod).build(); + } + + public StaticApiMethodView generatePagedCallableMethod(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(namer.getPagedCallableMethodName(context.getMethod())); + setListMethodFields(context, methodViewBuilder); + setCallableMethodFields( + context, namer.getPagedCallableName(context.getMethod()), methodViewBuilder); + + return methodViewBuilder.type(ApiMethodType.PagedCallableMethod).build(); + } + + public StaticApiMethodView generateUnpagedListCallableMethod(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(namer.getCallableMethodName(context.getMethod())); + setListMethodFields(context, methodViewBuilder); + setCallableMethodFields(context, namer.getCallableName(context.getMethod()), methodViewBuilder); + + String getResourceListCallName = + namer.getGetResourceListCallName( + context.getMethodConfig().getPageStreaming().getResourcesField()); + UnpagedListCallableMethodDetailView unpagedListCallableDetails = + UnpagedListCallableMethodDetailView.newBuilder() + .fnGetResourceListCall(getResourceListCallName) + .build(); + methodViewBuilder.unpagedListCallableMethod(unpagedListCallableDetails); + + methodViewBuilder.responseTypeName( + context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getOutputType())); + + return methodViewBuilder.type(ApiMethodType.UnpagedListCallableMethod).build(); + } + + public StaticApiMethodView generateFlattenedMethod( + MethodTransformerContext context, ImmutableList fields) { + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(context.getNamer().getApiMethodName(context.getMethod())); + setFlattenedMethodFields(context, fields, methodViewBuilder); + setSyncStaticReturnFields(context, methodViewBuilder); + + return methodViewBuilder.type(ApiMethodType.FlattenedMethod).build(); + } + + public StaticApiMethodView generateRequestObjectMethod(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(namer.getApiMethodName(context.getMethod())); + setRequestObjectMethodFields( + context, namer.getCallableMethodName(context.getMethod()), methodViewBuilder); + setSyncStaticReturnFields(context, methodViewBuilder); + + return methodViewBuilder.type(ApiMethodType.RequestObjectMethod).build(); + } + + public StaticApiMethodView generateCallableMethod(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + StaticApiMethodView.Builder methodViewBuilder = StaticApiMethodView.newBuilder(); + + setCommonFields(context, methodViewBuilder); + methodViewBuilder.name(namer.getCallableMethodName(context.getMethod())); + setCallableMethodFields(context, namer.getCallableName(context.getMethod()), methodViewBuilder); + methodViewBuilder.responseTypeName( + context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getOutputType())); + methodViewBuilder.hasReturnValue( + !ServiceMessages.s_isEmptyType(context.getMethod().getOutputType())); + + return methodViewBuilder.type(ApiMethodType.CallableMethod).build(); + } + + public void setCommonFields( + MethodTransformerContext context, StaticApiMethodView.Builder methodViewBuilder) { + SurfaceNamer namer = context.getNamer(); + methodViewBuilder.apiRequestTypeName( + context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getInputType())); + methodViewBuilder.apiClassName(namer.getApiWrapperClassName(context.getInterface())); + methodViewBuilder.apiVariableName(namer.getApiWrapperVariableName(context.getInterface())); + } + + private void setListMethodFields( + MethodTransformerContext context, StaticApiMethodView.Builder methodViewBuilder) { + PageStreamingConfig pageStreaming = context.getMethodConfig().getPageStreaming(); + TypeRef resourceType = pageStreaming.getResourcesField().getType(); + String resourceTypeName = context.getTypeTable().getAndSaveNicknameForElementType(resourceType); + methodViewBuilder.listMethod( + ListMethodDetailView.newBuilder().resourceTypeName(resourceTypeName).build()); + methodViewBuilder.responseTypeName( + context.getNamer().getAndSavePagedResponseTypeName(context.getTypeTable(), resourceType)); + methodViewBuilder.hasReturnValue(true); + } + + public void setFlattenedMethodFields( + MethodTransformerContext context, + ImmutableList fields, + StaticApiMethodView.Builder methodViewBuilder) { + SurfaceNamer namer = context.getNamer(); + methodViewBuilder.initCode(initCodeTransformer.generateInitCode(context, fields)); + methodViewBuilder.doc( + ApiMethodDocView.newBuilder() + .mainDocLines(namer.getDocLines(context.getMethod())) + .paramDocs(getMethodParamDocs(context, fields)) + .throwsDocLines(namer.getThrowsDocLines()) + .build()); + + List params = new ArrayList<>(); + for (Field field : fields) { + params.add(generateRequestObjectParam(context, field)); + } + methodViewBuilder.methodParams(params); + methodViewBuilder.requestObjectParams(params); + + methodViewBuilder.pathTemplateChecks(generatePathTemplateChecks(context, fields)); + } + + public void setRequestObjectMethodFields( + MethodTransformerContext context, + String callableMethodName, + StaticApiMethodView.Builder methodViewBuilder) { + SurfaceNamer namer = context.getNamer(); + methodViewBuilder.doc( + ApiMethodDocView.newBuilder() + .mainDocLines(namer.getDocLines(context.getMethod())) + .paramDocs( + Arrays.asList( + getRequestObjectParamDoc(context, context.getMethod().getInputType()))) + .throwsDocLines(namer.getThrowsDocLines()) + .build()); + methodViewBuilder.initCode(initCodeTransformer.generateRequestObjectInitCode(context)); + + methodViewBuilder.methodParams(new ArrayList()); + methodViewBuilder.requestObjectParams(new ArrayList()); + methodViewBuilder.pathTemplateChecks(new ArrayList()); + + RequestObjectMethodDetailView.Builder detailBuilder = + RequestObjectMethodDetailView.newBuilder(); + if (context.getMethodConfig().hasRequestObjectMethod()) { + detailBuilder.accessModifier(context.getNamer().getPublicAccessModifier()); + } else { + detailBuilder.accessModifier(context.getNamer().getPrivateAccessModifier()); + } + detailBuilder.callableMethodName(callableMethodName); + methodViewBuilder.requestObjectMethod(detailBuilder.build()); + } + + private void setCallableMethodFields( + MethodTransformerContext context, String callableName, Builder methodViewBuilder) { + methodViewBuilder.doc( + ApiMethodDocView.newBuilder() + .mainDocLines(context.getNamer().getDocLines(context.getMethod())) + .paramDocs(new ArrayList()) + .throwsDocLines(new ArrayList()) + .build()); + methodViewBuilder.initCode(initCodeTransformer.generateRequestObjectInitCode(context)); + + methodViewBuilder.methodParams(new ArrayList()); + methodViewBuilder.requestObjectParams(new ArrayList()); + methodViewBuilder.pathTemplateChecks(new ArrayList()); + + String genericAwareResponseType = + context + .getNamer() + .getGenericAwareResponseType( + context.getTypeTable(), context.getMethod().getOutputType()); + methodViewBuilder.callableMethod( + CallableMethodDetailView.newBuilder() + .genericAwareResponseType(genericAwareResponseType) + .callableName(callableName) + .build()); + } + + public void setSyncStaticReturnFields( + MethodTransformerContext context, StaticApiMethodView.Builder methodViewBuilder) { + methodViewBuilder.responseTypeName( + context + .getNamer() + .getStaticReturnTypeName( + context.getTypeTable(), context.getMethod(), context.getMethodConfig())); + methodViewBuilder.hasReturnValue( + !ServiceMessages.s_isEmptyType(context.getMethod().getOutputType())); + } + + public List generatePathTemplateChecks( + MethodTransformerContext context, ImmutableList fields) { + List pathTemplateChecks = new ArrayList<>(); + for (Field field : fields) { + ImmutableMap fieldNamePatterns = + context.getMethodConfig().getFieldNamePatterns(); + String entityName = fieldNamePatterns.get(field.getSimpleName()); + if (entityName != null) { + CollectionConfig collectionConfig = context.getCollectionConfig(entityName); + PathTemplateCheckView.Builder check = PathTemplateCheckView.newBuilder(); + check.pathTemplateName(context.getNamer().getPathTemplateName(collectionConfig)); + check.paramName(context.getNamer().getVariableName(field)); + + pathTemplateChecks.add(check.build()); + } + } + return pathTemplateChecks; + } + public OptionalArrayMethodView generateOptionalArrayMethod(MethodTransformerContext context) { SurfaceNamer namer = context.getNamer(); OptionalArrayMethodView.Builder apiMethod = OptionalArrayMethodView.newBuilder(); diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index ffc679d47f..95a00909f0 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -29,6 +29,7 @@ import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.TypeRef; +import java.util.ArrayList; import java.util.List; /** @@ -49,6 +50,10 @@ public String getApiWrapperVariableName(Interface interfaze) { return varName(Name.upperCamel(interfaze.getSimpleName(), "Api")); } + public String getApiSettingsClassName(Interface interfaze) { + return className(Name.upperCamel(interfaze.getSimpleName(), "Settings")); + } + public String getVariableName(Name identifier, InitValueConfig initValueConfig) { if (initValueConfig == null || !initValueConfig.hasFormattingConfig()) { return varName(identifier); @@ -138,6 +143,18 @@ public List getDocLines(ProtoElement element) { return getDocLines(DocumentationUtil.getDescription(element)); } + public List getThrowsDocLines() { + return new ArrayList<>(); + } + + public String getPublicAccessModifier() { + return "public"; + } + + public String getPrivateAccessModifier() { + return "private"; + } + public String getGrpcMethodName(Method method) { // This might seem silly, but it makes clear what we're dealing with (upper camel). // This is language-independent because of gRPC conventions. @@ -156,4 +173,41 @@ public String getDynamicReturnTypeName( ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { return SurfaceNamer.NOT_IMPLEMENTED; } + + public String getStaticReturnTypeName( + ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + return SurfaceNamer.NOT_IMPLEMENTED; + } + + public String getPagedCallableMethodName(Method method) { + return methodName(Name.upperCamel(method.getSimpleName(), "PagedCallable")); + } + + public String getPagedCallableName(Method method) { + return varName(Name.upperCamel(method.getSimpleName(), "PagedCallable")); + } + + public String getCallableMethodName(Method method) { + return methodName(Name.upperCamel(method.getSimpleName(), "Callable")); + } + + public String getCallableName(Method method) { + return varName(Name.upperCamel(method.getSimpleName(), "Callable")); + } + + public String getSettingsFunctionName(Method method) { + return methodName(Name.upperCamel(method.getSimpleName(), "Settings")); + } + + public String getGenericAwareResponseType(ModelTypeTable typeTable, TypeRef outputType) { + return SurfaceNamer.NOT_IMPLEMENTED; + } + + public String getGetResourceListCallName(Field resourcesField) { + return methodName(Name.from("get", resourcesField.getSimpleName(), "list")); + } + + public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef resourceType) { + return SurfaceNamer.NOT_IMPLEMENTED; + } } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java new file mode 100644 index 0000000000..419c93eef6 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -0,0 +1,260 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer.java; + +import com.google.api.codegen.ApiConfig; +import com.google.api.codegen.InterfaceView; +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.PageStreamingConfig; +import com.google.api.codegen.ServiceConfig; +import com.google.api.codegen.gapic.GapicCodePathMapper; +import com.google.api.codegen.transformer.ApiMethodTransformer; +import com.google.api.codegen.transformer.MethodTransformerContext; +import com.google.api.codegen.transformer.ModelToViewTransformer; +import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.PathTemplateTransformer; +import com.google.api.codegen.transformer.SurfaceTransformerContext; +import com.google.api.codegen.viewmodel.ApiCallableType; +import com.google.api.codegen.viewmodel.ApiCallableView; +import com.google.api.codegen.viewmodel.StaticApiMethodView; +import com.google.api.codegen.viewmodel.StaticXApiView; +import com.google.api.codegen.viewmodel.StaticXSettingsView; +import com.google.api.codegen.viewmodel.ViewModel; +import com.google.api.tools.framework.model.Field; +import com.google.api.tools.framework.model.Interface; +import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.Model; +import com.google.common.collect.ImmutableList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * The ModelToViewTransformer to transform a Model into the standard GAPIC surface in Java. + */ +public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { + private GapicCodePathMapper pathMapper; + private PathTemplateTransformer pathTemplateTransformer; + private ApiMethodTransformer apiMethodTransformer; + + private static final String XAPI_TEMPLATE_FILENAME = "java/xapi.snip"; + private static final String XSETTINGS_TEMPLATE_FILENAME = "java/xsettings.snip"; + + /** + * Standard constructor. + */ + public JavaGapicSurfaceTransformer(GapicCodePathMapper pathMapper) { + this.pathMapper = pathMapper; + this.pathTemplateTransformer = new PathTemplateTransformer(); + this.apiMethodTransformer = new ApiMethodTransformer(); + } + + @Override + public List getTemplateFileNames() { + return Arrays.asList(XAPI_TEMPLATE_FILENAME, XSETTINGS_TEMPLATE_FILENAME); + } + + @Override + public List transform(Model model, ApiConfig apiConfig) { + List surfaceDocs = new ArrayList<>(); + for (Interface service : new InterfaceView().getElementIterable(model)) { + SurfaceTransformerContext context = + SurfaceTransformerContext.create( + service, apiConfig, new JavaModelTypeTable(), new JavaSurfaceNamer()); + surfaceDocs.addAll(transform(context)); + } + return surfaceDocs; + } + + public List transform(SurfaceTransformerContext context) { + List surfaceData = new ArrayList<>(); + + surfaceData.add(generateXApi(context)); + + context = context.withNewTypeTable(); + surfaceData.add(generateXSettings(context)); + + return surfaceData; + } + + private StaticXApiView generateXApi(SurfaceTransformerContext context) { + addXApiImports(context); + + StaticXApiView.Builder xapiClass = StaticXApiView.newBuilder(); + xapiClass.templateFileName(XAPI_TEMPLATE_FILENAME); + xapiClass.packageName(context.getApiConfig().getPackageName()); + String name = context.getNamer().getApiWrapperClassName(context.getInterface()); + xapiClass.name(name); + xapiClass.settingsClassName(context.getNamer().getApiSettingsClassName(context.getInterface())); + xapiClass.apiCallableMembers(generateApiCallables(context)); + xapiClass.pathTemplates(pathTemplateTransformer.generatePathTemplates(context)); + xapiClass.formatResourceFunctions( + pathTemplateTransformer.generateFormatResourceFunctions(context)); + xapiClass.parseResourceFunctions( + pathTemplateTransformer.generateParseResourceFunctions(context)); + xapiClass.apiMethods(generateApiMethods(context)); + + // must be done as the last step to catch all imports + xapiClass.imports(context.getTypeTable().getImports()); + + String outputPath = pathMapper.getOutputPath(context.getInterface(), context.getApiConfig()); + xapiClass.outputPath(outputPath + "/" + name + ".java"); + + return xapiClass.build(); + } + + private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) { + addXSettingsImports(context); + + StaticXSettingsView.Builder xsettingsClass = StaticXSettingsView.newBuilder(); + xsettingsClass.templateFileName(XSETTINGS_TEMPLATE_FILENAME); + xsettingsClass.packageName(context.getApiConfig().getPackageName()); + String name = context.getNamer().getApiSettingsClassName(context.getInterface()); + xsettingsClass.name(name); + ServiceConfig serviceConfig = new ServiceConfig(); + xsettingsClass.serviceAddress(serviceConfig.getServiceAddress(context.getInterface())); + xsettingsClass.servicePort(serviceConfig.getServicePort()); + xsettingsClass.authScopes(serviceConfig.getAuthScopes(context.getInterface())); + + // must be done as the last step to catch all imports + xsettingsClass.imports(context.getTypeTable().getImports()); + + String outputPath = pathMapper.getOutputPath(context.getInterface(), context.getApiConfig()); + xsettingsClass.outputPath(outputPath + "/" + name + ".java"); + + return xsettingsClass.build(); + } + + private void addXApiImports(SurfaceTransformerContext context) { + ModelTypeTable typeTable = context.getTypeTable(); + typeTable.saveNicknameFor("com.google.api.gax.grpc.ApiCallable"); + typeTable.saveNicknameFor("com.google.api.gax.protobuf.PathTemplate"); + typeTable.saveNicknameFor("io.grpc.ManagedChannel"); + typeTable.saveNicknameFor("java.io.Closeable"); + typeTable.saveNicknameFor("java.io.IOException"); + typeTable.saveNicknameFor("java.util.ArrayList"); + typeTable.saveNicknameFor("java.util.List"); + typeTable.saveNicknameFor("java.util.concurrent.ScheduledExecutorService"); + } + + private void addXSettingsImports(SurfaceTransformerContext context) { + ModelTypeTable typeTable = context.getTypeTable(); + typeTable.saveNicknameFor("com.google.api.gax.core.ConnectionSettings"); + typeTable.saveNicknameFor("com.google.api.gax.core.RetrySettings"); + typeTable.saveNicknameFor("com.google.api.gax.grpc.ApiCallSettings"); + typeTable.saveNicknameFor("com.google.api.gax.grpc.SimpleCallSettings"); + typeTable.saveNicknameFor("com.google.api.gax.grpc.ServiceApiSettings"); + typeTable.saveNicknameFor("com.google.auth.Credentials"); + typeTable.saveNicknameFor("com.google.common.collect.ImmutableList"); + typeTable.saveNicknameFor("com.google.common.collect.ImmutableMap"); + typeTable.saveNicknameFor("com.google.common.collect.ImmutableSet"); + typeTable.saveNicknameFor("com.google.common.collect.Lists"); + typeTable.saveNicknameFor("com.google.common.collect.Sets"); + typeTable.saveNicknameFor("io.grpc.ManagedChannel"); + typeTable.saveNicknameFor("io.grpc.Status"); + typeTable.saveNicknameFor("org.joda.time.Duration"); + typeTable.saveNicknameFor("java.io.IOException"); + typeTable.saveNicknameFor("java.util.List"); + typeTable.saveNicknameFor("java.util.concurrent.ScheduledExecutorService"); + } + + private List generateApiCallables(SurfaceTransformerContext context) { + List callableMembers = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + MethodConfig methodConfig = context.getMethodConfig(method); + callableMembers.addAll(generateApiCallables(context, method, methodConfig)); + } + + return callableMembers; + } + + private List generateApiCallables( + SurfaceTransformerContext context, Method method, MethodConfig methodConfig) { + ModelTypeTable typeTable = context.getTypeTable(); + + List apiCallables = new ArrayList<>(); + + ApiCallableView.Builder apiCallableBuilder = ApiCallableView.newBuilder(); + + apiCallableBuilder.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); + apiCallableBuilder.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); + apiCallableBuilder.name(context.getNamer().getCallableName(method)); + apiCallableBuilder.settingsFunctionName(context.getNamer().getSettingsFunctionName(method)); + + if (methodConfig.isBundling()) { + apiCallableBuilder.type(ApiCallableType.BundlingApiCallable); + } else { + apiCallableBuilder.type(ApiCallableType.SimpleApiCallable); + } + + apiCallables.add(apiCallableBuilder.build()); + + if (methodConfig.isPageStreaming()) { + PageStreamingConfig pageStreaming = methodConfig.getPageStreaming(); + + ApiCallableView.Builder pagedApiCallableBuilder = ApiCallableView.newBuilder(); + + String pagedResponseTypeName = + context + .getNamer() + .getAndSavePagedResponseTypeName( + typeTable, pageStreaming.getResourcesField().getType()); + + pagedApiCallableBuilder.requestTypeName( + typeTable.getAndSaveNicknameFor(method.getInputType())); + pagedApiCallableBuilder.responseTypeName(pagedResponseTypeName); + pagedApiCallableBuilder.name(context.getNamer().getPagedCallableName(method)); + pagedApiCallableBuilder.settingsFunctionName( + context.getNamer().getSettingsFunctionName(method)); + + apiCallables.add(pagedApiCallableBuilder.type(ApiCallableType.PagedApiCallable).build()); + } + + return apiCallables; + } + + private List generateApiMethods(SurfaceTransformerContext context) { + List apiMethods = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + MethodConfig methodConfig = context.getMethodConfig(method); + MethodTransformerContext methodContext = context.asMethodContext(method); + + if (methodConfig.isPageStreaming()) { + if (methodConfig.isFlattening()) { + for (ImmutableList fields : methodConfig.getFlattening().getFlatteningGroups()) { + apiMethods.add( + apiMethodTransformer.generatePagedFlattenedMethod(methodContext, fields)); + } + } + apiMethods.add(apiMethodTransformer.generatePagedRequestObjectMethod(methodContext)); + apiMethods.add(apiMethodTransformer.generatePagedCallableMethod(methodContext)); + apiMethods.add(apiMethodTransformer.generateUnpagedListCallableMethod(methodContext)); + } else { + if (methodConfig.isFlattening()) { + for (ImmutableList fields : methodConfig.getFlattening().getFlatteningGroups()) { + apiMethods.add(apiMethodTransformer.generateFlattenedMethod(methodContext, fields)); + } + } + apiMethods.add(apiMethodTransformer.generateRequestObjectMethod(methodContext)); + apiMethods.add(apiMethodTransformer.generateCallableMethod(methodContext)); + } + } + + return apiMethods; + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java new file mode 100644 index 0000000000..f69c9eddd5 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java @@ -0,0 +1,288 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer.java; + +import com.google.api.codegen.LanguageUtil; +import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.java.JavaTypeTable; +import com.google.api.tools.framework.model.ProtoElement; +import com.google.api.tools.framework.model.ProtoFile; +import com.google.api.tools.framework.model.TypeRef; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import com.google.common.io.Files; +import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; + +import java.io.File; +import java.util.List; + +/** + * The ModelTypeTable for Java. + */ +public class JavaModelTypeTable implements ModelTypeTable { + private JavaTypeTable javaTypeTable; + + /** + * The package prefix protoc uses if no java package option was provided. + */ + private static final String DEFAULT_JAVA_PACKAGE_PREFIX = "com.google.protos"; + + /** + * A map from primitive types in proto to Java counterparts. + */ + private static final ImmutableMap PRIMITIVE_TYPE_MAP = + ImmutableMap.builder() + .put(Type.TYPE_BOOL, "boolean") + .put(Type.TYPE_DOUBLE, "double") + .put(Type.TYPE_FLOAT, "float") + .put(Type.TYPE_INT64, "long") + .put(Type.TYPE_UINT64, "long") + .put(Type.TYPE_SINT64, "long") + .put(Type.TYPE_FIXED64, "long") + .put(Type.TYPE_SFIXED64, "long") + .put(Type.TYPE_INT32, "int") + .put(Type.TYPE_UINT32, "int") + .put(Type.TYPE_SINT32, "int") + .put(Type.TYPE_FIXED32, "int") + .put(Type.TYPE_SFIXED32, "int") + .put(Type.TYPE_STRING, "java.lang.String") + .put(Type.TYPE_BYTES, "com.google.protobuf.ByteString") + .build(); + + /** + * A map from primitive types in proto to zero value in Java + */ + private static final ImmutableMap PRIMITIVE_ZERO_VALUE = + ImmutableMap.builder() + .put(Type.TYPE_BOOL, "false") + .put(Type.TYPE_DOUBLE, "0.0") + .put(Type.TYPE_FLOAT, "0.0F") + .put(Type.TYPE_INT64, "0L") + .put(Type.TYPE_UINT64, "0L") + .put(Type.TYPE_SINT64, "0L") + .put(Type.TYPE_FIXED64, "0L") + .put(Type.TYPE_SFIXED64, "0L") + .put(Type.TYPE_INT32, "0") + .put(Type.TYPE_UINT32, "0") + .put(Type.TYPE_SINT32, "0") + .put(Type.TYPE_FIXED32, "0") + .put(Type.TYPE_SFIXED32, "0") + .put(Type.TYPE_STRING, "\"\"") + .put(Type.TYPE_BYTES, "ByteString.copyFromUtf8(\"\")") + .build(); + + /** + * Standard constructor. + */ + public JavaModelTypeTable() { + javaTypeTable = new JavaTypeTable(); + } + + @Override + public ModelTypeTable cloneEmpty() { + return new JavaModelTypeTable(); + } + + @Override + public void saveNicknameFor(String fullName) { + getAndSaveNicknameFor(fullName); + } + + @Override + public String getFullNameFor(TypeRef type) { + return getTypeName(type).getFullName(); + } + + @Override + public String getFullNameForElementType(TypeRef type) { + return getTypeNameForElementType(type, true).getFullName(); + } + + @Override + public String getNicknameFor(TypeRef type) { + return getTypeName(type).getNickname(); + } + + @Override + public String getAndSaveNicknameFor(String fullName) { + return javaTypeTable.getAndSaveNicknameFor(fullName); + } + + /** + * Returns the Java representation of a reference to a type. + */ + @Override + public String getAndSaveNicknameFor(TypeRef type) { + return javaTypeTable.getAndSaveNicknameFor(getTypeName(type)); + } + + private TypeName getTypeName(TypeRef type) { + if (type.isMap()) { + TypeName mapTypeName = javaTypeTable.getTypeName("java.util.Map"); + TypeName keyTypeName = getTypeNameForElementType(type.getMapKeyField().getType(), true); + TypeName valueTypeName = getTypeNameForElementType(type.getMapValueField().getType(), true); + return new TypeName( + mapTypeName.getFullName(), + mapTypeName.getNickname(), + "%s<%i, %i>", + keyTypeName, + valueTypeName); + } else if (type.isRepeated()) { + TypeName listTypeName = javaTypeTable.getTypeName("java.util.List"); + TypeName elementTypeName = getTypeNameForElementType(type, true); + return new TypeName( + listTypeName.getFullName(), listTypeName.getNickname(), "%s<%i>", elementTypeName); + } else { + return getTypeNameForElementType(type, false); + } + } + + @Override + public String getAndSaveNicknameForElementType(TypeRef type) { + return javaTypeTable.getAndSaveNicknameFor(getTypeNameForElementType(type, true)); + } + + @Override + public String getAndSaveNicknameForContainer(String containerFullName, String elementFullName) { + TypeName containerTypeName = javaTypeTable.getTypeName(containerFullName); + TypeName elementTypeName = javaTypeTable.getTypeName(elementFullName); + TypeName completeTypeName = + new TypeName( + containerTypeName.getFullName(), + containerTypeName.getNickname(), + "%s<%i>", + elementTypeName); + return javaTypeTable.getAndSaveNicknameFor(completeTypeName); + } + + /** + * Returns the Java representation of a type, without cardinality. If the type is a Java + * primitive, basicTypeName returns it in unboxed form. + */ + private TypeName getTypeNameForElementType(TypeRef type, boolean shouldBoxPrimitives) { + String primitiveTypeName = PRIMITIVE_TYPE_MAP.get(type.getKind()); + if (primitiveTypeName != null) { + if (primitiveTypeName.contains(".")) { + // Fully qualified type name, use regular type name resolver. Can skip boxing logic + // because those types are already boxed. + return javaTypeTable.getTypeName(primitiveTypeName); + } else { + if (shouldBoxPrimitives) { + return new TypeName(JavaTypeTable.getBoxedTypeName(primitiveTypeName)); + } else { + return new TypeName(primitiveTypeName); + } + } + } + switch (type.getKind()) { + case TYPE_MESSAGE: + return getTypeName(type.getMessageType()); + case TYPE_ENUM: + return getTypeName(type.getEnumType()); + default: + throw new IllegalArgumentException("unknown type kind: " + type.getKind()); + } + } + + @Override + public List getImports() { + return javaTypeTable.getImports(); + } + + @Override + public String renderPrimitiveValue(TypeRef type, String value) { + Type primitiveType = type.getKind(); + if (!PRIMITIVE_TYPE_MAP.containsKey(primitiveType)) { + throw new IllegalArgumentException( + "Initial values are only supported for primitive types, got type " + + type + + ", with value " + + value); + } + switch (primitiveType) { + case TYPE_BOOL: + return value.toLowerCase(); + case TYPE_FLOAT: + return value + "F"; + case TYPE_INT64: + case TYPE_UINT64: + return value + "L"; + case TYPE_STRING: + return "\"" + value + "\""; + case TYPE_BYTES: + return "ByteString.copyFromUtf8(\"" + value + "\")"; + default: + // Types that do not need to be modified (e.g. TYPE_INT32) are handled here + return value; + } + } + + /** + * Returns the Java representation of a zero value for that type, to be used in code sample doc. + * + * Parametric types may use the diamond operator, since the return value will be used only in + * initialization. + */ + @Override + public String getZeroValueAndSaveNicknameFor(TypeRef type) { + // Don't call importAndGetShortestName; we don't need to import these. + if (type.isMap()) { + return "new HashMap<>()"; + } + if (type.isRepeated()) { + return "new ArrayList<>()"; + } + if (PRIMITIVE_ZERO_VALUE.containsKey(type.getKind())) { + return PRIMITIVE_ZERO_VALUE.get(type.getKind()); + } + if (type.isMessage()) { + return getAndSaveNicknameFor(type) + ".newBuilder().build()"; + } + return "null"; + } + + private TypeName getTypeName(ProtoElement elem) { + // Construct the full name in Java + String name = getJavaPackage(elem.getFile()); + if (!elem.getFile().getProto().getOptions().getJavaMultipleFiles()) { + String outerClassName = elem.getFile().getProto().getOptions().getJavaOuterClassname(); + if (outerClassName.isEmpty()) { + outerClassName = getFileClassName(elem.getFile()); + } + name = name + "." + outerClassName; + } + String shortName = elem.getFullName().substring(elem.getFile().getFullName().length() + 1); + name = name + "." + shortName; + + return new TypeName(name, shortName); + } + + private static String getJavaPackage(ProtoFile file) { + String packageName = file.getProto().getOptions().getJavaPackage(); + if (Strings.isNullOrEmpty(packageName)) { + return DEFAULT_JAVA_PACKAGE_PREFIX + "." + file.getFullName(); + } + return packageName; + } + + /** + * Gets the class name for the given proto file. + */ + private static String getFileClassName(ProtoFile file) { + String baseName = Files.getNameWithoutExtension(new File(file.getSimpleName()).getName()); + return LanguageUtil.lowerUnderscoreToUpperCamel(baseName); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java new file mode 100644 index 0000000000..98b9a6f8b0 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java @@ -0,0 +1,77 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer.java; + +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.ServiceMessages; +import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.SurfaceNamer; +import com.google.api.codegen.util.java.JavaNameFormatter; +import com.google.api.codegen.util.java.JavaRenderingUtil; +import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; +import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.ProtoElement; +import com.google.api.tools.framework.model.TypeRef; + +import java.util.Arrays; +import java.util.List; + +/** + * The SurfaceNamer for Java. + */ +public class JavaSurfaceNamer extends SurfaceNamer { + + /** + * Standard constructor. + */ + public JavaSurfaceNamer() { + super(new JavaNameFormatter()); + } + + @Override + public List getDocLines(String text) { + return JavaRenderingUtil.getDocLines(text); + } + + @Override + public List getThrowsDocLines() { + return Arrays.asList("@throws com.google.api.gax.grpc.ApiException if the remote call fails"); + } + + @Override + public String getStaticReturnTypeName( + ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + if (ServiceMessages.s_isEmptyType(method.getOutputType())) { + return "void"; + } + return typeTable.getAndSaveNicknameFor(method.getOutputType()); + } + + @Override + public String getGenericAwareResponseType(ModelTypeTable typeTable, TypeRef outputType) { + if (ServiceMessages.s_isEmptyType(outputType)) { + return "Void"; + } else { + return typeTable.getAndSaveNicknameFor(outputType); + } + } + + @Override + public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef resourceType) { + String resourceTypeName = typeTable.getFullNameForElementType(resourceType); + return typeTable.getAndSaveNicknameForContainer( + "com.google.api.gax.core.PageAccessor", resourceTypeName); + } +} diff --git a/src/main/java/com/google/api/codegen/util/java/JavaNameFormatter.java b/src/main/java/com/google/api/codegen/util/java/JavaNameFormatter.java new file mode 100644 index 0000000000..c478fbe9da --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/java/JavaNameFormatter.java @@ -0,0 +1,65 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util.java; + +import com.google.api.codegen.util.Name; +import com.google.api.codegen.util.NameFormatter; +import com.google.api.codegen.util.NamePath; + +/** + * The NameFormatter for Java. + */ +public class JavaNameFormatter implements NameFormatter { + + @Override + public String className(Name name) { + return name.toUpperCamel(); + } + + @Override + public String varName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String varReference(Name name) { + return varName(name); + } + + @Override + public String methodName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String staticFunctionName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String inittedConstantName(Name name) { + return name.toUpperUnderscore(); + } + + @Override + public String keyName(Name name) { + return name.toLowerCamel(); + } + + @Override + public String qualifiedName(NamePath namePath) { + return namePath.toDotted(); + } +} diff --git a/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java b/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java new file mode 100644 index 0000000000..ce3a1c0899 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java @@ -0,0 +1,52 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util.java; + +import com.google.common.base.Splitter; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utility class for Java to process text in the templates. + */ +public class JavaRenderingUtil { + /** + * Escaper for formatting javadoc strings. + */ + private static final Escaper JAVADOC_ESCAPER = + Escapers.builder() + .addEscape('&', "&") + .addEscape('<', "<") + .addEscape('>', ">") + .addEscape('*', "*") + .build(); + + /** + * Splits given text into lines and returns an list of strings, each one representing a line. + * Performs escaping of certain html characters. + */ + public static List getDocLines(String text) { + // TODO: convert markdown to javadoc + List result = new ArrayList<>(); + text = JAVADOC_ESCAPER.escape(text); + for (String line : Splitter.on(String.format("%n")).split(text)) { + result.add(line); + } + return result; + } +} diff --git a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java new file mode 100644 index 0000000000..0830110afe --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java @@ -0,0 +1,136 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util.java; + +import com.google.api.codegen.LanguageUtil; +import com.google.api.codegen.util.TypeAlias; +import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.TypeTable; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * The TypeTable for Java. + */ +public class JavaTypeTable implements TypeTable { + /** + * A bi-map from full names to short names indicating the import map. + */ + private final BiMap imports = HashBiMap.create(); + + /** + * A map from simple type name to a boolean, indicating whether its in java.lang or not. If a + * simple type name is not in the map, this information is unknown. + */ + private final Map implicitImports = Maps.newHashMap(); + + private static final String JAVA_LANG_TYPE_PREFIX = "java.lang."; + + /** + * A map from unboxed Java primitive type name to boxed counterpart. + */ + private static final ImmutableMap BOXED_TYPE_MAP = + ImmutableMap.builder() + .put("boolean", "Boolean") + .put("int", "Integer") + .put("long", "Long") + .put("float", "Float") + .put("double", "Double") + .build(); + + public TypeName getTypeName(String fullName) { + int lastDotIndex = fullName.lastIndexOf('.'); + if (lastDotIndex < 0) { + throw new IllegalArgumentException("expected fully qualified name"); + } + String shortTypeName = fullName.substring(lastDotIndex + 1); + return new TypeName(fullName, shortTypeName); + } + + public String getAndSaveNicknameFor(String fullName) { + return getAndSaveNicknameFor(getTypeName(fullName)); + } + + public String getAndSaveNicknameFor(TypeName typeName) { + return typeName.getAndSaveNicknameIn(this); + } + + @Override + public String getAndSaveNicknameFor(TypeAlias alias) { + if (!alias.needsImport()) { + return alias.getNickname(); + } + // Derive a short name if possible + if (imports.containsKey(alias.getFullName())) { + // Short name already there. + return imports.get(alias.getFullName()); + } + if (imports.containsValue(alias.getNickname()) + || !alias.getFullName().startsWith(JAVA_LANG_TYPE_PREFIX) + && isImplicitImport(alias.getNickname())) { + // Short name clashes, use long name. + return alias.getFullName(); + } + imports.put(alias.getFullName(), alias.getNickname()); + return alias.getNickname(); + } + + /** + * Returns the Java representation of a basic type in boxed form. + */ + public static String getBoxedTypeName(String primitiveTypeName) { + return LanguageUtil.getRename(primitiveTypeName, BOXED_TYPE_MAP); + } + + public List getImports() { + // Clean up the imports. + List cleanedImports = new ArrayList<>(); + for (String imported : imports.keySet()) { + if (imported.startsWith(JAVA_LANG_TYPE_PREFIX)) { + // Imported type is in java.lang or in package, can be ignored. + continue; + } + cleanedImports.add(imported); + } + Collections.sort(cleanedImports); + return cleanedImports; + } + + /** + * Checks whether the simple type name is implicitly imported from java.lang. + */ + private boolean isImplicitImport(String name) { + Boolean yes = implicitImports.get(name); + if (yes != null) { + return yes; + } + // Use reflection to determine whether the name exists in java.lang. + try { + Class.forName("java.lang." + name); + yes = true; + } catch (Exception e) { + yes = false; + } + implicitImports.put(name, yes); + return yes; + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiCallableType.java b/src/main/java/com/google/api/codegen/viewmodel/ApiCallableType.java new file mode 100644 index 0000000000..0126026268 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiCallableType.java @@ -0,0 +1,21 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +public enum ApiCallableType { + SimpleApiCallable, + PagedApiCallable, + BundlingApiCallable +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiCallableView.java b/src/main/java/com/google/api/codegen/viewmodel/ApiCallableView.java new file mode 100644 index 0000000000..d28ac97b69 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiCallableView.java @@ -0,0 +1,49 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class ApiCallableView { + public abstract ApiCallableType type(); + + public abstract String requestTypeName(); + + public abstract String responseTypeName(); + + public abstract String name(); + + public abstract String settingsFunctionName(); + + public static Builder newBuilder() { + return new AutoValue_ApiCallableView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder type(ApiCallableType type); + + public abstract Builder requestTypeName(String name); + + public abstract Builder responseTypeName(String name); + + public abstract Builder name(String name); + + public abstract Builder settingsFunctionName(String name); + + public abstract ApiCallableView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/CallableMethodDetailView.java b/src/main/java/com/google/api/codegen/viewmodel/CallableMethodDetailView.java new file mode 100644 index 0000000000..b98223e3a8 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/CallableMethodDetailView.java @@ -0,0 +1,37 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class CallableMethodDetailView { + public abstract String callableName(); + + public abstract String genericAwareResponseType(); + + public static Builder newBuilder() { + return new AutoValue_CallableMethodDetailView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder callableName(String name); + + public abstract Builder genericAwareResponseType(String name); + + public abstract CallableMethodDetailView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java b/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java index af0f480c8a..b6c96b8db2 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/DynamicXApiView.java @@ -15,7 +15,6 @@ package com.google.api.codegen.viewmodel; import com.google.api.codegen.SnippetSetRunner; -import com.google.api.codegen.viewmodel.DynamicDefaultableParamView.Builder; import com.google.auto.value.AutoValue; import java.util.List; diff --git a/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java b/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java index 6a8b6d81ec..af44754685 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/FieldSettingView.java @@ -14,7 +14,6 @@ */ package com.google.api.codegen.viewmodel; -import com.google.api.codegen.viewmodel.DynamicXApiView.Builder; import com.google.auto.value.AutoValue; @AutoValue diff --git a/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java b/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java index c120dd6c33..c8d966389d 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/FormatResourceFunctionView.java @@ -14,7 +14,6 @@ */ package com.google.api.codegen.viewmodel; -import com.google.api.codegen.viewmodel.FieldSettingView.Builder; import com.google.auto.value.AutoValue; import java.util.List; diff --git a/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java b/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java index ac4a66f824..4df98bc6c9 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/InitCodeView.java @@ -14,7 +14,6 @@ */ package com.google.api.codegen.viewmodel; -import com.google.api.codegen.viewmodel.FormattedInitValueView.Builder; import com.google.auto.value.AutoValue; import java.util.List; diff --git a/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java b/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java index 1f87c9d850..5e48d2a13e 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/ListInitCodeLineView.java @@ -15,7 +15,6 @@ package com.google.api.codegen.viewmodel; import com.google.api.codegen.metacode.InitCodeLineType; -import com.google.api.codegen.viewmodel.InitCodeView.Builder; import com.google.auto.value.AutoValue; import java.util.List; diff --git a/src/main/java/com/google/api/codegen/viewmodel/ListMethodDetailView.java b/src/main/java/com/google/api/codegen/viewmodel/ListMethodDetailView.java new file mode 100644 index 0000000000..f0379366ed --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ListMethodDetailView.java @@ -0,0 +1,33 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class ListMethodDetailView { + public abstract String resourceTypeName(); + + public static Builder newBuilder() { + return new AutoValue_ListMethodDetailView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder resourceTypeName(String name); + + public abstract ListMethodDetailView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/PathTemplateCheckView.java b/src/main/java/com/google/api/codegen/viewmodel/PathTemplateCheckView.java new file mode 100644 index 0000000000..a71a6d3029 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/PathTemplateCheckView.java @@ -0,0 +1,38 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class PathTemplateCheckView { + + public abstract String pathTemplateName(); + + public abstract String paramName(); + + public static Builder newBuilder() { + return new AutoValue_PathTemplateCheckView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder pathTemplateName(String val); + + public abstract Builder paramName(String val); + + public abstract PathTemplateCheckView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/RequestObjectMethodDetailView.java b/src/main/java/com/google/api/codegen/viewmodel/RequestObjectMethodDetailView.java new file mode 100644 index 0000000000..3f1a896b53 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/RequestObjectMethodDetailView.java @@ -0,0 +1,37 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class RequestObjectMethodDetailView { + public abstract String accessModifier(); + + public abstract String callableMethodName(); + + public static Builder newBuilder() { + return new AutoValue_RequestObjectMethodDetailView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder accessModifier(String modifier); + + public abstract Builder callableMethodName(String name); + + public abstract RequestObjectMethodDetailView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java b/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java index 6900617279..4a8660c79e 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java @@ -14,13 +14,10 @@ */ package com.google.api.codegen.viewmodel; -import com.google.api.codegen.viewmodel.ApiMethodDocView.Builder; import com.google.auto.value.AutoValue; import java.util.List; -import javax.annotation.Nullable; - @AutoValue public abstract class ServiceDocView { diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java new file mode 100644 index 0000000000..146de833f3 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java @@ -0,0 +1,106 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +import javax.annotation.Nullable; + +/** + * View of a single api method. This is a union class that is capable of holding the + * data for any type of static api method; the type is maintained as a value of the + * ApiMethodType enum. + */ +@AutoValue +public abstract class StaticApiMethodView { + public abstract ApiMethodType type(); + + public abstract String apiClassName(); + + public abstract String apiVariableName(); + + public abstract InitCodeView initCode(); + + public abstract ApiMethodDocView doc(); + + public abstract String apiRequestTypeName(); + + public abstract String responseTypeName(); + + public abstract String name(); + + public abstract List methodParams(); + + public abstract List pathTemplateChecks(); + + public abstract boolean hasReturnValue(); + + public abstract List requestObjectParams(); + + @Nullable + public abstract ListMethodDetailView listMethod(); + + @Nullable + public abstract UnpagedListCallableMethodDetailView unpagedListCallableMethod(); + + @Nullable + public abstract CallableMethodDetailView callableMethod(); + + @Nullable + public abstract RequestObjectMethodDetailView requestObjectMethod(); + + public static Builder newBuilder() { + return new AutoValue_StaticApiMethodView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder type(ApiMethodType type); + + public abstract Builder apiClassName(String apiClassName); + + public abstract Builder apiVariableName(String apiVariableName); + + public abstract Builder initCode(InitCodeView initCode); + + public abstract Builder doc(ApiMethodDocView doc); + + public abstract Builder apiRequestTypeName(String requestTypeName); + + public abstract Builder responseTypeName(String responseTypeName); + + public abstract Builder name(String name); + + public abstract Builder methodParams(List methodParams); + + public abstract Builder pathTemplateChecks(List pathTemplateChecks); + + public abstract Builder hasReturnValue(boolean hasReturnValue); + + public abstract Builder requestObjectParams(List requestObjectParams); + + public abstract Builder listMethod(ListMethodDetailView details); + + public abstract Builder unpagedListCallableMethod(UnpagedListCallableMethodDetailView details); + + public abstract Builder callableMethod(CallableMethodDetailView details); + + public abstract Builder requestObjectMethod(RequestObjectMethodDetailView details); + + public abstract StaticApiMethodView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java new file mode 100644 index 0000000000..6303db79ea --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java @@ -0,0 +1,81 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.SnippetSetRunner; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class StaticXApiView implements ViewModel { + public abstract String templateFileName(); + + public abstract String packageName(); + + public abstract String name(); + + public abstract String settingsClassName(); + + public abstract List apiCallableMembers(); + + public abstract List pathTemplates(); + + public abstract List formatResourceFunctions(); + + public abstract List parseResourceFunctions(); + + public abstract List apiMethods(); + + public abstract List imports(); + + public abstract String outputPath(); + + @Override + public String resourceRoot() { + return SnippetSetRunner.SNIPPET_RESOURCE_ROOT; + } + + public static Builder newBuilder() { + return new AutoValue_StaticXApiView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder templateFileName(String val); + + public abstract Builder packageName(String val); + + public abstract Builder name(String val); + + public abstract Builder settingsClassName(String val); + + public abstract Builder apiCallableMembers(List val); + + public abstract Builder pathTemplates(List val); + + public abstract Builder formatResourceFunctions(List val); + + public abstract Builder parseResourceFunctions(List val); + + public abstract Builder apiMethods(List val); + + public abstract Builder imports(List val); + + public abstract Builder outputPath(String val); + + public abstract StaticXApiView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java new file mode 100644 index 0000000000..1882c30a2c --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java @@ -0,0 +1,69 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.SnippetSetRunner; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class StaticXSettingsView implements ViewModel { + public abstract String templateFileName(); + + public abstract String packageName(); + + public abstract String name(); + + public abstract String serviceAddress(); + + public abstract Integer servicePort(); + + public abstract Iterable authScopes(); + + public abstract List imports(); + + public abstract String outputPath(); + + @Override + public String resourceRoot() { + return SnippetSetRunner.SNIPPET_RESOURCE_ROOT; + } + + public static Builder newBuilder() { + return new AutoValue_StaticXSettingsView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder templateFileName(String val); + + public abstract Builder packageName(String val); + + public abstract Builder name(String val); + + public abstract Builder serviceAddress(String val); + + public abstract Builder servicePort(Integer val); + + public abstract Builder authScopes(Iterable val); + + public abstract Builder imports(List val); + + public abstract Builder outputPath(String val); + + public abstract StaticXSettingsView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/UnpagedListCallableMethodDetailView.java b/src/main/java/com/google/api/codegen/viewmodel/UnpagedListCallableMethodDetailView.java new file mode 100644 index 0000000000..373e5a286b --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/UnpagedListCallableMethodDetailView.java @@ -0,0 +1,33 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class UnpagedListCallableMethodDetailView { + public abstract String fnGetResourceListCall(); + + public static Builder newBuilder() { + return new AutoValue_UnpagedListCallableMethodDetailView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder fnGetResourceListCall(String name); + + public abstract UnpagedListCallableMethodDetailView build(); + } +} diff --git a/src/main/resources/com/google/api/codegen/java/mvvm_common.snip b/src/main/resources/com/google/api/codegen/java/mvvm_common.snip new file mode 100644 index 0000000000..50127de622 --- /dev/null +++ b/src/main/resources/com/google/api/codegen/java/mvvm_common.snip @@ -0,0 +1,12 @@ + +@snippet paramList(params) + @join param : params on ", " + {@param.typeName} {@param.name} + @end +@end + +@snippet argList(args) + @join arg : args on ", " + {@arg} + @end +@end diff --git a/src/main/resources/com/google/api/codegen/java/xapi.snip b/src/main/resources/com/google/api/codegen/java/xapi.snip new file mode 100644 index 0000000000..512bec17b3 --- /dev/null +++ b/src/main/resources/com/google/api/codegen/java/xapi.snip @@ -0,0 +1,341 @@ +@extends "java/mvvm_common.snip" +@extends "java/xapi_sample.snip" + +@snippet generate(xapiClass) + package {@xapiClass.packageName}; + + @join import : xapiClass.imports + import {@import}; + @end + + @@javax.annotation.Generated("by GAPIC") + public class {@xapiClass.name} implements AutoCloseable { + {@members(xapiClass)} + {@statics(xapiClass)} + {@staticFunctions(xapiClass)} + {@constructors(xapiClass)} + {@apiMethods(xapiClass)} + {@cleanupSection()} + } +@end + +@private statics(xapiClass) + @join pathTemplate : xapiClass.pathTemplates + private static final PathTemplate {@pathTemplate.name} = + PathTemplate.createWithoutUrlEncoding("{@pathTemplate.pattern}"); + {@""} + @end +@end + +@private staticFunctions(xapiClass) + @join function : xapiClass.formatResourceFunctions + {@formatResourceFunction(function)} + @end + {@""} + @join function : xapiClass.parseResourceFunctions + {@parseResourceFunction(function)} + @end +@end + +@private formatResourceFunction(function) + /** + * Formats a string containing the fully-qualified path to represent + * a {@function.entityName} resource. + */ + public static final String {@function.name}(\ + {@formatResourceFunctionParams(function.resourceIdParams)}) { + return {@function.pathTemplateName}.instantiate( + {@pathTemplateArgs(function.resourceIdParams)}); + } + {@""} +@end + +@private formatResourceFunctionParams(resourceIdParams) + @join param : resourceIdParams on ", " + String {@param.name} + @end +@end + +@private pathTemplateArgs(resourceIdParams) + @join param : resourceIdParams on ",".add(BREAK) + "{@param.templateKey}", {@param.name} + @end +@end + +@private parseResourceFunction(function) + /** + * Parses the {@function.outputResourceId} from the given fully-qualified path which + * represents a {@function.entityName} resource. + */ + public static final String {@function.name}(String {@function.entityNameParamName}) { + return {@function.pathTemplateName}.parse({@function.entityNameParamName})\ + .get("{@function.outputResourceId}"); + } + {@""} +@end + +@private members(xapiClass) + private final {@xapiClass.settingsClassName} settings; + private final ManagedChannel channel; + private final ScheduledExecutorService executor; + private final List closeables = new ArrayList<>(); + + @join apiCallable : xapiClass.apiCallableMembers + private final ApiCallable<{@apiCallable.requestTypeName}, {@apiCallable.responseTypeName}> {@apiCallable.name}; + @end + + public final {@xapiClass.settingsClassName} getSettings() { + return settings; + } + {@""} +@end + +@private constructors(xapiClass) + /** + * Constructs an instance of {@xapiClass.name} with default settings. + */ + public static final {@xapiClass.name} createWithDefaults() throws IOException { + return create({@xapiClass.settingsClassName}.defaultBuilder().build()); + } + + /** + * Constructs an instance of {@xapiClass.name}, using the given settings. + * The channels are created based on the settings passed in, or defaults for any + * settings that are not set. + */ + public static final {@xapiClass.name} create({@xapiClass.settingsClassName} settings) throws IOException { + return new {@xapiClass.name}(settings); + } + + /** + * Constructs an instance of {@xapiClass.name}, using the given settings. + * This is protected so that it easy to make a subclass, but otherwise, the static + * factory methods should be preferred. + */ + protected {@xapiClass.name}({@xapiClass.settingsClassName} settings) throws IOException { + this.settings = settings; + this.executor = settings.getExecutorProvider().getOrBuildExecutor(); + this.channel = settings.getChannelProvider().getOrBuildChannel(this.executor); + + @join apiCallable : xapiClass.apiCallableMembers + @switch apiCallable.type.toString + @case "SimpleApiCallable" + this.{@apiCallable.name} = ApiCallable.create(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); + @case "PagedApiCallable" + this.{@apiCallable.name} = + ApiCallable.createPagedVariant(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); + @case "BundlingApiCallable" + this.{@apiCallable.name} = ApiCallable.create(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); + if (settings.{@apiCallable.settingsFunctionName}().getBundlerFactory() != null) { + closeables.add(settings.{@apiCallable.settingsFunctionName}().getBundlerFactory()); + } + @default + $unhandledCase: {@apiCallable.getClass.getSimpleName}$ + @end + @end + + if (settings.getChannelProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @@Override + public void close() throws IOException { + channel.shutdown(); + } + }); + } + if (settings.getExecutorProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @@Override + public void close() throws IOException { + executor.shutdown(); + } + }); + } + } + {@""} +@end + +@private apiMethods(xapiClass) + @join apiMethod : xapiClass.apiMethods + @switch apiMethod.type.toString + @case "PagedFlattenedMethod" + {@pagedFlattenedMethod(apiMethod)} + @case "PagedRequestObjectMethod" + {@pagedRequestObjectMethod(apiMethod)} + @case "PagedCallableMethod" + {@pagedCallableMethod(apiMethod)} + @case "UnpagedListCallableMethod" + {@unpagedListCallableMethod(apiMethod)} + @case "FlattenedMethod" + {@flattenedMethod(apiMethod)} + @case "RequestObjectMethod" + {@requestObjectMethod(apiMethod)} + @case "CallableMethod" + {@callableMethod(apiMethod)} + @default + $unhandledCase: {@apiMethod.getClass.getSimpleName}$ + @end + {@BREAK} + @end +@end + +@private cleanupSection() + /** + * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately + * cancelled. + */ + @@Override + public final void close() throws Exception { + for (AutoCloseable closeable : closeables) { + closeable.close(); + } + } + +@end + +@private pagedFlattenedMethod(apiMethod) + @let coreSampleCode = pagedIterableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + public final {@apiMethod.responseTypeName} {@apiMethod.name}({@paramList(apiMethod.methodParams)}) { + @join pathTemplateCheck : apiMethod.pathTemplateChecks + {@pathTemplateCheckLine(pathTemplateCheck)} + @end + {@apiMethod.apiRequestTypeName} request = + {@apiMethod.apiRequestTypeName}.newBuilder() + {@builderSetCalls(apiMethod.requestObjectParams)} + .build(); + return {@apiMethod.name}(request); + } +@end + +@private pagedRequestObjectMethod(apiMethod) + @let coreSampleCode = pagedIterableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + {@apiMethod.requestObjectMethod.accessModifier} final {@apiMethod.responseTypeName} \ + {@apiMethod.name}({@apiMethod.apiRequestTypeName} request) { + return {@apiMethod.requestObjectMethod.callableMethodName}() + .call(request); + } +@end + +@private pagedCallableMethod(apiMethod) + @let coreSampleCode = pagedCallableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + {@callableMethodImpl(apiMethod)} +@end + +@private unpagedListCallableMethod(apiMethod) + @let coreSampleCode = unpagedListCallableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + {@callableMethodImpl(apiMethod)} +@end + +@private flattenedMethod(apiMethod) + @let coreSampleCode = syncMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + public final {@apiMethod.responseTypeName} {@apiMethod.name}(\ + {@paramList(apiMethod.methodParams)}) { + @join pathTemplateCheck : apiMethod.pathTemplateChecks + {@pathTemplateCheckLine(pathTemplateCheck)} + @end + {@apiMethod.apiRequestTypeName} request = + {@apiMethod.apiRequestTypeName}.newBuilder() + {@builderSetCalls(apiMethod.requestObjectParams)} + .build(); + @if apiMethod.hasReturnValue + return {@apiMethod.name}(request); + @else + {@apiMethod.name}(request); + @end + } +@end + +@private requestObjectMethod(apiMethod) + @let coreSampleCode = syncMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + {@apiMethod.requestObjectMethod.accessModifier} final {@apiMethod.responseTypeName} \ + {@apiMethod.name}({@apiMethod.apiRequestTypeName} request) { + @if apiMethod.hasReturnValue + return {@apiMethod.requestObjectMethod.callableMethodName}().call(request); + @else + {@apiMethod.requestObjectMethod.callableMethodName}().call(request); + @end + } +@end + +@private callableMethod(apiMethod) + @let coreSampleCode = callableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} + @end + {@callableMethodImpl(apiMethod)} +@end + +@private callableMethodImpl(apiMethod) + public final ApiCallable<{@apiMethod.apiRequestTypeName}, {@apiMethod.responseTypeName}> \ + {@apiMethod.name}() { + return {@apiMethod.callableMethod.callableName}; + } +@end + +@private methodDoc(apiMethodDoc, methodSampleCode) + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + @join commentLine : apiMethodDoc.mainDocLines + {@""} * {@commentLine} + @end + * + * Sample code: + *

+  @join sampleLine : util.getDocLines(methodSampleCode)
+    {@""} * {@sampleLine}
+  @end
+   * 
+ @if apiMethodDoc.paramDocs + {@""} * + @join doc : apiMethodDoc.paramDocs + {@paramDoc(doc)} + @end + @end + @if apiMethodDoc.throwsDocLines + @join commentLine : apiMethodDoc.throwsDocLines + {@""} * {@commentLine} + @end + @end + */ + {@EMPTY} +@end + +@private paramDoc(doc) + @switch doc.type + @case "SimpleParamDocView" + {@simpleParamDoc(doc)} + @default + $unhandledCase: {@doc.type}$ + @end +@end + +@private simpleParamDoc(doc) + {@""} * @@param {@doc.paramName} {@doc.firstLine} + @if doc.remainingLines + @join commentLine : doc.remainingLines + {@""} * {@commentLine} + @end + @end +@end + +@private builderSetCalls(requestObjectParams) + @join requestObjectParam : requestObjectParams + .{@requestObjectParam.setCallName}({@requestObjectParam.name}) + @end +@end + +@private pathTemplateCheckLine(pathTemplateCheck) + {@pathTemplateCheck.pathTemplateName}.validate({@pathTemplateCheck.paramName}); +@end diff --git a/src/main/resources/com/google/api/codegen/java/xapi_sample.snip b/src/main/resources/com/google/api/codegen/java/xapi_sample.snip new file mode 100644 index 0000000000..bda454a0e8 --- /dev/null +++ b/src/main/resources/com/google/api/codegen/java/xapi_sample.snip @@ -0,0 +1,131 @@ +@extends "java/mvvm_common.snip" + +@snippet decorateSampleCode(apiMethod, coreSampleCode) + try ({@apiMethod.apiClassName} {@apiMethod.apiVariableName} = \ + {@apiMethod.apiClassName}.createWithDefaults()) { + {@coreSampleCode} + } +@end + +@snippet pagedIterableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + for ({@apiMethod.listMethod.resourceTypeName} element : {@sampleSyncMethodCall(apiMethod)}) { + // doThingsWith(element); + } +@end + +@snippet pagedCallableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + ListenableFuture<{@apiMethod.responseTypeName}> future = {@sampleFutureMethodCall(apiMethod)}; + // Do something + for ({@apiMethod.listMethod.resourceTypeName} element : future.get()) { + // doThingsWith(element); + } +@end + +@snippet unpagedListCallableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + while (true) { + {@apiMethod.responseTypeName} response = \ + {@apiMethod.apiVariableName}.{@apiMethod.name}().call(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}); + for ({@apiMethod.listMethod.resourceTypeName} element : \ + response.{@apiMethod.unpagedListCallableMethod.fnGetResourceListCall}()) { + // doThingsWith(element); + } + String nextPageToken = response.getNextPageToken(); + if (!Strings.isNullOrEmpty(nextPageToken)) { + request = request.toBuilder().setPageToken(nextPageToken).build(); + } else { + break; + } + } +@end + +@snippet syncMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + @if apiMethod.hasReturnValue + {@apiMethod.responseTypeName} response = {@sampleSyncMethodCall(apiMethod)}; + @else + {@sampleSyncMethodCall(apiMethod)}; + @end +@end + +@snippet callableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + ListenableFuture<{@apiMethod.callableMethod.genericAwareResponseType}> future = {@sampleFutureMethodCall(apiMethod)}; + // Do something + @if apiMethod.hasReturnValue + {@apiMethod.responseTypeName} response = future.get(); + @else + future.get(); + @end +@end + +@private sampleFutureMethodCall(apiMethod) + {@apiMethod.apiVariableName}.{@apiMethod.name}().futureCall(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) +@end + +@private sampleSyncMethodCall(apiMethod) + {@apiMethod.apiVariableName}.{@apiMethod.name}(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) +@end + +@private sampleMethodCallArgList(fieldSettings) + @join fieldSetting : fieldSettings on ", " + {@fieldSetting.identifier} + @end +@end + +@private initCode(initCodeSpec) + @join line : initCodeSpec.lines + @switch line.lineType.toString + @case "StructureInitLine" + {@initLineStructure(line)} + @case "ListInitLine" + {@initLineList(line)} + @case "MapInitLine" + {@initLineMap(line)} + @case "SimpleInitLine" + {@initLineSimple(line)} + @default + $unhandledCase: {@line.lineType.toString}$ + @end + @end +@end + +@private initLineStructure(line) + {@line.typeName} {@line.identifier} = {@line.typeName}.newBuilder() + @join fieldSetting : line.fieldSettings + {@EMPTY} .{@fieldSetting.fnSetFunctionCallName}({@fieldSetting.identifier}) + @end + {@EMPTY} .build(); +@end + +@private initLineList(line) + List<{@line.elementTypeName}> {@line.identifier} = \ + Arrays.asList({@argList(line.elementIdentifiers)}); +@end + +@private initLineMap(line) + Map<{@line.keyTypeName}, {@line.valueTypeName}> {@line.identifier} = new HashMap<>(); + @join mapEntry : line.initEntries vertical + {@line.identifier}.put({@mapEntry.key}, {@mapEntry.value}); + @end +@end + +@private initLineSimple(line) + {@line.typeName} {@line.identifier} = {@renderInitValue(line.initValue)}; +@end + +@private renderInitValue(initValue) + @switch initValue.type + @case "SimpleInitValueView" + {@initValue.initialValue} + @case "FormattedInitValueView" + {@initValue.apiWrapperName}.{@initValue.formatFunctionName}({@argList(initValue.formatArgs)}) + @default + $unhandledCase: {@initValue.type}$ + @end +@end diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip new file mode 100644 index 0000000000..928317d72e --- /dev/null +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -0,0 +1,43 @@ +@snippet generate(xsettingsClass) + package {@xsettingsClass.packageName}; + + @join import : xsettingsClass.imports + import {@import}; + @end + + @@javax.annotation.Generated("by GAPIC") + public class {@xsettingsClass.name} extends ServiceApiSettings { + {@constants(xsettingsClass)} + } +@end + +@private constants(xsettingsClass) + /** + * The default address of the service. + */ + public static final String DEFAULT_SERVICE_ADDRESS = "{@xsettingsClass.serviceAddress}"; + + /** + * The default port of the service. + */ + public static final int DEFAULT_SERVICE_PORT = {@xsettingsClass.servicePort}; + + /** + * The default scopes of the service. + */ + public static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() + @join scope : {@xsettingsClass.authScopes} + .add("{@scope}") + @end + .build(); + + /** + * The default connection settings of the service. + */ + public static final ConnectionSettings DEFAULT_CONNECTION_SETTINGS = + ConnectionSettings.newBuilder() + .setServiceAddress(DEFAULT_SERVICE_ADDRESS) + .setPort(DEFAULT_SERVICE_PORT) + .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) + .build(); +@end diff --git a/src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java b/src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java new file mode 100644 index 0000000000..48c0f20bfc --- /dev/null +++ b/src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java @@ -0,0 +1,57 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen; + +import com.google.api.codegen.gapic.MainGapicProviderFactory; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Java code generator baseline tests. + */ +@RunWith(Parameterized.class) +public class JavaSurfaceCodeGeneratorTest extends GapicTestBase { + + public JavaSurfaceCodeGeneratorTest( + String name, String idForFactory, String[] gapicConfigFileNames, String snippetName) { + super(name, idForFactory, gapicConfigFileNames, snippetName); + getTestDataLocator() + .addTestDataSource(com.google.api.codegen.java.JavaSnippetSetRunner.class, ""); + } + + /** + * Declares test parameters, each one an array of values passed to the constructor, with the + * first element a name, the second a config of this name. + */ + @Parameters(name = "{0}") + public static List testedConfigs() { + return GapicTestBase.createTestedConfigs( + MainGapicProviderFactory.JAVA_SURFACE, + new String[] {"java_gapic.yaml", "library_gapic.yaml"}); + } + + // Tests + // ===== + + @Test + public void library() throws Exception { + test("library"); + } +} diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline new file mode 100644 index 0000000000..a907bc5519 --- /dev/null +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline @@ -0,0 +1,1580 @@ +============== file: src/main/java/com/google/gcloud/pubsub/spi/LibraryServiceApi.java ============== +package com.google.gcloud.pubsub.spi; + +import com.google.api.gax.core.PageAccessor; +import com.google.api.gax.grpc.ApiCallable; +import com.google.api.gax.protobuf.PathTemplate; +import com.google.example.library.v1.AddCommentsRequest; +import com.google.example.library.v1.Book; +import com.google.example.library.v1.Comment; +import com.google.example.library.v1.CreateBookRequest; +import com.google.example.library.v1.CreateShelfRequest; +import com.google.example.library.v1.DeleteBookRequest; +import com.google.example.library.v1.DeleteShelfRequest; +import com.google.example.library.v1.GetBookFromArchiveRequest; +import com.google.example.library.v1.GetBookRequest; +import com.google.example.library.v1.GetShelfRequest; +import com.google.example.library.v1.ListBooksRequest; +import com.google.example.library.v1.ListBooksResponse; +import com.google.example.library.v1.ListShelvesRequest; +import com.google.example.library.v1.ListShelvesResponse; +import com.google.example.library.v1.ListStringsRequest; +import com.google.example.library.v1.ListStringsResponse; +import com.google.example.library.v1.MergeShelvesRequest; +import com.google.example.library.v1.MoveBookRequest; +import com.google.example.library.v1.PublishSeriesRequest; +import com.google.example.library.v1.PublishSeriesResponse; +import com.google.example.library.v1.Shelf; +import com.google.example.library.v1.SomeMessage; +import com.google.example.library.v1.UpdateBookIndexRequest; +import com.google.example.library.v1.UpdateBookIndexRequest.IndexMapEntry; +import com.google.example.library.v1.UpdateBookRequest; +import com.google.protobuf.ByteString; +import com.google.protobuf.Empty; +import com.google.protobuf.FieldMask; +import io.grpc.ManagedChannel; +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; + +@javax.annotation.Generated("by GAPIC") +public class LibraryServiceApi implements AutoCloseable { + private final LibraryServiceSettings settings; + private final ManagedChannel channel; + private final ScheduledExecutorService executor; + private final List closeables = new ArrayList<>(); + + private final ApiCallable createShelfCallable; + private final ApiCallable getShelfCallable; + private final ApiCallable listShelvesCallable; + private final ApiCallable> listShelvesPagedCallable; + private final ApiCallable deleteShelfCallable; + private final ApiCallable mergeShelvesCallable; + private final ApiCallable createBookCallable; + private final ApiCallable publishSeriesCallable; + private final ApiCallable getBookCallable; + private final ApiCallable listBooksCallable; + private final ApiCallable> listBooksPagedCallable; + private final ApiCallable deleteBookCallable; + private final ApiCallable updateBookCallable; + private final ApiCallable moveBookCallable; + private final ApiCallable listStringsCallable; + private final ApiCallable> listStringsPagedCallable; + private final ApiCallable addCommentsCallable; + private final ApiCallable getBookFromArchiveCallable; + private final ApiCallable updateBookIndexCallable; + + public final LibraryServiceSettings getSettings() { + return settings; + } + + private static final PathTemplate SHELF_PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("shelves/{shelf}"); + + private static final PathTemplate BOOK_PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("shelves/{shelf}/books/{book}"); + + private static final PathTemplate ARCHIVED_BOOK_PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("archives/{archive_path=**}/books/{book}"); + + /** + * Formats a string containing the fully-qualified path to represent + * a shelf resource. + */ + public static final String formatShelfName(String shelf) { + return SHELF_PATH_TEMPLATE.instantiate( + "shelf", shelf); + } + + /** + * Formats a string containing the fully-qualified path to represent + * a book resource. + */ + public static final String formatBookName(String shelf, String book) { + return BOOK_PATH_TEMPLATE.instantiate( + "shelf", shelf, + "book", book); + } + + /** + * Formats a string containing the fully-qualified path to represent + * a archived_book resource. + */ + public static final String formatArchivedBookName(String archivePath, String book) { + return ARCHIVED_BOOK_PATH_TEMPLATE.instantiate( + "archive_path", archivePath, + "book", book); + } + + /** + * Parses the shelf from the given fully-qualified path which + * represents a shelf resource. + */ + public static final String parseShelfFromShelfName(String shelfName) { + return SHELF_PATH_TEMPLATE.parse(shelfName).get("shelf"); + } + + /** + * Parses the shelf from the given fully-qualified path which + * represents a book resource. + */ + public static final String parseShelfFromBookName(String bookName) { + return BOOK_PATH_TEMPLATE.parse(bookName).get("shelf"); + } + + /** + * Parses the book from the given fully-qualified path which + * represents a book resource. + */ + public static final String parseBookFromBookName(String bookName) { + return BOOK_PATH_TEMPLATE.parse(bookName).get("book"); + } + + /** + * Parses the archive_path from the given fully-qualified path which + * represents a archivedBook resource. + */ + public static final String parseArchivePathFromArchivedBookName(String archivedBookName) { + return ARCHIVED_BOOK_PATH_TEMPLATE.parse(archivedBookName).get("archive_path"); + } + + /** + * Parses the book from the given fully-qualified path which + * represents a archivedBook resource. + */ + public static final String parseBookFromArchivedBookName(String archivedBookName) { + return ARCHIVED_BOOK_PATH_TEMPLATE.parse(archivedBookName).get("book"); + } + + /** + * Constructs an instance of LibraryServiceApi with default settings. + */ + public static final LibraryServiceApi createWithDefaults() throws IOException { + return create(LibraryServiceSettings.defaultBuilder().build()); + } + + /** + * Constructs an instance of LibraryServiceApi, using the given settings. + * The channels are created based on the settings passed in, or defaults for any + * settings that are not set. + */ + public static final LibraryServiceApi create(LibraryServiceSettings settings) throws IOException { + return new LibraryServiceApi(settings); + } + + /** + * Constructs an instance of LibraryServiceApi, using the given settings. + * This is protected so that it easy to make a subclass, but otherwise, the static + * factory methods should be preferred. + */ + protected LibraryServiceApi(LibraryServiceSettings settings) throws IOException { + this.settings = settings; + this.executor = settings.getExecutorProvider().getOrBuildExecutor(); + this.channel = settings.getChannelProvider().getOrBuildChannel(this.executor); + + this.createShelfCallable = ApiCallable.create(settings.createShelfSettings(), this.channel, this.executor); + this.getShelfCallable = ApiCallable.create(settings.getShelfSettings(), this.channel, this.executor); + this.listShelvesCallable = ApiCallable.create(settings.listShelvesSettings(), this.channel, this.executor); + this.listShelvesPagedCallable = + ApiCallable.createPagedVariant(settings.listShelvesSettings(), this.channel, this.executor); + this.deleteShelfCallable = ApiCallable.create(settings.deleteShelfSettings(), this.channel, this.executor); + this.mergeShelvesCallable = ApiCallable.create(settings.mergeShelvesSettings(), this.channel, this.executor); + this.createBookCallable = ApiCallable.create(settings.createBookSettings(), this.channel, this.executor); + this.publishSeriesCallable = ApiCallable.create(settings.publishSeriesSettings(), this.channel, this.executor); + if (settings.publishSeriesSettings().getBundlerFactory() != null) { + closeables.add(settings.publishSeriesSettings().getBundlerFactory()); + } + this.getBookCallable = ApiCallable.create(settings.getBookSettings(), this.channel, this.executor); + this.listBooksCallable = ApiCallable.create(settings.listBooksSettings(), this.channel, this.executor); + this.listBooksPagedCallable = + ApiCallable.createPagedVariant(settings.listBooksSettings(), this.channel, this.executor); + this.deleteBookCallable = ApiCallable.create(settings.deleteBookSettings(), this.channel, this.executor); + this.updateBookCallable = ApiCallable.create(settings.updateBookSettings(), this.channel, this.executor); + this.moveBookCallable = ApiCallable.create(settings.moveBookSettings(), this.channel, this.executor); + this.listStringsCallable = ApiCallable.create(settings.listStringsSettings(), this.channel, this.executor); + this.listStringsPagedCallable = + ApiCallable.createPagedVariant(settings.listStringsSettings(), this.channel, this.executor); + this.addCommentsCallable = ApiCallable.create(settings.addCommentsSettings(), this.channel, this.executor); + this.getBookFromArchiveCallable = ApiCallable.create(settings.getBookFromArchiveSettings(), this.channel, this.executor); + this.updateBookIndexCallable = ApiCallable.create(settings.updateBookIndexSettings(), this.channel, this.executor); + + if (settings.getChannelProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @Override + public void close() throws IOException { + channel.shutdown(); + } + }); + } + if (settings.getExecutorProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @Override + public void close() throws IOException { + executor.shutdown(); + } + }); + } + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a shelf, and returns the new Shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   Shelf shelf = Shelf.newBuilder().build();
+   *   Shelf response = libraryServiceApi.createShelf(shelf);
+   * }
+   * 
+ * + * @param shelf The shelf to create. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf createShelf(Shelf shelf) { + CreateShelfRequest request = + CreateShelfRequest.newBuilder() + .setShelf(shelf) + .build(); + return createShelf(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a shelf, and returns the new Shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   Shelf shelf = Shelf.newBuilder().build();
+   *   CreateShelfRequest request = CreateShelfRequest.newBuilder()
+   *     .setShelf(shelf)
+   *     .build();
+   *   Shelf response = libraryServiceApi.createShelf(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final Shelf createShelf(CreateShelfRequest request) { + return createShelfCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a shelf, and returns the new Shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   Shelf shelf = Shelf.newBuilder().build();
+   *   CreateShelfRequest request = CreateShelfRequest.newBuilder()
+   *     .setShelf(shelf)
+   *     .build();
+   *   ListenableFuture<Shelf> future = libraryServiceApi.createShelfCallable().futureCall(request);
+   *   // Do something
+   *   Shelf response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable createShelfCallable() { + return createShelfCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   Shelf response = libraryServiceApi.getShelf(formattedName);
+   * }
+   * 
+ * + * @param name The name of the shelf to retrieve. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf getShelf(String name) { + SHELF_PATH_TEMPLATE.validate(name); + GetShelfRequest request = + GetShelfRequest.newBuilder() + .setName(name) + .build(); + return getShelf(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   SomeMessage message = SomeMessage.newBuilder().build();
+   *   Shelf response = libraryServiceApi.getShelf(formattedName, message);
+   * }
+   * 
+ * + * @param name The name of the shelf to retrieve. + * @param message Field to verify that message-type query parameter gets flattened. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf getShelf(String name, SomeMessage message) { + SHELF_PATH_TEMPLATE.validate(name); + GetShelfRequest request = + GetShelfRequest.newBuilder() + .setName(name) + .setMessage(message) + .build(); + return getShelf(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   SomeMessage message = SomeMessage.newBuilder().build();
+   *   com.google.example.library.v1.StringBuilder stringBuilder = com.google.example.library.v1.StringBuilder.newBuilder().build();
+   *   Shelf response = libraryServiceApi.getShelf(formattedName, message, stringBuilder);
+   * }
+   * 
+ * + * @param name The name of the shelf to retrieve. + * @param message Field to verify that message-type query parameter gets flattened. + * @param stringBuilder + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf getShelf(String name, SomeMessage message, com.google.example.library.v1.StringBuilder stringBuilder) { + SHELF_PATH_TEMPLATE.validate(name); + GetShelfRequest request = + GetShelfRequest.newBuilder() + .setName(name) + .setMessage(message) + .setStringBuilder(stringBuilder) + .build(); + return getShelf(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   String options = "";
+   *   GetShelfRequest request = GetShelfRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setOptions(options)
+   *     .build();
+   *   Shelf response = libraryServiceApi.getShelf(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf getShelf(GetShelfRequest request) { + return getShelfCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   String options = "";
+   *   GetShelfRequest request = GetShelfRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setOptions(options)
+   *     .build();
+   *   ListenableFuture<Shelf> future = libraryServiceApi.getShelfCallable().futureCall(request);
+   *   // Do something
+   *   Shelf response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable getShelfCallable() { + return getShelfCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists shelves. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *
+   *   for (Shelf element : libraryServiceApi.listShelves()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final PageAccessor listShelves() { + ListShelvesRequest request = + ListShelvesRequest.newBuilder() + + .build(); + return listShelves(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists shelves. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   ListShelvesRequest request = ListShelvesRequest.newBuilder()
+   *     .build();
+   *   for (Shelf element : libraryServiceApi.listShelves(request)) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final PageAccessor listShelves(ListShelvesRequest request) { + return listShelvesPagedCallable() + .call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists shelves. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   ListShelvesRequest request = ListShelvesRequest.newBuilder()
+   *     .build();
+   *   ListenableFuture<PageAccessor<Shelf>> future = libraryServiceApi.listShelvesPagedCallable().futureCall(request);
+   *   // Do something
+   *   for (Shelf element : future.get()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ */ + public final ApiCallable> listShelvesPagedCallable() { + return listShelvesPagedCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists shelves. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   ListShelvesRequest request = ListShelvesRequest.newBuilder()
+   *     .build();
+   *   while (true) {
+   *     ListShelvesResponse response = libraryServiceApi.listShelvesCallable().call(request);
+   *     for (Shelf element : response.getShelvesList()) {
+   *       // doThingsWith(element);
+   *     }
+   *     String nextPageToken = response.getNextPageToken();
+   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
+   *       request = request.toBuilder().setPageToken(nextPageToken).build();
+   *     } else {
+   *       break;
+   *     }
+   *   }
+   * }
+   * 
+ */ + public final ApiCallable listShelvesCallable() { + return listShelvesCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Deletes a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   libraryServiceApi.deleteShelf(formattedName);
+   * }
+   * 
+ * + * @param name The name of the shelf to delete. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void deleteShelf(String name) { + SHELF_PATH_TEMPLATE.validate(name); + DeleteShelfRequest request = + DeleteShelfRequest.newBuilder() + .setName(name) + .build(); + deleteShelf(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Deletes a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   DeleteShelfRequest request = DeleteShelfRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   libraryServiceApi.deleteShelf(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final void deleteShelf(DeleteShelfRequest request) { + deleteShelfCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Deletes a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   DeleteShelfRequest request = DeleteShelfRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   ListenableFuture<Void> future = libraryServiceApi.deleteShelfCallable().futureCall(request);
+   *   // Do something
+   *   future.get();
+   * }
+   * 
+ */ + public final ApiCallable deleteShelfCallable() { + return deleteShelfCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Merges two shelves by adding all books from the shelf named + * `other_shelf_name` to shelf `name`, and deletes + * `other_shelf_name`. Returns the updated shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   Shelf response = libraryServiceApi.mergeShelves(formattedName, formattedOtherShelfName);
+   * }
+   * 
+ * + * @param name The name of the shelf we're adding books to. + * @param otherShelfName The name of the shelf we're removing books from and deleting. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf mergeShelves(String name, String otherShelfName) { + SHELF_PATH_TEMPLATE.validate(name); + SHELF_PATH_TEMPLATE.validate(otherShelfName); + MergeShelvesRequest request = + MergeShelvesRequest.newBuilder() + .setName(name) + .setOtherShelfName(otherShelfName) + .build(); + return mergeShelves(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Merges two shelves by adding all books from the shelf named + * `other_shelf_name` to shelf `name`, and deletes + * `other_shelf_name`. Returns the updated shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   MergeShelvesRequest request = MergeShelvesRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setOtherShelfName(formattedOtherShelfName)
+   *     .build();
+   *   Shelf response = libraryServiceApi.mergeShelves(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Shelf mergeShelves(MergeShelvesRequest request) { + return mergeShelvesCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Merges two shelves by adding all books from the shelf named + * `other_shelf_name` to shelf `name`, and deletes + * `other_shelf_name`. Returns the updated shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   MergeShelvesRequest request = MergeShelvesRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setOtherShelfName(formattedOtherShelfName)
+   *     .build();
+   *   ListenableFuture<Shelf> future = libraryServiceApi.mergeShelvesCallable().futureCall(request);
+   *   // Do something
+   *   Shelf response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable mergeShelvesCallable() { + return mergeShelvesCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   Book book = Book.newBuilder().build();
+   *   Book response = libraryServiceApi.createBook(formattedName, book);
+   * }
+   * 
+ * + * @param name The name of the shelf in which the book is created. + * @param book The book to create. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book createBook(String name, Book book) { + SHELF_PATH_TEMPLATE.validate(name); + CreateBookRequest request = + CreateBookRequest.newBuilder() + .setName(name) + .setBook(book) + .build(); + return createBook(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   Book book = Book.newBuilder().build();
+   *   CreateBookRequest request = CreateBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setBook(book)
+   *     .build();
+   *   Book response = libraryServiceApi.createBook(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book createBook(CreateBookRequest request) { + return createBookCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   Book book = Book.newBuilder().build();
+   *   CreateBookRequest request = CreateBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setBook(book)
+   *     .build();
+   *   ListenableFuture<Book> future = libraryServiceApi.createBookCallable().futureCall(request);
+   *   // Do something
+   *   Book response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable createBookCallable() { + return createBookCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a series of books. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   Shelf shelf = Shelf.newBuilder().build();
+   *   List<Book> books = new ArrayList<>();
+   *   int edition = 0;
+   *   PublishSeriesResponse response = libraryServiceApi.publishSeries(shelf, books, edition);
+   * }
+   * 
+ * + * @param shelf The shelf in which the series is created. + * @param books The books to publish in the series. + * @param edition The edition of the series + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final PublishSeriesResponse publishSeries(Shelf shelf, List books, int edition) { + PublishSeriesRequest request = + PublishSeriesRequest.newBuilder() + .setShelf(shelf) + .addAllBooks(books) + .setEdition(edition) + .build(); + return publishSeries(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a series of books. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   Shelf shelf = Shelf.newBuilder().build();
+   *   List<Book> books = new ArrayList<>();
+   *   PublishSeriesRequest request = PublishSeriesRequest.newBuilder()
+   *     .setShelf(shelf)
+   *     .addAllBooks(books)
+   *     .build();
+   *   PublishSeriesResponse response = libraryServiceApi.publishSeries(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final PublishSeriesResponse publishSeries(PublishSeriesRequest request) { + return publishSeriesCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Creates a series of books. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   Shelf shelf = Shelf.newBuilder().build();
+   *   List<Book> books = new ArrayList<>();
+   *   PublishSeriesRequest request = PublishSeriesRequest.newBuilder()
+   *     .setShelf(shelf)
+   *     .addAllBooks(books)
+   *     .build();
+   *   ListenableFuture<PublishSeriesResponse> future = libraryServiceApi.publishSeriesCallable().futureCall(request);
+   *   // Do something
+   *   PublishSeriesResponse response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable publishSeriesCallable() { + return publishSeriesCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   Book response = libraryServiceApi.getBook(formattedName);
+   * }
+   * 
+ * + * @param name The name of the book to retrieve. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book getBook(String name) { + BOOK_PATH_TEMPLATE.validate(name); + GetBookRequest request = + GetBookRequest.newBuilder() + .setName(name) + .build(); + return getBook(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   GetBookRequest request = GetBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   Book response = libraryServiceApi.getBook(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final Book getBook(GetBookRequest request) { + return getBookCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   GetBookRequest request = GetBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   ListenableFuture<Book> future = libraryServiceApi.getBookCallable().futureCall(request);
+   *   // Do something
+   *   Book response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable getBookCallable() { + return getBookCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists books in a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   String filter = "";
+   *   for (Book element : libraryServiceApi.listBooks(formattedName, filter)) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ * + * @param name The name of the shelf whose books we'd like to list. + * @param filter To test python built-in wrapping. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final PageAccessor listBooks(String name, String filter) { + SHELF_PATH_TEMPLATE.validate(name); + ListBooksRequest request = + ListBooksRequest.newBuilder() + .setName(name) + .setFilter(filter) + .build(); + return listBooks(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists books in a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   ListBooksRequest request = ListBooksRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   for (Book element : libraryServiceApi.listBooks(request)) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final PageAccessor listBooks(ListBooksRequest request) { + return listBooksPagedCallable() + .call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists books in a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   ListBooksRequest request = ListBooksRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   ListenableFuture<PageAccessor<Book>> future = libraryServiceApi.listBooksPagedCallable().futureCall(request);
+   *   // Do something
+   *   for (Book element : future.get()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ */ + public final ApiCallable> listBooksPagedCallable() { + return listBooksPagedCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists books in a shelf. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   ListBooksRequest request = ListBooksRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   while (true) {
+   *     ListBooksResponse response = libraryServiceApi.listBooksCallable().call(request);
+   *     for (Book element : response.getBooksList()) {
+   *       // doThingsWith(element);
+   *     }
+   *     String nextPageToken = response.getNextPageToken();
+   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
+   *       request = request.toBuilder().setPageToken(nextPageToken).build();
+   *     } else {
+   *       break;
+   *     }
+   *   }
+   * }
+   * 
+ */ + public final ApiCallable listBooksCallable() { + return listBooksCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Deletes a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   libraryServiceApi.deleteBook(formattedName);
+   * }
+   * 
+ * + * @param name The name of the book to delete. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void deleteBook(String name) { + BOOK_PATH_TEMPLATE.validate(name); + DeleteBookRequest request = + DeleteBookRequest.newBuilder() + .setName(name) + .build(); + deleteBook(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Deletes a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   DeleteBookRequest request = DeleteBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   libraryServiceApi.deleteBook(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final void deleteBook(DeleteBookRequest request) { + deleteBookCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Deletes a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   DeleteBookRequest request = DeleteBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   ListenableFuture<Void> future = libraryServiceApi.deleteBookCallable().futureCall(request);
+   *   // Do something
+   *   future.get();
+   * }
+   * 
+ */ + public final ApiCallable deleteBookCallable() { + return deleteBookCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   Book book = Book.newBuilder().build();
+   *   Book response = libraryServiceApi.updateBook(formattedName, book);
+   * }
+   * 
+ * + * @param name The name of the book to update. + * @param book The book to update with. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book updateBook(String name, Book book) { + BOOK_PATH_TEMPLATE.validate(name); + UpdateBookRequest request = + UpdateBookRequest.newBuilder() + .setName(name) + .setBook(book) + .build(); + return updateBook(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   Book book = Book.newBuilder().build();
+   *   FieldMask updateMask = FieldMask.newBuilder().build();
+   *   com.google.example.library.v1.FieldMask physicalMask = com.google.example.library.v1.FieldMask.newBuilder().build();
+   *   Book response = libraryServiceApi.updateBook(formattedName, book, updateMask, physicalMask);
+   * }
+   * 
+ * + * @param name The name of the book to update. + * @param book The book to update with. + * @param updateMask A field mask to apply, rendered as an HTTP parameter. + * @param physicalMask To test Python import clash resolution. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book updateBook(String name, Book book, FieldMask updateMask, com.google.example.library.v1.FieldMask physicalMask) { + BOOK_PATH_TEMPLATE.validate(name); + UpdateBookRequest request = + UpdateBookRequest.newBuilder() + .setName(name) + .setBook(book) + .setUpdateMask(updateMask) + .setPhysicalMask(physicalMask) + .build(); + return updateBook(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   Book book = Book.newBuilder().build();
+   *   UpdateBookRequest request = UpdateBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setBook(book)
+   *     .build();
+   *   Book response = libraryServiceApi.updateBook(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book updateBook(UpdateBookRequest request) { + return updateBookCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   Book book = Book.newBuilder().build();
+   *   UpdateBookRequest request = UpdateBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setBook(book)
+   *     .build();
+   *   ListenableFuture<Book> future = libraryServiceApi.updateBookCallable().futureCall(request);
+   *   // Do something
+   *   Book response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable updateBookCallable() { + return updateBookCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Moves a book to another shelf, and returns the new book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   Book response = libraryServiceApi.moveBook(formattedName, formattedOtherShelfName);
+   * }
+   * 
+ * + * @param name The name of the book to move. + * @param otherShelfName The name of the destination shelf. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book moveBook(String name, String otherShelfName) { + BOOK_PATH_TEMPLATE.validate(name); + SHELF_PATH_TEMPLATE.validate(otherShelfName); + MoveBookRequest request = + MoveBookRequest.newBuilder() + .setName(name) + .setOtherShelfName(otherShelfName) + .build(); + return moveBook(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Moves a book to another shelf, and returns the new book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   MoveBookRequest request = MoveBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setOtherShelfName(formattedOtherShelfName)
+   *     .build();
+   *   Book response = libraryServiceApi.moveBook(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book moveBook(MoveBookRequest request) { + return moveBookCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Moves a book to another shelf, and returns the new book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
+   *   MoveBookRequest request = MoveBookRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setOtherShelfName(formattedOtherShelfName)
+   *     .build();
+   *   ListenableFuture<Book> future = libraryServiceApi.moveBookCallable().futureCall(request);
+   *   // Do something
+   *   Book response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable moveBookCallable() { + return moveBookCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists a primitive resource. To test go page streaming. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *
+   *   for (String element : libraryServiceApi.listStrings()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final PageAccessor listStrings() { + ListStringsRequest request = + ListStringsRequest.newBuilder() + + .build(); + return listStrings(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists a primitive resource. To test go page streaming. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   ListStringsRequest request = ListStringsRequest.newBuilder()
+   *     .build();
+   *   for (String element : libraryServiceApi.listStrings(request)) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final PageAccessor listStrings(ListStringsRequest request) { + return listStringsPagedCallable() + .call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists a primitive resource. To test go page streaming. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   ListStringsRequest request = ListStringsRequest.newBuilder()
+   *     .build();
+   *   ListenableFuture<PageAccessor<String>> future = libraryServiceApi.listStringsPagedCallable().futureCall(request);
+   *   // Do something
+   *   for (String element : future.get()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * 
+ */ + public final ApiCallable> listStringsPagedCallable() { + return listStringsPagedCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Lists a primitive resource. To test go page streaming. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   ListStringsRequest request = ListStringsRequest.newBuilder()
+   *     .build();
+   *   while (true) {
+   *     ListStringsResponse response = libraryServiceApi.listStringsCallable().call(request);
+   *     for (String element : response.getStringsList()) {
+   *       // doThingsWith(element);
+   *     }
+   *     String nextPageToken = response.getNextPageToken();
+   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
+   *       request = request.toBuilder().setPageToken(nextPageToken).build();
+   *     } else {
+   *       break;
+   *     }
+   *   }
+   * }
+   * 
+ */ + public final ApiCallable listStringsCallable() { + return listStringsCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Adds comments to a book + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   ByteString comment = ByteString.copyFromUtf8("");
+   *   Comment commentsElement = Comment.newBuilder()
+   *     .setComment(comment)
+   *     .build();
+   *   List<Comment> comments = Arrays.asList(commentsElement);
+   *   libraryServiceApi.addComments(formattedName, comments);
+   * }
+   * 
+ * + * @param name + * @param comments + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void addComments(String name, List comments) { + BOOK_PATH_TEMPLATE.validate(name); + AddCommentsRequest request = + AddCommentsRequest.newBuilder() + .setName(name) + .addAllComments(comments) + .build(); + addComments(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Adds comments to a book + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   ByteString comment = ByteString.copyFromUtf8("");
+   *   Comment commentsElement = Comment.newBuilder()
+   *     .setComment(comment)
+   *     .build();
+   *   List<Comment> comments = Arrays.asList(commentsElement);
+   *   AddCommentsRequest request = AddCommentsRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .addAllComments(comments)
+   *     .build();
+   *   libraryServiceApi.addComments(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void addComments(AddCommentsRequest request) { + addCommentsCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Adds comments to a book + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   ByteString comment = ByteString.copyFromUtf8("");
+   *   Comment commentsElement = Comment.newBuilder()
+   *     .setComment(comment)
+   *     .build();
+   *   List<Comment> comments = Arrays.asList(commentsElement);
+   *   AddCommentsRequest request = AddCommentsRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .addAllComments(comments)
+   *     .build();
+   *   ListenableFuture<Void> future = libraryServiceApi.addCommentsCallable().futureCall(request);
+   *   // Do something
+   *   future.get();
+   * }
+   * 
+ */ + public final ApiCallable addCommentsCallable() { + return addCommentsCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a book from an archive. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatArchivedBookName("[ARCHIVE_PATH]", "[BOOK]");
+   *   Book response = libraryServiceApi.getBookFromArchive(formattedName);
+   * }
+   * 
+ * + * @param name The name of the book to retrieve. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final Book getBookFromArchive(String name) { + ARCHIVED_BOOK_PATH_TEMPLATE.validate(name); + GetBookFromArchiveRequest request = + GetBookFromArchiveRequest.newBuilder() + .setName(name) + .build(); + return getBookFromArchive(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a book from an archive. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatArchivedBookName("[ARCHIVE_PATH]", "[BOOK]");
+   *   GetBookFromArchiveRequest request = GetBookFromArchiveRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   Book response = libraryServiceApi.getBookFromArchive(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + private final Book getBookFromArchive(GetBookFromArchiveRequest request) { + return getBookFromArchiveCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Gets a book from an archive. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatArchivedBookName("[ARCHIVE_PATH]", "[BOOK]");
+   *   GetBookFromArchiveRequest request = GetBookFromArchiveRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .build();
+   *   ListenableFuture<Book> future = libraryServiceApi.getBookFromArchiveCallable().futureCall(request);
+   *   // Do something
+   *   Book response = future.get();
+   * }
+   * 
+ */ + public final ApiCallable getBookFromArchiveCallable() { + return getBookFromArchiveCallable; + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates the index of a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   String indexName = "default index";
+   *   String indexMapItem = "";
+   *   Map<String, String> indexMap = new HashMap<>();
+   *   indexMap.put("default_key", indexMapItem);
+   *   libraryServiceApi.updateBookIndex(formattedName, indexName, indexMap);
+   * }
+   * 
+ * + * @param name The name of the book to update. + * @param indexName The name of the index for the book + * @param indexMap The index to update the book with + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void updateBookIndex(String name, String indexName, Map indexMap) { + BOOK_PATH_TEMPLATE.validate(name); + UpdateBookIndexRequest request = + UpdateBookIndexRequest.newBuilder() + .setName(name) + .setIndexName(indexName) + .putAllIndexMap(indexMap) + .build(); + updateBookIndex(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates the index of a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   String indexName = "default index";
+   *   String indexMapItem = "";
+   *   Map<String, String> indexMap = new HashMap<>();
+   *   indexMap.put("default_key", indexMapItem);
+   *   UpdateBookIndexRequest request = UpdateBookIndexRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setIndexName(indexName)
+   *     .putAllIndexMap(indexMap)
+   *     .build();
+   *   libraryServiceApi.updateBookIndex(request);
+   * }
+   * 
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.grpc.ApiException if the remote call fails + */ + public final void updateBookIndex(UpdateBookIndexRequest request) { + updateBookIndexCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD + /** + * Updates the index of a book. + * + * Sample code: + *

+   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
+   *   String indexName = "default index";
+   *   String indexMapItem = "";
+   *   Map<String, String> indexMap = new HashMap<>();
+   *   indexMap.put("default_key", indexMapItem);
+   *   UpdateBookIndexRequest request = UpdateBookIndexRequest.newBuilder()
+   *     .setName(formattedName)
+   *     .setIndexName(indexName)
+   *     .putAllIndexMap(indexMap)
+   *     .build();
+   *   ListenableFuture<Void> future = libraryServiceApi.updateBookIndexCallable().futureCall(request);
+   *   // Do something
+   *   future.get();
+   * }
+   * 
+ */ + public final ApiCallable updateBookIndexCallable() { + return updateBookIndexCallable; + } + + /** + * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately + * cancelled. + */ + @Override + public final void close() throws Exception { + for (AutoCloseable closeable : closeables) { + closeable.close(); + } + } + +} diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline new file mode 100644 index 0000000000..b4ab0c1f78 --- /dev/null +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -0,0 +1,51 @@ +============== file: src/main/java/com/google/gcloud/pubsub/spi/LibraryServiceSettings.java ============== +package com.google.gcloud.pubsub.spi; + +import com.google.api.gax.core.ConnectionSettings; +import com.google.api.gax.core.RetrySettings; +import com.google.api.gax.grpc.ApiCallSettings; +import com.google.api.gax.grpc.ServiceApiSettings; +import com.google.api.gax.grpc.SimpleCallSettings; +import com.google.auth.Credentials; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import io.grpc.ManagedChannel; +import io.grpc.Status; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import org.joda.time.Duration; + +@javax.annotation.Generated("by GAPIC") +public class LibraryServiceSettings extends ServiceApiSettings { + /** + * The default address of the service. + */ + public static final String DEFAULT_SERVICE_ADDRESS = "library-example.googleapis.com"; + + /** + * The default port of the service. + */ + public static final int DEFAULT_SERVICE_PORT = 443; + + /** + * The default scopes of the service. + */ + public static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() + .add("https://www.googleapis.com/auth/cloud-platform") + .add("https://www.googleapis.com/auth/library") + .build(); + + /** + * The default connection settings of the service. + */ + public static final ConnectionSettings DEFAULT_CONNECTION_SETTINGS = + ConnectionSettings.newBuilder() + .setServiceAddress(DEFAULT_SERVICE_ADDRESS) + .setPort(DEFAULT_SERVICE_PORT) + .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) + .build(); +} From 046b5c31480315e0b48dc64c3a6031c4e694b970 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Fri, 22 Jul 2016 13:39:07 -0700 Subject: [PATCH 03/26] InitCodeGenerator: using Name for suggestedName --- .../codegen/metacode/InitCodeGenerator.java | 32 ++++++++++--------- .../com/google/api/codegen/util/Name.java | 2 +- .../com/google/api/codegen/util/NameTest.java | 9 ++++++ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java b/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java index 52fd906f63..278fc3ae54 100644 --- a/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java +++ b/src/main/java/com/google/api/codegen/metacode/InitCodeGenerator.java @@ -45,7 +45,7 @@ public class InitCodeGenerator { public InitCode generateRequestObjectInitCode( Method method, Map initFieldStructure) { InitCodeLine lastLine = - generateSampleCodeInit("request", method.getInputType(), initFieldStructure); + generateSampleCodeInit(Name.from("request"), method.getInputType(), initFieldStructure); initLineSpecs.add(lastLine); FieldSetting requestField = FieldSetting.create( @@ -74,7 +74,8 @@ public InitCode generateRequestFieldInitCode( } } - InitCodeLine lastLine = generateSampleCodeInit("request", method.getInputType(), filteredInit); + InitCodeLine lastLine = + generateSampleCodeInit(Name.from("request"), method.getInputType(), filteredInit); if (!(lastLine instanceof StructureInitCodeLine)) { throw new IllegalArgumentException( "Expected method request to be a message, found " + lastLine.getClass().getName()); @@ -83,18 +84,18 @@ public InitCode generateRequestFieldInitCode( return InitCode.create(initLineSpecs, requestInitCodeLine.getFieldSettings()); } - private Name getNewSymbol(String desiredName) { - String actualName = desiredName; + private Name getNewSymbol(Name desiredName) { + Name actualName = desiredName; int i = 2; - while (symbolTable.contains(actualName)) { - actualName = desiredName + i; + while (symbolTable.contains(actualName.toLowerUnderscore())) { + actualName = desiredName.join(Integer.toString(i)); } - symbolTable.add(actualName); - return Name.from(actualName); + symbolTable.add(actualName.toLowerUnderscore()); + return actualName; } private InitCodeLine generateSampleCodeInitStructure( - String suggestedName, TypeRef typeRef, Map initFieldMap) { + Name suggestedName, TypeRef typeRef, Map initFieldMap) { List fieldSettings = new ArrayList<>(); for (Field field : typeRef.getMessageType().getFields()) { Object thisFieldInitStructure = initFieldMap.get(field.getSimpleName()); @@ -103,7 +104,8 @@ private InitCodeLine generateSampleCodeInitStructure( } InitCodeLine subFieldInit = - generateSampleCodeInit(field.getSimpleName(), field.getType(), thisFieldInitStructure); + generateSampleCodeInit( + Name.from(field.getSimpleName()), field.getType(), thisFieldInitStructure); initLineSpecs.add(subFieldInit); FieldSetting fieldSetting = @@ -125,10 +127,10 @@ private InitCodeLine generateSampleCodeInitStructure( } private InitCodeLine generateSampleCodeInitList( - String suggestedName, TypeRef typeRef, List thisFieldInitList) { + Name suggestedName, TypeRef typeRef, List thisFieldInitList) { List elementIdentifiers = new ArrayList<>(); for (Object elementInitStructure : thisFieldInitList) { - String suggestedElementName = suggestedName + "_element"; + Name suggestedElementName = suggestedName.join("element"); // Using the Optional cardinality replaces the Repeated cardinality TypeRef elementType = typeRef.makeOptional(); InitCodeLine subFieldInit = @@ -145,7 +147,7 @@ private InitCodeLine generateSampleCodeInitList( } private InitCodeLine generateSampleCodeInitMap( - String suggestedName, TypeRef typeRef, Map thisFieldInitMap) { + Name suggestedName, TypeRef typeRef, Map thisFieldInitMap) { TypeRef keyTypeRef = typeRef.getMapKeyField().getType(); TypeRef elementType = typeRef.getMapValueField().getType(); Map elementIdentifierMap = new HashMap<>(); @@ -164,7 +166,7 @@ private InitCodeLine generateSampleCodeInitMap( } Object elementInitStructure = thisFieldInitMap.get(keyString); - String suggestedElementName = suggestedName + "_item"; + Name suggestedElementName = suggestedName.join("item"); InitCodeLine subFieldInit = generateSampleCodeInit(suggestedElementName, elementType, elementInitStructure); initLineSpecs.add(subFieldInit); @@ -180,7 +182,7 @@ private InitCodeLine generateSampleCodeInitMap( } private InitCodeLine generateSampleCodeInit( - String suggestedName, TypeRef typeRef, Object initFieldStructure) { + Name suggestedName, TypeRef typeRef, Object initFieldStructure) { // No matter what the type in the model is, we want to stop here, because we // have reached the end of initFieldStructure. At codegen time, we will // generate the zero value for the type. diff --git a/src/main/java/com/google/api/codegen/util/Name.java b/src/main/java/com/google/api/codegen/util/Name.java index 11459cfcdf..8336f17260 100644 --- a/src/main/java/com/google/api/codegen/util/Name.java +++ b/src/main/java/com/google/api/codegen/util/Name.java @@ -79,7 +79,7 @@ private static void validateLowerUnderscore(String identifier) { private static boolean isLowerUnderscore(String identifier) { Character underscore = Character.valueOf('_'); for (Character ch : identifier.toCharArray()) { - if (!Character.isLowerCase(ch) && !ch.equals(underscore)) { + if (!Character.isLowerCase(ch) && !ch.equals(underscore) && !Character.isDigit(ch)) { return false; } } diff --git a/src/test/java/com/google/api/codegen/util/NameTest.java b/src/test/java/com/google/api/codegen/util/NameTest.java index 5321dd1f45..b2992584d9 100644 --- a/src/test/java/com/google/api/codegen/util/NameTest.java +++ b/src/test/java/com/google/api/codegen/util/NameTest.java @@ -65,6 +65,15 @@ public void testFromUpperCamel() { Truth.assertThat(name.toUpperCamel()).isEqualTo("FactoryDecoratorDelegateImpl"); } + @Test + public void testWordAndNumber() { + Name name = Name.from("dog", "2"); + Truth.assertThat(name.toLowerUnderscore()).isEqualTo("dog_2"); + Truth.assertThat(name.toUpperUnderscore()).isEqualTo("DOG_2"); + Truth.assertThat(name.toLowerCamel()).isEqualTo("dog2"); + Truth.assertThat(name.toUpperCamel()).isEqualTo("Dog2"); + } + @Test(expected = IllegalArgumentException.class) public void illegalLowerUnderscore() { Name.from("factoryDecorator"); From a0fc1d83de9f696f3f0dafe9171e5804097cc5e3 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Fri, 22 Jul 2016 13:53:21 -0700 Subject: [PATCH 04/26] breaking apart long method --- .../transformer/ApiMethodTransformer.java | 105 ++++++++++-------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index 62cd83173f..b8e885930e 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -58,73 +58,90 @@ public OptionalArrayMethodView generateOptionalArrayMethod(MethodTransformerCont initCodeTransformer.generateInitCode( context, context.getMethodConfig().getRequiredFields())); + apiMethod.doc(generateOptionalArrayMethodDoc(context)); + + apiMethod.name(namer.getApiMethodName(context.getMethod())); + apiMethod.requestTypeName( + context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getInputType())); + apiMethod.hasReturnValue(!ServiceMessages.s_isEmptyType(context.getMethod().getOutputType())); + apiMethod.key(namer.getMethodKey(context.getMethod())); + apiMethod.grpcMethodName(namer.getGrpcMethodName(context.getMethod())); + + apiMethod.methodParams(generateOptionalArrayMethodParams(context)); + + apiMethod.requiredRequestObjectParams( + generateRequestObjectParams(context, context.getMethodConfig().getRequiredFields())); + apiMethod.optionalRequestObjectParams( + generateRequestObjectParams(context, context.getMethodConfig().getOptionalFields())); + + return apiMethod.build(); + } + + private ApiMethodDocView generateOptionalArrayMethodDoc(MethodTransformerContext context) { ApiMethodDocView.Builder docBuilder = ApiMethodDocView.newBuilder(); - docBuilder.mainDocLines(namer.getDocLines(context.getMethod())); + docBuilder.mainDocLines(context.getNamer().getDocLines(context.getMethod())); List paramDocs = getMethodParamDocs(context, context.getMethodConfig().getRequiredFields()); paramDocs.add(getOptionalArrayParamDoc(context, context.getMethodConfig().getOptionalFields())); paramDocs.add(getCallSettingsParamDoc(context)); docBuilder.paramDocs(paramDocs); docBuilder.returnTypeName( - namer.getDynamicReturnTypeName( - context.getTypeTable(), context.getMethod(), context.getMethodConfig())); + context + .getNamer() + .getDynamicReturnTypeName( + context.getTypeTable(), context.getMethod(), context.getMethodConfig())); docBuilder.throwsDocLines(new ArrayList()); - apiMethod.doc(docBuilder.build()); - - apiMethod.name(namer.getApiMethodName(context.getMethod())); - apiMethod.requestTypeName( - context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getInputType())); - apiMethod.hasReturnValue(!ServiceMessages.s_isEmptyType(context.getMethod().getOutputType())); - apiMethod.key(namer.getMethodKey(context.getMethod())); - apiMethod.grpcMethodName(namer.getGrpcMethodName(context.getMethod())); + return docBuilder.build(); + } - List methodParams = new ArrayList<>(); - for (Field field : context.getMethodConfig().getRequiredFields()) { - methodParams.add(generateDefaultableParam(context, field)); - } + private List generateOptionalArrayMethodParams( + MethodTransformerContext context) { + List methodParams = + generateDefaultableParams(context, context.getMethodConfig().getRequiredFields()); // TODO create a map TypeRef here instead of an array // (not done yet because array is sufficient for PHP, and maps are more complex to construct) TypeRef arrayType = TypeRef.fromPrimitiveName("string").makeRepeated(); DynamicDefaultableParamView.Builder optionalArgs = DynamicDefaultableParamView.newBuilder(); - optionalArgs.name(namer.varName(Name.from("optional", "args"))); + optionalArgs.name(context.getNamer().varName(Name.from("optional", "args"))); optionalArgs.defaultValue(context.getTypeTable().getZeroValueAndSaveNicknameFor(arrayType)); methodParams.add(optionalArgs.build()); DynamicDefaultableParamView.Builder callSettings = DynamicDefaultableParamView.newBuilder(); - callSettings.name(namer.varName(Name.from("call", "settings"))); + callSettings.name(context.getNamer().varName(Name.from("call", "settings"))); callSettings.defaultValue(context.getTypeTable().getZeroValueAndSaveNicknameFor(arrayType)); methodParams.add(callSettings.build()); - apiMethod.methodParams(methodParams); + return methodParams; + } - List requiredRequestObjectParams = new ArrayList<>(); + private List generateDefaultableParams( + MethodTransformerContext context, Iterable fields) { + List methodParams = new ArrayList<>(); for (Field field : context.getMethodConfig().getRequiredFields()) { - requiredRequestObjectParams.add(generateRequestObjectParam(context, field)); - } - apiMethod.requiredRequestObjectParams(requiredRequestObjectParams); - - List optionalRequestObjectParams = new ArrayList<>(); - for (Field field : context.getMethodConfig().getOptionalFields()) { - optionalRequestObjectParams.add(generateRequestObjectParam(context, field)); + DynamicDefaultableParamView param = + DynamicDefaultableParamView.newBuilder() + .name(context.getNamer().getVariableName(field)) + .defaultValue("") + .build(); + methodParams.add(param); } - apiMethod.optionalRequestObjectParams(optionalRequestObjectParams); - - return apiMethod.build(); + return methodParams; } - public DynamicDefaultableParamView generateDefaultableParam( - MethodTransformerContext context, Field field) { - return DynamicDefaultableParamView.newBuilder() - .name(context.getNamer().getVariableName(field)) - .defaultValue("") - .build(); + private List generateRequestObjectParams( + MethodTransformerContext context, Iterable fields) { + List params = new ArrayList<>(); + for (Field field : fields) { + params.add(generateRequestObjectParam(context, field)); + } + return params; } - public RequestObjectParamView generateRequestObjectParam( + private RequestObjectParamView generateRequestObjectParam( MethodTransformerContext context, Field field) { SurfaceNamer namer = context.getNamer(); RequestObjectParamView.Builder param = RequestObjectParamView.newBuilder(); @@ -144,7 +161,7 @@ public RequestObjectParamView generateRequestObjectParam( return param.build(); } - public List getMethodParamDocs( + private List getMethodParamDocs( MethodTransformerContext context, Iterable fields) { List allDocs = new ArrayList<>(); for (Field field : fields) { @@ -178,17 +195,7 @@ public List getMethodParamDocs( return allDocs; } - public SimpleParamDocView getRequestObjectParamDoc( - MethodTransformerContext context, TypeRef typeRef) { - return SimpleParamDocView.newBuilder() - .paramName("request") - .typeName(context.getTypeTable().getAndSaveNicknameFor(typeRef)) - .firstLine("The request object containing all of the parameters for the API call.") - .remainingLines(Arrays.asList()) - .build(); - } - - public ParamDocView getOptionalArrayParamDoc( + private ParamDocView getOptionalArrayParamDoc( MethodTransformerContext context, Iterable fields) { MapParamDocView.Builder paramDoc = MapParamDocView.newBuilder(); @@ -216,7 +223,7 @@ public ParamDocView getOptionalArrayParamDoc( return paramDoc.build(); } - public ParamDocView getCallSettingsParamDoc(MethodTransformerContext context) { + private ParamDocView getCallSettingsParamDoc(MethodTransformerContext context) { MapParamDocView.Builder paramDoc = MapParamDocView.newBuilder(); paramDoc.paramName(context.getNamer().varName(Name.from("call", "settings"))); From 1f223810eaca0e1916fe962d0ca3d9e313202d3a Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Mon, 25 Jul 2016 10:27:28 -0700 Subject: [PATCH 05/26] Restoring method deleted in merge --- .../api/codegen/transformer/ApiMethodTransformer.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index 8072dcb6fe..cfae51ad8c 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -438,6 +438,16 @@ private List getMethodParamDocs( return allDocs; } + public SimpleParamDocView getRequestObjectParamDoc( + MethodTransformerContext context, TypeRef typeRef) { + return SimpleParamDocView.newBuilder() + .paramName("request") + .typeName(context.getTypeTable().getAndSaveNicknameFor(typeRef)) + .firstLine("The request object containing all of the parameters for the API call.") + .remainingLines(Arrays.asList()) + .build(); + } + private ParamDocView getOptionalArrayParamDoc( MethodTransformerContext context, Iterable fields) { MapParamDocView.Builder paramDoc = MapParamDocView.newBuilder(); From 0c8ce0f1d75db8759b8abdac4bc3c901af792b98 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Mon, 25 Jul 2016 11:28:24 -0700 Subject: [PATCH 06/26] Java surface: adding api call settings members/functions --- .../transformer/ApiCallableTransformer.java | 127 +++++++++++++ .../api/codegen/transformer/SurfaceNamer.java | 6 +- .../java/JavaGapicSurfaceTransformer.java | 65 +------ .../viewmodel/ApiCallSettingsView.java | 58 ++++++ .../viewmodel/StaticXSettingsView.java | 4 + .../com/google/api/codegen/java/xapi.snip | 2 +- .../google/api/codegen/java/xsettings.snip | 74 ++++++++ .../java_surface_xsettings_library.baseline | 173 ++++++++++++++++++ 8 files changed, 447 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java diff --git a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java new file mode 100644 index 0000000000..90a329b8e1 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java @@ -0,0 +1,127 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.PageStreamingConfig; +import com.google.api.codegen.viewmodel.ApiCallSettingsView; +import com.google.api.codegen.viewmodel.ApiCallableType; +import com.google.api.codegen.viewmodel.ApiCallableView; +import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.TypeRef; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ApiCallableTransformer { + + public List generateStaticApiCallables(SurfaceTransformerContext context) { + List callableMembers = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + callableMembers.addAll(generateStaticApiCallables(context.asMethodContext(method))); + } + + return callableMembers; + } + + public List generateCallSettings(SurfaceTransformerContext context) { + List settingsMembers = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + settingsMembers.addAll(generateApiCallableSettings(context.asMethodContext(method))); + } + + return settingsMembers; + } + + private List generateStaticApiCallables(MethodTransformerContext context) { + ModelTypeTable typeTable = context.getTypeTable(); + Method method = context.getMethod(); + MethodConfig methodConfig = context.getMethodConfig(); + + List apiCallables = new ArrayList<>(); + + ApiCallableView.Builder apiCallableBuilder = ApiCallableView.newBuilder(); + + apiCallableBuilder.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); + apiCallableBuilder.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); + apiCallableBuilder.name(context.getNamer().getCallableName(method)); + apiCallableBuilder.settingsFunctionName(context.getNamer().getSettingsFunctionName(method)); + + if (methodConfig.isBundling()) { + apiCallableBuilder.type(ApiCallableType.BundlingApiCallable); + } else { + apiCallableBuilder.type(ApiCallableType.SimpleApiCallable); + } + + apiCallables.add(apiCallableBuilder.build()); + + if (methodConfig.isPageStreaming()) { + PageStreamingConfig pageStreaming = methodConfig.getPageStreaming(); + + ApiCallableView.Builder pagedApiCallableBuilder = ApiCallableView.newBuilder(); + + String pagedResponseTypeName = + context + .getNamer() + .getAndSavePagedResponseTypeName( + typeTable, pageStreaming.getResourcesField().getType()); + + pagedApiCallableBuilder.requestTypeName( + typeTable.getAndSaveNicknameFor(method.getInputType())); + pagedApiCallableBuilder.responseTypeName(pagedResponseTypeName); + pagedApiCallableBuilder.name(context.getNamer().getPagedCallableName(method)); + pagedApiCallableBuilder.settingsFunctionName( + context.getNamer().getSettingsFunctionName(method)); + + apiCallables.add(pagedApiCallableBuilder.type(ApiCallableType.PagedApiCallable).build()); + } + + return apiCallables; + } + + private List generateApiCallableSettings(MethodTransformerContext context) { + ModelTypeTable typeTable = context.getTypeTable(); + Method method = context.getMethod(); + MethodConfig methodConfig = context.getMethodConfig(); + + ApiCallSettingsView.Builder settings = ApiCallSettingsView.newBuilder(); + + settings.methodName(context.getNamer().getApiMethodName(method)); + settings.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); + settings.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); + + if (methodConfig.isPageStreaming()) { + settings.type(ApiCallableType.PagedApiCallable); + TypeRef resourceType = methodConfig.getPageStreaming().getResourcesField().getType(); + settings.resourceTypeName( + context.getTypeTable().getAndSaveNicknameForElementType(resourceType)); + } else { + settings.resourceTypeName(SurfaceNamer.NOT_IMPLEMENTED); + if (methodConfig.isBundling()) { + settings.type(ApiCallableType.BundlingApiCallable); + } else { + settings.type(ApiCallableType.SimpleApiCallable); + } + } + + settings.memberName(context.getNamer().getSettingsMemberName(method)); + settings.fnGetterName(context.getNamer().getSettingsMemberName(method)); + + return Arrays.asList(settings.build()); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 95a00909f0..6967ab9780 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -195,10 +195,14 @@ public String getCallableName(Method method) { return varName(Name.upperCamel(method.getSimpleName(), "Callable")); } - public String getSettingsFunctionName(Method method) { + public String getSettingsMemberName(Method method) { return methodName(Name.upperCamel(method.getSimpleName(), "Settings")); } + public String getSettingsFunctionName(Method method) { + return getSettingsMemberName(method); + } + public String getGenericAwareResponseType(ModelTypeTable typeTable, TypeRef outputType) { return SurfaceNamer.NOT_IMPLEMENTED; } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index 419c93eef6..8c2ed6be86 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -17,17 +17,15 @@ import com.google.api.codegen.ApiConfig; import com.google.api.codegen.InterfaceView; import com.google.api.codegen.MethodConfig; -import com.google.api.codegen.PageStreamingConfig; import com.google.api.codegen.ServiceConfig; import com.google.api.codegen.gapic.GapicCodePathMapper; +import com.google.api.codegen.transformer.ApiCallableTransformer; import com.google.api.codegen.transformer.ApiMethodTransformer; import com.google.api.codegen.transformer.MethodTransformerContext; import com.google.api.codegen.transformer.ModelToViewTransformer; import com.google.api.codegen.transformer.ModelTypeTable; import com.google.api.codegen.transformer.PathTemplateTransformer; import com.google.api.codegen.transformer.SurfaceTransformerContext; -import com.google.api.codegen.viewmodel.ApiCallableType; -import com.google.api.codegen.viewmodel.ApiCallableView; import com.google.api.codegen.viewmodel.StaticApiMethodView; import com.google.api.codegen.viewmodel.StaticXApiView; import com.google.api.codegen.viewmodel.StaticXSettingsView; @@ -48,6 +46,7 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { private GapicCodePathMapper pathMapper; private PathTemplateTransformer pathTemplateTransformer; + private ApiCallableTransformer apiCallableTransformer; private ApiMethodTransformer apiMethodTransformer; private static final String XAPI_TEMPLATE_FILENAME = "java/xapi.snip"; @@ -59,6 +58,7 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { public JavaGapicSurfaceTransformer(GapicCodePathMapper pathMapper) { this.pathMapper = pathMapper; this.pathTemplateTransformer = new PathTemplateTransformer(); + this.apiCallableTransformer = new ApiCallableTransformer(); this.apiMethodTransformer = new ApiMethodTransformer(); } @@ -99,7 +99,7 @@ private StaticXApiView generateXApi(SurfaceTransformerContext context) { String name = context.getNamer().getApiWrapperClassName(context.getInterface()); xapiClass.name(name); xapiClass.settingsClassName(context.getNamer().getApiSettingsClassName(context.getInterface())); - xapiClass.apiCallableMembers(generateApiCallables(context)); + xapiClass.apiCallableMembers(apiCallableTransformer.generateStaticApiCallables(context)); xapiClass.pathTemplates(pathTemplateTransformer.generatePathTemplates(context)); xapiClass.formatResourceFunctions( pathTemplateTransformer.generateFormatResourceFunctions(context)); @@ -128,6 +128,7 @@ private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) xsettingsClass.serviceAddress(serviceConfig.getServiceAddress(context.getInterface())); xsettingsClass.servicePort(serviceConfig.getServicePort()); xsettingsClass.authScopes(serviceConfig.getAuthScopes(context.getInterface())); + xsettingsClass.callSettings(apiCallableTransformer.generateCallSettings(context)); // must be done as the last step to catch all imports xsettingsClass.imports(context.getTypeTable().getImports()); @@ -171,62 +172,6 @@ private void addXSettingsImports(SurfaceTransformerContext context) { typeTable.saveNicknameFor("java.util.concurrent.ScheduledExecutorService"); } - private List generateApiCallables(SurfaceTransformerContext context) { - List callableMembers = new ArrayList<>(); - - for (Method method : context.getInterface().getMethods()) { - MethodConfig methodConfig = context.getMethodConfig(method); - callableMembers.addAll(generateApiCallables(context, method, methodConfig)); - } - - return callableMembers; - } - - private List generateApiCallables( - SurfaceTransformerContext context, Method method, MethodConfig methodConfig) { - ModelTypeTable typeTable = context.getTypeTable(); - - List apiCallables = new ArrayList<>(); - - ApiCallableView.Builder apiCallableBuilder = ApiCallableView.newBuilder(); - - apiCallableBuilder.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); - apiCallableBuilder.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); - apiCallableBuilder.name(context.getNamer().getCallableName(method)); - apiCallableBuilder.settingsFunctionName(context.getNamer().getSettingsFunctionName(method)); - - if (methodConfig.isBundling()) { - apiCallableBuilder.type(ApiCallableType.BundlingApiCallable); - } else { - apiCallableBuilder.type(ApiCallableType.SimpleApiCallable); - } - - apiCallables.add(apiCallableBuilder.build()); - - if (methodConfig.isPageStreaming()) { - PageStreamingConfig pageStreaming = methodConfig.getPageStreaming(); - - ApiCallableView.Builder pagedApiCallableBuilder = ApiCallableView.newBuilder(); - - String pagedResponseTypeName = - context - .getNamer() - .getAndSavePagedResponseTypeName( - typeTable, pageStreaming.getResourcesField().getType()); - - pagedApiCallableBuilder.requestTypeName( - typeTable.getAndSaveNicknameFor(method.getInputType())); - pagedApiCallableBuilder.responseTypeName(pagedResponseTypeName); - pagedApiCallableBuilder.name(context.getNamer().getPagedCallableName(method)); - pagedApiCallableBuilder.settingsFunctionName( - context.getNamer().getSettingsFunctionName(method)); - - apiCallables.add(pagedApiCallableBuilder.type(ApiCallableType.PagedApiCallable).build()); - } - - return apiCallables; - } - private List generateApiMethods(SurfaceTransformerContext context) { List apiMethods = new ArrayList<>(); diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java new file mode 100644 index 0000000000..a4b330d814 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java @@ -0,0 +1,58 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.viewmodel.ApiCallableView.Builder; +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class ApiCallSettingsView { + public abstract ApiCallableType type(); + + public abstract String methodName(); + + public abstract String requestTypeName(); + + public abstract String responseTypeName(); + + public abstract String resourceTypeName(); + + public abstract String memberName(); + + public abstract String fnGetterName(); + + public static Builder newBuilder() { + return new AutoValue_ApiCallSettingsView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder type(ApiCallableType type); + + public abstract Builder methodName(String apiMethodName); + + public abstract Builder requestTypeName(String val); + + public abstract Builder responseTypeName(String val); + + public abstract Builder resourceTypeName(String val); + + public abstract Builder memberName(String val); + + public abstract Builder fnGetterName(String val); + + public abstract ApiCallSettingsView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java index 1882c30a2c..787d031fe5 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java @@ -33,6 +33,8 @@ public abstract class StaticXSettingsView implements ViewModel { public abstract Iterable authScopes(); + public abstract List callSettings(); + public abstract List imports(); public abstract String outputPath(); @@ -60,6 +62,8 @@ public static abstract class Builder { public abstract Builder authScopes(Iterable val); + public abstract Builder callSettings(List callSettings); + public abstract Builder imports(List val); public abstract Builder outputPath(String val); diff --git a/src/main/resources/com/google/api/codegen/java/xapi.snip b/src/main/resources/com/google/api/codegen/java/xapi.snip index 512bec17b3..aef1e7aa0c 100644 --- a/src/main/resources/com/google/api/codegen/java/xapi.snip +++ b/src/main/resources/com/google/api/codegen/java/xapi.snip @@ -130,7 +130,7 @@ closeables.add(settings.{@apiCallable.settingsFunctionName}().getBundlerFactory()); } @default - $unhandledCase: {@apiCallable.getClass.getSimpleName}$ + $unhandledCase: {@apiCallable.type.toString}$ @end @end diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index 928317d72e..a6578d8035 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -8,6 +8,7 @@ @@javax.annotation.Generated("by GAPIC") public class {@xsettingsClass.name} extends ServiceApiSettings { {@constants(xsettingsClass)} + {@members(xsettingsClass)} } @end @@ -40,4 +41,77 @@ .setPort(DEFAULT_SERVICE_PORT) .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) .build(); + {@""} +@end + +@private members(xsettingsClass) + {@methodMembers(xsettingsClass)} + {@methodGetters(xsettingsClass)} + /** + * Returns a builder for this class with recommended defaults. + */ + public static Builder defaultBuilder() { + return Builder.createDefault(); + } + + /** + * Returns a new builder for this class. + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Returns a builder containing all the values of this settings class. + */ + public Builder toBuilder() { + return new Builder(this); + } +@end + +@private methodMembers(xsettingsClass) + @join settings : xsettingsClass.callSettings + @switch settings.type.toString + @case "SimpleApiCallable" + private final SimpleCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; + @case "PagedApiCallable" + private final PageStreamingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.memberName}; + @case "BundlingApiCallable" + private final BundlingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; + @default + $unhandledCase: {@settings.type.toString}$ + @end + @end + {@BREAK} +@end + +@private methodGetters(xsettingsClass) + @join settings : xsettingsClass.callSettings + /** + * Returns the object with the settings used for calls to {@settings.methodName}. + */ + @switch settings.type.toString + @case "SimpleApiCallable" + public SimpleCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "PagedApiCallable" + public PageStreamingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "BundlingApiCallable" + public BundlingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @default + $unhandledCase: {@settings.type.toString}$ + @end + {@""} + @end @end diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline index b4ab0c1f78..f4889eac5e 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -12,6 +12,29 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.google.example.library.v1.AddCommentsRequest; +import com.google.example.library.v1.Book; +import com.google.example.library.v1.CreateBookRequest; +import com.google.example.library.v1.CreateShelfRequest; +import com.google.example.library.v1.DeleteBookRequest; +import com.google.example.library.v1.DeleteShelfRequest; +import com.google.example.library.v1.GetBookFromArchiveRequest; +import com.google.example.library.v1.GetBookRequest; +import com.google.example.library.v1.GetShelfRequest; +import com.google.example.library.v1.ListBooksRequest; +import com.google.example.library.v1.ListBooksResponse; +import com.google.example.library.v1.ListShelvesRequest; +import com.google.example.library.v1.ListShelvesResponse; +import com.google.example.library.v1.ListStringsRequest; +import com.google.example.library.v1.ListStringsResponse; +import com.google.example.library.v1.MergeShelvesRequest; +import com.google.example.library.v1.MoveBookRequest; +import com.google.example.library.v1.PublishSeriesRequest; +import com.google.example.library.v1.PublishSeriesResponse; +import com.google.example.library.v1.Shelf; +import com.google.example.library.v1.UpdateBookIndexRequest; +import com.google.example.library.v1.UpdateBookRequest; +import com.google.protobuf.Empty; import io.grpc.ManagedChannel; import io.grpc.Status; import java.io.IOException; @@ -48,4 +71,154 @@ public class LibraryServiceSettings extends ServiceApiSettings { .setPort(DEFAULT_SERVICE_PORT) .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) .build(); + + private final SimpleCallSettings createShelfSettings; + private final SimpleCallSettings getShelfSettings; + private final PageStreamingCallSettings listShelvesSettings; + private final SimpleCallSettings deleteShelfSettings; + private final SimpleCallSettings mergeShelvesSettings; + private final SimpleCallSettings createBookSettings; + private final BundlingCallSettings publishSeriesSettings; + private final SimpleCallSettings getBookSettings; + private final PageStreamingCallSettings listBooksSettings; + private final SimpleCallSettings deleteBookSettings; + private final SimpleCallSettings updateBookSettings; + private final SimpleCallSettings moveBookSettings; + private final PageStreamingCallSettings listStringsSettings; + private final SimpleCallSettings addCommentsSettings; + private final SimpleCallSettings getBookFromArchiveSettings; + private final SimpleCallSettings updateBookIndexSettings; + + /** + * Returns the object with the settings used for calls to createShelf. + */ + public SimpleCallSettings createShelfSettings() { + return createShelfSettings; + } + + /** + * Returns the object with the settings used for calls to getShelf. + */ + public SimpleCallSettings getShelfSettings() { + return getShelfSettings; + } + + /** + * Returns the object with the settings used for calls to listShelves. + */ + public PageStreamingCallSettings listShelvesSettings() { + return listShelvesSettings; + } + + /** + * Returns the object with the settings used for calls to deleteShelf. + */ + public SimpleCallSettings deleteShelfSettings() { + return deleteShelfSettings; + } + + /** + * Returns the object with the settings used for calls to mergeShelves. + */ + public SimpleCallSettings mergeShelvesSettings() { + return mergeShelvesSettings; + } + + /** + * Returns the object with the settings used for calls to createBook. + */ + public SimpleCallSettings createBookSettings() { + return createBookSettings; + } + + /** + * Returns the object with the settings used for calls to publishSeries. + */ + public BundlingCallSettings publishSeriesSettings() { + return publishSeriesSettings; + } + + /** + * Returns the object with the settings used for calls to getBook. + */ + public SimpleCallSettings getBookSettings() { + return getBookSettings; + } + + /** + * Returns the object with the settings used for calls to listBooks. + */ + public PageStreamingCallSettings listBooksSettings() { + return listBooksSettings; + } + + /** + * Returns the object with the settings used for calls to deleteBook. + */ + public SimpleCallSettings deleteBookSettings() { + return deleteBookSettings; + } + + /** + * Returns the object with the settings used for calls to updateBook. + */ + public SimpleCallSettings updateBookSettings() { + return updateBookSettings; + } + + /** + * Returns the object with the settings used for calls to moveBook. + */ + public SimpleCallSettings moveBookSettings() { + return moveBookSettings; + } + + /** + * Returns the object with the settings used for calls to listStrings. + */ + public PageStreamingCallSettings listStringsSettings() { + return listStringsSettings; + } + + /** + * Returns the object with the settings used for calls to addComments. + */ + public SimpleCallSettings addCommentsSettings() { + return addCommentsSettings; + } + + /** + * Returns the object with the settings used for calls to getBookFromArchive. + */ + public SimpleCallSettings getBookFromArchiveSettings() { + return getBookFromArchiveSettings; + } + + /** + * Returns the object with the settings used for calls to updateBookIndex. + */ + public SimpleCallSettings updateBookIndexSettings() { + return updateBookIndexSettings; + } + + /** + * Returns a builder for this class with recommended defaults. + */ + public static Builder defaultBuilder() { + return Builder.createDefault(); + } + + /** + * Returns a new builder for this class. + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Returns a builder containing all the values of this settings class. + */ + public Builder toBuilder() { + return new Builder(this); + } } From 97c4dc9307439c9a22c5796f2e2e950f36ced5e9 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Mon, 25 Jul 2016 11:37:13 -0700 Subject: [PATCH 07/26] Java settings surface: adding constructor --- .../google/api/codegen/java/xsettings.snip | 17 ++++++++++++ .../java_surface_xsettings_library.baseline | 26 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index a6578d8035..f6b62a3a12 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -9,6 +9,7 @@ public class {@xsettingsClass.name} extends ServiceApiSettings { {@constants(xsettingsClass)} {@members(xsettingsClass)} + {@constructors(xsettingsClass)} } @end @@ -67,6 +68,7 @@ public Builder toBuilder() { return new Builder(this); } + {@""} @end @private methodMembers(xsettingsClass) @@ -115,3 +117,18 @@ {@""} @end @end + +@private constructors(xsettingsClass) + private {@xsettingsClass.name}(Builder settingsBuilder) throws IOException { + super(settingsBuilder.getChannelProvider(), + settingsBuilder.getExecutorProvider(), + settingsBuilder.getGeneratorName(), + settingsBuilder.getGeneratorVersion(), + settingsBuilder.getClientLibName(), + settingsBuilder.getClientLibVersion()); + + @join settings : xsettingsClass.callSettings + {@settings.memberName} = settingsBuilder.{@settings.fnGetterName}().build(); + @end + } +@end diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline index f4889eac5e..7cd6d6e6b7 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -221,4 +221,30 @@ public class LibraryServiceSettings extends ServiceApiSettings { public Builder toBuilder() { return new Builder(this); } + + private LibraryServiceSettings(Builder settingsBuilder) throws IOException { + super(settingsBuilder.getChannelProvider(), + settingsBuilder.getExecutorProvider(), + settingsBuilder.getGeneratorName(), + settingsBuilder.getGeneratorVersion(), + settingsBuilder.getClientLibName(), + settingsBuilder.getClientLibVersion()); + + createShelfSettings = settingsBuilder.createShelfSettings().build(); + getShelfSettings = settingsBuilder.getShelfSettings().build(); + listShelvesSettings = settingsBuilder.listShelvesSettings().build(); + deleteShelfSettings = settingsBuilder.deleteShelfSettings().build(); + mergeShelvesSettings = settingsBuilder.mergeShelvesSettings().build(); + createBookSettings = settingsBuilder.createBookSettings().build(); + publishSeriesSettings = settingsBuilder.publishSeriesSettings().build(); + getBookSettings = settingsBuilder.getBookSettings().build(); + listBooksSettings = settingsBuilder.listBooksSettings().build(); + deleteBookSettings = settingsBuilder.deleteBookSettings().build(); + updateBookSettings = settingsBuilder.updateBookSettings().build(); + moveBookSettings = settingsBuilder.moveBookSettings().build(); + listStringsSettings = settingsBuilder.listStringsSettings().build(); + addCommentsSettings = settingsBuilder.addCommentsSettings().build(); + getBookFromArchiveSettings = settingsBuilder.getBookFromArchiveSettings().build(); + updateBookIndexSettings = settingsBuilder.updateBookIndexSettings().build(); + } } From 2c9b3035febecf134e6dca06afbfb925663e6ed2 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Mon, 25 Jul 2016 13:27:44 -0700 Subject: [PATCH 08/26] Java surface: adding page streaming descriptor classes --- .../transformer/ApiMethodTransformer.java | 3 +- .../transformer/PageStreamingTransformer.java | 45 ++++++++++++ .../api/codegen/transformer/SurfaceNamer.java | 20 ++++++ .../java/JavaGapicSurfaceTransformer.java | 5 ++ .../PageStreamingDescriptorClassView.java | 66 +++++++++++++++++ .../viewmodel/StaticXSettingsView.java | 5 ++ .../google/api/codegen/java/xsettings.snip | 35 ++++++++++ .../java_surface_xsettings_library.baseline | 70 +++++++++++++++++++ 8 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorClassView.java diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index cfae51ad8c..6a3d891c2e 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -397,8 +397,7 @@ private RequestObjectParamView generateRequestObjectParam( param.elementTypeName(SurfaceNamer.NOT_IMPLEMENTED); param.typeName(SurfaceNamer.NOT_IMPLEMENTED); } - param.setCallName( - namer.getSetFunctionCallName(field.getType(), Name.from(field.getSimpleName()))); + param.setCallName(namer.getSetFunctionCallName(field)); param.isMap(field.getType().isMap()); param.isArray(!field.getType().isMap() && field.getType().isRepeated()); return param.build(); diff --git a/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java b/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java index 915c5d6f7b..6d4c4b2d6d 100644 --- a/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java @@ -17,8 +17,10 @@ import com.google.api.codegen.MethodConfig; import com.google.api.codegen.PageStreamingConfig; import com.google.api.codegen.util.Name; +import com.google.api.codegen.viewmodel.PageStreamingDescriptorClassView; import com.google.api.codegen.viewmodel.PageStreamingDescriptorView; import com.google.api.tools.framework.model.Method; +import com.google.api.tools.framework.model.TypeRef; import java.util.ArrayList; import java.util.List; @@ -51,4 +53,47 @@ public List generateDescriptors(SurfaceTransformerC return descriptors; } + + public List generateDescriptorClasses( + SurfaceTransformerContext context) { + List descriptors = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + MethodConfig methodConfig = context.getMethodConfig(method); + if (!methodConfig.isPageStreaming()) { + continue; + } + descriptors.add(generateDescriptorClass(context.asMethodContext(method))); + } + + return descriptors; + } + + private PageStreamingDescriptorClassView generateDescriptorClass( + MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + ModelTypeTable typeTable = context.getTypeTable(); + Method method = context.getMethod(); + PageStreamingConfig pageStreaming = context.getMethodConfig().getPageStreaming(); + + PageStreamingDescriptorClassView.Builder desc = PageStreamingDescriptorClassView.newBuilder(); + + desc.name(namer.getPageStreamingDescriptorConstName(method)); + desc.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); + desc.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); + + TypeRef resourceType = pageStreaming.getResourcesField().getType(); + desc.resourceTypeName(context.getTypeTable().getAndSaveNicknameForElementType(resourceType)); + + TypeRef tokenType = pageStreaming.getResponseTokenField().getType(); + desc.tokenTypeName(typeTable.getAndSaveNicknameFor(tokenType)); + + desc.defaultTokenValue(context.getTypeTable().getZeroValueAndSaveNicknameFor(tokenType)); + + desc.fnSetRequestToken(namer.getSetFunctionCallName(pageStreaming.getRequestTokenField())); + desc.fnGetResponseToken(namer.getGetFunctionCallName(pageStreaming.getResponseTokenField())); + desc.fnGetResourcesField(namer.getGetFunctionCallName(pageStreaming.getResourcesField())); + + return desc.build(); + } } diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 6967ab9780..d679973864 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -62,6 +62,10 @@ public String getVariableName(Name identifier, InitValueConfig initValueConfig) } } + public String getSetFunctionCallName(Field field) { + return getSetFunctionCallName(field.getType(), Name.from(field.getSimpleName())); + } + public String getSetFunctionCallName(TypeRef type, Name identifier) { if (type.isMap()) { return methodName(Name.from("put", "all").join(identifier)); @@ -72,6 +76,18 @@ public String getSetFunctionCallName(TypeRef type, Name identifier) { } } + public String getGetFunctionCallName(Field field) { + return getGetFunctionCallName(field.getType(), Name.from(field.getSimpleName())); + } + + public String getGetFunctionCallName(TypeRef type, Name identifier) { + if (type.isRepeated()) { + return methodName(Name.from("get").join(identifier).join("list")); + } else { + return methodName(Name.from("get").join(identifier)); + } + } + public String getPathTemplateName(CollectionConfig collectionConfig) { return inittedConstantName(Name.from(collectionConfig.getEntityName(), "path", "template")); } @@ -105,6 +121,10 @@ public String getPageStreamingDescriptorName(Method method) { return varName(Name.upperCamel(method.getSimpleName(), "PageStreamingDescriptor")); } + public String getPageStreamingDescriptorConstName(Method method) { + return inittedConstantName(Name.upperCamel(method.getSimpleName()).join("page_str_desc")); + } + public void addPageStreamingDescriptorImports(ModelTypeTable typeTable) { // do nothing } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index 8c2ed6be86..cacb775cf6 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -24,6 +24,7 @@ import com.google.api.codegen.transformer.MethodTransformerContext; import com.google.api.codegen.transformer.ModelToViewTransformer; import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.PageStreamingTransformer; import com.google.api.codegen.transformer.PathTemplateTransformer; import com.google.api.codegen.transformer.SurfaceTransformerContext; import com.google.api.codegen.viewmodel.StaticApiMethodView; @@ -48,6 +49,7 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { private PathTemplateTransformer pathTemplateTransformer; private ApiCallableTransformer apiCallableTransformer; private ApiMethodTransformer apiMethodTransformer; + private PageStreamingTransformer pageStreamingTransformer; private static final String XAPI_TEMPLATE_FILENAME = "java/xapi.snip"; private static final String XSETTINGS_TEMPLATE_FILENAME = "java/xsettings.snip"; @@ -60,6 +62,7 @@ public JavaGapicSurfaceTransformer(GapicCodePathMapper pathMapper) { this.pathTemplateTransformer = new PathTemplateTransformer(); this.apiCallableTransformer = new ApiCallableTransformer(); this.apiMethodTransformer = new ApiMethodTransformer(); + this.pageStreamingTransformer = new PageStreamingTransformer(); } @Override @@ -129,6 +132,8 @@ private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) xsettingsClass.servicePort(serviceConfig.getServicePort()); xsettingsClass.authScopes(serviceConfig.getAuthScopes(context.getInterface())); xsettingsClass.callSettings(apiCallableTransformer.generateCallSettings(context)); + xsettingsClass.pageStreamingDescriptors( + pageStreamingTransformer.generateDescriptorClasses(context)); // must be done as the last step to catch all imports xsettingsClass.imports(context.getTypeTable().getImports()); diff --git a/src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorClassView.java b/src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorClassView.java new file mode 100644 index 0000000000..7d3c4e2ebf --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/PageStreamingDescriptorClassView.java @@ -0,0 +1,66 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class PageStreamingDescriptorClassView { + public abstract String name(); + + public abstract String requestTypeName(); + + public abstract String responseTypeName(); + + public abstract String resourceTypeName(); + + public abstract String tokenTypeName(); + + public abstract String defaultTokenValue(); + + public abstract String fnSetRequestToken(); + + public abstract String fnGetResponseToken(); + + public abstract String fnGetResourcesField(); + + public static Builder newBuilder() { + return new AutoValue_PageStreamingDescriptorClassView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + + public abstract Builder name(String val); + + public abstract Builder requestTypeName(String val); + + public abstract Builder responseTypeName(String val); + + public abstract Builder resourceTypeName(String val); + + public abstract Builder tokenTypeName(String val); + + public abstract Builder defaultTokenValue(String val); + + public abstract Builder fnSetRequestToken(String val); + + public abstract Builder fnGetResponseToken(String val); + + public abstract Builder fnGetResourcesField(String val); + + public abstract PageStreamingDescriptorClassView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java index 787d031fe5..467de5c3b1 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java @@ -35,6 +35,8 @@ public abstract class StaticXSettingsView implements ViewModel { public abstract List callSettings(); + public abstract List pageStreamingDescriptors(); + public abstract List imports(); public abstract String outputPath(); @@ -64,6 +66,9 @@ public static abstract class Builder { public abstract Builder callSettings(List callSettings); + public abstract Builder pageStreamingDescriptors( + List generateDescriptorClasses); + public abstract Builder imports(List val); public abstract Builder outputPath(String val); diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index f6b62a3a12..76359f8530 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -10,6 +10,7 @@ {@constants(xsettingsClass)} {@members(xsettingsClass)} {@constructors(xsettingsClass)} + {@descriptors(xsettingsClass)} } @end @@ -131,4 +132,38 @@ {@settings.memberName} = settingsBuilder.{@settings.fnGetterName}().build(); @end } + {@""} +@end + +@private descriptors(xsettingsClass) + {@pageStreamingDescriptors(xsettingsClass)} + # {@bundlingDescriptors(xsettingsClass)} +@end + +@private pageStreamingDescriptors(xsettingsClass) + @join desc : xsettingsClass.pageStreamingDescriptors + private static PageStreamingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}, {@desc.resourceTypeName}> {@desc.name} = + new PageStreamingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}, {@desc.resourceTypeName}>() { + @@Override + public Object emptyToken() { + return {@desc.defaultTokenValue}; + } + @@Override + public {@desc.requestTypeName} injectToken({@desc.requestTypeName} payload, Object token) { + return {@desc.requestTypeName} + .newBuilder(payload) + .{@desc.fnSetRequestToken}(({@desc.tokenTypeName}) token) + .build(); + } + @@Override + public Object extractNextToken({@desc.responseTypeName} payload) { + return payload.{@desc.fnGetResponseToken}(); + } + @@Override + public Iterable<{@desc.resourceTypeName}> extractResources({@desc.responseTypeName} payload) { + return payload.{@desc.fnGetResourcesField}(); + } + }; + {@""} + @end @end diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline index 7cd6d6e6b7..341b434101 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -247,4 +247,74 @@ public class LibraryServiceSettings extends ServiceApiSettings { getBookFromArchiveSettings = settingsBuilder.getBookFromArchiveSettings().build(); updateBookIndexSettings = settingsBuilder.updateBookIndexSettings().build(); } + + private static PageStreamingDescriptor LIST_SHELVES_PAGE_STR_DESC = + new PageStreamingDescriptor() { + @Override + public Object emptyToken() { + return ""; + } + @Override + public ListShelvesRequest injectToken(ListShelvesRequest payload, Object token) { + return ListShelvesRequest + .newBuilder(payload) + .setPageToken((String) token) + .build(); + } + @Override + public Object extractNextToken(ListShelvesResponse payload) { + return payload.getNextPageToken(); + } + @Override + public Iterable extractResources(ListShelvesResponse payload) { + return payload.getShelvesList(); + } + }; + + private static PageStreamingDescriptor LIST_BOOKS_PAGE_STR_DESC = + new PageStreamingDescriptor() { + @Override + public Object emptyToken() { + return ""; + } + @Override + public ListBooksRequest injectToken(ListBooksRequest payload, Object token) { + return ListBooksRequest + .newBuilder(payload) + .setPageToken((String) token) + .build(); + } + @Override + public Object extractNextToken(ListBooksResponse payload) { + return payload.getNextPageToken(); + } + @Override + public Iterable extractResources(ListBooksResponse payload) { + return payload.getBooksList(); + } + }; + + private static PageStreamingDescriptor LIST_STRINGS_PAGE_STR_DESC = + new PageStreamingDescriptor() { + @Override + public Object emptyToken() { + return ""; + } + @Override + public ListStringsRequest injectToken(ListStringsRequest payload, Object token) { + return ListStringsRequest + .newBuilder(payload) + .setPageToken((String) token) + .build(); + } + @Override + public Object extractNextToken(ListStringsResponse payload) { + return payload.getNextPageToken(); + } + @Override + public Iterable extractResources(ListStringsResponse payload) { + return payload.getStringsList(); + } + }; + } From 5642c053ae066bceee9a008a06710e3ab3d11027 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Mon, 25 Jul 2016 14:51:17 -0700 Subject: [PATCH 09/26] Java settings surface: adding bundling descriptors --- .../transformer/BundlingTransformer.java | 104 ++++++++++++++++++ .../api/codegen/transformer/SurfaceNamer.java | 22 ++++ .../java/JavaGapicSurfaceTransformer.java | 4 + .../BundlingDescriptorClassView.java | 82 ++++++++++++++ .../viewmodel/BundlingPartitionKeyView.java | 40 +++++++ .../api/codegen/viewmodel/FieldCopyView.java | 38 +++++++ .../viewmodel/StaticXSettingsView.java | 4 + .../google/api/codegen/java/xsettings.snip | 82 +++++++++++++- .../java_surface_xsettings_library.baseline | 63 +++++++++++ 9 files changed, 438 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/BundlingDescriptorClassView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/BundlingPartitionKeyView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/FieldCopyView.java diff --git a/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java b/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java new file mode 100644 index 0000000000..2baf990654 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java @@ -0,0 +1,104 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.BundlingConfig; +import com.google.api.codegen.MethodConfig; +import com.google.api.codegen.viewmodel.BundlingDescriptorClassView; +import com.google.api.codegen.viewmodel.BundlingPartitionKeyView; +import com.google.api.codegen.viewmodel.FieldCopyView; +import com.google.api.tools.framework.model.FieldSelector; +import com.google.api.tools.framework.model.Method; + +import java.util.ArrayList; +import java.util.List; + +public class BundlingTransformer { + + public List generateDescriptorClasses( + SurfaceTransformerContext context) { + List descriptors = new ArrayList<>(); + + for (Method method : context.getInterface().getMethods()) { + MethodConfig methodConfig = context.getMethodConfig(method); + if (!methodConfig.isBundling()) { + continue; + } + descriptors.add(generateDescriptorClass(context.asMethodContext(method))); + } + + return descriptors; + } + + private BundlingDescriptorClassView generateDescriptorClass(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); + ModelTypeTable typeTable = context.getTypeTable(); + Method method = context.getMethod(); + BundlingConfig bundling = context.getMethodConfig().getBundling(); + + BundlingDescriptorClassView.Builder desc = BundlingDescriptorClassView.newBuilder(); + + desc.name(namer.getBundlingDescriptorConstName(method)); + desc.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); + desc.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); + desc.bundledFieldTypeName( + typeTable.getAndSaveNicknameFor(bundling.getBundledField().getType())); + desc.subresponseTypeName( + typeTable.getAndSaveNicknameFor(bundling.getSubresponseField().getType())); + + desc.partitionKeys(generatePartitionKeys(context)); + desc.discriminatorFieldCopies(generateDiscriminatorFieldCopies(context)); + + desc.fnGetBundledField(namer.getGetFunctionCallName(bundling.getBundledField())); + desc.fnSetBundledField(namer.getSetFunctionCallName(bundling.getBundledField())); + desc.fnGetBundledFieldCount(namer.getGetCountCallName(bundling.getBundledField())); + desc.fnGetSubresponseByIndex(namer.getGetByIndexCallName(bundling.getSubresponseField())); + desc.fnSetSubresponse(namer.getSetFunctionCallName(bundling.getSubresponseField())); + + return desc.build(); + } + + private List generatePartitionKeys(MethodTransformerContext context) { + List keys = new ArrayList<>(); + BundlingConfig bundling = context.getMethodConfig().getBundling(); + for (FieldSelector fieldSelector : bundling.getDiscriminatorFields()) { + BundlingPartitionKeyView key = + BundlingPartitionKeyView.newBuilder() + .separatorLiteral("\"|\"") + .fnGetCallName( + context.getNamer().getGetFunctionCallName(fieldSelector.getLastField())) + .build(); + keys.add(key); + } + return keys; + } + + private List generateDiscriminatorFieldCopies(MethodTransformerContext context) { + List fieldCopies = new ArrayList<>(); + BundlingConfig bundling = context.getMethodConfig().getBundling(); + for (FieldSelector fieldSelector : bundling.getDiscriminatorFields()) { + FieldCopyView fieldCopy = + FieldCopyView.newBuilder() + .fnGetFunctionCallName( + context.getNamer().getGetFunctionCallName(fieldSelector.getLastField())) + .fnSetFunctionCallName( + context.getNamer().getSetFunctionCallName(fieldSelector.getLastField())) + .build(); + fieldCopies.add(fieldCopy); + } + return fieldCopies; + } + +} diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index d679973864..2932dde1c8 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -88,6 +88,24 @@ public String getGetFunctionCallName(TypeRef type, Name identifier) { } } + public String getGetCountCallName(Field field) { + if (field.isRepeated()) { + return methodName(Name.from("get", field.getSimpleName(), "count")); + } else { + throw new IllegalArgumentException( + "Non-repeated field " + field.getSimpleName() + " has no count function."); + } + } + + public String getGetByIndexCallName(Field field) { + if (field.isRepeated()) { + return methodName(Name.from("get", field.getSimpleName())); + } else { + throw new IllegalArgumentException( + "Non-repeated field " + field.getSimpleName() + " has no get-by-index function."); + } + } + public String getPathTemplateName(CollectionConfig collectionConfig) { return inittedConstantName(Name.from(collectionConfig.getEntityName(), "path", "template")); } @@ -125,6 +143,10 @@ public String getPageStreamingDescriptorConstName(Method method) { return inittedConstantName(Name.upperCamel(method.getSimpleName()).join("page_str_desc")); } + public String getBundlingDescriptorConstName(Method method) { + return inittedConstantName(Name.upperCamel(method.getSimpleName()).join("bundling_desc")); + } + public void addPageStreamingDescriptorImports(ModelTypeTable typeTable) { // do nothing } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index cacb775cf6..2c83b7e136 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -21,6 +21,7 @@ import com.google.api.codegen.gapic.GapicCodePathMapper; import com.google.api.codegen.transformer.ApiCallableTransformer; import com.google.api.codegen.transformer.ApiMethodTransformer; +import com.google.api.codegen.transformer.BundlingTransformer; import com.google.api.codegen.transformer.MethodTransformerContext; import com.google.api.codegen.transformer.ModelToViewTransformer; import com.google.api.codegen.transformer.ModelTypeTable; @@ -50,6 +51,7 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { private ApiCallableTransformer apiCallableTransformer; private ApiMethodTransformer apiMethodTransformer; private PageStreamingTransformer pageStreamingTransformer; + private BundlingTransformer bundlingTransformer; private static final String XAPI_TEMPLATE_FILENAME = "java/xapi.snip"; private static final String XSETTINGS_TEMPLATE_FILENAME = "java/xsettings.snip"; @@ -63,6 +65,7 @@ public JavaGapicSurfaceTransformer(GapicCodePathMapper pathMapper) { this.apiCallableTransformer = new ApiCallableTransformer(); this.apiMethodTransformer = new ApiMethodTransformer(); this.pageStreamingTransformer = new PageStreamingTransformer(); + this.bundlingTransformer = new BundlingTransformer(); } @Override @@ -134,6 +137,7 @@ private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) xsettingsClass.callSettings(apiCallableTransformer.generateCallSettings(context)); xsettingsClass.pageStreamingDescriptors( pageStreamingTransformer.generateDescriptorClasses(context)); + xsettingsClass.bundlingDescriptors(bundlingTransformer.generateDescriptorClasses(context)); // must be done as the last step to catch all imports xsettingsClass.imports(context.getTypeTable().getImports()); diff --git a/src/main/java/com/google/api/codegen/viewmodel/BundlingDescriptorClassView.java b/src/main/java/com/google/api/codegen/viewmodel/BundlingDescriptorClassView.java new file mode 100644 index 0000000000..e7fe49d66f --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/BundlingDescriptorClassView.java @@ -0,0 +1,82 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class BundlingDescriptorClassView { + + public abstract String name(); + + public abstract String requestTypeName(); + + public abstract String responseTypeName(); + + public abstract String bundledFieldTypeName(); + + public abstract String subresponseTypeName(); + + public abstract List partitionKeys(); + + public abstract List discriminatorFieldCopies(); + + public abstract String fnGetBundledField(); + + public abstract String fnSetBundledField(); + + public abstract String fnGetBundledFieldCount(); + + public abstract String fnGetSubresponseByIndex(); + + public abstract String fnSetSubresponse(); + + public static Builder newBuilder() { + return new AutoValue_BundlingDescriptorClassView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + + public abstract Builder name(String val); + + public abstract Builder requestTypeName(String val); + + public abstract Builder responseTypeName(String val); + + public abstract Builder bundledFieldTypeName(String val); + + public abstract Builder subresponseTypeName(String val); + + public abstract Builder partitionKeys(List val); + + public abstract Builder discriminatorFieldCopies( + List generateDiscriminatorFieldCopies); + + public abstract Builder fnGetBundledField(String val); + + public abstract Builder fnSetBundledField(String val); + + public abstract Builder fnGetBundledFieldCount(String val); + + public abstract Builder fnGetSubresponseByIndex(String val); + + public abstract Builder fnSetSubresponse(String val); + + public abstract BundlingDescriptorClassView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/BundlingPartitionKeyView.java b/src/main/java/com/google/api/codegen/viewmodel/BundlingPartitionKeyView.java new file mode 100644 index 0000000000..2f1ee8a648 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/BundlingPartitionKeyView.java @@ -0,0 +1,40 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.viewmodel.BundlingDescriptorClassView.Builder; +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class BundlingPartitionKeyView { + + public abstract String separatorLiteral(); + + public abstract String fnGetCallName(); + + public static Builder newBuilder() { + return new AutoValue_BundlingPartitionKeyView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + + public abstract Builder separatorLiteral(String val); + + public abstract Builder fnGetCallName(String val); + + public abstract BundlingPartitionKeyView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/FieldCopyView.java b/src/main/java/com/google/api/codegen/viewmodel/FieldCopyView.java new file mode 100644 index 0000000000..a636db4a5f --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/FieldCopyView.java @@ -0,0 +1,38 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class FieldCopyView { + + public abstract String fnSetFunctionCallName(); + + public abstract String fnGetFunctionCallName(); + + public static Builder newBuilder() { + return new AutoValue_FieldCopyView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder fnSetFunctionCallName(String val); + + public abstract Builder fnGetFunctionCallName(String val); + + public abstract FieldCopyView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java index 467de5c3b1..c811a81c36 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java @@ -37,6 +37,8 @@ public abstract class StaticXSettingsView implements ViewModel { public abstract List pageStreamingDescriptors(); + public abstract List bundlingDescriptors(); + public abstract List imports(); public abstract String outputPath(); @@ -69,6 +71,8 @@ public static abstract class Builder { public abstract Builder pageStreamingDescriptors( List generateDescriptorClasses); + public abstract Builder bundlingDescriptors(List val); + public abstract Builder imports(List val); public abstract Builder outputPath(String val); diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index 76359f8530..f710a9a9dd 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -137,7 +137,7 @@ @private descriptors(xsettingsClass) {@pageStreamingDescriptors(xsettingsClass)} - # {@bundlingDescriptors(xsettingsClass)} + {@bundlingDescriptors(xsettingsClass)} @end @private pageStreamingDescriptors(xsettingsClass) @@ -167,3 +167,83 @@ {@""} @end @end + +@private bundlingDescriptors(xsettingsClass) + @join desc : xsettingsClass.bundlingDescriptors + private static BundlingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}> {@desc.name} = + new BundlingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}>() { + @@Override + public String getBundlePartitionKey({@desc.requestTypeName} request) { + return {@partitionKeyCode(desc)}; + } + + @@Override + public {@desc.requestTypeName} mergeRequests(Collection<{@desc.requestTypeName}> requests) { + {@desc.requestTypeName} firstRequest = requests.iterator().next(); + + {@desc.bundledFieldTypeName} elements = new ArrayList<>(); + for ({@desc.requestTypeName} request : requests) { + elements.addAll(request.{@desc.fnGetBundledField}()); + } + + {@desc.requestTypeName} bundleRequest = + {@desc.requestTypeName}.newBuilder() + {@fieldCopyCalls(desc.discriminatorFieldCopies)} + .{@desc.fnSetBundledField}(elements) + .build(); + return bundleRequest; + } + + @@Override + public void splitResponse( + {@desc.responseTypeName} bundleResponse, + Collection> bundle) { + # TODO(garrettjones) support case of no subresponse_field (e.g. Logging) + int bundleMessageIndex = 0; + for (RequestIssuer<{@desc.requestTypeName}, {@desc.responseTypeName}> responder : bundle) { + {@desc.subresponseTypeName} subresponseElements = new ArrayList<>(); + int subresponseCount = responder.getRequest().{@desc.fnGetBundledFieldCount}(); + for (int i = 0; i < subresponseCount; i++) { + subresponseElements.add(bundleResponse.{@desc.fnGetSubresponseByIndex}(bundleMessageIndex)); + bundleMessageIndex += 1; + } + {@desc.responseTypeName} response = + {@desc.responseTypeName}.newBuilder().{@desc.fnSetSubresponse}(subresponseElements).build(); + responder.setResponse(response); + } + } + + @@Override + public void splitException( + Throwable throwable, + Collection> bundle) { + for (RequestIssuer<{@desc.requestTypeName}, {@desc.responseTypeName}> responder : bundle) { + responder.setException(throwable); + } + } + + @@Override + public long countElements({@desc.requestTypeName} request) { + return request.{@desc.fnGetBundledFieldCount}(); + } + + @@Override + public long countBytes({@desc.requestTypeName} request) { + return request.getSerializedSize(); + } + }; + {@""} + @end +@end + +@private partitionKeyCode(bundlingDesc) + @join partitionKey : bundlingDesc.partitionKeys on " + " + request.{@partitionKey.fnGetCallName}() + {@partitionKey.separatorLiteral} + @end +@end + +@private fieldCopyCalls(fieldCopies) + @join fieldCopy : fieldCopies + .{@fieldCopy.fnSetFunctionCallName}(firstRequest.{@fieldCopy.fnGetFunctionCallName}()) + @end +@end diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline index 341b434101..c438ce6d9e 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -317,4 +317,67 @@ public class LibraryServiceSettings extends ServiceApiSettings { } }; + private static BundlingDescriptor PUBLISH_SERIES_BUNDLING_DESC = + new BundlingDescriptor() { + @Override + public String getBundlePartitionKey(PublishSeriesRequest request) { + return request.getEdition() + "|" + request.getName() + "|"; + } + + @Override + public PublishSeriesRequest mergeRequests(Collection requests) { + PublishSeriesRequest firstRequest = requests.iterator().next(); + + List elements = new ArrayList<>(); + for (PublishSeriesRequest request : requests) { + elements.addAll(request.getBooksList()); + } + + PublishSeriesRequest bundleRequest = + PublishSeriesRequest.newBuilder() + .setEdition(firstRequest.getEdition()) + .setName(firstRequest.getName()) + .addAllBooks(elements) + .build(); + return bundleRequest; + } + + @Override + public void splitResponse( + PublishSeriesResponse bundleResponse, + Collection> bundle) { + int bundleMessageIndex = 0; + for (RequestIssuer responder : bundle) { + List subresponseElements = new ArrayList<>(); + int subresponseCount = responder.getRequest().getBooksCount(); + for (int i = 0; i < subresponseCount; i++) { + subresponseElements.add(bundleResponse.getBookNames(bundleMessageIndex)); + bundleMessageIndex += 1; + } + PublishSeriesResponse response = + PublishSeriesResponse.newBuilder().addAllBookNames(subresponseElements).build(); + responder.setResponse(response); + } + } + + @Override + public void splitException( + Throwable throwable, + Collection> bundle) { + for (RequestIssuer responder : bundle) { + responder.setException(throwable); + } + } + + @Override + public long countElements(PublishSeriesRequest request) { + return request.getBooksCount(); + } + + @Override + public long countBytes(PublishSeriesRequest request) { + return request.getSerializedSize(); + } + }; + } From 01e30eba90ad21a16bde54086e6280e23f7245e4 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 26 Jul 2016 11:45:24 -0700 Subject: [PATCH 10/26] PR feedback --- .../transformer/ApiMethodTransformer.java | 14 ++++++++++++-- .../api/codegen/transformer/SurfaceNamer.java | 12 +++++++----- .../com/google/api/codegen/util/ViewNamer.java | 2 +- .../api/codegen/util/php/PhpTypeTable.java | 2 +- .../viewmodel/DynamicDefaultableParamView.java | 2 +- .../google/api/codegen/viewmodel/ParamView.java | 17 ----------------- .../viewmodel/RequestObjectParamView.java | 2 +- 7 files changed, 23 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/com/google/api/codegen/viewmodel/ParamView.java diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index b8e885930e..1ee91cdf19 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -151,8 +151,12 @@ private RequestObjectParamView generateRequestObjectParam( context.getTypeTable().getAndSaveNicknameForElementType(field.getType())); param.typeName(context.getTypeTable().getAndSaveNicknameFor(field.getType())); } else { - param.elementTypeName(SurfaceNamer.NOT_IMPLEMENTED); - param.typeName(SurfaceNamer.NOT_IMPLEMENTED); + param.elementTypeName( + namer.getNotImplementedString( + "ApiMethodTransformer.generateRequestObjectParam - elementTypeName")); + param.typeName( + namer.getNotImplementedString( + "ApiMethodTransformer.generateRequestObjectParam - typeName")); } param.setCallName( namer.getSetFunctionCallName(field.getType(), Name.from(field.getSimpleName()))); @@ -206,6 +210,8 @@ private ParamDocView getOptionalArrayParamDoc( List docLines = null; if (!fields.iterator().hasNext()) { + // TODO figure out a reliable way to line-wrap comments across all languages + // instead of encoding it in the transformer String retrySettingsDocText = String.format( "Optional. There are no optional parameters for this method yet;\n" @@ -239,6 +245,8 @@ private ParamDocView getCallSettingsParamDoc(MethodTransformerContext context) { Name timeoutMillisName = Name.from("timeout", "millis"); retrySettingsDoc.paramName(context.getNamer().varName(retrySettingsName)); + // TODO figure out a reliable way to line-wrap comments across all languages + // instead of encoding it in the transformer String retrySettingsDocText = String.format( "Retry settings to use for this call. If present, then\n%s is ignored.", @@ -251,6 +259,8 @@ private ParamDocView getCallSettingsParamDoc(MethodTransformerContext context) { SimpleParamDocView.Builder timeoutDoc = SimpleParamDocView.newBuilder(); timeoutDoc.typeName(context.getTypeTable().getAndSaveNicknameFor(TypeRef.of(Type.TYPE_INT32))); timeoutDoc.paramName(context.getNamer().varName(timeoutMillisName)); + // TODO figure out a reliable way to line-wrap comments across all languages + // instead of encoding it in the transformer String timeoutMillisDocText = String.format( "Timeout to use for this call. Only used if %s\nis not set.", diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index ffc679d47f..3e0c0b57fa 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -39,7 +39,9 @@ public SurfaceNamer(NameFormatter languageNamer) { super(languageNamer); } - public static final String NOT_IMPLEMENTED = "$ NOT IMPLEMENTED $"; + public String getNotImplementedString(String feature) { + return "$ NOT IMPLEMENTED: " + feature + " $"; + } public String getApiWrapperClassName(Interface interfaze) { return className(Name.upperCamel(interfaze.getSimpleName(), "Api")); @@ -109,7 +111,7 @@ public String getMethodKey(Method method) { } public String getClientConfigPath(Interface service) { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getClientConfigPath"); } public String getGrpcClientTypeName(Interface service) { @@ -145,15 +147,15 @@ public String getGrpcMethodName(Method method) { } public String getRetrySettingsClassName() { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getRetrySettingsClassName"); } public String getOptionalArrayTypeName() { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getOptionalArrayTypeName"); } public String getDynamicReturnTypeName( ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getDynamicReturnTypeName"); } } diff --git a/src/main/java/com/google/api/codegen/util/ViewNamer.java b/src/main/java/com/google/api/codegen/util/ViewNamer.java index fcff536738..7a667bbf5b 100644 --- a/src/main/java/com/google/api/codegen/util/ViewNamer.java +++ b/src/main/java/com/google/api/codegen/util/ViewNamer.java @@ -25,7 +25,7 @@ * This class delegates step 2 to the provided name formatter, which generally * would be a language-specific namer. */ -public class ViewNamer implements NameFormatter { +public abstract class ViewNamer implements NameFormatter { private NameFormatter formatter; diff --git a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java index 250ad850a7..3267b99268 100644 --- a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java @@ -26,7 +26,7 @@ import java.util.List; /** - * The TypeTable for Java. + * The TypeTable for PHP. */ public class PhpTypeTable implements TypeTable { /** diff --git a/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java b/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java index 92b2c7d7cd..a9a84d75b4 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/DynamicDefaultableParamView.java @@ -17,7 +17,7 @@ import com.google.auto.value.AutoValue; @AutoValue -public abstract class DynamicDefaultableParamView implements ParamView { +public abstract class DynamicDefaultableParamView { public abstract String name(); public abstract String defaultValue(); diff --git a/src/main/java/com/google/api/codegen/viewmodel/ParamView.java b/src/main/java/com/google/api/codegen/viewmodel/ParamView.java deleted file mode 100644 index 91e3757ef1..0000000000 --- a/src/main/java/com/google/api/codegen/viewmodel/ParamView.java +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.viewmodel; - -public interface ParamView {} diff --git a/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java b/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java index 197d6448ed..c1a79ede69 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/RequestObjectParamView.java @@ -17,7 +17,7 @@ import com.google.auto.value.AutoValue; @AutoValue -public abstract class RequestObjectParamView implements ParamView { +public abstract class RequestObjectParamView { public abstract String name(); public abstract String elementTypeName(); From c98316aaaa940247563108f367b4587ea81b2767 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 26 Jul 2016 13:26:36 -0700 Subject: [PATCH 11/26] Fixes after merge --- .../api/codegen/transformer/ApiCallableTransformer.java | 6 +++++- .../google/api/codegen/transformer/BundlingTransformer.java | 1 - .../com/google/api/codegen/transformer/SurfaceNamer.java | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java index 90a329b8e1..494624c3a9 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java @@ -111,7 +111,11 @@ private List generateApiCallableSettings(MethodTransformerC settings.resourceTypeName( context.getTypeTable().getAndSaveNicknameForElementType(resourceType)); } else { - settings.resourceTypeName(SurfaceNamer.NOT_IMPLEMENTED); + settings.resourceTypeName( + context + .getNamer() + .getNotImplementedString( + "ApiCallableTransformer.generateApiCallableSettings - resourceTypeName")); if (methodConfig.isBundling()) { settings.type(ApiCallableType.BundlingApiCallable); } else { diff --git a/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java b/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java index 2baf990654..fb2b17f7b7 100644 --- a/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java @@ -100,5 +100,4 @@ private List generateDiscriminatorFieldCopies(MethodTransformerCo } return fieldCopies; } - } diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 7c06084144..01e3b22127 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -220,7 +220,7 @@ public String getDynamicReturnTypeName( public String getStaticReturnTypeName( ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getStaticReturnTypeName"); } public String getPagedCallableMethodName(Method method) { @@ -248,7 +248,7 @@ public String getSettingsFunctionName(Method method) { } public String getGenericAwareResponseType(ModelTypeTable typeTable, TypeRef outputType) { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getGenericAwareResponseType"); } public String getGetResourceListCallName(Field resourcesField) { @@ -256,6 +256,6 @@ public String getGetResourceListCallName(Field resourcesField) { } public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef resourceType) { - return SurfaceNamer.NOT_IMPLEMENTED; + return getNotImplementedString("SurfaceNamer.getAndSavePagedResponseTypeName"); } } From 6196a6d719a0996ffbb63df5ecdd8ba41c32c41c Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 26 Jul 2016 13:49:38 -0700 Subject: [PATCH 12/26] Renaming ViewNamer to NameFormatterMixin --- .../api/codegen/transformer/SurfaceNamer.java | 14 +++++++++++--- ...{ViewNamer.java => NameFormatterMixin.java} | 18 ++++++++---------- 2 files changed, 19 insertions(+), 13 deletions(-) rename src/main/java/com/google/api/codegen/util/{ViewNamer.java => NameFormatterMixin.java} (73%) diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 3e0c0b57fa..72f8018bd1 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -21,7 +21,7 @@ import com.google.api.codegen.util.Name; import com.google.api.codegen.util.NameFormatter; import com.google.api.codegen.util.NamePath; -import com.google.api.codegen.util.ViewNamer; +import com.google.api.codegen.util.NameFormatterMixin; import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.Interface; @@ -32,9 +32,17 @@ import java.util.List; /** - * A SurfaceNamer provides language-specific names or other strings. + * A SurfaceNamer provides language-specific names for specific components of a view for a surface. + * + * Naming is composed of two steps: + * + * 1. Composing a Name instance with the name pieces + * 2. Formatting the Name for the particular type of identifier needed. + * + * This class delegates step 2 to the provided name formatter, which generally + * would be a language-specific namer. */ -public class SurfaceNamer extends ViewNamer { +public class SurfaceNamer extends NameFormatterMixin { public SurfaceNamer(NameFormatter languageNamer) { super(languageNamer); } diff --git a/src/main/java/com/google/api/codegen/util/ViewNamer.java b/src/main/java/com/google/api/codegen/util/NameFormatterMixin.java similarity index 73% rename from src/main/java/com/google/api/codegen/util/ViewNamer.java rename to src/main/java/com/google/api/codegen/util/NameFormatterMixin.java index 7a667bbf5b..0c000afadd 100644 --- a/src/main/java/com/google/api/codegen/util/ViewNamer.java +++ b/src/main/java/com/google/api/codegen/util/NameFormatterMixin.java @@ -15,21 +15,19 @@ package com.google.api.codegen.util; /** - * A ViewNamer provides names for specific components of a view. + * NameFormatterMixin is an abstract class that implements NameFormatter and + * simply forwards calls to another NameFormatter. This allows a child class + * to provide the interface of NameFormatter along with additional functionality. * - * Naming is composed of two steps: - * - * 1. Composing a Name instance with the name pieces - * 2. Formatting the Name for the particular type of identifier needed. - * - * This class delegates step 2 to the provided name formatter, which generally - * would be a language-specific namer. + * Note to future maintainers: This class should only contain methods which + * forward on to NameFormatter and nothing else; otherwise, it is no longer + * functioning in spirit as a mix-in. */ -public abstract class ViewNamer implements NameFormatter { +public abstract class NameFormatterMixin implements NameFormatter { private NameFormatter formatter; - public ViewNamer(NameFormatter formatter) { + public NameFormatterMixin(NameFormatter formatter) { this.formatter = formatter; } From 0bc4f9d9f26fa351d782c97a6fa80197af34a48e Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 26 Jul 2016 16:42:58 -0700 Subject: [PATCH 13/26] Decomposing type naming functionality further --- .../transformer/ApiMethodTransformer.java | 5 +- .../transformer/ModelTypeFormatter.java | 41 +++++ .../transformer/ModelTypeFormatterImpl.java | 46 ++++++ .../transformer/ModelTypeNameConverter.java | 51 ++++++ .../codegen/transformer/ModelTypeTable.java | 80 ++++++---- .../api/codegen/transformer/SurfaceNamer.java | 16 +- .../php/PhpGapicSurfaceTransformer.java | 5 +- ...le.java => PhpModelTypeNameConverter.java} | 150 +++++------------- .../transformer/php/PhpSurfaceNamer.java | 10 +- .../api/codegen/util/TypeNameConverter.java | 25 +++ .../google/api/codegen/util/TypeTable.java | 30 +++- .../google/api/codegen/util/TypedValue.java | 51 ++++++ .../api/codegen/util/php/PhpTypeTable.java | 9 ++ .../google/api/codegen/util/TypeNameTest.java | 25 +++ 14 files changed, 390 insertions(+), 154 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java create mode 100644 src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java create mode 100644 src/main/java/com/google/api/codegen/transformer/ModelTypeNameConverter.java rename src/main/java/com/google/api/codegen/transformer/php/{PhpModelTypeTable.java => PhpModelTypeNameConverter.java} (68%) create mode 100644 src/main/java/com/google/api/codegen/util/TypeNameConverter.java create mode 100644 src/main/java/com/google/api/codegen/util/TypedValue.java diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index 1ee91cdf19..646d997178 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -89,8 +89,7 @@ private ApiMethodDocView generateOptionalArrayMethodDoc(MethodTransformerContext docBuilder.returnTypeName( context .getNamer() - .getDynamicReturnTypeName( - context.getTypeTable(), context.getMethod(), context.getMethodConfig())); + .getDynamicReturnTypeName(context.getMethod(), context.getMethodConfig())); docBuilder.throwsDocLines(new ArrayList()); return docBuilder.build(); @@ -239,7 +238,7 @@ private ParamDocView getCallSettingsParamDoc(MethodTransformerContext context) { List arrayKeyDocs = new ArrayList<>(); SimpleParamDocView.Builder retrySettingsDoc = SimpleParamDocView.newBuilder(); - retrySettingsDoc.typeName(context.getNamer().getRetrySettingsClassName()); + retrySettingsDoc.typeName(context.getNamer().getRetrySettingsTypeName()); Name retrySettingsName = Name.from("retry", "settings"); Name timeoutMillisName = Name.from("timeout", "millis"); diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java new file mode 100644 index 0000000000..31a2af06ec --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java @@ -0,0 +1,41 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.tools.framework.model.TypeRef; + +/** + * A read-only interface for mapping TypeRef instances to a corresponding + * String representation for a particular language. + * + * Passing this type ensures that mutable functionality in derived classes + * won't be called. + */ +public interface ModelTypeFormatter { + /** + * Get the full name for the given type. + */ + String getFullNameFor(TypeRef type); + + /** + * Returns the nickname for the given type (without adding the full name to the import set). + */ + String getNicknameFor(TypeRef type); + + /** + * Renders the primitive value of the given type. + */ + String renderPrimitiveValue(TypeRef type, String key); +} diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java new file mode 100644 index 0000000000..7337483d6c --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java @@ -0,0 +1,46 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.tools.framework.model.TypeRef; + +/** + * Default implementation of ModelTypeFormatter. + */ +public class ModelTypeFormatterImpl implements ModelTypeFormatter { + private ModelTypeNameConverter typeNameConverter; + + /** + * Standard constructor. + */ + public ModelTypeFormatterImpl(ModelTypeNameConverter typeNameConverter) { + this.typeNameConverter = typeNameConverter; + } + + @Override + public String getFullNameFor(TypeRef type) { + return typeNameConverter.getTypeName(type).getFullName(); + } + + @Override + public String getNicknameFor(TypeRef type) { + return typeNameConverter.getTypeName(type).getNickname(); + } + + @Override + public String renderPrimitiveValue(TypeRef type, String value) { + return typeNameConverter.renderPrimitiveValue(type, value); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeNameConverter.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeNameConverter.java new file mode 100644 index 0000000000..93a60cdcf4 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeNameConverter.java @@ -0,0 +1,51 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.TypedValue; +import com.google.api.tools.framework.model.ProtoElement; +import com.google.api.tools.framework.model.TypeRef; + +/** + * ModelTypeNameConverter maps TypeRef instances to TypeName instances. + */ +public interface ModelTypeNameConverter { + /** + * Provides a TypeName for the given TypeRef. + */ + TypeName getTypeName(TypeRef type); + + /** + * Provides a TypeName for the element type of the given TypeRef. + */ + TypeName getTypeNameForElementType(TypeRef type); + + /** + * Provides a TypeName for the given ProtoElement. + */ + TypeName getTypeName(ProtoElement elem); + + /** + * Provides a TypedValue containing the zero value of the given + * type, plus the TypeName of the type. + */ + TypedValue getZeroValue(TypeRef type); + + /** + * Renders the given value if it is a primitive type. + */ + String renderPrimitiveValue(TypeRef type, String value); +} diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java index 91e1549878..a1a402433c 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.transformer; +import com.google.api.codegen.util.TypeTable; import com.google.api.tools.framework.model.TypeRef; import java.util.List; @@ -22,45 +23,64 @@ * A ModelTypeTable manages the imports for a set of fully-qualified type names, and * provides helper methods for importing instances of TypeRef. */ -public interface ModelTypeTable { +public class ModelTypeTable implements ModelTypeFormatter { + private ModelTypeFormatterImpl typeFormatter; + private TypeTable typeTable; + private ModelTypeNameConverter typeNameConverter; /** - * Creates a new ModelTypeTable of the same concrete type, but with an empty import set. + * Standard constructor. */ - ModelTypeTable cloneEmpty(); + public ModelTypeTable(TypeTable typeTable, ModelTypeNameConverter typeNameConverter) { + this.typeFormatter = new ModelTypeFormatterImpl(typeNameConverter); + this.typeTable = typeTable; + this.typeNameConverter = typeNameConverter; + } - /** - * Compute the nickname for the given fullName and save it in the import set. - */ - void saveNicknameFor(String fullName); + @Override + public String getFullNameFor(TypeRef type) { + return typeFormatter.getFullNameFor(type); + } - /** - * Get the full name for the given type. - */ - String getFullNameFor(TypeRef type); + @Override + public String getNicknameFor(TypeRef type) { + return typeFormatter.getNicknameFor(type); + } + + @Override + public String renderPrimitiveValue(TypeRef type, String value) { + return typeFormatter.renderPrimitiveValue(type, value); + } /** - * If the given type is repeated, then returns the contained type; if the type is - * not a repeated type, then returns the boxed form of the type. + * Creates a new ModelTypeTable of the same concrete type, but with an empty import set. */ - String getFullNameForElementType(TypeRef type); + public ModelTypeTable cloneEmpty() { + return new ModelTypeTable(typeTable.cloneEmpty(), typeNameConverter); + } /** - * Returns the nickname for the given type (without adding the full name to the import set). + * Compute the nickname for the given fullName and save it in the import set. */ - String getNicknameFor(TypeRef type); + public void saveNicknameFor(String fullName) { + getAndSaveNicknameFor(fullName); + } /** * Computes the nickname for the given full name, adds the full name to the import set, * and returns the nickname. */ - String getAndSaveNicknameFor(String fullName); + public String getAndSaveNicknameFor(String fullName) { + return typeTable.getAndSaveNicknameFor(fullName); + } /** * Computes the nickname for the given type, adds the full name to the import set, * and returns the nickname. */ - String getAndSaveNicknameFor(TypeRef type); + public String getAndSaveNicknameFor(TypeRef type) { + return typeTable.getAndSaveNicknameFor(typeNameConverter.getTypeName(type)); + } /** * This function will compute the nickname for the element type, add the full name to the @@ -68,28 +88,22 @@ public interface ModelTypeTable { * element type is the contained type; if the type is not a repeated type, then the element * type is the boxed form of the type. */ - String getAndSaveNicknameForElementType(TypeRef type); - - /** - * Computes the nickname for the given container type name and element type name, - * saves the full names of those types in the import set, and then returns the - * formatted nickname for the type. - */ - String getAndSaveNicknameForContainer(String containerFullName, String elementFullName); - - /** - * Renders the primitive value of the given type. - */ - String renderPrimitiveValue(TypeRef type, String key); + public String getAndSaveNicknameForElementType(TypeRef type) { + return typeTable.getAndSaveNicknameFor(typeNameConverter.getTypeNameForElementType(type)); + } /** * If the given type is not implicitly imported, the add it to the import set, then return * the zero value for that type. */ - String getZeroValueAndSaveNicknameFor(TypeRef type); + public String getZeroValueAndSaveNicknameFor(TypeRef type) { + return typeNameConverter.getZeroValue(type).getValueAndSaveTypeNicknameIn(typeTable); + } /** * Returns the imports accumulated so far. */ - List getImports(); + public List getImports() { + return typeTable.getImports(); + } } diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 72f8018bd1..bd42d2b269 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -20,8 +20,8 @@ import com.google.api.codegen.util.CommonRenderingUtil; import com.google.api.codegen.util.Name; import com.google.api.codegen.util.NameFormatter; -import com.google.api.codegen.util.NamePath; import com.google.api.codegen.util.NameFormatterMixin; +import com.google.api.codegen.util.NamePath; import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.Interface; @@ -43,8 +43,15 @@ * would be a language-specific namer. */ public class SurfaceNamer extends NameFormatterMixin { - public SurfaceNamer(NameFormatter languageNamer) { + private ModelTypeFormatter modelTypeFormatter; + + public SurfaceNamer(NameFormatter languageNamer, ModelTypeFormatter modelTypeFormatter) { super(languageNamer); + this.modelTypeFormatter = modelTypeFormatter; + } + + public ModelTypeFormatter getModelTypeFormatter() { + return modelTypeFormatter; } public String getNotImplementedString(String feature) { @@ -154,7 +161,7 @@ public String getGrpcMethodName(Method method) { return Name.upperCamel(method.getSimpleName()).toUpperCamel(); } - public String getRetrySettingsClassName() { + public String getRetrySettingsTypeName() { return getNotImplementedString("SurfaceNamer.getRetrySettingsClassName"); } @@ -162,8 +169,7 @@ public String getOptionalArrayTypeName() { return getNotImplementedString("SurfaceNamer.getOptionalArrayTypeName"); } - public String getDynamicReturnTypeName( - ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + public String getDynamicReturnTypeName(Method method, MethodConfig methodConfig) { return getNotImplementedString("SurfaceNamer.getDynamicReturnTypeName"); } } diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java index 6f1acf3e3a..d254f00aa3 100644 --- a/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java @@ -25,6 +25,7 @@ import com.google.api.codegen.transformer.PathTemplateTransformer; import com.google.api.codegen.transformer.SurfaceNamer; import com.google.api.codegen.transformer.SurfaceTransformerContext; +import com.google.api.codegen.util.php.PhpTypeTable; import com.google.api.codegen.viewmodel.ApiMethodView; import com.google.api.codegen.viewmodel.DynamicXApiView; import com.google.api.codegen.viewmodel.ServiceDocView; @@ -67,9 +68,11 @@ public List getTemplateFileNames() { public List transform(Model model, ApiConfig apiConfig) { List surfaceDocs = new ArrayList<>(); for (Interface service : new InterfaceView().getElementIterable(model)) { + ModelTypeTable modelTypeTable = + new ModelTypeTable(new PhpTypeTable(), new PhpModelTypeNameConverter()); SurfaceTransformerContext context = SurfaceTransformerContext.create( - service, apiConfig, new PhpModelTypeTable(), new PhpSurfaceNamer()); + service, apiConfig, modelTypeTable, new PhpSurfaceNamer()); surfaceDocs.addAll(transform(context)); } diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java similarity index 68% rename from src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java rename to src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java index 81331ef5b3..9cd87ec5af 100644 --- a/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java @@ -14,8 +14,10 @@ */ package com.google.api.codegen.transformer.php; -import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.ModelTypeNameConverter; import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.TypeNameConverter; +import com.google.api.codegen.util.TypedValue; import com.google.api.codegen.util.php.PhpTypeTable; import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.ProtoFile; @@ -23,15 +25,7 @@ import com.google.common.collect.ImmutableMap; import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; -import java.util.List; - -import org.apache.commons.lang3.NotImplementedException; - -/** - * The ModelTypeTable for PHP. - */ -public class PhpModelTypeTable implements ModelTypeTable { - private PhpTypeTable phpTypeTable; +public class PhpModelTypeNameConverter implements ModelTypeNameConverter { /** * A map from primitive types in proto to PHP counterparts. @@ -77,52 +71,14 @@ public class PhpModelTypeTable implements ModelTypeTable { .put(Type.TYPE_BYTES, "\"\"") .build(); - /** - * Standard constructor. - */ - public PhpModelTypeTable() { - phpTypeTable = new PhpTypeTable(); - } - - @Override - public ModelTypeTable cloneEmpty() { - return new PhpModelTypeTable(); - } - - @Override - public String getFullNameFor(TypeRef type) { - return getTypeName(type).getFullName(); - } - - @Override - public String getFullNameForElementType(TypeRef type) { - return getTypeNameForElementType(type).getFullName(); - } - - @Override - public String getNicknameFor(TypeRef type) { - return getTypeName(type).getNickname(); - } - - @Override - public void saveNicknameFor(String fullName) { - getAndSaveNicknameFor(fullName); - } + private TypeNameConverter typeNameConverter; - @Override - public String getAndSaveNicknameFor(String fullName) { - return phpTypeTable.getAndSaveNicknameFor(fullName); + public PhpModelTypeNameConverter() { + this.typeNameConverter = new PhpTypeTable(); } - /** - * Returns the PHP representation of a reference to a type. - */ @Override - public String getAndSaveNicknameFor(TypeRef type) { - return phpTypeTable.getAndSaveNicknameFor(getTypeName(type)); - } - - private TypeName getTypeName(TypeRef type) { + public TypeName getTypeName(TypeRef type) { if (type.isMap()) { return new TypeName("array"); } else if (type.isRepeated()) { @@ -133,27 +89,18 @@ private TypeName getTypeName(TypeRef type) { } } - @Override - public String getAndSaveNicknameForElementType(TypeRef type) { - return phpTypeTable.getAndSaveNicknameFor(getTypeNameForElementType(type)); - } - - @Override - public String getAndSaveNicknameForContainer(String containerFullName, String elementFullName) { - throw new NotImplementedException("ModelToPhpTypeTable.getAndSaveNicknameForContainer"); - } - /** * Returns the PHP representation of a type, without cardinality. If the type is a primitive, - * importAndGetShortestNameForElementType returns it in unboxed form. + * getTypeNameForElementType returns it in unboxed form. */ - private TypeName getTypeNameForElementType(TypeRef type) { + @Override + public TypeName getTypeNameForElementType(TypeRef type) { String primitiveTypeName = PRIMITIVE_TYPE_MAP.get(type.getKind()); if (primitiveTypeName != null) { if (primitiveTypeName.contains("\\")) { // Fully qualified type name, use regular type name resolver. Can skip boxing logic // because those types are already boxed. - return phpTypeTable.getTypeName(primitiveTypeName); + return typeNameConverter.getTypeName(primitiveTypeName); } else { return new TypeName(primitiveTypeName); } @@ -169,65 +116,56 @@ private TypeName getTypeNameForElementType(TypeRef type) { } @Override - public String renderPrimitiveValue(TypeRef type, String value) { - Type primitiveType = type.getKind(); - if (!PRIMITIVE_TYPE_MAP.containsKey(primitiveType)) { - throw new IllegalArgumentException( - "Initial values are only supported for primitive types, got type " - + type - + ", with value " - + value); - } - switch (primitiveType) { - case TYPE_BOOL: - return value.toLowerCase(); - case TYPE_STRING: - case TYPE_BYTES: - return "\"" + value + "\""; - default: - // Types that do not need to be modified (e.g. TYPE_INT32) are handled here - return value; - } + public TypeName getTypeName(ProtoElement elem) { + // Construct the fully-qualified PHP class name + int fullNamePrefixLength = elem.getFile().getFullName().length() + 1; + String nickname = elem.getFullName().substring(fullNamePrefixLength); + String fullName = getPhpPackage(elem.getFile()) + "\\" + nickname; + return new TypeName(fullName, nickname); } /** * Returns the PHP representation of a zero value for that type, to be used in code sample doc. - * - * Parametric types may use the diamond operator, since the return value will be used only in - * initialization. */ @Override - public String getZeroValueAndSaveNicknameFor(TypeRef type) { + public TypedValue getZeroValue(TypeRef type) { // Don't call getTypeName; we don't need to import these. if (type.isMap()) { - return "[]"; + return TypedValue.create(new TypeName("array"), "[]"); } if (type.isRepeated()) { - return "[]"; + return TypedValue.create(new TypeName("array"), "[]"); } if (PRIMITIVE_ZERO_VALUE.containsKey(type.getKind())) { - return PRIMITIVE_ZERO_VALUE.get(type.getKind()); + return TypedValue.create(getTypeName(type), PRIMITIVE_ZERO_VALUE.get(type.getKind())); } if (type.isMessage()) { - return "new " + getAndSaveNicknameFor(type) + "()"; + return TypedValue.create(getTypeName(type), "new %s()"); } - return "null"; + return TypedValue.create(new TypeName(""), "null"); } @Override - public List getImports() { - return phpTypeTable.getImports(); - } - - /** - * Gets the full name of the message or enum type in PHP. - */ - private TypeName getTypeName(ProtoElement elem) { - // Construct the fully-qualified PHP class name - int fullNamePrefixLength = elem.getFile().getFullName().length() + 1; - String nickname = elem.getFullName().substring(fullNamePrefixLength); - String fullName = getPhpPackage(elem.getFile()) + "\\" + nickname; - return new TypeName(fullName, nickname); + public String renderPrimitiveValue(TypeRef type, String value) { + Type primitiveType = type.getKind(); + if (!PRIMITIVE_TYPE_MAP.containsKey(primitiveType)) { + throw new IllegalArgumentException( + "Initial values are only supported for primitive types, got type " + + type + + ", with value " + + value); + } + switch (primitiveType) { + case TYPE_BOOL: + return value.toLowerCase(); + case TYPE_STRING: + case TYPE_BYTES: + return "\"" + value + "\""; + default: + // Types that do not need to be modified (e.g. TYPE_INT32) are handled + // here + return value; + } } /** diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java index f50b32b0e3..52207489bd 100644 --- a/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java @@ -17,6 +17,7 @@ import com.google.api.codegen.CollectionConfig; import com.google.api.codegen.MethodConfig; import com.google.api.codegen.ServiceMessages; +import com.google.api.codegen.transformer.ModelTypeFormatterImpl; import com.google.api.codegen.transformer.ModelTypeTable; import com.google.api.codegen.transformer.SurfaceNamer; import com.google.api.codegen.util.Name; @@ -31,7 +32,7 @@ */ public class PhpSurfaceNamer extends SurfaceNamer { public PhpSurfaceNamer() { - super(new PhpNameFormatter()); + super(new PhpNameFormatter(), new ModelTypeFormatterImpl(new PhpModelTypeNameConverter())); } @Override @@ -66,7 +67,7 @@ public boolean shouldImportRequestObjectParamType(Field field) { } @Override - public String getRetrySettingsClassName() { + public String getRetrySettingsTypeName() { return "Google\\GAX\\RetrySettings"; } @@ -76,14 +77,13 @@ public String getOptionalArrayTypeName() { } @Override - public String getDynamicReturnTypeName( - ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + public String getDynamicReturnTypeName(Method method, MethodConfig methodConfig) { if (new ServiceMessages().isEmptyType(method.getOutputType())) { return ""; } if (methodConfig.isPageStreaming()) { return "Google\\GAX\\PageAccessor"; } - return typeTable.getFullNameFor(method.getOutputType()); + return getModelTypeFormatter().getFullNameFor(method.getOutputType()); } } diff --git a/src/main/java/com/google/api/codegen/util/TypeNameConverter.java b/src/main/java/com/google/api/codegen/util/TypeNameConverter.java new file mode 100644 index 0000000000..8cb57de50b --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/TypeNameConverter.java @@ -0,0 +1,25 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +/** + * A TypeNameConverter maps Strings to TypeName instances. + */ +public interface TypeNameConverter { + /** + * Maps the given fullName to a TypeName. + */ + TypeName getTypeName(String fullName); +} diff --git a/src/main/java/com/google/api/codegen/util/TypeTable.java b/src/main/java/com/google/api/codegen/util/TypeTable.java index 4393b81c52..419e2f59af 100644 --- a/src/main/java/com/google/api/codegen/util/TypeTable.java +++ b/src/main/java/com/google/api/codegen/util/TypeTable.java @@ -14,14 +14,42 @@ */ package com.google.api.codegen.util; +import java.util.List; + /** * A type table manages the imports for a set of fully-qualified type names. */ -public interface TypeTable { +public interface TypeTable extends TypeNameConverter { + + @Override + TypeName getTypeName(String fullName); + + /** + * Return a new TypeTable with the same concrete type as this one. + */ + TypeTable cloneEmpty(); + + /** + * Computes the nickname for the given full name, adds the full name to the import set, + * and returns the nickname. + */ + String getAndSaveNicknameFor(String fullName); + + /** + * Computes the nickname for the given type, adds the full name to the import set, + * and returns the nickname. + */ + String getAndSaveNicknameFor(TypeName typeName); + /** * Determines if the nickname of the given alias can be used, and if so, then * saves it in the import table and returns it; otherwise (e.g. if there would * be a clash), returns the full name. */ String getAndSaveNicknameFor(TypeAlias alias); + + /** + * Returns the imports accumulated so far. + */ + List getImports(); } diff --git a/src/main/java/com/google/api/codegen/util/TypedValue.java b/src/main/java/com/google/api/codegen/util/TypedValue.java new file mode 100644 index 0000000000..249f20b302 --- /dev/null +++ b/src/main/java/com/google/api/codegen/util/TypedValue.java @@ -0,0 +1,51 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.util; + +import com.google.auto.value.AutoValue; + +import org.apache.commons.lang3.StringUtils; + +/** + * Represents a value and its associated type. + */ +@AutoValue +public abstract class TypedValue { + + /** + * Create a TypedValue. The pattern "%s" in valuePattern is used by + * getValueAndSaveTypeNicknameIn to format the final value. + */ + public static TypedValue create(TypeName typeName, String valuePattern) { + return new AutoValue_TypedValue(typeName, valuePattern); + } + + public abstract TypeName getTypeName(); + + public abstract String getValuePattern(); + + /** + * Renders the value given the value pattern, and adds any necessary nicknames + * to the given type table. + */ + public String getValueAndSaveTypeNicknameIn(TypeTable typeTable) { + if (getValuePattern().contains("%s")) { + String nickname = typeTable.getAndSaveNicknameFor(getTypeName()); + return StringUtils.replaceOnce(getValuePattern(), "%s", nickname); + } else { + return getValuePattern(); + } + } +} diff --git a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java index 3267b99268..5ad91a87d2 100644 --- a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java @@ -34,6 +34,12 @@ public class PhpTypeTable implements TypeTable { */ private final BiMap imports = HashBiMap.create(); + @Override + public TypeTable cloneEmpty() { + return new PhpTypeTable(); + } + + @Override public TypeName getTypeName(String fullName) { int lastBackslashIndex = fullName.lastIndexOf('\\'); if (lastBackslashIndex < 0) { @@ -43,10 +49,12 @@ public TypeName getTypeName(String fullName) { return new TypeName(fullName, nickname); } + @Override public String getAndSaveNicknameFor(String fullName) { return getAndSaveNicknameFor(getTypeName(fullName)); } + @Override public String getAndSaveNicknameFor(TypeName typeName) { return typeName.getAndSaveNicknameIn(this); } @@ -69,6 +77,7 @@ public String getAndSaveNicknameFor(TypeAlias alias) { return alias.getNickname(); } + @Override public List getImports() { // Clean up the imports. List cleanedImports = new ArrayList<>(); diff --git a/src/test/java/com/google/api/codegen/util/TypeNameTest.java b/src/test/java/com/google/api/codegen/util/TypeNameTest.java index 612b8c6765..d2ebcafc4d 100644 --- a/src/test/java/com/google/api/codegen/util/TypeNameTest.java +++ b/src/test/java/com/google/api/codegen/util/TypeNameTest.java @@ -60,5 +60,30 @@ public String getAndSaveNicknameFor(TypeAlias alias) { imports.add(alias); return alias.getNickname(); } + + @Override + public TypeName getTypeName(String fullName) { + return null; + } + + @Override + public TypeTable cloneEmpty() { + return new MockTypeTable(); + } + + @Override + public String getAndSaveNicknameFor(String fullName) { + return null; + } + + @Override + public String getAndSaveNicknameFor(TypeName typeName) { + return null; + } + + @Override + public List getImports() { + return null; + } } } From fd76cf954a615cc7fb437ae3bfb8bf808db99fd9 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 26 Jul 2016 16:48:26 -0700 Subject: [PATCH 14/26] Partial impl --- .../transformer/java/JavaSurfaceNamer.java | 2 - .../google/api/codegen/java/xsettings.snip | 55 +++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java index 98b9a6f8b0..135ad22408 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java @@ -20,9 +20,7 @@ import com.google.api.codegen.transformer.SurfaceNamer; import com.google.api.codegen.util.java.JavaNameFormatter; import com.google.api.codegen.util.java.JavaRenderingUtil; -import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; import com.google.api.tools.framework.model.Method; -import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.TypeRef; import java.util.Arrays; diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index f710a9a9dd..2c367db3f7 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -11,6 +11,7 @@ {@members(xsettingsClass)} {@constructors(xsettingsClass)} {@descriptors(xsettingsClass)} + {@innerBuilderClass(xsettingsClass)} } @end @@ -247,3 +248,57 @@ .{@fieldCopy.fnSetFunctionCallName}(firstRequest.{@fieldCopy.fnGetFunctionCallName}()) @end @end + +@private innerBuilderClass(xsettingsClass) + /** + * Builder for {@xsettingsClass.name}. + */ + public static class Builder extends ServiceApiSettings.Builder { + private final ImmutableList methodSettingsBuilders; + + {@builderMembers(xsettingsClass)} + + # {@builderConstants(xsettingsClass)} + + # {@builderConstructors(xsettingsClass)} + + # {@builderMethods(xsettingsClass)} + } +@end + +@private builderMembers(xsettingsClass) + @join settings : xsettingsClass.callSettings + @switch settings.type.toString + @case "SimpleApiCallable" + private SimpleCallSettings.Builder<{@desc.requestTypeName}, \ + {@desc.responseTypeName}> {@settings.memberName}; + @case "PagedApiCallable" + private PageStreamingCallSettings.Builder<{@desc.requestTypeName}, \ + {@desc.responseTypeName}, {@desc.resourceTypeName}> {@settings.memberName}; + @case "BundlingApiCallable" + private BundlingCallSettings.Builder<{@desc.requestTypeName}, \ + {@desc.responseTypeName}> {@settings.memberName}; + @default + $unhandledCase: {@settings.type.toString}$ + @end + @end + @join method : service.getMethods + @if {@isPageStreaming} + @let pageStreaming = methodConfig.getPageStreaming(), \ + resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ + dummy = context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings") + private PageStreamingCallSettings.Builder<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> + {@methodName}Settings; + @end + @else + @if {@isBundling} + @let bundling = methodConfig.getBundling(), \ + dummy = context.addImport("com.google.api.gax.grpc.BundlingCallSettings") + private BundlingCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings; + @end + @else + private SimpleCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings; + @end + @end + @end +@end From 8a06ab935858178a5e293e997d0137438a0c61d1 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Tue, 26 Jul 2016 18:59:47 -0700 Subject: [PATCH 15/26] fixing java code after merge --- .../transformer/ApiMethodTransformer.java | 14 ++- .../transformer/ModelTypeFormatter.java | 5 + .../transformer/ModelTypeFormatterImpl.java | 5 + .../codegen/transformer/ModelTypeTable.java | 18 ++++ .../api/codegen/transformer/SurfaceNamer.java | 5 +- .../java/JavaGapicSurfaceTransformer.java | 5 +- ...e.java => JavaModelTypeNameConverter.java} | 96 +++++-------------- .../transformer/java/JavaSurfaceNamer.java | 13 +-- .../api/codegen/util/java/JavaTypeTable.java | 7 +- .../google/api/codegen/java/xsettings.snip | 5 +- 10 files changed, 78 insertions(+), 95 deletions(-) rename src/main/java/com/google/api/codegen/transformer/java/{JavaModelTypeTable.java => JavaModelTypeNameConverter.java} (74%) diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index 73689bcf9b..2cc10e32f9 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -244,11 +244,10 @@ private void setCallableMethodFields( methodViewBuilder.requestObjectParams(new ArrayList()); methodViewBuilder.pathTemplateChecks(new ArrayList()); + String genericAwareResponseTypeFullName = + context.getNamer().getGenericAwareResponseTypeName(context.getMethod().getOutputType()); String genericAwareResponseType = - context - .getNamer() - .getGenericAwareResponseType( - context.getTypeTable(), context.getMethod().getOutputType()); + context.getTypeTable().getAndSaveNicknameFor(genericAwareResponseTypeFullName); methodViewBuilder.callableMethod( CallableMethodDetailView.newBuilder() .genericAwareResponseType(genericAwareResponseType) @@ -258,11 +257,10 @@ private void setCallableMethodFields( public void setSyncStaticReturnFields( MethodTransformerContext context, StaticApiMethodView.Builder methodViewBuilder) { + String staticReturnTypeFullName = + context.getNamer().getStaticReturnTypeName(context.getMethod(), context.getMethodConfig()); methodViewBuilder.responseTypeName( - context - .getNamer() - .getStaticReturnTypeName( - context.getTypeTable(), context.getMethod(), context.getMethodConfig())); + context.getTypeTable().getAndSaveNicknameFor(staticReturnTypeFullName)); methodViewBuilder.hasReturnValue( !ServiceMessages.s_isEmptyType(context.getMethod().getOutputType())); } diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java index 31a2af06ec..a05c68cd31 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java @@ -29,6 +29,11 @@ public interface ModelTypeFormatter { */ String getFullNameFor(TypeRef type); + /** + * Get the full name for the element type of the given type. + */ + String getFullNameForElementType(TypeRef type); + /** * Returns the nickname for the given type (without adding the full name to the import set). */ diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java index 7337483d6c..9e0dad107e 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java @@ -34,6 +34,11 @@ public String getFullNameFor(TypeRef type) { return typeNameConverter.getTypeName(type).getFullName(); } + @Override + public String getFullNameForElementType(TypeRef type) { + return typeNameConverter.getTypeNameForElementType(type).getFullName(); + } + @Override public String getNicknameFor(TypeRef type) { return typeNameConverter.getTypeName(type).getNickname(); diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java index a1a402433c..0dabfb20d1 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.transformer; +import com.google.api.codegen.util.TypeName; import com.google.api.codegen.util.TypeTable; import com.google.api.tools.framework.model.TypeRef; @@ -42,6 +43,10 @@ public String getFullNameFor(TypeRef type) { return typeFormatter.getFullNameFor(type); } + public String getFullNameForElementType(TypeRef type) { + return typeFormatter.getFullNameForElementType(type); + } + @Override public String getNicknameFor(TypeRef type) { return typeFormatter.getNicknameFor(type); @@ -92,6 +97,19 @@ public String getAndSaveNicknameForElementType(TypeRef type) { return typeTable.getAndSaveNicknameFor(typeNameConverter.getTypeNameForElementType(type)); } + public String getAndSaveNicknameForContainer(String containerFullName, String elementFullName) { + TypeName containerTypeName = typeTable.getTypeName(containerFullName); + TypeName elementTypeName = typeTable.getTypeName(elementFullName); + TypeName completeTypeName = + new TypeName( + containerTypeName.getFullName(), + containerTypeName.getNickname(), + // FIXME make not java specific + "%s<%i>", + elementTypeName); + return typeTable.getAndSaveNicknameFor(completeTypeName); + } + /** * If the given type is not implicitly imported, the add it to the import set, then return * the zero value for that type. diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 1a855d76f0..dd7c59dd93 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -232,8 +232,7 @@ public String getDynamicReturnTypeName(Method method, MethodConfig methodConfig) return getNotImplementedString("SurfaceNamer.getDynamicReturnTypeName"); } - public String getStaticReturnTypeName( - ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + public String getStaticReturnTypeName(Method method, MethodConfig methodConfig) { return getNotImplementedString("SurfaceNamer.getStaticReturnTypeName"); } @@ -261,7 +260,7 @@ public String getSettingsFunctionName(Method method) { return getSettingsMemberName(method); } - public String getGenericAwareResponseType(ModelTypeTable typeTable, TypeRef outputType) { + public String getGenericAwareResponseTypeName(TypeRef outputType) { return getNotImplementedString("SurfaceNamer.getGenericAwareResponseType"); } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index 2c83b7e136..17d27000cc 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -28,6 +28,7 @@ import com.google.api.codegen.transformer.PageStreamingTransformer; import com.google.api.codegen.transformer.PathTemplateTransformer; import com.google.api.codegen.transformer.SurfaceTransformerContext; +import com.google.api.codegen.util.java.JavaTypeTable; import com.google.api.codegen.viewmodel.StaticApiMethodView; import com.google.api.codegen.viewmodel.StaticXApiView; import com.google.api.codegen.viewmodel.StaticXSettingsView; @@ -77,9 +78,11 @@ public List getTemplateFileNames() { public List transform(Model model, ApiConfig apiConfig) { List surfaceDocs = new ArrayList<>(); for (Interface service : new InterfaceView().getElementIterable(model)) { + ModelTypeTable modelTypeTable = + new ModelTypeTable(new JavaTypeTable(), new JavaModelTypeNameConverter()); SurfaceTransformerContext context = SurfaceTransformerContext.create( - service, apiConfig, new JavaModelTypeTable(), new JavaSurfaceNamer()); + service, apiConfig, modelTypeTable, new JavaSurfaceNamer()); surfaceDocs.addAll(transform(context)); } return surfaceDocs; diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeNameConverter.java similarity index 74% rename from src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java rename to src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeNameConverter.java index f69c9eddd5..2f2e1e4ae5 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaModelTypeNameConverter.java @@ -15,8 +15,10 @@ package com.google.api.codegen.transformer.java; import com.google.api.codegen.LanguageUtil; -import com.google.api.codegen.transformer.ModelTypeTable; +import com.google.api.codegen.transformer.ModelTypeNameConverter; import com.google.api.codegen.util.TypeName; +import com.google.api.codegen.util.TypeNameConverter; +import com.google.api.codegen.util.TypedValue; import com.google.api.codegen.util.java.JavaTypeTable; import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.ProtoFile; @@ -27,13 +29,11 @@ import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; import java.io.File; -import java.util.List; /** * The ModelTypeTable for Java. */ -public class JavaModelTypeTable implements ModelTypeTable { - private JavaTypeTable javaTypeTable; +public class JavaModelTypeNameConverter implements ModelTypeNameConverter { /** * The package prefix protoc uses if no java package option was provided. @@ -84,54 +84,19 @@ public class JavaModelTypeTable implements ModelTypeTable { .put(Type.TYPE_BYTES, "ByteString.copyFromUtf8(\"\")") .build(); + private TypeNameConverter typeNameConverter; + /** * Standard constructor. */ - public JavaModelTypeTable() { - javaTypeTable = new JavaTypeTable(); - } - - @Override - public ModelTypeTable cloneEmpty() { - return new JavaModelTypeTable(); - } - - @Override - public void saveNicknameFor(String fullName) { - getAndSaveNicknameFor(fullName); - } - - @Override - public String getFullNameFor(TypeRef type) { - return getTypeName(type).getFullName(); - } - - @Override - public String getFullNameForElementType(TypeRef type) { - return getTypeNameForElementType(type, true).getFullName(); - } - - @Override - public String getNicknameFor(TypeRef type) { - return getTypeName(type).getNickname(); - } - - @Override - public String getAndSaveNicknameFor(String fullName) { - return javaTypeTable.getAndSaveNicknameFor(fullName); + public JavaModelTypeNameConverter() { + this.typeNameConverter = new JavaTypeTable(); } - /** - * Returns the Java representation of a reference to a type. - */ @Override - public String getAndSaveNicknameFor(TypeRef type) { - return javaTypeTable.getAndSaveNicknameFor(getTypeName(type)); - } - - private TypeName getTypeName(TypeRef type) { + public TypeName getTypeName(TypeRef type) { if (type.isMap()) { - TypeName mapTypeName = javaTypeTable.getTypeName("java.util.Map"); + TypeName mapTypeName = typeNameConverter.getTypeName("java.util.Map"); TypeName keyTypeName = getTypeNameForElementType(type.getMapKeyField().getType(), true); TypeName valueTypeName = getTypeNameForElementType(type.getMapValueField().getType(), true); return new TypeName( @@ -141,7 +106,7 @@ private TypeName getTypeName(TypeRef type) { keyTypeName, valueTypeName); } else if (type.isRepeated()) { - TypeName listTypeName = javaTypeTable.getTypeName("java.util.List"); + TypeName listTypeName = typeNameConverter.getTypeName("java.util.List"); TypeName elementTypeName = getTypeNameForElementType(type, true); return new TypeName( listTypeName.getFullName(), listTypeName.getNickname(), "%s<%i>", elementTypeName); @@ -151,21 +116,8 @@ private TypeName getTypeName(TypeRef type) { } @Override - public String getAndSaveNicknameForElementType(TypeRef type) { - return javaTypeTable.getAndSaveNicknameFor(getTypeNameForElementType(type, true)); - } - - @Override - public String getAndSaveNicknameForContainer(String containerFullName, String elementFullName) { - TypeName containerTypeName = javaTypeTable.getTypeName(containerFullName); - TypeName elementTypeName = javaTypeTable.getTypeName(elementFullName); - TypeName completeTypeName = - new TypeName( - containerTypeName.getFullName(), - containerTypeName.getNickname(), - "%s<%i>", - elementTypeName); - return javaTypeTable.getAndSaveNicknameFor(completeTypeName); + public TypeName getTypeNameForElementType(TypeRef type) { + return getTypeNameForElementType(type, true); } /** @@ -178,7 +130,7 @@ private TypeName getTypeNameForElementType(TypeRef type, boolean shouldBoxPrimit if (primitiveTypeName.contains(".")) { // Fully qualified type name, use regular type name resolver. Can skip boxing logic // because those types are already boxed. - return javaTypeTable.getTypeName(primitiveTypeName); + return typeNameConverter.getTypeName(primitiveTypeName); } else { if (shouldBoxPrimitives) { return new TypeName(JavaTypeTable.getBoxedTypeName(primitiveTypeName)); @@ -197,11 +149,6 @@ private TypeName getTypeNameForElementType(TypeRef type, boolean shouldBoxPrimit } } - @Override - public List getImports() { - return javaTypeTable.getImports(); - } - @Override public String renderPrimitiveValue(TypeRef type, String value) { Type primitiveType = type.getKind(); @@ -237,24 +184,25 @@ public String renderPrimitiveValue(TypeRef type, String value) { * initialization. */ @Override - public String getZeroValueAndSaveNicknameFor(TypeRef type) { + public TypedValue getZeroValue(TypeRef type) { // Don't call importAndGetShortestName; we don't need to import these. if (type.isMap()) { - return "new HashMap<>()"; + return TypedValue.create(typeNameConverter.getTypeName("java.util.HashMap"), "new %s<>()"); } if (type.isRepeated()) { - return "new ArrayList<>()"; + return TypedValue.create(typeNameConverter.getTypeName("java.util.ArrayList"), "new %s<>()"); } if (PRIMITIVE_ZERO_VALUE.containsKey(type.getKind())) { - return PRIMITIVE_ZERO_VALUE.get(type.getKind()); + return TypedValue.create(getTypeName(type), PRIMITIVE_ZERO_VALUE.get(type.getKind())); } if (type.isMessage()) { - return getAndSaveNicknameFor(type) + ".newBuilder().build()"; + return TypedValue.create(getTypeName(type), "%s.newBuilder().build()"); } - return "null"; + return TypedValue.create(new TypeName(""), "null"); } - private TypeName getTypeName(ProtoElement elem) { + @Override + public TypeName getTypeName(ProtoElement elem) { // Construct the full name in Java String name = getJavaPackage(elem.getFile()); if (!elem.getFile().getProto().getOptions().getJavaMultipleFiles()) { diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java index 135ad22408..dbeace41a1 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java @@ -16,8 +16,10 @@ import com.google.api.codegen.MethodConfig; import com.google.api.codegen.ServiceMessages; +import com.google.api.codegen.transformer.ModelTypeFormatterImpl; import com.google.api.codegen.transformer.ModelTypeTable; import com.google.api.codegen.transformer.SurfaceNamer; +import com.google.api.codegen.util.TypeName; import com.google.api.codegen.util.java.JavaNameFormatter; import com.google.api.codegen.util.java.JavaRenderingUtil; import com.google.api.tools.framework.model.Method; @@ -35,7 +37,7 @@ public class JavaSurfaceNamer extends SurfaceNamer { * Standard constructor. */ public JavaSurfaceNamer() { - super(new JavaNameFormatter()); + super(new JavaNameFormatter(), new ModelTypeFormatterImpl(new JavaModelTypeNameConverter())); } @Override @@ -49,20 +51,19 @@ public List getThrowsDocLines() { } @Override - public String getStaticReturnTypeName( - ModelTypeTable typeTable, Method method, MethodConfig methodConfig) { + public String getStaticReturnTypeName(Method method, MethodConfig methodConfig) { if (ServiceMessages.s_isEmptyType(method.getOutputType())) { return "void"; } - return typeTable.getAndSaveNicknameFor(method.getOutputType()); + return getModelTypeFormatter().getFullNameFor(method.getOutputType()); } @Override - public String getGenericAwareResponseType(ModelTypeTable typeTable, TypeRef outputType) { + public String getGenericAwareResponseTypeName(TypeRef outputType) { if (ServiceMessages.s_isEmptyType(outputType)) { return "Void"; } else { - return typeTable.getAndSaveNicknameFor(outputType); + return getModelTypeFormatter().getFullNameFor(outputType); } } diff --git a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java index 0830110afe..01aab1ce6d 100644 --- a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java @@ -57,10 +57,15 @@ public class JavaTypeTable implements TypeTable { .put("double", "Double") .build(); + @Override + public TypeTable cloneEmpty() { + return new JavaTypeTable(); + } + public TypeName getTypeName(String fullName) { int lastDotIndex = fullName.lastIndexOf('.'); if (lastDotIndex < 0) { - throw new IllegalArgumentException("expected fully qualified name"); + return new TypeName(fullName, fullName); } String shortTypeName = fullName.substring(lastDotIndex + 1); return new TypeName(fullName, shortTypeName); diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index 2c367db3f7..664e668712 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -11,7 +11,7 @@ {@members(xsettingsClass)} {@constructors(xsettingsClass)} {@descriptors(xsettingsClass)} - {@innerBuilderClass(xsettingsClass)} + # {@innerBuilderClass(xsettingsClass)} } @end @@ -256,7 +256,7 @@ public static class Builder extends ServiceApiSettings.Builder { private final ImmutableList methodSettingsBuilders; - {@builderMembers(xsettingsClass)} + # {@builderMembers(xsettingsClass)} # {@builderConstants(xsettingsClass)} @@ -282,6 +282,7 @@ $unhandledCase: {@settings.type.toString}$ @end @end + # old @join method : service.getMethods @if {@isPageStreaming} @let pageStreaming = methodConfig.getPageStreaming(), \ From 62ac865c219766f9a7285b1897576b04167bcf42 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Wed, 27 Jul 2016 10:23:49 -0700 Subject: [PATCH 16/26] Java surface: generating settings builder --- .../transformer/ApiCallableTransformer.java | 48 ++- .../api/codegen/transformer/SurfaceNamer.java | 18 + .../java/JavaGapicSurfaceTransformer.java | 47 ++ .../transformer/java/JavaSurfaceNamer.java | 10 + .../viewmodel/ApiCallSettingsView.java | 32 +- .../codegen/viewmodel/BundlingConfigView.java | 49 +++ .../viewmodel/RetryCodesDefinitionView.java | 40 ++ .../viewmodel/RetryParamsDefinitionView.java | 67 +++ .../viewmodel/StaticXSettingsView.java | 8 + .../google/api/codegen/java/xsettings.snip | 227 ++++++++-- .../java_surface_xsettings_library.baseline | 404 ++++++++++++++++++ 11 files changed, 911 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/viewmodel/BundlingConfigView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/RetryCodesDefinitionView.java create mode 100644 src/main/java/com/google/api/codegen/viewmodel/RetryParamsDefinitionView.java diff --git a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java index 494624c3a9..476c1e3614 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java @@ -14,11 +14,13 @@ */ package com.google.api.codegen.transformer; +import com.google.api.codegen.BundlingConfig; import com.google.api.codegen.MethodConfig; import com.google.api.codegen.PageStreamingConfig; import com.google.api.codegen.viewmodel.ApiCallSettingsView; import com.google.api.codegen.viewmodel.ApiCallableType; import com.google.api.codegen.viewmodel.ApiCallableView; +import com.google.api.codegen.viewmodel.BundlingConfigView; import com.google.api.tools.framework.model.Method; import com.google.api.tools.framework.model.TypeRef; @@ -95,37 +97,63 @@ private List generateStaticApiCallables(MethodTransformerContex } private List generateApiCallableSettings(MethodTransformerContext context) { + SurfaceNamer namer = context.getNamer(); ModelTypeTable typeTable = context.getTypeTable(); Method method = context.getMethod(); MethodConfig methodConfig = context.getMethodConfig(); ApiCallSettingsView.Builder settings = ApiCallSettingsView.newBuilder(); - settings.methodName(context.getNamer().getApiMethodName(method)); + settings.methodName(namer.getApiMethodName(method)); settings.requestTypeName(typeTable.getAndSaveNicknameFor(method.getInputType())); settings.responseTypeName(typeTable.getAndSaveNicknameFor(method.getOutputType())); + settings.grpcTypeName( + typeTable.getAndSaveNicknameFor(namer.getGrpcContainerTypeName(context.getInterface()))); + settings.grpcMethodConstant(namer.getGrpcMethodConstant(method)); + settings.retryCodesName(methodConfig.getRetryCodesConfigName()); + settings.retryParamsName(methodConfig.getRetrySettingsConfigName()); + + String notImplementedPrefix = "ApiCallableTransformer.generateApiCallableSettings - "; + settings.resourceTypeName( + namer.getNotImplementedString(notImplementedPrefix + "resourceTypeName")); + settings.pageStreamingDescriptorName( + namer.getNotImplementedString(notImplementedPrefix + "pageStreamingDescriptorName")); + settings.bundlingDescriptorName( + namer.getNotImplementedString(notImplementedPrefix + "bundlingDescriptorName")); if (methodConfig.isPageStreaming()) { + typeTable.saveNicknameFor(namer.getPageStreamingCallSettingsTypeName()); settings.type(ApiCallableType.PagedApiCallable); TypeRef resourceType = methodConfig.getPageStreaming().getResourcesField().getType(); - settings.resourceTypeName( - context.getTypeTable().getAndSaveNicknameForElementType(resourceType)); + settings.resourceTypeName(typeTable.getAndSaveNicknameForElementType(resourceType)); + settings.pageStreamingDescriptorName(namer.getPageStreamingDescriptorConstName(method)); } else { - settings.resourceTypeName( - context - .getNamer() - .getNotImplementedString( - "ApiCallableTransformer.generateApiCallableSettings - resourceTypeName")); if (methodConfig.isBundling()) { + typeTable.saveNicknameFor(namer.getBundlingCallSettingsTypeName()); settings.type(ApiCallableType.BundlingApiCallable); + settings.bundlingDescriptorName(namer.getBundlingDescriptorConstName(method)); + settings.bundlingConfig(generateBundlingConfig(context)); } else { settings.type(ApiCallableType.SimpleApiCallable); } } - settings.memberName(context.getNamer().getSettingsMemberName(method)); - settings.fnGetterName(context.getNamer().getSettingsMemberName(method)); + settings.memberName(namer.getSettingsMemberName(method)); + settings.fnGetterName(namer.getSettingsMemberName(method)); return Arrays.asList(settings.build()); } + + private BundlingConfigView generateBundlingConfig(MethodTransformerContext context) { + BundlingConfig bundlingConfig = context.getMethodConfig().getBundling(); + BundlingConfigView.Builder bundlingConfigView = BundlingConfigView.newBuilder(); + + bundlingConfigView.elementCountThreshold(bundlingConfig.getElementCountThreshold()); + bundlingConfigView.elementCountLimit(bundlingConfig.getElementCountLimit()); + bundlingConfigView.requestByteThreshold(bundlingConfig.getRequestByteThreshold()); + bundlingConfigView.requestByteLimit(bundlingConfig.getRequestByteLimit()); + bundlingConfigView.delayThresholdMillis(bundlingConfig.getDelayThresholdMillis()); + + return bundlingConfigView.build(); + } } diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index dd7c59dd93..950c51d4bb 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -182,6 +182,16 @@ public String getGrpcClientTypeName(Interface service) { return qualifiedName(namePath.withHead(className)); } + public String getGrpcContainerTypeName(Interface service) { + NamePath namePath = NamePath.dotted(service.getFullName()); + String className = className(Name.upperCamel(namePath.getHead(), "Grpc")); + return qualifiedName(namePath.withHead(className)); + } + + public String getGrpcMethodConstant(Method method) { + return inittedConstantName(Name.from("method").join(Name.upperCamel(method.getSimpleName()))); + } + public String getApiMethodName(Method method) { return methodName(Name.upperCamel(method.getSimpleName())); } @@ -271,4 +281,12 @@ public String getGetResourceListCallName(Field resourcesField) { public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef resourceType) { return getNotImplementedString("SurfaceNamer.getAndSavePagedResponseTypeName"); } + + public String getPageStreamingCallSettingsTypeName() { + return getNotImplementedString("SurfaceNamer.getPageStreamingCallSettingsTypeName"); + } + + public String getBundlingCallSettingsTypeName() { + return getNotImplementedString("SurfaceNamer.getBundlingCallSettingsTypeName"); + } } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index 17d27000cc..258705ed57 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -29,19 +29,26 @@ import com.google.api.codegen.transformer.PathTemplateTransformer; import com.google.api.codegen.transformer.SurfaceTransformerContext; import com.google.api.codegen.util.java.JavaTypeTable; +import com.google.api.codegen.viewmodel.RetryCodesDefinitionView; +import com.google.api.codegen.viewmodel.RetryParamsDefinitionView; import com.google.api.codegen.viewmodel.StaticApiMethodView; import com.google.api.codegen.viewmodel.StaticXApiView; import com.google.api.codegen.viewmodel.StaticXSettingsView; import com.google.api.codegen.viewmodel.ViewModel; +import com.google.api.gax.core.RetrySettings; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.Interface; import com.google.api.tools.framework.model.Method; import com.google.api.tools.framework.model.Model; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import io.grpc.Status.Code; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map.Entry; /** * The ModelToViewTransformer to transform a Model into the standard GAPIC surface in Java. @@ -141,6 +148,8 @@ private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) xsettingsClass.pageStreamingDescriptors( pageStreamingTransformer.generateDescriptorClasses(context)); xsettingsClass.bundlingDescriptors(bundlingTransformer.generateDescriptorClasses(context)); + xsettingsClass.retryCodesDefinitions(generateRetryCodesDefinitions(context)); + xsettingsClass.retryParamsDefinitions(generateRetryParamsDefinitions(context)); // must be done as the last step to catch all imports xsettingsClass.imports(context.getTypeTable().getImports()); @@ -214,4 +223,42 @@ private List generateApiMethods(SurfaceTransformerContext c return apiMethods; } + + private List generateRetryCodesDefinitions( + SurfaceTransformerContext context) { + List definitions = new ArrayList<>(); + + for (Entry> retryCodesDef : + context.getInterfaceConfig().getRetryCodesDefinition().entrySet()) { + definitions.add( + RetryCodesDefinitionView.newBuilder() + .key(retryCodesDef.getKey()) + .codes(retryCodesDef.getValue()) + .build()); + } + + return definitions; + } + + private List generateRetryParamsDefinitions( + SurfaceTransformerContext context) { + List definitions = new ArrayList<>(); + + for (Entry retryCodesDef : + context.getInterfaceConfig().getRetrySettingsDefinition().entrySet()) { + RetrySettings settings = retryCodesDef.getValue(); + RetryParamsDefinitionView.Builder params = RetryParamsDefinitionView.newBuilder(); + params.key(retryCodesDef.getKey()); + params.initialRetryDelay(settings.getInitialRetryDelay()); + params.retryDelayMultiplier(settings.getRetryDelayMultiplier()); + params.maxRetryDelay(settings.getMaxRetryDelay()); + params.initialRpcTimeout(settings.getInitialRpcTimeout()); + params.rpcTimeoutMultiplier(settings.getRpcTimeoutMultiplier()); + params.maxRpcTimeout(settings.getMaxRpcTimeout()); + params.totalTimeout(settings.getTotalTimeout()); + definitions.add(params.build()); + } + + return definitions; + } } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java index dbeace41a1..6fa97e7bc0 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java @@ -73,4 +73,14 @@ public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef return typeTable.getAndSaveNicknameForContainer( "com.google.api.gax.core.PageAccessor", resourceTypeName); } + + @Override + public String getPageStreamingCallSettingsTypeName() { + return "com.google.api.gax.grpc.PageStreamingCallSettings"; + } + + @Override + public String getBundlingCallSettingsTypeName() { + return "com.google.api.gax.grpc.BundlingCallSettings"; + } } diff --git a/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java index a4b330d814..258215cabe 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/ApiCallSettingsView.java @@ -14,9 +14,10 @@ */ package com.google.api.codegen.viewmodel; -import com.google.api.codegen.viewmodel.ApiCallableView.Builder; import com.google.auto.value.AutoValue; +import javax.annotation.Nullable; + @AutoValue public abstract class ApiCallSettingsView { public abstract ApiCallableType type(); @@ -33,6 +34,21 @@ public abstract class ApiCallSettingsView { public abstract String fnGetterName(); + public abstract String grpcTypeName(); + + public abstract String grpcMethodConstant(); + + public abstract String pageStreamingDescriptorName(); + + public abstract String bundlingDescriptorName(); + + public abstract String retryCodesName(); + + public abstract String retryParamsName(); + + @Nullable + public abstract BundlingConfigView bundlingConfig(); + public static Builder newBuilder() { return new AutoValue_ApiCallSettingsView.Builder(); } @@ -53,6 +69,20 @@ public static abstract class Builder { public abstract Builder fnGetterName(String val); + public abstract Builder grpcTypeName(String val); + + public abstract Builder grpcMethodConstant(String val); + + public abstract Builder pageStreamingDescriptorName(String val); + + public abstract Builder bundlingDescriptorName(String val); + + public abstract Builder bundlingConfig(BundlingConfigView val); + + public abstract Builder retryCodesName(String val); + + public abstract Builder retryParamsName(String val); + public abstract ApiCallSettingsView build(); } } diff --git a/src/main/java/com/google/api/codegen/viewmodel/BundlingConfigView.java b/src/main/java/com/google/api/codegen/viewmodel/BundlingConfigView.java new file mode 100644 index 0000000000..0221e0d5df --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/BundlingConfigView.java @@ -0,0 +1,49 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class BundlingConfigView { + public abstract int elementCountThreshold(); + + public abstract long requestByteThreshold(); + + public abstract int elementCountLimit(); + + public abstract long requestByteLimit(); + + public abstract long delayThresholdMillis(); + + public static Builder newBuilder() { + return new AutoValue_BundlingConfigView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder elementCountThreshold(int val); + + public abstract Builder requestByteThreshold(long val); + + public abstract Builder elementCountLimit(int val); + + public abstract Builder requestByteLimit(long val); + + public abstract Builder delayThresholdMillis(long val); + + public abstract BundlingConfigView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/RetryCodesDefinitionView.java b/src/main/java/com/google/api/codegen/viewmodel/RetryCodesDefinitionView.java new file mode 100644 index 0000000000..bfc9dbea30 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/RetryCodesDefinitionView.java @@ -0,0 +1,40 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableSet; + +import io.grpc.Status.Code; + +@AutoValue +public abstract class RetryCodesDefinitionView { + public abstract String key(); + + public abstract ImmutableSet codes(); + + public static Builder newBuilder() { + return new AutoValue_RetryCodesDefinitionView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder key(String val); + + public abstract Builder codes(ImmutableSet val); + + public abstract RetryCodesDefinitionView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/RetryParamsDefinitionView.java b/src/main/java/com/google/api/codegen/viewmodel/RetryParamsDefinitionView.java new file mode 100644 index 0000000000..93fd57b15a --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/RetryParamsDefinitionView.java @@ -0,0 +1,67 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.gax.core.RetrySettings.Builder; +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableSet; + +import io.grpc.Status.Code; + +import org.joda.time.Duration; + +@AutoValue +public abstract class RetryParamsDefinitionView { + public abstract String key(); + + public abstract Duration totalTimeout(); + + public abstract Duration initialRetryDelay(); + + public abstract double retryDelayMultiplier(); + + public abstract Duration maxRetryDelay(); + + public abstract Duration initialRpcTimeout(); + + public abstract double rpcTimeoutMultiplier(); + + public abstract Duration maxRpcTimeout(); + + public static Builder newBuilder() { + return new AutoValue_RetryParamsDefinitionView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder key(String val); + + public abstract Builder initialRetryDelay(Duration initialDelay); + + public abstract Builder retryDelayMultiplier(double multiplier); + + public abstract Builder maxRetryDelay(Duration maxDelay); + + public abstract Builder initialRpcTimeout(Duration initialTimeout); + + public abstract Builder rpcTimeoutMultiplier(double multiplier); + + public abstract Builder maxRpcTimeout(Duration maxTimeout); + + public abstract Builder totalTimeout(Duration totalTimeout); + + public abstract RetryParamsDefinitionView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java index c811a81c36..ba7196ab50 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java @@ -39,6 +39,10 @@ public abstract class StaticXSettingsView implements ViewModel { public abstract List bundlingDescriptors(); + public abstract List retryCodesDefinitions(); + + public abstract List retryParamsDefinitions(); + public abstract List imports(); public abstract String outputPath(); @@ -73,6 +77,10 @@ public abstract Builder pageStreamingDescriptors( public abstract Builder bundlingDescriptors(List val); + public abstract Builder retryCodesDefinitions(List val); + + public abstract Builder retryParamsDefinitions(List val); + public abstract Builder imports(List val); public abstract Builder outputPath(String val); diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index 664e668712..a15754faa7 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -11,7 +11,7 @@ {@members(xsettingsClass)} {@constructors(xsettingsClass)} {@descriptors(xsettingsClass)} - # {@innerBuilderClass(xsettingsClass)} + {@innerBuilderClass(xsettingsClass)} } @end @@ -256,13 +256,13 @@ public static class Builder extends ServiceApiSettings.Builder { private final ImmutableList methodSettingsBuilders; - # {@builderMembers(xsettingsClass)} + {@builderMembers(xsettingsClass)} - # {@builderConstants(xsettingsClass)} + {@builderConstants(xsettingsClass)} - # {@builderConstructors(xsettingsClass)} + {@builderConstructors(xsettingsClass)} - # {@builderMethods(xsettingsClass)} + {@builderMethods(xsettingsClass)} } @end @@ -270,36 +270,207 @@ @join settings : xsettingsClass.callSettings @switch settings.type.toString @case "SimpleApiCallable" - private SimpleCallSettings.Builder<{@desc.requestTypeName}, \ - {@desc.responseTypeName}> {@settings.memberName}; + private SimpleCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; @case "PagedApiCallable" - private PageStreamingCallSettings.Builder<{@desc.requestTypeName}, \ - {@desc.responseTypeName}, {@desc.resourceTypeName}> {@settings.memberName}; + private PageStreamingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.memberName}; @case "BundlingApiCallable" - private BundlingCallSettings.Builder<{@desc.requestTypeName}, \ - {@desc.responseTypeName}> {@settings.memberName}; + private BundlingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; @default $unhandledCase: {@settings.type.toString}$ @end @end - # old - @join method : service.getMethods - @if {@isPageStreaming} - @let pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - dummy = context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings") - private PageStreamingCallSettings.Builder<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> - {@methodName}Settings; - @end - @else - @if {@isBundling} - @let bundling = methodConfig.getBundling(), \ - dummy = context.addImport("com.google.api.gax.grpc.BundlingCallSettings") - private BundlingCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings; - @end - @else - private SimpleCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings; +@end + +@private builderConstants(xsettingsClass) + private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = ImmutableMap.builder(); + @join retryCodesDef : xsettingsClass.retryCodesDefinitions + definitions.put( + "{@retryCodesDef.key}", + Sets.immutableEnumSet(Lists.newArrayList({@statusCodes(retryCodesDef.codes)}))); + @end + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings.Builder settingsBuilder = null; + @join retryParamsDef : xsettingsClass.retryParamsDefinitions + settingsBuilder = RetrySettings.newBuilder() + .setInitialRetryDelay(Duration.millis({@retryParamsDef.initialRetryDelay.getMillis}L)) + .setRetryDelayMultiplier({@retryParamsDef.retryDelayMultiplier}) + .setMaxRetryDelay(Duration.millis({@retryParamsDef.maxRetryDelay.getMillis}L)) + .setInitialRpcTimeout(Duration.millis({@retryParamsDef.initialRpcTimeout.getMillis}L)) + .setRpcTimeoutMultiplier({@retryParamsDef.rpcTimeoutMultiplier}) + .setMaxRpcTimeout(Duration.millis({@retryParamsDef.maxRpcTimeout.getMillis}L)) + .setTotalTimeout(Duration.millis({@retryParamsDef.totalTimeout.getMillis}L)); + definitions.put("{@retryParamsDef.key}", settingsBuilder); + @end + RETRY_PARAM_DEFINITIONS = definitions.build(); + } +@end + +@private statusCodes(codes) + @join code : codes on ", " + Status.Code.{@code} + @end +@end + +@private builderConstructors(xsettingsClass) + private Builder() { + super(DEFAULT_CONNECTION_SETTINGS); + + @join settings : xsettingsClass.callSettings + @switch settings.type.toString + @case "SimpleApiCallable" + {@settings.memberName} = SimpleCallSettings.newBuilder({@settings.grpcTypeName}.{@settings.grpcMethodConstant}); + @case "PagedApiCallable" + {@settings.memberName} = PageStreamingCallSettings.newBuilder( + {@settings.grpcTypeName}.{@settings.grpcMethodConstant}, + {@settings.pageStreamingDescriptorName}); + @case "BundlingApiCallable" + {@settings.memberName} = BundlingCallSettings.newBuilder( + {@settings.grpcTypeName}.{@settings.grpcMethodConstant}, + {@settings.bundlingDescriptorName}) + .setBundlingSettingsBuilder(BundlingSettings.newBuilder()); + @default + $unhandledCase: {@settings.type.toString}$ + @end + {@BREAK} + @end + methodSettingsBuilders = ImmutableList.of( + @join settings : xsettingsClass.callSettings vertical on ",".add(BREAK) + {@settings.memberName} @end + ); + } + + private static Builder createDefault() { + Builder builder = new Builder(); + @join settings : xsettingsClass.callSettings + {@""} + @switch settings.type.toString + @case "SimpleApiCallable" + @case "PagedApiCallable" + @case "BundlingApiCallable" + builder.{@settings.fnGetterName}().getBundlingSettingsBuilder() + .setElementCountThreshold({@settings.bundlingConfig.elementCountThreshold}) + .setElementCountLimit({@settings.bundlingConfig.elementCountLimit}) + .setRequestByteThreshold({@settings.bundlingConfig.requestByteThreshold}) + .setRequestByteLimit({@settings.bundlingConfig.requestByteLimit}) + .setDelayThreshold(Duration.millis({@settings.bundlingConfig.delayThresholdMillis})) + .setBlockingCallCountThreshold(1); + @default + $unhandledCase: {@settings.type.toString}$ @end + builder.{@settings.fnGetterName}() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("{@settings.retryCodesName}")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("{@settings.retryParamsName}")); + @end + + return builder; + } + + private Builder({@xsettingsClass.name} settings) { + super(settings); + + @join settings : xsettingsClass.callSettings + {@settings.memberName} = settings.{@settings.memberName}.toBuilder(); + @end + + methodSettingsBuilders = ImmutableList.of( + @join settings : xsettingsClass.callSettings vertical on ",".add(BREAK) + {@settings.memberName} + @end + ); + } +@end + +@private builderMethods(xsettingsClass) + @@Override + protected ConnectionSettings getDefaultConnectionSettings() { + return DEFAULT_CONNECTION_SETTINGS; + } + @@Override + public Builder provideExecutorWith(ScheduledExecutorService executor, boolean shouldAutoClose) { + super.provideExecutorWith(executor, shouldAutoClose); + return this; + } + @@Override + public Builder provideChannelWith(ManagedChannel channel, boolean shouldAutoClose) { + super.provideChannelWith(channel, shouldAutoClose); + return this; + } + @@Override + public Builder provideChannelWith(ConnectionSettings settings) { + super.provideChannelWith(settings); + return this; + } + @@Override + public Builder provideChannelWith(Credentials credentials) { + super.provideChannelWith(credentials); + return this; + } + @@Override + public Builder provideChannelWith(List scopes) { + super.provideChannelWith(scopes); + return this; + } + @@Override + public Builder setGeneratorHeader(String name, String version) { + super.setGeneratorHeader(name, version); + return this; + } + @@Override + public Builder setClientLibHeader(String name, String version) { + super.setClientLibHeader(name, version); + return this; + } + + /** + * Applies the given settings to all of the API methods in this service. Only + * values that are non-null will be applied, so this method is not capable + * of un-setting any values. + */ + public Builder applyToAllApiMethods(ApiCallSettings.Builder apiCallSettings) throws Exception { + super.applyToAllApiMethods(methodSettingsBuilders, apiCallSettings); + return this; + } + + @join settings : xsettingsClass.callSettings + /** + * Returns the builder for the settings used for calls to {@settings.methodName}. + */ + @switch settings.type.toString + @case "SimpleApiCallable" + public SimpleCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "PagedApiCallable" + public PageStreamingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "BundlingApiCallable" + public BundlingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @default + $unhandledCase: {@settings.type.toString}$ + @end + {@""} @end + @@Override + public {@xsettingsClass.name} build() throws IOException { + return new {@xsettingsClass.name}(this); + } @end diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline index c438ce6d9e..85b61b598f 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -4,6 +4,8 @@ package com.google.gcloud.pubsub.spi; import com.google.api.gax.core.ConnectionSettings; import com.google.api.gax.core.RetrySettings; import com.google.api.gax.grpc.ApiCallSettings; +import com.google.api.gax.grpc.BundlingCallSettings; +import com.google.api.gax.grpc.PageStreamingCallSettings; import com.google.api.gax.grpc.ServiceApiSettings; import com.google.api.gax.grpc.SimpleCallSettings; import com.google.auth.Credentials; @@ -35,6 +37,7 @@ import com.google.example.library.v1.Shelf; import com.google.example.library.v1.UpdateBookIndexRequest; import com.google.example.library.v1.UpdateBookRequest; import com.google.protobuf.Empty; +import google.example.library.v1.LibraryServiceGrpc; import io.grpc.ManagedChannel; import io.grpc.Status; import java.io.IOException; @@ -380,4 +383,405 @@ public class LibraryServiceSettings extends ServiceApiSettings { } }; + /** + * Builder for LibraryServiceSettings. + */ + public static class Builder extends ServiceApiSettings.Builder { + private final ImmutableList methodSettingsBuilders; + + private SimpleCallSettings.Builder createShelfSettings; + private SimpleCallSettings.Builder getShelfSettings; + private PageStreamingCallSettings.Builder listShelvesSettings; + private SimpleCallSettings.Builder deleteShelfSettings; + private SimpleCallSettings.Builder mergeShelvesSettings; + private SimpleCallSettings.Builder createBookSettings; + private BundlingCallSettings.Builder publishSeriesSettings; + private SimpleCallSettings.Builder getBookSettings; + private PageStreamingCallSettings.Builder listBooksSettings; + private SimpleCallSettings.Builder deleteBookSettings; + private SimpleCallSettings.Builder updateBookSettings; + private SimpleCallSettings.Builder moveBookSettings; + private PageStreamingCallSettings.Builder listStringsSettings; + private SimpleCallSettings.Builder addCommentsSettings; + private SimpleCallSettings.Builder getBookFromArchiveSettings; + private SimpleCallSettings.Builder updateBookIndexSettings; + + private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = ImmutableMap.builder(); + definitions.put( + "idempotent", + Sets.immutableEnumSet(Lists.newArrayList(Status.Code.DEADLINE_EXCEEDED, Status.Code.UNAVAILABLE))); + definitions.put( + "non_idempotent", + Sets.immutableEnumSet(Lists.newArrayList())); + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings.Builder settingsBuilder = null; + settingsBuilder = RetrySettings.newBuilder() + .setInitialRetryDelay(Duration.millis(100L)) + .setRetryDelayMultiplier(1.2) + .setMaxRetryDelay(Duration.millis(1000L)) + .setInitialRpcTimeout(Duration.millis(300L)) + .setRpcTimeoutMultiplier(1.3) + .setMaxRpcTimeout(Duration.millis(3000L)) + .setTotalTimeout(Duration.millis(30000L)); + definitions.put("default", settingsBuilder); + RETRY_PARAM_DEFINITIONS = definitions.build(); + } + + private Builder() { + super(DEFAULT_CONNECTION_SETTINGS); + + createShelfSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_CREATE_SHELF); + + getShelfSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_GET_SHELF); + + listShelvesSettings = PageStreamingCallSettings.newBuilder( + LibraryServiceGrpc.METHOD_LIST_SHELVES, + LIST_SHELVES_PAGE_STR_DESC); + + deleteShelfSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_DELETE_SHELF); + + mergeShelvesSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_MERGE_SHELVES); + + createBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_CREATE_BOOK); + + publishSeriesSettings = BundlingCallSettings.newBuilder( + LibraryServiceGrpc.METHOD_PUBLISH_SERIES, + PUBLISH_SERIES_BUNDLING_DESC) + .setBundlingSettingsBuilder(BundlingSettings.newBuilder()); + + getBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_GET_BOOK); + + listBooksSettings = PageStreamingCallSettings.newBuilder( + LibraryServiceGrpc.METHOD_LIST_BOOKS, + LIST_BOOKS_PAGE_STR_DESC); + + deleteBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_DELETE_BOOK); + + updateBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_UPDATE_BOOK); + + moveBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_MOVE_BOOK); + + listStringsSettings = PageStreamingCallSettings.newBuilder( + LibraryServiceGrpc.METHOD_LIST_STRINGS, + LIST_STRINGS_PAGE_STR_DESC); + + addCommentsSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_ADD_COMMENTS); + + getBookFromArchiveSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_GET_BOOK_FROM_ARCHIVE); + + updateBookIndexSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_UPDATE_BOOK_INDEX); + + methodSettingsBuilders = ImmutableList.of( + createShelfSettings, + getShelfSettings, + listShelvesSettings, + deleteShelfSettings, + mergeShelvesSettings, + createBookSettings, + publishSeriesSettings, + getBookSettings, + listBooksSettings, + deleteBookSettings, + updateBookSettings, + moveBookSettings, + listStringsSettings, + addCommentsSettings, + getBookFromArchiveSettings, + updateBookIndexSettings + ); + } + + private static Builder createDefault() { + Builder builder = new Builder(); + + builder.createShelfSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.getShelfSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.listShelvesSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.deleteShelfSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.mergeShelvesSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.createBookSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.publishSeriesSettings().getBundlingSettingsBuilder() + .setElementCountThreshold(6) + .setElementCountLimit(7) + .setRequestByteThreshold(100000) + .setRequestByteLimit(150000) + .setDelayThreshold(Duration.millis(500)) + .setBlockingCallCountThreshold(1); + builder.publishSeriesSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.getBookSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.listBooksSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.deleteBookSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.updateBookSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.moveBookSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.listStringsSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.addCommentsSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.getBookFromArchiveSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + builder.updateBookIndexSettings() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); + + return builder; + } + + private Builder(LibraryServiceSettings settings) { + super(settings); + + createShelfSettings = settings.createShelfSettings.toBuilder(); + getShelfSettings = settings.getShelfSettings.toBuilder(); + listShelvesSettings = settings.listShelvesSettings.toBuilder(); + deleteShelfSettings = settings.deleteShelfSettings.toBuilder(); + mergeShelvesSettings = settings.mergeShelvesSettings.toBuilder(); + createBookSettings = settings.createBookSettings.toBuilder(); + publishSeriesSettings = settings.publishSeriesSettings.toBuilder(); + getBookSettings = settings.getBookSettings.toBuilder(); + listBooksSettings = settings.listBooksSettings.toBuilder(); + deleteBookSettings = settings.deleteBookSettings.toBuilder(); + updateBookSettings = settings.updateBookSettings.toBuilder(); + moveBookSettings = settings.moveBookSettings.toBuilder(); + listStringsSettings = settings.listStringsSettings.toBuilder(); + addCommentsSettings = settings.addCommentsSettings.toBuilder(); + getBookFromArchiveSettings = settings.getBookFromArchiveSettings.toBuilder(); + updateBookIndexSettings = settings.updateBookIndexSettings.toBuilder(); + + methodSettingsBuilders = ImmutableList.of( + createShelfSettings, + getShelfSettings, + listShelvesSettings, + deleteShelfSettings, + mergeShelvesSettings, + createBookSettings, + publishSeriesSettings, + getBookSettings, + listBooksSettings, + deleteBookSettings, + updateBookSettings, + moveBookSettings, + listStringsSettings, + addCommentsSettings, + getBookFromArchiveSettings, + updateBookIndexSettings + ); + } + + @Override + protected ConnectionSettings getDefaultConnectionSettings() { + return DEFAULT_CONNECTION_SETTINGS; + } + @Override + public Builder provideExecutorWith(ScheduledExecutorService executor, boolean shouldAutoClose) { + super.provideExecutorWith(executor, shouldAutoClose); + return this; + } + @Override + public Builder provideChannelWith(ManagedChannel channel, boolean shouldAutoClose) { + super.provideChannelWith(channel, shouldAutoClose); + return this; + } + @Override + public Builder provideChannelWith(ConnectionSettings settings) { + super.provideChannelWith(settings); + return this; + } + @Override + public Builder provideChannelWith(Credentials credentials) { + super.provideChannelWith(credentials); + return this; + } + @Override + public Builder provideChannelWith(List scopes) { + super.provideChannelWith(scopes); + return this; + } + @Override + public Builder setGeneratorHeader(String name, String version) { + super.setGeneratorHeader(name, version); + return this; + } + @Override + public Builder setClientLibHeader(String name, String version) { + super.setClientLibHeader(name, version); + return this; + } + + /** + * Applies the given settings to all of the API methods in this service. Only + * values that are non-null will be applied, so this method is not capable + * of un-setting any values. + */ + public Builder applyToAllApiMethods(ApiCallSettings.Builder apiCallSettings) throws Exception { + super.applyToAllApiMethods(methodSettingsBuilders, apiCallSettings); + return this; + } + + /** + * Returns the builder for the settings used for calls to createShelf. + */ + public SimpleCallSettings.Builder createShelfSettings() { + return createShelfSettings; + } + + /** + * Returns the builder for the settings used for calls to getShelf. + */ + public SimpleCallSettings.Builder getShelfSettings() { + return getShelfSettings; + } + + /** + * Returns the builder for the settings used for calls to listShelves. + */ + public PageStreamingCallSettings.Builder listShelvesSettings() { + return listShelvesSettings; + } + + /** + * Returns the builder for the settings used for calls to deleteShelf. + */ + public SimpleCallSettings.Builder deleteShelfSettings() { + return deleteShelfSettings; + } + + /** + * Returns the builder for the settings used for calls to mergeShelves. + */ + public SimpleCallSettings.Builder mergeShelvesSettings() { + return mergeShelvesSettings; + } + + /** + * Returns the builder for the settings used for calls to createBook. + */ + public SimpleCallSettings.Builder createBookSettings() { + return createBookSettings; + } + + /** + * Returns the builder for the settings used for calls to publishSeries. + */ + public BundlingCallSettings.Builder publishSeriesSettings() { + return publishSeriesSettings; + } + + /** + * Returns the builder for the settings used for calls to getBook. + */ + public SimpleCallSettings.Builder getBookSettings() { + return getBookSettings; + } + + /** + * Returns the builder for the settings used for calls to listBooks. + */ + public PageStreamingCallSettings.Builder listBooksSettings() { + return listBooksSettings; + } + + /** + * Returns the builder for the settings used for calls to deleteBook. + */ + public SimpleCallSettings.Builder deleteBookSettings() { + return deleteBookSettings; + } + + /** + * Returns the builder for the settings used for calls to updateBook. + */ + public SimpleCallSettings.Builder updateBookSettings() { + return updateBookSettings; + } + + /** + * Returns the builder for the settings used for calls to moveBook. + */ + public SimpleCallSettings.Builder moveBookSettings() { + return moveBookSettings; + } + + /** + * Returns the builder for the settings used for calls to listStrings. + */ + public PageStreamingCallSettings.Builder listStringsSettings() { + return listStringsSettings; + } + + /** + * Returns the builder for the settings used for calls to addComments. + */ + public SimpleCallSettings.Builder addCommentsSettings() { + return addCommentsSettings; + } + + /** + * Returns the builder for the settings used for calls to getBookFromArchive. + */ + public SimpleCallSettings.Builder getBookFromArchiveSettings() { + return getBookFromArchiveSettings; + } + + /** + * Returns the builder for the settings used for calls to updateBookIndex. + */ + public SimpleCallSettings.Builder updateBookIndexSettings() { + return updateBookIndexSettings; + } + + @Override + public LibraryServiceSettings build() throws IOException { + return new LibraryServiceSettings(this); + } + } } From 62b0c92dfd0ebc686bc402731f9663faff20a1dc Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Wed, 27 Jul 2016 10:52:51 -0700 Subject: [PATCH 17/26] Java surface: adding license --- .../api/codegen/transformer/ModelTypeTable.java | 1 + .../com/google/api/codegen/java/mvvm_common.snip | 15 +++++++++++++++ .../com/google/api/codegen/java/xapi.snip | 1 + .../com/google/api/codegen/java/xsettings.snip | 3 +++ .../testdata/java_surface_xapi_library.baseline | 13 +++++++++++++ .../java_surface_xsettings_library.baseline | 13 +++++++++++++ 6 files changed, 46 insertions(+) diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java index 0dabfb20d1..fcfa14f216 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java @@ -43,6 +43,7 @@ public String getFullNameFor(TypeRef type) { return typeFormatter.getFullNameFor(type); } + @Override public String getFullNameForElementType(TypeRef type) { return typeFormatter.getFullNameForElementType(type); } diff --git a/src/main/resources/com/google/api/codegen/java/mvvm_common.snip b/src/main/resources/com/google/api/codegen/java/mvvm_common.snip index 50127de622..6192801030 100644 --- a/src/main/resources/com/google/api/codegen/java/mvvm_common.snip +++ b/src/main/resources/com/google/api/codegen/java/mvvm_common.snip @@ -1,3 +1,18 @@ +@snippet license() + /* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +@end @snippet paramList(params) @join param : params on ", " diff --git a/src/main/resources/com/google/api/codegen/java/xapi.snip b/src/main/resources/com/google/api/codegen/java/xapi.snip index aef1e7aa0c..cc20c7eb3b 100644 --- a/src/main/resources/com/google/api/codegen/java/xapi.snip +++ b/src/main/resources/com/google/api/codegen/java/xapi.snip @@ -2,6 +2,7 @@ @extends "java/xapi_sample.snip" @snippet generate(xapiClass) + {@license()} package {@xapiClass.packageName}; @join import : xapiClass.imports diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip index a15754faa7..e41697d0af 100644 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ b/src/main/resources/com/google/api/codegen/java/xsettings.snip @@ -1,4 +1,7 @@ +@extends "java/mvvm_common.snip" + @snippet generate(xsettingsClass) + {@license()} package {@xsettingsClass.packageName}; @join import : xsettingsClass.imports diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline index a907bc5519..95faca52c6 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline @@ -1,4 +1,17 @@ ============== file: src/main/java/com/google/gcloud/pubsub/spi/LibraryServiceApi.java ============== +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gcloud.pubsub.spi; import com.google.api.gax.core.PageAccessor; diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline index 85b61b598f..a9156922c4 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline @@ -1,4 +1,17 @@ ============== file: src/main/java/com/google/gcloud/pubsub/spi/LibraryServiceSettings.java ============== +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ package com.google.gcloud.pubsub.spi; import com.google.api.gax.core.ConnectionSettings; From 5a15f5a2597f1d00ba2cf17bfb04ba48e307a901 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Wed, 27 Jul 2016 11:29:38 -0700 Subject: [PATCH 18/26] Java surface: generating service doc --- .../transformer/ServiceTransformer.java | 38 +++++++++++ .../api/codegen/transformer/SurfaceNamer.java | 4 ++ .../java/JavaGapicSurfaceTransformer.java | 19 +++++- .../php/PhpGapicSurfaceTransformer.java | 11 ++- .../api/codegen/viewmodel/ServiceDocView.java | 16 +++++ .../viewmodel/StaticApiMethodView.java | 2 +- .../api/codegen/viewmodel/StaticXApiView.java | 4 ++ .../com/google/api/codegen/java/xapi.snip | 68 +++++++++++++++++++ .../java_surface_xapi_library.baseline | 63 +++++++++++++++++ 9 files changed, 216 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/transformer/ServiceTransformer.java diff --git a/src/main/java/com/google/api/codegen/transformer/ServiceTransformer.java b/src/main/java/com/google/api/codegen/transformer/ServiceTransformer.java new file mode 100644 index 0000000000..a4ea7ba702 --- /dev/null +++ b/src/main/java/com/google/api/codegen/transformer/ServiceTransformer.java @@ -0,0 +1,38 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.transformer; + +import com.google.api.codegen.viewmodel.ApiMethodView; +import com.google.api.codegen.viewmodel.ServiceDocView; + +import java.util.List; + +public class ServiceTransformer { + + public ServiceDocView generateServiceDoc( + SurfaceTransformerContext context, ApiMethodView exampleApiMethod) { + SurfaceNamer namer = context.getNamer(); + ServiceDocView.Builder serviceDoc = ServiceDocView.newBuilder(); + List docLines = context.getNamer().getDocLines(context.getInterface()); + serviceDoc.firstLine(docLines.get(0)); + serviceDoc.remainingLines(docLines.subList(1, docLines.size())); + serviceDoc.exampleApiMethod(exampleApiMethod); + serviceDoc.apiVarName(namer.getApiWrapperVariableName(context.getInterface())); + serviceDoc.apiClassName(namer.getApiWrapperClassName(context.getInterface())); + serviceDoc.settingsVarName(namer.getApiSettingsVariableName(context.getInterface())); + serviceDoc.settingsClassName(namer.getApiSettingsClassName(context.getInterface())); + return serviceDoc.build(); + } +} diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 950c51d4bb..1328422e21 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -71,6 +71,10 @@ public String getApiSettingsClassName(Interface interfaze) { return className(Name.upperCamel(interfaze.getSimpleName(), "Settings")); } + public String getApiSettingsVariableName(Interface interfaze) { + return varName(Name.upperCamel(interfaze.getSimpleName(), "Settings")); + } + public String getVariableName(Name identifier, InitValueConfig initValueConfig) { if (initValueConfig == null || !initValueConfig.hasFormattingConfig()) { return varName(identifier); diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index 258705ed57..ec9949c14d 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -27,8 +27,11 @@ import com.google.api.codegen.transformer.ModelTypeTable; import com.google.api.codegen.transformer.PageStreamingTransformer; import com.google.api.codegen.transformer.PathTemplateTransformer; +import com.google.api.codegen.transformer.ServiceTransformer; import com.google.api.codegen.transformer.SurfaceTransformerContext; import com.google.api.codegen.util.java.JavaTypeTable; +import com.google.api.codegen.viewmodel.ApiMethodType; +import com.google.api.codegen.viewmodel.ApiMethodView; import com.google.api.codegen.viewmodel.RetryCodesDefinitionView; import com.google.api.codegen.viewmodel.RetryParamsDefinitionView; import com.google.api.codegen.viewmodel.StaticApiMethodView; @@ -55,6 +58,7 @@ */ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { private GapicCodePathMapper pathMapper; + private ServiceTransformer serviceTransformer; private PathTemplateTransformer pathTemplateTransformer; private ApiCallableTransformer apiCallableTransformer; private ApiMethodTransformer apiMethodTransformer; @@ -69,6 +73,7 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { */ public JavaGapicSurfaceTransformer(GapicCodePathMapper pathMapper) { this.pathMapper = pathMapper; + this.serviceTransformer = new ServiceTransformer(); this.pathTemplateTransformer = new PathTemplateTransformer(); this.apiCallableTransformer = new ApiCallableTransformer(); this.apiMethodTransformer = new ApiMethodTransformer(); @@ -109,7 +114,19 @@ public List transform(SurfaceTransformerContext context) { private StaticXApiView generateXApi(SurfaceTransformerContext context) { addXApiImports(context); + List methods = generateApiMethods(context); + StaticXApiView.Builder xapiClass = StaticXApiView.newBuilder(); + + ApiMethodView exampleApiMethod = null; + for (StaticApiMethodView method : methods) { + if (method.type().equals(ApiMethodType.FlattenedMethod)) { + exampleApiMethod = method; + break; + } + } + xapiClass.doc(serviceTransformer.generateServiceDoc(context, exampleApiMethod)); + xapiClass.templateFileName(XAPI_TEMPLATE_FILENAME); xapiClass.packageName(context.getApiConfig().getPackageName()); String name = context.getNamer().getApiWrapperClassName(context.getInterface()); @@ -121,7 +138,7 @@ private StaticXApiView generateXApi(SurfaceTransformerContext context) { pathTemplateTransformer.generateFormatResourceFunctions(context)); xapiClass.parseResourceFunctions( pathTemplateTransformer.generateParseResourceFunctions(context)); - xapiClass.apiMethods(generateApiMethods(context)); + xapiClass.apiMethods(methods); // must be done as the last step to catch all imports xapiClass.imports(context.getTypeTable().getImports()); diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java index d254f00aa3..c0dc30c110 100644 --- a/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpGapicSurfaceTransformer.java @@ -23,12 +23,12 @@ import com.google.api.codegen.transformer.ModelTypeTable; import com.google.api.codegen.transformer.PageStreamingTransformer; import com.google.api.codegen.transformer.PathTemplateTransformer; +import com.google.api.codegen.transformer.ServiceTransformer; import com.google.api.codegen.transformer.SurfaceNamer; import com.google.api.codegen.transformer.SurfaceTransformerContext; import com.google.api.codegen.util.php.PhpTypeTable; import com.google.api.codegen.viewmodel.ApiMethodView; import com.google.api.codegen.viewmodel.DynamicXApiView; -import com.google.api.codegen.viewmodel.ServiceDocView; import com.google.api.codegen.viewmodel.ViewModel; import com.google.api.tools.framework.model.Interface; import com.google.api.tools.framework.model.Method; @@ -43,6 +43,7 @@ */ public class PhpGapicSurfaceTransformer implements ModelToViewTransformer { private GapicCodePathMapper pathMapper; + private ServiceTransformer serviceTransformer; private PathTemplateTransformer pathTemplateTransformer; private PageStreamingTransformer pageStreamingTransformer; private ApiMethodTransformer apiMethodTransformer; @@ -54,6 +55,7 @@ public class PhpGapicSurfaceTransformer implements ModelToViewTransformer { */ public PhpGapicSurfaceTransformer(ApiConfig apiConfig, GapicCodePathMapper pathMapper) { this.pathMapper = pathMapper; + this.serviceTransformer = new ServiceTransformer(); this.pathTemplateTransformer = new PathTemplateTransformer(); this.pageStreamingTransformer = new PageStreamingTransformer(); this.apiMethodTransformer = new ApiMethodTransformer(); @@ -91,12 +93,7 @@ public List transform(SurfaceTransformerContext context) { DynamicXApiView.Builder xapiClass = DynamicXApiView.newBuilder(); - ServiceDocView.Builder serviceDoc = ServiceDocView.newBuilder(); - List docLines = context.getNamer().getDocLines(context.getInterface()); - serviceDoc.firstLine(docLines.get(0)); - serviceDoc.remainingLines(docLines.subList(1, docLines.size())); - serviceDoc.exampleApiMethod(methods.get(0)); - xapiClass.doc(serviceDoc.build()); + xapiClass.doc(serviceTransformer.generateServiceDoc(context, methods.get(0))); xapiClass.templateFileName(XAPI_TEMPLATE_FILENAME); xapiClass.protoFilename(context.getInterface().getFile().getSimpleName()); diff --git a/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java b/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java index 4a8660c79e..3c1a906718 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/ServiceDocView.java @@ -27,6 +27,14 @@ public abstract class ServiceDocView { public abstract ApiMethodView exampleApiMethod(); + public abstract String apiVarName(); + + public abstract String apiClassName(); + + public abstract String settingsVarName(); + + public abstract String settingsClassName(); + public static Builder newBuilder() { return new AutoValue_ServiceDocView.Builder(); } @@ -39,6 +47,14 @@ public static abstract class Builder { public abstract Builder exampleApiMethod(ApiMethodView val); + public abstract Builder apiVarName(String val); + + public abstract Builder apiClassName(String val); + + public abstract Builder settingsVarName(String val); + + public abstract Builder settingsClassName(String val); + public abstract ServiceDocView build(); } } diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java index 146de833f3..d60148cd68 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java @@ -26,7 +26,7 @@ * ApiMethodType enum. */ @AutoValue -public abstract class StaticApiMethodView { +public abstract class StaticApiMethodView implements ApiMethodView { public abstract ApiMethodType type(); public abstract String apiClassName(); diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java index 6303db79ea..daf74bf8a1 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java @@ -25,6 +25,8 @@ public abstract class StaticXApiView implements ViewModel { public abstract String packageName(); + public abstract ServiceDocView doc(); + public abstract String name(); public abstract String settingsClassName(); @@ -58,6 +60,8 @@ public static abstract class Builder { public abstract Builder packageName(String val); + public abstract Builder doc(ServiceDocView val); + public abstract Builder name(String val); public abstract Builder settingsClassName(String val); diff --git a/src/main/resources/com/google/api/codegen/java/xapi.snip b/src/main/resources/com/google/api/codegen/java/xapi.snip index cc20c7eb3b..34516f4dc4 100644 --- a/src/main/resources/com/google/api/codegen/java/xapi.snip +++ b/src/main/resources/com/google/api/codegen/java/xapi.snip @@ -9,6 +9,7 @@ import {@import}; @end + {@serviceDoc(xapiClass)} @@javax.annotation.Generated("by GAPIC") public class {@xapiClass.name} implements AutoCloseable { {@members(xapiClass)} @@ -20,6 +21,73 @@ } @end +@private serviceDoc(xapiClass) + @let coreSampleCode = syncMethodSampleCode(xapiClass.doc.exampleApiMethod), \ + decoratedSampleCode = decorateSampleCode(xapiClass.doc.exampleApiMethod, coreSampleCode) + {@renderServiceDoc(xapiClass.doc, decoratedSampleCode)} + @end +@end + +@private renderServiceDoc(xapiClassDoc, exampleMethodSampleCode) + // AUTO-GENERATED DOCUMENTATION AND SERVICE + /** + * Service Description: {@xapiClassDoc.firstLine} + @if xapiClassDoc.remainingLines + @join commentLine : xapiClassDoc.remainingLines + {@""} * {@commentLine} + @end + @end + * + *

This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

+   * 
+  @join sampleLine : util.getDocLines(exampleMethodSampleCode)
+    {@""} * {@sampleLine}
+  @end
+   * 
+   * 
+ * + *

Note: close() needs to be called on the {@xapiClassDoc.apiVarName} object to clean up resources such + * as threads. In the example above, try-with-resources is used, which automatically calls + * close(). + * + *

The surface of this class includes several types of Java methods for each of the API's methods: + * + *

    + *
  1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available + * as parameters, and not every API method will have a flattened method entry point. + *
  2. A "request object" method. This type of method only takes one parameter, a request + * object, which must be constructed before the call. Not every API method will have a request + * object method. + *
  3. A "callable" method. This type of method takes no parameters and returns an immutable + * ApiCallable object, which can be used to initiate calls to the service. + *
+ * + *

See the individual methods for example code. + * + *

Many parameters require resource names to be formatted in a particular way. To assist + * with these names, this class includes a format method for each type of name, and additionally + * a parse method to extract the individual identifiers contained within names that are + * returned. + * + *

This class can be customized by passing in a custom instance of {@xapiClassDoc.settingsClassName} to + * create(). For example: + * + *

+   * 
+   * {@xapiClassDoc.settingsClassName} {@xapiClassDoc.settingsVarName} = {@xapiClassDoc.settingsClassName}.defaultBuilder()
+   *     .provideChannelWith(myCredentials)
+   *     .build();
+   * {@xapiClassDoc.apiClassName} {@xapiClassDoc.apiVarName} = \
+       {@xapiClassDoc.apiClassName}.create({@xapiClassDoc.settingsVarName});
+   * 
+   * 
+ */ +@end + @private statics(xapiClass) @join pathTemplate : xapiClass.pathTemplates private static final PathTemplate {@pathTemplate.name} = diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline index 95faca52c6..b83727a11c 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline @@ -53,6 +53,69 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; +// AUTO-GENERATED DOCUMENTATION AND SERVICE +/** + * Service Description: This API represents a simple digital library. It lets you manage Shelf + * resources and Book resources in the library. It defines the following + * resource model: + * + * - The API has a collection of [Shelf][google.example.library.v1.Shelf] + * resources, named ``bookShelves/*`` + * + * - Each Shelf has a collection of [Book][google.example.library.v1.Book] + * resources, named `bookShelves/*/books/*` + * + * Check out [cloud docs!](/library/example/link). + * This is [not a cloud link](http://www.google.com). + * + *

This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

+ * 
+ * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+ *   Shelf shelf = Shelf.newBuilder().build();
+ *   Shelf response = libraryServiceApi.createShelf(shelf);
+ * }
+ * 
+ * 
+ * + *

Note: close() needs to be called on the libraryServiceApi object to clean up resources such + * as threads. In the example above, try-with-resources is used, which automatically calls + * close(). + * + *

The surface of this class includes several types of Java methods for each of the API's methods: + * + *

    + *
  1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available + * as parameters, and not every API method will have a flattened method entry point. + *
  2. A "request object" method. This type of method only takes one parameter, a request + * object, which must be constructed before the call. Not every API method will have a request + * object method. + *
  3. A "callable" method. This type of method takes no parameters and returns an immutable + * ApiCallable object, which can be used to initiate calls to the service. + *
+ * + *

See the individual methods for example code. + * + *

Many parameters require resource names to be formatted in a particular way. To assist + * with these names, this class includes a format method for each type of name, and additionally + * a parse method to extract the individual identifiers contained within names that are + * returned. + * + *

This class can be customized by passing in a custom instance of LibraryServiceSettings to + * create(). For example: + * + *

+ * 
+ * LibraryServiceSettings libraryServiceSettings = LibraryServiceSettings.defaultBuilder()
+ *     .provideChannelWith(myCredentials)
+ *     .build();
+ * LibraryServiceApi libraryServiceApi = LibraryServiceApi.create(libraryServiceSettings);
+ * 
+ * 
+ */ @javax.annotation.Generated("by GAPIC") public class LibraryServiceApi implements AutoCloseable { private final LibraryServiceSettings settings; From 376ae35da936698d262dce73dc262f5b5b530b8c Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Wed, 27 Jul 2016 18:21:55 -0700 Subject: [PATCH 19/26] Addressing PR comments --- .../api/codegen/csharp/CSharpContextCommon.java | 2 ++ .../codegen/gapic/ViewModelGapicProvider.java | 1 + .../api/codegen/java/JavaContextCommon.java | 3 ++- .../codegen/transformer/InitCodeTransformer.java | 16 ++++++++-------- .../php/PhpModelTypeNameConverter.java | 6 +----- .../api/codegen/util/CommonRenderingUtil.java | 1 + .../com/google/api/codegen/php/main.snip | 2 ++ .../codegen/testdata/php_main_library.baseline | 5 +++-- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/google/api/codegen/csharp/CSharpContextCommon.java b/src/main/java/com/google/api/codegen/csharp/CSharpContextCommon.java index ae59115d2a..ae5099d087 100644 --- a/src/main/java/com/google/api/codegen/csharp/CSharpContextCommon.java +++ b/src/main/java/com/google/api/codegen/csharp/CSharpContextCommon.java @@ -50,6 +50,7 @@ public String addImport(String namespace) { */ public Iterable getXmlDocLines(String text, String element) { // TODO(jonskeet): Convert markdown to XML documentation format. + // https://github.com/googleapis/toolkit/issues/331 List result = new ArrayList<>(); result.add("/// <" + element + ">"); for (String line : Splitter.on(String.format("%n")).split(text)) { @@ -65,6 +66,7 @@ public Iterable getXmlDocLines(String text, String element) { */ public Iterable getXmlParameterLines(String text, String parameterName) { // TODO(jonskeet): Convert markdown to XML documentation format. + // https://github.com/googleapis/toolkit/issues/331 List result = new ArrayList<>(); result.add("/// "); for (String line : Splitter.on(String.format("%n")).split(text)) { diff --git a/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java b/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java index 461feb669d..3e80395365 100644 --- a/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java +++ b/src/main/java/com/google/api/codegen/gapic/ViewModelGapicProvider.java @@ -74,6 +74,7 @@ public Map generate(String snippetFileName) { } Doc doc = snippetSetRunner.generate(surfaceDoc); if (doc == null) { + // generation failed; failures are captured in the model. continue; } docs.put(surfaceDoc.outputPath(), doc); diff --git a/src/main/java/com/google/api/codegen/java/JavaContextCommon.java b/src/main/java/com/google/api/codegen/java/JavaContextCommon.java index fe8de9c9de..34d05da145 100644 --- a/src/main/java/com/google/api/codegen/java/JavaContextCommon.java +++ b/src/main/java/com/google/api/codegen/java/JavaContextCommon.java @@ -128,7 +128,8 @@ public Iterable getJavaDocLines(String text) { * firstLinePrefix. Markdown will be translated to javadoc. */ public Iterable getJavaDocLinesWithPrefix(String text, String firstLinePrefix) { - // TODO(wgg): convert markdown to javadoc + // TODO: convert markdown to javadoc + // https://github.com/googleapis/toolkit/issues/331 List result = new ArrayList<>(); String linePrefix = firstLinePrefix; text = JAVADOC_ESCAPER.escape(text); diff --git a/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java b/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java index 2f113db9a7..16cdb8ce9a 100644 --- a/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/InitCodeTransformer.java @@ -76,7 +76,7 @@ public InitCodeView generateRequestObjectInitCode(MethodTransformerContext conte .build(); } - public Map createInitFieldStructure(MethodTransformerContext context) { + private Map createInitFieldStructure(MethodTransformerContext context) { Map fieldNamePatterns = context.getMethodConfig().getFieldNamePatterns(); ImmutableMap.Builder initValueConfigMap = ImmutableMap.builder(); @@ -94,7 +94,7 @@ public Map createInitFieldStructure(MethodTransformerContext con return initFieldStructure; } - public List generateSurfaceInitCodeLines( + private List generateSurfaceInitCodeLines( MethodTransformerContext context, InitCode initCode) { List surfaceLines = new ArrayList<>(); for (InitCodeLine line : initCode.getLines()) { @@ -118,7 +118,7 @@ public List generateSurfaceInitCodeLines( return surfaceLines; } - public StructureInitCodeLineView generateStructureInitCodeLine( + private StructureInitCodeLineView generateStructureInitCodeLine( MethodTransformerContext context, StructureInitCodeLine line) { StructureInitCodeLineView.Builder surfaceLine = StructureInitCodeLineView.newBuilder(); @@ -132,7 +132,7 @@ public StructureInitCodeLineView generateStructureInitCodeLine( return surfaceLine.build(); } - public ListInitCodeLineView generateListInitCodeLine( + private ListInitCodeLineView generateListInitCodeLine( MethodTransformerContext context, ListInitCodeLine line) { ListInitCodeLineView.Builder surfaceLine = ListInitCodeLineView.newBuilder(); @@ -150,7 +150,7 @@ public ListInitCodeLineView generateListInitCodeLine( return surfaceLine.build(); } - public SimpleInitCodeLineView generateSimpleInitCodeLine( + private SimpleInitCodeLineView generateSimpleInitCodeLine( MethodTransformerContext context, SimpleInitCodeLine line) { SimpleInitCodeLineView.Builder surfaceLine = SimpleInitCodeLineView.newBuilder(); @@ -163,7 +163,7 @@ public SimpleInitCodeLineView generateSimpleInitCodeLine( return surfaceLine.build(); } - public InitCodeLineView generateMapInitCodeLine( + private InitCodeLineView generateMapInitCodeLine( MethodTransformerContext context, MapInitCodeLine line) { MapInitCodeLineView.Builder surfaceLine = MapInitCodeLineView.newBuilder(); @@ -186,7 +186,7 @@ public InitCodeLineView generateMapInitCodeLine( return surfaceLine.build(); } - public InitValueView getInitValue( + private InitValueView getInitValue( MethodTransformerContext context, TypeRef type, InitValueConfig initValueConfig) { if (initValueConfig.hasFormattingConfig()) { FormattedInitValueView.Builder initValue = FormattedInitValueView.newBuilder(); @@ -215,7 +215,7 @@ public InitValueView getInitValue( } } - public List getFieldSettings( + private List getFieldSettings( MethodTransformerContext context, Iterable fieldSettings) { SurfaceNamer namer = context.getNamer(); List allSettings = new ArrayList<>(); diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java b/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java index 9cd87ec5af..89244d6262 100644 --- a/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpModelTypeNameConverter.java @@ -117,11 +117,7 @@ public TypeName getTypeNameForElementType(TypeRef type) { @Override public TypeName getTypeName(ProtoElement elem) { - // Construct the fully-qualified PHP class name - int fullNamePrefixLength = elem.getFile().getFullName().length() + 1; - String nickname = elem.getFullName().substring(fullNamePrefixLength); - String fullName = getPhpPackage(elem.getFile()) + "\\" + nickname; - return new TypeName(fullName, nickname); + return typeNameConverter.getTypeName(elem.getFullName().replaceAll("\\.", "\\\\")); } /** diff --git a/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java b/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java index 020635dc4e..7483010b9f 100644 --- a/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java +++ b/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java @@ -26,6 +26,7 @@ public class CommonRenderingUtil { public static List getDocLines(String text) { // TODO: convert markdown to phpDoc + // https://github.com/googleapis/toolkit/issues/331 List result = new ArrayList<>(); for (String line : Splitter.on(String.format("%n")).split(text)) { result.add(line); diff --git a/src/main/resources/com/google/api/codegen/php/main.snip b/src/main/resources/com/google/api/codegen/php/main.snip index 63be79957d..48f18f7130 100644 --- a/src/main/resources/com/google/api/codegen/php/main.snip +++ b/src/main/resources/com/google/api/codegen/php/main.snip @@ -278,6 +278,7 @@ } // TODO load the client config in a more package-friendly way + // https://github.com/googleapis/toolkit/issues/332 $clientConfigJsonString = file_get_contents('{@xapiClass.clientConfigPath}'); $clientConfig = json_decode($clientConfigJsonString, true); $this->defaultCallSettings = @@ -365,6 +366,7 @@ if (isset($optionalArgs['{@param.name}'])) { @if param.isMap // TODO make this work + // https://github.com/googleapis/toolkit/issues/333 putAll... @else @if param.isArray diff --git a/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline index 6dad061b1b..85ea70034d 100644 --- a/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline @@ -51,7 +51,7 @@ use google\example\library\v1\Shelf; use google\example\library\v1\SomeMessage; use google\example\library\v1\StringBuilder; use google\example\library\v1\UpdateBookIndexRequest; -use google\example\library\v1\UpdateBookIndexRequest.IndexMapEntry; +use google\example\library\v1\UpdateBookIndexRequest\IndexMapEntry; use google\example\library\v1\UpdateBookRequest; use google\protobuf\FieldMask; @@ -340,6 +340,7 @@ class LibraryServiceApi } // TODO load the client config in a more package-friendly way + // https://github.com/googleapis/toolkit/issues/332 $clientConfigJsonString = file_get_contents('./resources/library_service_client_config.json'); $clientConfig = json_decode($clientConfigJsonString, true); $this->defaultCallSettings = @@ -1249,7 +1250,7 @@ class LibraryServiceApi $request->setName($name); $request->setIndexName($indexName); foreach ($indexMap as $key => $value) { - $request->addIndexMap((new UpdateBookIndexRequest.IndexMapEntry())->setKey($key)->setValue($value)); + $request->addIndexMap((new IndexMapEntry())->setKey($key)->setValue($value)); } $mergedSettings = $this->defaultCallSettings['updateBookIndex']->merge( From f42e48c5e749927a5aaf45e28275bc25486dcddf Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Wed, 27 Jul 2016 17:21:07 -0700 Subject: [PATCH 20/26] Java surface: generating package-info --- .../java/JavaGapicSurfaceTransformer.java | 83 ++++++++++++++----- .../api/codegen/util/CommonRenderingUtil.java | 3 +- .../codegen/util/java/JavaRenderingUtil.java | 9 ++ .../codegen/viewmodel/PackageInfoView.java | 60 ++++++++++++++ .../api/codegen/viewmodel/StaticXApiView.java | 2 + .../api/codegen/java/xpackage-info.snip | 50 +++++++++++ ...ava_surface_xpackage-info_library.baseline | 50 +++++++++++ 7 files changed, 234 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/viewmodel/PackageInfoView.java create mode 100644 src/main/resources/com/google/api/codegen/java/xpackage-info.snip create mode 100644 src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index ec9949c14d..1f1a73be12 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -28,12 +28,15 @@ import com.google.api.codegen.transformer.PageStreamingTransformer; import com.google.api.codegen.transformer.PathTemplateTransformer; import com.google.api.codegen.transformer.ServiceTransformer; +import com.google.api.codegen.transformer.SurfaceNamer; import com.google.api.codegen.transformer.SurfaceTransformerContext; import com.google.api.codegen.util.java.JavaTypeTable; import com.google.api.codegen.viewmodel.ApiMethodType; import com.google.api.codegen.viewmodel.ApiMethodView; +import com.google.api.codegen.viewmodel.PackageInfoView; import com.google.api.codegen.viewmodel.RetryCodesDefinitionView; import com.google.api.codegen.viewmodel.RetryParamsDefinitionView; +import com.google.api.codegen.viewmodel.ServiceDocView; import com.google.api.codegen.viewmodel.StaticApiMethodView; import com.google.api.codegen.viewmodel.StaticXApiView; import com.google.api.codegen.viewmodel.StaticXSettingsView; @@ -67,6 +70,7 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { private static final String XAPI_TEMPLATE_FILENAME = "java/xapi.snip"; private static final String XSETTINGS_TEMPLATE_FILENAME = "java/xsettings.snip"; + private static final String PACKAGE_INFO_TEMPLATE_FILENAME = "java/xpackage-info.snip"; /** * Standard constructor. @@ -83,32 +87,38 @@ public JavaGapicSurfaceTransformer(GapicCodePathMapper pathMapper) { @Override public List getTemplateFileNames() { - return Arrays.asList(XAPI_TEMPLATE_FILENAME, XSETTINGS_TEMPLATE_FILENAME); + return Arrays.asList( + XAPI_TEMPLATE_FILENAME, XSETTINGS_TEMPLATE_FILENAME, PACKAGE_INFO_TEMPLATE_FILENAME); } @Override public List transform(Model model, ApiConfig apiConfig) { List surfaceDocs = new ArrayList<>(); + SurfaceNamer namer = new JavaSurfaceNamer(); + + List serviceDocs = new ArrayList<>(); for (Interface service : new InterfaceView().getElementIterable(model)) { - ModelTypeTable modelTypeTable = - new ModelTypeTable(new JavaTypeTable(), new JavaModelTypeNameConverter()); SurfaceTransformerContext context = - SurfaceTransformerContext.create( - service, apiConfig, modelTypeTable, new JavaSurfaceNamer()); - surfaceDocs.addAll(transform(context)); - } - return surfaceDocs; - } + SurfaceTransformerContext.create(service, apiConfig, createTypeTable(), namer); + StaticXApiView xapi = generateXApi(context); + surfaceDocs.add(xapi); - public List transform(SurfaceTransformerContext context) { - List surfaceData = new ArrayList<>(); + serviceDocs.add(xapi.doc()); - surfaceData.add(generateXApi(context)); + context = SurfaceTransformerContext.create(service, apiConfig, createTypeTable(), namer); + StaticXSettingsView xsettings = generateXSettings(context); + surfaceDocs.add(xsettings); + } + + PackageInfoView packageInfo = + generatePackageInfo(model, apiConfig, createTypeTable(), namer, serviceDocs); + surfaceDocs.add(packageInfo); - context = context.withNewTypeTable(); - surfaceData.add(generateXSettings(context)); + return surfaceDocs; + } - return surfaceData; + private ModelTypeTable createTypeTable() { + return new ModelTypeTable(new JavaTypeTable(), new JavaModelTypeNameConverter()); } private StaticXApiView generateXApi(SurfaceTransformerContext context) { @@ -118,13 +128,7 @@ private StaticXApiView generateXApi(SurfaceTransformerContext context) { StaticXApiView.Builder xapiClass = StaticXApiView.newBuilder(); - ApiMethodView exampleApiMethod = null; - for (StaticApiMethodView method : methods) { - if (method.type().equals(ApiMethodType.FlattenedMethod)) { - exampleApiMethod = method; - break; - } - } + ApiMethodView exampleApiMethod = getExampleApiMethod(methods); xapiClass.doc(serviceTransformer.generateServiceDoc(context, exampleApiMethod)); xapiClass.templateFileName(XAPI_TEMPLATE_FILENAME); @@ -149,6 +153,20 @@ private StaticXApiView generateXApi(SurfaceTransformerContext context) { return xapiClass.build(); } + private ApiMethodView getExampleApiMethod(List methods) { + ApiMethodView exampleApiMethod = null; + for (StaticApiMethodView method : methods) { + if (method.type().equals(ApiMethodType.FlattenedMethod)) { + exampleApiMethod = method; + break; + } + } + if (exampleApiMethod == null) { + throw new RuntimeException("Could not find flattened method to use as an example method"); + } + return exampleApiMethod; + } + private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) { addXSettingsImports(context); @@ -177,6 +195,27 @@ private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) return xsettingsClass.build(); } + private PackageInfoView generatePackageInfo( + Model model, + ApiConfig apiConfig, + ModelTypeTable createTypeTable, + SurfaceNamer namer, + List serviceDocs) { + PackageInfoView.Builder packageInfo = PackageInfoView.newBuilder(); + + packageInfo.templateFileName(PACKAGE_INFO_TEMPLATE_FILENAME); + + packageInfo.serviceTitle(model.getServiceConfig().getTitle()); + packageInfo.serviceDocs(serviceDocs); + packageInfo.packageName(apiConfig.getPackageName()); + + Interface firstInterface = new InterfaceView().getElementIterable(model).iterator().next(); + String outputPath = pathMapper.getOutputPath(firstInterface, apiConfig); + packageInfo.outputPath(outputPath + "/package-info.java"); + + return packageInfo.build(); + } + private void addXApiImports(SurfaceTransformerContext context) { ModelTypeTable typeTable = context.getTypeTable(); typeTable.saveNicknameFor("com.google.api.gax.grpc.ApiCallable"); diff --git a/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java b/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java index 020635dc4e..1971b7c7a7 100644 --- a/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java +++ b/src/main/java/com/google/api/codegen/util/CommonRenderingUtil.java @@ -25,7 +25,8 @@ public class CommonRenderingUtil { public static List getDocLines(String text) { - // TODO: convert markdown to phpDoc + // TODO: convert markdown to language-specific doc format + // https://github.com/googleapis/toolkit/issues/331 List result = new ArrayList<>(); for (String line : Splitter.on(String.format("%n")).split(text)) { result.add(line); diff --git a/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java b/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java index ce3a1c0899..36a719be9c 100644 --- a/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java +++ b/src/main/java/com/google/api/codegen/util/java/JavaRenderingUtil.java @@ -19,6 +19,7 @@ import com.google.common.escape.Escapers; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -42,6 +43,7 @@ public class JavaRenderingUtil { */ public static List getDocLines(String text) { // TODO: convert markdown to javadoc + // https://github.com/googleapis/toolkit/issues/331 List result = new ArrayList<>(); text = JAVADOC_ESCAPER.escape(text); for (String line : Splitter.on(String.format("%n")).split(text)) { @@ -49,4 +51,11 @@ public static List getDocLines(String text) { } return result; } + + public List getMultilineHeading(String heading) { + final char[] array = new char[heading.length()]; + Arrays.fill(array, '='); + String eqsString = new String(array); + return Arrays.asList(eqsString, heading, eqsString); + } } diff --git a/src/main/java/com/google/api/codegen/viewmodel/PackageInfoView.java b/src/main/java/com/google/api/codegen/viewmodel/PackageInfoView.java new file mode 100644 index 0000000000..59d2fefcda --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/PackageInfoView.java @@ -0,0 +1,60 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.api.codegen.SnippetSetRunner; +import com.google.api.codegen.viewmodel.StaticXApiView.Builder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +public abstract class PackageInfoView implements ViewModel { + @Override + public abstract String templateFileName(); + + @Override + public abstract String outputPath(); + + public abstract String serviceTitle(); + + public abstract List serviceDocs(); + + public abstract String packageName(); + + @Override + public String resourceRoot() { + return SnippetSetRunner.SNIPPET_RESOURCE_ROOT; + } + + public static Builder newBuilder() { + return new AutoValue_PackageInfoView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder templateFileName(String val); + + public abstract Builder outputPath(String val); + + public abstract Builder serviceTitle(String val); + + public abstract Builder serviceDocs(List val); + + public abstract Builder packageName(String val); + + public abstract PackageInfoView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java index daf74bf8a1..095d278fc2 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXApiView.java @@ -21,6 +21,7 @@ @AutoValue public abstract class StaticXApiView implements ViewModel { + @Override public abstract String templateFileName(); public abstract String packageName(); @@ -43,6 +44,7 @@ public abstract class StaticXApiView implements ViewModel { public abstract List imports(); + @Override public abstract String outputPath(); @Override diff --git a/src/main/resources/com/google/api/codegen/java/xpackage-info.snip b/src/main/resources/com/google/api/codegen/java/xpackage-info.snip new file mode 100644 index 0000000000..5e756dfe12 --- /dev/null +++ b/src/main/resources/com/google/api/codegen/java/xpackage-info.snip @@ -0,0 +1,50 @@ +@extends "java/mvvm_common.snip" +@extends "java/xapi_sample.snip" + +@snippet generate(packageInfo) + {@license()} + + /** + * A client to {@packageInfo.serviceTitle}. + * + * The interfaces provided are listed below, along with a usage sample + * + @join xapiClassDoc : packageInfo.serviceDocs + {@serviceShortDoc(xapiClassDoc)} + @end + */ + + package {@packageInfo.packageName}; +@end + +@private serviceShortDoc(xapiClassDoc) + @let coreSampleCode = syncMethodSampleCode(xapiClassDoc.exampleApiMethod), \ + decoratedSampleCode = decorateSampleCode(xapiClassDoc.exampleApiMethod, coreSampleCode) + {@renderServiceShortDoc(xapiClassDoc, decoratedSampleCode)} + @end +@end + +@private renderServiceShortDoc(xapiClassDoc, exampleMethodSampleCode) + @join commentLine : util.getMultilineHeading(xapiClassDoc.apiClassName) + {@""} * {@commentLine} + @end + # The join above doesn't properly add a newline on the end, so we need to force it + {@""} + {@""} * + * Service Description: {@xapiClassDoc.firstLine} + @if xapiClassDoc.remainingLines + @join commentLine : xapiClassDoc.remainingLines + {@""} * {@commentLine} + @end + @end + * + * Sample for {@xapiClassDoc.apiClassName}: + *
+   * 
+  @join sampleLine : util.getDocLines(exampleMethodSampleCode)
+    {@""} * {@sampleLine}
+  @end
+   * 
+   * 
+ * +@end diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline new file mode 100644 index 0000000000..9543ce0c55 --- /dev/null +++ b/src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline @@ -0,0 +1,50 @@ +============== file: src/main/java/com/google/gcloud/pubsub/spi/package-info.java ============== +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * A client to Google Example Library API. + * + * The interfaces provided are listed below, along with a usage sample + * + * ================= + * LibraryServiceApi + * ================= + * + * Service Description: This API represents a simple digital library. It lets you manage Shelf + * resources and Book resources in the library. It defines the following + * resource model: + * + * - The API has a collection of [Shelf][google.example.library.v1.Shelf] + * resources, named ``bookShelves/*`` + * + * - Each Shelf has a collection of [Book][google.example.library.v1.Book] + * resources, named `bookShelves/*/books/*` + * + * Check out [cloud docs!](/library/example/link). + * This is [not a cloud link](http://www.google.com). + * + * Sample for LibraryServiceApi: + *
+ * 
+ * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
+ *   Shelf shelf = Shelf.newBuilder().build();
+ *   Shelf response = libraryServiceApi.createShelf(shelf);
+ * }
+ * 
+ * 
+ * + */ + +package com.google.gcloud.pubsub.spi; From 60005b28ed14155789d762c0090bcb822b8bb34b Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Thu, 28 Jul 2016 12:08:21 -0700 Subject: [PATCH 21/26] blank line fixes --- src/main/resources/com/google/api/codegen/php/main.snip | 5 +++-- .../google/api/codegen/testdata/php_main_library.baseline | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/resources/com/google/api/codegen/php/main.snip b/src/main/resources/com/google/api/codegen/php/main.snip index 48f18f7130..304f960b79 100644 --- a/src/main/resources/com/google/api/codegen/php/main.snip +++ b/src/main/resources/com/google/api/codegen/php/main.snip @@ -129,7 +129,6 @@ @join function : xapiClass.pathTemplateGetterFunctions {@pathTemplateGetterFunction(function)} @end - {@""} {@pageStreamingDescriptorFunction(xapiClass)} @end @@ -439,7 +438,9 @@ @if doc.arrayKeyDocs @join simpleParamDoc : doc.arrayKeyDocs {@""} * @@var {@simpleParamDoc.typeName} ${@simpleParamDoc.paramName} - * {@simpleParamDoc.firstLine} + @if simpleParamDoc.firstLine + {@""} * {@simpleParamDoc.firstLine} + @end @if simpleParamDoc.remainingLines @join commentLine : simpleParamDoc.remainingLines {@""} * {@commentLine} diff --git a/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline index 85ea70034d..964d736901 100644 --- a/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/php_main_library.baseline @@ -228,7 +228,6 @@ class LibraryServiceApi return self::$archivedBookNameTemplate; } - private static function getPageStreamingDescriptors() { $listShelvesPageStreamingDescriptor = @@ -442,7 +441,6 @@ class LibraryServiceApi * @var SomeMessage $message * Field to verify that message-type query parameter gets flattened. * @var StringBuilder $stringBuilder - * * } * @param array $callSettings { * Optional. @@ -1055,7 +1053,6 @@ class LibraryServiceApi * @param array $optionalArgs { * Optional. * @var string $name - * * @var int $pageSize * The maximum number of resources contained in the underlying API * response. If page streaming is performed per-resource, this From 68c5b2e61aaf2e4ddb2ff7645b0815d42f213245 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Thu, 28 Jul 2016 12:40:05 -0700 Subject: [PATCH 22/26] Renaming to NameFormatterDelegator --- .../google/api/codegen/transformer/SurfaceNamer.java | 4 ++-- ...ormatterMixin.java => NameFormatterDelegator.java} | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) rename src/main/java/com/google/api/codegen/util/{NameFormatterMixin.java => NameFormatterDelegator.java} (81%) diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index bd42d2b269..f225b1e044 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -20,7 +20,7 @@ import com.google.api.codegen.util.CommonRenderingUtil; import com.google.api.codegen.util.Name; import com.google.api.codegen.util.NameFormatter; -import com.google.api.codegen.util.NameFormatterMixin; +import com.google.api.codegen.util.NameFormatterDelegator; import com.google.api.codegen.util.NamePath; import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; import com.google.api.tools.framework.model.Field; @@ -42,7 +42,7 @@ * This class delegates step 2 to the provided name formatter, which generally * would be a language-specific namer. */ -public class SurfaceNamer extends NameFormatterMixin { +public class SurfaceNamer extends NameFormatterDelegator { private ModelTypeFormatter modelTypeFormatter; public SurfaceNamer(NameFormatter languageNamer, ModelTypeFormatter modelTypeFormatter) { diff --git a/src/main/java/com/google/api/codegen/util/NameFormatterMixin.java b/src/main/java/com/google/api/codegen/util/NameFormatterDelegator.java similarity index 81% rename from src/main/java/com/google/api/codegen/util/NameFormatterMixin.java rename to src/main/java/com/google/api/codegen/util/NameFormatterDelegator.java index 0c000afadd..40c1cfb12f 100644 --- a/src/main/java/com/google/api/codegen/util/NameFormatterMixin.java +++ b/src/main/java/com/google/api/codegen/util/NameFormatterDelegator.java @@ -15,19 +15,20 @@ package com.google.api.codegen.util; /** - * NameFormatterMixin is an abstract class that implements NameFormatter and - * simply forwards calls to another NameFormatter. This allows a child class - * to provide the interface of NameFormatter along with additional functionality. + * NameFormatterDelegator is an abstract class that implements the NameFormatter + * interface and simply delegates calls to another NameFormatter. This allows a + * child class to provide the interface of NameFormatter along with additional + * functionality. * * Note to future maintainers: This class should only contain methods which * forward on to NameFormatter and nothing else; otherwise, it is no longer * functioning in spirit as a mix-in. */ -public abstract class NameFormatterMixin implements NameFormatter { +public abstract class NameFormatterDelegator implements NameFormatter { private NameFormatter formatter; - public NameFormatterMixin(NameFormatter formatter) { + public NameFormatterDelegator(NameFormatter formatter) { this.formatter = formatter; } From c9c9608cb2c01ad49b1d0c534a01f026c1aeb272 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Fri, 29 Jul 2016 10:27:48 -0700 Subject: [PATCH 23/26] Replacing primary Java generation with MVVM, fixing differences --- .../gapic/MainGapicProviderFactory.java | 32 - .../transformer/ApiCallableTransformer.java | 4 +- .../transformer/ApiMethodTransformer.java | 1 + .../transformer/BundlingTransformer.java | 2 + .../transformer/ModelTypeFormatter.java | 6 + .../transformer/ModelTypeFormatterImpl.java | 6 + .../codegen/transformer/ModelTypeTable.java | 6 + .../transformer/PageStreamingTransformer.java | 1 + .../api/codegen/transformer/SurfaceNamer.java | 27 +- .../java/JavaGapicSurfaceTransformer.java | 34 +- .../transformer/java/JavaSurfaceNamer.java | 34 +- .../codegen/viewmodel/SettingsDocView.java | 61 + .../viewmodel/StaticApiMethodView.java | 4 + .../viewmodel/StaticXSettingsView.java | 4 + .../com/google/api/codegen/java/common.snip | 116 +- .../com/google/api/codegen/java/main.snip | 773 +++----- .../api/codegen/java/method_sample.snip | 234 +-- .../google/api/codegen/java/mvvm_common.snip | 27 - .../google/api/codegen/java/package-info.snip | 80 +- .../com/google/api/codegen/java/settings.snip | 901 ++++----- .../com/google/api/codegen/java/xapi.snip | 410 ---- .../google/api/codegen/java/xapi_sample.snip | 131 -- .../api/codegen/java/xpackage-info.snip | 50 - .../google/api/codegen/java/xsettings.snip | 479 ----- .../codegen/JavaSurfaceCodeGeneratorTest.java | 57 - .../testdata/java_main_library.baseline | 142 +- .../testdata/java_settings_library.baseline | 88 +- .../java_surface_xapi_library.baseline | 1656 ----------------- ...ava_surface_xpackage-info_library.baseline | 50 - .../java_surface_xsettings_library.baseline | 800 -------- 30 files changed, 1036 insertions(+), 5180 deletions(-) create mode 100644 src/main/java/com/google/api/codegen/viewmodel/SettingsDocView.java delete mode 100644 src/main/resources/com/google/api/codegen/java/mvvm_common.snip delete mode 100644 src/main/resources/com/google/api/codegen/java/xapi.snip delete mode 100644 src/main/resources/com/google/api/codegen/java/xapi_sample.snip delete mode 100644 src/main/resources/com/google/api/codegen/java/xpackage-info.snip delete mode 100644 src/main/resources/com/google/api/codegen/java/xsettings.snip delete mode 100644 src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java delete mode 100644 src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline delete mode 100644 src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline delete mode 100644 src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline diff --git a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java index 01d66701fc..876e3682e1 100644 --- a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java +++ b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java @@ -66,8 +66,6 @@ public class MainGapicProviderFactory public static final String PYTHON = "python"; public static final String RUBY = "ruby"; - public static final String JAVA_SURFACE = "java_surface"; - /** * Create the GapicProviders based on the given id */ @@ -118,36 +116,6 @@ public static List> defaultCreate( return Arrays.>asList(provider); } else if (id.equals(JAVA)) { - GapicCodePathMapper javaPathMapper = - CommonGapicCodePathMapper.newBuilder() - .setPrefix("src/main/java") - .setShouldAppendPackage(true) - .build(); - GapicProvider mainProvider = - CommonGapicProvider.newBuilder() - .setModel(model) - .setView(new InterfaceView()) - .setContext(new JavaGapicContext(model, apiConfig)) - .setSnippetSetRunner( - new JavaSnippetSetRunner(SnippetSetRunner.SNIPPET_RESOURCE_ROOT)) - .setSnippetFileNames(Arrays.asList("java/main.snip", "java/settings.snip")) - .setCodePathMapper(javaPathMapper) - .build(); - GapicProvider packageInfoProvider = - CommonGapicProvider.>newBuilder() - .setModel(model) - .setView(new InterfaceListView()) - .setContext(new JavaGapicContext(model, apiConfig)) - .setSnippetSetRunner( - new JavaIterableSnippetSetRunner( - SnippetSetRunner.SNIPPET_RESOURCE_ROOT)) - .setSnippetFileNames(Arrays.asList("java/package-info.snip")) - .setCodePathMapper(javaPathMapper) - .build(); - - return Arrays.>asList(mainProvider, packageInfoProvider); - - } else if (id.equals(JAVA_SURFACE)) { GapicCodePathMapper javaPathMapper = CommonGapicCodePathMapper.newBuilder() .setPrefix("src/main/java") diff --git a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java index 476c1e3614..32731a6444 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiCallableTransformer.java @@ -122,14 +122,14 @@ private List generateApiCallableSettings(MethodTransformerC namer.getNotImplementedString(notImplementedPrefix + "bundlingDescriptorName")); if (methodConfig.isPageStreaming()) { - typeTable.saveNicknameFor(namer.getPageStreamingCallSettingsTypeName()); + namer.addPageStreamingCallSettingsImports(typeTable); settings.type(ApiCallableType.PagedApiCallable); TypeRef resourceType = methodConfig.getPageStreaming().getResourcesField().getType(); settings.resourceTypeName(typeTable.getAndSaveNicknameForElementType(resourceType)); settings.pageStreamingDescriptorName(namer.getPageStreamingDescriptorConstName(method)); } else { if (methodConfig.isBundling()) { - typeTable.saveNicknameFor(namer.getBundlingCallSettingsTypeName()); + namer.addBundlingCallSettingsImports(typeTable); settings.type(ApiCallableType.BundlingApiCallable); settings.bundlingDescriptorName(namer.getBundlingDescriptorConstName(method)); settings.bundlingConfig(generateBundlingConfig(context)); diff --git a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java index 2cc10e32f9..d998d65248 100644 --- a/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/ApiMethodTransformer.java @@ -163,6 +163,7 @@ public void setCommonFields( context.getTypeTable().getAndSaveNicknameFor(context.getMethod().getInputType())); methodViewBuilder.apiClassName(namer.getApiWrapperClassName(context.getInterface())); methodViewBuilder.apiVariableName(namer.getApiWrapperVariableName(context.getInterface())); + methodViewBuilder.settingsGetterName(namer.getSettingsFunctionName(context.getMethod())); } private void setListMethodFields( diff --git a/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java b/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java index fb2b17f7b7..15a40f0364 100644 --- a/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/BundlingTransformer.java @@ -67,6 +67,8 @@ private BundlingDescriptorClassView generateDescriptorClass(MethodTransformerCon desc.fnGetSubresponseByIndex(namer.getGetByIndexCallName(bundling.getSubresponseField())); desc.fnSetSubresponse(namer.getSetFunctionCallName(bundling.getSubresponseField())); + namer.addBundlingDescriptorImports(typeTable); + return desc.build(); } diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java index a05c68cd31..a73fc09af5 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatter.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.transformer; +import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.TypeRef; /** @@ -29,6 +30,11 @@ public interface ModelTypeFormatter { */ String getFullNameFor(TypeRef type); + /** + * Get the full name for the given proto element. + */ + String getFullNameFor(ProtoElement element); + /** * Get the full name for the element type of the given type. */ diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java index 9e0dad107e..0a82f76025 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeFormatterImpl.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.transformer; +import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.TypeRef; /** @@ -34,6 +35,11 @@ public String getFullNameFor(TypeRef type) { return typeNameConverter.getTypeName(type).getFullName(); } + @Override + public String getFullNameFor(ProtoElement element) { + return typeNameConverter.getTypeName(element).getFullName(); + } + @Override public String getFullNameForElementType(TypeRef type) { return typeNameConverter.getTypeNameForElementType(type).getFullName(); diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java index fcfa14f216..d42a70bfcd 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java @@ -16,6 +16,7 @@ import com.google.api.codegen.util.TypeName; import com.google.api.codegen.util.TypeTable; +import com.google.api.tools.framework.model.ProtoElement; import com.google.api.tools.framework.model.TypeRef; import java.util.List; @@ -43,6 +44,11 @@ public String getFullNameFor(TypeRef type) { return typeFormatter.getFullNameFor(type); } + @Override + public String getFullNameFor(ProtoElement element) { + return typeFormatter.getFullNameFor(element); + } + @Override public String getFullNameForElementType(TypeRef type) { return typeFormatter.getFullNameForElementType(type); diff --git a/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java b/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java index 6d4c4b2d6d..a3a6c1033b 100644 --- a/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/PageStreamingTransformer.java @@ -58,6 +58,7 @@ public List generateDescriptorClasses( SurfaceTransformerContext context) { List descriptors = new ArrayList<>(); + context.getNamer().addPageStreamingDescriptorImports(context.getTypeTable()); for (Method method : context.getInterface().getMethods()) { MethodConfig methodConfig = context.getMethodConfig(method); if (!methodConfig.isPageStreaming()) { diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 1328422e21..f4037b933a 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -75,6 +75,10 @@ public String getApiSettingsVariableName(Interface interfaze) { return varName(Name.upperCamel(interfaze.getSimpleName(), "Settings")); } + public String getApiSettingsBuilderVarName(Interface interfaze) { + return varName(Name.upperCamel(interfaze.getSimpleName(), "SettingsBuilder")); + } + public String getVariableName(Name identifier, InitValueConfig initValueConfig) { if (initValueConfig == null || !initValueConfig.hasFormattingConfig()) { return varName(identifier); @@ -172,6 +176,18 @@ public void addPageStreamingDescriptorImports(ModelTypeTable typeTable) { // do nothing } + public void addBundlingDescriptorImports(ModelTypeTable typeTable) { + // do nothing + } + + public void addPageStreamingCallSettingsImports(ModelTypeTable typeTable) { + // do nothing + } + + public void addBundlingCallSettingsImports(ModelTypeTable typeTable) { + // do nothing + } + public String getMethodKey(Method method) { return keyName(Name.upperCamel(method.getSimpleName())); } @@ -181,13 +197,14 @@ public String getClientConfigPath(Interface service) { } public String getGrpcClientTypeName(Interface service) { + // FIXME make general (e.g. if Java wanted to use this); needs to use modelTypeFormatter.getFullNameFor NamePath namePath = NamePath.dotted(service.getFullName()); String className = className(Name.upperCamel(namePath.getHead(), "Client")); return qualifiedName(namePath.withHead(className)); } public String getGrpcContainerTypeName(Interface service) { - NamePath namePath = NamePath.dotted(service.getFullName()); + NamePath namePath = NamePath.dotted(modelTypeFormatter.getFullNameFor(service)); String className = className(Name.upperCamel(namePath.getHead(), "Grpc")); return qualifiedName(namePath.withHead(className)); } @@ -285,12 +302,4 @@ public String getGetResourceListCallName(Field resourcesField) { public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef resourceType) { return getNotImplementedString("SurfaceNamer.getAndSavePagedResponseTypeName"); } - - public String getPageStreamingCallSettingsTypeName() { - return getNotImplementedString("SurfaceNamer.getPageStreamingCallSettingsTypeName"); - } - - public String getBundlingCallSettingsTypeName() { - return getNotImplementedString("SurfaceNamer.getBundlingCallSettingsTypeName"); - } } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java index 1f1a73be12..7ddaeda77e 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaGapicSurfaceTransformer.java @@ -37,6 +37,7 @@ import com.google.api.codegen.viewmodel.RetryCodesDefinitionView; import com.google.api.codegen.viewmodel.RetryParamsDefinitionView; import com.google.api.codegen.viewmodel.ServiceDocView; +import com.google.api.codegen.viewmodel.SettingsDocView; import com.google.api.codegen.viewmodel.StaticApiMethodView; import com.google.api.codegen.viewmodel.StaticXApiView; import com.google.api.codegen.viewmodel.StaticXSettingsView; @@ -68,9 +69,9 @@ public class JavaGapicSurfaceTransformer implements ModelToViewTransformer { private PageStreamingTransformer pageStreamingTransformer; private BundlingTransformer bundlingTransformer; - private static final String XAPI_TEMPLATE_FILENAME = "java/xapi.snip"; - private static final String XSETTINGS_TEMPLATE_FILENAME = "java/xsettings.snip"; - private static final String PACKAGE_INFO_TEMPLATE_FILENAME = "java/xpackage-info.snip"; + private static final String XAPI_TEMPLATE_FILENAME = "java/main.snip"; + private static final String XSETTINGS_TEMPLATE_FILENAME = "java/settings.snip"; + private static final String PACKAGE_INFO_TEMPLATE_FILENAME = "java/package-info.snip"; /** * Standard constructor. @@ -106,7 +107,8 @@ public List transform(Model model, ApiConfig apiConfig) { serviceDocs.add(xapi.doc()); context = SurfaceTransformerContext.create(service, apiConfig, createTypeTable(), namer); - StaticXSettingsView xsettings = generateXSettings(context); + StaticApiMethodView exampleApiMethod = getExampleApiMethod(xapi.apiMethods()); + StaticXSettingsView xsettings = generateXSettings(context, exampleApiMethod); surfaceDocs.add(xsettings); } @@ -153,8 +155,8 @@ private StaticXApiView generateXApi(SurfaceTransformerContext context) { return xapiClass.build(); } - private ApiMethodView getExampleApiMethod(List methods) { - ApiMethodView exampleApiMethod = null; + private StaticApiMethodView getExampleApiMethod(List methods) { + StaticApiMethodView exampleApiMethod = null; for (StaticApiMethodView method : methods) { if (method.type().equals(ApiMethodType.FlattenedMethod)) { exampleApiMethod = method; @@ -167,12 +169,14 @@ private ApiMethodView getExampleApiMethod(List methods) { return exampleApiMethod; } - private StaticXSettingsView generateXSettings(SurfaceTransformerContext context) { + private StaticXSettingsView generateXSettings( + SurfaceTransformerContext context, StaticApiMethodView exampleApiMethod) { addXSettingsImports(context); StaticXSettingsView.Builder xsettingsClass = StaticXSettingsView.newBuilder(); xsettingsClass.templateFileName(XSETTINGS_TEMPLATE_FILENAME); xsettingsClass.packageName(context.getApiConfig().getPackageName()); + xsettingsClass.doc(generateSettingsDoc(context, exampleApiMethod)); String name = context.getNamer().getApiSettingsClassName(context.getInterface()); xsettingsClass.name(name); ServiceConfig serviceConfig = new ServiceConfig(); @@ -249,6 +253,22 @@ private void addXSettingsImports(SurfaceTransformerContext context) { typeTable.saveNicknameFor("java.util.concurrent.ScheduledExecutorService"); } + public SettingsDocView generateSettingsDoc( + SurfaceTransformerContext context, StaticApiMethodView exampleApiMethod) { + SurfaceNamer namer = context.getNamer(); + SettingsDocView.Builder settingsDoc = SettingsDocView.newBuilder(); + ServiceConfig serviceConfig = new ServiceConfig(); + settingsDoc.serviceAddress(serviceConfig.getServiceAddress(context.getInterface())); + settingsDoc.servicePort(serviceConfig.getServicePort()); + settingsDoc.exampleApiMethodName(exampleApiMethod.name()); + settingsDoc.exampleApiMethodSettingsGetter(exampleApiMethod.settingsGetterName()); + settingsDoc.apiClassName(namer.getApiWrapperClassName(context.getInterface())); + settingsDoc.settingsVarName(namer.getApiSettingsVariableName(context.getInterface())); + settingsDoc.settingsClassName(namer.getApiSettingsClassName(context.getInterface())); + settingsDoc.settingsBuilderVarName(namer.getApiSettingsBuilderVarName(context.getInterface())); + return settingsDoc.build(); + } + private List generateApiMethods(SurfaceTransformerContext context) { List apiMethods = new ArrayList<>(); diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java index 6fa97e7bc0..c75df18049 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java @@ -50,6 +50,30 @@ public List getThrowsDocLines() { return Arrays.asList("@throws com.google.api.gax.grpc.ApiException if the remote call fails"); } + @Override + public void addPageStreamingDescriptorImports(ModelTypeTable typeTable) { + typeTable.saveNicknameFor("com.google.api.gax.grpc.PageStreamingDescriptor"); + } + + @Override + public void addBundlingDescriptorImports(ModelTypeTable typeTable) { + typeTable.saveNicknameFor("com.google.api.gax.grpc.BundlingDescriptor"); + typeTable.saveNicknameFor("com.google.api.gax.grpc.RequestIssuer"); + typeTable.saveNicknameFor("java.util.ArrayList"); + typeTable.saveNicknameFor("java.util.Collection"); + } + + @Override + public void addPageStreamingCallSettingsImports(ModelTypeTable typeTable) { + typeTable.saveNicknameFor("com.google.api.gax.grpc.PageStreamingCallSettings"); + } + + @Override + public void addBundlingCallSettingsImports(ModelTypeTable typeTable) { + typeTable.saveNicknameFor("com.google.api.gax.grpc.BundlingCallSettings"); + typeTable.saveNicknameFor("com.google.api.gax.grpc.BundlingSettings"); + } + @Override public String getStaticReturnTypeName(Method method, MethodConfig methodConfig) { if (ServiceMessages.s_isEmptyType(method.getOutputType())) { @@ -73,14 +97,4 @@ public String getAndSavePagedResponseTypeName(ModelTypeTable typeTable, TypeRef return typeTable.getAndSaveNicknameForContainer( "com.google.api.gax.core.PageAccessor", resourceTypeName); } - - @Override - public String getPageStreamingCallSettingsTypeName() { - return "com.google.api.gax.grpc.PageStreamingCallSettings"; - } - - @Override - public String getBundlingCallSettingsTypeName() { - return "com.google.api.gax.grpc.BundlingCallSettings"; - } } diff --git a/src/main/java/com/google/api/codegen/viewmodel/SettingsDocView.java b/src/main/java/com/google/api/codegen/viewmodel/SettingsDocView.java new file mode 100644 index 0000000000..f1226bc211 --- /dev/null +++ b/src/main/java/com/google/api/codegen/viewmodel/SettingsDocView.java @@ -0,0 +1,61 @@ +/* Copyright 2016 Google Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.api.codegen.viewmodel; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class SettingsDocView { + public abstract String serviceAddress(); + + public abstract Integer servicePort(); + + public abstract String exampleApiMethodName(); + + public abstract String exampleApiMethodSettingsGetter(); + + public abstract String apiClassName(); + + public abstract String settingsVarName(); + + public abstract String settingsClassName(); + + public abstract String settingsBuilderVarName(); + + public static Builder newBuilder() { + return new AutoValue_SettingsDocView.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder serviceAddress(String val); + + public abstract Builder servicePort(Integer val); + + public abstract Builder exampleApiMethodName(String val); + + public abstract Builder exampleApiMethodSettingsGetter(String val); + + public abstract Builder apiClassName(String val); + + public abstract Builder settingsVarName(String val); + + public abstract Builder settingsClassName(String val); + + public abstract Builder settingsBuilderVarName(String val); + + public abstract SettingsDocView build(); + } +} diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java index d60148cd68..8a6202efb7 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticApiMethodView.java @@ -43,6 +43,8 @@ public abstract class StaticApiMethodView implements ApiMethodView { public abstract String name(); + public abstract String settingsGetterName(); + public abstract List methodParams(); public abstract List pathTemplateChecks(); @@ -85,6 +87,8 @@ public static abstract class Builder { public abstract Builder name(String name); + public abstract Builder settingsGetterName(String name); + public abstract Builder methodParams(List methodParams); public abstract Builder pathTemplateChecks(List pathTemplateChecks); diff --git a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java index ba7196ab50..3d99d061db 100644 --- a/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java +++ b/src/main/java/com/google/api/codegen/viewmodel/StaticXSettingsView.java @@ -25,6 +25,8 @@ public abstract class StaticXSettingsView implements ViewModel { public abstract String packageName(); + public abstract SettingsDocView doc(); + public abstract String name(); public abstract String serviceAddress(); @@ -62,6 +64,8 @@ public static abstract class Builder { public abstract Builder packageName(String val); + public abstract Builder doc(SettingsDocView generateSettingsDoc); + public abstract Builder name(String val); public abstract Builder serviceAddress(String val); diff --git a/src/main/resources/com/google/api/codegen/java/common.snip b/src/main/resources/com/google/api/codegen/java/common.snip index 1860288858..6192801030 100644 --- a/src/main/resources/com/google/api/codegen/java/common.snip +++ b/src/main/resources/com/google/api/codegen/java/common.snip @@ -14,118 +14,14 @@ */ @end -@snippet autoGenClassWarning() - // AUTO-GENERATED DOCUMENTATION AND CLASS -@end - -@snippet autoGenServiceWarning() - // AUTO-GENERATED DOCUMENTATION AND SERVICE -@end - -@snippet autoGenMethodWarning() - // AUTO-GENERATED DOCUMENTATION AND METHOD -@end - -@snippet settingsClassName(service) - {@service.getSimpleName}Settings -@end - -@snippet javaDoc(protoElement) - {@javaDocFromStr(getDoc(protoElement))} -@end - -@snippet javaDocFromStr(str) - {@javaDocStart()} - {@javaDocLinesFromStr(str)} - {@javaDocEnd()} -@end - -@snippet javaDocStart() - /** -@end - -@snippet javaDocLines(protoElement) - {@javaDocLinesFromStr(getDoc(protoElement))} -@end - -@snippet javaDocLinesFromStr(str) - @join commentLine : context.java.getJavaDocLines(str) - {@commentLine} +@snippet paramList(params) + @join param : params on ", " + {@param.typeName} {@param.name} @end @end -@snippet javaDocEmptyLine() - {@""} * -@end - -@snippet javaDocThrows() - {@""} * @ throws com.google.api.gax.grpc.ApiException if the remote call fails -@end - -@snippet javaDocEnd() - {@""} */ -@end - -@snippet getDoc(protoElement) - {@context.getDescription(protoElement)} -@end - -@snippet setCallName(field) - {@setCallName(field.getType, context.lowerUnderscoreToUpperCamel(field.getSimpleName))} -@end - -@snippet setCallName(type, name) - @if type.isMap - putAll{@name} - @else - @if type.isRepeated - addAll{@name} - @else - set{@name} - @end - @end -@end - -@snippet getCallName(field) - @let paramNameInCamel = context.lowerUnderscoreToUpperCamel(field.getSimpleName) - @if field.isRepeated - get{@paramNameInCamel}List - @else - get{@paramNameInCamel} - @end - @end -@end - -@snippet getIndexCallName(field) - @let paramNameInCamel = context.lowerUnderscoreToUpperCamel(field.getSimpleName) - @if field.isRepeated - get{@paramNameInCamel} - @else - # TODO(garrettjones) throw snippet error - INVALID - @end +@snippet argList(args) + @join arg : args on ", " + {@arg} @end @end - -@snippet getCountCallName(field) - @let paramNameInCamel = context.lowerUnderscoreToUpperCamel(field.getSimpleName) - @if field.isRepeated - get{@paramNameInCamel}Count - @else - # TODO(garrettjones) throw snippet error - 1 #INVALID - @end - @end -@end - -@snippet formatResourceFunctionName(collectionConfig) - format{@resourceName(collectionConfig)} -@end - -@snippet resourceName(collectionConfig) - {@context.lowerUnderscoreToUpperCamel(collectionConfig.getEntityName)}Name -@end - -@snippet elementTypeName(resourcesField) - {@context.basicTypeNameBoxed(resourcesField.getType())} -@end diff --git a/src/main/resources/com/google/api/codegen/java/main.snip b/src/main/resources/com/google/api/codegen/java/main.snip index 583c522239..534d109627 100644 --- a/src/main/resources/com/google/api/codegen/java/main.snip +++ b/src/main/resources/com/google/api/codegen/java/main.snip @@ -1,268 +1,251 @@ @extends "java/common.snip" @extends "java/method_sample.snip" -@snippet generateFilename(service) - {@context.getApiWrapperName(service)}.java -@end - -@snippet generateClass(service, body, imports) +@snippet generate(xapiClass) {@license()} - package {@context.getApiConfig.getPackageName}; + package {@xapiClass.packageName}; - @join import : imports + @join import : xapiClass.imports import {@import}; @end - {@body} -@end - -@snippet generateBody(service) - {@alwaysImport()} - - {@serviceJavaDoc(service)} + {@serviceDoc(xapiClass)} @@javax.annotation.Generated("by GAPIC") - public class {@context.getApiWrapperName(service)} implements AutoCloseable { - {@members(service)} - - {@resourceUtils(service)} - - {@constructors(service)} - - {@callables(service)} - + public class {@xapiClass.name} implements AutoCloseable { + {@members(xapiClass)} + {@statics(xapiClass)} + {@staticFunctions(xapiClass)} + {@constructors(xapiClass)} + {@apiMethods(xapiClass)} {@cleanupSection()} } @end -@private alwaysImport() fill - {@context.addImport("com.google.api.gax.grpc.ApiCallable")} - {@context.addImport("com.google.api.gax.protobuf.PathTemplate")} - {@context.addImport("io.grpc.ManagedChannel")} - {@context.addImport("java.io.Closeable")} - {@context.addImport("java.io.IOException")} - {@context.addImport("java.util.ArrayList")} - {@context.addImport("java.util.List")} - {@context.addImport("java.util.concurrent.ScheduledExecutorService")} -@end - -@private resourceUtils(service) - {@resourceConstants(service)} - {@resourceFunctions(service)} -@end - -@private resourceConstants(service) - {@pathTemplateConstants(service)} -@end - -@private pathTemplateConstants(service) - @join collectionConfig : context.getApiConfig.getInterfaceConfig(service).getCollectionConfigs() - {@pathTemplateConstant(collectionConfig)} - +@private serviceDoc(xapiClass) + @let coreSampleCode = syncMethodSampleCode(xapiClass.doc.exampleApiMethod), \ + decoratedSampleCode = decorateSampleCode(xapiClass.doc.exampleApiMethod, coreSampleCode) + {@renderServiceDoc(xapiClass.doc, decoratedSampleCode)} @end @end -@private pathTemplateConstant(collectionConfig) - private static final PathTemplate {@pathTemplateConstantName(collectionConfig)} = - PathTemplate.createWithoutUrlEncoding("{@collectionConfig.getNamePattern}"); +@private renderServiceDoc(xapiClassDoc, exampleMethodSampleCode) + // AUTO-GENERATED DOCUMENTATION AND SERVICE + /** + * Service Description: {@xapiClassDoc.firstLine} + @if xapiClassDoc.remainingLines + @join commentLine : xapiClassDoc.remainingLines + {@""} * {@commentLine} + @end + @end + * + *

This class provides the ability to make remote calls to the backing service through method + * calls that map to API methods. Sample code to get started: + * + *

+   * 
+  @join sampleLine : util.getDocLines(exampleMethodSampleCode)
+    {@""} * {@sampleLine}
+  @end
+   * 
+   * 
+ * + *

Note: close() needs to be called on the {@xapiClassDoc.apiVarName} object to clean up resources such + * as threads. In the example above, try-with-resources is used, which automatically calls + * close(). + * + *

The surface of this class includes several types of Java methods for each of the API's methods: + * + *

    + *
  1. A "flattened" method. With this type of method, the fields of the request type have been + * converted into function parameters. It may be the case that not all fields are available + * as parameters, and not every API method will have a flattened method entry point. + *
  2. A "request object" method. This type of method only takes one parameter, a request + * object, which must be constructed before the call. Not every API method will have a request + * object method. + *
  3. A "callable" method. This type of method takes no parameters and returns an immutable + * ApiCallable object, which can be used to initiate calls to the service. + *
+ * + *

See the individual methods for example code. + * + *

Many parameters require resource names to be formatted in a particular way. To assist + * with these names, this class includes a format method for each type of name, and additionally + * a parse method to extract the individual identifiers contained within names that are + * returned. + * + *

This class can be customized by passing in a custom instance of {@xapiClassDoc.settingsClassName} to + * create(). For example: + * + *

+   * 
+   * {@xapiClassDoc.settingsClassName} {@xapiClassDoc.settingsVarName} = {@xapiClassDoc.settingsClassName}.defaultBuilder()
+   *     .provideChannelWith(myCredentials)
+   *     .build();
+   * {@xapiClassDoc.apiClassName} {@xapiClassDoc.apiVarName} = \
+       {@xapiClassDoc.apiClassName}.create({@xapiClassDoc.settingsVarName});
+   * 
+   * 
+ */ @end -@private pathTemplateConstantName(collectionConfig) - {@context.lowerUnderscoreToUpperUnderscore(collectionConfig.getEntityName)}_PATH_TEMPLATE +@private statics(xapiClass) + @join pathTemplate : xapiClass.pathTemplates + private static final PathTemplate {@pathTemplate.name} = + PathTemplate.createWithoutUrlEncoding("{@pathTemplate.pattern}"); + {@""} + @end @end -@private resourceFunctions(service) - @join collectionConfig : context.getApiConfig.getInterfaceConfig(service).getCollectionConfigs() - {@formatResourceFunctions(collectionConfig)} +@private staticFunctions(xapiClass) + @join function : xapiClass.formatResourceFunctions + {@formatResourceFunction(function)} @end - - @join collectionConfig : context.getApiConfig.getInterfaceConfig(service).getCollectionConfigs() - {@parseResourceFunctions(collectionConfig)} + {@""} + @join function : xapiClass.parseResourceFunctions + {@parseResourceFunction(function)} @end @end -@private formatResourceFunctions(collectionConfig) +@private formatResourceFunction(function) /** * Formats a string containing the fully-qualified path to represent - * a {@collectionConfig.getEntityName} resource. + * a {@function.entityName} resource. */ - public static final String {@formatResourceFunctionName(collectionConfig)}(\ - {@formatResourceFunctionParams(collectionConfig)}) { - return {@pathTemplateConstantName(collectionConfig)}.instantiate( - {@pathTemplateArgs(collectionConfig)}); + public static final String {@function.name}(\ + {@formatResourceFunctionParams(function.resourceIdParams)}) { + return {@function.pathTemplateName}.instantiate( + {@pathTemplateArgs(function.resourceIdParams)}); } - + {@""} @end -@private formatResourceFunctionParams(collectionConfig) - @join param : collectionConfig.getNameTemplate.vars() on ", " - String {@context.lowerUnderscoreToLowerCamel(param)} +@private formatResourceFunctionParams(resourceIdParams) + @join param : resourceIdParams on ", " + String {@param.name} @end @end -@private pathTemplateArgs(collectionConfig) - @join param : collectionConfig.getNameTemplate.vars() vertical on "," - "{@param}", {@context.lowerUnderscoreToLowerCamel(param)} +@private pathTemplateArgs(resourceIdParams) + @join param : resourceIdParams on ",".add(BREAK) + "{@param.templateKey}", {@param.name} @end @end -@private parseResourceFunctions(collectionConfig) - @join subField : collectionConfig.getNameTemplate.vars() - @let fieldPath = context.upperCamelToLowerCamel(resourceName(collectionConfig)) - /** - * Parses the {@subField} from the given fully-qualified path which - * represents a {@context.lowerUnderscoreToLowerCamel(collectionConfig.getEntityName)} resource. - */ - public static final String \ - parse{@context.lowerUnderscoreToUpperCamel(subField)}From{@resourceName(collectionConfig)}(\ - String {@fieldPath}) { - return {@pathTemplateConstantName(collectionConfig)}.parse({@fieldPath}).get("{@subField}"); - } - - @end - @end +@private parseResourceFunction(function) + /** + * Parses the {@function.outputResourceId} from the given fully-qualified path which + * represents a {@function.entityName} resource. + */ + public static final String {@function.name}(String {@function.entityNameParamName}) { + return {@function.pathTemplateName}.parse({@function.entityNameParamName})\ + .get("{@function.outputResourceId}"); + } + {@""} @end -@private members(service) - private final {@settingsClassName(service)} settings; +@private members(xapiClass) + private final {@xapiClass.settingsClassName} settings; private final ManagedChannel channel; private final ScheduledExecutorService executor; private final List closeables = new ArrayList<>(); - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - isPageStreaming = methodConfig.isPageStreaming - private final ApiCallable<{@inTypeName}, {@outTypeName}> {@methodName}Callable; - @if {@isPageStreaming} - @let pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - dummy = context.addImport("com.google.api.gax.core.PageAccessor") - private final ApiCallable<{@inTypeName}, PageAccessor<{@resourceTypeName}>> - {@methodName}PagedCallable; - @end - @end - @end + @join apiCallable : xapiClass.apiCallableMembers + private final ApiCallable<{@apiCallable.requestTypeName}, {@apiCallable.responseTypeName}> {@apiCallable.name}; @end - public final {@settingsClassName(service)} getSettings() { + public final {@xapiClass.settingsClassName} getSettings() { return settings; } + {@""} @end -@private constructors(service) - @let className = context.getApiWrapperName(service) - /** - * Constructs an instance of {@className} with default settings. - */ - public static final {@className} createWithDefaults() throws IOException { - return create({@settingsClassName(service)}.defaultBuilder().build()); - } +@private constructors(xapiClass) + /** + * Constructs an instance of {@xapiClass.name} with default settings. + */ + public static final {@xapiClass.name} createWithDefaults() throws IOException { + return create({@xapiClass.settingsClassName}.defaultBuilder().build()); + } - /** - * Constructs an instance of {@className}, using the given settings. - * The channels are created based on the settings passed in, or defaults for any - * settings that are not set. - */ - public static final {@className} create({@settingsClassName(service)} settings) throws IOException { - return new {@className}(settings); - } + /** + * Constructs an instance of {@xapiClass.name}, using the given settings. + * The channels are created based on the settings passed in, or defaults for any + * settings that are not set. + */ + public static final {@xapiClass.name} create({@xapiClass.settingsClassName} settings) throws IOException { + return new {@xapiClass.name}(settings); + } - /** - * Constructs an instance of {@className}, using the given settings. - * This is protected so that it easy to make a subclass, but otherwise, the static - * factory methods should be preferred. - */ - protected {@className}({@settingsClassName(service)} settings) throws IOException { - this.settings = settings; - this.executor = settings.getExecutorProvider().getOrBuildExecutor(); - this.channel = settings.getChannelProvider().getOrBuildChannel(this.executor); - - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - this.{@methodName}Callable = ApiCallable.create(settings.{@methodName}Settings(), this.channel, this.executor); - @if {@isPageStreaming} - this.{@methodName}PagedCallable = - ApiCallable.createPagedVariant(settings.{@methodName}Settings(), this.channel, this.executor); - @end - @if {@isBundling} - if (settings.{@methodName}Settings().getBundlerFactory() != null) { - closeables.add(settings.{@methodName}Settings().getBundlerFactory()); - } - @end - @end + /** + * Constructs an instance of {@xapiClass.name}, using the given settings. + * This is protected so that it easy to make a subclass, but otherwise, the static + * factory methods should be preferred. + */ + protected {@xapiClass.name}({@xapiClass.settingsClassName} settings) throws IOException { + this.settings = settings; + this.executor = settings.getExecutorProvider().getOrBuildExecutor(); + this.channel = settings.getChannelProvider().getOrBuildChannel(this.executor); + + @join apiCallable : xapiClass.apiCallableMembers + @switch apiCallable.type.toString + @case "SimpleApiCallable" + this.{@apiCallable.name} = ApiCallable.create(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); + @case "PagedApiCallable" + this.{@apiCallable.name} = + ApiCallable.createPagedVariant(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); + @case "BundlingApiCallable" + this.{@apiCallable.name} = ApiCallable.create(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); + if (settings.{@apiCallable.settingsFunctionName}().getBundlerFactory() != null) { + closeables.add(settings.{@apiCallable.settingsFunctionName}().getBundlerFactory()); + } + @default + $unhandledCase: {@apiCallable.type.toString}$ @end + @end - if (settings.getChannelProvider().shouldAutoClose()) { - closeables.add( - new Closeable() { - @@Override - public void close() throws IOException { - channel.shutdown(); - } - }); - } - if (settings.getExecutorProvider().shouldAutoClose()) { - closeables.add( - new Closeable() { - @@Override - public void close() throws IOException { - executor.shutdown(); - } - }); - } + if (settings.getChannelProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @@Override + public void close() throws IOException { + channel.shutdown(); + } + }); } - @end -@end - -@private callables(service) - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - isPageStreaming = methodConfig.isPageStreaming, \ - isFlattening = methodConfig.isFlattening, \ - requestObjectMethodAccessStr = requestObjectMethodAccess(methodConfig) - // ----- {@methodName} ----- - - # TODO (garrettjones) put some kind of limit on number of flattened parameters, and - # don't generated a flattened method if there are too many. - @if {@isPageStreaming} - @if {@isFlattening} - @join flatteningGroup: \ - methodConfig.getFlattening().getFlatteningGroups() - {@pagedFlattenedMethod(service, method, methodName, flatteningGroup)} - @end - {@BREAK} - @end - {@pagedMethodWithRequestParam(service, method, methodName, inTypeName, outTypeName, requestObjectMethodAccessStr)} - {@methodReturningPagedCallable(service, method, methodName, inTypeName, outTypeName)} - {@methodReturningUnpagedListCallable(service, method, methodName, inTypeName, outTypeName)} - @else - @if {@isFlattening} - @join flatteningGroup : \ - methodConfig.getFlattening().getFlatteningGroups() - {@flattenedMethod(service, method, methodName, flatteningGroup)} - @end - {@BREAK} - @end - {@methodWithRequestParam(service, method, methodName, inTypeName, outTypeName, requestObjectMethodAccessStr)} - {@methodReturningCallable(service, method, methodName, inTypeName, outTypeName)} - @end + if (settings.getExecutorProvider().shouldAutoClose()) { + closeables.add( + new Closeable() { + @@Override + public void close() throws IOException { + executor.shutdown(); + } + }); + } + } + {@""} +@end + +@private apiMethods(xapiClass) + @join apiMethod : xapiClass.apiMethods + @switch apiMethod.type.toString + @case "PagedFlattenedMethod" + {@pagedFlattenedMethod(apiMethod)} + @case "PagedRequestObjectMethod" + {@pagedRequestObjectMethod(apiMethod)} + @case "PagedCallableMethod" + {@pagedCallableMethod(apiMethod)} + @case "UnpagedListCallableMethod" + {@unpagedListCallableMethod(apiMethod)} + @case "FlattenedMethod" + {@flattenedMethod(apiMethod)} + @case "RequestObjectMethod" + {@requestObjectMethod(apiMethod)} + @case "CallableMethod" + {@callableMethod(apiMethod)} + @default + $unhandledCase: {@apiMethod.getClass.getSimpleName}$ @end - @end -@end - -@private requestObjectMethodAccess(methodConfig) - @if {@methodConfig.hasRequestObjectMethod} - public - @else - private + {@BREAK} @end @end @@ -280,306 +263,148 @@ @end -@private pagedFlattenedMethod(service, method, methodName, fields) - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = elementTypeName(pageStreaming.getResourcesField()), \ - requestTypeName = context.typeName(method.getInputType), \ - fieldNamePatterns = methodConfig.getFieldNamePatterns() - {@iterableFlattenedMethodJavaDoc(service, method, methodName, resourceTypeName, fields)} - public final PageAccessor<{@resourceTypeName}> \ - {@methodName}({@paramList(fields)}) { - @join field : fields - @if fieldNamePatterns.containsKey(field.getSimpleName) - @let entityName = fieldNamePatterns.get(field.getSimpleName), \ - collectionConfig = context.getCollectionConfig(service, entityName) - {@pathTemplateCheck(paramName(field), collectionConfig)} - @end - @end - @end - {@context.typeName(method.getInputType)} request = - {@requestTypeName}.newBuilder() - {@builderSetCalls(fields)} - .build(); - return {@methodName}(request); - } - +@private pagedFlattenedMethod(apiMethod) + @let coreSampleCode = pagedIterableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end + public final {@apiMethod.responseTypeName} {@apiMethod.name}({@paramList(apiMethod.methodParams)}) { + @join pathTemplateCheck : apiMethod.pathTemplateChecks + {@pathTemplateCheckLine(pathTemplateCheck)} + @end + {@apiMethod.apiRequestTypeName} request = + {@apiMethod.apiRequestTypeName}.newBuilder() + {@builderSetCalls(apiMethod.requestObjectParams)} + .build(); + return {@apiMethod.name}(request); + } @end -@private pagedMethodWithRequestParam(service, method, methodName, inTypeName, outTypeName, accessModifier) - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = elementTypeName(pageStreaming.getResourcesField()) - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(methodName) \ - .setReturnType(resourceTypeName) \ - .setRequestObjectInitCode(context, service, method) \ - .setRequestObjectParam(method) \ - .setPagedVariant({@TRUE}) \ - .setCallableVariant({@FALSE}) \ - .build)} - {@accessModifier} final PageAccessor<{@resourceTypeName}> {@methodName}({@inTypeName} request) { - return {@methodName}PagedCallable() - .call(request); - } - +@private pagedRequestObjectMethod(apiMethod) + @let coreSampleCode = pagedIterableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end + {@apiMethod.requestObjectMethod.accessModifier} final {@apiMethod.responseTypeName} \ + {@apiMethod.name}({@apiMethod.apiRequestTypeName} request) { + return {@apiMethod.requestObjectMethod.callableMethodName}() + .call(request); + } @end -@private methodReturningPagedCallable(service, method, methodName, inTypeName, outTypeName) - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - pageStreaming = methodConfig.getPageStreaming(), \ - dummy = context.addImport("com.google.api.gax.core.PageAccessor"), \ - resourceTypeName = elementTypeName(pageStreaming.getResourcesField()) - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(methodName) \ - .setReturnType(resourceTypeName) \ - .setRequestObjectInitCode(context, service, method) \ - .setEmptyParams() \ - .setPagedVariant({@TRUE}) \ - .setCallableVariant({@TRUE}) \ - .build)} - public final ApiCallable<{@inTypeName}, PageAccessor<{@resourceTypeName}>> {@methodName}PagedCallable() { - return {@methodName}PagedCallable; - } - +@private pagedCallableMethod(apiMethod) + @let coreSampleCode = pagedCallableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end + {@callableMethodImpl(apiMethod)} @end -@private methodReturningUnpagedListCallable(service, method, methodName, inTypeName, outTypeName) - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - pageStreaming = methodConfig.getPageStreaming(), \ - dummy = context.addImport("com.google.api.gax.core.PageAccessor"), \ - resourcesField = pageStreaming.getResourcesField() - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(methodName) \ - .setReturnType(context.returnTypeOrEmpty(method.getOutputType)) \ - .setRequestObjectInitCode(context, service, method) \ - .setEmptyParams() \ - .setPagedVariant({@FALSE}) \ - .setCallableVariant({@TRUE}) \ - .setResourcesFieldForUnpagedListCallable(resourcesField) \ - .build)} - public final ApiCallable<{@inTypeName}, {@outTypeName}> {@methodName}Callable() { - return {@methodName}Callable; - } - +@private unpagedListCallableMethod(apiMethod) + @let coreSampleCode = unpagedListCallableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end + {@callableMethodImpl(apiMethod)} @end -@private flattenedMethod(service, method, methodName, fields) - {@flattenedMethodJavaDoc(service, method, methodName, fields)} - @let methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - returnType = context.methodReturnTypeName(method.getOutputType), \ - returnStatement = context.methodReturnStatement(method.getOutputType), \ - requestTypeName = context.typeName(method.getInputType), \ - fieldNamePatterns = methodConfig.getFieldNamePatterns() - public final {@returnType} {@methodName}({@paramList(fields)}) { - @join field : fields - @if fieldNamePatterns.containsKey(field.getSimpleName) - @let entityName = fieldNamePatterns.get(field.getSimpleName), \ - collectionConfig = context.getCollectionConfig(service, entityName) - {@pathTemplateCheck(paramName(field), collectionConfig)} - @end - @end - @end - {@context.typeName(method.getInputType)} request = - {@requestTypeName}.newBuilder() - {@builderSetCalls(fields)} - .build(); - {@returnStatement}{@methodName}(request); - } - +@private flattenedMethod(apiMethod) + @let coreSampleCode = syncMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end + public final {@apiMethod.responseTypeName} {@apiMethod.name}(\ + {@paramList(apiMethod.methodParams)}) { + @join pathTemplateCheck : apiMethod.pathTemplateChecks + {@pathTemplateCheckLine(pathTemplateCheck)} + @end + {@apiMethod.apiRequestTypeName} request = + {@apiMethod.apiRequestTypeName}.newBuilder() + {@builderSetCalls(apiMethod.requestObjectParams)} + .build(); + @if apiMethod.hasReturnValue + return {@apiMethod.name}(request); + @else + {@apiMethod.name}(request); + @end + } @end -@private methodWithRequestParam(service, method, methodName, inTypeName, outTypeName, accessModifier) - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(context.upperCamelToLowerCamel(method.getSimpleName)) \ - .setReturnType(context.returnTypeOrEmpty(method.getOutputType)) \ - .setRequestObjectInitCode(context, service, method) \ - .setRequestObjectParam(method) \ - .setPagedVariant({@FALSE}) \ - .setCallableVariant({@FALSE}) \ - .build)} - @let returnType = context.methodReturnTypeName(method.getOutputType), \ - returnStatement = context.methodReturnStatement(method.getOutputType) - {@accessModifier} {@returnType} {@methodName}({@inTypeName} request) { - {@returnStatement}{@methodName}Callable().call(request); - } - +@private requestObjectMethod(apiMethod) + @let coreSampleCode = syncMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end -@end - -@private methodReturningCallable(service, method, methodName, inTypeName, outTypeName) - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(methodName) \ - .setReturnType(context.returnTypeOrEmpty(method.getOutputType)) \ - .setRequestObjectInitCode(context, service, method) \ - .setEmptyParams() \ - .setPagedVariant({@FALSE}) \ - .setCallableVariant({@TRUE}) \ - .build)} - public final ApiCallable<{@inTypeName}, {@outTypeName}> {@methodName}Callable() { - return {@methodName}Callable; + {@apiMethod.requestObjectMethod.accessModifier} final {@apiMethod.responseTypeName} \ + {@apiMethod.name}({@apiMethod.apiRequestTypeName} request) { + @if apiMethod.hasReturnValue + return {@apiMethod.requestObjectMethod.callableMethodName}().call(request); + @else + {@apiMethod.requestObjectMethod.callableMethodName}().call(request); + @end } - @end -@private serviceJavaDoc(service) - {@autoGenServiceWarning()} - @let serviceApiVariable = context.upperCamelToLowerCamel(context.getApiWrapperName(service)), \ - settingsVariable = context.upperCamelToLowerCamel(settingsClassName(service)), \ - # TODO: support the case where the API has no flattened methods. - firstFlattenedMethod = context.getFirstFlattenedMethod(service), \ - firstFlattenedMethodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(firstFlattenedMethod), \ - fields = firstFlattenedMethodConfig.getFlattening().getFlatteningGroups().get(0) - /** - {@javaDocLinesFromStr(serviceDocString(service))} - * - *

This class provides the ability to make remote calls to the backing service through method - * calls that map to API methods. Sample code to get started: - * - *

-     * 
-    @join commentLine : context.java.getJavaDocLines(generateMethodSampleCode(context.newJavaDocConfigBuilder \
-                               .setApiName(context.getApiWrapperName(service)) \
-                               .setMethodName(context.upperCamelToLowerCamel(firstFlattenedMethod.getSimpleName)) \
-                               .setReturnType(context.returnTypeOrEmpty(firstFlattenedMethod.getOutputType)) \
-                               .setFieldInitCode(context, service, firstFlattenedMethod, fields) \
-                               .setFieldParams(context, fields) \
-                               .setPagedVariant({@FALSE}) \
-                               .setCallableVariant({@FALSE}) \
-                               .build))
-      {@commentLine}
-    @end
-     * 
-     * 
- * - *

Note: close() needs to be called on the {@serviceApiVariable} object to clean up resources such - * as threads. In the example above, try-with-resources is used, which automatically calls - * close(). - * - *

The surface of this class includes several types of Java methods for each of the API's methods: - * - *

    - *
  1. A "flattened" method. With this type of method, the fields of the request type have been - * converted into function parameters. It may be the case that not all fields are available - * as parameters, and not every API method will have a flattened method entry point. - *
  2. A "request object" method. This type of method only takes one parameter, a request - * object, which must be constructed before the call. Not every API method will have a request - * object method. - *
  3. A "callable" method. This type of method takes no parameters and returns an immutable - * ApiCallable object, which can be used to initiate calls to the service. - *
- * - *

See the individual methods for example code. - * - *

Many parameters require resource names to be formatted in a particular way. To assist - * with these names, this class includes a format method for each type of name, and additionally - * a parse method to extract the individual identifiers contained within names that are - * returned. - * - *

This class can be customized by passing in a custom instance of {@settingsClassName(service)} to - * create(). For example: - * - *

-     * 
-     * {@settingsClassName(service)} {@settingsVariable} = {@settingsClassName(service)}.defaultBuilder()
-     *     .provideChannelWith(myCredentials)
-     *     .build();
-     * {@context.getApiWrapperName(service)} {@serviceApiVariable} = \
-         {@context.getApiWrapperName(service)}.create({@settingsVariable});
-     * 
-     * 
- */ +@private callableMethod(apiMethod) + @let coreSampleCode = callableMethodSampleCode(apiMethod) + {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} @end + {@callableMethodImpl(apiMethod)} @end -@snippet serviceDocString(protoElement) - Service Description: {@getDoc(protoElement)} -@end - -@private flattenedMethodJavaDoc(service, method, methodName, fields) - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(methodName) \ - .setReturnType(context.returnTypeOrEmpty(method.getOutputType)) \ - .setFieldInitCode(context, service, method, fields) \ - .setFieldParams(context, fields) \ - .setPagedVariant({@FALSE}) \ - .setCallableVariant({@FALSE}) \ - .build)} -@end - -@private iterableFlattenedMethodJavaDoc(service, method, methodName, resourceName, fields) - {@methodJavaDoc(method, context.newJavaDocConfigBuilder \ - .setApiName(context.getApiWrapperName(method.getParent)) \ - .setMethodName(methodName) \ - .setReturnType(resourceName) \ - .setFieldInitCode(context, service, method, fields) \ - .setFieldParams(context, fields) \ - .setPagedVariant({@TRUE}) \ - .setCallableVariant({@FALSE}) \ - .build)} +@private callableMethodImpl(apiMethod) + public final ApiCallable<{@apiMethod.apiRequestTypeName}, {@apiMethod.responseTypeName}> \ + {@apiMethod.name}() { + return {@apiMethod.callableMethod.callableName}; + } @end -@private methodJavaDoc(method, docConfig) - {@autoGenMethodWarning()} - {@javaDocStart()} - {@javaDocLines(method)} - @if context.getApiConfig.generateSamples - {@javaDocEmptyLine()} - {@javaDocEmptyLine()} Sample code: - {@javaDocEmptyLine()}

-    @join commentLine : context.java.getJavaDocLines(generateMethodSampleCode(docConfig))
-      {@commentLine}
+@private methodDoc(apiMethodDoc, methodSampleCode)
+  // AUTO-GENERATED DOCUMENTATION AND METHOD
+  /**
+  @join commentLine : apiMethodDoc.mainDocLines
+    {@""} * {@commentLine} 
+  @end
+   *
+   * Sample code:
+   * 

+  @join sampleLine : util.getDocLines(methodSampleCode)
+    {@""} * {@sampleLine}
+  @end
+   * 
+ @if apiMethodDoc.paramDocs + {@""} * + @join doc : apiMethodDoc.paramDocs + {@paramDoc(doc)} @end - {@javaDocEmptyLine()}
@end - @if docConfig.isCallableVariant - @else - {@javaDocEmptyLine()} - @join param : docConfig.getParams - @join commentLine : context.java.getJavaDocLinesWithPrefix(param.getDescription, paramDocLinePrefix(param)) - {@commentLine} - @end + @if apiMethodDoc.throwsDocLines + @join commentLine : apiMethodDoc.throwsDocLines + {@""} * {@commentLine} @end - {@javaDocThrows()} @end - {@javaDocEnd()} + */ + {@EMPTY} @end -@private paramDocLinePrefix(param) - @@param {@param.getName} {@""} +@private paramDoc(doc) + @switch doc.type + @case "SimpleParamDocView" + {@simpleParamDoc(doc)} + @default + $unhandledCase: {@doc.type}$ + @end @end -@private paramList(fields) - @join field : fields on ", " - @let paramName = context.lowerUnderscoreToLowerCamel(field.getSimpleName) - {@context.typeName(field.getType)} {@paramName} +@private simpleParamDoc(doc) + {@""} * @@param {@doc.paramName} {@doc.firstLine} + @if doc.remainingLines + @join commentLine : doc.remainingLines + {@""} * {@commentLine} @end @end @end -@private paramName(field) - {@context.lowerUnderscoreToLowerCamel(field.getSimpleName)} -@end - -@private builderSetCalls(fields) - @join field : fields - @let paramName = context.lowerUnderscoreToLowerCamel(field.getSimpleName) - .{@setCallName(field)}({@paramName}) - @end +@private builderSetCalls(requestObjectParams) + @join requestObjectParam : requestObjectParams + .{@requestObjectParam.setCallName}({@requestObjectParam.name}) @end @end -@snippet pathTemplateCheck(paramName, collectionConfig) - {@pathTemplateConstantName(collectionConfig)}.validate({@paramName}); +@private pathTemplateCheckLine(pathTemplateCheck) + {@pathTemplateCheck.pathTemplateName}.validate({@pathTemplateCheck.paramName}); @end diff --git a/src/main/resources/com/google/api/codegen/java/method_sample.snip b/src/main/resources/com/google/api/codegen/java/method_sample.snip index 990411f966..0ce04c3b3a 100644 --- a/src/main/resources/com/google/api/codegen/java/method_sample.snip +++ b/src/main/resources/com/google/api/codegen/java/method_sample.snip @@ -1,61 +1,86 @@ @extends "java/common.snip" -# Generate code samples for method-level documentation. -@snippet generateMethodSampleCode(docConfig) - @let ApiName = docConfig.getApiName, \ - apiName = context.upperCamelToLowerCamel(ApiName) - try ({@ApiName} {@apiName} = {@ApiName}.createWithDefaults()) { - {@initCode(docConfig.getInitCode)} - @if docConfig.isUnpagedListCallableVariant - @let resourcesField = docConfig.getResourcesFieldForUnpagedListCallable - while (true) { - {@callResultSampleCode(docConfig.getReturnType)}{@methodCallSampleCode(docConfig, apiName)}; - for ({@elementTypeName(resourcesField)} elements : response.{@getResourcesListCall(resourcesField)}) { - // doThingsWith(elements); - } - String nextPageToken = response.getNextPageToken(); - if (!Strings.isNullOrEmpty(nextPageToken)) { - request = request.toBuilder().setPageToken(nextPageToken).build(); - } else { - break; - } - } - @end - @else - @if docConfig.isCallableVariant - ListenableFuture<{@getGenericAwareReturnType(docConfig)}> future = {@methodFutureCall(docConfig, apiName)}; - // Do something{@BREAK} - @end - @if docConfig.isPagedVariant - for ({@docConfig.getReturnType} elements : {@methodCallSampleCode(docConfig, apiName)}) { - // doThingsWith(elements); - } - @else - {@callResultSampleCode(docConfig.getReturnType)}{@methodCallSampleCode(docConfig, apiName)}; - @end - @end +@snippet decorateSampleCode(apiMethod, coreSampleCode) + try ({@apiMethod.apiClassName} {@apiMethod.apiVariableName} = \ + {@apiMethod.apiClassName}.createWithDefaults()) { + {@coreSampleCode} + } +@end + +@snippet pagedIterableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + for ({@apiMethod.listMethod.resourceTypeName} element : {@sampleSyncMethodCall(apiMethod)}) { + // doThingsWith(element); + } +@end + +@snippet pagedCallableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + ListenableFuture<{@apiMethod.responseTypeName}> future = {@sampleFutureMethodCall(apiMethod)}; + // Do something + for ({@apiMethod.listMethod.resourceTypeName} element : future.get()) { + // doThingsWith(element); + } +@end + +@snippet unpagedListCallableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + while (true) { + {@apiMethod.responseTypeName} response = \ + {@apiMethod.apiVariableName}.{@apiMethod.name}().call(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}); + for ({@apiMethod.listMethod.resourceTypeName} element : \ + response.{@apiMethod.unpagedListCallableMethod.fnGetResourceListCall}()) { + // doThingsWith(element); } - @end + String nextPageToken = response.getNextPageToken(); + if (!Strings.isNullOrEmpty(nextPageToken)) { + request = request.toBuilder().setPageToken(nextPageToken).build(); + } else { + break; + } + } @end -# Helper functions for generateMethodSampleCode() +@snippet syncMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + @if apiMethod.hasReturnValue + {@apiMethod.responseTypeName} response = {@sampleSyncMethodCall(apiMethod)}; + @else + {@sampleSyncMethodCall(apiMethod)}; + @end +@end -@private getGenericAwareReturnType(docConfig) - @if docConfig.isPagedVariant - PageAccessor<{@docConfig.getGenericAwareReturnType}> +@snippet callableMethodSampleCode(apiMethod) + {@initCode(apiMethod.initCode)} + ListenableFuture<{@apiMethod.callableMethod.genericAwareResponseType}> future = {@sampleFutureMethodCall(apiMethod)}; + // Do something + @if apiMethod.hasReturnValue + {@apiMethod.responseTypeName} response = future.get(); @else - {@docConfig.getGenericAwareReturnType} + future.get(); @end @end -@private getResourcesListCall(resourcesField) - get{@context.lowerUnderscoreToUpperCamel(resourcesField.getSimpleName)}List() +@private sampleFutureMethodCall(apiMethod) + {@apiMethod.apiVariableName}.{@apiMethod.name}().futureCall(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) +@end + +@private sampleSyncMethodCall(apiMethod) + {@apiMethod.apiVariableName}.{@apiMethod.name}(\ + {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) +@end + +@private sampleMethodCallArgList(fieldSettings) + @join fieldSetting : fieldSettings on ", " + {@fieldSetting.identifier} + @end @end -# Generate argument initialization code for API call @private initCode(initCodeSpec) - @join line : initCodeSpec.getLines() - @switch line.getLineType.toString() + @join line : initCodeSpec.lines + @switch line.lineType.toString @case "StructureInitLine" {@initLineStructure(line)} @case "ListInitLine" @@ -65,125 +90,42 @@ @case "SimpleInitLine" {@initLineSimple(line)} @default - {@unhandledCase()} + $unhandledCase: {@line.lineType.toString}$ @end @end @end -# Generate a Protobuf message argument @private initLineStructure(line) - {@context.typeName(line.getType)} {@formattedIdentifier(line)} = {@context.typeName(line.getType)}.newBuilder() - @join fieldSetting : line.getFieldSettings - @let setCallName = setCallName(fieldSetting.getType, fieldSetting.getFieldName.toUpperCamel) - {@EMPTY} .{@setCallName}({@formattedIdentifier(fieldSetting)}) - @end + {@line.typeName} {@line.identifier} = {@line.typeName}.newBuilder() + @join fieldSetting : line.fieldSettings + {@EMPTY} .{@fieldSetting.fnSetFunctionCallName}({@fieldSetting.identifier}) @end {@EMPTY} .build(); @end -# Generate a List argument @private initLineList(line) - List<{@context.basicTypeNameBoxed(line.getElementType)}> {@formattedIdentifier(line)} = Arrays.asList({@initList(line)}); + List<{@line.elementTypeName}> {@line.identifier} = \ + Arrays.asList({@argList(line.elementIdentifiers)}); @end -# Generate a Map argument @private initLineMap(line) - Map<{@context.basicTypeNameBoxed(line.getKeyType)}, {@context.basicTypeNameBoxed(line.getValueType)}> {@formattedIdentifier(line)} = new HashMap<>(); - @join key : line.getElementIdentifierKeys vertical - @let identifierValue = line.getElementIdentifierValue(key) - {@formattedIdentifier(line)}.put({@context.renderPrimitiveValue(line.getKeyType, key)}, {@identifierValue.toLowerCamel}); - @end - @end -@end - -# Helper method for initLineList() -@private initList(line) - @join identifier : line.getElementIdentifiers on ", " - {@identifier.toLowerCamel} + Map<{@line.keyTypeName}, {@line.valueTypeName}> {@line.identifier} = new HashMap<>(); + @join mapEntry : line.initEntries vertical + {@line.identifier}.put({@mapEntry.key}, {@mapEntry.value}); @end @end -# Generate a simple argument @private initLineSimple(line) - {@context.typeName(line.getType)} {@formattedIdentifier(line)} = {@initValue(line)}; -@end - -# Properly format an identifier for this language -@private formattedIdentifier(lineOrFieldSetting) - @if lineOrFieldSetting.getInitValueConfig.hasFormattingConfig - formatted{@lineOrFieldSetting.getIdentifier.toUpperCamel} - @else - {@lineOrFieldSetting.getIdentifier.toLowerCamel} - @end -@end - -# Value for simple argument -@private initValue(line) - @let metadata = line.getInitValueConfig - @if metadata.hasFormattingConfig() - {@metadata.getApiWrapperName}.{@formatResourceFunctionName(metadata.getCollectionConfig)}({@formatResourceFunctionArgs(metadata.getCollectionConfig)}) - @else - @if metadata.hasInitialValue() - {@context.renderPrimitiveValue(line.getType, metadata.getInitialValue)} - @else - {@context.zeroValue(line.getType)} - @end - @end - @end + {@line.typeName} {@line.identifier} = {@renderInitValue(line.initValue)}; @end -# Format arguments for resource function call in sample -@private formatResourceFunctionArgs(collectionConfig) - @join param : collectionConfig.getNameTemplate.vars() on ", " - "[{@context.lowerUnderscoreToUpperUnderscore(param)}]" - @end -@end - -# Optionally render the return value from the API method call -@private callResultSampleCode(returnType) - @if returnType.isEmpty - @else - {@returnType} response = {@""} - @end -@end - -@private methodFutureCall(docConfig, apiName) - {@apiName}.{@methodCallName(docConfig)}().futureCall({@argList(docConfig.getInitCode.getArgFields)}) -@end - -# Render the API method call itself -@private methodCallSampleCode(docConfig, apiName) - @if docConfig.isUnpagedListCallableVariant - {@apiName}.{@methodCallName(docConfig)}().call({@argList(docConfig.getInitCode.getArgFields)}) - @else - @if docConfig.isCallableVariant - future.get() - @else - {@apiName}.{@methodCallName(docConfig)}({@argList(docConfig.getInitCode.getArgFields)}) - @end - @end -@end - -# Render the name of the method call -@private methodCallName(docConfig) - @if docConfig.isCallableVariant - {@methodCallNameIter(docConfig)}Callable - @else - {@docConfig.getMethodName} - @end -@end - -@private methodCallNameIter(docConfig) - @if docConfig.isPagedVariant - {@docConfig.getMethodName}Paged - @else - {@docConfig.getMethodName} - @end -@end - -# Generate argument list -@private argList(fieldSettings) - @join fieldSetting : fieldSettings on ", " - {@formattedIdentifier(fieldSetting)} +@private renderInitValue(initValue) + @switch initValue.type + @case "SimpleInitValueView" + {@initValue.initialValue} + @case "FormattedInitValueView" + {@initValue.apiWrapperName}.{@initValue.formatFunctionName}({@argList(initValue.formatArgs)}) + @default + $unhandledCase: {@initValue.type}$ @end @end diff --git a/src/main/resources/com/google/api/codegen/java/mvvm_common.snip b/src/main/resources/com/google/api/codegen/java/mvvm_common.snip deleted file mode 100644 index 6192801030..0000000000 --- a/src/main/resources/com/google/api/codegen/java/mvvm_common.snip +++ /dev/null @@ -1,27 +0,0 @@ -@snippet license() - /* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -@end - -@snippet paramList(params) - @join param : params on ", " - {@param.typeName} {@param.name} - @end -@end - -@snippet argList(args) - @join arg : args on ", " - {@arg} - @end -@end diff --git a/src/main/resources/com/google/api/codegen/java/package-info.snip b/src/main/resources/com/google/api/codegen/java/package-info.snip index a2efe9ec62..4523928682 100644 --- a/src/main/resources/com/google/api/codegen/java/package-info.snip +++ b/src/main/resources/com/google/api/codegen/java/package-info.snip @@ -1,56 +1,50 @@ @extends "java/common.snip" -@extends "java/main.snip" +@extends "java/method_sample.snip" -@snippet generateFilename() - package-info.java -@end - -@snippet generateDocument(fragmentList) +@snippet generate(packageInfo) {@license()} - {@packageJavaDoc(fragmentList)} + /** + * A client to {@packageInfo.serviceTitle}. + * + * The interfaces provided are listed below, along with a usage sample + * + @join xapiClassDoc : packageInfo.serviceDocs + {@serviceShortDoc(xapiClassDoc)} + @end + */ - package {@context.getApiConfig.getPackageName}; + package {@packageInfo.packageName}; @end -@snippet generateFragment(service) - @let firstFlattenedMethod = context.getFirstFlattenedMethod(service), \ - # TODO: support the case where the API has no flattened methods. - firstFlattenedMethodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(firstFlattenedMethod), \ - fields = firstFlattenedMethodConfig.getFlattening().getFlatteningGroups().get(0), \ - fieldNamePatterns = firstFlattenedMethodConfig.getFieldNamePatterns() - {@javaDocLinesFromStr(context.getMultilineHeading(context.getApiWrapperName(service)))} - * - {@javaDocLinesFromStr(serviceDocString(service))} - * - * Sample for {@context.getApiWrapperName(service)}: - *
-     * 
-    @join commentLine : context.java.getJavaDocLines(generateMethodSampleCode(context.newJavaDocConfigBuilder \
-                               .setApiName(context.getApiWrapperName(service)) \
-                               .setMethodName(context.upperCamelToLowerCamel(firstFlattenedMethod.getSimpleName)) \
-                               .setReturnType(context.returnTypeOrEmpty(firstFlattenedMethod.getOutputType)) \
-                               .setFieldInitCode(context, service, firstFlattenedMethod, fields) \
-                               .setFieldParams(context, fields) \
-                               .setPagedVariant({@FALSE}) \
-                               .setCallableVariant({@FALSE}) \
-                               .build))
-      {@commentLine}
-    @end
-    {@EMPTY} * 
-     * 
- * +@private serviceShortDoc(xapiClassDoc) + @let coreSampleCode = syncMethodSampleCode(xapiClassDoc.exampleApiMethod), \ + decoratedSampleCode = decorateSampleCode(xapiClassDoc.exampleApiMethod, coreSampleCode) + {@renderServiceShortDoc(xapiClassDoc, decoratedSampleCode)} @end @end -@private packageJavaDoc(fragmentList) - /** - * A client to {@context.getTitle()}. - * - * The interfaces provided are listed below, along with a usage sample +@private renderServiceShortDoc(xapiClassDoc, exampleMethodSampleCode) + @join commentLine : util.getMultilineHeading(xapiClassDoc.apiClassName) + {@""} * {@commentLine} + @end + # The join above doesn't properly add a newline on the end, so we need to force it + {@""} + {@""} * + * Service Description: {@xapiClassDoc.firstLine} + @if xapiClassDoc.remainingLines + @join commentLine : xapiClassDoc.remainingLines + {@""} * {@commentLine} + @end + @end * - @join fragment : fragmentList - {@fragment} + * Sample for {@xapiClassDoc.apiClassName}: + *
+   * 
+  @join sampleLine : util.getDocLines(exampleMethodSampleCode)
+    {@""} * {@sampleLine}
   @end
-   */
+   * 
+   * 
+ * @end diff --git a/src/main/resources/com/google/api/codegen/java/settings.snip b/src/main/resources/com/google/api/codegen/java/settings.snip index 55838ecabb..3f38d0cf3a 100644 --- a/src/main/resources/com/google/api/codegen/java/settings.snip +++ b/src/main/resources/com/google/api/codegen/java/settings.snip @@ -1,108 +1,70 @@ @extends "java/common.snip" -@snippet generateFilename(service) - {@settingsClassName(service)}.java -@end - -@snippet generateClass(service, body, imports) +@snippet generate(xsettingsClass) {@license()} - package {@context.getApiConfig.getPackageName}; - - @join import : imports + package {@xsettingsClass.packageName}; + + @join import : xsettingsClass.imports import {@import}; @end - {@body} -@end - -@snippet generateBody(service) - {@alwaysImport()} - - {@autoGenClassWarning()} - {@settingsJavaDoc(service)} + {@settingsDoc(xsettingsClass.doc)} @@javax.annotation.Generated("by GAPIC") - public class {@settingsClassName(service)} extends ServiceApiSettings { - - {@constants(service)} - - {@members(service)} - - {@constructors(service)} - - {@descriptors(service)} - - {@innerBuilderClass(service)} + public class {@xsettingsClass.name} extends ServiceApiSettings { + {@constants(xsettingsClass)} + {@members(xsettingsClass)} + {@constructors(xsettingsClass)} + {@descriptors(xsettingsClass)} + {@innerBuilderClass(xsettingsClass)} } @end -@private alwaysImport() fill - {@context.addImport("com.google.api.gax.core.ConnectionSettings")} - {@context.addImport("com.google.api.gax.core.RetrySettings")} - {@context.addImport("com.google.api.gax.grpc.ApiCallSettings")} - {@context.addImport("com.google.api.gax.grpc.SimpleCallSettings")} - {@context.addImport("com.google.api.gax.grpc.ServiceApiSettings")} - {@context.addImport("com.google.auth.Credentials")} - {@context.addImport("com.google.common.collect.ImmutableList")} - {@context.addImport("com.google.common.collect.ImmutableMap")} - {@context.addImport("com.google.common.collect.ImmutableSet")} - {@context.addImport("com.google.common.collect.Lists")} - {@context.addImport("com.google.common.collect.Sets")} - {@context.addImport("io.grpc.ManagedChannel")} - {@context.addImport("io.grpc.Status")} - {@context.addImport("org.joda.time.Duration")} - {@context.addImport("java.io.IOException")} - {@context.addImport("java.util.List")} - {@context.addImport("java.util.concurrent.ScheduledExecutorService")} -@end - -@private settingsJavaDoc(service) - @let settingsVariable = context.upperCamelToLowerCamel(settingsClassName(service)), \ - firstFlattenedMethod = context.getFirstFlattenedMethod(service) - /** - * Settings class to configure an instance of {@@link {@context.getApiWrapperName(service)}}. - * - *

The default instance has everything set to sensible defaults: - * - *

    - *
  • The default service address ({@context.getServiceConfig.getServiceAddress(service)}) and default port ({@context.getServiceConfig.getServicePort()}) - * are used. - *
  • Credentials are acquired automatically through Application Default Credentials. - *
  • Retries are configured for idempotent methods but not for non-idempotent methods. - *
- * - *

The builder of this class is recursive, so contained classes are themselves builders. - * When build() is called, the tree of builders is called to create the complete settings - * object. For example, to set the total timeout of {@firstFlattenedMethod.getSimpleName} to 30 seconds: - * - *

-     * 
-     * {@settingsClassName(service)}.Builder {@settingsVariable}Builder =
-     *     {@settingsClassName(service)}.defaultBuilder();
-     * {@settingsVariable}Builder.{@firstFlattenedMethod.getSimpleName}Settings().getRetrySettingsBuilder()
-     *     .setTotalTimeout(Duration.standardSeconds(30));
-     * {@settingsClassName(service)} {@settingsVariable} = {@settingsVariable}Builder.build();
-     * 
-     * 
- */ - @end +@private settingsDoc(doc) + // AUTO-GENERATED DOCUMENTATION AND CLASS + /** + * Settings class to configure an instance of {@@link {@doc.apiClassName}}. + * + *

The default instance has everything set to sensible defaults: + * + *

    + *
  • The default service address ({@doc.serviceAddress}) and default port ({@doc.servicePort}) + * are used. + *
  • Credentials are acquired automatically through Application Default Credentials. + *
  • Retries are configured for idempotent methods but not for non-idempotent methods. + *
+ * + *

The builder of this class is recursive, so contained classes are themselves builders. + * When build() is called, the tree of builders is called to create the complete settings + * object. For example, to set the total timeout of {@doc.exampleApiMethodName} to 30 seconds: + * + *

+   * 
+   * {@doc.settingsClassName}.Builder {@doc.settingsBuilderVarName} =
+   *     {@doc.settingsClassName}.defaultBuilder();
+   * {@doc.settingsBuilderVarName}.{@doc.exampleApiMethodSettingsGetter}().getRetrySettingsBuilder()
+   *     .setTotalTimeout(Duration.standardSeconds(30));
+   * {@doc.settingsClassName} {@doc.settingsVarName} = {@doc.settingsBuilderVarName}.build();
+   * 
+   * 
+ */ @end -@private constants(service) +@private constants(xsettingsClass) /** * The default address of the service. */ - public static final String DEFAULT_SERVICE_ADDRESS = "{@context.getServiceConfig.getServiceAddress(service)}"; + public static final String DEFAULT_SERVICE_ADDRESS = "{@xsettingsClass.serviceAddress}"; /** * The default port of the service. */ - public static final int DEFAULT_SERVICE_PORT = {@context.getServiceConfig.getServicePort()}; + public static final int DEFAULT_SERVICE_PORT = {@xsettingsClass.servicePort}; /** * The default scopes of the service. */ public static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() - @join scope : context.getServiceConfig.getAuthScopes(service) + @join scope : {@xsettingsClass.authScopes} .add("{@scope}") @end .build(); @@ -116,310 +78,356 @@ .setPort(DEFAULT_SERVICE_PORT) .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) .build(); + {@""} @end -@private members(service) - {@methodMembers(service)} - - {@methodGetters(service)} - - @let className = settingsClassName(service) - /** - * Returns a builder for this class with recommended defaults. - */ - public static Builder defaultBuilder() { - return Builder.createDefault(); - } +@private members(xsettingsClass) + {@methodMembers(xsettingsClass)} + {@methodGetters(xsettingsClass)} + /** + * Returns a builder for this class with recommended defaults. + */ + public static Builder defaultBuilder() { + return Builder.createDefault(); + } - /** - * Returns a new builder for this class. - */ - public static Builder newBuilder() { - return new Builder(); - } + /** + * Returns a new builder for this class. + */ + public static Builder newBuilder() { + return new Builder(); + } - /** - * Returns a builder containing all the values of this settings class. - */ - public Builder toBuilder() { - return new Builder(this); - } - @end + /** + * Returns a builder containing all the values of this settings class. + */ + public Builder toBuilder() { + return new Builder(this); + } + {@""} @end -@private methodMembers(service) - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - @if {@isPageStreaming} - @let pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - dummy = context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings") - private final PageStreamingCallSettings<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> - {@methodName}Settings; - - @end - @else - @if {@isBundling} - @let bundling = methodConfig.getBundling(), \ - dummy = context.addImport("com.google.api.gax.grpc.BundlingCallSettings") - private final BundlingCallSettings<{@inTypeName}, {@outTypeName}> {@methodName}Settings; - @end - @else - private final SimpleCallSettings<{@inTypeName}, {@outTypeName}> {@methodName}Settings; - @end - @end +@private methodMembers(xsettingsClass) + @join settings : xsettingsClass.callSettings + @switch settings.type.toString + @case "SimpleApiCallable" + private final SimpleCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; + @case "PagedApiCallable" + private final PageStreamingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.memberName}; + @case "BundlingApiCallable" + private final BundlingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; + @default + $unhandledCase: {@settings.type.toString}$ @end @end + {@BREAK} @end -@private methodGetters(service) - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - /** - * Returns the object with the settings used for calls to {@methodName}. - */ - @if {@isPageStreaming} - @let pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - dummy = context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings") - public PageStreamingCallSettings<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> - {@methodName}Settings() { - return {@methodName}Settings; - } - - @end - @else - @if {@isBundling} - @let bundling = methodConfig.getBundling(), \ - dummy = context.addImport("com.google.api.gax.grpc.BundlingCallSettings") - public BundlingCallSettings<{@inTypeName}, {@outTypeName}> {@methodName}Settings() { - return {@methodName}Settings; - } - - @end - @else - public SimpleCallSettings<{@inTypeName}, {@outTypeName}> {@methodName}Settings() { - return {@methodName}Settings; - } - - @end - @end +@private methodGetters(xsettingsClass) + @join settings : xsettingsClass.callSettings + /** + * Returns the object with the settings used for calls to {@settings.methodName}. + */ + @switch settings.type.toString + @case "SimpleApiCallable" + public SimpleCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "PagedApiCallable" + public PageStreamingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "BundlingApiCallable" + public BundlingCallSettings<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @default + $unhandledCase: {@settings.type.toString}$ @end + {@""} @end @end -@private constructors(service) - @let className = settingsClassName(service) - private {@className}(Builder settingsBuilder) throws IOException { - super(settingsBuilder.getChannelProvider(), - settingsBuilder.getExecutorProvider(), - settingsBuilder.getGeneratorName(), - settingsBuilder.getGeneratorVersion(), - settingsBuilder.getClientLibName(), - settingsBuilder.getClientLibVersion()); - - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName) - {@methodName}Settings = settingsBuilder.{@methodName}Settings().build(); - @end - @end - } - @end +@private constructors(xsettingsClass) + private {@xsettingsClass.name}(Builder settingsBuilder) throws IOException { + super(settingsBuilder.getChannelProvider(), + settingsBuilder.getExecutorProvider(), + settingsBuilder.getGeneratorName(), + settingsBuilder.getGeneratorVersion(), + settingsBuilder.getClientLibName(), + settingsBuilder.getClientLibVersion()); + + @join settings : xsettingsClass.callSettings + {@settings.memberName} = settingsBuilder.{@settings.fnGetterName}().build(); + @end + } + {@""} @end -@private descriptors(service) - {@pageStreamingDescriptors(service)} - {@bundlingDescriptors(service)} +@private descriptors(xsettingsClass) + {@pageStreamingDescriptors(xsettingsClass)} + {@bundlingDescriptors(xsettingsClass)} @end -@private pageStreamingDescriptors(service) - @let interfaceConfig = context.getApiConfig.getInterfaceConfig(service), \ - dummy = context.addImport("com.google.api.gax.grpc.PageStreamingDescriptor") - @join method : context.messages.filterPageStreamingMethods(interfaceConfig, service.getMethods) - @let methodConstant = context.upperCamelToUpperUnderscore(method.getSimpleName), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - pageStreaming = interfaceConfig.getMethodConfig(method).getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - tokenTypeName = context.typeName(pageStreaming.getResponseTokenField.getType) - private static PageStreamingDescriptor<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> {@methodConstant}_PAGE_STR_DESC = - new PageStreamingDescriptor<{@inTypeName}, {@outTypeName}, {@resourceTypeName}>() { - @@Override - public Object emptyToken() { - return {@context.defaultTokenValue(pageStreaming.getRequestTokenField())}; - } - @@Override - public {@inTypeName} injectToken( - {@inTypeName} payload, Object token) { - return {@inTypeName} - .newBuilder(payload) - .{@setCallName(pageStreaming.getRequestTokenField())}(({@tokenTypeName}) token) - .build(); - } - @@Override - public Object extractNextToken({@outTypeName} payload) { - return payload.{@getCallName(pageStreaming.getResponseTokenField())}(); - } - @@Override - public Iterable<{@resourceTypeName}> extractResources({@outTypeName} payload) { - return payload.{@getCallName(pageStreaming.getResourcesField())}(); - } - }; - - @end - @end +@private pageStreamingDescriptors(xsettingsClass) + @join desc : xsettingsClass.pageStreamingDescriptors + private static PageStreamingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}, {@desc.resourceTypeName}> {@desc.name} = + new PageStreamingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}, {@desc.resourceTypeName}>() { + @@Override + public Object emptyToken() { + return {@desc.defaultTokenValue}; + } + @@Override + public {@desc.requestTypeName} injectToken({@desc.requestTypeName} payload, Object token) { + return {@desc.requestTypeName} + .newBuilder(payload) + .{@desc.fnSetRequestToken}(({@desc.tokenTypeName}) token) + .build(); + } + @@Override + public Object extractNextToken({@desc.responseTypeName} payload) { + return payload.{@desc.fnGetResponseToken}(); + } + @@Override + public Iterable<{@desc.resourceTypeName}> extractResources({@desc.responseTypeName} payload) { + return payload.{@desc.fnGetResourcesField}(); + } + }; + {@""} @end @end -@private bundlingDescriptors(service) - @let interfaceConfig = context.getApiConfig.getInterfaceConfig(service) - @join method : context.messages.filterBundlingMethods(interfaceConfig, service.getMethods) - @let methodConstant = context.upperCamelToUpperUnderscore(method.getSimpleName), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - bundling = interfaceConfig.getMethodConfig(method).getBundling(), \ - dummy = context.addImport("com.google.api.gax.grpc.BundlingDescriptor"), \ - dummy2 = context.addImport("java.util.Collection"), \ - dummy3 = context.addImport("com.google.api.gax.grpc.RequestIssuer"), \ - dummy4 = context.addImport("java.util.ArrayList") - private static BundlingDescriptor<{@inTypeName}, {@outTypeName}> {@methodConstant}_BUNDLING_DESC = - new BundlingDescriptor<{@inTypeName}, {@outTypeName}>() { - @@Override - public String getBundlePartitionKey({@inTypeName} request) { - return {@partitionKeyCode(bundling)}; - } +@private bundlingDescriptors(xsettingsClass) + @join desc : xsettingsClass.bundlingDescriptors + private static BundlingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}> {@desc.name} = + new BundlingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}>() { + @@Override + public String getBundlePartitionKey({@desc.requestTypeName} request) { + return {@partitionKeyCode(desc)}; + } - @@Override - public {@inTypeName} mergeRequests(Collection<{@inTypeName}> requests) { - {@inTypeName} firstRequest = requests.iterator().next(); - - {@context.typeName(bundling.getBundledField.getType)} elements = new ArrayList<>(); - for ({@inTypeName} request : requests) { - elements.addAll(request.{@getCallName(bundling.getBundledField)}()); - } - - {@inTypeName} bundleRequest = - {@inTypeName}.newBuilder() - {@setDescriminatorFields(bundling)} - .{@setCallName(bundling.getBundledField)}(elements) - .build(); - return bundleRequest; - } + @@Override + public {@desc.requestTypeName} mergeRequests(Collection<{@desc.requestTypeName}> requests) { + {@desc.requestTypeName} firstRequest = requests.iterator().next(); - @@Override - public void splitResponse( - {@outTypeName} bundleResponse, - Collection> bundle) { - # TODO(garrettjones) support case of no subresponse_field (e.g. Logging) - int bundleMessageIndex = 0; - for (RequestIssuer<{@inTypeName}, {@outTypeName}> responder : bundle) { - {@context.typeName(bundling.getSubresponseField.getType)} subresponseElements = new ArrayList<>(); - int subresponseCount = responder.getRequest().{@getCountCallName(bundling.getBundledField)}(); - for (int i = 0; i < subresponseCount; i++) { - subresponseElements.add(bundleResponse.{@getIndexCallName(bundling.getSubresponseField)}(bundleMessageIndex)); - bundleMessageIndex += 1; - } - {@outTypeName} response = - {@outTypeName}.newBuilder().{@setCallName(bundling.getSubresponseField)}(subresponseElements).build(); - responder.setResponse(response); - } - } + {@desc.bundledFieldTypeName} elements = new ArrayList<>(); + for ({@desc.requestTypeName} request : requests) { + elements.addAll(request.{@desc.fnGetBundledField}()); + } - @@Override - public void splitException( - Throwable throwable, - Collection> bundle) { - for (RequestIssuer<{@inTypeName}, {@outTypeName}> responder : bundle) { - responder.setException(throwable); - } - } + {@desc.requestTypeName} bundleRequest = + {@desc.requestTypeName}.newBuilder() + {@fieldCopyCalls(desc.discriminatorFieldCopies)} + .{@desc.fnSetBundledField}(elements) + .build(); + return bundleRequest; + } - @@Override - public long countElements({@inTypeName} request) { - return request.{@getCountCallName(bundling.getBundledField)}(); + @@Override + public void splitResponse( + {@desc.responseTypeName} bundleResponse, + Collection> bundle) { + # TODO(garrettjones) support case of no subresponse_field (e.g. Logging) + int bundleMessageIndex = 0; + for (RequestIssuer<{@desc.requestTypeName}, {@desc.responseTypeName}> responder : bundle) { + {@desc.subresponseTypeName} subresponseElements = new ArrayList<>(); + int subresponseCount = responder.getRequest().{@desc.fnGetBundledFieldCount}(); + for (int i = 0; i < subresponseCount; i++) { + subresponseElements.add(bundleResponse.{@desc.fnGetSubresponseByIndex}(bundleMessageIndex)); + bundleMessageIndex += 1; } + {@desc.responseTypeName} response = + {@desc.responseTypeName}.newBuilder().{@desc.fnSetSubresponse}(subresponseElements).build(); + responder.setResponse(response); + } + } - @@Override - public long countBytes({@inTypeName} request) { - return request.getSerializedSize(); - } - }; + @@Override + public void splitException( + Throwable throwable, + Collection> bundle) { + for (RequestIssuer<{@desc.requestTypeName}, {@desc.responseTypeName}> responder : bundle) { + responder.setException(throwable); + } + } - @end - @end + @@Override + public long countElements({@desc.requestTypeName} request) { + return request.{@desc.fnGetBundledFieldCount}(); + } + + @@Override + public long countBytes({@desc.requestTypeName} request) { + return request.getSerializedSize(); + } + }; + {@""} @end @end -@private partitionKeyCode(bundling) - {@context.partitionKeyCode(bundling.getDiscriminatorFields)} +@private partitionKeyCode(bundlingDesc) + @join partitionKey : bundlingDesc.partitionKeys on " + " + request.{@partitionKey.fnGetCallName}() + {@partitionKey.separatorLiteral} + @end @end -@private setDescriminatorFields(bundling) - @join fieldSelector : bundling.getDiscriminatorFields - # Note: This only supports field selectors with a single field. - @let field = fieldSelector.getLastField - .{@setCallName(field)}(firstRequest.{@getCallName(field)}()) - @end +@private fieldCopyCalls(fieldCopies) + @join fieldCopy : fieldCopies + .{@fieldCopy.fnSetFunctionCallName}(firstRequest.{@fieldCopy.fnGetFunctionCallName}()) @end @end -@private innerBuilderClass(service) +@private innerBuilderClass(xsettingsClass) /** - * Builder for {@settingsClassName(service)}. + * Builder for {@xsettingsClass.name}. */ public static class Builder extends ServiceApiSettings.Builder { private final ImmutableList methodSettingsBuilders; - {@builderMembers(service)} + {@builderMembers(xsettingsClass)} - {@builderConstants(service)} + {@builderConstants(xsettingsClass)} - {@builderConstructors(service)} + {@builderConstructors(xsettingsClass)} - {@builderMethods(service)} + {@builderMethods(xsettingsClass)} } @end -@private builderMembers(service) - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - @if {@isPageStreaming} - @let pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - dummy = context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings") - private PageStreamingCallSettings.Builder<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> - {@methodName}Settings; - @end - @else - @if {@isBundling} - @let bundling = methodConfig.getBundling(), \ - dummy = context.addImport("com.google.api.gax.grpc.BundlingCallSettings") - private BundlingCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings; - @end - @else - private SimpleCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings; +@private builderMembers(xsettingsClass) + @join settings : xsettingsClass.callSettings + @switch settings.type.toString + @case "SimpleApiCallable" + private SimpleCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; + @case "PagedApiCallable" + private PageStreamingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.memberName}; + @case "BundlingApiCallable" + private BundlingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.memberName}; + @default + $unhandledCase: {@settings.type.toString}$ + @end + @end +@end + +@private builderConstants(xsettingsClass) + private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; + + static { + ImmutableMap.Builder> definitions = ImmutableMap.builder(); + @join retryCodesDef : xsettingsClass.retryCodesDefinitions + definitions.put( + "{@retryCodesDef.key}", + Sets.immutableEnumSet(Lists.newArrayList({@statusCodes(retryCodesDef.codes)}))); + @end + RETRYABLE_CODE_DEFINITIONS = definitions.build(); + } + + private static final ImmutableMap RETRY_PARAM_DEFINITIONS; + + static { + ImmutableMap.Builder definitions = ImmutableMap.builder(); + RetrySettings.Builder settingsBuilder = null; + @join retryParamsDef : xsettingsClass.retryParamsDefinitions + settingsBuilder = RetrySettings.newBuilder() + .setInitialRetryDelay(Duration.millis({@retryParamsDef.initialRetryDelay.getMillis}L)) + .setRetryDelayMultiplier({@retryParamsDef.retryDelayMultiplier}) + .setMaxRetryDelay(Duration.millis({@retryParamsDef.maxRetryDelay.getMillis}L)) + .setInitialRpcTimeout(Duration.millis({@retryParamsDef.initialRpcTimeout.getMillis}L)) + .setRpcTimeoutMultiplier({@retryParamsDef.rpcTimeoutMultiplier}) + .setMaxRpcTimeout(Duration.millis({@retryParamsDef.maxRpcTimeout.getMillis}L)) + .setTotalTimeout(Duration.millis({@retryParamsDef.totalTimeout.getMillis}L)); + definitions.put("{@retryParamsDef.key}", settingsBuilder); + @end + RETRY_PARAM_DEFINITIONS = definitions.build(); + } +@end + +@private statusCodes(codes) + @join code : codes on ", " + Status.Code.{@code} + @end +@end + +@private builderConstructors(xsettingsClass) + private Builder() { + super(DEFAULT_CONNECTION_SETTINGS); + + @join settings : xsettingsClass.callSettings + @switch settings.type.toString + @case "SimpleApiCallable" + {@settings.memberName} = SimpleCallSettings.newBuilder({@settings.grpcTypeName}.{@settings.grpcMethodConstant}); + @case "PagedApiCallable" + {@settings.memberName} = PageStreamingCallSettings.newBuilder( + {@settings.grpcTypeName}.{@settings.grpcMethodConstant}, + {@settings.pageStreamingDescriptorName}); + @case "BundlingApiCallable" + {@settings.memberName} = BundlingCallSettings.newBuilder( + {@settings.grpcTypeName}.{@settings.grpcMethodConstant}, + {@settings.bundlingDescriptorName}) + .setBundlingSettingsBuilder(BundlingSettings.newBuilder()); + @default + $unhandledCase: {@settings.type.toString}$ + @end + {@BREAK} + @end + methodSettingsBuilders = ImmutableList.of( + @join settings : xsettingsClass.callSettings vertical on ",".add(BREAK) + {@settings.memberName} @end + ); + } + + private static Builder createDefault() { + Builder builder = new Builder(); + @join settings : xsettingsClass.callSettings + {@""} + @switch settings.type.toString + @case "SimpleApiCallable" + @case "PagedApiCallable" + @case "BundlingApiCallable" + builder.{@settings.fnGetterName}().getBundlingSettingsBuilder() + .setElementCountThreshold({@settings.bundlingConfig.elementCountThreshold}) + .setElementCountLimit({@settings.bundlingConfig.elementCountLimit}) + .setRequestByteThreshold({@settings.bundlingConfig.requestByteThreshold}) + .setRequestByteLimit({@settings.bundlingConfig.requestByteLimit}) + .setDelayThreshold(Duration.millis({@settings.bundlingConfig.delayThresholdMillis})) + .setBlockingCallCountThreshold(1); + @default + $unhandledCase: {@settings.type.toString}$ @end + builder.{@settings.fnGetterName}() + .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("{@settings.retryCodesName}")) + .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("{@settings.retryParamsName}")); @end - @end + + return builder; + } + + private Builder({@xsettingsClass.name} settings) { + super(settings); + + @join settings : xsettingsClass.callSettings + {@settings.memberName} = settings.{@settings.memberName}.toBuilder(); + @end + + methodSettingsBuilders = ImmutableList.of( + @join settings : xsettingsClass.callSettings vertical on ",".add(BREAK) + {@settings.memberName} + @end + ); + } @end -@private builderMethods(service) +@private builderMethods(xsettingsClass) @@Override protected ConnectionSettings getDefaultConnectionSettings() { return DEFAULT_CONNECTION_SETTINGS; @@ -470,210 +478,33 @@ return this; } - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - inTypeName = context.typeName(method.getInputType), \ - outTypeName = context.typeName(method.getOutputType), \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - /** - * Returns the builder for the settings used for calls to {@methodName}. - */ - @if {@isPageStreaming} - @let pageStreaming = methodConfig.getPageStreaming(), \ - resourceTypeName = context.basicTypeNameBoxed(pageStreaming.getResourcesField().getType()), \ - dummy = context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings") - public PageStreamingCallSettings.Builder<{@inTypeName}, {@outTypeName}, {@resourceTypeName}> - {@methodName}Settings() { - return {@methodName}Settings; - } - - @end - @else - @if {@isBundling} - @let bundling = methodConfig.getBundling(), \ - dummy = context.addImport("com.google.api.gax.grpc.BundlingCallSettings") - public BundlingCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings() { - return {@methodName}Settings; - } - - @end - @else - public SimpleCallSettings.Builder<{@inTypeName}, {@outTypeName}> {@methodName}Settings() { - return {@methodName}Settings; - } - - @end - @end + @join settings : xsettingsClass.callSettings + /** + * Returns the builder for the settings used for calls to {@settings.methodName}. + */ + @switch settings.type.toString + @case "SimpleApiCallable" + public SimpleCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "PagedApiCallable" + public PageStreamingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @case "BundlingApiCallable" + public BundlingCallSettings.Builder<{@settings.requestTypeName}, \ + {@settings.responseTypeName}> {@settings.fnGetterName}() { + return {@settings.memberName}; + } + @default + $unhandledCase: {@settings.type.toString}$ @end + {@""} @end @@Override - public {@settingsClassName(service)} build() throws IOException { - return new {@settingsClassName(service)}(this); + public {@xsettingsClass.name} build() throws IOException { + return new {@xsettingsClass.name}(this); } @end - -@private builderConstants(service) - @let interfaceConfig = context.getApiConfig.getInterfaceConfig(service) - private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; - - static { - ImmutableMap.Builder> definitions = ImmutableMap.builder(); - @join retryDef : context.entrySet(interfaceConfig.getRetryCodesDefinition) - definitions.put( - "{@retryDef.getKey}", - Sets.immutableEnumSet(Lists.newArrayList({@statusCodes(retryDef.getValue)}))); - @end - RETRYABLE_CODE_DEFINITIONS = definitions.build(); - } - - private static final ImmutableMap RETRY_PARAM_DEFINITIONS; - - static { - ImmutableMap.Builder definitions = ImmutableMap.builder(); - RetrySettings.Builder settingsBuilder = null; - @join retryDef : context.entrySet(interfaceConfig.getRetrySettingsDefinition) - settingsBuilder = RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.millis({@retryDef.getValue.getInitialRetryDelay.getMillis}L)) - .setRetryDelayMultiplier({@retryDef.getValue.getRetryDelayMultiplier}) - .setMaxRetryDelay(Duration.millis({@retryDef.getValue.getMaxRetryDelay.getMillis}L)) - .setInitialRpcTimeout(Duration.millis({@retryDef.getValue.getInitialRpcTimeout.getMillis}L)) - .setRpcTimeoutMultiplier({@retryDef.getValue.getRpcTimeoutMultiplier}) - .setMaxRpcTimeout(Duration.millis({@retryDef.getValue.getMaxRpcTimeout.getMillis}L)) - .setTotalTimeout(Duration.millis({@retryDef.getValue.getTotalTimeout.getMillis}L)); - definitions.put("{@retryDef.getKey}", settingsBuilder); - @end - RETRY_PARAM_DEFINITIONS = definitions.build(); - } - @end -@end - -@private statusCodes(codes) - @join code : codes on ", " - Status.Code.{@code} - @end -@end - -@private builderConstructors(service) - private Builder() { - super(DEFAULT_CONNECTION_SETTINGS); - - @let serviceName = service.getSimpleName, \ - grpcName = context.getGrpcName(service) - @join method : service.getMethods - @let methodConstant = context.upperCamelToUpperUnderscore(method.getSimpleName), \ - methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - retryCodesName = methodConfig.getRetryCodesConfigName, \ - RetrySettingsName = methodConfig.getRetrySettingsConfigName, \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - @if {@isPageStreaming} - @let dummy = {@context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings")} - {@methodName}Settings = PageStreamingCallSettings.newBuilder( - {@grpcName}.METHOD_{@methodConstant}, - {@methodConstant}_PAGE_STR_DESC); - - @end - @else - @if {@isBundling} - @let bundlingConfig = methodConfig.getBundling, \ - dummy = {@context.addImport("com.google.api.gax.grpc.BundlingSettings")} - {@methodName}Settings = BundlingCallSettings.newBuilder( - {@grpcName}.METHOD_{@methodConstant}, - {@methodConstant}_BUNDLING_DESC) - .setBundlingSettingsBuilder(BundlingSettings.newBuilder()); - - @end - @else - {@methodName}Settings = SimpleCallSettings.newBuilder({@grpcName}.METHOD_{@methodConstant}); - - @end - @end - @end - @end - @end - methodSettingsBuilders = ImmutableList.of( - {@settingsList(service)} - ); - } - - private static Builder createDefault() { - Builder builder = new Builder(); - @let serviceName = service.getSimpleName, \ - grpcName = context.getGrpcName(service) - @join method : service.getMethods - @let methodConstant = context.upperCamelToUpperUnderscore(method.getSimpleName), \ - methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - retryCodesName = methodConfig.getRetryCodesConfigName, \ - RetrySettingsName = methodConfig.getRetrySettingsConfigName, \ - isPageStreaming = methodConfig.isPageStreaming, \ - isBundling = methodConfig.isBundling - @if {@isPageStreaming} - @let dummy = {@context.addImport("com.google.api.gax.grpc.PageStreamingCallSettings")} - builder.{@methodName}Settings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("{@retryCodesName}")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("{@RetrySettingsName}")); - - @end - @else - @if {@isBundling} - @let bundlingConfig = methodConfig.getBundling, \ - dummy = {@context.addImport("com.google.api.gax.grpc.BundlingSettings")} - builder.{@methodName}Settings().getBundlingSettingsBuilder() - .setElementCountThreshold({@bundlingConfig.getElementCountThreshold}) - .setElementCountLimit({@bundlingConfig.getElementCountLimit}) - .setRequestByteThreshold({@bundlingConfig.getRequestByteThreshold}) - .setRequestByteLimit({@bundlingConfig.getRequestByteLimit}) - .setDelayThreshold(Duration.millis({@bundlingConfig.getDelayThresholdMillis})) - .setBlockingCallCountThreshold(1); - builder.{@methodName}Settings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("{@retryCodesName}")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("{@RetrySettingsName}")); - - @end - @else - builder.{@methodName}Settings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("{@retryCodesName}")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("{@RetrySettingsName}")); - - @end - @end - @end - @end - @end - return builder; - } - - private Builder({@settingsClassName(service)} settings) { - super(settings); - - @join method : service.getMethods - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - isPageStreaming = methodConfig.isPageStreaming - {@methodName}Settings = settings.{@methodName}Settings.toBuilder(); - @end - @end - - methodSettingsBuilders = ImmutableList.of( - {@settingsList(service)} - ); - } -@end - -@private settingsList(service) - @join method : service.getMethods vertical on ",".add(BREAK) - @let methodName = context.upperCamelToLowerCamel(method.getSimpleName), \ - methodConfig = context.getApiConfig.getInterfaceConfig(service).getMethodConfig(method), \ - isPageStreaming = methodConfig.isPageStreaming - {@methodName}Settings - @end - @end -@end - -@snippet generateMethodSampleCode(sampleConfig) -# not used -@end diff --git a/src/main/resources/com/google/api/codegen/java/xapi.snip b/src/main/resources/com/google/api/codegen/java/xapi.snip deleted file mode 100644 index 34516f4dc4..0000000000 --- a/src/main/resources/com/google/api/codegen/java/xapi.snip +++ /dev/null @@ -1,410 +0,0 @@ -@extends "java/mvvm_common.snip" -@extends "java/xapi_sample.snip" - -@snippet generate(xapiClass) - {@license()} - package {@xapiClass.packageName}; - - @join import : xapiClass.imports - import {@import}; - @end - - {@serviceDoc(xapiClass)} - @@javax.annotation.Generated("by GAPIC") - public class {@xapiClass.name} implements AutoCloseable { - {@members(xapiClass)} - {@statics(xapiClass)} - {@staticFunctions(xapiClass)} - {@constructors(xapiClass)} - {@apiMethods(xapiClass)} - {@cleanupSection()} - } -@end - -@private serviceDoc(xapiClass) - @let coreSampleCode = syncMethodSampleCode(xapiClass.doc.exampleApiMethod), \ - decoratedSampleCode = decorateSampleCode(xapiClass.doc.exampleApiMethod, coreSampleCode) - {@renderServiceDoc(xapiClass.doc, decoratedSampleCode)} - @end -@end - -@private renderServiceDoc(xapiClassDoc, exampleMethodSampleCode) - // AUTO-GENERATED DOCUMENTATION AND SERVICE - /** - * Service Description: {@xapiClassDoc.firstLine} - @if xapiClassDoc.remainingLines - @join commentLine : xapiClassDoc.remainingLines - {@""} * {@commentLine} - @end - @end - * - *

This class provides the ability to make remote calls to the backing service through method - * calls that map to API methods. Sample code to get started: - * - *

-   * 
-  @join sampleLine : util.getDocLines(exampleMethodSampleCode)
-    {@""} * {@sampleLine}
-  @end
-   * 
-   * 
- * - *

Note: close() needs to be called on the {@xapiClassDoc.apiVarName} object to clean up resources such - * as threads. In the example above, try-with-resources is used, which automatically calls - * close(). - * - *

The surface of this class includes several types of Java methods for each of the API's methods: - * - *

    - *
  1. A "flattened" method. With this type of method, the fields of the request type have been - * converted into function parameters. It may be the case that not all fields are available - * as parameters, and not every API method will have a flattened method entry point. - *
  2. A "request object" method. This type of method only takes one parameter, a request - * object, which must be constructed before the call. Not every API method will have a request - * object method. - *
  3. A "callable" method. This type of method takes no parameters and returns an immutable - * ApiCallable object, which can be used to initiate calls to the service. - *
- * - *

See the individual methods for example code. - * - *

Many parameters require resource names to be formatted in a particular way. To assist - * with these names, this class includes a format method for each type of name, and additionally - * a parse method to extract the individual identifiers contained within names that are - * returned. - * - *

This class can be customized by passing in a custom instance of {@xapiClassDoc.settingsClassName} to - * create(). For example: - * - *

-   * 
-   * {@xapiClassDoc.settingsClassName} {@xapiClassDoc.settingsVarName} = {@xapiClassDoc.settingsClassName}.defaultBuilder()
-   *     .provideChannelWith(myCredentials)
-   *     .build();
-   * {@xapiClassDoc.apiClassName} {@xapiClassDoc.apiVarName} = \
-       {@xapiClassDoc.apiClassName}.create({@xapiClassDoc.settingsVarName});
-   * 
-   * 
- */ -@end - -@private statics(xapiClass) - @join pathTemplate : xapiClass.pathTemplates - private static final PathTemplate {@pathTemplate.name} = - PathTemplate.createWithoutUrlEncoding("{@pathTemplate.pattern}"); - {@""} - @end -@end - -@private staticFunctions(xapiClass) - @join function : xapiClass.formatResourceFunctions - {@formatResourceFunction(function)} - @end - {@""} - @join function : xapiClass.parseResourceFunctions - {@parseResourceFunction(function)} - @end -@end - -@private formatResourceFunction(function) - /** - * Formats a string containing the fully-qualified path to represent - * a {@function.entityName} resource. - */ - public static final String {@function.name}(\ - {@formatResourceFunctionParams(function.resourceIdParams)}) { - return {@function.pathTemplateName}.instantiate( - {@pathTemplateArgs(function.resourceIdParams)}); - } - {@""} -@end - -@private formatResourceFunctionParams(resourceIdParams) - @join param : resourceIdParams on ", " - String {@param.name} - @end -@end - -@private pathTemplateArgs(resourceIdParams) - @join param : resourceIdParams on ",".add(BREAK) - "{@param.templateKey}", {@param.name} - @end -@end - -@private parseResourceFunction(function) - /** - * Parses the {@function.outputResourceId} from the given fully-qualified path which - * represents a {@function.entityName} resource. - */ - public static final String {@function.name}(String {@function.entityNameParamName}) { - return {@function.pathTemplateName}.parse({@function.entityNameParamName})\ - .get("{@function.outputResourceId}"); - } - {@""} -@end - -@private members(xapiClass) - private final {@xapiClass.settingsClassName} settings; - private final ManagedChannel channel; - private final ScheduledExecutorService executor; - private final List closeables = new ArrayList<>(); - - @join apiCallable : xapiClass.apiCallableMembers - private final ApiCallable<{@apiCallable.requestTypeName}, {@apiCallable.responseTypeName}> {@apiCallable.name}; - @end - - public final {@xapiClass.settingsClassName} getSettings() { - return settings; - } - {@""} -@end - -@private constructors(xapiClass) - /** - * Constructs an instance of {@xapiClass.name} with default settings. - */ - public static final {@xapiClass.name} createWithDefaults() throws IOException { - return create({@xapiClass.settingsClassName}.defaultBuilder().build()); - } - - /** - * Constructs an instance of {@xapiClass.name}, using the given settings. - * The channels are created based on the settings passed in, or defaults for any - * settings that are not set. - */ - public static final {@xapiClass.name} create({@xapiClass.settingsClassName} settings) throws IOException { - return new {@xapiClass.name}(settings); - } - - /** - * Constructs an instance of {@xapiClass.name}, using the given settings. - * This is protected so that it easy to make a subclass, but otherwise, the static - * factory methods should be preferred. - */ - protected {@xapiClass.name}({@xapiClass.settingsClassName} settings) throws IOException { - this.settings = settings; - this.executor = settings.getExecutorProvider().getOrBuildExecutor(); - this.channel = settings.getChannelProvider().getOrBuildChannel(this.executor); - - @join apiCallable : xapiClass.apiCallableMembers - @switch apiCallable.type.toString - @case "SimpleApiCallable" - this.{@apiCallable.name} = ApiCallable.create(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); - @case "PagedApiCallable" - this.{@apiCallable.name} = - ApiCallable.createPagedVariant(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); - @case "BundlingApiCallable" - this.{@apiCallable.name} = ApiCallable.create(settings.{@apiCallable.settingsFunctionName}(), this.channel, this.executor); - if (settings.{@apiCallable.settingsFunctionName}().getBundlerFactory() != null) { - closeables.add(settings.{@apiCallable.settingsFunctionName}().getBundlerFactory()); - } - @default - $unhandledCase: {@apiCallable.type.toString}$ - @end - @end - - if (settings.getChannelProvider().shouldAutoClose()) { - closeables.add( - new Closeable() { - @@Override - public void close() throws IOException { - channel.shutdown(); - } - }); - } - if (settings.getExecutorProvider().shouldAutoClose()) { - closeables.add( - new Closeable() { - @@Override - public void close() throws IOException { - executor.shutdown(); - } - }); - } - } - {@""} -@end - -@private apiMethods(xapiClass) - @join apiMethod : xapiClass.apiMethods - @switch apiMethod.type.toString - @case "PagedFlattenedMethod" - {@pagedFlattenedMethod(apiMethod)} - @case "PagedRequestObjectMethod" - {@pagedRequestObjectMethod(apiMethod)} - @case "PagedCallableMethod" - {@pagedCallableMethod(apiMethod)} - @case "UnpagedListCallableMethod" - {@unpagedListCallableMethod(apiMethod)} - @case "FlattenedMethod" - {@flattenedMethod(apiMethod)} - @case "RequestObjectMethod" - {@requestObjectMethod(apiMethod)} - @case "CallableMethod" - {@callableMethod(apiMethod)} - @default - $unhandledCase: {@apiMethod.getClass.getSimpleName}$ - @end - {@BREAK} - @end -@end - -@private cleanupSection() - /** - * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately - * cancelled. - */ - @@Override - public final void close() throws Exception { - for (AutoCloseable closeable : closeables) { - closeable.close(); - } - } - -@end - -@private pagedFlattenedMethod(apiMethod) - @let coreSampleCode = pagedIterableMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - public final {@apiMethod.responseTypeName} {@apiMethod.name}({@paramList(apiMethod.methodParams)}) { - @join pathTemplateCheck : apiMethod.pathTemplateChecks - {@pathTemplateCheckLine(pathTemplateCheck)} - @end - {@apiMethod.apiRequestTypeName} request = - {@apiMethod.apiRequestTypeName}.newBuilder() - {@builderSetCalls(apiMethod.requestObjectParams)} - .build(); - return {@apiMethod.name}(request); - } -@end - -@private pagedRequestObjectMethod(apiMethod) - @let coreSampleCode = pagedIterableMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - {@apiMethod.requestObjectMethod.accessModifier} final {@apiMethod.responseTypeName} \ - {@apiMethod.name}({@apiMethod.apiRequestTypeName} request) { - return {@apiMethod.requestObjectMethod.callableMethodName}() - .call(request); - } -@end - -@private pagedCallableMethod(apiMethod) - @let coreSampleCode = pagedCallableMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - {@callableMethodImpl(apiMethod)} -@end - -@private unpagedListCallableMethod(apiMethod) - @let coreSampleCode = unpagedListCallableMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - {@callableMethodImpl(apiMethod)} -@end - -@private flattenedMethod(apiMethod) - @let coreSampleCode = syncMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - public final {@apiMethod.responseTypeName} {@apiMethod.name}(\ - {@paramList(apiMethod.methodParams)}) { - @join pathTemplateCheck : apiMethod.pathTemplateChecks - {@pathTemplateCheckLine(pathTemplateCheck)} - @end - {@apiMethod.apiRequestTypeName} request = - {@apiMethod.apiRequestTypeName}.newBuilder() - {@builderSetCalls(apiMethod.requestObjectParams)} - .build(); - @if apiMethod.hasReturnValue - return {@apiMethod.name}(request); - @else - {@apiMethod.name}(request); - @end - } -@end - -@private requestObjectMethod(apiMethod) - @let coreSampleCode = syncMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - {@apiMethod.requestObjectMethod.accessModifier} final {@apiMethod.responseTypeName} \ - {@apiMethod.name}({@apiMethod.apiRequestTypeName} request) { - @if apiMethod.hasReturnValue - return {@apiMethod.requestObjectMethod.callableMethodName}().call(request); - @else - {@apiMethod.requestObjectMethod.callableMethodName}().call(request); - @end - } -@end - -@private callableMethod(apiMethod) - @let coreSampleCode = callableMethodSampleCode(apiMethod) - {@methodDoc(apiMethod.doc, decorateSampleCode(apiMethod, coreSampleCode))} - @end - {@callableMethodImpl(apiMethod)} -@end - -@private callableMethodImpl(apiMethod) - public final ApiCallable<{@apiMethod.apiRequestTypeName}, {@apiMethod.responseTypeName}> \ - {@apiMethod.name}() { - return {@apiMethod.callableMethod.callableName}; - } -@end - -@private methodDoc(apiMethodDoc, methodSampleCode) - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - @join commentLine : apiMethodDoc.mainDocLines - {@""} * {@commentLine} - @end - * - * Sample code: - *

-  @join sampleLine : util.getDocLines(methodSampleCode)
-    {@""} * {@sampleLine}
-  @end
-   * 
- @if apiMethodDoc.paramDocs - {@""} * - @join doc : apiMethodDoc.paramDocs - {@paramDoc(doc)} - @end - @end - @if apiMethodDoc.throwsDocLines - @join commentLine : apiMethodDoc.throwsDocLines - {@""} * {@commentLine} - @end - @end - */ - {@EMPTY} -@end - -@private paramDoc(doc) - @switch doc.type - @case "SimpleParamDocView" - {@simpleParamDoc(doc)} - @default - $unhandledCase: {@doc.type}$ - @end -@end - -@private simpleParamDoc(doc) - {@""} * @@param {@doc.paramName} {@doc.firstLine} - @if doc.remainingLines - @join commentLine : doc.remainingLines - {@""} * {@commentLine} - @end - @end -@end - -@private builderSetCalls(requestObjectParams) - @join requestObjectParam : requestObjectParams - .{@requestObjectParam.setCallName}({@requestObjectParam.name}) - @end -@end - -@private pathTemplateCheckLine(pathTemplateCheck) - {@pathTemplateCheck.pathTemplateName}.validate({@pathTemplateCheck.paramName}); -@end diff --git a/src/main/resources/com/google/api/codegen/java/xapi_sample.snip b/src/main/resources/com/google/api/codegen/java/xapi_sample.snip deleted file mode 100644 index bda454a0e8..0000000000 --- a/src/main/resources/com/google/api/codegen/java/xapi_sample.snip +++ /dev/null @@ -1,131 +0,0 @@ -@extends "java/mvvm_common.snip" - -@snippet decorateSampleCode(apiMethod, coreSampleCode) - try ({@apiMethod.apiClassName} {@apiMethod.apiVariableName} = \ - {@apiMethod.apiClassName}.createWithDefaults()) { - {@coreSampleCode} - } -@end - -@snippet pagedIterableMethodSampleCode(apiMethod) - {@initCode(apiMethod.initCode)} - for ({@apiMethod.listMethod.resourceTypeName} element : {@sampleSyncMethodCall(apiMethod)}) { - // doThingsWith(element); - } -@end - -@snippet pagedCallableMethodSampleCode(apiMethod) - {@initCode(apiMethod.initCode)} - ListenableFuture<{@apiMethod.responseTypeName}> future = {@sampleFutureMethodCall(apiMethod)}; - // Do something - for ({@apiMethod.listMethod.resourceTypeName} element : future.get()) { - // doThingsWith(element); - } -@end - -@snippet unpagedListCallableMethodSampleCode(apiMethod) - {@initCode(apiMethod.initCode)} - while (true) { - {@apiMethod.responseTypeName} response = \ - {@apiMethod.apiVariableName}.{@apiMethod.name}().call(\ - {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}); - for ({@apiMethod.listMethod.resourceTypeName} element : \ - response.{@apiMethod.unpagedListCallableMethod.fnGetResourceListCall}()) { - // doThingsWith(element); - } - String nextPageToken = response.getNextPageToken(); - if (!Strings.isNullOrEmpty(nextPageToken)) { - request = request.toBuilder().setPageToken(nextPageToken).build(); - } else { - break; - } - } -@end - -@snippet syncMethodSampleCode(apiMethod) - {@initCode(apiMethod.initCode)} - @if apiMethod.hasReturnValue - {@apiMethod.responseTypeName} response = {@sampleSyncMethodCall(apiMethod)}; - @else - {@sampleSyncMethodCall(apiMethod)}; - @end -@end - -@snippet callableMethodSampleCode(apiMethod) - {@initCode(apiMethod.initCode)} - ListenableFuture<{@apiMethod.callableMethod.genericAwareResponseType}> future = {@sampleFutureMethodCall(apiMethod)}; - // Do something - @if apiMethod.hasReturnValue - {@apiMethod.responseTypeName} response = future.get(); - @else - future.get(); - @end -@end - -@private sampleFutureMethodCall(apiMethod) - {@apiMethod.apiVariableName}.{@apiMethod.name}().futureCall(\ - {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) -@end - -@private sampleSyncMethodCall(apiMethod) - {@apiMethod.apiVariableName}.{@apiMethod.name}(\ - {@sampleMethodCallArgList(apiMethod.initCode.fieldSettings)}) -@end - -@private sampleMethodCallArgList(fieldSettings) - @join fieldSetting : fieldSettings on ", " - {@fieldSetting.identifier} - @end -@end - -@private initCode(initCodeSpec) - @join line : initCodeSpec.lines - @switch line.lineType.toString - @case "StructureInitLine" - {@initLineStructure(line)} - @case "ListInitLine" - {@initLineList(line)} - @case "MapInitLine" - {@initLineMap(line)} - @case "SimpleInitLine" - {@initLineSimple(line)} - @default - $unhandledCase: {@line.lineType.toString}$ - @end - @end -@end - -@private initLineStructure(line) - {@line.typeName} {@line.identifier} = {@line.typeName}.newBuilder() - @join fieldSetting : line.fieldSettings - {@EMPTY} .{@fieldSetting.fnSetFunctionCallName}({@fieldSetting.identifier}) - @end - {@EMPTY} .build(); -@end - -@private initLineList(line) - List<{@line.elementTypeName}> {@line.identifier} = \ - Arrays.asList({@argList(line.elementIdentifiers)}); -@end - -@private initLineMap(line) - Map<{@line.keyTypeName}, {@line.valueTypeName}> {@line.identifier} = new HashMap<>(); - @join mapEntry : line.initEntries vertical - {@line.identifier}.put({@mapEntry.key}, {@mapEntry.value}); - @end -@end - -@private initLineSimple(line) - {@line.typeName} {@line.identifier} = {@renderInitValue(line.initValue)}; -@end - -@private renderInitValue(initValue) - @switch initValue.type - @case "SimpleInitValueView" - {@initValue.initialValue} - @case "FormattedInitValueView" - {@initValue.apiWrapperName}.{@initValue.formatFunctionName}({@argList(initValue.formatArgs)}) - @default - $unhandledCase: {@initValue.type}$ - @end -@end diff --git a/src/main/resources/com/google/api/codegen/java/xpackage-info.snip b/src/main/resources/com/google/api/codegen/java/xpackage-info.snip deleted file mode 100644 index 5e756dfe12..0000000000 --- a/src/main/resources/com/google/api/codegen/java/xpackage-info.snip +++ /dev/null @@ -1,50 +0,0 @@ -@extends "java/mvvm_common.snip" -@extends "java/xapi_sample.snip" - -@snippet generate(packageInfo) - {@license()} - - /** - * A client to {@packageInfo.serviceTitle}. - * - * The interfaces provided are listed below, along with a usage sample - * - @join xapiClassDoc : packageInfo.serviceDocs - {@serviceShortDoc(xapiClassDoc)} - @end - */ - - package {@packageInfo.packageName}; -@end - -@private serviceShortDoc(xapiClassDoc) - @let coreSampleCode = syncMethodSampleCode(xapiClassDoc.exampleApiMethod), \ - decoratedSampleCode = decorateSampleCode(xapiClassDoc.exampleApiMethod, coreSampleCode) - {@renderServiceShortDoc(xapiClassDoc, decoratedSampleCode)} - @end -@end - -@private renderServiceShortDoc(xapiClassDoc, exampleMethodSampleCode) - @join commentLine : util.getMultilineHeading(xapiClassDoc.apiClassName) - {@""} * {@commentLine} - @end - # The join above doesn't properly add a newline on the end, so we need to force it - {@""} - {@""} * - * Service Description: {@xapiClassDoc.firstLine} - @if xapiClassDoc.remainingLines - @join commentLine : xapiClassDoc.remainingLines - {@""} * {@commentLine} - @end - @end - * - * Sample for {@xapiClassDoc.apiClassName}: - *
-   * 
-  @join sampleLine : util.getDocLines(exampleMethodSampleCode)
-    {@""} * {@sampleLine}
-  @end
-   * 
-   * 
- * -@end diff --git a/src/main/resources/com/google/api/codegen/java/xsettings.snip b/src/main/resources/com/google/api/codegen/java/xsettings.snip deleted file mode 100644 index e41697d0af..0000000000 --- a/src/main/resources/com/google/api/codegen/java/xsettings.snip +++ /dev/null @@ -1,479 +0,0 @@ -@extends "java/mvvm_common.snip" - -@snippet generate(xsettingsClass) - {@license()} - package {@xsettingsClass.packageName}; - - @join import : xsettingsClass.imports - import {@import}; - @end - - @@javax.annotation.Generated("by GAPIC") - public class {@xsettingsClass.name} extends ServiceApiSettings { - {@constants(xsettingsClass)} - {@members(xsettingsClass)} - {@constructors(xsettingsClass)} - {@descriptors(xsettingsClass)} - {@innerBuilderClass(xsettingsClass)} - } -@end - -@private constants(xsettingsClass) - /** - * The default address of the service. - */ - public static final String DEFAULT_SERVICE_ADDRESS = "{@xsettingsClass.serviceAddress}"; - - /** - * The default port of the service. - */ - public static final int DEFAULT_SERVICE_PORT = {@xsettingsClass.servicePort}; - - /** - * The default scopes of the service. - */ - public static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() - @join scope : {@xsettingsClass.authScopes} - .add("{@scope}") - @end - .build(); - - /** - * The default connection settings of the service. - */ - public static final ConnectionSettings DEFAULT_CONNECTION_SETTINGS = - ConnectionSettings.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) - .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) - .build(); - {@""} -@end - -@private members(xsettingsClass) - {@methodMembers(xsettingsClass)} - {@methodGetters(xsettingsClass)} - /** - * Returns a builder for this class with recommended defaults. - */ - public static Builder defaultBuilder() { - return Builder.createDefault(); - } - - /** - * Returns a new builder for this class. - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Returns a builder containing all the values of this settings class. - */ - public Builder toBuilder() { - return new Builder(this); - } - {@""} -@end - -@private methodMembers(xsettingsClass) - @join settings : xsettingsClass.callSettings - @switch settings.type.toString - @case "SimpleApiCallable" - private final SimpleCallSettings<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.memberName}; - @case "PagedApiCallable" - private final PageStreamingCallSettings<{@settings.requestTypeName}, \ - {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.memberName}; - @case "BundlingApiCallable" - private final BundlingCallSettings<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.memberName}; - @default - $unhandledCase: {@settings.type.toString}$ - @end - @end - {@BREAK} -@end - -@private methodGetters(xsettingsClass) - @join settings : xsettingsClass.callSettings - /** - * Returns the object with the settings used for calls to {@settings.methodName}. - */ - @switch settings.type.toString - @case "SimpleApiCallable" - public SimpleCallSettings<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.fnGetterName}() { - return {@settings.memberName}; - } - @case "PagedApiCallable" - public PageStreamingCallSettings<{@settings.requestTypeName}, \ - {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.fnGetterName}() { - return {@settings.memberName}; - } - @case "BundlingApiCallable" - public BundlingCallSettings<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.fnGetterName}() { - return {@settings.memberName}; - } - @default - $unhandledCase: {@settings.type.toString}$ - @end - {@""} - @end -@end - -@private constructors(xsettingsClass) - private {@xsettingsClass.name}(Builder settingsBuilder) throws IOException { - super(settingsBuilder.getChannelProvider(), - settingsBuilder.getExecutorProvider(), - settingsBuilder.getGeneratorName(), - settingsBuilder.getGeneratorVersion(), - settingsBuilder.getClientLibName(), - settingsBuilder.getClientLibVersion()); - - @join settings : xsettingsClass.callSettings - {@settings.memberName} = settingsBuilder.{@settings.fnGetterName}().build(); - @end - } - {@""} -@end - -@private descriptors(xsettingsClass) - {@pageStreamingDescriptors(xsettingsClass)} - {@bundlingDescriptors(xsettingsClass)} -@end - -@private pageStreamingDescriptors(xsettingsClass) - @join desc : xsettingsClass.pageStreamingDescriptors - private static PageStreamingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}, {@desc.resourceTypeName}> {@desc.name} = - new PageStreamingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}, {@desc.resourceTypeName}>() { - @@Override - public Object emptyToken() { - return {@desc.defaultTokenValue}; - } - @@Override - public {@desc.requestTypeName} injectToken({@desc.requestTypeName} payload, Object token) { - return {@desc.requestTypeName} - .newBuilder(payload) - .{@desc.fnSetRequestToken}(({@desc.tokenTypeName}) token) - .build(); - } - @@Override - public Object extractNextToken({@desc.responseTypeName} payload) { - return payload.{@desc.fnGetResponseToken}(); - } - @@Override - public Iterable<{@desc.resourceTypeName}> extractResources({@desc.responseTypeName} payload) { - return payload.{@desc.fnGetResourcesField}(); - } - }; - {@""} - @end -@end - -@private bundlingDescriptors(xsettingsClass) - @join desc : xsettingsClass.bundlingDescriptors - private static BundlingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}> {@desc.name} = - new BundlingDescriptor<{@desc.requestTypeName}, {@desc.responseTypeName}>() { - @@Override - public String getBundlePartitionKey({@desc.requestTypeName} request) { - return {@partitionKeyCode(desc)}; - } - - @@Override - public {@desc.requestTypeName} mergeRequests(Collection<{@desc.requestTypeName}> requests) { - {@desc.requestTypeName} firstRequest = requests.iterator().next(); - - {@desc.bundledFieldTypeName} elements = new ArrayList<>(); - for ({@desc.requestTypeName} request : requests) { - elements.addAll(request.{@desc.fnGetBundledField}()); - } - - {@desc.requestTypeName} bundleRequest = - {@desc.requestTypeName}.newBuilder() - {@fieldCopyCalls(desc.discriminatorFieldCopies)} - .{@desc.fnSetBundledField}(elements) - .build(); - return bundleRequest; - } - - @@Override - public void splitResponse( - {@desc.responseTypeName} bundleResponse, - Collection> bundle) { - # TODO(garrettjones) support case of no subresponse_field (e.g. Logging) - int bundleMessageIndex = 0; - for (RequestIssuer<{@desc.requestTypeName}, {@desc.responseTypeName}> responder : bundle) { - {@desc.subresponseTypeName} subresponseElements = new ArrayList<>(); - int subresponseCount = responder.getRequest().{@desc.fnGetBundledFieldCount}(); - for (int i = 0; i < subresponseCount; i++) { - subresponseElements.add(bundleResponse.{@desc.fnGetSubresponseByIndex}(bundleMessageIndex)); - bundleMessageIndex += 1; - } - {@desc.responseTypeName} response = - {@desc.responseTypeName}.newBuilder().{@desc.fnSetSubresponse}(subresponseElements).build(); - responder.setResponse(response); - } - } - - @@Override - public void splitException( - Throwable throwable, - Collection> bundle) { - for (RequestIssuer<{@desc.requestTypeName}, {@desc.responseTypeName}> responder : bundle) { - responder.setException(throwable); - } - } - - @@Override - public long countElements({@desc.requestTypeName} request) { - return request.{@desc.fnGetBundledFieldCount}(); - } - - @@Override - public long countBytes({@desc.requestTypeName} request) { - return request.getSerializedSize(); - } - }; - {@""} - @end -@end - -@private partitionKeyCode(bundlingDesc) - @join partitionKey : bundlingDesc.partitionKeys on " + " - request.{@partitionKey.fnGetCallName}() + {@partitionKey.separatorLiteral} - @end -@end - -@private fieldCopyCalls(fieldCopies) - @join fieldCopy : fieldCopies - .{@fieldCopy.fnSetFunctionCallName}(firstRequest.{@fieldCopy.fnGetFunctionCallName}()) - @end -@end - -@private innerBuilderClass(xsettingsClass) - /** - * Builder for {@xsettingsClass.name}. - */ - public static class Builder extends ServiceApiSettings.Builder { - private final ImmutableList methodSettingsBuilders; - - {@builderMembers(xsettingsClass)} - - {@builderConstants(xsettingsClass)} - - {@builderConstructors(xsettingsClass)} - - {@builderMethods(xsettingsClass)} - } -@end - -@private builderMembers(xsettingsClass) - @join settings : xsettingsClass.callSettings - @switch settings.type.toString - @case "SimpleApiCallable" - private SimpleCallSettings.Builder<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.memberName}; - @case "PagedApiCallable" - private PageStreamingCallSettings.Builder<{@settings.requestTypeName}, \ - {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.memberName}; - @case "BundlingApiCallable" - private BundlingCallSettings.Builder<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.memberName}; - @default - $unhandledCase: {@settings.type.toString}$ - @end - @end -@end - -@private builderConstants(xsettingsClass) - private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; - - static { - ImmutableMap.Builder> definitions = ImmutableMap.builder(); - @join retryCodesDef : xsettingsClass.retryCodesDefinitions - definitions.put( - "{@retryCodesDef.key}", - Sets.immutableEnumSet(Lists.newArrayList({@statusCodes(retryCodesDef.codes)}))); - @end - RETRYABLE_CODE_DEFINITIONS = definitions.build(); - } - - private static final ImmutableMap RETRY_PARAM_DEFINITIONS; - - static { - ImmutableMap.Builder definitions = ImmutableMap.builder(); - RetrySettings.Builder settingsBuilder = null; - @join retryParamsDef : xsettingsClass.retryParamsDefinitions - settingsBuilder = RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.millis({@retryParamsDef.initialRetryDelay.getMillis}L)) - .setRetryDelayMultiplier({@retryParamsDef.retryDelayMultiplier}) - .setMaxRetryDelay(Duration.millis({@retryParamsDef.maxRetryDelay.getMillis}L)) - .setInitialRpcTimeout(Duration.millis({@retryParamsDef.initialRpcTimeout.getMillis}L)) - .setRpcTimeoutMultiplier({@retryParamsDef.rpcTimeoutMultiplier}) - .setMaxRpcTimeout(Duration.millis({@retryParamsDef.maxRpcTimeout.getMillis}L)) - .setTotalTimeout(Duration.millis({@retryParamsDef.totalTimeout.getMillis}L)); - definitions.put("{@retryParamsDef.key}", settingsBuilder); - @end - RETRY_PARAM_DEFINITIONS = definitions.build(); - } -@end - -@private statusCodes(codes) - @join code : codes on ", " - Status.Code.{@code} - @end -@end - -@private builderConstructors(xsettingsClass) - private Builder() { - super(DEFAULT_CONNECTION_SETTINGS); - - @join settings : xsettingsClass.callSettings - @switch settings.type.toString - @case "SimpleApiCallable" - {@settings.memberName} = SimpleCallSettings.newBuilder({@settings.grpcTypeName}.{@settings.grpcMethodConstant}); - @case "PagedApiCallable" - {@settings.memberName} = PageStreamingCallSettings.newBuilder( - {@settings.grpcTypeName}.{@settings.grpcMethodConstant}, - {@settings.pageStreamingDescriptorName}); - @case "BundlingApiCallable" - {@settings.memberName} = BundlingCallSettings.newBuilder( - {@settings.grpcTypeName}.{@settings.grpcMethodConstant}, - {@settings.bundlingDescriptorName}) - .setBundlingSettingsBuilder(BundlingSettings.newBuilder()); - @default - $unhandledCase: {@settings.type.toString}$ - @end - {@BREAK} - @end - methodSettingsBuilders = ImmutableList.of( - @join settings : xsettingsClass.callSettings vertical on ",".add(BREAK) - {@settings.memberName} - @end - ); - } - - private static Builder createDefault() { - Builder builder = new Builder(); - @join settings : xsettingsClass.callSettings - {@""} - @switch settings.type.toString - @case "SimpleApiCallable" - @case "PagedApiCallable" - @case "BundlingApiCallable" - builder.{@settings.fnGetterName}().getBundlingSettingsBuilder() - .setElementCountThreshold({@settings.bundlingConfig.elementCountThreshold}) - .setElementCountLimit({@settings.bundlingConfig.elementCountLimit}) - .setRequestByteThreshold({@settings.bundlingConfig.requestByteThreshold}) - .setRequestByteLimit({@settings.bundlingConfig.requestByteLimit}) - .setDelayThreshold(Duration.millis({@settings.bundlingConfig.delayThresholdMillis})) - .setBlockingCallCountThreshold(1); - @default - $unhandledCase: {@settings.type.toString}$ - @end - builder.{@settings.fnGetterName}() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("{@settings.retryCodesName}")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("{@settings.retryParamsName}")); - @end - - return builder; - } - - private Builder({@xsettingsClass.name} settings) { - super(settings); - - @join settings : xsettingsClass.callSettings - {@settings.memberName} = settings.{@settings.memberName}.toBuilder(); - @end - - methodSettingsBuilders = ImmutableList.of( - @join settings : xsettingsClass.callSettings vertical on ",".add(BREAK) - {@settings.memberName} - @end - ); - } -@end - -@private builderMethods(xsettingsClass) - @@Override - protected ConnectionSettings getDefaultConnectionSettings() { - return DEFAULT_CONNECTION_SETTINGS; - } - @@Override - public Builder provideExecutorWith(ScheduledExecutorService executor, boolean shouldAutoClose) { - super.provideExecutorWith(executor, shouldAutoClose); - return this; - } - @@Override - public Builder provideChannelWith(ManagedChannel channel, boolean shouldAutoClose) { - super.provideChannelWith(channel, shouldAutoClose); - return this; - } - @@Override - public Builder provideChannelWith(ConnectionSettings settings) { - super.provideChannelWith(settings); - return this; - } - @@Override - public Builder provideChannelWith(Credentials credentials) { - super.provideChannelWith(credentials); - return this; - } - @@Override - public Builder provideChannelWith(List scopes) { - super.provideChannelWith(scopes); - return this; - } - @@Override - public Builder setGeneratorHeader(String name, String version) { - super.setGeneratorHeader(name, version); - return this; - } - @@Override - public Builder setClientLibHeader(String name, String version) { - super.setClientLibHeader(name, version); - return this; - } - - /** - * Applies the given settings to all of the API methods in this service. Only - * values that are non-null will be applied, so this method is not capable - * of un-setting any values. - */ - public Builder applyToAllApiMethods(ApiCallSettings.Builder apiCallSettings) throws Exception { - super.applyToAllApiMethods(methodSettingsBuilders, apiCallSettings); - return this; - } - - @join settings : xsettingsClass.callSettings - /** - * Returns the builder for the settings used for calls to {@settings.methodName}. - */ - @switch settings.type.toString - @case "SimpleApiCallable" - public SimpleCallSettings.Builder<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.fnGetterName}() { - return {@settings.memberName}; - } - @case "PagedApiCallable" - public PageStreamingCallSettings.Builder<{@settings.requestTypeName}, \ - {@settings.responseTypeName}, {@settings.resourceTypeName}> {@settings.fnGetterName}() { - return {@settings.memberName}; - } - @case "BundlingApiCallable" - public BundlingCallSettings.Builder<{@settings.requestTypeName}, \ - {@settings.responseTypeName}> {@settings.fnGetterName}() { - return {@settings.memberName}; - } - @default - $unhandledCase: {@settings.type.toString}$ - @end - {@""} - @end - @@Override - public {@xsettingsClass.name} build() throws IOException { - return new {@xsettingsClass.name}(this); - } -@end diff --git a/src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java b/src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java deleted file mode 100644 index 48c0f20bfc..0000000000 --- a/src/test/java/com/google/api/codegen/JavaSurfaceCodeGeneratorTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen; - -import com.google.api.codegen.gapic.MainGapicProviderFactory; - -import java.util.List; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -/** - * Java code generator baseline tests. - */ -@RunWith(Parameterized.class) -public class JavaSurfaceCodeGeneratorTest extends GapicTestBase { - - public JavaSurfaceCodeGeneratorTest( - String name, String idForFactory, String[] gapicConfigFileNames, String snippetName) { - super(name, idForFactory, gapicConfigFileNames, snippetName); - getTestDataLocator() - .addTestDataSource(com.google.api.codegen.java.JavaSnippetSetRunner.class, ""); - } - - /** - * Declares test parameters, each one an array of values passed to the constructor, with the - * first element a name, the second a config of this name. - */ - @Parameters(name = "{0}") - public static List testedConfigs() { - return GapicTestBase.createTestedConfigs( - MainGapicProviderFactory.JAVA_SURFACE, - new String[] {"java_gapic.yaml", "library_gapic.yaml"}); - } - - // Tests - // ===== - - @Test - public void library() throws Exception { - test("library"); - } -} diff --git a/src/test/java/com/google/api/codegen/testdata/java_main_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_main_library.baseline index 359fdf465a..b83727a11c 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_main_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_main_library.baseline @@ -40,6 +40,7 @@ import com.google.example.library.v1.PublishSeriesResponse; import com.google.example.library.v1.Shelf; import com.google.example.library.v1.SomeMessage; import com.google.example.library.v1.UpdateBookIndexRequest; +import com.google.example.library.v1.UpdateBookIndexRequest.IndexMapEntry; import com.google.example.library.v1.UpdateBookRequest; import com.google.protobuf.ByteString; import com.google.protobuf.Empty; @@ -52,8 +53,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; - - // AUTO-GENERATED DOCUMENTATION AND SERVICE /** * Service Description: This API represents a simple digital library. It lets you manage Shelf @@ -127,22 +126,19 @@ public class LibraryServiceApi implements AutoCloseable { private final ApiCallable createShelfCallable; private final ApiCallable getShelfCallable; private final ApiCallable listShelvesCallable; - private final ApiCallable> - listShelvesPagedCallable; + private final ApiCallable> listShelvesPagedCallable; private final ApiCallable deleteShelfCallable; private final ApiCallable mergeShelvesCallable; private final ApiCallable createBookCallable; private final ApiCallable publishSeriesCallable; private final ApiCallable getBookCallable; private final ApiCallable listBooksCallable; - private final ApiCallable> - listBooksPagedCallable; + private final ApiCallable> listBooksPagedCallable; private final ApiCallable deleteBookCallable; private final ApiCallable updateBookCallable; private final ApiCallable moveBookCallable; private final ApiCallable listStringsCallable; - private final ApiCallable> - listStringsPagedCallable; + private final ApiCallable> listStringsPagedCallable; private final ApiCallable addCommentsCallable; private final ApiCallable getBookFromArchiveCallable; private final ApiCallable updateBookIndexCallable; @@ -175,7 +171,8 @@ public class LibraryServiceApi implements AutoCloseable { */ public static final String formatBookName(String shelf, String book) { return BOOK_PATH_TEMPLATE.instantiate( - "shelf", shelf,"book", book); + "shelf", shelf, + "book", book); } /** @@ -184,7 +181,8 @@ public class LibraryServiceApi implements AutoCloseable { */ public static final String formatArchivedBookName(String archivePath, String book) { return ARCHIVED_BOOK_PATH_TEMPLATE.instantiate( - "archive_path", archivePath,"book", book); + "archive_path", archivePath, + "book", book); } /** @@ -227,7 +225,6 @@ public class LibraryServiceApi implements AutoCloseable { return ARCHIVED_BOOK_PATH_TEMPLATE.parse(archivedBookName).get("book"); } - /** * Constructs an instance of LibraryServiceApi with default settings. */ @@ -300,8 +297,6 @@ public class LibraryServiceApi implements AutoCloseable { } } - // ----- createShelf ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Creates a shelf, and returns the new Shelf. @@ -343,7 +338,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - private Shelf createShelf(CreateShelfRequest request) { + private final Shelf createShelf(CreateShelfRequest request) { return createShelfCallable().call(request); } @@ -368,8 +363,6 @@ public class LibraryServiceApi implements AutoCloseable { return createShelfCallable; } - // ----- getShelf ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Gets a shelf. @@ -413,7 +406,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final Shelf getShelf(String name, SomeMessage message) { SHELF_PATH_TEMPLATE.validate(name); - GetShelfRequest request = GetShelfRequest.newBuilder() .setName(name) @@ -443,8 +435,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final Shelf getShelf(String name, SomeMessage message, com.google.example.library.v1.StringBuilder stringBuilder) { SHELF_PATH_TEMPLATE.validate(name); - - GetShelfRequest request = GetShelfRequest.newBuilder() .setName(name) @@ -474,7 +464,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public Shelf getShelf(GetShelfRequest request) { + public final Shelf getShelf(GetShelfRequest request) { return getShelfCallable().call(request); } @@ -501,8 +491,6 @@ public class LibraryServiceApi implements AutoCloseable { return getShelfCallable; } - // ----- listShelves ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Lists shelves. @@ -511,12 +499,11 @@ public class LibraryServiceApi implements AutoCloseable { *

    * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
    *
-   *   for (Shelf elements : libraryServiceApi.listShelves()) {
-   *     // doThingsWith(elements);
+   *   for (Shelf element : libraryServiceApi.listShelves()) {
+   *     // doThingsWith(element);
    *   }
    * }
    * 
- * * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ public final PageAccessor listShelves() { @@ -536,8 +523,8 @@ public class LibraryServiceApi implements AutoCloseable { * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) { * ListShelvesRequest request = ListShelvesRequest.newBuilder() * .build(); - * for (Shelf elements : libraryServiceApi.listShelves(request)) { - * // doThingsWith(elements); + * for (Shelf element : libraryServiceApi.listShelves(request)) { + * // doThingsWith(element); * } * } *
@@ -561,8 +548,8 @@ public class LibraryServiceApi implements AutoCloseable { * .build(); * ListenableFuture<PageAccessor<Shelf>> future = libraryServiceApi.listShelvesPagedCallable().futureCall(request); * // Do something - * for (Shelf elements : future.get()) { - * // doThingsWith(elements); + * for (Shelf element : future.get()) { + * // doThingsWith(element); * } * } *
@@ -582,8 +569,8 @@ public class LibraryServiceApi implements AutoCloseable { * .build(); * while (true) { * ListShelvesResponse response = libraryServiceApi.listShelvesCallable().call(request); - * for (Shelf elements : response.getShelvesList()) { - * // doThingsWith(elements); + * for (Shelf element : response.getShelvesList()) { + * // doThingsWith(element); * } * String nextPageToken = response.getNextPageToken(); * if (!Strings.isNullOrEmpty(nextPageToken)) { @@ -599,8 +586,6 @@ public class LibraryServiceApi implements AutoCloseable { return listShelvesCallable; } - // ----- deleteShelf ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Deletes a shelf. @@ -643,7 +628,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - private void deleteShelf(DeleteShelfRequest request) { + private final void deleteShelf(DeleteShelfRequest request) { deleteShelfCallable().call(request); } @@ -668,8 +653,6 @@ public class LibraryServiceApi implements AutoCloseable { return deleteShelfCallable; } - // ----- mergeShelves ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Merges two shelves by adding all books from the shelf named @@ -722,7 +705,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public Shelf mergeShelves(MergeShelvesRequest request) { + public final Shelf mergeShelves(MergeShelvesRequest request) { return mergeShelvesCallable().call(request); } @@ -751,8 +734,6 @@ public class LibraryServiceApi implements AutoCloseable { return mergeShelvesCallable; } - // ----- createBook ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Creates a book. @@ -772,7 +753,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final Book createBook(String name, Book book) { SHELF_PATH_TEMPLATE.validate(name); - CreateBookRequest request = CreateBookRequest.newBuilder() .setName(name) @@ -801,7 +781,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public Book createBook(CreateBookRequest request) { + public final Book createBook(CreateBookRequest request) { return createBookCallable().call(request); } @@ -828,8 +808,6 @@ public class LibraryServiceApi implements AutoCloseable { return createBookCallable; } - // ----- publishSeries ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Creates a series of books. @@ -850,8 +828,6 @@ public class LibraryServiceApi implements AutoCloseable { * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ public final PublishSeriesResponse publishSeries(Shelf shelf, List books, int edition) { - - PublishSeriesRequest request = PublishSeriesRequest.newBuilder() .setShelf(shelf) @@ -881,7 +857,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public PublishSeriesResponse publishSeries(PublishSeriesRequest request) { + public final PublishSeriesResponse publishSeries(PublishSeriesRequest request) { return publishSeriesCallable().call(request); } @@ -908,8 +884,6 @@ public class LibraryServiceApi implements AutoCloseable { return publishSeriesCallable; } - // ----- getBook ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Gets a book. @@ -952,7 +926,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - private Book getBook(GetBookRequest request) { + private final Book getBook(GetBookRequest request) { return getBookCallable().call(request); } @@ -977,8 +951,6 @@ public class LibraryServiceApi implements AutoCloseable { return getBookCallable; } - // ----- listBooks ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Lists books in a shelf. @@ -988,8 +960,8 @@ public class LibraryServiceApi implements AutoCloseable { * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) { * String formattedName = LibraryServiceApi.formatShelfName("[SHELF]"); * String filter = ""; - * for (Book elements : libraryServiceApi.listBooks(formattedName, filter)) { - * // doThingsWith(elements); + * for (Book element : libraryServiceApi.listBooks(formattedName, filter)) { + * // doThingsWith(element); * } * } * @@ -1000,7 +972,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final PageAccessor listBooks(String name, String filter) { SHELF_PATH_TEMPLATE.validate(name); - ListBooksRequest request = ListBooksRequest.newBuilder() .setName(name) @@ -1020,8 +991,8 @@ public class LibraryServiceApi implements AutoCloseable { * ListBooksRequest request = ListBooksRequest.newBuilder() * .setName(formattedName) * .build(); - * for (Book elements : libraryServiceApi.listBooks(request)) { - * // doThingsWith(elements); + * for (Book element : libraryServiceApi.listBooks(request)) { + * // doThingsWith(element); * } * } * @@ -1047,8 +1018,8 @@ public class LibraryServiceApi implements AutoCloseable { * .build(); * ListenableFuture<PageAccessor<Book>> future = libraryServiceApi.listBooksPagedCallable().futureCall(request); * // Do something - * for (Book elements : future.get()) { - * // doThingsWith(elements); + * for (Book element : future.get()) { + * // doThingsWith(element); * } * } * @@ -1070,8 +1041,8 @@ public class LibraryServiceApi implements AutoCloseable { * .build(); * while (true) { * ListBooksResponse response = libraryServiceApi.listBooksCallable().call(request); - * for (Book elements : response.getBooksList()) { - * // doThingsWith(elements); + * for (Book element : response.getBooksList()) { + * // doThingsWith(element); * } * String nextPageToken = response.getNextPageToken(); * if (!Strings.isNullOrEmpty(nextPageToken)) { @@ -1087,8 +1058,6 @@ public class LibraryServiceApi implements AutoCloseable { return listBooksCallable; } - // ----- deleteBook ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Deletes a book. @@ -1131,7 +1100,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - private void deleteBook(DeleteBookRequest request) { + private final void deleteBook(DeleteBookRequest request) { deleteBookCallable().call(request); } @@ -1156,8 +1125,6 @@ public class LibraryServiceApi implements AutoCloseable { return deleteBookCallable; } - // ----- updateBook ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Updates a book. @@ -1177,7 +1144,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final Book updateBook(String name, Book book) { BOOK_PATH_TEMPLATE.validate(name); - UpdateBookRequest request = UpdateBookRequest.newBuilder() .setName(name) @@ -1209,9 +1175,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final Book updateBook(String name, Book book, FieldMask updateMask, com.google.example.library.v1.FieldMask physicalMask) { BOOK_PATH_TEMPLATE.validate(name); - - - UpdateBookRequest request = UpdateBookRequest.newBuilder() .setName(name) @@ -1242,7 +1205,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public Book updateBook(UpdateBookRequest request) { + public final Book updateBook(UpdateBookRequest request) { return updateBookCallable().call(request); } @@ -1269,8 +1232,6 @@ public class LibraryServiceApi implements AutoCloseable { return updateBookCallable; } - // ----- moveBook ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Moves a book to another shelf, and returns the new book. @@ -1319,7 +1280,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public Book moveBook(MoveBookRequest request) { + public final Book moveBook(MoveBookRequest request) { return moveBookCallable().call(request); } @@ -1346,8 +1307,6 @@ public class LibraryServiceApi implements AutoCloseable { return moveBookCallable; } - // ----- listStrings ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Lists a primitive resource. To test go page streaming. @@ -1356,12 +1315,11 @@ public class LibraryServiceApi implements AutoCloseable { *

    * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
    *
-   *   for (String elements : libraryServiceApi.listStrings()) {
-   *     // doThingsWith(elements);
+   *   for (String element : libraryServiceApi.listStrings()) {
+   *     // doThingsWith(element);
    *   }
    * }
    * 
- * * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ public final PageAccessor listStrings() { @@ -1381,8 +1339,8 @@ public class LibraryServiceApi implements AutoCloseable { * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) { * ListStringsRequest request = ListStringsRequest.newBuilder() * .build(); - * for (String elements : libraryServiceApi.listStrings(request)) { - * // doThingsWith(elements); + * for (String element : libraryServiceApi.listStrings(request)) { + * // doThingsWith(element); * } * } * @@ -1406,8 +1364,8 @@ public class LibraryServiceApi implements AutoCloseable { * .build(); * ListenableFuture<PageAccessor<String>> future = libraryServiceApi.listStringsPagedCallable().futureCall(request); * // Do something - * for (String elements : future.get()) { - * // doThingsWith(elements); + * for (String element : future.get()) { + * // doThingsWith(element); * } * } * @@ -1427,8 +1385,8 @@ public class LibraryServiceApi implements AutoCloseable { * .build(); * while (true) { * ListStringsResponse response = libraryServiceApi.listStringsCallable().call(request); - * for (String elements : response.getStringsList()) { - * // doThingsWith(elements); + * for (String element : response.getStringsList()) { + * // doThingsWith(element); * } * String nextPageToken = response.getNextPageToken(); * if (!Strings.isNullOrEmpty(nextPageToken)) { @@ -1444,8 +1402,6 @@ public class LibraryServiceApi implements AutoCloseable { return listStringsCallable; } - // ----- addComments ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Adds comments to a book @@ -1469,7 +1425,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final void addComments(String name, List comments) { BOOK_PATH_TEMPLATE.validate(name); - AddCommentsRequest request = AddCommentsRequest.newBuilder() .setName(name) @@ -1502,7 +1457,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public void addComments(AddCommentsRequest request) { + public final void addComments(AddCommentsRequest request) { addCommentsCallable().call(request); } @@ -1533,8 +1488,6 @@ public class LibraryServiceApi implements AutoCloseable { return addCommentsCallable; } - // ----- getBookFromArchive ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Gets a book from an archive. @@ -1577,7 +1530,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - private Book getBookFromArchive(GetBookFromArchiveRequest request) { + private final Book getBookFromArchive(GetBookFromArchiveRequest request) { return getBookFromArchiveCallable().call(request); } @@ -1602,8 +1555,6 @@ public class LibraryServiceApi implements AutoCloseable { return getBookFromArchiveCallable; } - // ----- updateBookIndex ----- - // AUTO-GENERATED DOCUMENTATION AND METHOD /** * Updates the index of a book. @@ -1627,8 +1578,6 @@ public class LibraryServiceApi implements AutoCloseable { */ public final void updateBookIndex(String name, String indexName, Map indexMap) { BOOK_PATH_TEMPLATE.validate(name); - - UpdateBookIndexRequest request = UpdateBookIndexRequest.newBuilder() .setName(name) @@ -1662,7 +1611,7 @@ public class LibraryServiceApi implements AutoCloseable { * @param request The request object containing all of the parameters for the API call. * @throws com.google.api.gax.grpc.ApiException if the remote call fails */ - public void updateBookIndex(UpdateBookIndexRequest request) { + public final void updateBookIndex(UpdateBookIndexRequest request) { updateBookIndexCallable().call(request); } @@ -1693,7 +1642,6 @@ public class LibraryServiceApi implements AutoCloseable { return updateBookIndexCallable; } - /** * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately * cancelled. diff --git a/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline index eec969bec7..9d15220668 100644 --- a/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline +++ b/src/test/java/com/google/api/codegen/testdata/java_settings_library.baseline @@ -64,8 +64,6 @@ import java.util.List; import java.util.concurrent.ScheduledExecutorService; import org.joda.time.Duration; - - // AUTO-GENERATED DOCUMENTATION AND CLASS /** * Settings class to configure an instance of {@link LibraryServiceApi}. @@ -81,13 +79,13 @@ import org.joda.time.Duration; * *

The builder of this class is recursive, so contained classes are themselves builders. * When build() is called, the tree of builders is called to create the complete settings - * object. For example, to set the total timeout of CreateShelf to 30 seconds: + * object. For example, to set the total timeout of createShelf to 30 seconds: * *

  * 
  * LibraryServiceSettings.Builder libraryServiceSettingsBuilder =
  *     LibraryServiceSettings.defaultBuilder();
- * libraryServiceSettingsBuilder.CreateShelfSettings().getRetrySettingsBuilder()
+ * libraryServiceSettingsBuilder.createShelfSettings().getRetrySettingsBuilder()
  *     .setTotalTimeout(Duration.standardSeconds(30));
  * LibraryServiceSettings libraryServiceSettings = libraryServiceSettingsBuilder.build();
  * 
@@ -95,7 +93,6 @@ import org.joda.time.Duration;
  */
 @javax.annotation.Generated("by GAPIC")
 public class LibraryServiceSettings extends ServiceApiSettings {
-
   /**
    * The default address of the service.
    */
@@ -126,23 +123,17 @@ public class LibraryServiceSettings extends ServiceApiSettings {
 
   private final SimpleCallSettings createShelfSettings;
   private final SimpleCallSettings getShelfSettings;
-  private final PageStreamingCallSettings
-      listShelvesSettings;
-
+  private final PageStreamingCallSettings listShelvesSettings;
   private final SimpleCallSettings deleteShelfSettings;
   private final SimpleCallSettings mergeShelvesSettings;
   private final SimpleCallSettings createBookSettings;
   private final BundlingCallSettings publishSeriesSettings;
   private final SimpleCallSettings getBookSettings;
-  private final PageStreamingCallSettings
-      listBooksSettings;
-
+  private final PageStreamingCallSettings listBooksSettings;
   private final SimpleCallSettings deleteBookSettings;
   private final SimpleCallSettings updateBookSettings;
   private final SimpleCallSettings moveBookSettings;
-  private final PageStreamingCallSettings
-      listStringsSettings;
-
+  private final PageStreamingCallSettings listStringsSettings;
   private final SimpleCallSettings addCommentsSettings;
   private final SimpleCallSettings getBookFromArchiveSettings;
   private final SimpleCallSettings updateBookIndexSettings;
@@ -164,8 +155,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
   /**
    * Returns the object with the settings used for calls to listShelves.
    */
-  public PageStreamingCallSettings
-      listShelvesSettings() {
+  public PageStreamingCallSettings listShelvesSettings() {
     return listShelvesSettings;
   }
 
@@ -207,8 +197,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
   /**
    * Returns the object with the settings used for calls to listBooks.
    */
-  public PageStreamingCallSettings
-      listBooksSettings() {
+  public PageStreamingCallSettings listBooksSettings() {
     return listBooksSettings;
   }
 
@@ -236,8 +225,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
   /**
    * Returns the object with the settings used for calls to listStrings.
    */
-  public PageStreamingCallSettings
-      listStringsSettings() {
+  public PageStreamingCallSettings listStringsSettings() {
     return listStringsSettings;
   }
 
@@ -262,7 +250,6 @@ public class LibraryServiceSettings extends ServiceApiSettings {
     return updateBookIndexSettings;
   }
 
-
   /**
    * Returns a builder for this class with recommended defaults.
    */
@@ -317,8 +304,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
           return "";
         }
         @Override
-        public ListShelvesRequest injectToken(
-            ListShelvesRequest payload, Object token) {
+        public ListShelvesRequest injectToken(ListShelvesRequest payload, Object token) {
           return ListShelvesRequest
             .newBuilder(payload)
             .setPageToken((String) token)
@@ -341,8 +327,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
           return "";
         }
         @Override
-        public ListBooksRequest injectToken(
-            ListBooksRequest payload, Object token) {
+        public ListBooksRequest injectToken(ListBooksRequest payload, Object token) {
           return ListBooksRequest
             .newBuilder(payload)
             .setPageToken((String) token)
@@ -365,8 +350,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
           return "";
         }
         @Override
-        public ListStringsRequest injectToken(
-            ListStringsRequest payload, Object token) {
+        public ListStringsRequest injectToken(ListStringsRequest payload, Object token) {
           return ListStringsRequest
             .newBuilder(payload)
             .setPageToken((String) token)
@@ -386,7 +370,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
       new BundlingDescriptor() {
         @Override
         public String getBundlePartitionKey(PublishSeriesRequest request) {
-          return request.getEdition() + "|" + request.getName();
+          return request.getEdition() + "|" + request.getName() + "|";
         }
 
         @Override
@@ -445,7 +429,6 @@ public class LibraryServiceSettings extends ServiceApiSettings {
         }
       };
 
-
   /**
    * Builder for LibraryServiceSettings.
    */
@@ -454,20 +437,17 @@ public class LibraryServiceSettings extends ServiceApiSettings {
 
     private SimpleCallSettings.Builder createShelfSettings;
     private SimpleCallSettings.Builder getShelfSettings;
-    private PageStreamingCallSettings.Builder
-        listShelvesSettings;
+    private PageStreamingCallSettings.Builder listShelvesSettings;
     private SimpleCallSettings.Builder deleteShelfSettings;
     private SimpleCallSettings.Builder mergeShelvesSettings;
     private SimpleCallSettings.Builder createBookSettings;
     private BundlingCallSettings.Builder publishSeriesSettings;
     private SimpleCallSettings.Builder getBookSettings;
-    private PageStreamingCallSettings.Builder
-        listBooksSettings;
+    private PageStreamingCallSettings.Builder listBooksSettings;
     private SimpleCallSettings.Builder deleteBookSettings;
     private SimpleCallSettings.Builder updateBookSettings;
     private SimpleCallSettings.Builder moveBookSettings;
-    private PageStreamingCallSettings.Builder
-        listStringsSettings;
+    private PageStreamingCallSettings.Builder listStringsSettings;
     private SimpleCallSettings.Builder addCommentsSettings;
     private SimpleCallSettings.Builder getBookFromArchiveSettings;
     private SimpleCallSettings.Builder updateBookIndexSettings;
@@ -568,6 +548,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
 
     private static Builder createDefault() {
       Builder builder = new Builder();
+
       builder.createShelfSettings()
           .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"))
           .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
@@ -577,8 +558,8 @@ public class LibraryServiceSettings extends ServiceApiSettings {
           .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.listShelvesSettings()
-              .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
-              .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
+          .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
+          .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.deleteShelfSettings()
           .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
@@ -593,23 +574,23 @@ public class LibraryServiceSettings extends ServiceApiSettings {
           .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.publishSeriesSettings().getBundlingSettingsBuilder()
-              .setElementCountThreshold(6)
-              .setElementCountLimit(7)
-              .setRequestByteThreshold(100000)
-              .setRequestByteLimit(150000)
-              .setDelayThreshold(Duration.millis(500))
-              .setBlockingCallCountThreshold(1);
+          .setElementCountThreshold(6)
+          .setElementCountLimit(7)
+          .setRequestByteThreshold(100000)
+          .setRequestByteLimit(150000)
+          .setDelayThreshold(Duration.millis(500))
+          .setBlockingCallCountThreshold(1);
       builder.publishSeriesSettings()
-              .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"))
-              .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
+          .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"))
+          .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.getBookSettings()
           .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
           .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.listBooksSettings()
-              .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
-              .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
+          .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
+          .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.deleteBookSettings()
           .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
@@ -624,8 +605,8 @@ public class LibraryServiceSettings extends ServiceApiSettings {
           .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.listStringsSettings()
-              .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
-              .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
+          .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent"))
+          .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default"));
 
       builder.addCommentsSettings()
           .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent"))
@@ -749,8 +730,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
     /**
      * Returns the builder for the settings used for calls to listShelves.
      */
-    public PageStreamingCallSettings.Builder
-        listShelvesSettings() {
+    public PageStreamingCallSettings.Builder listShelvesSettings() {
       return listShelvesSettings;
     }
 
@@ -792,8 +772,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
     /**
      * Returns the builder for the settings used for calls to listBooks.
      */
-    public PageStreamingCallSettings.Builder
-        listBooksSettings() {
+    public PageStreamingCallSettings.Builder listBooksSettings() {
       return listBooksSettings;
     }
 
@@ -821,8 +800,7 @@ public class LibraryServiceSettings extends ServiceApiSettings {
     /**
      * Returns the builder for the settings used for calls to listStrings.
      */
-    public PageStreamingCallSettings.Builder
-        listStringsSettings() {
+    public PageStreamingCallSettings.Builder listStringsSettings() {
       return listStringsSettings;
     }
 
diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline
deleted file mode 100644
index b83727a11c..0000000000
--- a/src/test/java/com/google/api/codegen/testdata/java_surface_xapi_library.baseline
+++ /dev/null
@@ -1,1656 +0,0 @@
-============== file: src/main/java/com/google/gcloud/pubsub/spi/LibraryServiceApi.java ==============
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gcloud.pubsub.spi;
-
-import com.google.api.gax.core.PageAccessor;
-import com.google.api.gax.grpc.ApiCallable;
-import com.google.api.gax.protobuf.PathTemplate;
-import com.google.example.library.v1.AddCommentsRequest;
-import com.google.example.library.v1.Book;
-import com.google.example.library.v1.Comment;
-import com.google.example.library.v1.CreateBookRequest;
-import com.google.example.library.v1.CreateShelfRequest;
-import com.google.example.library.v1.DeleteBookRequest;
-import com.google.example.library.v1.DeleteShelfRequest;
-import com.google.example.library.v1.GetBookFromArchiveRequest;
-import com.google.example.library.v1.GetBookRequest;
-import com.google.example.library.v1.GetShelfRequest;
-import com.google.example.library.v1.ListBooksRequest;
-import com.google.example.library.v1.ListBooksResponse;
-import com.google.example.library.v1.ListShelvesRequest;
-import com.google.example.library.v1.ListShelvesResponse;
-import com.google.example.library.v1.ListStringsRequest;
-import com.google.example.library.v1.ListStringsResponse;
-import com.google.example.library.v1.MergeShelvesRequest;
-import com.google.example.library.v1.MoveBookRequest;
-import com.google.example.library.v1.PublishSeriesRequest;
-import com.google.example.library.v1.PublishSeriesResponse;
-import com.google.example.library.v1.Shelf;
-import com.google.example.library.v1.SomeMessage;
-import com.google.example.library.v1.UpdateBookIndexRequest;
-import com.google.example.library.v1.UpdateBookIndexRequest.IndexMapEntry;
-import com.google.example.library.v1.UpdateBookRequest;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.Empty;
-import com.google.protobuf.FieldMask;
-import io.grpc.ManagedChannel;
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ScheduledExecutorService;
-
-// AUTO-GENERATED DOCUMENTATION AND SERVICE
-/**
- * Service Description: This API represents a simple digital library.  It lets you manage Shelf
- * resources and Book resources in the library. It defines the following
- * resource model:
- *
- * - The API has a collection of [Shelf][google.example.library.v1.Shelf]
- *   resources, named ``bookShelves/*``
- *
- * - Each Shelf has a collection of [Book][google.example.library.v1.Book]
- *   resources, named `bookShelves/*/books/*`
- *
- * Check out [cloud docs!](/library/example/link).
- * This is [not a cloud link](http://www.google.com).
- *
- * 

This class provides the ability to make remote calls to the backing service through method - * calls that map to API methods. Sample code to get started: - * - *

- * 
- * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
- *   Shelf shelf = Shelf.newBuilder().build();
- *   Shelf response = libraryServiceApi.createShelf(shelf);
- * }
- * 
- * 
- * - *

Note: close() needs to be called on the libraryServiceApi object to clean up resources such - * as threads. In the example above, try-with-resources is used, which automatically calls - * close(). - * - *

The surface of this class includes several types of Java methods for each of the API's methods: - * - *

    - *
  1. A "flattened" method. With this type of method, the fields of the request type have been - * converted into function parameters. It may be the case that not all fields are available - * as parameters, and not every API method will have a flattened method entry point. - *
  2. A "request object" method. This type of method only takes one parameter, a request - * object, which must be constructed before the call. Not every API method will have a request - * object method. - *
  3. A "callable" method. This type of method takes no parameters and returns an immutable - * ApiCallable object, which can be used to initiate calls to the service. - *
- * - *

See the individual methods for example code. - * - *

Many parameters require resource names to be formatted in a particular way. To assist - * with these names, this class includes a format method for each type of name, and additionally - * a parse method to extract the individual identifiers contained within names that are - * returned. - * - *

This class can be customized by passing in a custom instance of LibraryServiceSettings to - * create(). For example: - * - *

- * 
- * LibraryServiceSettings libraryServiceSettings = LibraryServiceSettings.defaultBuilder()
- *     .provideChannelWith(myCredentials)
- *     .build();
- * LibraryServiceApi libraryServiceApi = LibraryServiceApi.create(libraryServiceSettings);
- * 
- * 
- */ -@javax.annotation.Generated("by GAPIC") -public class LibraryServiceApi implements AutoCloseable { - private final LibraryServiceSettings settings; - private final ManagedChannel channel; - private final ScheduledExecutorService executor; - private final List closeables = new ArrayList<>(); - - private final ApiCallable createShelfCallable; - private final ApiCallable getShelfCallable; - private final ApiCallable listShelvesCallable; - private final ApiCallable> listShelvesPagedCallable; - private final ApiCallable deleteShelfCallable; - private final ApiCallable mergeShelvesCallable; - private final ApiCallable createBookCallable; - private final ApiCallable publishSeriesCallable; - private final ApiCallable getBookCallable; - private final ApiCallable listBooksCallable; - private final ApiCallable> listBooksPagedCallable; - private final ApiCallable deleteBookCallable; - private final ApiCallable updateBookCallable; - private final ApiCallable moveBookCallable; - private final ApiCallable listStringsCallable; - private final ApiCallable> listStringsPagedCallable; - private final ApiCallable addCommentsCallable; - private final ApiCallable getBookFromArchiveCallable; - private final ApiCallable updateBookIndexCallable; - - public final LibraryServiceSettings getSettings() { - return settings; - } - - private static final PathTemplate SHELF_PATH_TEMPLATE = - PathTemplate.createWithoutUrlEncoding("shelves/{shelf}"); - - private static final PathTemplate BOOK_PATH_TEMPLATE = - PathTemplate.createWithoutUrlEncoding("shelves/{shelf}/books/{book}"); - - private static final PathTemplate ARCHIVED_BOOK_PATH_TEMPLATE = - PathTemplate.createWithoutUrlEncoding("archives/{archive_path=**}/books/{book}"); - - /** - * Formats a string containing the fully-qualified path to represent - * a shelf resource. - */ - public static final String formatShelfName(String shelf) { - return SHELF_PATH_TEMPLATE.instantiate( - "shelf", shelf); - } - - /** - * Formats a string containing the fully-qualified path to represent - * a book resource. - */ - public static final String formatBookName(String shelf, String book) { - return BOOK_PATH_TEMPLATE.instantiate( - "shelf", shelf, - "book", book); - } - - /** - * Formats a string containing the fully-qualified path to represent - * a archived_book resource. - */ - public static final String formatArchivedBookName(String archivePath, String book) { - return ARCHIVED_BOOK_PATH_TEMPLATE.instantiate( - "archive_path", archivePath, - "book", book); - } - - /** - * Parses the shelf from the given fully-qualified path which - * represents a shelf resource. - */ - public static final String parseShelfFromShelfName(String shelfName) { - return SHELF_PATH_TEMPLATE.parse(shelfName).get("shelf"); - } - - /** - * Parses the shelf from the given fully-qualified path which - * represents a book resource. - */ - public static final String parseShelfFromBookName(String bookName) { - return BOOK_PATH_TEMPLATE.parse(bookName).get("shelf"); - } - - /** - * Parses the book from the given fully-qualified path which - * represents a book resource. - */ - public static final String parseBookFromBookName(String bookName) { - return BOOK_PATH_TEMPLATE.parse(bookName).get("book"); - } - - /** - * Parses the archive_path from the given fully-qualified path which - * represents a archivedBook resource. - */ - public static final String parseArchivePathFromArchivedBookName(String archivedBookName) { - return ARCHIVED_BOOK_PATH_TEMPLATE.parse(archivedBookName).get("archive_path"); - } - - /** - * Parses the book from the given fully-qualified path which - * represents a archivedBook resource. - */ - public static final String parseBookFromArchivedBookName(String archivedBookName) { - return ARCHIVED_BOOK_PATH_TEMPLATE.parse(archivedBookName).get("book"); - } - - /** - * Constructs an instance of LibraryServiceApi with default settings. - */ - public static final LibraryServiceApi createWithDefaults() throws IOException { - return create(LibraryServiceSettings.defaultBuilder().build()); - } - - /** - * Constructs an instance of LibraryServiceApi, using the given settings. - * The channels are created based on the settings passed in, or defaults for any - * settings that are not set. - */ - public static final LibraryServiceApi create(LibraryServiceSettings settings) throws IOException { - return new LibraryServiceApi(settings); - } - - /** - * Constructs an instance of LibraryServiceApi, using the given settings. - * This is protected so that it easy to make a subclass, but otherwise, the static - * factory methods should be preferred. - */ - protected LibraryServiceApi(LibraryServiceSettings settings) throws IOException { - this.settings = settings; - this.executor = settings.getExecutorProvider().getOrBuildExecutor(); - this.channel = settings.getChannelProvider().getOrBuildChannel(this.executor); - - this.createShelfCallable = ApiCallable.create(settings.createShelfSettings(), this.channel, this.executor); - this.getShelfCallable = ApiCallable.create(settings.getShelfSettings(), this.channel, this.executor); - this.listShelvesCallable = ApiCallable.create(settings.listShelvesSettings(), this.channel, this.executor); - this.listShelvesPagedCallable = - ApiCallable.createPagedVariant(settings.listShelvesSettings(), this.channel, this.executor); - this.deleteShelfCallable = ApiCallable.create(settings.deleteShelfSettings(), this.channel, this.executor); - this.mergeShelvesCallable = ApiCallable.create(settings.mergeShelvesSettings(), this.channel, this.executor); - this.createBookCallable = ApiCallable.create(settings.createBookSettings(), this.channel, this.executor); - this.publishSeriesCallable = ApiCallable.create(settings.publishSeriesSettings(), this.channel, this.executor); - if (settings.publishSeriesSettings().getBundlerFactory() != null) { - closeables.add(settings.publishSeriesSettings().getBundlerFactory()); - } - this.getBookCallable = ApiCallable.create(settings.getBookSettings(), this.channel, this.executor); - this.listBooksCallable = ApiCallable.create(settings.listBooksSettings(), this.channel, this.executor); - this.listBooksPagedCallable = - ApiCallable.createPagedVariant(settings.listBooksSettings(), this.channel, this.executor); - this.deleteBookCallable = ApiCallable.create(settings.deleteBookSettings(), this.channel, this.executor); - this.updateBookCallable = ApiCallable.create(settings.updateBookSettings(), this.channel, this.executor); - this.moveBookCallable = ApiCallable.create(settings.moveBookSettings(), this.channel, this.executor); - this.listStringsCallable = ApiCallable.create(settings.listStringsSettings(), this.channel, this.executor); - this.listStringsPagedCallable = - ApiCallable.createPagedVariant(settings.listStringsSettings(), this.channel, this.executor); - this.addCommentsCallable = ApiCallable.create(settings.addCommentsSettings(), this.channel, this.executor); - this.getBookFromArchiveCallable = ApiCallable.create(settings.getBookFromArchiveSettings(), this.channel, this.executor); - this.updateBookIndexCallable = ApiCallable.create(settings.updateBookIndexSettings(), this.channel, this.executor); - - if (settings.getChannelProvider().shouldAutoClose()) { - closeables.add( - new Closeable() { - @Override - public void close() throws IOException { - channel.shutdown(); - } - }); - } - if (settings.getExecutorProvider().shouldAutoClose()) { - closeables.add( - new Closeable() { - @Override - public void close() throws IOException { - executor.shutdown(); - } - }); - } - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a shelf, and returns the new Shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   Shelf shelf = Shelf.newBuilder().build();
-   *   Shelf response = libraryServiceApi.createShelf(shelf);
-   * }
-   * 
- * - * @param shelf The shelf to create. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf createShelf(Shelf shelf) { - CreateShelfRequest request = - CreateShelfRequest.newBuilder() - .setShelf(shelf) - .build(); - return createShelf(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a shelf, and returns the new Shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   Shelf shelf = Shelf.newBuilder().build();
-   *   CreateShelfRequest request = CreateShelfRequest.newBuilder()
-   *     .setShelf(shelf)
-   *     .build();
-   *   Shelf response = libraryServiceApi.createShelf(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final Shelf createShelf(CreateShelfRequest request) { - return createShelfCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a shelf, and returns the new Shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   Shelf shelf = Shelf.newBuilder().build();
-   *   CreateShelfRequest request = CreateShelfRequest.newBuilder()
-   *     .setShelf(shelf)
-   *     .build();
-   *   ListenableFuture<Shelf> future = libraryServiceApi.createShelfCallable().futureCall(request);
-   *   // Do something
-   *   Shelf response = future.get();
-   * }
-   * 
- */ - public final ApiCallable createShelfCallable() { - return createShelfCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   Shelf response = libraryServiceApi.getShelf(formattedName);
-   * }
-   * 
- * - * @param name The name of the shelf to retrieve. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf getShelf(String name) { - SHELF_PATH_TEMPLATE.validate(name); - GetShelfRequest request = - GetShelfRequest.newBuilder() - .setName(name) - .build(); - return getShelf(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   SomeMessage message = SomeMessage.newBuilder().build();
-   *   Shelf response = libraryServiceApi.getShelf(formattedName, message);
-   * }
-   * 
- * - * @param name The name of the shelf to retrieve. - * @param message Field to verify that message-type query parameter gets flattened. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf getShelf(String name, SomeMessage message) { - SHELF_PATH_TEMPLATE.validate(name); - GetShelfRequest request = - GetShelfRequest.newBuilder() - .setName(name) - .setMessage(message) - .build(); - return getShelf(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   SomeMessage message = SomeMessage.newBuilder().build();
-   *   com.google.example.library.v1.StringBuilder stringBuilder = com.google.example.library.v1.StringBuilder.newBuilder().build();
-   *   Shelf response = libraryServiceApi.getShelf(formattedName, message, stringBuilder);
-   * }
-   * 
- * - * @param name The name of the shelf to retrieve. - * @param message Field to verify that message-type query parameter gets flattened. - * @param stringBuilder - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf getShelf(String name, SomeMessage message, com.google.example.library.v1.StringBuilder stringBuilder) { - SHELF_PATH_TEMPLATE.validate(name); - GetShelfRequest request = - GetShelfRequest.newBuilder() - .setName(name) - .setMessage(message) - .setStringBuilder(stringBuilder) - .build(); - return getShelf(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   String options = "";
-   *   GetShelfRequest request = GetShelfRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setOptions(options)
-   *     .build();
-   *   Shelf response = libraryServiceApi.getShelf(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf getShelf(GetShelfRequest request) { - return getShelfCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   String options = "";
-   *   GetShelfRequest request = GetShelfRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setOptions(options)
-   *     .build();
-   *   ListenableFuture<Shelf> future = libraryServiceApi.getShelfCallable().futureCall(request);
-   *   // Do something
-   *   Shelf response = future.get();
-   * }
-   * 
- */ - public final ApiCallable getShelfCallable() { - return getShelfCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists shelves. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *
-   *   for (Shelf element : libraryServiceApi.listShelves()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final PageAccessor listShelves() { - ListShelvesRequest request = - ListShelvesRequest.newBuilder() - - .build(); - return listShelves(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists shelves. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   ListShelvesRequest request = ListShelvesRequest.newBuilder()
-   *     .build();
-   *   for (Shelf element : libraryServiceApi.listShelves(request)) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final PageAccessor listShelves(ListShelvesRequest request) { - return listShelvesPagedCallable() - .call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists shelves. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   ListShelvesRequest request = ListShelvesRequest.newBuilder()
-   *     .build();
-   *   ListenableFuture<PageAccessor<Shelf>> future = libraryServiceApi.listShelvesPagedCallable().futureCall(request);
-   *   // Do something
-   *   for (Shelf element : future.get()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- */ - public final ApiCallable> listShelvesPagedCallable() { - return listShelvesPagedCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists shelves. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   ListShelvesRequest request = ListShelvesRequest.newBuilder()
-   *     .build();
-   *   while (true) {
-   *     ListShelvesResponse response = libraryServiceApi.listShelvesCallable().call(request);
-   *     for (Shelf element : response.getShelvesList()) {
-   *       // doThingsWith(element);
-   *     }
-   *     String nextPageToken = response.getNextPageToken();
-   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
-   *       request = request.toBuilder().setPageToken(nextPageToken).build();
-   *     } else {
-   *       break;
-   *     }
-   *   }
-   * }
-   * 
- */ - public final ApiCallable listShelvesCallable() { - return listShelvesCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Deletes a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   libraryServiceApi.deleteShelf(formattedName);
-   * }
-   * 
- * - * @param name The name of the shelf to delete. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final void deleteShelf(String name) { - SHELF_PATH_TEMPLATE.validate(name); - DeleteShelfRequest request = - DeleteShelfRequest.newBuilder() - .setName(name) - .build(); - deleteShelf(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Deletes a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   DeleteShelfRequest request = DeleteShelfRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   libraryServiceApi.deleteShelf(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final void deleteShelf(DeleteShelfRequest request) { - deleteShelfCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Deletes a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   DeleteShelfRequest request = DeleteShelfRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   ListenableFuture<Void> future = libraryServiceApi.deleteShelfCallable().futureCall(request);
-   *   // Do something
-   *   future.get();
-   * }
-   * 
- */ - public final ApiCallable deleteShelfCallable() { - return deleteShelfCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Merges two shelves by adding all books from the shelf named - * `other_shelf_name` to shelf `name`, and deletes - * `other_shelf_name`. Returns the updated shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   Shelf response = libraryServiceApi.mergeShelves(formattedName, formattedOtherShelfName);
-   * }
-   * 
- * - * @param name The name of the shelf we're adding books to. - * @param otherShelfName The name of the shelf we're removing books from and deleting. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf mergeShelves(String name, String otherShelfName) { - SHELF_PATH_TEMPLATE.validate(name); - SHELF_PATH_TEMPLATE.validate(otherShelfName); - MergeShelvesRequest request = - MergeShelvesRequest.newBuilder() - .setName(name) - .setOtherShelfName(otherShelfName) - .build(); - return mergeShelves(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Merges two shelves by adding all books from the shelf named - * `other_shelf_name` to shelf `name`, and deletes - * `other_shelf_name`. Returns the updated shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   MergeShelvesRequest request = MergeShelvesRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setOtherShelfName(formattedOtherShelfName)
-   *     .build();
-   *   Shelf response = libraryServiceApi.mergeShelves(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Shelf mergeShelves(MergeShelvesRequest request) { - return mergeShelvesCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Merges two shelves by adding all books from the shelf named - * `other_shelf_name` to shelf `name`, and deletes - * `other_shelf_name`. Returns the updated shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   MergeShelvesRequest request = MergeShelvesRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setOtherShelfName(formattedOtherShelfName)
-   *     .build();
-   *   ListenableFuture<Shelf> future = libraryServiceApi.mergeShelvesCallable().futureCall(request);
-   *   // Do something
-   *   Shelf response = future.get();
-   * }
-   * 
- */ - public final ApiCallable mergeShelvesCallable() { - return mergeShelvesCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   Book book = Book.newBuilder().build();
-   *   Book response = libraryServiceApi.createBook(formattedName, book);
-   * }
-   * 
- * - * @param name The name of the shelf in which the book is created. - * @param book The book to create. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book createBook(String name, Book book) { - SHELF_PATH_TEMPLATE.validate(name); - CreateBookRequest request = - CreateBookRequest.newBuilder() - .setName(name) - .setBook(book) - .build(); - return createBook(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   Book book = Book.newBuilder().build();
-   *   CreateBookRequest request = CreateBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setBook(book)
-   *     .build();
-   *   Book response = libraryServiceApi.createBook(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book createBook(CreateBookRequest request) { - return createBookCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   Book book = Book.newBuilder().build();
-   *   CreateBookRequest request = CreateBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setBook(book)
-   *     .build();
-   *   ListenableFuture<Book> future = libraryServiceApi.createBookCallable().futureCall(request);
-   *   // Do something
-   *   Book response = future.get();
-   * }
-   * 
- */ - public final ApiCallable createBookCallable() { - return createBookCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a series of books. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   Shelf shelf = Shelf.newBuilder().build();
-   *   List<Book> books = new ArrayList<>();
-   *   int edition = 0;
-   *   PublishSeriesResponse response = libraryServiceApi.publishSeries(shelf, books, edition);
-   * }
-   * 
- * - * @param shelf The shelf in which the series is created. - * @param books The books to publish in the series. - * @param edition The edition of the series - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final PublishSeriesResponse publishSeries(Shelf shelf, List books, int edition) { - PublishSeriesRequest request = - PublishSeriesRequest.newBuilder() - .setShelf(shelf) - .addAllBooks(books) - .setEdition(edition) - .build(); - return publishSeries(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a series of books. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   Shelf shelf = Shelf.newBuilder().build();
-   *   List<Book> books = new ArrayList<>();
-   *   PublishSeriesRequest request = PublishSeriesRequest.newBuilder()
-   *     .setShelf(shelf)
-   *     .addAllBooks(books)
-   *     .build();
-   *   PublishSeriesResponse response = libraryServiceApi.publishSeries(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final PublishSeriesResponse publishSeries(PublishSeriesRequest request) { - return publishSeriesCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Creates a series of books. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   Shelf shelf = Shelf.newBuilder().build();
-   *   List<Book> books = new ArrayList<>();
-   *   PublishSeriesRequest request = PublishSeriesRequest.newBuilder()
-   *     .setShelf(shelf)
-   *     .addAllBooks(books)
-   *     .build();
-   *   ListenableFuture<PublishSeriesResponse> future = libraryServiceApi.publishSeriesCallable().futureCall(request);
-   *   // Do something
-   *   PublishSeriesResponse response = future.get();
-   * }
-   * 
- */ - public final ApiCallable publishSeriesCallable() { - return publishSeriesCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   Book response = libraryServiceApi.getBook(formattedName);
-   * }
-   * 
- * - * @param name The name of the book to retrieve. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book getBook(String name) { - BOOK_PATH_TEMPLATE.validate(name); - GetBookRequest request = - GetBookRequest.newBuilder() - .setName(name) - .build(); - return getBook(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   GetBookRequest request = GetBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   Book response = libraryServiceApi.getBook(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final Book getBook(GetBookRequest request) { - return getBookCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   GetBookRequest request = GetBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   ListenableFuture<Book> future = libraryServiceApi.getBookCallable().futureCall(request);
-   *   // Do something
-   *   Book response = future.get();
-   * }
-   * 
- */ - public final ApiCallable getBookCallable() { - return getBookCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists books in a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   String filter = "";
-   *   for (Book element : libraryServiceApi.listBooks(formattedName, filter)) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * - * @param name The name of the shelf whose books we'd like to list. - * @param filter To test python built-in wrapping. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final PageAccessor listBooks(String name, String filter) { - SHELF_PATH_TEMPLATE.validate(name); - ListBooksRequest request = - ListBooksRequest.newBuilder() - .setName(name) - .setFilter(filter) - .build(); - return listBooks(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists books in a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   ListBooksRequest request = ListBooksRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   for (Book element : libraryServiceApi.listBooks(request)) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final PageAccessor listBooks(ListBooksRequest request) { - return listBooksPagedCallable() - .call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists books in a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   ListBooksRequest request = ListBooksRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   ListenableFuture<PageAccessor<Book>> future = libraryServiceApi.listBooksPagedCallable().futureCall(request);
-   *   // Do something
-   *   for (Book element : future.get()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- */ - public final ApiCallable> listBooksPagedCallable() { - return listBooksPagedCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists books in a shelf. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   ListBooksRequest request = ListBooksRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   while (true) {
-   *     ListBooksResponse response = libraryServiceApi.listBooksCallable().call(request);
-   *     for (Book element : response.getBooksList()) {
-   *       // doThingsWith(element);
-   *     }
-   *     String nextPageToken = response.getNextPageToken();
-   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
-   *       request = request.toBuilder().setPageToken(nextPageToken).build();
-   *     } else {
-   *       break;
-   *     }
-   *   }
-   * }
-   * 
- */ - public final ApiCallable listBooksCallable() { - return listBooksCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Deletes a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   libraryServiceApi.deleteBook(formattedName);
-   * }
-   * 
- * - * @param name The name of the book to delete. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final void deleteBook(String name) { - BOOK_PATH_TEMPLATE.validate(name); - DeleteBookRequest request = - DeleteBookRequest.newBuilder() - .setName(name) - .build(); - deleteBook(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Deletes a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   DeleteBookRequest request = DeleteBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   libraryServiceApi.deleteBook(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final void deleteBook(DeleteBookRequest request) { - deleteBookCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Deletes a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   DeleteBookRequest request = DeleteBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   ListenableFuture<Void> future = libraryServiceApi.deleteBookCallable().futureCall(request);
-   *   // Do something
-   *   future.get();
-   * }
-   * 
- */ - public final ApiCallable deleteBookCallable() { - return deleteBookCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   Book book = Book.newBuilder().build();
-   *   Book response = libraryServiceApi.updateBook(formattedName, book);
-   * }
-   * 
- * - * @param name The name of the book to update. - * @param book The book to update with. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book updateBook(String name, Book book) { - BOOK_PATH_TEMPLATE.validate(name); - UpdateBookRequest request = - UpdateBookRequest.newBuilder() - .setName(name) - .setBook(book) - .build(); - return updateBook(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   Book book = Book.newBuilder().build();
-   *   FieldMask updateMask = FieldMask.newBuilder().build();
-   *   com.google.example.library.v1.FieldMask physicalMask = com.google.example.library.v1.FieldMask.newBuilder().build();
-   *   Book response = libraryServiceApi.updateBook(formattedName, book, updateMask, physicalMask);
-   * }
-   * 
- * - * @param name The name of the book to update. - * @param book The book to update with. - * @param updateMask A field mask to apply, rendered as an HTTP parameter. - * @param physicalMask To test Python import clash resolution. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book updateBook(String name, Book book, FieldMask updateMask, com.google.example.library.v1.FieldMask physicalMask) { - BOOK_PATH_TEMPLATE.validate(name); - UpdateBookRequest request = - UpdateBookRequest.newBuilder() - .setName(name) - .setBook(book) - .setUpdateMask(updateMask) - .setPhysicalMask(physicalMask) - .build(); - return updateBook(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   Book book = Book.newBuilder().build();
-   *   UpdateBookRequest request = UpdateBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setBook(book)
-   *     .build();
-   *   Book response = libraryServiceApi.updateBook(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book updateBook(UpdateBookRequest request) { - return updateBookCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   Book book = Book.newBuilder().build();
-   *   UpdateBookRequest request = UpdateBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setBook(book)
-   *     .build();
-   *   ListenableFuture<Book> future = libraryServiceApi.updateBookCallable().futureCall(request);
-   *   // Do something
-   *   Book response = future.get();
-   * }
-   * 
- */ - public final ApiCallable updateBookCallable() { - return updateBookCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Moves a book to another shelf, and returns the new book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   Book response = libraryServiceApi.moveBook(formattedName, formattedOtherShelfName);
-   * }
-   * 
- * - * @param name The name of the book to move. - * @param otherShelfName The name of the destination shelf. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book moveBook(String name, String otherShelfName) { - BOOK_PATH_TEMPLATE.validate(name); - SHELF_PATH_TEMPLATE.validate(otherShelfName); - MoveBookRequest request = - MoveBookRequest.newBuilder() - .setName(name) - .setOtherShelfName(otherShelfName) - .build(); - return moveBook(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Moves a book to another shelf, and returns the new book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   MoveBookRequest request = MoveBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setOtherShelfName(formattedOtherShelfName)
-   *     .build();
-   *   Book response = libraryServiceApi.moveBook(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book moveBook(MoveBookRequest request) { - return moveBookCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Moves a book to another shelf, and returns the new book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   String formattedOtherShelfName = LibraryServiceApi.formatShelfName("[SHELF]");
-   *   MoveBookRequest request = MoveBookRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setOtherShelfName(formattedOtherShelfName)
-   *     .build();
-   *   ListenableFuture<Book> future = libraryServiceApi.moveBookCallable().futureCall(request);
-   *   // Do something
-   *   Book response = future.get();
-   * }
-   * 
- */ - public final ApiCallable moveBookCallable() { - return moveBookCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists a primitive resource. To test go page streaming. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *
-   *   for (String element : libraryServiceApi.listStrings()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final PageAccessor listStrings() { - ListStringsRequest request = - ListStringsRequest.newBuilder() - - .build(); - return listStrings(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists a primitive resource. To test go page streaming. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   ListStringsRequest request = ListStringsRequest.newBuilder()
-   *     .build();
-   *   for (String element : libraryServiceApi.listStrings(request)) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final PageAccessor listStrings(ListStringsRequest request) { - return listStringsPagedCallable() - .call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists a primitive resource. To test go page streaming. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   ListStringsRequest request = ListStringsRequest.newBuilder()
-   *     .build();
-   *   ListenableFuture<PageAccessor<String>> future = libraryServiceApi.listStringsPagedCallable().futureCall(request);
-   *   // Do something
-   *   for (String element : future.get()) {
-   *     // doThingsWith(element);
-   *   }
-   * }
-   * 
- */ - public final ApiCallable> listStringsPagedCallable() { - return listStringsPagedCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Lists a primitive resource. To test go page streaming. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   ListStringsRequest request = ListStringsRequest.newBuilder()
-   *     .build();
-   *   while (true) {
-   *     ListStringsResponse response = libraryServiceApi.listStringsCallable().call(request);
-   *     for (String element : response.getStringsList()) {
-   *       // doThingsWith(element);
-   *     }
-   *     String nextPageToken = response.getNextPageToken();
-   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
-   *       request = request.toBuilder().setPageToken(nextPageToken).build();
-   *     } else {
-   *       break;
-   *     }
-   *   }
-   * }
-   * 
- */ - public final ApiCallable listStringsCallable() { - return listStringsCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Adds comments to a book - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   ByteString comment = ByteString.copyFromUtf8("");
-   *   Comment commentsElement = Comment.newBuilder()
-   *     .setComment(comment)
-   *     .build();
-   *   List<Comment> comments = Arrays.asList(commentsElement);
-   *   libraryServiceApi.addComments(formattedName, comments);
-   * }
-   * 
- * - * @param name - * @param comments - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final void addComments(String name, List comments) { - BOOK_PATH_TEMPLATE.validate(name); - AddCommentsRequest request = - AddCommentsRequest.newBuilder() - .setName(name) - .addAllComments(comments) - .build(); - addComments(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Adds comments to a book - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   ByteString comment = ByteString.copyFromUtf8("");
-   *   Comment commentsElement = Comment.newBuilder()
-   *     .setComment(comment)
-   *     .build();
-   *   List<Comment> comments = Arrays.asList(commentsElement);
-   *   AddCommentsRequest request = AddCommentsRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .addAllComments(comments)
-   *     .build();
-   *   libraryServiceApi.addComments(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final void addComments(AddCommentsRequest request) { - addCommentsCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Adds comments to a book - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   ByteString comment = ByteString.copyFromUtf8("");
-   *   Comment commentsElement = Comment.newBuilder()
-   *     .setComment(comment)
-   *     .build();
-   *   List<Comment> comments = Arrays.asList(commentsElement);
-   *   AddCommentsRequest request = AddCommentsRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .addAllComments(comments)
-   *     .build();
-   *   ListenableFuture<Void> future = libraryServiceApi.addCommentsCallable().futureCall(request);
-   *   // Do something
-   *   future.get();
-   * }
-   * 
- */ - public final ApiCallable addCommentsCallable() { - return addCommentsCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a book from an archive. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatArchivedBookName("[ARCHIVE_PATH]", "[BOOK]");
-   *   Book response = libraryServiceApi.getBookFromArchive(formattedName);
-   * }
-   * 
- * - * @param name The name of the book to retrieve. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final Book getBookFromArchive(String name) { - ARCHIVED_BOOK_PATH_TEMPLATE.validate(name); - GetBookFromArchiveRequest request = - GetBookFromArchiveRequest.newBuilder() - .setName(name) - .build(); - return getBookFromArchive(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a book from an archive. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatArchivedBookName("[ARCHIVE_PATH]", "[BOOK]");
-   *   GetBookFromArchiveRequest request = GetBookFromArchiveRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   Book response = libraryServiceApi.getBookFromArchive(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - private final Book getBookFromArchive(GetBookFromArchiveRequest request) { - return getBookFromArchiveCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Gets a book from an archive. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatArchivedBookName("[ARCHIVE_PATH]", "[BOOK]");
-   *   GetBookFromArchiveRequest request = GetBookFromArchiveRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .build();
-   *   ListenableFuture<Book> future = libraryServiceApi.getBookFromArchiveCallable().futureCall(request);
-   *   // Do something
-   *   Book response = future.get();
-   * }
-   * 
- */ - public final ApiCallable getBookFromArchiveCallable() { - return getBookFromArchiveCallable; - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates the index of a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   String indexName = "default index";
-   *   String indexMapItem = "";
-   *   Map<String, String> indexMap = new HashMap<>();
-   *   indexMap.put("default_key", indexMapItem);
-   *   libraryServiceApi.updateBookIndex(formattedName, indexName, indexMap);
-   * }
-   * 
- * - * @param name The name of the book to update. - * @param indexName The name of the index for the book - * @param indexMap The index to update the book with - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final void updateBookIndex(String name, String indexName, Map indexMap) { - BOOK_PATH_TEMPLATE.validate(name); - UpdateBookIndexRequest request = - UpdateBookIndexRequest.newBuilder() - .setName(name) - .setIndexName(indexName) - .putAllIndexMap(indexMap) - .build(); - updateBookIndex(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates the index of a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   String indexName = "default index";
-   *   String indexMapItem = "";
-   *   Map<String, String> indexMap = new HashMap<>();
-   *   indexMap.put("default_key", indexMapItem);
-   *   UpdateBookIndexRequest request = UpdateBookIndexRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setIndexName(indexName)
-   *     .putAllIndexMap(indexMap)
-   *     .build();
-   *   libraryServiceApi.updateBookIndex(request);
-   * }
-   * 
- * - * @param request The request object containing all of the parameters for the API call. - * @throws com.google.api.gax.grpc.ApiException if the remote call fails - */ - public final void updateBookIndex(UpdateBookIndexRequest request) { - updateBookIndexCallable().call(request); - } - - // AUTO-GENERATED DOCUMENTATION AND METHOD - /** - * Updates the index of a book. - * - * Sample code: - *

-   * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
-   *   String formattedName = LibraryServiceApi.formatBookName("[SHELF]", "[BOOK]");
-   *   String indexName = "default index";
-   *   String indexMapItem = "";
-   *   Map<String, String> indexMap = new HashMap<>();
-   *   indexMap.put("default_key", indexMapItem);
-   *   UpdateBookIndexRequest request = UpdateBookIndexRequest.newBuilder()
-   *     .setName(formattedName)
-   *     .setIndexName(indexName)
-   *     .putAllIndexMap(indexMap)
-   *     .build();
-   *   ListenableFuture<Void> future = libraryServiceApi.updateBookIndexCallable().futureCall(request);
-   *   // Do something
-   *   future.get();
-   * }
-   * 
- */ - public final ApiCallable updateBookIndexCallable() { - return updateBookIndexCallable; - } - - /** - * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately - * cancelled. - */ - @Override - public final void close() throws Exception { - for (AutoCloseable closeable : closeables) { - closeable.close(); - } - } - -} diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline deleted file mode 100644 index 9543ce0c55..0000000000 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xpackage-info_library.baseline +++ /dev/null @@ -1,50 +0,0 @@ -============== file: src/main/java/com/google/gcloud/pubsub/spi/package-info.java ============== -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * A client to Google Example Library API. - * - * The interfaces provided are listed below, along with a usage sample - * - * ================= - * LibraryServiceApi - * ================= - * - * Service Description: This API represents a simple digital library. It lets you manage Shelf - * resources and Book resources in the library. It defines the following - * resource model: - * - * - The API has a collection of [Shelf][google.example.library.v1.Shelf] - * resources, named ``bookShelves/*`` - * - * - Each Shelf has a collection of [Book][google.example.library.v1.Book] - * resources, named `bookShelves/*/books/*` - * - * Check out [cloud docs!](/library/example/link). - * This is [not a cloud link](http://www.google.com). - * - * Sample for LibraryServiceApi: - *
- * 
- * try (LibraryServiceApi libraryServiceApi = LibraryServiceApi.createWithDefaults()) {
- *   Shelf shelf = Shelf.newBuilder().build();
- *   Shelf response = libraryServiceApi.createShelf(shelf);
- * }
- * 
- * 
- * - */ - -package com.google.gcloud.pubsub.spi; diff --git a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline deleted file mode 100644 index a9156922c4..0000000000 --- a/src/test/java/com/google/api/codegen/testdata/java_surface_xsettings_library.baseline +++ /dev/null @@ -1,800 +0,0 @@ -============== file: src/main/java/com/google/gcloud/pubsub/spi/LibraryServiceSettings.java ============== -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.gcloud.pubsub.spi; - -import com.google.api.gax.core.ConnectionSettings; -import com.google.api.gax.core.RetrySettings; -import com.google.api.gax.grpc.ApiCallSettings; -import com.google.api.gax.grpc.BundlingCallSettings; -import com.google.api.gax.grpc.PageStreamingCallSettings; -import com.google.api.gax.grpc.ServiceApiSettings; -import com.google.api.gax.grpc.SimpleCallSettings; -import com.google.auth.Credentials; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.example.library.v1.AddCommentsRequest; -import com.google.example.library.v1.Book; -import com.google.example.library.v1.CreateBookRequest; -import com.google.example.library.v1.CreateShelfRequest; -import com.google.example.library.v1.DeleteBookRequest; -import com.google.example.library.v1.DeleteShelfRequest; -import com.google.example.library.v1.GetBookFromArchiveRequest; -import com.google.example.library.v1.GetBookRequest; -import com.google.example.library.v1.GetShelfRequest; -import com.google.example.library.v1.ListBooksRequest; -import com.google.example.library.v1.ListBooksResponse; -import com.google.example.library.v1.ListShelvesRequest; -import com.google.example.library.v1.ListShelvesResponse; -import com.google.example.library.v1.ListStringsRequest; -import com.google.example.library.v1.ListStringsResponse; -import com.google.example.library.v1.MergeShelvesRequest; -import com.google.example.library.v1.MoveBookRequest; -import com.google.example.library.v1.PublishSeriesRequest; -import com.google.example.library.v1.PublishSeriesResponse; -import com.google.example.library.v1.Shelf; -import com.google.example.library.v1.UpdateBookIndexRequest; -import com.google.example.library.v1.UpdateBookRequest; -import com.google.protobuf.Empty; -import google.example.library.v1.LibraryServiceGrpc; -import io.grpc.ManagedChannel; -import io.grpc.Status; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; -import org.joda.time.Duration; - -@javax.annotation.Generated("by GAPIC") -public class LibraryServiceSettings extends ServiceApiSettings { - /** - * The default address of the service. - */ - public static final String DEFAULT_SERVICE_ADDRESS = "library-example.googleapis.com"; - - /** - * The default port of the service. - */ - public static final int DEFAULT_SERVICE_PORT = 443; - - /** - * The default scopes of the service. - */ - public static final ImmutableList DEFAULT_SERVICE_SCOPES = ImmutableList.builder() - .add("https://www.googleapis.com/auth/cloud-platform") - .add("https://www.googleapis.com/auth/library") - .build(); - - /** - * The default connection settings of the service. - */ - public static final ConnectionSettings DEFAULT_CONNECTION_SETTINGS = - ConnectionSettings.newBuilder() - .setServiceAddress(DEFAULT_SERVICE_ADDRESS) - .setPort(DEFAULT_SERVICE_PORT) - .provideCredentialsWith(DEFAULT_SERVICE_SCOPES) - .build(); - - private final SimpleCallSettings createShelfSettings; - private final SimpleCallSettings getShelfSettings; - private final PageStreamingCallSettings listShelvesSettings; - private final SimpleCallSettings deleteShelfSettings; - private final SimpleCallSettings mergeShelvesSettings; - private final SimpleCallSettings createBookSettings; - private final BundlingCallSettings publishSeriesSettings; - private final SimpleCallSettings getBookSettings; - private final PageStreamingCallSettings listBooksSettings; - private final SimpleCallSettings deleteBookSettings; - private final SimpleCallSettings updateBookSettings; - private final SimpleCallSettings moveBookSettings; - private final PageStreamingCallSettings listStringsSettings; - private final SimpleCallSettings addCommentsSettings; - private final SimpleCallSettings getBookFromArchiveSettings; - private final SimpleCallSettings updateBookIndexSettings; - - /** - * Returns the object with the settings used for calls to createShelf. - */ - public SimpleCallSettings createShelfSettings() { - return createShelfSettings; - } - - /** - * Returns the object with the settings used for calls to getShelf. - */ - public SimpleCallSettings getShelfSettings() { - return getShelfSettings; - } - - /** - * Returns the object with the settings used for calls to listShelves. - */ - public PageStreamingCallSettings listShelvesSettings() { - return listShelvesSettings; - } - - /** - * Returns the object with the settings used for calls to deleteShelf. - */ - public SimpleCallSettings deleteShelfSettings() { - return deleteShelfSettings; - } - - /** - * Returns the object with the settings used for calls to mergeShelves. - */ - public SimpleCallSettings mergeShelvesSettings() { - return mergeShelvesSettings; - } - - /** - * Returns the object with the settings used for calls to createBook. - */ - public SimpleCallSettings createBookSettings() { - return createBookSettings; - } - - /** - * Returns the object with the settings used for calls to publishSeries. - */ - public BundlingCallSettings publishSeriesSettings() { - return publishSeriesSettings; - } - - /** - * Returns the object with the settings used for calls to getBook. - */ - public SimpleCallSettings getBookSettings() { - return getBookSettings; - } - - /** - * Returns the object with the settings used for calls to listBooks. - */ - public PageStreamingCallSettings listBooksSettings() { - return listBooksSettings; - } - - /** - * Returns the object with the settings used for calls to deleteBook. - */ - public SimpleCallSettings deleteBookSettings() { - return deleteBookSettings; - } - - /** - * Returns the object with the settings used for calls to updateBook. - */ - public SimpleCallSettings updateBookSettings() { - return updateBookSettings; - } - - /** - * Returns the object with the settings used for calls to moveBook. - */ - public SimpleCallSettings moveBookSettings() { - return moveBookSettings; - } - - /** - * Returns the object with the settings used for calls to listStrings. - */ - public PageStreamingCallSettings listStringsSettings() { - return listStringsSettings; - } - - /** - * Returns the object with the settings used for calls to addComments. - */ - public SimpleCallSettings addCommentsSettings() { - return addCommentsSettings; - } - - /** - * Returns the object with the settings used for calls to getBookFromArchive. - */ - public SimpleCallSettings getBookFromArchiveSettings() { - return getBookFromArchiveSettings; - } - - /** - * Returns the object with the settings used for calls to updateBookIndex. - */ - public SimpleCallSettings updateBookIndexSettings() { - return updateBookIndexSettings; - } - - /** - * Returns a builder for this class with recommended defaults. - */ - public static Builder defaultBuilder() { - return Builder.createDefault(); - } - - /** - * Returns a new builder for this class. - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Returns a builder containing all the values of this settings class. - */ - public Builder toBuilder() { - return new Builder(this); - } - - private LibraryServiceSettings(Builder settingsBuilder) throws IOException { - super(settingsBuilder.getChannelProvider(), - settingsBuilder.getExecutorProvider(), - settingsBuilder.getGeneratorName(), - settingsBuilder.getGeneratorVersion(), - settingsBuilder.getClientLibName(), - settingsBuilder.getClientLibVersion()); - - createShelfSettings = settingsBuilder.createShelfSettings().build(); - getShelfSettings = settingsBuilder.getShelfSettings().build(); - listShelvesSettings = settingsBuilder.listShelvesSettings().build(); - deleteShelfSettings = settingsBuilder.deleteShelfSettings().build(); - mergeShelvesSettings = settingsBuilder.mergeShelvesSettings().build(); - createBookSettings = settingsBuilder.createBookSettings().build(); - publishSeriesSettings = settingsBuilder.publishSeriesSettings().build(); - getBookSettings = settingsBuilder.getBookSettings().build(); - listBooksSettings = settingsBuilder.listBooksSettings().build(); - deleteBookSettings = settingsBuilder.deleteBookSettings().build(); - updateBookSettings = settingsBuilder.updateBookSettings().build(); - moveBookSettings = settingsBuilder.moveBookSettings().build(); - listStringsSettings = settingsBuilder.listStringsSettings().build(); - addCommentsSettings = settingsBuilder.addCommentsSettings().build(); - getBookFromArchiveSettings = settingsBuilder.getBookFromArchiveSettings().build(); - updateBookIndexSettings = settingsBuilder.updateBookIndexSettings().build(); - } - - private static PageStreamingDescriptor LIST_SHELVES_PAGE_STR_DESC = - new PageStreamingDescriptor() { - @Override - public Object emptyToken() { - return ""; - } - @Override - public ListShelvesRequest injectToken(ListShelvesRequest payload, Object token) { - return ListShelvesRequest - .newBuilder(payload) - .setPageToken((String) token) - .build(); - } - @Override - public Object extractNextToken(ListShelvesResponse payload) { - return payload.getNextPageToken(); - } - @Override - public Iterable extractResources(ListShelvesResponse payload) { - return payload.getShelvesList(); - } - }; - - private static PageStreamingDescriptor LIST_BOOKS_PAGE_STR_DESC = - new PageStreamingDescriptor() { - @Override - public Object emptyToken() { - return ""; - } - @Override - public ListBooksRequest injectToken(ListBooksRequest payload, Object token) { - return ListBooksRequest - .newBuilder(payload) - .setPageToken((String) token) - .build(); - } - @Override - public Object extractNextToken(ListBooksResponse payload) { - return payload.getNextPageToken(); - } - @Override - public Iterable extractResources(ListBooksResponse payload) { - return payload.getBooksList(); - } - }; - - private static PageStreamingDescriptor LIST_STRINGS_PAGE_STR_DESC = - new PageStreamingDescriptor() { - @Override - public Object emptyToken() { - return ""; - } - @Override - public ListStringsRequest injectToken(ListStringsRequest payload, Object token) { - return ListStringsRequest - .newBuilder(payload) - .setPageToken((String) token) - .build(); - } - @Override - public Object extractNextToken(ListStringsResponse payload) { - return payload.getNextPageToken(); - } - @Override - public Iterable extractResources(ListStringsResponse payload) { - return payload.getStringsList(); - } - }; - - private static BundlingDescriptor PUBLISH_SERIES_BUNDLING_DESC = - new BundlingDescriptor() { - @Override - public String getBundlePartitionKey(PublishSeriesRequest request) { - return request.getEdition() + "|" + request.getName() + "|"; - } - - @Override - public PublishSeriesRequest mergeRequests(Collection requests) { - PublishSeriesRequest firstRequest = requests.iterator().next(); - - List elements = new ArrayList<>(); - for (PublishSeriesRequest request : requests) { - elements.addAll(request.getBooksList()); - } - - PublishSeriesRequest bundleRequest = - PublishSeriesRequest.newBuilder() - .setEdition(firstRequest.getEdition()) - .setName(firstRequest.getName()) - .addAllBooks(elements) - .build(); - return bundleRequest; - } - - @Override - public void splitResponse( - PublishSeriesResponse bundleResponse, - Collection> bundle) { - int bundleMessageIndex = 0; - for (RequestIssuer responder : bundle) { - List subresponseElements = new ArrayList<>(); - int subresponseCount = responder.getRequest().getBooksCount(); - for (int i = 0; i < subresponseCount; i++) { - subresponseElements.add(bundleResponse.getBookNames(bundleMessageIndex)); - bundleMessageIndex += 1; - } - PublishSeriesResponse response = - PublishSeriesResponse.newBuilder().addAllBookNames(subresponseElements).build(); - responder.setResponse(response); - } - } - - @Override - public void splitException( - Throwable throwable, - Collection> bundle) { - for (RequestIssuer responder : bundle) { - responder.setException(throwable); - } - } - - @Override - public long countElements(PublishSeriesRequest request) { - return request.getBooksCount(); - } - - @Override - public long countBytes(PublishSeriesRequest request) { - return request.getSerializedSize(); - } - }; - - /** - * Builder for LibraryServiceSettings. - */ - public static class Builder extends ServiceApiSettings.Builder { - private final ImmutableList methodSettingsBuilders; - - private SimpleCallSettings.Builder createShelfSettings; - private SimpleCallSettings.Builder getShelfSettings; - private PageStreamingCallSettings.Builder listShelvesSettings; - private SimpleCallSettings.Builder deleteShelfSettings; - private SimpleCallSettings.Builder mergeShelvesSettings; - private SimpleCallSettings.Builder createBookSettings; - private BundlingCallSettings.Builder publishSeriesSettings; - private SimpleCallSettings.Builder getBookSettings; - private PageStreamingCallSettings.Builder listBooksSettings; - private SimpleCallSettings.Builder deleteBookSettings; - private SimpleCallSettings.Builder updateBookSettings; - private SimpleCallSettings.Builder moveBookSettings; - private PageStreamingCallSettings.Builder listStringsSettings; - private SimpleCallSettings.Builder addCommentsSettings; - private SimpleCallSettings.Builder getBookFromArchiveSettings; - private SimpleCallSettings.Builder updateBookIndexSettings; - - private static final ImmutableMap> RETRYABLE_CODE_DEFINITIONS; - - static { - ImmutableMap.Builder> definitions = ImmutableMap.builder(); - definitions.put( - "idempotent", - Sets.immutableEnumSet(Lists.newArrayList(Status.Code.DEADLINE_EXCEEDED, Status.Code.UNAVAILABLE))); - definitions.put( - "non_idempotent", - Sets.immutableEnumSet(Lists.newArrayList())); - RETRYABLE_CODE_DEFINITIONS = definitions.build(); - } - - private static final ImmutableMap RETRY_PARAM_DEFINITIONS; - - static { - ImmutableMap.Builder definitions = ImmutableMap.builder(); - RetrySettings.Builder settingsBuilder = null; - settingsBuilder = RetrySettings.newBuilder() - .setInitialRetryDelay(Duration.millis(100L)) - .setRetryDelayMultiplier(1.2) - .setMaxRetryDelay(Duration.millis(1000L)) - .setInitialRpcTimeout(Duration.millis(300L)) - .setRpcTimeoutMultiplier(1.3) - .setMaxRpcTimeout(Duration.millis(3000L)) - .setTotalTimeout(Duration.millis(30000L)); - definitions.put("default", settingsBuilder); - RETRY_PARAM_DEFINITIONS = definitions.build(); - } - - private Builder() { - super(DEFAULT_CONNECTION_SETTINGS); - - createShelfSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_CREATE_SHELF); - - getShelfSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_GET_SHELF); - - listShelvesSettings = PageStreamingCallSettings.newBuilder( - LibraryServiceGrpc.METHOD_LIST_SHELVES, - LIST_SHELVES_PAGE_STR_DESC); - - deleteShelfSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_DELETE_SHELF); - - mergeShelvesSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_MERGE_SHELVES); - - createBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_CREATE_BOOK); - - publishSeriesSettings = BundlingCallSettings.newBuilder( - LibraryServiceGrpc.METHOD_PUBLISH_SERIES, - PUBLISH_SERIES_BUNDLING_DESC) - .setBundlingSettingsBuilder(BundlingSettings.newBuilder()); - - getBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_GET_BOOK); - - listBooksSettings = PageStreamingCallSettings.newBuilder( - LibraryServiceGrpc.METHOD_LIST_BOOKS, - LIST_BOOKS_PAGE_STR_DESC); - - deleteBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_DELETE_BOOK); - - updateBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_UPDATE_BOOK); - - moveBookSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_MOVE_BOOK); - - listStringsSettings = PageStreamingCallSettings.newBuilder( - LibraryServiceGrpc.METHOD_LIST_STRINGS, - LIST_STRINGS_PAGE_STR_DESC); - - addCommentsSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_ADD_COMMENTS); - - getBookFromArchiveSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_GET_BOOK_FROM_ARCHIVE); - - updateBookIndexSettings = SimpleCallSettings.newBuilder(LibraryServiceGrpc.METHOD_UPDATE_BOOK_INDEX); - - methodSettingsBuilders = ImmutableList.of( - createShelfSettings, - getShelfSettings, - listShelvesSettings, - deleteShelfSettings, - mergeShelvesSettings, - createBookSettings, - publishSeriesSettings, - getBookSettings, - listBooksSettings, - deleteBookSettings, - updateBookSettings, - moveBookSettings, - listStringsSettings, - addCommentsSettings, - getBookFromArchiveSettings, - updateBookIndexSettings - ); - } - - private static Builder createDefault() { - Builder builder = new Builder(); - - builder.createShelfSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.getShelfSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.listShelvesSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.deleteShelfSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.mergeShelvesSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.createBookSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.publishSeriesSettings().getBundlingSettingsBuilder() - .setElementCountThreshold(6) - .setElementCountLimit(7) - .setRequestByteThreshold(100000) - .setRequestByteLimit(150000) - .setDelayThreshold(Duration.millis(500)) - .setBlockingCallCountThreshold(1); - builder.publishSeriesSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.getBookSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.listBooksSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.deleteBookSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.updateBookSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.moveBookSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.listStringsSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.addCommentsSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("non_idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.getBookFromArchiveSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - builder.updateBookIndexSettings() - .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("idempotent")) - .setRetrySettingsBuilder(RETRY_PARAM_DEFINITIONS.get("default")); - - return builder; - } - - private Builder(LibraryServiceSettings settings) { - super(settings); - - createShelfSettings = settings.createShelfSettings.toBuilder(); - getShelfSettings = settings.getShelfSettings.toBuilder(); - listShelvesSettings = settings.listShelvesSettings.toBuilder(); - deleteShelfSettings = settings.deleteShelfSettings.toBuilder(); - mergeShelvesSettings = settings.mergeShelvesSettings.toBuilder(); - createBookSettings = settings.createBookSettings.toBuilder(); - publishSeriesSettings = settings.publishSeriesSettings.toBuilder(); - getBookSettings = settings.getBookSettings.toBuilder(); - listBooksSettings = settings.listBooksSettings.toBuilder(); - deleteBookSettings = settings.deleteBookSettings.toBuilder(); - updateBookSettings = settings.updateBookSettings.toBuilder(); - moveBookSettings = settings.moveBookSettings.toBuilder(); - listStringsSettings = settings.listStringsSettings.toBuilder(); - addCommentsSettings = settings.addCommentsSettings.toBuilder(); - getBookFromArchiveSettings = settings.getBookFromArchiveSettings.toBuilder(); - updateBookIndexSettings = settings.updateBookIndexSettings.toBuilder(); - - methodSettingsBuilders = ImmutableList.of( - createShelfSettings, - getShelfSettings, - listShelvesSettings, - deleteShelfSettings, - mergeShelvesSettings, - createBookSettings, - publishSeriesSettings, - getBookSettings, - listBooksSettings, - deleteBookSettings, - updateBookSettings, - moveBookSettings, - listStringsSettings, - addCommentsSettings, - getBookFromArchiveSettings, - updateBookIndexSettings - ); - } - - @Override - protected ConnectionSettings getDefaultConnectionSettings() { - return DEFAULT_CONNECTION_SETTINGS; - } - @Override - public Builder provideExecutorWith(ScheduledExecutorService executor, boolean shouldAutoClose) { - super.provideExecutorWith(executor, shouldAutoClose); - return this; - } - @Override - public Builder provideChannelWith(ManagedChannel channel, boolean shouldAutoClose) { - super.provideChannelWith(channel, shouldAutoClose); - return this; - } - @Override - public Builder provideChannelWith(ConnectionSettings settings) { - super.provideChannelWith(settings); - return this; - } - @Override - public Builder provideChannelWith(Credentials credentials) { - super.provideChannelWith(credentials); - return this; - } - @Override - public Builder provideChannelWith(List scopes) { - super.provideChannelWith(scopes); - return this; - } - @Override - public Builder setGeneratorHeader(String name, String version) { - super.setGeneratorHeader(name, version); - return this; - } - @Override - public Builder setClientLibHeader(String name, String version) { - super.setClientLibHeader(name, version); - return this; - } - - /** - * Applies the given settings to all of the API methods in this service. Only - * values that are non-null will be applied, so this method is not capable - * of un-setting any values. - */ - public Builder applyToAllApiMethods(ApiCallSettings.Builder apiCallSettings) throws Exception { - super.applyToAllApiMethods(methodSettingsBuilders, apiCallSettings); - return this; - } - - /** - * Returns the builder for the settings used for calls to createShelf. - */ - public SimpleCallSettings.Builder createShelfSettings() { - return createShelfSettings; - } - - /** - * Returns the builder for the settings used for calls to getShelf. - */ - public SimpleCallSettings.Builder getShelfSettings() { - return getShelfSettings; - } - - /** - * Returns the builder for the settings used for calls to listShelves. - */ - public PageStreamingCallSettings.Builder listShelvesSettings() { - return listShelvesSettings; - } - - /** - * Returns the builder for the settings used for calls to deleteShelf. - */ - public SimpleCallSettings.Builder deleteShelfSettings() { - return deleteShelfSettings; - } - - /** - * Returns the builder for the settings used for calls to mergeShelves. - */ - public SimpleCallSettings.Builder mergeShelvesSettings() { - return mergeShelvesSettings; - } - - /** - * Returns the builder for the settings used for calls to createBook. - */ - public SimpleCallSettings.Builder createBookSettings() { - return createBookSettings; - } - - /** - * Returns the builder for the settings used for calls to publishSeries. - */ - public BundlingCallSettings.Builder publishSeriesSettings() { - return publishSeriesSettings; - } - - /** - * Returns the builder for the settings used for calls to getBook. - */ - public SimpleCallSettings.Builder getBookSettings() { - return getBookSettings; - } - - /** - * Returns the builder for the settings used for calls to listBooks. - */ - public PageStreamingCallSettings.Builder listBooksSettings() { - return listBooksSettings; - } - - /** - * Returns the builder for the settings used for calls to deleteBook. - */ - public SimpleCallSettings.Builder deleteBookSettings() { - return deleteBookSettings; - } - - /** - * Returns the builder for the settings used for calls to updateBook. - */ - public SimpleCallSettings.Builder updateBookSettings() { - return updateBookSettings; - } - - /** - * Returns the builder for the settings used for calls to moveBook. - */ - public SimpleCallSettings.Builder moveBookSettings() { - return moveBookSettings; - } - - /** - * Returns the builder for the settings used for calls to listStrings. - */ - public PageStreamingCallSettings.Builder listStringsSettings() { - return listStringsSettings; - } - - /** - * Returns the builder for the settings used for calls to addComments. - */ - public SimpleCallSettings.Builder addCommentsSettings() { - return addCommentsSettings; - } - - /** - * Returns the builder for the settings used for calls to getBookFromArchive. - */ - public SimpleCallSettings.Builder getBookFromArchiveSettings() { - return getBookFromArchiveSettings; - } - - /** - * Returns the builder for the settings used for calls to updateBookIndex. - */ - public SimpleCallSettings.Builder updateBookIndexSettings() { - return updateBookIndexSettings; - } - - @Override - public LibraryServiceSettings build() throws IOException { - return new LibraryServiceSettings(this); - } - } -} From 4cfd08d3f7c8db2177980331b2c5bee5f845bd87 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Fri, 29 Jul 2016 11:35:39 -0700 Subject: [PATCH 24/26] generalizing Grpc type names --- .../api/codegen/transformer/SurfaceNamer.java | 13 +++++++++---- .../codegen/transformer/java/JavaSurfaceNamer.java | 7 +++++-- .../codegen/transformer/php/PhpSurfaceNamer.java | 6 +++++- .../java/com/google/api/codegen/util/NamePath.java | 10 +++++++++- .../google/api/codegen/util/TypeNameConverter.java | 5 +++++ .../java/com/google/api/codegen/util/TypeTable.java | 3 +++ .../google/api/codegen/util/java/JavaTypeTable.java | 6 ++++++ .../google/api/codegen/util/php/PhpTypeTable.java | 6 ++++++ .../com/google/api/codegen/util/TypeNameTest.java | 5 +++++ 9 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java index 073076cc04..af8519753b 100644 --- a/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/SurfaceNamer.java @@ -22,6 +22,7 @@ import com.google.api.codegen.util.NameFormatter; import com.google.api.codegen.util.NameFormatterDelegator; import com.google.api.codegen.util.NamePath; +import com.google.api.codegen.util.TypeNameConverter; import com.google.api.tools.framework.aspects.documentation.model.DocumentationUtil; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.Interface; @@ -45,10 +46,15 @@ */ public class SurfaceNamer extends NameFormatterDelegator { private ModelTypeFormatter modelTypeFormatter; + private TypeNameConverter typeNameConverter; - public SurfaceNamer(NameFormatter languageNamer, ModelTypeFormatter modelTypeFormatter) { + public SurfaceNamer( + NameFormatter languageNamer, + ModelTypeFormatter modelTypeFormatter, + TypeNameConverter typeNameConverter) { super(languageNamer); this.modelTypeFormatter = modelTypeFormatter; + this.typeNameConverter = typeNameConverter; } public ModelTypeFormatter getModelTypeFormatter() { @@ -197,14 +203,13 @@ public String getClientConfigPath(Interface service) { } public String getGrpcClientTypeName(Interface service) { - // FIXME make general (e.g. if Java wanted to use this); needs to use modelTypeFormatter.getFullNameFor - NamePath namePath = NamePath.dotted(service.getFullName()); + NamePath namePath = typeNameConverter.getNamePath(modelTypeFormatter.getFullNameFor(service)); String className = className(Name.upperCamel(namePath.getHead(), "Client")); return qualifiedName(namePath.withHead(className)); } public String getGrpcContainerTypeName(Interface service) { - NamePath namePath = NamePath.dotted(modelTypeFormatter.getFullNameFor(service)); + NamePath namePath = typeNameConverter.getNamePath(modelTypeFormatter.getFullNameFor(service)); String className = className(Name.upperCamel(namePath.getHead(), "Grpc")); return qualifiedName(namePath.withHead(className)); } diff --git a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java index c75df18049..6e5d6d7c13 100644 --- a/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/java/JavaSurfaceNamer.java @@ -19,9 +19,9 @@ import com.google.api.codegen.transformer.ModelTypeFormatterImpl; import com.google.api.codegen.transformer.ModelTypeTable; import com.google.api.codegen.transformer.SurfaceNamer; -import com.google.api.codegen.util.TypeName; import com.google.api.codegen.util.java.JavaNameFormatter; import com.google.api.codegen.util.java.JavaRenderingUtil; +import com.google.api.codegen.util.java.JavaTypeTable; import com.google.api.tools.framework.model.Method; import com.google.api.tools.framework.model.TypeRef; @@ -37,7 +37,10 @@ public class JavaSurfaceNamer extends SurfaceNamer { * Standard constructor. */ public JavaSurfaceNamer() { - super(new JavaNameFormatter(), new ModelTypeFormatterImpl(new JavaModelTypeNameConverter())); + super( + new JavaNameFormatter(), + new ModelTypeFormatterImpl(new JavaModelTypeNameConverter()), + new JavaTypeTable()); } @Override diff --git a/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java b/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java index 52207489bd..4561806332 100644 --- a/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java +++ b/src/main/java/com/google/api/codegen/transformer/php/PhpSurfaceNamer.java @@ -22,6 +22,7 @@ import com.google.api.codegen.transformer.SurfaceNamer; import com.google.api.codegen.util.Name; import com.google.api.codegen.util.php.PhpNameFormatter; +import com.google.api.codegen.util.php.PhpTypeTable; import com.google.api.tools.framework.model.Field; import com.google.api.tools.framework.model.Interface; import com.google.api.tools.framework.model.Method; @@ -32,7 +33,10 @@ */ public class PhpSurfaceNamer extends SurfaceNamer { public PhpSurfaceNamer() { - super(new PhpNameFormatter(), new ModelTypeFormatterImpl(new PhpModelTypeNameConverter())); + super( + new PhpNameFormatter(), + new ModelTypeFormatterImpl(new PhpModelTypeNameConverter()), + new PhpTypeTable()); } @Override diff --git a/src/main/java/com/google/api/codegen/util/NamePath.java b/src/main/java/com/google/api/codegen/util/NamePath.java index e004f23cb0..b34c3a4276 100644 --- a/src/main/java/com/google/api/codegen/util/NamePath.java +++ b/src/main/java/com/google/api/codegen/util/NamePath.java @@ -30,9 +30,17 @@ public class NamePath { * Create a NamePath that is separated by dots. */ public static NamePath dotted(String... pieces) { + return parse("\\.", pieces); + } + + public static NamePath backslashed(String... pieces) { + return parse("\\\\", pieces); + } + + private static NamePath parse(String separatorRegex, String... pieces) { List namePieces = new ArrayList<>(); for (String piece : pieces) { - for (String subPiece : piece.split("\\.")) { + for (String subPiece : piece.split(separatorRegex)) { namePieces.add(subPiece); } } diff --git a/src/main/java/com/google/api/codegen/util/TypeNameConverter.java b/src/main/java/com/google/api/codegen/util/TypeNameConverter.java index 8cb57de50b..9fe9743a48 100644 --- a/src/main/java/com/google/api/codegen/util/TypeNameConverter.java +++ b/src/main/java/com/google/api/codegen/util/TypeNameConverter.java @@ -22,4 +22,9 @@ public interface TypeNameConverter { * Maps the given fullName to a TypeName. */ TypeName getTypeName(String fullName); + + /** + * Maps the given fullName to a NamePath. + */ + NamePath getNamePath(String fullName); } diff --git a/src/main/java/com/google/api/codegen/util/TypeTable.java b/src/main/java/com/google/api/codegen/util/TypeTable.java index 419e2f59af..26749d6732 100644 --- a/src/main/java/com/google/api/codegen/util/TypeTable.java +++ b/src/main/java/com/google/api/codegen/util/TypeTable.java @@ -24,6 +24,9 @@ public interface TypeTable extends TypeNameConverter { @Override TypeName getTypeName(String fullName); + @Override + NamePath getNamePath(String fullName); + /** * Return a new TypeTable with the same concrete type as this one. */ diff --git a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java index 01aab1ce6d..2156073318 100644 --- a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java @@ -15,6 +15,7 @@ package com.google.api.codegen.util.java; import com.google.api.codegen.LanguageUtil; +import com.google.api.codegen.util.NamePath; import com.google.api.codegen.util.TypeAlias; import com.google.api.codegen.util.TypeName; import com.google.api.codegen.util.TypeTable; @@ -71,6 +72,11 @@ public TypeName getTypeName(String fullName) { return new TypeName(fullName, shortTypeName); } + @Override + public NamePath getNamePath(String fullName) { + return NamePath.dotted(fullName); + } + public String getAndSaveNicknameFor(String fullName) { return getAndSaveNicknameFor(getTypeName(fullName)); } diff --git a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java index 5ad91a87d2..8b5b108e21 100644 --- a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java @@ -14,6 +14,7 @@ */ package com.google.api.codegen.util.php; +import com.google.api.codegen.util.NamePath; import com.google.api.codegen.util.TypeAlias; import com.google.api.codegen.util.TypeName; import com.google.api.codegen.util.TypeTable; @@ -49,6 +50,11 @@ public TypeName getTypeName(String fullName) { return new TypeName(fullName, nickname); } + @Override + public NamePath getNamePath(String fullName) { + return NamePath.backslashed(fullName); + } + @Override public String getAndSaveNicknameFor(String fullName) { return getAndSaveNicknameFor(getTypeName(fullName)); diff --git a/src/test/java/com/google/api/codegen/util/TypeNameTest.java b/src/test/java/com/google/api/codegen/util/TypeNameTest.java index d2ebcafc4d..5e88f325e6 100644 --- a/src/test/java/com/google/api/codegen/util/TypeNameTest.java +++ b/src/test/java/com/google/api/codegen/util/TypeNameTest.java @@ -85,5 +85,10 @@ public String getAndSaveNicknameFor(TypeName typeName) { public List getImports() { return null; } + + @Override + public NamePath getNamePath(String fullName) { + return null; + } } } From 12b02ce362a514a5635b6d4a60afb8ae0b01f2fb Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Fri, 29 Jul 2016 11:51:24 -0700 Subject: [PATCH 25/26] Generalizing container type name --- .../api/codegen/transformer/ModelTypeTable.java | 10 +--------- .../google/api/codegen/util/TypeNameConverter.java | 5 +++++ .../java/com/google/api/codegen/util/TypeTable.java | 3 +++ .../google/api/codegen/util/java/JavaTypeTable.java | 11 +++++++++++ .../com/google/api/codegen/util/php/PhpTypeTable.java | 5 +++++ .../com/google/api/codegen/util/TypeNameTest.java | 5 +++++ 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java index d42a70bfcd..545a3e4e43 100644 --- a/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java +++ b/src/main/java/com/google/api/codegen/transformer/ModelTypeTable.java @@ -105,15 +105,7 @@ public String getAndSaveNicknameForElementType(TypeRef type) { } public String getAndSaveNicknameForContainer(String containerFullName, String elementFullName) { - TypeName containerTypeName = typeTable.getTypeName(containerFullName); - TypeName elementTypeName = typeTable.getTypeName(elementFullName); - TypeName completeTypeName = - new TypeName( - containerTypeName.getFullName(), - containerTypeName.getNickname(), - // FIXME make not java specific - "%s<%i>", - elementTypeName); + TypeName completeTypeName = typeTable.getContainerTypeName(containerFullName, elementFullName); return typeTable.getAndSaveNicknameFor(completeTypeName); } diff --git a/src/main/java/com/google/api/codegen/util/TypeNameConverter.java b/src/main/java/com/google/api/codegen/util/TypeNameConverter.java index 9fe9743a48..9dd4dc6269 100644 --- a/src/main/java/com/google/api/codegen/util/TypeNameConverter.java +++ b/src/main/java/com/google/api/codegen/util/TypeNameConverter.java @@ -27,4 +27,9 @@ public interface TypeNameConverter { * Maps the given fullName to a NamePath. */ NamePath getNamePath(String fullName); + + /** + * Creates a TypeName for the container type and element type. + */ + TypeName getContainerTypeName(String containerFullName, String elementFullName); } diff --git a/src/main/java/com/google/api/codegen/util/TypeTable.java b/src/main/java/com/google/api/codegen/util/TypeTable.java index 26749d6732..44117bb2de 100644 --- a/src/main/java/com/google/api/codegen/util/TypeTable.java +++ b/src/main/java/com/google/api/codegen/util/TypeTable.java @@ -27,6 +27,9 @@ public interface TypeTable extends TypeNameConverter { @Override NamePath getNamePath(String fullName); + @Override + TypeName getContainerTypeName(String containerFullName, String elementFullName); + /** * Return a new TypeTable with the same concrete type as this one. */ diff --git a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java index 2156073318..9d68902613 100644 --- a/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/java/JavaTypeTable.java @@ -77,6 +77,17 @@ public NamePath getNamePath(String fullName) { return NamePath.dotted(fullName); } + @Override + public TypeName getContainerTypeName(String containerFullName, String elementFullName) { + TypeName containerTypeName = getTypeName(containerFullName); + TypeName elementTypeName = getTypeName(elementFullName); + return new TypeName( + containerTypeName.getFullName(), + containerTypeName.getNickname(), + "%s<%i>", + elementTypeName); + } + public String getAndSaveNicknameFor(String fullName) { return getAndSaveNicknameFor(getTypeName(fullName)); } diff --git a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java index 8b5b108e21..896b834233 100644 --- a/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java +++ b/src/main/java/com/google/api/codegen/util/php/PhpTypeTable.java @@ -55,6 +55,11 @@ public NamePath getNamePath(String fullName) { return NamePath.backslashed(fullName); } + @Override + public TypeName getContainerTypeName(String containerFullName, String elementFullName) { + return getTypeName(containerFullName); + } + @Override public String getAndSaveNicknameFor(String fullName) { return getAndSaveNicknameFor(getTypeName(fullName)); diff --git a/src/test/java/com/google/api/codegen/util/TypeNameTest.java b/src/test/java/com/google/api/codegen/util/TypeNameTest.java index 5e88f325e6..ad64ee689d 100644 --- a/src/test/java/com/google/api/codegen/util/TypeNameTest.java +++ b/src/test/java/com/google/api/codegen/util/TypeNameTest.java @@ -90,5 +90,10 @@ public List getImports() { public NamePath getNamePath(String fullName) { return null; } + + @Override + public TypeName getContainerTypeName(String containerFullName, String elementFullName) { + return null; + } } } From f7bb388f59408665d571f02c6df892f754ce9820 Mon Sep 17 00:00:00 2001 From: Garrett Jones Date: Fri, 29 Jul 2016 11:58:46 -0700 Subject: [PATCH 26/26] Deleting dead code --- .../google/api/codegen/InterfaceListView.java | 43 -- .../gapic/MainGapicProviderFactory.java | 4 - .../api/codegen/java/JavaDocConfig.java | 85 ---- .../api/codegen/java/JavaGapicContext.java | 367 ------------------ .../codegen/java/JavaIterableSnippetSet.java | 38 -- .../java/JavaIterableSnippetSetRunner.java | 68 ---- .../api/codegen/java/JavaSnippetSet.java | 5 - .../api/codegen/JavaCodeGeneratorTest.java | 2 +- .../testdata/java_fragments_library.baseline | 48 --- 9 files changed, 1 insertion(+), 659 deletions(-) delete mode 100644 src/main/java/com/google/api/codegen/InterfaceListView.java delete mode 100644 src/main/java/com/google/api/codegen/java/JavaDocConfig.java delete mode 100644 src/main/java/com/google/api/codegen/java/JavaGapicContext.java delete mode 100644 src/main/java/com/google/api/codegen/java/JavaIterableSnippetSet.java delete mode 100644 src/main/java/com/google/api/codegen/java/JavaIterableSnippetSetRunner.java delete mode 100644 src/test/java/com/google/api/codegen/testdata/java_fragments_library.baseline diff --git a/src/main/java/com/google/api/codegen/InterfaceListView.java b/src/main/java/com/google/api/codegen/InterfaceListView.java deleted file mode 100644 index 2ab47d1e5e..0000000000 --- a/src/main/java/com/google/api/codegen/InterfaceListView.java +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen; - -import com.google.api.tools.framework.model.Interface; -import com.google.api.tools.framework.model.Model; - -import java.util.ArrayList; - -/** - * An interface-based view of model, consisting of a strategy for getting the interfaces of the - * model and returning them in a single iterable object. - */ -public class InterfaceListView implements InputElementView> { - - /** - * Gets the reachable interfaces of the model. - */ - @Override - public Iterable> getElementIterable(Model model) { - ArrayList interfaces = new ArrayList<>(); - for (Interface iface : model.getSymbolTable().getInterfaces()) { - if (iface.isReachable()) { - interfaces.add(iface); - } - } - ArrayList> result = new ArrayList<>(); - result.add(interfaces); - return result; - } -} diff --git a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java index 876e3682e1..bd08f66881 100644 --- a/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java +++ b/src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java @@ -15,7 +15,6 @@ package com.google.api.codegen.gapic; import com.google.api.codegen.ApiConfig; -import com.google.api.codegen.InterfaceListView; import com.google.api.codegen.InterfaceView; import com.google.api.codegen.ProtoFileView; import com.google.api.codegen.SnippetSetRunner; @@ -26,9 +25,6 @@ import com.google.api.codegen.csharp.CSharpSnippetSetRunner; import com.google.api.codegen.go.GoGapicContext; import com.google.api.codegen.go.GoSnippetSetRunner; -import com.google.api.codegen.java.JavaGapicContext; -import com.google.api.codegen.java.JavaIterableSnippetSetRunner; -import com.google.api.codegen.java.JavaSnippetSetRunner; import com.google.api.codegen.nodejs.NodeJSGapicContext; import com.google.api.codegen.nodejs.NodeJSSnippetSetRunner; import com.google.api.codegen.py.PythonGapicContext; diff --git a/src/main/java/com/google/api/codegen/java/JavaDocConfig.java b/src/main/java/com/google/api/codegen/java/JavaDocConfig.java deleted file mode 100644 index e8f738f6ea..0000000000 --- a/src/main/java/com/google/api/codegen/java/JavaDocConfig.java +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.java; - -import com.google.api.codegen.DocConfig; -import com.google.api.codegen.metacode.InitCode; -import com.google.api.codegen.metacode.InputParameter; -import com.google.api.tools.framework.model.Field; -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableList; - -import javax.annotation.Nullable; - -/** - * Represents the Java documentation settings for an Api method. - */ -@AutoValue -abstract class JavaDocConfig extends DocConfig { - public static Builder newBuilder() { - return new AutoValue_JavaDocConfig.Builder(); - } - - public String getGenericAwareReturnType() { - String returnType = getReturnType(); - if (returnType == null || returnType.isEmpty()) { - return "Void"; - } else { - return returnType; - } - } - - public abstract boolean isPagedVariant(); - - public abstract boolean isCallableVariant(); - - @Nullable - public abstract Field getResourcesFieldForUnpagedListCallable(); - - public boolean isUnpagedListCallableVariant() { - return getResourcesFieldForUnpagedListCallable() != null; - } - - @AutoValue.Builder - abstract static class Builder extends DocConfig.Builder { - public abstract JavaDocConfig build(); - - public abstract Builder setApiName(String serviceName); - - public abstract Builder setMethodName(String methodName); - - public abstract Builder setReturnType(String returnType); - - public abstract Builder setInitCode(InitCode initCode); - - public abstract Builder setParams(ImmutableList params); - - public abstract Builder setPagedVariant(boolean paged); - - public abstract Builder setCallableVariant(boolean callable); - - public abstract Builder setResourcesFieldForUnpagedListCallable(Field field); - - @Override - protected Builder setInitCodeProxy(InitCode initCode) { - return setInitCode(initCode); - } - - @Override - protected Builder setParamsProxy(ImmutableList params) { - return setParams(params); - } - } -} diff --git a/src/main/java/com/google/api/codegen/java/JavaGapicContext.java b/src/main/java/com/google/api/codegen/java/JavaGapicContext.java deleted file mode 100644 index d026fb36d7..0000000000 --- a/src/main/java/com/google/api/codegen/java/JavaGapicContext.java +++ /dev/null @@ -1,367 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.java; - -import com.google.api.codegen.ApiConfig; -import com.google.api.codegen.GapicContext; -import com.google.api.codegen.MethodConfig; -import com.google.api.tools.framework.model.Field; -import com.google.api.tools.framework.model.FieldSelector; -import com.google.api.tools.framework.model.Interface; -import com.google.api.tools.framework.model.Method; -import com.google.api.tools.framework.model.Model; -import com.google.api.tools.framework.model.ProtoElement; -import com.google.api.tools.framework.model.ProtoFile; -import com.google.api.tools.framework.model.TypeRef; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.io.Files; -import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Type; - -import java.io.File; -import java.util.Arrays; - -/** - * A GapicContext specialized for Java. - */ -public class JavaGapicContext extends GapicContext implements JavaContext { - - /** - * The package prefix protoc uses if no java package option was provided. - */ - private static final String DEFAULT_JAVA_PACKAGE_PREFIX = "com.google.protos"; - - /** - * A map from primitive types in proto to Java counterparts. - */ - private static final ImmutableMap PRIMITIVE_TYPE_MAP = - ImmutableMap.builder() - .put(Type.TYPE_BOOL, "boolean") - .put(Type.TYPE_DOUBLE, "double") - .put(Type.TYPE_FLOAT, "float") - .put(Type.TYPE_INT64, "long") - .put(Type.TYPE_UINT64, "long") - .put(Type.TYPE_SINT64, "long") - .put(Type.TYPE_FIXED64, "long") - .put(Type.TYPE_SFIXED64, "long") - .put(Type.TYPE_INT32, "int") - .put(Type.TYPE_UINT32, "int") - .put(Type.TYPE_SINT32, "int") - .put(Type.TYPE_FIXED32, "int") - .put(Type.TYPE_SFIXED32, "int") - .put(Type.TYPE_STRING, "java.lang.String") - .put(Type.TYPE_BYTES, "com.google.protobuf.ByteString") - .build(); - - /** - * A map from primitive types in proto to zero value in Java - */ - private static final ImmutableMap PRIMITIVE_ZERO_VALUE = - ImmutableMap.builder() - .put(Type.TYPE_BOOL, "false") - .put(Type.TYPE_DOUBLE, "0.0") - .put(Type.TYPE_FLOAT, "0.0F") - .put(Type.TYPE_INT64, "0L") - .put(Type.TYPE_UINT64, "0L") - .put(Type.TYPE_SINT64, "0L") - .put(Type.TYPE_FIXED64, "0L") - .put(Type.TYPE_SFIXED64, "0L") - .put(Type.TYPE_INT32, "0") - .put(Type.TYPE_UINT32, "0") - .put(Type.TYPE_SINT32, "0") - .put(Type.TYPE_FIXED32, "0") - .put(Type.TYPE_SFIXED32, "0") - .put(Type.TYPE_STRING, "\"\"") - .put(Type.TYPE_BYTES, "ByteString.copyFromUtf8(\"\")") - .build(); - - private JavaContextCommon javaCommon; - - public JavaGapicContext(Model model, ApiConfig apiConfig) { - super(model, apiConfig); - } - - @Override - public void resetState(JavaContextCommon javaCommon) { - this.javaCommon = javaCommon; - } - - public JavaContextCommon java() { - return javaCommon; - } - - // Snippet Helpers - // =============== - - /** - * Takes a fully-qualified type name and returns its simple name, and also saves the type in the - * import list. - */ - public String getTypeName(String typeName) { - int lastDotIndex = typeName.lastIndexOf('.'); - if (lastDotIndex < 0) { - throw new IllegalArgumentException("expected fully qualified name"); - } - String shortTypeName = typeName.substring(lastDotIndex + 1); - return javaCommon.getMinimallyQualifiedName(typeName, shortTypeName); - } - - /** - * Adds the given type name to the import list. Returns an empty string so that the output is not - * affected in snippets. - */ - public String addImport(String typeName) { - // used for its side effect of adding the type to the import list if the short name - // hasn't been imported yet - getTypeName(typeName); - return ""; - } - - /** - * Gets the java package for the given proto file. - */ - public String getJavaPackage(ProtoFile file) { - String packageName = file.getProto().getOptions().getJavaPackage(); - if (Strings.isNullOrEmpty(packageName)) { - return DEFAULT_JAVA_PACKAGE_PREFIX + "." + file.getFullName(); - } - return packageName; - } - - /** - * Gets the name of the class which is the grpc container for this service interface. - */ - public String getGrpcName(Interface service) { - String fullName = - String.format("%s.%sGrpc", getJavaPackage(service.getFile()), service.getSimpleName()); - return getTypeName(fullName); - } - - /** - * Given a TypeRef, returns the return statement for that type. Specifically, this will return an - * empty string for the empty type (we don't want a return statement for void). - */ - public String methodReturnStatement(TypeRef type) { - if (messages().isEmptyType(type)) { - return ""; - } else { - return "return "; - } - } - - /** - * Given a TypeRef, returns the String form of the type to be used as a return value. Special - * case: this will return "void" for the Empty return type. - */ - public String methodReturnTypeName(TypeRef type) { - if (messages().isEmptyType(type)) { - return "void"; - } else { - return typeName(type); - } - } - - /** - * Returns the Java representation of a reference to a type. - */ - public String typeName(TypeRef type) { - if (type.isMap()) { - String mapTypeName = getTypeName("java.util.Map"); - return String.format( - "%s<%s, %s>", - mapTypeName, - basicTypeNameBoxed(type.getMapKeyField().getType()), - basicTypeNameBoxed(type.getMapValueField().getType())); - } else if (type.isRepeated()) { - String listTypeName = getTypeName("java.util.List"); - return String.format("%s<%s>", listTypeName, basicTypeNameBoxed(type)); - } else { - return basicTypeName(type); - } - } - - /** - * Returns the Java representation of a zero value for that type, to be used in code sample doc. - * - * Parametric types may use the diamond operator, since the return value will be used only in - * initialization. - */ - public String zeroValue(TypeRef type) { - // Don't call getTypeName; we don't need to import these. - if (type.isMap()) { - return "new HashMap<>()"; - } - if (type.isRepeated()) { - return "new ArrayList<>()"; - } - if (PRIMITIVE_ZERO_VALUE.containsKey(type.getKind())) { - return PRIMITIVE_ZERO_VALUE.get(type.getKind()); - } - if (type.isMessage()) { - return typeName(type) + ".newBuilder().build()"; - } - return "null"; - } - - public String returnTypeOrEmpty(TypeRef returnType) { - return messages().isEmptyType(returnType) ? "" : typeName(returnType); - } - - /** - * Returns the Java representation of a type, without cardinality, in boxed form. - */ - public String basicTypeNameBoxed(TypeRef type) { - return javaCommon.boxedTypeName(basicTypeName(type)); - } - - /** - * Returns the Java representation of a type, without cardinality. If the type is a Java - * primitive, basicTypeName returns it in unboxed form. - */ - public String basicTypeName(TypeRef type) { - String result = PRIMITIVE_TYPE_MAP.get(type.getKind()); - if (result != null) { - if (result.contains(".")) { - // Fully qualified type name, use regular type name resolver. Can skip boxing logic - // because those types are already boxed. - return getTypeName(result); - } - return result; - } - switch (type.getKind()) { - case TYPE_MESSAGE: - return getTypeName(type.getMessageType()); - case TYPE_ENUM: - return getTypeName(type.getEnumType()); - default: - throw new IllegalArgumentException("unknown type kind: " + type.getKind()); - } - } - - /** - * Gets the full name of the message or enum type in Java. - */ - public String getTypeName(ProtoElement elem) { - // Construct the full name in Java - String name = getJavaPackage(elem.getFile()); - if (!elem.getFile().getProto().getOptions().getJavaMultipleFiles()) { - String outerClassName = elem.getFile().getProto().getOptions().getJavaOuterClassname(); - if (outerClassName.isEmpty()) { - outerClassName = getFileClassName(elem.getFile()); - } - name = name + "." + outerClassName; - } - String shortName = elem.getFullName().substring(elem.getFile().getFullName().length() + 1); - name = name + "." + shortName; - - return javaCommon.getMinimallyQualifiedName(name, shortName); - } - - /** - * Gets the class name for the given proto file. - */ - private String getFileClassName(ProtoFile file) { - String baseName = Files.getNameWithoutExtension(new File(file.getSimpleName()).getName()); - return lowerUnderscoreToUpperCamel(baseName); - } - - public String defaultTokenValue(Field field) { - if (field.getType().getKind().equals(Type.TYPE_STRING)) { - return "\"\""; - } else if (field.getType().getKind().equals(Type.TYPE_BYTES)) { - String byteStringTypeName = getTypeName("com.google.protobuf.ByteString"); - return byteStringTypeName + ".EMPTY"; - } else { - throw new IllegalArgumentException( - String.format( - "Unsupported type for field %s - found %s, " - + "but expected TYPE_STRING or TYPE_BYTES", - field.getFullName(), - field.getType().getKind())); - } - } - - // Workaround for the fact that quotes can't be used in a snippet @join - public String partitionKeyCode(ImmutableList discriminatorFields) { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < discriminatorFields.size(); i++) { - if (i > 0) { - buf.append(" + \"|\" + "); - } - String simpleName = discriminatorFields.get(i).getLastField().getSimpleName(); - buf.append("request.get" + lowerUnderscoreToUpperCamel(simpleName) + "()"); - } - return buf.toString(); - } - - public Method getFirstFlattenedMethod(Interface service) { - for (Method method : service.getMethods()) { - MethodConfig methodConfig = - getApiConfig().getInterfaceConfig(service).getMethodConfig(method); - if (methodConfig.isFlattening()) { - return method; - } - } - throw new RuntimeException("No flattened methods available."); - } - - public String getTitle() { - return getModel().getServiceConfig().getTitle(); - } - - public String getMultilineHeading(String heading) { - final char[] array = new char[heading.length()]; - Arrays.fill(array, '='); - String eqsString = new String(array); - return String.format("%s\n%s\n%s", eqsString, heading, eqsString); - } - - public JavaDocConfig.Builder newJavaDocConfigBuilder() { - return JavaDocConfig.newBuilder(); - } - - /** - * Get a Java formatted primitive value, given a primitive type and a string representation of - * that value. The value must be a valid example of that type. Values of type Bool must be either - * the string 'true' or 'false' (other capitalizations are permitted). - */ - public String renderPrimitiveValue(TypeRef type, String value) { - Type primitiveType = type.getKind(); - if (!PRIMITIVE_TYPE_MAP.containsKey(primitiveType)) { - throw new IllegalArgumentException( - "Initial values are only supported for primitive types, got type " - + type - + ", with value " - + value); - } - switch (primitiveType) { - case TYPE_BOOL: - return value.toLowerCase(); - case TYPE_FLOAT: - return value + "F"; - case TYPE_INT64: - case TYPE_UINT64: - return value + "L"; - case TYPE_STRING: - return "\"" + value + "\""; - case TYPE_BYTES: - return "ByteString.copyFromUtf8(\"" + value + "\")"; - default: - // Types that do not need to be modified (e.g. TYPE_INT32) are handled here - return value; - } - } -} diff --git a/src/main/java/com/google/api/codegen/java/JavaIterableSnippetSet.java b/src/main/java/com/google/api/codegen/java/JavaIterableSnippetSet.java deleted file mode 100644 index e4c7e3cec3..0000000000 --- a/src/main/java/com/google/api/codegen/java/JavaIterableSnippetSet.java +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.java; - -import com.google.api.tools.framework.snippet.Doc; - -/** - * Entry points for a simple Java snippet set. Generation is a single phase. - */ -interface JavaIterableSnippetSet { - - /** - * Generates the result filename for the generated document. - */ - Doc generateFilename(); - - /** - * Generates the contents of the document. - */ - Doc generateDocument(Iterable fragments); - - /** - * Generates a fragment of the doc from a service. - */ - Doc generateFragment(T service); -} diff --git a/src/main/java/com/google/api/codegen/java/JavaIterableSnippetSetRunner.java b/src/main/java/com/google/api/codegen/java/JavaIterableSnippetSetRunner.java deleted file mode 100644 index acb39dac90..0000000000 --- a/src/main/java/com/google/api/codegen/java/JavaIterableSnippetSetRunner.java +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2016 Google Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.api.codegen.java; - -import com.google.api.codegen.CodegenContext; -import com.google.api.codegen.GeneratedResult; -import com.google.api.codegen.SnippetSetRunner; -import com.google.api.tools.framework.snippet.Doc; -import com.google.api.tools.framework.snippet.SnippetSet; -import com.google.common.collect.ImmutableMap; - -import java.util.ArrayList; -import java.util.List; - -/** - * A JavaProvider provides general Java code generation logic that is agnostic to the use case - * (e.g. Gapic vs Discovery). Behavior that is specific to a use case is provided through a - * subclass of JavaContext. - */ -public class JavaIterableSnippetSetRunner - implements SnippetSetRunner.Generator> { - - private final String resourceRoot; - - public JavaIterableSnippetSetRunner(String resourceRoot) { - this.resourceRoot = resourceRoot; - } - - @Override - @SuppressWarnings("unchecked") - public GeneratedResult generate( - Iterable elementList, String snippetFileName, CodegenContext context) { - JavaIterableSnippetSet snippets = - SnippetSet.createSnippetInterface( - JavaIterableSnippetSet.class, - resourceRoot, - snippetFileName, - ImmutableMap.of("context", context)); - - String outputFilename = snippets.generateFilename().prettyPrint(); - JavaContextCommon javaContextCommon = new JavaContextCommon(); - - // TODO don't depend on a cast here - JavaContext javaContext = (JavaContext) context; - javaContext.resetState(javaContextCommon); - - List fragmentList = new ArrayList<>(); - for (ElementT element : elementList) { - fragmentList.add(snippets.generateFragment(element)); - } - - // Generate result. - Doc result = snippets.generateDocument(fragmentList); - return GeneratedResult.create(result, outputFilename); - } -} diff --git a/src/main/java/com/google/api/codegen/java/JavaSnippetSet.java b/src/main/java/com/google/api/codegen/java/JavaSnippetSet.java index 17e20dde73..e23020c5ca 100644 --- a/src/main/java/com/google/api/codegen/java/JavaSnippetSet.java +++ b/src/main/java/com/google/api/codegen/java/JavaSnippetSet.java @@ -38,9 +38,4 @@ interface JavaSnippetSet { * to be imported. */ Doc generateClass(Element element, Doc body, Iterable imports); - - /** - * Generate the example snippet for a method. - */ - Doc generateMethodSampleCode(JavaDocConfig config); } diff --git a/src/test/java/com/google/api/codegen/JavaCodeGeneratorTest.java b/src/test/java/com/google/api/codegen/JavaCodeGeneratorTest.java index 9439e02b3b..0d82ae27ea 100644 --- a/src/test/java/com/google/api/codegen/JavaCodeGeneratorTest.java +++ b/src/test/java/com/google/api/codegen/JavaCodeGeneratorTest.java @@ -32,7 +32,7 @@ public class JavaCodeGeneratorTest extends GapicTestBase { public JavaCodeGeneratorTest( String name, String idForFactory, String[] gapicConfigFileNames, String snippetName) { super(name, idForFactory, gapicConfigFileNames, snippetName); - getTestDataLocator().addTestDataSource(com.google.api.codegen.java.JavaGapicContext.class, ""); + getTestDataLocator().addTestDataSource(com.google.api.codegen.java.JavaContextCommon.class, ""); } /** diff --git a/src/test/java/com/google/api/codegen/testdata/java_fragments_library.baseline b/src/test/java/com/google/api/codegen/testdata/java_fragments_library.baseline deleted file mode 100644 index 7c153c636d..0000000000 --- a/src/test/java/com/google/api/codegen/testdata/java_fragments_library.baseline +++ /dev/null @@ -1,48 +0,0 @@ -/* - * PRE-REQUISITES: - * --------------- - * 1. If not already done, enable the LibraryService API and check quota for your project at - * https://console.developers.google.com/apis/api/libraryService_component/quotas - * 2. To install the client library on Maven or Gradle, check installation instructions at - * https://github.com/google/google-api-java-client. - * On other build systems, you can add the jar files to your project from - * https://developers.google.com/resources/api-libraries/download/libraryService/com.google.gcloud.pubsub.spi/java - * 3. This sample uses Application Default Credentials for Auth. If not already done, install the gcloud CLI from - * https://cloud.google.com/sdk/ and run 'gcloud auth login' - */ - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.example.library.v1.CreateShelfRequest; -import com.google.example.library.v1.Shelf; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.Collections; - - -@javax.annotation.Generated("by the sample snippet generator") -public class LibraryServiceSample { - public static void main(String[] args) throws IOException, GeneralSecurityException { - // Authentication is provided by the 'gcloud' tool when running locally - // and by built-in service accounts when running on GAE, GCE, or GKE. - GoogleCredential credential = GoogleCredential.getApplicationDefault(); - - // The createScopedRequired method returns true when running on GAE or a local developer - // machine. In that case, the desired scopes must be passed in manually. When the code is - // running in GCE, GKE or a Managed VM, the scopes are pulled from the GCE metadata server. - // See https://developers.google.com/identity/protocols/application-default-credentials for more information. - if (credential.createScopedRequired()) { - credential = credential.createScoped(Collections.singletonList("https://www.googleapis.com/auth/cloud-platform")); - } - - HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - LibraryService libraryServiceService = new LibraryService.Builder(httpTransport, jsonFactory, credential) - .setApplicationName("Google Cloud Platform Sample") - .build(); - - } -}