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

devonfw / IDEasy / 38705799879

15 Oct 2026 08:27AM UTC coverage: 74.732% (+0.05%) from 74.686%
38705799879

Pull #2672

github

web-flow
Merge 5ceb19842 into 747c9a4cd
Pull Request #2672: Feature/2583 extract shared commandlet api into interface

5852 of 8705 branches covered (67.23%)

Branch coverage included in aggregate %.

15303 of 19603 relevant lines covered (78.06%)

3.35 hits per line

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

85.53
cli/src/main/java/com/devonfw/tools/ide/commandlet/AbstractCommandlet.java
1
package com.devonfw.tools.ide.commandlet;
2

3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.HashMap;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Objects;
9

10
import com.devonfw.tools.ide.context.AbstractIdeContext;
11
import com.devonfw.tools.ide.context.IdeContext;
12
import com.devonfw.tools.ide.property.KeywordProperty;
13
import com.devonfw.tools.ide.property.Property;
14

15
/**
16
 * A {@link AbstractCommandlet} is a sub-command of the IDE CLI.
17
 */
18
public abstract class AbstractCommandlet implements Commandlet {
1 ✔
19

20
  /** The {@link IdeContext} instance. */
21
  protected final IdeContext context;
22

23
  private final List<Property<?>> propertiesList;
24

25
  private final List<Property<?>> properties;
26

27
  private final List<Property<?>> valuesList;
28

29
  private final List<Property<?>> values;
30

31
  private final Map<String, Property<?>> optionMap;
32

33
  private Property<?> multiValued;
34

35
  private KeywordProperty firstKeyword;
36

37
  /**
38
   * The constructor.
39
   *
40
   * @param context the {@link IdeContext}.
41
   */
42
  public AbstractCommandlet(IdeContext context) {
43

44
    super();
2 ✔
45
    this.context = context;
3 ✔
46
    this.propertiesList = new ArrayList<>();
5 ✔
47
    this.properties = Collections.unmodifiableList(this.propertiesList);
5 ✔
48
    this.valuesList = new ArrayList<>();
5 ✔
49
    this.values = Collections.unmodifiableList(this.valuesList);
5 ✔
50
    this.optionMap = new HashMap<>();
5 ✔
51
  }
1 ✔
52

53
  /**
54
   * @return the {@link List} with all {@link Property properties} of this {@link AbstractCommandlet}.
55
   */
56
  @Override
57
  public List<Property<?>> getProperties() {
58

59
    return this.properties;
3 ✔
60
  }
61

62
  /**
63
   * @return the {@link List} of {@link Property properties} that are {@link Property#isValue() values}.
64
   */
65
  @Override
66
  public List<Property<?>> getValues() {
67

68
    return this.values;
3 ✔
69
  }
70

71
  /**
72
   * @param nameOrAlias the potential {@link Property#getName() name} or {@link Property#getAlias() alias} of the requested {@link Property}.
73
   * @return the requested {@link Property property} or {@code null} if not found.
74
   */
75
  @Override
76
  public Property<?> getOption(String nameOrAlias) {
77

78
    return this.optionMap.get(nameOrAlias);
6 ✔
79
  }
80

81
  /**
82
   * @param keyword the {@link KeywordProperty keyword} to {@link #add(Property) add}.
83
   */
84
  protected void addKeyword(String keyword) {
85

86
    addKeyword(keyword, null);
4 ✔
87
  }
1 ✔
88

89
  /**
90
   * @param keyword the {@link KeywordProperty keyword} to {@link #add(Property) add}.
91
   * @param alias the optional {@link KeywordProperty#getAlias() alias}.
92
   */
93
  protected void addKeyword(String keyword, String alias) {
94

95
    KeywordProperty property = new KeywordProperty(keyword, true, alias);
7 ✔
96
    if (this.firstKeyword == null) {
3 ✔
97
      if (!this.properties.isEmpty()) {
4 !
98
        throw new IllegalStateException(property + " must be first property in " + getClass().getSimpleName());
×
99
      }
100
      this.firstKeyword = property;
3 ✔
101
    }
102
    add(property);
4 ✔
103
  }
1 ✔
104

105
  /**
106
   * @param <P> type of the {@link Property}.
107
   * @param property the {@link Property} to register.
108
   * @return the given {@link Property}.
109
   */
110
  protected <P extends Property<?>> P add(P property) {
111

112
    if (this.multiValued != null) {
3 !
113
      throw new IllegalStateException("The multi-valued property " + this.multiValued + " can not be followed by " + property);
×
114
    }
115
    this.propertiesList.add(property);
5 ✔
116
    if (property.isOption()) {
3 ✔
117
      add(property.getName(), property, false);
6 ✔
118
      add(property.getAlias(), property, true);
6 ✔
119
    }
120
    if (property.isValue()) {
3 ✔
121
      this.valuesList.add(property);
5 ✔
122
    }
123
    if (property.isMultiValued()) {
3 ✔
124
      this.multiValued = property;
3 ✔
125
    }
126
    return property;
2 ✔
127
  }
128

129
  private void add(String name, Property<?> property, boolean alias) {
130

131
    if (alias && (name == null)) {
4 ✔
132
      return;
1 ✔
133
    }
134
    Objects.requireNonNull(name);
3 ✔
135
    assert (name.equals(name.trim()));
6 !
136
    if (name.isEmpty() && !alias) {
3 !
137
      return;
×
138
    }
139
    Property<?> duplicate = this.optionMap.put(name, property);
7 ✔
140
    if (duplicate != null) {
2 !
141
      throw new IllegalStateException("Duplicate name or alias " + name + " for " + property + " and " + duplicate);
×
142
    }
143
  }
1 ✔
144

145
  @Override
146
  public IdeContext getContext() {
147

148
    return this.context;
3 ✔
149
  }
150

151
  @Override
152
  public abstract String getName();
153

154
  /**
155
   * @return the first keyword of this {@link AbstractCommandlet}. Typically, the same as {@link #getName() name} but may also differ (e.g. "set" vs.
156
   *     "set-version").
157
   */
158
  @Override
159
  public KeywordProperty getFirstKeyword() {
160

161
    return this.firstKeyword;
3 ✔
162
  }
163

164
  /**
165
   * @param <C> type of the {@link AbstractCommandlet}.
166
   * @param commandletType the {@link Class} reflecting the requested {@link AbstractCommandlet}.
167
   * @return the requested {@link AbstractCommandlet}.
168
   * @see CommandletManager#getCommandlet(Class)
169
   */
170
  protected <C extends AbstractCommandlet> C getCommandlet(Class<C> commandletType) {
171

172
    return this.context.getCommandletManager().getCommandlet(commandletType);
6 ✔
173
  }
174

175
  /**
176
   * Runs this {@link AbstractCommandlet}.
177
   */
178
  public final void run() {
179

180
    if (this.context != null) { // for ContextCommandlet we do not have a context yet
3 ✔
181
      ((AbstractIdeContext) this.context).configureJavaUtilLogging(this);
5 ✔
182
    }
183
    doRun();
2 ✔
184
  }
1 ✔
185

186
  protected abstract void doRun();
187

188
  @Override
189
  public String toString() {
190

191
    return getClass().getSimpleName() + "[" + getName() + "]";
7 ✔
192
  }
193
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc