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.ldif.builder;
018
019import org.springframework.batch.item.ldif.MappingLdifReader;
020import org.springframework.batch.item.ldif.RecordCallbackHandler;
021import org.springframework.batch.item.ldif.RecordMapper;
022import org.springframework.core.io.Resource;
023import org.springframework.util.Assert;
024
025/**
026 * Creates a fully qualified MappingLdifReader.
027 *
028 * @author Glenn Renfro
029 *
030 * @since 4.0
031 */
032public class MappingLdifReaderBuilder<T>  {
033        private Resource resource;
034
035        private int recordsToSkip = 0;
036
037        private boolean strict = true;
038
039        private RecordCallbackHandler skippedRecordsCallback;
040
041        private RecordMapper<T> recordMapper;
042
043        private boolean saveState = true;
044
045        private String name;
046
047        private int maxItemCount = Integer.MAX_VALUE;
048
049        private int currentItemCount;
050
051        /**
052         * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport}
053         * should be persisted within the {@link org.springframework.batch.item.ExecutionContext}
054         * for restart purposes.
055         *
056         * @param saveState defaults to true
057         * @return The current instance of the builder.
058         */
059        public MappingLdifReaderBuilder<T> saveState(boolean saveState) {
060                this.saveState = saveState;
061
062                return this;
063        }
064
065        /**
066         * The name used to calculate the key within the
067         * {@link org.springframework.batch.item.ExecutionContext}. Required if
068         * {@link #saveState(boolean)} is set to true.
069         *
070         * @param name name of the reader instance
071         * @return The current instance of the builder.
072         * @see org.springframework.batch.item.ItemStreamSupport#setName(String)
073         */
074        public MappingLdifReaderBuilder<T> name(String name) {
075                this.name = name;
076
077                return this;
078        }
079
080        /**
081         * Configure the max number of items to be read.
082         *
083         * @param maxItemCount the max items to be read
084         * @return The current instance of the builder.
085         * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int)
086         */
087        public MappingLdifReaderBuilder<T> maxItemCount(int maxItemCount) {
088                this.maxItemCount = maxItemCount;
089
090                return this;
091        }
092
093        /**
094         * Index for the current item. Used on restarts to indicate where to start from.
095         *
096         * @param currentItemCount current index
097         * @return this instance for method chaining
098         * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int)
099         */
100        public MappingLdifReaderBuilder<T> currentItemCount(int currentItemCount) {
101                this.currentItemCount = currentItemCount;
102
103                return this;
104        }
105
106        /**
107         * In strict mode the reader will throw an exception on
108         * {@link MappingLdifReader#open(org.springframework.batch.item.ExecutionContext)} if
109         * the input resource does not exist.
110         *
111         * @param strict true by default
112         * @return this instance for method chaining.
113         * @see MappingLdifReader#setStrict(boolean)
114         */
115        public MappingLdifReaderBuilder<T> strict(boolean strict) {
116                this.strict = strict;
117
118                return this;
119        }
120
121        /**
122         * {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to
123         * take action on skipped records.
124         *
125         * @param skippedRecordsCallback will be called for each one of the initial skipped
126         * lines before any items are read.
127         * @return this instance for method chaining.
128         * @see MappingLdifReader#setSkippedRecordsCallback(RecordCallbackHandler)
129         */
130        public MappingLdifReaderBuilder<T> skippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) {
131                this.skippedRecordsCallback = skippedRecordsCallback;
132
133                return this;
134        }
135
136        /**
137         * Public setter for the number of lines to skip at the start of a file. Can be used
138         * if the file contains a header without useful (column name) information, and without
139         * a comment delimiter at the beginning of the lines.
140         *
141         * @param recordsToSkip the number of lines to skip
142         * @return this instance for method chaining.
143         * @see MappingLdifReader#setRecordsToSkip(int)
144         */
145        public MappingLdifReaderBuilder<T> recordsToSkip(int recordsToSkip) {
146                this.recordsToSkip = recordsToSkip;
147
148                return this;
149        }
150
151        /**
152         * Establishes the resource that will be used as the input for the MappingLdifReader.
153         *
154         * @param resource the resource that will be read.
155         * @return this instance for method chaining.
156         * @see MappingLdifReader#setResource(Resource)
157         */
158        public MappingLdifReaderBuilder<T> resource(Resource resource) {
159                this.resource = resource;
160
161                return this;
162        }
163
164        /**
165         * Setter for object mapper. This property is required to be set.
166         *
167         * @param recordMapper maps record to an object
168         * @return this instance for method chaining.
169         */
170        public MappingLdifReaderBuilder<T> recordMapper(RecordMapper<T> recordMapper) {
171                this.recordMapper = recordMapper;
172
173                return this;
174        }
175
176        /**
177         * Returns a fully constructed {@link MappingLdifReader}.
178         *
179         * @return a new {@link org.springframework.batch.item.ldif.MappingLdifReader}
180         */
181        public MappingLdifReader<T> build() {
182                Assert.notNull(this.resource, "Resource is required.");
183                Assert.notNull(this.recordMapper, "RecordMapper is required.");
184                if (this.saveState) {
185                        Assert.hasText(this.name, "A name is required when saveState is set to true");
186                }
187                MappingLdifReader<T> reader = new MappingLdifReader<>();
188                reader.setResource(this.resource);
189                reader.setRecordsToSkip(this.recordsToSkip);
190                reader.setSaveState(saveState);
191                reader.setCurrentItemCount(this.currentItemCount);
192                reader.setMaxItemCount(this.maxItemCount);
193                reader.setRecordMapper(this.recordMapper);
194                reader.setName(this.name);
195                if (this.skippedRecordsCallback != null) {
196                        reader.setSkippedRecordsCallback(this.skippedRecordsCallback);
197                }
198                reader.setStrict(this.strict);
199
200                return reader;
201        }
202}