1 /*
2 * Copyright 2006-2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.springframework.batch.repeat.policy;
18
19 import org.springframework.batch.repeat.RepeatContext;
20 import org.springframework.batch.repeat.context.RepeatContextCounter;
21 import org.springframework.batch.repeat.context.RepeatContextSupport;
22
23 /**
24 * Abstract base class for policies that need to count the number of occurrences
25 * of some event (e.g. an exception type in the context), and terminate based on
26 * a limit for the counter. The value of the counter can be stored between
27 * batches in a nested context, so that the termination decision is based on the
28 * aggregate of a number of sibling batches.
29 *
30 * @author Dave Syer
31 *
32 */
33 public abstract class CountingCompletionPolicy extends DefaultResultCompletionPolicy {
34
35 /**
36 * Session key for global counter.
37 */
38 public static final String COUNT = CountingCompletionPolicy.class.getName() + ".COUNT";
39
40 private boolean useParent = false;
41
42 private int maxCount = 0;
43
44 /**
45 * Flag to indicate whether the count is at the level of the parent context,
46 * or just local to the context. If true then the count is aggregated among
47 * siblings in a nested batch.
48 *
49 * @param useParent whether to use the parent context to cache the total
50 * count. Default value is false.
51 */
52 public void setUseParent(boolean useParent) {
53 this.useParent = useParent;
54 }
55
56 /**
57 * Setter for maximum value of count before termination.
58 *
59 * @param maxCount the maximum number of counts before termination. Default
60 * 0 so termination is immediate.
61 */
62 public void setMaxCount(int maxCount) {
63 this.maxCount = maxCount;
64 }
65
66 /**
67 * Extension point for subclasses. Obtain the value of the count in the
68 * current context. Subclasses can count the number of attempts or
69 * violations and store the result in their context. This policy base class
70 * will take care of the termination contract and aggregating at the level
71 * of the session if required.
72 *
73 * @param context the current context, specific to the subclass.
74 * @return the value of the counter in the context.
75 */
76 protected abstract int getCount(RepeatContext context);
77
78 /**
79 * Extension point for subclasses. Inspect the context and update the state
80 * of a counter in whatever way is appropriate. This will be added to the
81 * session-level counter if {@link #setUseParent(boolean)} is true.
82 *
83 * @param context the current context.
84 *
85 * @return the change in the value of the counter (default 0).
86 */
87 protected int doUpdate(RepeatContext context) {
88 return 0;
89 }
90
91 /*
92 * (non-Javadoc)
93 * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#isComplete(org.springframework.batch.repeat.BatchContext)
94 */
95 @Override
96 final public boolean isComplete(RepeatContext context) {
97 int count = ((CountingBatchContext) context).getCounter().getCount();
98 return count >= maxCount;
99 }
100
101 /*
102 * (non-Javadoc)
103 * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#start(org.springframework.batch.repeat.BatchContext)
104 */
105 @Override
106 public RepeatContext start(RepeatContext parent) {
107 return new CountingBatchContext(parent);
108 }
109
110 /*
111 * (non-Javadoc)
112 * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#update(org.springframework.batch.repeat.BatchContext)
113 */
114 @Override
115 final public void update(RepeatContext context) {
116 super.update(context);
117 int delta = doUpdate(context);
118 ((CountingBatchContext) context).getCounter().increment(delta);
119 }
120
121 protected class CountingBatchContext extends RepeatContextSupport {
122
123 RepeatContextCounter counter;
124
125 public CountingBatchContext(RepeatContext parent) {
126 super(parent);
127 counter = new RepeatContextCounter(this, COUNT, useParent);
128 }
129
130 public RepeatContextCounter getCounter() {
131 return counter;
132 }
133
134 }
135 }