View Javadoc
1   /**************************************************************************
2    *
3    * Copyright (c) 2015-2020 Yawg project contributors.
4    *
5    **************************************************************************/
6   
7   package com.varmateo.yawg.cli;
8   
9   import java.io.OutputStream;
10  import java.io.OutputStreamWriter;
11  import java.io.PrintWriter;
12  import java.io.Writer;
13  import java.nio.charset.StandardCharsets;
14  import java.nio.file.Path;
15  
16  import io.vavr.control.Try;
17  
18  import com.varmateo.yawg.api.BakeOptions;
19  import com.varmateo.yawg.api.Result;
20  import com.varmateo.yawg.api.SiteBaker;
21  import com.varmateo.yawg.api.YawgInfo;
22  import com.varmateo.yawg.core.DefaultSiteBaker;
23  import com.varmateo.yawg.logging.Log;
24  import com.varmateo.yawg.logging.LogFactory;
25  import com.varmateo.yawg.util.Results;
26  
27  
28  /**
29   * Command line interface for the baker utility.
30   */
31  public final class BakerCli {
32  
33  
34      private static final int EXIT_STATUS_OK = 0;
35      private static final int EXIT_STATUS_FAILURE = 1;
36  
37  
38      private final Log _log = LogFactory.createFor(BakerCli.class);
39  
40  
41      private BakerCli() {
42          // Nothing to do.
43      }
44  
45  
46      /**
47       *
48       */
49      public static BakerCli create() {
50  
51          return new BakerCli();
52      }
53  
54  
55      /**
56       * The utility entry point.
57       *
58       * @return The utility exit status. Zero means all went
59       * well. Non-zero means something failed.
60       */
61      public int run(final BakerCliRunOptions options) {
62  
63          final InfoPrinter infoPrinter = buildInfoPrinter(options.argv0, options.output);
64          final Try<Void> bakeResult = tryRun(infoPrinter, options.args)
65                  .onFailure(cause -> infoPrinter.printError(cause));
66  
67          final int exitStatus = bakeResult
68                  .map(x -> EXIT_STATUS_OK)
69                  .recover(x -> EXIT_STATUS_FAILURE)
70                  .get();
71  
72          return exitStatus;
73      }
74  
75  
76      /**
77       *
78       */
79      private static InfoPrinter buildInfoPrinter(
80              final String argv0,
81              final OutputStream output) {
82  
83          final boolean autoFlush = true;
84          final Writer stdoutWriter = new OutputStreamWriter(output, StandardCharsets.UTF_8);
85          final PrintWriter stdout = new PrintWriter(stdoutWriter, autoFlush);
86  
87          return InfoPrinter.builder()
88                  .argv0(argv0)
89                  .output(stdout)
90                  .build();
91      }
92  
93  
94      /**
95       *
96       */
97      private Try<Void> tryRun(
98              final InfoPrinter infoPrinter,
99              final String[] args) {
100 
101         return BakerCliAction.parse(args)
102                 .flatMap(action -> performAction(infoPrinter, action));
103     }
104 
105 
106     private Try<Void> performAction(
107             final InfoPrinter infoPrinter,
108             final BakerCliAction action) {
109 
110         return action.match(
111                 () -> Try.run(infoPrinter::printHelp),
112                 () -> Try.run(infoPrinter::printVersion),
113                 bake -> doBake(bake.options()));
114     }
115 
116 
117     private Try<Void> doBake(final BakerCliBakeOptions options) {
118 
119         logOptions(options);
120 
121         final SiteBaker siteBaker = options.templatesDir()
122                 .map(path -> DefaultSiteBaker.create(path))
123                 .getOrElse(() -> DefaultSiteBaker.create());
124 
125         final BakeOptions bakeOptions = BakeOptions.builder()
126                 .sourceDir(options.sourceDir())
127                 .targetDir(options.targetDir())
128                 .putAllExternalPageVars(options.externalPageVars().toJavaMap())
129                 .build();
130 
131         final Result<Void> result = siteBaker.bake(bakeOptions);
132 
133         return Results.toTry(result)
134                 .recoverWith(cause -> Try.failure(CliException.bakeFailure(cause)));
135     }
136 
137 
138     private void logOptions(final BakerCliBakeOptions options) {
139 
140         final Path sourceDir = options.sourceDir();
141         final Path targetDir = options.targetDir();
142         final String templatesDir = options.templatesDir().map(Path::toString).getOrElse("NONE");
143 
144         _log.info("{0} {1}", YawgInfo.PRODUCT_NAME, YawgInfo.VERSION);
145         _log.info("    Source    : {0}", sourceDir);
146         _log.info("    Target    : {0}", targetDir);
147         _log.info("    Templates : {0}", templatesDir);
148     }
149 
150 }