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.support;
018
019import org.springframework.batch.repeat.RepeatCallback;
020import org.springframework.batch.repeat.RepeatContext;
021import org.springframework.batch.repeat.RepeatOperations;
022
023/**
024 * Global variable support for repeat clients. Normally it is not necessary for
025 * clients to be aware of the surrounding environment because a
026 * {@link RepeatCallback} can always use the context it is passed by the
027 * enclosing {@link RepeatOperations}. But occasionally it might be helpful to
028 * have lower level access to the ongoing {@link RepeatContext} so we provide a
029 * global accessor here. The mutator methods ({@link #clear()} and
030 * {@link #register(RepeatContext)} should not be used except internally by
031 * {@link RepeatOperations} implementations.
032 * 
033 * @author Dave Syer
034 * 
035 */
036public final class RepeatSynchronizationManager {
037
038        private static final ThreadLocal<RepeatContext> contextHolder = new ThreadLocal<RepeatContext>();
039
040        private RepeatSynchronizationManager() {
041        }
042
043        /**
044         * Getter for the current context. A context is shared by all items in the
045         * batch, so this method is intended to return the same context object
046         * independent of whether the callback is running synchronously or
047         * asynchronously with the surrounding {@link RepeatOperations}.
048         * 
049         * @return the current {@link RepeatContext} or null if there is none (if we
050         * are not in a batch).
051         */
052        public static RepeatContext getContext() {
053                return contextHolder.get();
054        }
055
056        /**
057         * Convenience method to set the current repeat operation to complete if it
058         * exists.
059         */
060        public static void setCompleteOnly() {
061                RepeatContext context = getContext();
062                if (context != null) {
063                        context.setCompleteOnly();
064                }
065        }
066
067        /**
068         * Method for registering a context - should only be used by
069         * {@link RepeatOperations} implementations to ensure that
070         * {@link #getContext()} always returns the correct value.
071         * 
072         * @param context a new context at the start of a batch.
073         * @return the old value if there was one.
074         */
075        public static RepeatContext register(RepeatContext context) {
076                RepeatContext oldSession = getContext();
077                RepeatSynchronizationManager.contextHolder.set(context);
078                return oldSession;
079        }
080
081        /**
082         * Clear the current context at the end of a batch - should only be used by
083         * {@link RepeatOperations} implementations.
084         * 
085         * @return the old value if there was one.
086         */
087        public static RepeatContext clear() {
088                RepeatContext context = getContext();
089                RepeatSynchronizationManager.contextHolder.set(null);
090                return context;
091        }
092
093        /**
094         * Set current session and all ancestors (via parent) to complete.,
095         */
096        public static void setAncestorsCompleteOnly() {
097                RepeatContext context = getContext();
098                while (context != null) {
099                        context.setCompleteOnly();
100                        context = context.getParent();
101                }
102        }
103
104}