/* * Copyright (C) 2011 Google Inc. * * 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.explorer.client.base; import com.google.web.bindery.autobean.shared.AutoBean; import com.google.web.bindery.autobean.shared.AutoBean.PropertyName; import java.util.List; import java.util.Map; import java.util.Set; /** * Represents a description of an request or response, including its type, and, * if it's an object, its fields. * * @author jasonhall@google.com (Jason Hall) */ public interface Schema { public static final String KIND_KEY = "kind"; public static final String REF_KEY = "$ref"; /** Possible types. */ public enum Type { @PropertyName("string") STRING, @PropertyName("array") ARRAY, @PropertyName("object") OBJECT, @PropertyName("boolean") BOOLEAN, @PropertyName("integer") INTEGER, @PropertyName("number") NUMBER, @PropertyName("any") ANY; } /** Uniquely-identifying name of this schema. */ String getId(); /** Type of this data. */ Type getType(); /** All properties of this object, or {@code null} if this is not an object. */ Map<String, Schema> getProperties(); /** Type which should be used for the values associated with extra keys. */ Schema getAdditionalProperties(); /** * Reference to an object defining this property, or {@code null} if this is * not an otherwise-referenced object. */ @PropertyName("$ref") String getRef(); /** Default value of this property. */ String getDefault(); /** * If this is an array, Property definition of items in this array. Otherwise * {@code null}. */ Schema getItems(); /** Description of this property, {@code null} if none is given. */ String getDescription(); /** * Mapping of an annotation and a set of method identifiers for which that * annotation applies to this property. */ Map<String, Set<String>> getAnnotations(); /** * Returns true if this property is required for the method identified by the * given method identifier. */ boolean requiredForMethod(String methodIdentifier); /** * Returns true if this property is mutable (or required) for the method * identified by the given method identifier. */ boolean mutableForMethod(String methodIdentifier); /** * Regular expression pattern that any value of this parameter must match, or * {@code null} if no pattern is defined. */ String getPattern(); /** Whether or not this parameter is required. */ boolean isRequired(); /** Whether or not this parameter can be specified multiple times. */ boolean isRepeated(); /** * The minimum valid value for this parameter if the {@link Type} of the * parameter's value is {@link Type#INTEGER} or {@link Type#NUMBER}, or * {@code null} if no minimum value is defined. */ String getMinimum(); /** * The maximum valid value for this parameter if the {@link Type} of the * parameter's value is {@link Type#INTEGER} or {@link Type#NUMBER}, or * {@code null} if no maximum value is defined. */ String getMaximum(); /** * The {@link List} of valid String values for this parameter, or {@code null} * if no specific values are defined. */ @PropertyName("enum") List<String> getEnumValues(); /** * Descriptions corresponding to the valid values specified in * {@link #getEnumValues()}, or {@code null} if no specific enum values are * specified. * * <p> * The ordering of this list corresponds to the order of values in * {@link #getEnumValues()}, and may include empty strings if a value does not * have a corresponding description. * </p> */ List<String> getEnumDescriptions(); /** * Extra information to indicate whether this schema object is locked, this * does not come from Discovery and is a manifestation of the APIs Explorer's * manual creation of Schemas to represent top level parameters such as method * and version. */ boolean locked(); /** * If this schema is a reference, follow the reference and return the * referenced schema, recursively. * * @param allSchemas Map of schemas which contains all named schemas. * @return Referenced schema. */ Schema followRefs(Map<String, Schema> allSchemas); /** * Wrapper class used by the AutoBeanFactory to provide the implementation of * some methods. * * <p> * All of these methods map to a method in {@link Schema} which delegates to * the method in this class to provide its implementation. * </p> */ static class PropertyWrapper { private static final String REQUIRED = "required"; private static final String MUTABLE = "mutable"; private static boolean hasAnnotationForMethod( Schema property, String annotation, String methodIdentifier) { return property.getAnnotations() != null && property.getAnnotations().containsKey(annotation) && property.getAnnotations().get(annotation).contains(methodIdentifier); } /** * Returns true if this property is required for the method identified by * the given method identifier. */ public static boolean requiredForMethod(AutoBean<Schema> instance, String methodIdentifier) { return hasAnnotationForMethod(instance.as(), REQUIRED, methodIdentifier); } /** * Returns true if this property is mutable (or required) for the method * identified by the given method identifier. */ public static boolean mutableForMethod(AutoBean<Schema> instance, String methodIdentifier) { // Required properties will not be explicitly marked mutable, since // mutablility is assumed for required properties. return requiredForMethod(instance, methodIdentifier) || hasAnnotationForMethod(instance.as(), MUTABLE, methodIdentifier); } /** * Always returns false, only hand created schemas can be locked */ public static boolean locked(AutoBean<Schema> instance) { return false; } /** * Unwrap the schema and pass it off to the function that does the real work. */ public static Schema followRefs(AutoBean<Schema> instance, Map<String, Schema> allSchemas) { return followRefsHelper(instance.as(), allSchemas); } /** * If this schema is a reference, follow the reference and return the * referenced schema, recursively. */ private static Schema followRefsHelper(Schema possiblyARef, Map<String, Schema> allSchemas) { if (possiblyARef != null) { String ref = possiblyARef.getRef(); if (ref != null) { Schema referenced = allSchemas.get(ref); return followRefsHelper(referenced, allSchemas); } } return possiblyARef; } } }