/*
 * 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.myfaces.orchestra.conversation.annotations;

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

/**
 * Can be used to prevent access to a view where the expected bean state
 * (ie conversation) does not exist, and redirect instead to another view.
 * <p>
 * This annotation is expected to be applied only to classes that are also
 * a ViewController (i.e. have the ViewController annotation applied, or
 * use one of the other mechanisms the Orchestra ViewController framework
 * supports for mapping views to controller beans). This annotation has no
 * effect when applied to a class that is not acting as a view controller.
 * <p>
 * When a workflow passes through a number of different views, all views
 * except the first one will expect a conversation to exist, with the
 * beans in that conversation holding appropriate state. If the
 * conversation does not exist then the view will fail to work correctly.
 * Possible causes for this kind of invalid state include:
 * <ul>
 * <li>A user selecting a bookmark
 * <li>A user directly manipulating a URL
 * <li>A conversation expiring
 * </ul>
 * <p>
 * To resolve these issues, a bean can use the Orchestra ViewController
 * to configure itself as being associated with specific views, then
 * use this ConversationRequire annotation to declare what conversation(s)
 * it expects to exist. When an associated view is activated and the
 * conversation does not exist then a redirect immediately occurs to the
 * specified page - which is usually set to the first page in the relevant
 * workflow.  
 */
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ConversationRequire
{
    /**
     * One or many conversation names the view require as prerequesite.
     * If one of the configured conversations is not active a redirect or
     * navigationAction will be issued.
     */
    String[] conversationNames();

    /**
     * The servlet url to redirect to if one of the conversations is not running.
     * Use either this <i>or</i> navigationAction.
     */
    String redirect() default "";

    /**
     * The logical navigation rule to execute if one of the conversations is not running.
     * <p>
     * In a JSF environment, the specified name must be configured as as a global navigation
     * rule in the application's faces-config.xml file.
     */
    String navigationAction() default "";

    /**
     * A list of viewIds which cause this annotation to be ignored. If this is defined,
     * and the current viewId matches any of the specified viewIds, then no checks for
     * active conversations is done.
     * <p>
     * A ViewController with this annotation may be referenced from multiple views, eg
     * in a "wizard" type page-flow. In this case, certain conversations are expected
     * to exist in all pages except the first, but for the first ("entry") page of the
     * wizard, they will not exist and the check should not be done. In this scenario,
     * the viewId of the "entry" page can be added to the ignoredViews property of
     * the annotation.
     * <p>
     * Note that this property does require java code to contain explicit viewIds,
     * which causes tight coupling between view "templates" and java code. However
     * this property is not mandatory; an alternative is to have just a single
     * ViewController per view, in which case this is not needed. State that needs
     * to be shared between views can be on a separate bean. 
     */
    String[] entryPointViewIds() default "";
}
