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

org.apache.juneau.rest.BasicRestInfoProvider Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you 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 org.apache.juneau.rest;

import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;

import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;

import org.apache.juneau.dto.swagger.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.svl.*;

/**
 * Default implementation of {@link RestInfoProvider}.
 *
 * 

* Subclasses can override these methods to tailor how HTTP REST resources are documented. * *

See Also:
*
    *
  • {@link RestContext#REST_infoProvider} *
*/ public class BasicRestInfoProvider implements RestInfoProvider { private final RestContext context; private final String siteName, title, description; private final ConcurrentHashMap> swaggers = new ConcurrentHashMap<>(); /** * Constructor. * * @param context The resource context. */ public BasicRestInfoProvider(RestContext context) { this.context = context; Builder b = new Builder(context); this.siteName = b.siteName; this.title = b.title; this.description = b.description; } private static final class Builder { String siteName, title, description; Builder(RestContext context) { for (RestResource r : getAnnotationsParentFirst(RestResource.class, context.getResource().getClass())) { if (! r.siteName().isEmpty()) siteName = r.siteName(); if (r.title().length > 0) title = joinnl(r.title()); if (r.description().length > 0) description = joinnl(r.description()); } } } /** * Returns the localized swagger for this REST resource. * *

* Subclasses can override this method to customize the Swagger. * * @param req The incoming HTTP request. * @return * A new Swagger instance. *
Never null. * @throws Exception */ @Override /* RestInfoProvider */ public Swagger getSwagger(RestRequest req) throws Exception { Locale locale = req.getLocale(); // Find it in the cache. // Swaggers are cached by user locale and an int hash of the @RestMethods they have access to. HashCode userHash = HashCode.create(); for (RestJavaMethod sm : context.getCallMethods().values()) if (sm.isRequestAllowed(req)) userHash.add(sm.hashCode()); int hashCode = userHash.get(); if (! swaggers.containsKey(locale)) swaggers.putIfAbsent(locale, new ConcurrentHashMap()); Swagger swagger = swaggers.get(locale).get(hashCode); if (swagger != null) return swagger; // Wasn't cached...need to create one. swagger = new SwaggerGenerator(req).getSwagger(); swaggers.get(locale).put(hashCode, swagger); return swagger; } /** * Returns the localized summary of the specified java method on this servlet. * *

* Subclasses can override this method to provide their own summary. * *

* The default implementation returns the value from the following locations (whichever matches first): *

    *
  1. {@link RestMethod#summary() @RestMethod(summary)} annotation. *
    Examples:
    *

    * // Direct value * @RestMethod(summary="Summary of my method") * public Object myMethod() {...} * * // Pulled from some other location * @RestMethod(summary="$L{myLocalizedSummary}") * public Object myMethod() {...} *

    *
  2. Localized string from resource bundle identified by {@link RestResource#messages() @RestResource(messages)} * on the resource class, then any parent classes. *
      *
    1. [ClassName].[javaMethodName].summary *
    2. [javaMethodName].summary *
    *
    Value can contain any SVL variables defined on the {@link RestMethod#summary() @RestMethod(summary)} annotation. *
    Examples:
    *

    * // Direct value * MyClass.myMethod.summary = Summary of my method. * * // Pulled from some other location * MyClass.myMethod.summary = $C{MyStrings/MyClass.myMethod.summary} *

    *
* * @param method The Java method annotated with {@link RestMethod @RestMethod}. * @param req The current request. * @return The localized summary of the method, or null if none was found. * @throws Exception */ @Override /* RestInfoProvider */ public String getMethodSummary(Method method, RestRequest req) throws Exception { VarResolverSession vr = req.getVarResolverSession(); String s = method.getAnnotation(RestMethod.class).summary(); if (s.isEmpty()) { Operation o = getSwaggerOperation(method, req); if (o != null) s = o.getSummary(); } return isEmpty(s) ? null : vr.resolve(s); } /** * Returns the localized description of the specified java method on this servlet. * *

* Subclasses can override this method to provide their own description. * *

* The default implementation returns the value from the following locations (whichever matches first): *

    *
  1. {@link RestMethod#description() @RestMethod(description)} annotation. *
    Examples:
    *

    * // Direct value * @RestMethod(description="Description of my method") * public Object myMethod() {...} * * // Pulled from some other location * @RestMethod(description="$L{myLocalizedDescription}") * public Object myMethod() {...} *

    *
  2. Localized string from resource bundle identified by {@link RestResource#messages() @RestResource(messages)} * on the resource class, then any parent classes. *
      *
    1. [ClassName].[javaMethodName].description *
    2. [javaMethodName].description *
    *
    Value can contain any SVL variables defined on the {@link RestMethod#description() @RestMethod(description)} annotation. *
    Examples:
    *

    * // Direct value * MyClass.myMethod.description = Description of my method. * * // Pulled from some other location * MyClass.myMethod.description = $C{MyStrings/MyClass.myMethod.description} *

    *
* * @param method The Java method annotated with {@link RestMethod @RestMethod}. * @param req The current request. * @return The localized description of the method, or null if none was found. * @throws Exception */ @Override /* RestInfoProvider */ public String getMethodDescription(Method method, RestRequest req) throws Exception { VarResolverSession vr = req.getVarResolverSession(); String s = joinnl(method.getAnnotation(RestMethod.class).description()); if (s.isEmpty()) { Operation o = getSwaggerOperation(method, req); if (o != null) s = o.getDescription(); } return isEmpty(s) ? null : vr.resolve(s); } /** * Returns the localized site name of this REST resource. * *

* Subclasses can override this method to provide their own site name. * *

* The default implementation returns the value from the following locations (whichever matches first): *

    *
  1. {@link RestResource#siteName() @RestResource(siteName)} annotation on this class, and then any parent classes. *
    Examples:
    *

    * // Direct value * @RestResource(siteName="My Site") * public class MyResource {...} * * // Pulled from some other location * @RestResource(siteName="$L{myLocalizedSiteName}") * public class MyResource {...} *

    *
  2. Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource(messages)} * on the resource class, then any parent classes. *
      *
    1. [ClassName].siteName *
    2. siteName *
    *
    Value can contain any SVL variables defined on the {@link RestResource#siteName() @RestResource(siteName)} annotation. *
    Examples:
    *

    * // Direct value * MyClass.siteName = My Site * * // Pulled from some other location * MyClass.siteName = $C{MyStrings/MyClass.siteName} *

    *
* * @param req The current request. * @return The localized site name of this REST resource, or null if none was found. * @throws Exception */ @Override /* RestInfoProvider */ public String getSiteName(RestRequest req) throws Exception { VarResolverSession vr = req.getVarResolverSession(); if (siteName != null) return vr.resolve(siteName); String siteName = context.getMessages().findFirstString(req.getLocale(), "siteName"); if (siteName != null) return vr.resolve(siteName); return null; } /** * Returns the localized title of this REST resource. * *

* Subclasses can override this method to provide their own title. * *

* The default implementation returns the value from the following locations (whichever matches first): *

    *
  1. {@link RestResource#title() @RestResource(siteName)} annotation on this class, and then any parent classes. *
    Examples:
    *

    * // Direct value * @RestResource(title="My Resource") * public class MyResource {...} * * // Pulled from some other location * @RestResource(title="$L{myLocalizedTitle}") * public class MyResource {...} *

    *
  2. Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource(messages)} * on the resource class, then any parent classes. *
      *
    1. [ClassName].title *
    2. title *
    *
    Value can contain any SVL variables defined on the {@link RestResource#title() @RestResource(title)} annotation. *
    Examples:
    *

    * // Direct value * MyClass.title = My Resource * * // Pulled from some other location * MyClass.title = $C{MyStrings/MyClass.title} *

    *
  3. /info/title entry in swagger file. *
* * @param req The current request. * @return The localized title of this REST resource, or null if none was found. * @throws Exception */ @Override /* RestInfoProvider */ public String getTitle(RestRequest req) throws Exception { VarResolverSession vr = req.getVarResolverSession(); if (title != null) return vr.resolve(title); String title = context.getMessages().findFirstString(req.getLocale(), "title"); if (title != null) return vr.resolve(title); return null; } /** * Returns the localized description of this REST resource. * *

* Subclasses can override this method to provide their own description. * *

* The default implementation returns the value from the following locations (whichever matches first): *

    *
  1. {@link RestResource#description() @RestResource(description)} annotation on this class, and then any parent classes. *
    Examples:
    *

    * // Direct value * @RestResource(description="My Resource") * public class MyResource {...} * * // Pulled from some other location * @RestResource(description="$L{myLocalizedDescription}") * public class MyResource {...} *

    *
  2. Localized strings from resource bundle identified by {@link RestResource#messages() @RestResource(messages)} * on the resource class, then any parent classes. *
      *
    1. [ClassName].description *
    2. description *
    *
    Value can contain any SVL variables defined on the {@link RestResource#description() @RestResource(description)} annotation. *
    Examples:
    *

    * // Direct value * MyClass.description = My Resource * * // Pulled from some other location * MyClass.description = $C{MyStrings/MyClass.description} *

    *
  3. /info/description entry in swagger file. *
* * @param req The current request. * @return The localized description of this REST resource, or null if none was was found. * @throws Exception */ @Override /* RestInfoProvider */ public String getDescription(RestRequest req) throws Exception { VarResolverSession vr = req.getVarResolverSession(); if (description != null) return vr.resolve(description); String description = context.getMessages().findFirstString(req.getLocale(), "description"); if (description != null) return vr.resolve(description); return null; } //----------------------------------------------------------------------------------------------------------------- // Utility methods //----------------------------------------------------------------------------------------------------------------- private Operation getSwaggerOperation(Method method, RestRequest req) throws Exception { Swagger s = getSwagger(req); if (s != null) { Map sp = s.getPaths(); if (sp != null) { Map spp = sp.get(method.getAnnotation(RestMethod.class).path()); if (spp != null) return spp.get(req.getMethod()); } } return null; } static String joinnl(String[] ss) { if (ss.length == 0) return ""; return StringUtils.joinnl(ss).trim(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy