Skip to content
This repository was archived by the owner on Jun 28, 2022. It is now read-only.

Commit d9cea89

Browse files
Refactoring PHP generation to use the MVVM pattern (#317)
This was prototyped in #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
1 parent 03c0a5e commit d9cea89

File tree

92 files changed

+4955
-1216
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+4955
-1216
lines changed

src/main/java/com/google/api/codegen/ServiceConfig.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
import com.google.api.tools.framework.model.Interface;
2121

2222
import java.util.Arrays;
23-
import java.util.HashSet;
2423
import java.util.List;
2524
import java.util.Set;
25+
import java.util.TreeSet;
2626

2727
/**
2828
* Utility class that provides service configuration data from an Interface.
@@ -50,7 +50,7 @@ public String getTitle(Interface service) {
5050
* Return a list of scopes for authentication.
5151
*/
5252
public Iterable<String> getAuthScopes(Interface service) {
53-
Set<String> result = new HashSet<>();
53+
Set<String> result = new TreeSet<>();
5454
Service config = service.getModel().getServiceConfig();
5555
Authentication auth = config.getAuthentication();
5656
for (AuthenticationRule rule : auth.getRulesList()) {

src/main/java/com/google/api/codegen/ServiceMessages.java

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public class ServiceMessages {
3333
* Returns true if the message is the empty message.
3434
*/
3535
public boolean isEmptyType(TypeRef type) {
36+
return s_isEmptyType(type);
37+
}
38+
39+
public static boolean s_isEmptyType(TypeRef type) {
3640
return type.isMessage()
3741
&& type.getMessageType().getFullName().equals(Empty.getDescriptor().getFullName());
3842
}

src/main/java/com/google/api/codegen/csharp/CSharpContextCommon.java

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public String addImport(String namespace) {
5050
*/
5151
public Iterable<String> getXmlDocLines(String text, String element) {
5252
// TODO(jonskeet): Convert markdown to XML documentation format.
53+
// https://github.com/googleapis/toolkit/issues/331
5354
List<String> result = new ArrayList<>();
5455
result.add("/// <" + element + ">");
5556
for (String line : Splitter.on(String.format("%n")).split(text)) {
@@ -65,6 +66,7 @@ public Iterable<String> getXmlDocLines(String text, String element) {
6566
*/
6667
public Iterable<String> getXmlParameterLines(String text, String parameterName) {
6768
// TODO(jonskeet): Convert markdown to XML documentation format.
69+
// https://github.com/googleapis/toolkit/issues/331
6870
List<String> result = new ArrayList<>();
6971
result.add("/// <paramref name=\"" + parameterName + "\">");
7072
for (String line : Splitter.on(String.format("%n")).split(text)) {

src/main/java/com/google/api/codegen/gapic/MainGapicProviderFactory.java

+10-12
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
package com.google.api.codegen.gapic;
1616

1717
import com.google.api.codegen.ApiConfig;
18-
import com.google.api.codegen.clientconfig.ClientConfigGapicContext;
1918
import com.google.api.codegen.InterfaceListView;
2019
import com.google.api.codegen.InterfaceView;
2120
import com.google.api.codegen.ProtoFileView;
2221
import com.google.api.codegen.SnippetSetRunner;
22+
import com.google.api.codegen.clientconfig.ClientConfigGapicContext;
2323
import com.google.api.codegen.clientconfig.ClientConfigSnippetSetRunner;
2424
import com.google.api.codegen.csharp.CSharpCodePathMapper;
2525
import com.google.api.codegen.csharp.CSharpGapicContext;
@@ -31,23 +31,24 @@
3131
import com.google.api.codegen.java.JavaSnippetSetRunner;
3232
import com.google.api.codegen.nodejs.NodeJSGapicContext;
3333
import com.google.api.codegen.nodejs.NodeJSSnippetSetRunner;
34-
import com.google.api.codegen.php.PhpGapicContext;
35-
import com.google.api.codegen.php.PhpSnippetSetRunner;
3634
import com.google.api.codegen.py.PythonGapicContext;
3735
import com.google.api.codegen.py.PythonInterfaceInitializer;
3836
import com.google.api.codegen.py.PythonProtoFileInitializer;
3937
import com.google.api.codegen.py.PythonSnippetSetRunner;
38+
import com.google.api.codegen.rendering.CommonSnippetSetRunner;
4039
import com.google.api.codegen.ruby.RubyGapicContext;
4140
import com.google.api.codegen.ruby.RubySnippetSetRunner;
41+
import com.google.api.codegen.transformer.php.PhpGapicSurfaceTransformer;
42+
import com.google.api.codegen.util.CommonRenderingUtil;
4243
import com.google.api.tools.framework.model.Interface;
4344
import com.google.api.tools.framework.model.Model;
4445
import com.google.api.tools.framework.model.ProtoFile;
4546

46-
import org.apache.commons.lang3.NotImplementedException;
47-
4847
import java.util.Arrays;
4948
import java.util.List;
5049

50+
import org.apache.commons.lang3.NotImplementedException;
51+
5152
/**
5253
* MainGapicProviderFactory creates GapicProvider instances based on an id.
5354
*/
@@ -173,14 +174,11 @@ public static List<GapicProvider<? extends Object>> defaultCreate(
173174
GapicCodePathMapper phpPathMapper =
174175
CommonGapicCodePathMapper.newBuilder().setPrefix("src").build();
175176
GapicProvider<? extends Object> provider =
176-
CommonGapicProvider.<Interface>newBuilder()
177+
ViewModelGapicProvider.newBuilder()
177178
.setModel(model)
178-
.setView(new InterfaceView())
179-
.setContext(new PhpGapicContext(model, apiConfig))
180-
.setSnippetSetRunner(
181-
new PhpSnippetSetRunner<Interface>(SnippetSetRunner.SNIPPET_RESOURCE_ROOT))
182-
.setSnippetFileNames(Arrays.asList("php/main.snip"))
183-
.setCodePathMapper(phpPathMapper)
179+
.setApiConfig(apiConfig)
180+
.setSnippetSetRunner(new CommonSnippetSetRunner(new CommonRenderingUtil()))
181+
.setModelToViewTransformer(new PhpGapicSurfaceTransformer(apiConfig, phpPathMapper))
184182
.build();
185183

186184
GapicCodePathMapper phpClientConfigPathMapper =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* Copyright 2016 Google Inc
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
package com.google.api.codegen.gapic;
16+
17+
import com.google.api.codegen.ApiConfig;
18+
import com.google.api.codegen.rendering.CommonSnippetSetRunner;
19+
import com.google.api.codegen.transformer.ModelToViewTransformer;
20+
import com.google.api.codegen.viewmodel.ViewModel;
21+
import com.google.api.tools.framework.model.Interface;
22+
import com.google.api.tools.framework.model.Model;
23+
import com.google.api.tools.framework.model.stages.Merged;
24+
import com.google.api.tools.framework.snippet.Doc;
25+
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.TreeMap;
29+
30+
public class ViewModelGapicProvider implements GapicProvider<Interface> {
31+
private final Model model;
32+
private final ApiConfig apiConfig;
33+
private final CommonSnippetSetRunner snippetSetRunner;
34+
private final ModelToViewTransformer modelToViewTransformer;
35+
36+
private ViewModelGapicProvider(
37+
Model model,
38+
ApiConfig apiConfig,
39+
CommonSnippetSetRunner snippetSetRunner,
40+
ModelToViewTransformer modelToViewTransformer) {
41+
this.model = model;
42+
this.apiConfig = apiConfig;
43+
this.snippetSetRunner = snippetSetRunner;
44+
this.modelToViewTransformer = modelToViewTransformer;
45+
}
46+
47+
@Override
48+
public List<String> getSnippetFileNames() {
49+
return modelToViewTransformer.getTemplateFileNames();
50+
}
51+
52+
@Override
53+
public Map<String, Doc> generate() {
54+
return generate(null);
55+
}
56+
57+
@Override
58+
public Map<String, Doc> generate(String snippetFileName) {
59+
// Establish required stage for generation.
60+
model.establishStage(Merged.KEY);
61+
if (model.getDiagCollector().getErrorCount() > 0) {
62+
return null;
63+
}
64+
65+
List<ViewModel> surfaceDocs = modelToViewTransformer.transform(model, apiConfig);
66+
if (model.getDiagCollector().getErrorCount() > 0) {
67+
return null;
68+
}
69+
70+
Map<String, Doc> docs = new TreeMap<>();
71+
for (ViewModel surfaceDoc : surfaceDocs) {
72+
if (snippetFileName != null && !surfaceDoc.templateFileName().equals(snippetFileName)) {
73+
continue;
74+
}
75+
Doc doc = snippetSetRunner.generate(surfaceDoc);
76+
if (doc == null) {
77+
// generation failed; failures are captured in the model.
78+
continue;
79+
}
80+
docs.put(surfaceDoc.outputPath(), doc);
81+
}
82+
83+
return docs;
84+
}
85+
86+
public static Builder newBuilder() {
87+
return new Builder();
88+
}
89+
90+
public static class Builder {
91+
private Model model;
92+
private ApiConfig apiConfig;
93+
private CommonSnippetSetRunner snippetSetRunner;
94+
private ModelToViewTransformer modelToViewTransformer;
95+
96+
private Builder() {}
97+
98+
public Builder setModel(Model model) {
99+
this.model = model;
100+
return this;
101+
}
102+
103+
public Builder setApiConfig(ApiConfig apiConfig) {
104+
this.apiConfig = apiConfig;
105+
return this;
106+
}
107+
108+
public Builder setSnippetSetRunner(CommonSnippetSetRunner snippetSetRunner) {
109+
this.snippetSetRunner = snippetSetRunner;
110+
return this;
111+
}
112+
113+
public Builder setModelToViewTransformer(ModelToViewTransformer modelToViewTransformer) {
114+
this.modelToViewTransformer = modelToViewTransformer;
115+
return this;
116+
}
117+
118+
public ViewModelGapicProvider build() {
119+
return new ViewModelGapicProvider(model, apiConfig, snippetSetRunner, modelToViewTransformer);
120+
}
121+
}
122+
}

src/main/java/com/google/api/codegen/java/JavaContextCommon.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ public Iterable<String> getJavaDocLines(String text) {
128128
* firstLinePrefix. Markdown will be translated to javadoc.
129129
*/
130130
public Iterable<String> getJavaDocLinesWithPrefix(String text, String firstLinePrefix) {
131-
// TODO(wgg): convert markdown to javadoc
131+
// TODO: convert markdown to javadoc
132+
// https://github.com/googleapis/toolkit/issues/331
132133
List<String> result = new ArrayList<>();
133134
String linePrefix = firstLinePrefix;
134135
text = JAVADOC_ESCAPER.escape(text);

src/main/java/com/google/api/codegen/metacode/FieldSetting.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515
package com.google.api.codegen.metacode;
1616

17+
import com.google.api.codegen.util.Name;
1718
import com.google.api.tools.framework.model.TypeRef;
1819
import com.google.auto.value.AutoValue;
1920

@@ -25,7 +26,7 @@
2526
public abstract class FieldSetting {
2627

2728
public static FieldSetting create(
28-
TypeRef type, String fieldName, String identifier, InitValueConfig initValueConfig) {
29+
TypeRef type, Name fieldName, Name identifier, InitValueConfig initValueConfig) {
2930
return new AutoValue_FieldSetting(type, fieldName, identifier, initValueConfig);
3031
}
3132

@@ -37,12 +38,12 @@ public static FieldSetting create(
3738
/**
3839
* Returns the name of the field in the containing structure.
3940
*/
40-
public abstract String getFieldName();
41+
public abstract Name getFieldName();
4142

4243
/**
4344
* Returns the name of the identifier being set on the field.
4445
*/
45-
public abstract String getIdentifier();
46+
public abstract Name getIdentifier();
4647

4748
/**
4849
* Returns the InitValueConfig for the original identifier.

0 commit comments

Comments
 (0)