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

com.google.api.control.model.ResourceName Maven / Gradle / Ivy

There is a newer version: 1.0.14
Show newest version
/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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
 *
 *     http://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.api.control.model;

import com.google.common.annotations.Beta;
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: * *

 *   PathTemplate template = PathTemplate.create("shelves/*/books/*");
 *   ResourceName resourceName = ResourceName.create(template, "shelves/s1/books/b1");
 *   assert resourceName.get("$1").equals("b1");
 *   assert resourceName.parentName().toString().equals("shelves/s1/books");
 * 
*/ @Beta public class ResourceName 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, ResourceName 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, ResourceName 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 ResourceName create(PathTemplate template, String path) { ImmutableMap values = template.match(path); if (values == null) { throw new ValidationException("path '%s' does not match template '%s'", path, template); } return new ResourceName(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 ResourceName 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 ResourceName(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 ResourceName createFromFullName(PathTemplate template, String path) { ImmutableMap values = template.matchFromFullName(path); if (values == null) { return null; } return new ResourceName(template, values, null); } private final PathTemplate template; private final ImmutableMap values; private final String endpoint; private volatile String stringRepr; private ResourceName(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 ResourceName)) { return false; } ResourceName other = (ResourceName) 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 ResourceName withEndpoint(String endpoint) { return new ResourceName(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 ResourceName parentName() { PathTemplate parentTemplate = template.parentTemplate(); return new ResourceName(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(ResourceName parentName) { // TODO(wrwg): 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