2121import java .util .LinkedHashMap ;
2222import java .util .List ;
2323import java .util .Map ;
24- import java .util .stream .Collectors ;
25- import javax .annotation .Nullable ;
2624import java .util .regex .Matcher ;
2725import java .util .regex .Pattern ;
28-
26+ import java .util .stream .Collectors ;
27+ import javax .annotation .Nullable ;
2928
3029/**
3130 * Adapted from its counterpart in gapic-generator.
3736@ AutoValue
3837public abstract class Method implements Comparable <Method >, Node {
3938
40- /** Regex for finding the lone subresource pattern `{+FOO}` in a Discovery `path` field.*/
39+ /** Regex for finding the lone subresource pattern `{+FOO}` in a Discovery `path` field. */
4140 private static Pattern PATH_SUBRESOURCE_PATTERN = Pattern .compile ("\\ {\\ +([a-zA-Z0-9]+)\\ }" );
4241
4342 /**
@@ -51,15 +50,15 @@ public static Method from(DiscoveryNode root, Node parent) {
5150 String httpMethod = root .getString ("httpMethod" );
5251 String id = root .getString ("id" );
5352 String path = root .getString ("path" );
54- String flatPath = accomodatePathSubresources (path , root .has ("flatPath" ) ? root .getString ("flatPath" ) : path );
53+ String flatPath =
54+ accomodatePathSubresources (path , root .has ("flatPath" ) ? root .getString ("flatPath" ) : path );
5555 String apiVersion = root .getString ("apiVersion" );
5656
5757 DiscoveryNode parametersNode = root .getObject ("parameters" );
5858 Map <String , Schema > parameters = new LinkedHashMap <>();
5959 Map <String , Schema > queryParams = new LinkedHashMap <>();
6060 Map <String , Schema > pathParams = new LinkedHashMap <>();
6161
62-
6362 for (String name : root .getObject ("parameters" ).getFieldNames ()) {
6463 Schema schema = Schema .from (parametersNode .getObject (name ), name , null );
6564 // TODO: Remove these checks once we're sure that parameters can't be objects/arrays.
@@ -129,89 +128,88 @@ public static Method from(DiscoveryNode root, Node parent) {
129128 return thisMethod ;
130129 }
131130
132- /**
133- * Expands subresource templates in a flatPath using wildcards instead of subresource-field references.
134- *
135- * If path contains a segment like {+FOO}, that indicates that
136- * `FOO` is structured and refers to a sub-resource. In that case,
137- * the corresponding `flatPath` is presented in Discovery as the
138- * full template expansion of the subresource, which could itself
139- * refer to fields from the subresource message but not from the
140- * request where `flatPath` appears. For example, if the Discovery
141- * files contains
142- * "path": "something/{+foo}/random"
143- * "flatPath": "something/galaxy/{galaxyId}/system/{systemId}/planet/{planetId}/random"
144- * then this function wildcards the subresource-field references,
145- * so that flatPath behaves as though it had been specified this
146- * way (the Discovery file would have asterisks * instead of the
147- * star ✴ used below because this documentation is in a Java
148- * comment):
149- * "flatPath": "something/galaxy/✴/system/✴/planet/✴/random"
150- *
151- *
152- * @param path The template path containing the {+FOO} token denoting a subresource. Only one such subresource is allowed.
153- * @param flatPath The flattened path whose field references inside the subresource segement will be wildcarded.
154- * @return The processed string.
155- * @throws IllegalArgumentException If path has multiple tokens or flatPath doesn't match prefix/suffix.
156- */
157- public static String accomodatePathSubresources (String path , String flatPath ) {
158- // Regex to find {+FOO}, where FOO is alphanumeric.
159- // We escape the braces and the plus sign. We capture FOO.
160- Matcher matcher = PATH_SUBRESOURCE_PATTERN .matcher (path );
161-
162- int matchCount = 0 ;
163- while (matcher .find ()) {
164- matchCount ++;
165- }
166-
167- // Logic Branch 1: No instances of {+FOO}
168- if (matchCount == 0 ) {
169- return flatPath ;
170- }
171-
172- // Logic Branch 2: More than one instance
173- if (matchCount > 1 ) {
174- throw new IllegalArgumentException ("Error: 'path' contains multiple instances of variable expansion tokens." );
175- }
176-
177- // Logic Branch 3: Exactly one instance
178- matcher .reset (); // Reset matcher to retrieve positions
179- matcher .find ();
180-
181- String tokenName = Name .anyCamel (matcher .group (1 )).toLowerUnderscore ();
182-
183- // Extract Prefix and Suffix from 'path'
184-
185- String prefix = path .substring (0 , matcher .start ());
186- String suffix = path .substring (matcher .end ());
187-
188- // Validate 'flatPath' against prefix and suffix
189- // We must also check that the total length is sufficient to contain both without overlap
190- if (!flatPath .startsWith (prefix ) ||
191- !flatPath .endsWith (suffix ) ||
192- flatPath .length () < (prefix .length () + suffix .length ())) {
193- throw new IllegalArgumentException ("Error: 'flatPath' does not match the structure defined by 'path'." );
194- }
195-
196- // Extract subresource
197- // This is the content between the prefix and the suffix in flatPath
198- int subresourceStart = prefix .length ();
199- int subresourceEnd = flatPath .length () - suffix .length ();
200- String subresource = flatPath .substring (subresourceStart , subresourceEnd );
201-
202- // Modify subresource
203- // Regex: Opening brace {, followed by any character that is NOT a closing brace, followed by }
204- // This ensures we stop at the *next* closing brace.
205- // Note that any subresource's empty placeholders `{}` are
206- // not replaced; this anomalous condition will generate an
207- // error downstream in generators or GAPICs.
208- String modifiedSubresource = subresource .replaceAll ("\\ {[^}]+\\ }" , "*" );
209-
210- // Reconstruct and return
211- return prefix + "{" + tokenName + "=" + modifiedSubresource + "}" + suffix ;
212-
213- }
214-
131+ /**
132+ * Expands subresource templates in a flatPath using wildcards instead of subresource-field
133+ * references.
134+ *
135+ * <p>If path contains a segment like {+FOO}, that indicates that `FOO` is structured and refers
136+ * to a sub-resource. In that case, the corresponding `flatPath` is presented in Discovery as the
137+ * full template expansion of the subresource, which could itself refer to fields from the
138+ * subresource message but not from the request where `flatPath` appears. For example, if the
139+ * Discovery files contains "path": "something/{+foo}/random" "flatPath":
140+ * "something/galaxy/{galaxyId}/system/{systemId}/planet/{planetId}/random" then this function
141+ * wildcards the subresource-field references, so that flatPath behaves as though it had been
142+ * specified this way (the Discovery file would have asterisks * instead of the star ✴ used below
143+ * because this documentation is in a Java comment): "flatPath":
144+ * "something/galaxy/✴/system/✴/planet/✴/random"
145+ *
146+ * @param path The template path containing the {+FOO} token denoting a subresource. Only one such
147+ * subresource is allowed.
148+ * @param flatPath The flattened path whose field references inside the subresource segement will
149+ * be wildcarded.
150+ * @return The processed string.
151+ * @throws IllegalArgumentException If path has multiple tokens or flatPath doesn't match
152+ * prefix/suffix.
153+ */
154+ public static String accomodatePathSubresources (String path , String flatPath ) {
155+ // Regex to find {+FOO}, where FOO is alphanumeric.
156+ // We escape the braces and the plus sign. We capture FOO.
157+ Matcher matcher = PATH_SUBRESOURCE_PATTERN .matcher (path );
158+
159+ int matchCount = 0 ;
160+ while (matcher .find ()) {
161+ matchCount ++;
162+ }
163+
164+ // Logic Branch 1: No instances of {+FOO}
165+ if (matchCount == 0 ) {
166+ return flatPath ;
167+ }
168+
169+ // Logic Branch 2: More than one instance
170+ if (matchCount > 1 ) {
171+ throw new IllegalArgumentException (
172+ "Error: 'path' contains multiple instances of variable expansion tokens." );
173+ }
174+
175+ // Logic Branch 3: Exactly one instance
176+ matcher .reset (); // Reset matcher to retrieve positions
177+ matcher .find ();
178+
179+ String tokenName = Name .anyCamel (matcher .group (1 )).toLowerUnderscore ();
180+
181+ // Extract Prefix and Suffix from 'path'
182+
183+ String prefix = path .substring (0 , matcher .start ());
184+ String suffix = path .substring (matcher .end ());
185+
186+ // Validate 'flatPath' against prefix and suffix
187+ // We must also check that the total length is sufficient to contain both without overlap
188+ if (!flatPath .startsWith (prefix )
189+ || !flatPath .endsWith (suffix )
190+ || flatPath .length () < (prefix .length () + suffix .length ())) {
191+ throw new IllegalArgumentException (
192+ "Error: 'flatPath' does not match the structure defined by 'path'." );
193+ }
194+
195+ // Extract subresource
196+ // This is the content between the prefix and the suffix in flatPath
197+ int subresourceStart = prefix .length ();
198+ int subresourceEnd = flatPath .length () - suffix .length ();
199+ String subresource = flatPath .substring (subresourceStart , subresourceEnd );
200+
201+ // Modify subresource
202+ // Regex: Opening brace {, followed by any character that is NOT a closing brace, followed by }
203+ // This ensures we stop at the *next* closing brace.
204+ // Note that any subresource's empty placeholders `{}` are
205+ // not replaced; this anomalous condition will generate an
206+ // error downstream in generators or GAPICs.
207+ String modifiedSubresource = subresource .replaceAll ("\\ {[^}]+\\ }" , "*" );
208+
209+ // Reconstruct and return
210+ return prefix + "{" + tokenName + "=" + modifiedSubresource + "}" + suffix ;
211+ }
212+
215213 @ Override
216214 public int compareTo (Method other ) {
217215 return id ().compareTo (other .id ());
0 commit comments