All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.api.pathtemplate.TemplatedResourceName Maven / Gradle / Ivy

There is a newer version: 2.41.0
Show newest version
/*
 * Copyright 2016, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.google.api.pathtemplate;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Class for representing and working with resource names.
 *
 * 

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. * *

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. * *

Usage examples: * *

{@code
 * PathTemplate template = PathTemplate.create("shelves/*/books/*");
 * TemplatedResourceName resourceName = TemplatedResourceName.create(template, "shelves/s1/books/b1");
 * assert resourceName.get("$1").equals("b1");
 * assert resourceName.parentName().toString().equals("shelves/s1/books");
 * }
*/ public class TemplatedResourceName implements Map { // ResourceName Resolver // ===================== /** Represents a resource name resolver which can be registered with this class. */ public interface Resolver { /** Resolves the resource name into a resource by calling the underlying API. */ T resolve(Class resourceType, TemplatedResourceName name, @Nullable String version); } // The registered resource name resolver. // TODO(wrwg): its a bit spooky to have this static global. Think of ways to // configure this from the outside instead if programmatically (e.g. java properties). private static volatile Resolver resourceNameResolver = new Resolver() { @Override public T resolve(Class resourceType, TemplatedResourceName name, String version) { throw new IllegalStateException( "No resource name resolver is registered in ResourceName class."); } }; /** * 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; } // ResourceName // ============ /** * Creates a new resource name based on given template and path. The path must match the template, * otherwise null is returned. * * @throws ValidationException if the path does not match the template. */ public static TemplatedResourceName create(PathTemplate template, String path) { Map values = template.match(path); if (values == null) { throw new ValidationException("path '%s' does not match template '%s'", path, template); } return new TemplatedResourceName(template, values, null); } /** * Creates a new resource name from a template and a value assignment for variables. * * @throws ValidationException if not all variables in the template are bound. */ public static TemplatedResourceName create(PathTemplate template, Map values) { if (!values.keySet().containsAll(template.vars())) { Set unbound = Sets.newLinkedHashSet(template.vars()); unbound.removeAll(values.keySet()); throw new ValidationException("unbound variables: %s", unbound); } return new TemplatedResourceName(template, values, null); } /** * Creates a new resource name based on given template and path, where the path contains an * endpoint. If the path does not match, null is returned. */ @Nullable public static TemplatedResourceName createFromFullName(PathTemplate template, String path) { Map values = template.matchFromFullName(path); if (values == null) { return null; } return new TemplatedResourceName(template, values, null); } private final PathTemplate template; private final ImmutableMap values; private final String endpoint; private volatile String stringRepr; private TemplatedResourceName( PathTemplate template, Map values, String endpoint) { this.template = template; this.values = ImmutableMap.copyOf(values); this.endpoint = endpoint; } @Override public String toString() { if (stringRepr == null) { stringRepr = template.instantiate(values); } return stringRepr; } @Override public boolean equals(Object obj) { if (!(obj instanceof TemplatedResourceName)) { return false; } TemplatedResourceName other = (TemplatedResourceName) obj; return Objects.equals(template, other.template) && Objects.equals(endpoint, other.endpoint) && Objects.equals(values, other.values); } @Override public int hashCode() { return Objects.hash(template, endpoint, values); } /** Gets the template associated with this resource name. */ public PathTemplate template() { return template; } /** Checks whether the resource name has an endpoint. */ public boolean hasEndpoint() { return endpoint != null; } /** Returns the endpoint of this resource name, or null if none is defined. */ @Nullable public String endpoint() { return endpoint; } /** Returns a resource name with specified endpoint. */ public TemplatedResourceName withEndpoint(String endpoint) { return new TemplatedResourceName(template, values, Preconditions.checkNotNull(endpoint)); } /** * Returns the parent resource name. For example, if the name is {@code shelves/s1/books/b1}, the * parent is {@code shelves/s1/books}. */ public TemplatedResourceName parentName() { PathTemplate parentTemplate = template.parentTemplate(); return new TemplatedResourceName(parentTemplate, values, endpoint); } /** * 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. */ public T resolve(Class resourceType, @Nullable String version) { Preconditions.checkArgument(hasEndpoint(), "Resource name must have an endpoint."); return resourceNameResolver.resolve(resourceType, this, version); } // Map Interface // ============= @Override public int size() { return values.size(); } @Override public boolean isEmpty() { return values.isEmpty(); } @Override public boolean containsKey(Object key) { return values.containsKey(key); } @Override public boolean containsValue(Object value) { return values.containsValue(value); } @Override public String get(Object key) { return values.get(key); } @Override @Deprecated public String put(String key, String value) { return values.put(key, value); } @Override @Deprecated public String remove(Object key) { return values.remove(key); } @Override @Deprecated public void putAll(Map m) { values.putAll(m); } @Override @Deprecated public void clear() { values.clear(); } @Override public Set keySet() { return values.keySet(); } @Override public Collection values() { return values.values(); } @Override public Set> entrySet() { return values.entrySet(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy