/**
* Copyright 2013 the original author or authors.
*
* 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 io.neba.api.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Marks a parameter of a Spring @RequestMapping method as containing a resource path.
* This path is automatically resolved by NEBA using the
* {@link org.apache.sling.api.SlingHttpServletRequest#getResourceResolver() request's resource resolver}. If the annotated
* parameter's type is not {@link Class#isAssignableFrom(Class) assignable from} {@link org.apache.sling.api.resource.Resource},
* the resolved resource is {@link org.apache.sling.api.resource.Resource#adaptTo(Class) adapted} to the target type. Otherwise,
* the resolved resource is provided.
*
* <p>
* Example:
* <pre>
* @Controller
* @RequestMapping(produces = "text/plain")
* public class MyController {
* @RequestMapping("/echoTitle")
* @ResponseBody
* public String echoTitle(@{@link ResourceParam} Page page) {
* return page.getTitle();
* }
* }
* </pre>
*
* In the above example, a request parameter "page" is expected. The parameter value is regarded as a
* resource path and the corresponding resource is
* {@link org.apache.sling.api.resource.ResourceResolver#resolve(javax.servlet.http.HttpServletRequest, String) resolved}.
* The resolved resource is subsequently adapted to "Page":
*
* <pre>GET /bin/mvc.do/echoTitle?path=/content/site/en: "English page title".</pre>
* </p>
* <p>
* One may also append a segment to the path prior to resolution, for instance to target
* a sub resource of the provided path, like so:
* <pre>
* public String echoTitle(@ResourceParam(append = "jcr:content") PageContent content) {
* return page.getTitle();
* }
* </pre>
*
* The append path is also applied to the default value, if provided.
* </p>
*
* By default, @{@link ResourceParam} parameters are {@link ResourceParam#required() required}. If the parameter is missing,
* cannot be resolved to an existing resource or cannot be adapted to the required target type, an exception is thrown.
* Accordingly, the parameter provided to the controller method is guaranteed not to be <code>null</code> if it is required.
* Consequently, the parameter may be null if either the parameter value is missing, cannot
* be resolved to an existing resource or if the resolved resource cannot be adapted to the required target type
* when the parameter is not {@link ResourceParam#required() required}. If a {@link #defaultValue() default value} is provided,
* the parameter is always optional, regardless whether it is {@link #required() required}.
* If the default value cannot be resolved, the parameter provided to the method is <code>null</code>.
*
* @author Olaf Otto
*/
@Retention(RUNTIME)
@Target({PARAMETER, ANNOTATION_TYPE})
@Documented
public @interface ResourceParam {
/**
* The name of the request parameter. Defaults to the
* name of the annotated parameter.
*/
String value() default "";
/**
* @return when <code>true</code>, the resolved parameter is guaranteed not to be <code>null</code>.
*/
boolean required() default true;
/**
* @return if not <code>null</code> or empty, this default value is used in case no value is provided for this request parameter.
* Providing a default value implies {@link #required()} = false.
*/
String defaultValue() default "";
/**
* Append this path segment to the provided path prior to resource resolution.
*/
String append() default "";
}