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 org.springframework.batch.repeat.RepeatContext; 020import org.springframework.batch.repeat.context.RepeatContextCounter; 021import org.springframework.batch.repeat.context.RepeatContextSupport; 022 023/** 024 * Abstract base class for policies that need to count the number of occurrences 025 * of some event (e.g. an exception type in the context), and terminate based on 026 * a limit for the counter. The value of the counter can be stored between 027 * batches in a nested context, so that the termination decision is based on the 028 * aggregate of a number of sibling batches. 029 * 030 * @author Dave Syer 031 * 032 */ 033public abstract class CountingCompletionPolicy extends DefaultResultCompletionPolicy { 034 035 /** 036 * Session key for global counter. 037 */ 038 public static final String COUNT = CountingCompletionPolicy.class.getName() + ".COUNT"; 039 040 private boolean useParent = false; 041 042 private int maxCount = 0; 043 044 /** 045 * Flag to indicate whether the count is at the level of the parent context, 046 * or just local to the context. If true then the count is aggregated among 047 * siblings in a nested batch. 048 * 049 * @param useParent whether to use the parent context to cache the total 050 * count. Default value is false. 051 */ 052 public void setUseParent(boolean useParent) { 053 this.useParent = useParent; 054 } 055 056 /** 057 * Setter for maximum value of count before termination. 058 * 059 * @param maxCount the maximum number of counts before termination. Default 060 * 0 so termination is immediate. 061 */ 062 public void setMaxCount(int maxCount) { 063 this.maxCount = maxCount; 064 } 065 066 /** 067 * Extension point for subclasses. Obtain the value of the count in the 068 * current context. Subclasses can count the number of attempts or 069 * violations and store the result in their context. This policy base class 070 * will take care of the termination contract and aggregating at the level 071 * of the session if required. 072 * 073 * @param context the current context, specific to the subclass. 074 * @return the value of the counter in the context. 075 */ 076 protected abstract int getCount(RepeatContext context); 077 078 /** 079 * Extension point for subclasses. Inspect the context and update the state 080 * of a counter in whatever way is appropriate. This will be added to the 081 * session-level counter if {@link #setUseParent(boolean)} is true. 082 * 083 * @param context the current context. 084 * 085 * @return the change in the value of the counter (default 0). 086 */ 087 protected int doUpdate(RepeatContext context) { 088 return 0; 089 } 090 091 /* 092 * (non-Javadoc) 093 * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#isComplete(org.springframework.batch.repeat.BatchContext) 094 */ 095 @Override 096 final public boolean isComplete(RepeatContext context) { 097 int count = ((CountingBatchContext) context).getCounter().getCount(); 098 return count >= maxCount; 099 } 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}