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 */
016package org.springframework.batch.item.xml.builder;
017
018import java.util.Map;
019
020import org.springframework.batch.item.xml.StaxEventItemWriter;
021import org.springframework.batch.item.xml.StaxWriterCallback;
022import org.springframework.core.io.Resource;
023import org.springframework.oxm.Marshaller;
024import org.springframework.util.Assert;
025
026/**
027 * A builder for the {@link StaxEventItemWriter}.
028 *
029 * @author Michael Minella
030 * @since 4.0
031 * @see StaxEventItemWriter
032 */
033public class StaxEventItemWriterBuilder<T> {
034
035        private Resource resource;
036
037        private Marshaller marshaller;
038
039        private StaxWriterCallback headerCallback;
040
041        private StaxWriterCallback footerCallback;
042
043        private boolean transactional = true;
044
045        private boolean forceSync = false;
046
047        private boolean shouldDeleteIfEmpty = false;
048
049        private String encoding = StaxEventItemWriter.DEFAULT_ENCODING;
050
051        private String version = StaxEventItemWriter.DEFAULT_XML_VERSION;
052
053        private String rootTagName = StaxEventItemWriter.DEFAULT_ROOT_TAG_NAME;
054
055        private Map<String, String> rootElementAttributes;
056
057        private boolean overwriteOutput = true;
058
059        private boolean saveState = true;
060
061        private String name;
062
063        /**
064         * The name used to calculate the key within the
065         * {@link org.springframework.batch.item.ExecutionContext}.  Required if
066         * {@link StaxEventItemWriterBuilder#saveState(boolean)} is set to true.
067         *
068         * @param name name of the reader instance
069         * @return The current instance of the builder.
070         * @see StaxEventItemWriter#setName(String)
071         */
072        public StaxEventItemWriterBuilder<T> name(String name) {
073                this.name = name;
074
075                return this;
076        }
077
078        /**
079         * The {@link Resource} to be used as output.
080         *
081         * @param resource the output from the writer
082         * @return the current instance of the builder.
083         * @see StaxEventItemWriter#setResource(Resource)
084         */
085        public StaxEventItemWriterBuilder<T> resource(Resource resource) {
086                this.resource = resource;
087
088                return this;
089        }
090
091        /**
092         * The {@link Marshaller} implementation responsible for the serialization of the
093         * items to XML.  This field is required.
094         *
095         * @param marshaller the component used to generate XML
096         * @return the current instance of the builder.
097         * @see StaxEventItemWriter#setMarshaller(Marshaller)
098         */
099        public StaxEventItemWriterBuilder<T> marshaller(Marshaller marshaller) {
100                this.marshaller = marshaller;
101
102                return this;
103        }
104
105        /**
106         * A {@link StaxWriterCallback} to provide any header elements
107         *
108         * @param headerCallback a {@link StaxWriterCallback}
109         * @return the current instance of the builder.
110         * @see StaxEventItemWriter#setHeaderCallback(StaxWriterCallback)
111         */
112        public StaxEventItemWriterBuilder<T> headerCallback(StaxWriterCallback headerCallback) {
113                this.headerCallback = headerCallback;
114
115                return this;
116        }
117
118        /**
119         * A {@link StaxWriterCallback} to provide any footer elements
120         *
121         * @param footerCallback a {@link StaxWriterCallback}
122         * @return the current instance of the builder.
123         * @see StaxEventItemWriter#setFooterCallback(StaxWriterCallback)
124         */
125        public StaxEventItemWriterBuilder<T> footerCallback(StaxWriterCallback footerCallback) {
126                this.footerCallback = footerCallback;
127
128                return this;
129        }
130
131        /**
132         * The resulting writer is participating in a transaction and writes should be delayed
133         * as late as possible.
134         *
135         * @param transactional indicates that the writer is transactional.  Defaults to false.
136         * @return the current instance of the builder
137         * @see StaxEventItemWriter#setTransactional(boolean)
138         */
139        public StaxEventItemWriterBuilder<T> transactional(boolean transactional) {
140                this.transactional = transactional;
141
142                return this;
143        }
144
145        /**
146         * Flag to indicate that changes should be force-synced to disk on flush.
147         *
148         * @param forceSync indicates if force sync should occur.  Defaults to false.
149         * @return the current instance of the builder
150         * @see StaxEventItemWriter#setForceSync(boolean)
151         */
152        public StaxEventItemWriterBuilder<T> forceSync(boolean forceSync) {
153                this.forceSync = forceSync;
154
155                return this;
156        }
157
158        /**
159         * Flag to indicate that the output file should be deleted if no results were written
160         * to it.  Defaults to false.
161         *
162         * @param shouldDelete indicator
163         * @return the current instance of the builder
164         * @see StaxEventItemWriter#setShouldDeleteIfEmpty(boolean)
165         */
166        public StaxEventItemWriterBuilder<T> shouldDeleteIfEmpty(boolean shouldDelete) {
167                this.shouldDeleteIfEmpty = shouldDelete;
168
169                return this;
170        }
171
172        /**
173         * Encoding for the file.  Defaults to UTF-8.
174         *
175         * @param encoding String encoding algorithm
176         * @return the current instance of the builder
177         * @see StaxEventItemWriter#setEncoding(String)
178         */
179        public StaxEventItemWriterBuilder<T> encoding(String encoding) {
180                this.encoding = encoding;
181
182                return this;
183        }
184
185        /**
186         * Version of XML to be generated.  Must be supported by the {@link Marshaller}
187         * provided.
188         *
189         * @param version XML version
190         * @return the current instance of the builder
191         * @see StaxEventItemWriter#version
192         */
193        public StaxEventItemWriterBuilder<T> version(String version) {
194                this.version = version;
195
196                return this;
197        }
198
199        /**
200         * The name of the root tag for the output document.
201         *
202         * @param rootTagName tag name
203         * @return the current instance of the builder
204         * @see StaxEventItemWriter#setRootTagName(String)
205         */
206        public StaxEventItemWriterBuilder<T> rootTagName(String rootTagName) {
207                this.rootTagName = rootTagName;
208
209                return this;
210        }
211
212        /**
213         * A Map of attributes to be included in the document's root element.
214         *
215         * @param rootElementAttributes map fo attributes
216         * @return the current instance of the builder.
217         * @see StaxEventItemWriter#setRootElementAttributes(Map)
218         */
219        public StaxEventItemWriterBuilder<T> rootElementAttributes(Map<String, String> rootElementAttributes) {
220                this.rootElementAttributes = rootElementAttributes;
221
222                return this;
223        }
224
225        /**
226         * Indicates if an existing file should be overwritten if found. Defaults to true.
227         *
228         * @param overwriteOutput indicator
229         * @return the current instance of the builder.
230         * @see StaxEventItemWriter#setOverwriteOutput(boolean)
231         */
232        public StaxEventItemWriterBuilder<T> overwriteOutput(boolean overwriteOutput) {
233                this.overwriteOutput = overwriteOutput;
234
235                return this;
236        }
237
238        /**
239         * Indicates if the state of the writer should be saved in the
240         * {@link org.springframework.batch.item.ExecutionContext}.  Setting this to false
241         * will impact restartability.  Defaults to true.
242         *
243         * @param saveState indicator
244         * @return the current instance of the builder
245         * @see StaxEventItemWriter#setSaveState(boolean)
246         */
247        public StaxEventItemWriterBuilder<T> saveState(boolean saveState) {
248                this.saveState = saveState;
249
250                return this;
251        }
252
253        /**
254         * Returns a configured {@link StaxEventItemWriter}
255         *
256         * @return a StaxEventItemWriter
257         */
258        public StaxEventItemWriter<T> build() {
259                Assert.notNull(this.marshaller, "A marshaller is required");
260
261                if(this.saveState) {
262                        Assert.notNull(this.name, "A name is required");
263                }
264
265                StaxEventItemWriter<T> writer = new StaxEventItemWriter<>();
266
267                writer.setEncoding(this.encoding);
268                writer.setFooterCallback(this.footerCallback);
269                writer.setForceSync(this.forceSync);
270                writer.setHeaderCallback(this.headerCallback);
271                writer.setMarshaller(this.marshaller);
272                writer.setOverwriteOutput(this.overwriteOutput);
273                writer.setResource(this.resource);
274                writer.setRootElementAttributes(this.rootElementAttributes);
275                writer.setRootTagName(this.rootTagName);
276                writer.setSaveState(this.saveState);
277                writer.setShouldDeleteIfEmpty(this.shouldDeleteIfEmpty);
278                writer.setTransactional(this.transactional);
279                writer.setVersion(this.version);
280                writer.setName(this.name);
281
282                return writer;
283        }
284
285 }