1616
1717package org .springframework .batch .infrastructure .item .file .builder ;
1818
19+ import java .io .IOException ;
1920import java .util .Comparator ;
2021
2122import org .jspecify .annotations .Nullable ;
2526import org .springframework .batch .infrastructure .item .file .MultiResourceItemReader ;
2627import org .springframework .batch .infrastructure .item .file .ResourceAwareItemReaderItemStream ;
2728import org .springframework .core .io .Resource ;
29+ import org .springframework .core .io .support .PathMatchingResourcePatternResolver ;
30+ import org .springframework .core .io .support .ResourcePatternResolver ;
2831import org .springframework .util .Assert ;
2932import org .springframework .util .StringUtils ;
3033
3437 * @author Glenn Renfro
3538 * @author Drummond Dawson
3639 * @author Stefano Cordio
40+ * @author Sanghyuk Jung
3741 * @since 4.0
3842 * @see MultiResourceItemReader
3943 */
@@ -43,6 +47,8 @@ public class MultiResourceItemReaderBuilder<T> {
4347
4448 private Resource @ Nullable [] resources ;
4549
50+ private @ Nullable String filesPattern ;
51+
4652 private boolean strict = false ;
4753
4854 private @ Nullable Comparator <Resource > comparator ;
@@ -90,6 +96,19 @@ public MultiResourceItemReaderBuilder<T> resources(Resource... resources) {
9096 return this ;
9197 }
9298
99+ /**
100+ * The location pattern of files that the {@link MultiResourceItemReader} will use to
101+ * retrieve items. This is an Ant-style pattern that supports wildcards like `*`, `**`
102+ * and `?`(for example `/data/*.csv`or `data/**\/user?.txt`).
103+ * @param filesPattern the location pattern of files to use.
104+ * @return this instance for method chaining.
105+ */
106+ public MultiResourceItemReaderBuilder <T > filesPattern (String filesPattern ) {
107+ this .filesPattern = filesPattern ;
108+
109+ return this ;
110+ }
111+
93112 /**
94113 * Establishes the delegate to use for reading the resources provided.
95114 * @param delegate reads items from single {@link Resource}.
@@ -135,14 +154,31 @@ public MultiResourceItemReaderBuilder<T> comparator(Comparator<Resource> compara
135154 * @return a {@link MultiResourceItemReader}
136155 */
137156 public MultiResourceItemReader <T > build () {
138- Assert .notNull (this .resources , "resources array is required." );
157+ Assert .isTrue (this .resources != null || this .filesPattern != null ,
158+ "resources array or filesPattern is required." );
159+
139160 Assert .notNull (this .delegate , "delegate is required." );
140161 if (this .saveState ) {
141162 Assert .state (StringUtils .hasText (this .name ), "A name is required when saveState is set to true." );
142163 }
143164
144165 MultiResourceItemReader <T > reader = new MultiResourceItemReader <>(this .delegate );
145- reader .setResources (this .resources );
166+
167+ if (this .resources != null ) {
168+ reader .setResources (this .resources );
169+ }
170+ else if (this .filesPattern != null ) {
171+ ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver ();
172+ try {
173+ Resource [] resources = patternResolver .getResources ("file:" + this .filesPattern );
174+ reader .setResources (resources );
175+ }
176+ catch (IOException e ) {
177+ throw new IllegalArgumentException ("Unable to initialize resources by the pattern " + this .filesPattern ,
178+ e );
179+ }
180+ }
181+
146182 reader .setSaveState (this .saveState );
147183 reader .setStrict (this .strict );
148184
0 commit comments