Skip to content
This repository was archived by the owner on Sep 27, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ buildscript {
jcenter()
}
dependencies {
classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.2"
classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.6"
}
}

Expand Down Expand Up @@ -244,19 +244,21 @@ gradle.projectsEvaluated {
// Formatting tasks
// ================

task verifyLicense << {
def licenseText = new File(rootProject.rootDir, 'license-header-javadoc.txt').text
def srcFiles = []
sourceSets
.collectMany{it.allJava.getSrcDirs()}
.each{it.eachFileRecurse(FileType.FILES, {srcFiles << new Tuple(it, it.text)})}
srcFiles = srcFiles
.findAll{it.get(0).path.endsWith(".java")}
.collect{new Tuple(it.get(0), it.get(1).replaceAll("Copyright 20[0-9]{2}", "Copyright 20xx"))}
.findAll{!it.get(1).startsWith(licenseText)}
if (srcFiles.asList().size() > 0) {
srcFiles.each({println 'missing license: ' + it.get(0)})
throw new IllegalStateException("Above files do not have licenses")
task verifyLicense {
doLast {
def licenseText = new File(rootProject.rootDir, 'license-header-javadoc.txt').text
def srcFiles = []
sourceSets
.collectMany{it.allJava.getSrcDirs()}
.each{it.eachFileRecurse(FileType.FILES, {srcFiles << new Tuple(it, it.text)})}
srcFiles = srcFiles
.findAll{it.get(0).path.endsWith(".java")}
.collect{new Tuple(it.get(0), it.get(1).replaceAll("Copyright 20[0-9]{2}", "Copyright 20xx"))}
.findAll{!it.get(1).startsWith(licenseText)}
if (srcFiles.asList().size() > 0) {
srcFiles.each({println 'missing license: ' + it.get(0)})
throw new IllegalStateException("Above files do not have licenses")
}
}
}
test.dependsOn verifyLicense
Expand All @@ -280,10 +282,12 @@ test.dependsOn verifyGoogleJavaFormat
// =======

task checkOutGhPages {
if (!new File('tmp_gh-pages').exists()) {
exec {
commandLine 'git', 'clone', '--branch', 'gh-pages',
'--single-branch', 'https://github.com/googleapis/api-common-java/', 'tmp_gh-pages'
doLast {
if (!new File('tmp_gh-pages').exists()) {
exec {
commandLine 'git', 'clone', '--branch', 'gh-pages',
'--single-branch', 'https://github.com/googleapis/api-common-java/', 'tmp_gh-pages'
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/google/api/core/ApiAsyncFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@
/**
* Transforms a value, possibly asynchronously.
*
* <p>It is similar to Guava's {@code AsyncFunction}, redeclared so that Guava can be shaded.
* <p>
* It is similar to Guava's {@code AsyncFunction}, redeclared so that Guava can be shaded.
*/
public interface ApiAsyncFunction<I, O> {
/**
* Returns an output Future to use in place of the given input. The output Future need not be
* done, making AsyncFunction suitable for asynchronous derivations.
*
* <p>Throwing an exception from this method is equivalent to returning a failing Future.
* <p>
* Throwing an exception from this method is equivalent to returning a failing Future.
*/
ApiFuture<O> apply(I input) throws Exception;
}
4 changes: 2 additions & 2 deletions src/main/java/com/google/api/core/BetaApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
* <p>
* Usage guidelines:
* <ol>
* <li>This annotation is used only on APIs with public visibility. Internal interfaces should
* not use it.</li>
* <li>This annotation is used only on APIs with public visibility. Internal interfaces should not
* use it.</li>
* <li>This annotation should only be added to new APIs. Adding it to an existing API is considered
* API-breaking.</li>
* <li>Removing this annotation from an API gives it stable status.</li>
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/com/google/api/core/InternalApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@
import java.lang.annotation.Target;

/**
* Annotates a program element (class, method, package etc) which is internal to its
* containing library, not part of the public API, and should not be used by users of
* the library.
* Annotates a program element (class, method, package etc) which is internal to its containing
* library, not part of the public API, and should not be used by users of the library.
*
* This annotation only makes sense on APIs that are not private. Its existence
* is necessary because Java does not have a visibility level for code within a
* compilation unit.
* This annotation only makes sense on APIs that are not private. Its existence is necessary because
* Java does not have a visibility level for code within a compilation unit.
*/
@BetaApi
@Retention(RetentionPolicy.RUNTIME)
Expand Down
106 changes: 64 additions & 42 deletions src/main/java/com/google/api/pathtemplate/PathTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
Expand All @@ -49,24 +48,27 @@
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

/**
* Represents a path template.
*
* <p>Templates use the syntax of the API platform; see the protobuf of HttpRule for
* details. A template consists of a sequence of literals, wildcards, and variable bindings,
* where each binding can have a sub-path. A string representation can be parsed into an
* instance of {@link PathTemplate}, which can then be used to perform matching and instantiation.
* <p>
* Templates use the syntax of the API platform; see the protobuf of HttpRule for details. A
* template consists of a sequence of literals, wildcards, and variable bindings, where each binding
* can have a sub-path. A string representation can be parsed into an instance of
* {@link PathTemplate}, which can then be used to perform matching and instantiation.
*
* <p>Matching and instantiation deals with unescaping and escaping using URL encoding rules. For
* <p>
* Matching and instantiation deals with unescaping and escaping using URL encoding rules. For
* example, if a template variable for a single segment is instantiated with a string like
* {@code "a/b"}, the slash will be escaped to {@code "%2f"}. (Note that slash will not be escaped
* for a multiple-segment variable, but other characters will). The literals in the template
* itself are <em>not</em> escaped automatically, and must be already URL encoded.
* for a multiple-segment variable, but other characters will). The literals in the template itself
* are <em>not</em> escaped automatically, and must be already URL encoded.
*
* <p>
* Here is an example for a template using simple variables:
*
* <p>Here is an example for a template using simple variables:
* <pre>
* PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}");
* assert template.matches("v2/shelves") == false;
Expand All @@ -79,6 +81,7 @@
* </pre>
*
* Templates can use variables which match sub-paths. Example:
*
* <pre>
* PathTemplate template = PathTemplate.create("v1/{name=shelves/*&#47;books/*}"};
* assert template.match("v1/shelves/books/b1") == null;
Expand All @@ -87,9 +90,9 @@
* assert template.match("v1/shelves/s1/books/b1").equals(expectedValues);
* </pre>
*
* Path templates can also be used with only wildcards. Each wildcard is associated
* with an implicit variable {@code $n}, where n is the zero-based position of the
* wildcard. Example:
* Path templates can also be used with only wildcards. Each wildcard is associated with an implicit
* variable {@code $n}, where n is the zero-based position of the wildcard. Example:
*
* <pre>
* PathTemplate template = PathTemplate.create("shelves/*&#47;books/*"};
* assert template.match("shelves/books/b1") == null;
Expand All @@ -100,10 +103,11 @@
* assert values.equals(expectedValues);
* </pre>
*
* Paths input to matching can use URL relative syntax to indicate a host name by prefixing the
* host name, as in {@code //somewhere.io/some/path}. The host name is matched into the special
* variable {@link #HOSTNAME_VAR}. Patterns are agnostic about host names, and the same pattern
* can be used for URL relative syntax and simple path syntax:
* Paths input to matching can use URL relative syntax to indicate a host name by prefixing the host
* name, as in {@code //somewhere.io/some/path}. The host name is matched into the special variable
* {@link #HOSTNAME_VAR}. Patterns are agnostic about host names, and the same pattern can be used
* for URL relative syntax and simple path syntax:
*
* <pre>
* PathTemplate template = PathTemplate.create("shelves/*"};
* Map&lt;String, String&gt; expectedValues = new HashMap&lt;&gt;();
Expand All @@ -115,15 +119,15 @@
* assert template.match("shelves/s1").equals(expectedValues);
* </pre>
*
* For the representation of a <em>resource name</em> see {@link TemplatedResourceName}, which is based
* on path templates.
* For the representation of a <em>resource name</em> see {@link TemplatedResourceName}, which is
* based on path templates.
*/
@BetaApi
public class PathTemplate {

/**
* A constant identifying the special variable used for endpoint bindings in
* the result of {@link #matchFromFullName(String)}.
* A constant identifying the special variable used for endpoint bindings in the result of
* {@link #matchFromFullName(String)}.
*/
public static final String HOSTNAME_VAR = "$hostname";

Expand Down Expand Up @@ -322,16 +326,19 @@ public PathTemplate withoutVars() {
}

/**
* Returns a path template for the sub-path of the given variable. Example: <pre>
* Returns a path template for the sub-path of the given variable. Example:
*
* <pre>
* PathTemplate template = PathTemplate.create("v1/{name=shelves/*&#47;books/*}");
* assert template.subTemplate("name").toString().equals("shelves/*&#47;books/*");
* </pre>
*
* The returned template will never have named variables, but only wildcards, which are dealt with
* in matching and instantiation using '$n'-variables. See the documentation of {@link
* #match(String)} and {@link #instantiate(Map)}, respectively.
* in matching and instantiation using '$n'-variables. See the documentation of
* {@link #match(String)} and {@link #instantiate(Map)}, respectively.
*
* <p>For a variable which has no sub-path, this returns a path template with a single wildcard
* <p>
* For a variable which has no sub-path, this returns a path template with a single wildcard
* ('*').
*
* @throws ValidationException if the variable does not exist in the template.
Expand Down Expand Up @@ -413,13 +420,18 @@ public void validate(String path, String exceptionMessagePrefix) {
* throws a ValidationException. The exceptionMessagePrefix parameter will be prepended to the
* ValidationException message.
*
* <p>If the path starts with '//', the first segment will be interpreted as a host name and
* stored in the variable {@link #HOSTNAME_VAR}.
* <p>
* If the path starts with '//', the first segment will be interpreted as a host name and stored
* in the variable {@link #HOSTNAME_VAR}.
*
* <p>
* See the {@link PathTemplate} class documentation for examples.
*
* <p>See the {@link PathTemplate} class documentation for examples.
* <p>
* For free wildcards in the template, the matching process creates variables named '$n', where
* 'n' is the wildcard's position in the template (starting at n=0). For example:
*
* <p>For free wildcards in the template, the matching process creates variables named '$n', where
* 'n' is the wildcard's position in the template (starting at n=0). For example: <pre>
* <pre>
* PathTemplate template = PathTemplate.create("shelves/*&#47;books/*");
* Map&lt;String, String&gt; expectedValues = new HashMap&lt;&gt;();
* expectedValues.put("$0", "s1");
Expand Down Expand Up @@ -462,13 +474,18 @@ public boolean matches(String path) {
* will be properly unescaped using URL encoding rules. If the path does not match the template,
* null is returned.
*
* <p>If the path starts with '//', the first segment will be interpreted as a host name and
* stored in the variable {@link #HOSTNAME_VAR}.
* <p>
* If the path starts with '//', the first segment will be interpreted as a host name and stored
* in the variable {@link #HOSTNAME_VAR}.
*
* <p>
* See the {@link PathTemplate} class documentation for examples.
*
* <p>See the {@link PathTemplate} class documentation for examples.
* <p>
* For free wildcards in the template, the matching process creates variables named '$n', where
* 'n' is the wildcard's position in the template (starting at n=0). For example:
*
* <p>For free wildcards in the template, the matching process creates variables named '$n', where
* 'n' is the wildcard's position in the template (starting at n=0). For example: <pre>
* <pre>
* PathTemplate template = PathTemplate.create("shelves/*&#47;books/*");
* Map&lt;String, String&gt; expectedValues = new HashMap&lt;&gt;();
* expectedValues.put("$0", "s1");
Expand All @@ -491,7 +508,9 @@ public Map<String, String> match(String path) {

/**
* Matches the path, where the first segment is interpreted as the host name regardless of whether
* it starts with '//' or not. Example: <pre>
* it starts with '//' or not. Example:
*
* <pre>
* Map&lt;String, String&gt; expectedValues = new HashMap&lt;&gt;();
* expectedValues.put(HOSTNAME_VAR, "//somewhere.io");
* expectedValues.put("name", "shelves/s1");
Expand Down Expand Up @@ -618,9 +637,10 @@ private boolean match(
* Instantiate the template based on the given variable assignment. Performs proper URL escaping
* of variable assignments.
*
* <p>Note that free wildcards in the template must have bindings of '$n' variables, where 'n' is
* the position of the wildcard (starting at 0). See the documentation of {@link #match(String)}
* for details.
* <p>
* Note that free wildcards in the template must have bindings of '$n' variables, where 'n' is the
* position of the wildcard (starting at 0). See the documentation of {@link #match(String)} for
* details.
*
* @throws ValidationException if a variable occurs in the template without a binding.
*/
Expand All @@ -641,7 +661,9 @@ public String instantiate(String... keysAndValues) {

/**
* Same like {@link #instantiate(Map)} but allows for unbound variables, which are substituted
* using their original syntax. Example: <pre>
* using their original syntax. Example:
*
* <pre>
* PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}");
* Map&lt;String, String&gt; partialMap = new HashMap&lt;&gt;();
* partialMap.put("shelf", "s1");
Expand Down Expand Up @@ -957,8 +979,8 @@ public String toString() {
}

/**
* Returns a raw version of the template as a string. This renders the template in its
* internal, normalized form.
* Returns a raw version of the template as a string. This renders the template in its internal,
* normalized form.
*/
public String toRawString() {
return toSyntax(segments, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,19 @@
/**
* Class for representing and working with resource names.
*
* <p>A resource name is represented by {@link PathTemplate}, an assignment to variables in the
* <p>
* A resource name is represented by {@link PathTemplate}, an assignment to variables in the
* template, and an optional endpoint. The {@code ResourceName} class implements the map interface
* (unmodifiable) to work with the variable assignments, and has methods to reproduce the string
* representation of the name, to construct new names, and to dereference names into resources.
*
* <p>As a resource name essentially represents a match of a path template against a string, it can
* be also used for other purposes than naming resources. However, not all provided methods may make
* <p>
* As a resource name essentially represents a match of a path template against a string, it can be
* also used for other purposes than naming resources. However, not all provided methods may make
* sense in all applications.
*
* <p>Usage examples:
* <p>
* Usage examples:
*
* <pre>
* PathTemplate template = PathTemplate.create("shelves/*&#47;books/*");
Expand Down Expand Up @@ -91,8 +94,8 @@ public <T> T resolve(Class<T> resourceType, TemplatedResourceName name, String v
};

/**
* Sets the resource name resolver which is used by the {@link #resolve(Class, String)} method.
* By default, no resolver is registered.
* Sets the resource name resolver which is used by the {@link #resolve(Class, String)} method. By
* default, no resolver is registered.
*/
public static void registerResourceNameResolver(Resolver resolver) {
resourceNameResolver = resolver;
Expand Down Expand Up @@ -218,18 +221,18 @@ public TemplatedResourceName parentName() {
}

/**
* Returns true of the resource name starts with the parent resource name, i.e. is a child
* of the parent.
* Returns true of the resource name starts with the parent resource name, i.e. is a child of the
* parent.
*/
public boolean startsWith(TemplatedResourceName parentName) {
// TODO: more efficient implementation.
return toString().startsWith(parentName.toString());
}

/**
* Attempts to resolve a resource name into a resource, by calling the associated API.
* The resource name must have an endpoint. An optional version can be specified to
* determine in which version of the API to call.
* Attempts to resolve a resource name into a resource, by calling the associated API. The
* resource name must have an endpoint. An optional version can be specified to determine in which
* version of the API to call.
*/
public <T> T resolve(Class<T> resourceType, @Nullable String version) {
Preconditions.checkArgument(hasEndpoint(), "Resource name must have an endpoint.");
Expand Down
Loading