• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 15217656699

23 May 2025 07:22PM UTC coverage: 67.562% (-0.3%) from 67.89%
15217656699

push

github

web-flow
#1332: fixed bug pattern, proper Step usage, allow running tool if plugin failed (#1334)

Co-authored-by: jan-vcapgemini <59438728+jan-vcapgemini@users.noreply.github.com>

3151 of 5064 branches covered (62.22%)

Branch coverage included in aggregate %.

8048 of 11512 relevant lines covered (69.91%)

3.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.03
cli/src/main/java/com/devonfw/tools/ide/step/Step.java
1
package com.devonfw.tools.ide.step;
2

3
import java.util.concurrent.Callable;
4

5
import com.devonfw.tools.ide.log.IdeSubLogger;
6

7
/**
8
 * Interface for a {@link Step} of the process. Allows to split larger processes into smaller steps that are traced and measured. Also prevents that if one step
9
 * fails, the overall process can still continue so a sub-step (e.g. "plugin installation" or "git update") does not automatically block the entire process. At
10
 * the end you can get a report with the hierarchy of all steps and their success/failure status, duration in absolute and relative numbers to gain
11
 * transparency.<br> The typical use should follow this pattern:
12
 *
13
 * <pre>
14
 * Step step = context.{@link com.devonfw.tools.ide.context.IdeContext#newStep(String) newStep}("My step description");
15
 * step.run(() -> {
16
 *   // ... do something ...
17
 *   if (success) {
18
 *     step.{@link #success(String) success}("Did something successfully.");
19
 *   } else {
20
 *     step.{@link #error(String) error}("Failed to do something.");
21
 *   }
22
 * });
23
 * </pre>
24
 * No need to manually catch exceptions and report them as error. All this will happen automatically in {@link #run(Runnable)} method. You may pass a private
25
 * method as lambda to avoid multiline lambda syntax.
26
 */
27
public interface Step {
2!
28

29
  /**
30
   * Empty object array for no parameters.
31
   */
32
  Object[] NO_PARAMS = new Object[0];
4✔
33

34
  /**
35
   * @return the name of this {@link Step} as given to constructor.
36
   */
37
  String getName();
38

39
  /**
40
   * @return the duration of this {@link Step} from construction to {@link #success()} or {@link #close()}. Will be {@code 0} if not {@link #close() ended}.
41
   */
42
  long getDuration();
43

44
  /**
45
   * @return {@code Boolean#TRUE} if this {@link Step} has {@link #success() succeeded}, {@code Boolean#FALSE} if the {@link Step} has {@link #close() ended}
46
   *     without {@link #success() success} and {@code null} if the {@link Step} is still running.
47
   */
48
  Boolean getSuccess();
49

50
  /**
51
   * @return {@code true} if this step completed {@link #success() successfully}, {@code false} otherwise.
52
   */
53
  default boolean isSuccess() {
54

55
    return Boolean.TRUE.equals(getSuccess());
×
56
  }
57

58
  /**
59
   * @return {@code true} if this step {@link #close() ended} without {@link #success() success} e.g. with an {@link #error(String) error}, {@code false}
60
   *     otherwise.
61
   */
62
  default boolean isFailure() {
63

64
    return Boolean.FALSE.equals(getSuccess());
×
65
  }
66

67
  /**
68
   * @return {@code true} if this step is silent and not logged by default, {@code false} otherwise (default).
69
   */
70
  boolean isSilent();
71

72
  /**
73
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
74
   */
75
  default void success() {
76

77
    success(null);
3✔
78
  }
1✔
79

80
  /**
81
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
82
   *
83
   * @param message the explicit message to log as success.
84
   */
85
  default void success(String message) {
86

87
    success(message, (Object[]) null);
5✔
88
  }
1✔
89

90
  /**
91
   * Should be called to end this {@link Step} {@link #getSuccess() successfully}. May be called only once.
92
   *
93
   * @param message the explicit message to log as success.
94
   * @param args the optional arguments to fill as placeholder into the {@code message}.
95
   */
96
  void success(String message, Object... args);
97

98
  /**
99
   * @return the {@link IdeSubLogger} for success messages allowing generic code sharing logger fallback.
100
   */
101
  IdeSubLogger asSuccess();
102

103
  /**
104
   * Ensures this {@link Step} is properly ended. Has to be called from a finally block. Do not call manually but always use {@link #run(Runnable)} or
105
   * {@link #call(Callable)}.
106
   */
107
  void close();
108

109
  /**
110
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message. May be called only once.
111
   *
112
   * @param message the explicit message to log as error.
113
   */
114
  default void error(String message) {
115

116
    error(null, message);
4✔
117
  }
1✔
118

119
  /**
120
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
121
   * only once.
122
   *
123
   * @param message the explicit message to log as error.
124
   * @param args the optional arguments to fill as placeholder into the {@code message}.
125
   */
126
  default void error(String message, Object... args) {
127

128
    error(null, message, args);
5✔
129
  }
1✔
130

131
  /**
132
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
133
   * only once.
134
   *
135
   * @param error the catched {@link Throwable}.
136
   */
137
  default void error(Throwable error) {
138

139
    error(error, false);
4✔
140
  }
1✔
141

142
  /**
143
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
144
   * only once.
145
   *
146
   * @param error the catched {@link Throwable}.
147
   * @param suppress to suppress the error logging (if error will be rethrown and duplicated error messages shall be avoided).
148
   */
149
  default void error(Throwable error, boolean suppress) {
150

151
    assert (error != null);
4!
152
    error(error, suppress, null, (Object[]) null);
7✔
153
  }
1✔
154

155
  /**
156
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
157
   * only once.
158
   *
159
   * @param error the catched {@link Throwable}. May be {@code null} if only a {@code message} is provided.
160
   * @param message the explicit message to log as error.
161
   */
162
  default void error(Throwable error, String message) {
163

164
    error(error, message, (Object[]) null);
6✔
165
  }
1✔
166

167
  /**
168
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
169
   * only once.
170
   *
171
   * @param error the catched {@link Throwable}. May be {@code null} if only a {@code message} is provided.
172
   * @param message the explicit message to log as error.
173
   * @param args the optional arguments to fill as placeholder into the {@code message}.
174
   */
175
  default void error(Throwable error, String message, Object... args) {
176

177
    error(error, false, message, args);
6✔
178
  }
1✔
179

180
  /**
181
   * Should be called to end this {@link Step} as {@link #isFailure() failure} with an explicit error message and/or {@link Throwable exception}. May be called
182
   * only once.
183
   *
184
   * @param error the catched {@link Throwable}. May be {@code null} if only a {@code message} is provided.
185
   * @param suppress to suppress the error logging (if error will be rethrown and duplicated error messages shall be avoided).
186
   * @param message the explicit message to log as error.
187
   * @param args the optional arguments to fill as placeholder into the {@code message}.
188
   */
189
  void error(Throwable error, boolean suppress, String message, Object... args);
190

191
  /**
192
   * @return the {@link IdeSubLogger} for error messages allowing generic code sharing logger fallback.
193
   */
194
  IdeSubLogger asError();
195

196
  /**
197
   * @return the parent {@link Step} or {@code null} if there is no parent.
198
   */
199
  Step getParent();
200

201
  /**
202
   * @param i the index of the requested parameter. Should be in the range from {@code 0} to
203
   *     <code>{@link #getParameterCount()}-1</code>.
204
   * @return the parameter at the given index {@code i} or {@code null} if no such parameter exists.
205
   */
206
  Object getParameter(int i);
207

208
  /**
209
   * @return the number of {@link #getParameter(int) parameters}.
210
   */
211
  int getParameterCount();
212

213
  /**
214
   * @param stepCode the {@link Runnable} to {@link Runnable#run() execute} for this {@link Step}.
215
   * @return {@code true} on success, {@code false} on error.
216
   */
217
  default boolean run(Runnable stepCode) {
218

219
    return run(stepCode, false);
5✔
220
  }
221

222
  /**
223
   * @param stepCode the {@link Runnable} to {@link Runnable#run() execute} for this {@link Step}.
224
   * @param rethrow - {@code true} to rethrow a potential {@link Throwable error}.
225
   * @return {@code true} on success, {@code false} on error (if {@code rethrow} is {@code false}).
226
   */
227
  default boolean run(Runnable stepCode, boolean rethrow) {
228

229
    try {
230
      stepCode.run();
2✔
231
      if (getSuccess() == null) {
3✔
232
        success();
2✔
233
      }
234
      return true;
4✔
235
    } catch (RuntimeException | Error e) {
1✔
236
      error(e);
3✔
237
      if (rethrow) {
2!
238
        throw e;
×
239
      }
240
      return false;
4✔
241
    } finally {
242
      close();
2✔
243
    }
244
  }
245

246
  /**
247
   * @param stepCode the {@link Callable} to {@link Callable#call() execute} for this {@link Step}.
248
   * @param <R> type of the return value.
249
   * @return the value returned from {@link Callable#call()}.
250
   */
251
  default <R> R call(Callable<R> stepCode) {
252

253
    return call(stepCode, true, null);
×
254
  }
255

256
  /**
257
   * @param stepCode the {@link Callable} to {@link Callable#call() execute} for this {@link Step}.
258
   * @param resultOnError the result to be returned in case of a {@link Throwable error}.
259
   * @param <R> type of the return value.
260
   * @return the value returned from {@link Callable#call()}.
261
   */
262
  default <R> R call(Callable<R> stepCode, R resultOnError) {
263

264
    return call(stepCode, false, resultOnError);
×
265
  }
266

267
  /**
268
   * @param stepCode the {@link Callable} to {@link Callable#call() execute} for this {@link Step}.
269
   * @param rethrow - {@code true} to rethrow a potential {@link Throwable error}.
270
   * @param resultOnError the result to be returned in case of a {@link Throwable error}.
271
   * @param <R> type of the return value.
272
   * @return the value returned from {@link Callable#call()}.
273
   */
274
  default <R> R call(Callable<R> stepCode, boolean rethrow, R resultOnError) {
275

276
    try {
277
      R result = stepCode.call();
×
278
      if (getSuccess() == null) {
×
279
        success();
×
280
      }
281
      return result;
×
282
    } catch (Throwable e) {
×
283
      error(e);
×
284
      if (rethrow) {
×
285
        if (e instanceof RuntimeException re) {
×
286
          throw re;
×
287
        } else if (e instanceof Error error) {
×
288
          throw error;
×
289
        } else {
290
          throw new IllegalStateException(e);
×
291
        }
292
      }
293
      return resultOnError;
×
294
    } finally {
295
      close();
×
296
    }
297
  }
298

299
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc