package com.atlassian.stash.internal.rest.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * May be applied to {@code EntityHolder} REST resource parameters to allow them to be correctly deserialized.
 * <p>
 * An example REST method would look like this:
 * <code><pre>
 * &#064;Path("/example")
 * &#064;POST
 * public Response someMethod(&#064;OptionalBody EntityHolder&lt;RestExampleRequest&gt; bodyHolder) {
 *     if (bodyHolder.hasEntity()) {
 *         //Do something with the optional body, which will be deserialized according to the requested
 *         //MediaType and set as the entity on the holder
 *     } else {
 *         //The POST did not include any payload. In this case EntityHolder.getEntity() will return null
 *     }
 *
 *     ...
 * }
 * </pre></code>
 * <p>
 * The {@code EntityHolder} parameter <i>must have type arguments</i>. Those type arguments will be used to the
 * type the body should be deserialized to, if a body is provided.
 * <p>
 * <b>Note</b>: This is the standard behavior of {@code EntityHolder}; there's nothing special about this annotation.
 * However, for long, complicated reasons, {@code EntityHolder} doesn't work directly with Atlassian REST. Applying
 * this annotation triggers {@link com.atlassian.stash.internal.rest.inject.OptionalBodyInjectableProvider
 * OptionalBodyInjectableProvider} to handle the body instead of relying on Jersey's normal parsing. See the provider
 * Javadocs for the gory details.
 *
 * @since 3.7
 * @see com.atlassian.stash.internal.rest.inject.OptionalBodyInjectableProvider OptionalBodyInjectableProvider
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface OptionalBody {
}
