001/*
002 * Copyright 2006-2007 the original author or authors.
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 *      https://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
017package org.springframework.batch.repeat.policy;
018
019import java.util.ArrayList;
020import java.util.Arrays;
021import java.util.List;
022
023import org.springframework.batch.repeat.CompletionPolicy;
024import org.springframework.batch.repeat.RepeatContext;
025import org.springframework.batch.repeat.RepeatStatus;
026import org.springframework.batch.repeat.context.RepeatContextSupport;
027
028/**
029 * Composite policy that loops through a list of delegate policies and answers
030 * calls by a consensus.
031 * 
032 * @author Dave Syer
033 * 
034 */
035public class CompositeCompletionPolicy implements CompletionPolicy {
036
037        CompletionPolicy[] policies = new CompletionPolicy[0];
038
039        /**
040         * Setter for the policies.
041         * 
042         * @param policies an array of completion policies to be used to determine
043         *  {@link #isComplete(RepeatContext)}  by consensus.
044         */
045        public void setPolicies(CompletionPolicy[] policies) {
046                this.policies = Arrays.asList(policies).toArray(new CompletionPolicy[policies.length]);
047        }
048
049        /**
050         * This policy is complete if any of the composed policies is complete.
051         * 
052         * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext,
053         * RepeatStatus)
054         */
055    @Override
056        public boolean isComplete(RepeatContext context, RepeatStatus result) {
057                RepeatContext[] contexts = ((CompositeBatchContext) context).contexts;
058                CompletionPolicy[] policies = ((CompositeBatchContext) context).policies;
059                for (int i = 0; i < policies.length; i++) {
060                        if (policies[i].isComplete(contexts[i], result)) {
061                                return true;
062                        }
063                }
064                return false;
065        }
066
067        /**
068         * This policy is complete if any of the composed policies is complete.
069         * 
070         * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext)
071         */
072    @Override
073        public boolean isComplete(RepeatContext context) {
074                RepeatContext[] contexts = ((CompositeBatchContext) context).contexts;
075                CompletionPolicy[] policies = ((CompositeBatchContext) context).policies;
076                for (int i = 0; i < policies.length; i++) {
077                        if (policies[i].isComplete(contexts[i])) {
078                                return true;
079                        }
080                }
081                return false;
082        }
083
084        /**
085         * Create a new composite context from all the available policies.
086         * 
087         * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext)
088         */
089    @Override
090        public RepeatContext start(RepeatContext context) {
091                List<RepeatContext> list = new ArrayList<RepeatContext>();
092                for (int i = 0; i < policies.length; i++) {
093                        list.add(policies[i].start(context));
094                }
095                return new CompositeBatchContext(context, list);
096
097        }
098
099        /**
100         * Update all the composed contexts, and also increment the parent context.
101         * 
102         * @see org.springframework.batch.repeat.CompletionPolicy#update(org.springframework.batch.repeat.RepeatContext)
103         */
104    @Override
105        public void update(RepeatContext context) {
106                RepeatContext[] contexts = ((CompositeBatchContext) context).contexts;
107                CompletionPolicy[] policies = ((CompositeBatchContext) context).policies;
108                for (int i = 0; i < policies.length; i++) {
109                        policies[i].update(contexts[i]);
110                }
111                ((RepeatContextSupport) context).increment();
112        }
113
114        /**
115         * Composite context that knows about the policies and contexts is was
116         * created with.
117         * 
118         * @author Dave Syer
119         * 
120         */
121        protected class CompositeBatchContext extends RepeatContextSupport {
122
123                private RepeatContext[] contexts;
124
125                // Save a reference to the policies when we were created - gives some
126                // protection against reference changes (e.g. if the number of policies
127                // change).
128                private CompletionPolicy[] policies;
129
130                public CompositeBatchContext(RepeatContext context, List<RepeatContext> contexts) {
131                        super(context);
132                        this.contexts = contexts.toArray(new RepeatContext[contexts.size()]);
133                        this.policies = CompositeCompletionPolicy.this.policies;
134                }
135
136        }
137
138}