1
2
3
4
5
6
7 package com.varmateo.yawg.core;
8
9 import java.io.IOException;
10 import java.nio.file.Files;
11 import java.nio.file.Path;
12 import java.util.function.Function;
13
14 import io.vavr.collection.Seq;
15
16 import com.varmateo.yawg.api.YawgException;
17 import com.varmateo.yawg.logging.Log;
18 import com.varmateo.yawg.logging.LogFactory;
19 import com.varmateo.yawg.spi.DirBakeListener;
20 import com.varmateo.yawg.spi.PageContext;
21 import com.varmateo.yawg.spi.TemplateService;
22
23
24
25
26
27
28 final class DirBaker {
29
30
31 private final Log _log;
32 private final FileBaker _fileBaker;
33 private final DirBakeOptionsDao _dirBakeOptionsDao;
34 private final DirBakeListener _listener;
35 private final TemplateService _templateService;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 DirBaker(
53 final FileBaker fileBaker,
54 final TemplateService templateService,
55 final DirBakeOptionsDao dirBakeOptionsDao,
56 final DirBakeListener dirBakeListener) {
57
58 _log = LogFactory.createFor(DirBaker.class);
59 _fileBaker = fileBaker;
60 _dirBakeOptionsDao = dirBakeOptionsDao;
61 _listener = dirBakeListener;
62 _templateService = templateService;
63 }
64
65
66
67
68
69 public void bakeDirectory(
70 final Path sourceDir,
71 final Path targetDir,
72 final DirBakeOptions parentDirBakeOptions) {
73
74 final DirBakerContext context = DirBakerContext.create(
75 sourceDir, targetDir, _templateService, parentDirBakeOptions);
76
77 doBakeDirectory(sourceDir, targetDir, context);
78 }
79
80
81
82
83
84 private void doBakeDirectory(
85 final Path sourceDir,
86 final Path targetDir,
87 final DirBakerContext parentContext) {
88
89 final Path relSourceDir = parentContext.sourceRootDir().relativize(sourceDir);
90 _log.debug("Baking directory {0}", relSourceDir);
91
92 createDirIfNeeded(targetDir);
93
94 final DirBakeOptions specificDirBakeOptions = _dirBakeOptionsDao.loadFromDir(sourceDir);
95 final DirBakerContext context = parentContext.buildForChildDir(
96 targetDir,
97 specificDirBakeOptions,
98 x -> _listener.onDirBake(x).pageVars());
99 final DirBakeOptions dirBakeOptions = context.dirBakeOptions();
100 final Seq<Path> dirEntries = getDirEntries(sourceDir, dirBakeOptions);
101
102 bakeChildFiles(dirEntries, targetDir, dirBakeOptions, context.pageContext());
103 bakeChildDirectories(dirEntries, targetDir, context);
104 bakeExtraDirectories(sourceDir, targetDir, context);
105 }
106
107
108
109
110
111 private void createDirIfNeeded(final Path targetDir) {
112
113 if ( !Files.exists(targetDir) ) {
114 doIoAction(
115 () -> Files.createDirectory(targetDir),
116 DirBakerException.directoryCreationFailure(targetDir));
117 }
118 }
119
120
121
122
123
124 private Seq<Path> getDirEntries(
125 final Path dir,
126 final DirBakeOptions dirBakeOptions) {
127
128 final DirEntryScanner.html#DirEntryScanner">DirEntryScanner scanner = new DirEntryScanner(dirBakeOptions);
129
130 return doIoAction(
131 () -> scanner.getDirEntries(dir),
132 DirBakerException.directoryListFailure(dir));
133 }
134
135
136
137
138
139 private void bakeChildFiles(
140 final Seq<Path> dirEntries,
141 final Path targetDir,
142 final DirBakeOptions dirBakeOptions,
143 final PageContext context) {
144
145 final Seq<Path> filePathList = dirEntries.filter(Files::isRegularFile);
146
147 for ( final Path path : filePathList ) {
148 _fileBaker.bakeFile(path, context, targetDir, dirBakeOptions);
149 }
150 }
151
152
153
154
155
156 private void bakeChildDirectories(
157 final Seq<Path> dirEntries,
158 final Path targetDir,
159 final DirBakerContext context) {
160
161 final Seq<Path> dirPathList = dirEntries.filter(Files::isDirectory);
162
163 for ( final Path childSourceDir : dirPathList ) {
164 final Path dirBasename = childSourceDir.getFileName();
165 final Path childTargetDir = targetDir.resolve(dirBasename);
166
167 doBakeDirectory(childSourceDir, childTargetDir, context);
168 }
169 }
170
171
172
173
174
175 private void bakeExtraDirectories(
176 final Path sourceDir,
177 final Path targetDir,
178 final DirBakerContext context) {
179
180 final Seq<Path> extraDirPathList = context.dirBakeOptions()
181 .extraDirsHere
182 .map(path -> sourceDir.resolve(path));
183
184 for ( final Path extraSourceDir : extraDirPathList ) {
185 doBakeDirectory(extraSourceDir, targetDir, context);
186 }
187 }
188
189
190
191
192
193
194 private <T> T doIoAction(
195 final IoSupplier<T> supplier,
196 final Function<IOException, DirBakerException> exceptionBuilder) {
197
198 final T result;
199
200 try {
201 result = supplier.get();
202 } catch ( IOException e ) {
203 throw exceptionBuilder.apply(e);
204 }
205
206 return result;
207 }
208
209
210
211
212
213
214
215
216 @FunctionalInterface
217 private interface IoSupplier<T> {
218
219
220
221
222
223 T get() throws IOException;
224 }
225
226
227 }