-
Notifications
You must be signed in to change notification settings - Fork 11
/
Document.java
270 lines (234 loc) · 8.4 KB
/
Document.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
* Copyright 2020 Google LLC
*
* 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
*
* https://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.cloud.discotoproto3converter.disco;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.gson.internal.LinkedTreeMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Adapted from its counterpart in gapic-generator.
*
* <p>A representation of a Discovery Document.
*
* <p>Note that this class is not necessarily a 1-1 mapping of the official specification. For
* example, this class combines all methods in the Discovery Document into one list for convenience.
*/
@AutoValue
public abstract class Document implements Node {
// TODO(saicheems): Assert that all references link to a valid schema?
private static final String CLOUD_PLATFORM_SCOPE =
"https://www.googleapis.com/auth/cloud-platform";
/**
* Returns a document constructed from root.
*
* @param root the root node to parse.
* @return a document.
*/
public static Document from(DiscoveryNode root) {
AuthType authType;
DiscoveryNode scopesNode = root.getObject("auth").getObject("oauth2").getObject("scopes");
ImmutableList.Builder<String> authScopes = new Builder<>();
if (scopesNode.isEmpty()) {
authType = AuthType.API_KEY;
} else {
authScopes.addAll(scopesNode.getFieldNames());
if (scopesNode.has(CLOUD_PLATFORM_SCOPE)) {
authType = AuthType.ADC;
} else {
authType = AuthType.OAUTH_3L;
}
}
String canonicalName = root.getString("canonicalName");
String description = root.getString("description");
String id = root.getString("id");
Map<String, Schema> schemas = parseSchemas(root);
List<Method> methods = parseMethods(root);
Collections.sort(methods); // Ensure methods are ordered alphabetically by their ID.
String ownerDomain = root.getString("ownerDomain");
String name = root.getString("name");
if (canonicalName.isEmpty()) {
canonicalName = name;
}
Map<String, List<Method>> resources = parseResources(root);
String revision = root.getString("revision");
String rootUrl = root.getString("rootUrl");
String servicePath = root.getString("servicePath");
String title = root.getString("title");
String version = root.getString("version");
boolean versionModule = root.getBoolean("version_module");
String baseUrl =
root.has("baseUrl")
? root.getString("baseUrl")
: (rootUrl + Strings.nullToEmpty(root.getString("basePath")));
Document thisDocument =
new AutoValue_Document(
"", // authInstructionsUrl (only intended to be overridden).
authScopes.build(),
authType,
baseUrl,
canonicalName,
description,
"", // discoveryDocUrl (only intended to be overridden).
id,
methods,
name,
ownerDomain,
resources,
revision,
rootUrl,
schemas,
servicePath,
title,
version,
versionModule);
for (Schema schema : schemas.values()) {
schema.setParent(thisDocument);
}
for (Method method : methods) {
method.setParent(thisDocument);
}
for (List<Method> resourceMethods : resources.values()) {
for (Method method : resourceMethods) {
method.setParent(thisDocument);
}
}
return thisDocument;
}
private static Map<String, List<Method>> parseResources(DiscoveryNode root) {
List<Method> methods = new ArrayList<>();
DiscoveryNode methodsNode = root.getObject("methods");
List<String> resourceNames = methodsNode.getFieldNames();
for (String name : resourceNames) {
methods.add(Method.from(methodsNode.getObject(name), null));
}
Map<String, List<Method>> resources = new LinkedTreeMap<>();
DiscoveryNode resourcesNode = root.getObject("resources");
resourceNames = resourcesNode.getFieldNames();
for (String name : resourceNames) {
resources.put(name, parseMethods(resourcesNode.getObject(name)));
}
return resources;
}
private static List<Method> parseMethods(DiscoveryNode root) {
List<Method> methods = new ArrayList<>();
DiscoveryNode methodsNode = root.getObject("methods");
List<String> resourceNames = methodsNode.getFieldNames();
for (String name : resourceNames) {
methods.add(Method.from(methodsNode.getObject(name), null));
}
DiscoveryNode resourcesNode = root.getObject("resources");
resourceNames = resourcesNode.getFieldNames();
for (String name : resourceNames) {
methods.addAll(parseMethods(resourcesNode.getObject(name)));
}
return methods;
}
private static Map<String, Schema> parseSchemas(DiscoveryNode root) {
Map<String, Schema> schemas = new LinkedHashMap<>();
DiscoveryNode schemasNode = root.getObject("schemas");
for (String name : schemasNode.getFieldNames()) {
schemas.put(name, Schema.from(schemasNode.getObject(name), name, null));
}
return schemas;
}
/** @return the parent Node that contains this node. */
@JsonIgnore @Nullable private Node parent;
@Override
public Node parent() {
return parent;
}
// Package private for use by other Node objects.
void setParent(Node parent) {
this.parent = parent;
}
/** @return the auth instructions URL. */
@JsonProperty("authInstructionsUrl")
public abstract String authInstructionsUrl();
/** @return The list of OAuth2 scopes; this can be empty. */
public abstract List<String> authScopes();
/** @return the auth type. */
@JsonProperty("authType")
public abstract AuthType authType();
/** @return the base URL. */
@JsonProperty("baseUrl")
public abstract String baseUrl();
/** @return the canonical name. */
@JsonProperty("canonicalName")
public abstract String canonicalName();
/** @return the description. */
@JsonProperty("description")
public abstract String description();
/** @return the discovery document URL. */
@JsonProperty("discoveryDocUrl")
public abstract String discoveryDocUrl();
/** @return the ID of the Discovery document for the API. */
@Override
@JsonProperty("id")
public abstract String id();
/** @return the list of all methods. */
@JsonProperty("methods")
public abstract List<Method> methods();
/** @return the name. */
@JsonProperty("name")
public abstract String name();
/** @return the name. */
@JsonProperty("name")
public abstract String ownerDomain();
/** @return the revision. */
@JsonProperty("revision")
public abstract Map<String, List<Method>> resources();
/** @return the revision. */
@JsonProperty("revision")
public abstract String revision();
/** @return the root URL. */
@JsonProperty("rootUrl")
public abstract String rootUrl();
/** @return the map of schema IDs to schemas. */
@JsonProperty("schemas")
public abstract Map<String, Schema> schemas();
/** @return the service path. */
@JsonProperty("servicePath")
public abstract String servicePath();
/** @return the title. */
@JsonProperty("title")
public abstract String title();
/** @return the version. */
@JsonProperty("version")
public abstract String version();
/** @return whether or not to version the module. */
@JsonProperty("versionModule")
public abstract boolean versionModule();
/** The set of supported authentication formats. */
public enum AuthType {
/** No auth. */
NONE,
/** Application default credentials based auth. */
ADC,
/** 3-legged OAuth based auth. */
OAUTH_3L,
/** API key based auth. */
API_KEY,
}
}