001/* 002 * Copyright 2018 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.json.builder; 018 019import org.springframework.batch.item.file.FlatFileFooterCallback; 020import org.springframework.batch.item.file.FlatFileHeaderCallback; 021import org.springframework.batch.item.json.JsonFileItemWriter; 022import org.springframework.batch.item.json.JsonObjectMarshaller; 023import org.springframework.core.io.Resource; 024import org.springframework.util.Assert; 025 026/** 027 * Builder for {@link JsonFileItemWriter}. 028 * 029 * @param <T> type of objects to write as Json output. 030 * @author Mahmoud Ben Hassine 031 * @since 4.1 032 */ 033public class JsonFileItemWriterBuilder<T> { 034 035 private Resource resource; 036 private JsonObjectMarshaller<T> jsonObjectMarshaller; 037 private FlatFileHeaderCallback headerCallback; 038 private FlatFileFooterCallback footerCallback; 039 040 private String name; 041 private String encoding = JsonFileItemWriter.DEFAULT_CHARSET; 042 private String lineSeparator = JsonFileItemWriter.DEFAULT_LINE_SEPARATOR; 043 044 private boolean append = false; 045 private boolean forceSync = false; 046 private boolean saveState = true; 047 private boolean shouldDeleteIfExists = true; 048 private boolean shouldDeleteIfEmpty = false; 049 private boolean transactional = JsonFileItemWriter.DEFAULT_TRANSACTIONAL; 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 JsonFileItemWriterBuilder<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 JsonFileItemWriterBuilder<T> name(String name) { 075 this.name = name; 076 077 return this; 078 } 079 080 /** 081 * A flag indicating that changes should be force-synced to disk on flush. Defaults 082 * to false. 083 * 084 * @param forceSync value to set the flag to 085 * @return The current instance of the builder. 086 * @see JsonFileItemWriter#setForceSync(boolean) 087 */ 088 public JsonFileItemWriterBuilder<T> forceSync(boolean forceSync) { 089 this.forceSync = forceSync; 090 091 return this; 092 } 093 094 /** 095 * String used to separate lines in output. Defaults to the System property 096 * <code>line.separator</code>. 097 * 098 * @param lineSeparator value to use for a line separator 099 * @return The current instance of the builder. 100 * @see JsonFileItemWriter#setLineSeparator(String) 101 */ 102 public JsonFileItemWriterBuilder<T> lineSeparator(String lineSeparator) { 103 this.lineSeparator = lineSeparator; 104 105 return this; 106 } 107 108 /** 109 * Set the {@link JsonObjectMarshaller} to use to marshal objects to json. 110 * 111 * @param jsonObjectMarshaller to use 112 * @return The current instance of the builder. 113 * @see JsonFileItemWriter#setJsonObjectMarshaller(JsonObjectMarshaller) 114 */ 115 public JsonFileItemWriterBuilder<T> jsonObjectMarshaller(JsonObjectMarshaller<T> jsonObjectMarshaller) { 116 this.jsonObjectMarshaller = jsonObjectMarshaller; 117 118 return this; 119 } 120 121 /** 122 * The {@link Resource} to be used as output. 123 * 124 * @param resource the output of the writer. 125 * @return The current instance of the builder. 126 * @see JsonFileItemWriter#setResource(Resource) 127 */ 128 public JsonFileItemWriterBuilder<T> resource(Resource resource) { 129 this.resource = resource; 130 131 return this; 132 } 133 134 /** 135 * Encoding used for output. 136 * 137 * @param encoding encoding type. 138 * @return The current instance of the builder. 139 * @see JsonFileItemWriter#setEncoding(String) 140 */ 141 public JsonFileItemWriterBuilder<T> encoding(String encoding) { 142 this.encoding = encoding; 143 144 return this; 145 } 146 147 /** 148 * If set to true, once the step is complete, if the resource previously provided is 149 * empty, it will be deleted. 150 * 151 * @param shouldDelete defaults to false 152 * @return The current instance of the builder 153 * @see JsonFileItemWriter#setShouldDeleteIfEmpty(boolean) 154 */ 155 public JsonFileItemWriterBuilder<T> shouldDeleteIfEmpty(boolean shouldDelete) { 156 this.shouldDeleteIfEmpty = shouldDelete; 157 158 return this; 159 } 160 161 /** 162 * If set to true, upon the start of the step, if the resource already exists, it will 163 * be deleted and recreated. 164 * 165 * @param shouldDelete defaults to true 166 * @return The current instance of the builder 167 * @see JsonFileItemWriter#setShouldDeleteIfExists(boolean) 168 */ 169 public JsonFileItemWriterBuilder<T> shouldDeleteIfExists(boolean shouldDelete) { 170 this.shouldDeleteIfExists = shouldDelete; 171 172 return this; 173 } 174 175 /** 176 * If set to true and the file exists, the output will be appended to the existing 177 * file. 178 * 179 * @param append defaults to false 180 * @return The current instance of the builder 181 * @see JsonFileItemWriter#setAppendAllowed(boolean) 182 */ 183 public JsonFileItemWriterBuilder<T> append(boolean append) { 184 this.append = append; 185 186 return this; 187 } 188 189 /** 190 * A callback for header processing. 191 * 192 * @param callback {@link FlatFileHeaderCallback} implementation 193 * @return The current instance of the builder 194 * @see JsonFileItemWriter#setHeaderCallback(FlatFileHeaderCallback) 195 */ 196 public JsonFileItemWriterBuilder<T> headerCallback(FlatFileHeaderCallback callback) { 197 this.headerCallback = callback; 198 199 return this; 200 } 201 202 /** 203 * A callback for footer processing. 204 * 205 * @param callback {@link FlatFileFooterCallback} implementation 206 * @return The current instance of the builder 207 * @see JsonFileItemWriter#setFooterCallback(FlatFileFooterCallback) 208 */ 209 public JsonFileItemWriterBuilder<T> footerCallback(FlatFileFooterCallback callback) { 210 this.footerCallback = callback; 211 212 return this; 213 } 214 215 /** 216 * If set to true, the flushing of the buffer is delayed while a transaction is active. 217 * 218 * @param transactional defaults to true 219 * @return The current instance of the builder 220 * @see JsonFileItemWriter#setTransactional(boolean) 221 */ 222 public JsonFileItemWriterBuilder<T> transactional(boolean transactional) { 223 this.transactional = transactional; 224 225 return this; 226 } 227 228 /** 229 * Validate the configuration and build a new {@link JsonFileItemWriter}. 230 * 231 * @return a new instance of the {@link JsonFileItemWriter} 232 */ 233 public JsonFileItemWriter<T> build() { 234 Assert.notNull(this.resource, "A resource is required."); 235 Assert.notNull(this.jsonObjectMarshaller, "A json object marshaller is required."); 236 237 if (this.saveState) { 238 Assert.hasText(this.name, "A name is required when saveState is true"); 239 } 240 241 JsonFileItemWriter<T> jsonFileItemWriter = new JsonFileItemWriter<>(this.resource, this.jsonObjectMarshaller); 242 243 jsonFileItemWriter.setName(this.name); 244 jsonFileItemWriter.setAppendAllowed(this.append); 245 jsonFileItemWriter.setEncoding(this.encoding); 246 if (this.headerCallback != null) { 247 jsonFileItemWriter.setHeaderCallback(this.headerCallback); 248 } 249 if (this.footerCallback != null) { 250 jsonFileItemWriter.setFooterCallback(this.footerCallback); 251 } 252 jsonFileItemWriter.setForceSync(this.forceSync); 253 jsonFileItemWriter.setLineSeparator(this.lineSeparator); 254 jsonFileItemWriter.setSaveState(this.saveState); 255 jsonFileItemWriter.setShouldDeleteIfEmpty(this.shouldDeleteIfEmpty); 256 jsonFileItemWriter.setShouldDeleteIfExists(this.shouldDeleteIfExists); 257 jsonFileItemWriter.setTransactional(this.transactional); 258 259 return jsonFileItemWriter; 260 } 261}