View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.cling.invoker;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Optional;
26  import java.util.function.Consumer;
27  import java.util.function.Function;
28  
29  import org.apache.maven.api.cli.Options;
30  import org.apache.maven.api.cli.ParserRequest;
31  
32  /**
33   * Options that are "layered" by precedence order.
34   *
35   * @param <O> The type of options.
36   */
37  public abstract class LayeredOptions<O extends Options> implements Options {
38      protected final List<O> options;
39  
40      protected LayeredOptions(List<O> options) {
41          this.options = new ArrayList<>(options);
42      }
43  
44      @Override
45      public Optional<Map<String, String>> userProperties() {
46          return collectMapIfPresentOrEmpty(Options::userProperties);
47      }
48  
49      @Override
50      public String source() {
51          return String.format(
52                  "layered(%s)", options.stream().map(Options::source).toList());
53      }
54  
55      @Override
56      public Optional<Boolean> showVersionAndExit() {
57          return returnFirstPresentOrEmpty(Options::showVersionAndExit);
58      }
59  
60      @Override
61      public Optional<Boolean> showVersion() {
62          return returnFirstPresentOrEmpty(Options::showVersion);
63      }
64  
65      @Override
66      public Optional<Boolean> quiet() {
67          return returnFirstPresentOrEmpty(Options::quiet);
68      }
69  
70      @Override
71      public Optional<Boolean> verbose() {
72          return returnFirstPresentOrEmpty(Options::verbose);
73      }
74  
75      @Override
76      public Optional<Boolean> showErrors() {
77          return returnFirstPresentOrEmpty(Options::showErrors);
78      }
79  
80      @Override
81      public Optional<String> failOnSeverity() {
82          return returnFirstPresentOrEmpty(Options::failOnSeverity);
83      }
84  
85      @Override
86      public Optional<Boolean> nonInteractive() {
87          return returnFirstPresentOrEmpty(Options::nonInteractive);
88      }
89  
90      @Override
91      public Optional<Boolean> forceInteractive() {
92          return returnFirstPresentOrEmpty(Options::forceInteractive);
93      }
94  
95      @Override
96      public Optional<String> altUserSettings() {
97          return returnFirstPresentOrEmpty(Options::altUserSettings);
98      }
99  
100     @Override
101     public Optional<String> altProjectSettings() {
102         return returnFirstPresentOrEmpty(Options::altProjectSettings);
103     }
104 
105     @Override
106     public Optional<String> altInstallationSettings() {
107         return returnFirstPresentOrEmpty(Options::altInstallationSettings);
108     }
109 
110     @Override
111     public Optional<String> altUserToolchains() {
112         return returnFirstPresentOrEmpty(Options::altUserToolchains);
113     }
114 
115     @Override
116     public Optional<String> altInstallationToolchains() {
117         return returnFirstPresentOrEmpty(Options::altInstallationToolchains);
118     }
119 
120     @Override
121     public Optional<String> logFile() {
122         return returnFirstPresentOrEmpty(Options::logFile);
123     }
124 
125     @Override
126     public Optional<Boolean> rawStreams() {
127         return returnFirstPresentOrEmpty(Options::rawStreams);
128     }
129 
130     @Override
131     public Optional<String> color() {
132         return returnFirstPresentOrEmpty(Options::color);
133     }
134 
135     @Override
136     public Optional<Boolean> help() {
137         return returnFirstPresentOrEmpty(Options::help);
138     }
139 
140     @Override
141     public void warnAboutDeprecatedOptions(ParserRequest request, Consumer<String> printWriter) {}
142 
143     @Override
144     public void displayHelp(ParserRequest request, Consumer<String> printWriter) {
145         options.get(0).displayHelp(request, printWriter);
146     }
147 
148     protected <T> Optional<T> returnFirstPresentOrEmpty(Function<O, Optional<T>> getter) {
149         for (O option : options) {
150             Optional<T> o = getter.apply(option);
151             if (o.isPresent()) {
152                 return o;
153             }
154         }
155         return Optional.empty();
156     }
157 
158     protected Optional<List<String>> collectListIfPresentOrEmpty(Function<O, Optional<List<String>>> getter) {
159         int had = 0;
160         ArrayList<String> items = new ArrayList<>();
161         for (O option : options) {
162             Optional<List<String>> o = getter.apply(option);
163             if (o.isPresent()) {
164                 had++;
165                 items.addAll(o.get());
166             }
167         }
168         return had == 0 ? Optional.empty() : Optional.of(List.copyOf(items));
169     }
170 
171     protected Optional<Map<String, String>> collectMapIfPresentOrEmpty(
172             Function<O, Optional<Map<String, String>>> getter) {
173         int had = 0;
174         HashMap<String, String> items = new HashMap<>();
175         for (O option : options) {
176             Optional<Map<String, String>> up = getter.apply(option);
177             if (up.isPresent()) {
178                 had++;
179                 items.putAll(up.get());
180             }
181         }
182         return had == 0 ? Optional.empty() : Optional.of(Map.copyOf(items));
183     }
184 }