001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.ecm.automation.core.annotations; 020 021import java.lang.annotation.ElementType; 022import java.lang.annotation.Retention; 023import java.lang.annotation.RetentionPolicy; 024import java.lang.annotation.Target; 025 026import org.nuxeo.ecm.automation.OutputCollector; 027import org.nuxeo.ecm.core.api.AsyncService; 028import org.nuxeo.ecm.core.bulk.BulkService; 029 030/** 031 * To be used to mark methods provided by an operation. A method must have at most one argument which is the operation 032 * input and a return type which is the operation output. Methods with zero parameters (void input) will match any 033 * input. An operation may have multiple methods if it supports multiple input and output types. 034 * <p> 035 * For each INPUT/OUTPUT type association you must create a new method in an operation and annotate it using this 036 * annotation. The set of input types available in an operation are the operation accepted types and the set of output 037 * types are the operation produced types. A produced type will become the input type for the next operation in the 038 * chain, that will be dispatched to the right method that know how to consume the type. 039 * <p> 040 * When an operation provides 2 methods accepting the same input type the chain will need to take a decision to 041 * determine the best way to continue. A common algorithm to find the right path until the end of the chain is 042 * backtracking: from a set of potential nodes one is selected to be visited (randomly or not). If the node is a dead 043 * end then another node from the set is taken until the path to the last node is created. 044 * <p> 045 * A chain may have no paths until the last operation. In this case the chain is invalid and the chain processor will 046 * trigger an error. Also, a chain can provide multiple paths to the last operation. To help the engine to find the best 047 * path until the last operation you can use the {@link #priority()} attribute to specify which method is preferred. The 048 * default priority is 0 (e.g. no priority). Higher priorities have more chance to be selected when a conflict occurs. 049 * If no user priority is specified (i.e. priority is 0) then the default priority is used. Here is how the default 050 * priority is computed (the top most case has the greater priority): 051 * <ul> 052 * <li>The input type is an exact match of the method declared argument 053 * <li>The method argument type is assignable from the input type (i.e. a super type but not an exact match) 054 * <li>The input can be adapted to the method argument using registered type adapters 055 * <li>the method has no arguments (void input) 056 * </ul> 057 * If no one of these rules applies then the method will not match the input. 058 * <p> 059 * The class owning the annotated method must be annotated using {@link Operation} 060 * 061 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 062 */ 063@Retention(RetentionPolicy.RUNTIME) 064@Target(ElementType.METHOD) 065public @interface OperationMethod { 066 067 /** 068 * If defined the method is iterable. 069 * <p> 070 * It means that when such a method is called with an input type of <code>Iterable<INPUT></code> (where INPUT is the 071 * declared method input type) the method will be iteratively called to generate all the outputs and collect them 072 * using the given OutputCollector. 073 * 074 * @return 075 */ 076 @SuppressWarnings("rawtypes") 077 Class<? extends OutputCollector> collector() default OutputCollector.class; 078 079 int priority() default 0; 080 081 boolean async() default false; 082 083 Class<? extends AsyncService> asyncService() default AsyncService.class; 084}