001/*
002 * Copyright 2017 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.item.file.builder;
018
019import java.util.Comparator;
020
021import org.springframework.batch.item.file.MultiResourceItemReader;
022import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
023import org.springframework.core.io.Resource;
024import org.springframework.util.Assert;
025import org.springframework.util.StringUtils;
026
027/**
028 * A builder implementation for the {@link MultiResourceItemReader}.
029 *
030 * @author Glenn Renfro
031 * @since 4.0
032 * @see MultiResourceItemReader
033 */
034public class MultiResourceItemReaderBuilder<T> {
035
036        private ResourceAwareItemReaderItemStream<? extends T> delegate;
037
038        private Resource[] resources;
039
040        private boolean strict = false;
041
042        private Comparator<Resource> comparator;
043
044        private boolean saveState = true;
045
046        private String name;
047
048        /**
049         * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
050         * should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
051         * for restart purposes.
052         *
053         * @param saveState defaults to true
054         * @return The current instance of the builder.
055         */
056        public MultiResourceItemReaderBuilder<T> saveState(boolean saveState) {
057                this.saveState = saveState;
058
059                return this;
060        }
061
062        /**
063         * The name used to calculate the key within the
064         * {@link org.springframework.batch.item.ExecutionContext}. Required if
065         * {@link #saveState(boolean)} is set to true.
066         *
067         * @param name name of the reader instance
068         * @return The current instance of the builder.
069         * @see org.springframework.batch.item.ItemStreamSupport#setName(String)
070         */
071        public MultiResourceItemReaderBuilder<T> name(String name) {
072                this.name = name;
073
074                return this;
075        }
076
077        /**
078         * The array of resources that the {@link MultiResourceItemReader} will use to
079         * retrieve items.
080         *
081         * @param resources the array of resources to use.
082         * @return this instance for method chaining.
083         *
084         * @see MultiResourceItemReader#setResources(Resource[])
085         */
086        public MultiResourceItemReaderBuilder<T> resources(Resource[] resources) {
087                this.resources = resources;
088
089                return this;
090        }
091
092        /**
093         * Establishes the delegate to use for reading the resources provided.
094         *
095         * @param delegate reads items from single {@link Resource}.
096         * @return this instance for method chaining.
097         *
098         * @see MultiResourceItemReader#setDelegate(ResourceAwareItemReaderItemStream)
099         */
100        public MultiResourceItemReaderBuilder<T> delegate(ResourceAwareItemReaderItemStream<? extends T> delegate) {
101                this.delegate = delegate;
102
103                return this;
104        }
105
106        /**
107         * In strict mode the reader will throw an exception on
108         * {@link MultiResourceItemReader#open(org.springframework.batch.item.ExecutionContext)}
109         * if there are no resources to read.
110         *
111         * @param strict false by default.
112         * @return this instance for method chaining.
113         * @see MultiResourceItemReader#setStrict(boolean)
114         */
115        public MultiResourceItemReaderBuilder<T> setStrict(boolean strict) {
116                this.strict = strict;
117
118                return this;
119        }
120
121        /**
122         * Used to order the injected resources, by default compares
123         * {@link Resource#getFilename()} values.
124         *
125         * @param comparator the comparator to use for ordering resources.
126         * @return this instance for method chaining.
127         * @see MultiResourceItemReader#setComparator(Comparator)
128         */
129        public MultiResourceItemReaderBuilder<T> comparator(Comparator<Resource> comparator) {
130                this.comparator = comparator;
131
132                return this;
133        }
134
135        /**
136         * Builds the {@link MultiResourceItemReader}.
137         *
138         * @return a {@link MultiResourceItemReader}
139         */
140        public MultiResourceItemReader<T> build() {
141                Assert.notNull(this.resources, "resources array is required.");
142                Assert.notNull(this.delegate, "delegate is required.");
143                if (this.saveState) {
144                        Assert.state(StringUtils.hasText(this.name), "A name is required when saveState is set to true.");
145                }
146
147                MultiResourceItemReader<T> reader = new MultiResourceItemReader<>();
148                reader.setResources(this.resources);
149                reader.setDelegate(this.delegate);
150                reader.setSaveState(this.saveState);
151                reader.setStrict(this.strict);
152
153                if (comparator != null) {
154                        reader.setComparator(this.comparator);
155                }
156                if (StringUtils.hasText(this.name)) {
157                        reader.setName(this.name);
158                }
159
160                return reader;
161        }
162
163}