Skip to content

Commit 3f7fa45

Browse files
committed
Add Explain command
1 parent 8036ab4 commit 3f7fa45

File tree

7 files changed

+205
-82
lines changed

7 files changed

+205
-82
lines changed

src/main/java/io/openliberty/explore/DescribeCommand.java

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* =============================================================================
3+
* Copyright (c) 2022,2024 IBM Corporation and others.
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v2.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v20.html
8+
*
9+
* Contributors:
10+
* IBM Corporation - initial API and implementation
11+
* =============================================================================
12+
*/
13+
package io.openliberty.explore;
14+
15+
import java.util.EnumMap;
16+
import java.util.List;
17+
import static java.util.function.Predicate.not;
18+
import java.util.stream.Collectors;
19+
20+
import io.openliberty.inspect.Visibility;
21+
import io.openliberty.inspect.feature.Feature;
22+
import picocli.CommandLine.Command;
23+
import picocli.CommandLine.Parameters;
24+
import picocli.CommandLine.ParentCommand;
25+
26+
@Command(
27+
name = "explain",
28+
description = "Produce a detailed description of the specified elements"
29+
)
30+
public class ExplainCommand {
31+
private static final String BULLET_POINT = " - ";
32+
33+
@ParentCommand
34+
private LibertyExplorer explorer;
35+
36+
@Command(name = "features", description = "Explain a feature")
37+
void features(
38+
@Parameters(arity = "1..*", description = "one or more glob patterns to match features by name", defaultValue = "*")
39+
List<String> patterns
40+
) throws Exception {
41+
explorer.init(patterns); // find all features
42+
explorer.allResults()
43+
.stream()
44+
.filter(Feature.class::isInstance)
45+
.map(Feature.class::cast)
46+
.sorted()
47+
.forEach(this::explain);
48+
}
49+
50+
private static EnumMap<Visibility, String> VIS_DESCS = new EnumMap<>(Visibility.class);
51+
52+
private void explain(Feature f) {
53+
// Heading
54+
String name = f.name();
55+
System.out.println(name);
56+
System.out.println(name.replaceAll(".", "="));
57+
// Feature names
58+
System.out.printf("The feature %s is defined by the file: %s%n", f.symbolicName(), f.path());
59+
f.shortName().ifPresent(n -> System.out.printf("It is also known by its short name: %s%n", n));
60+
// Describe visibility, auto-ness, and include embedded description
61+
System.out.printf(switch (f.visibility()) {
62+
case PUBLIC -> "This is a public feature; it can be configured directly in server configuration,"
63+
+ " or included by Liberty or extension features.%n"
64+
+ f.description() + "%n";
65+
case PROTECTED -> "This is a protected feature; it can be included by Liberty or extension features.%n";
66+
case PRIVATE -> f.isAutoFeature() ?
67+
"This is an auto-feature; it will be included automatically based on the presence of other features in combination.%n" :
68+
"This is a private feature; it can be included by other Liberty features.%n";
69+
default -> "The visibility of this feature is unknown.%n";
70+
});
71+
boolean hasFeatureDeps = f.hasFeatureDependencies();
72+
if (hasFeatureDeps) {
73+
System.out.println("This feature includes the following features:");
74+
f.formatFeatureDependencies().map(BULLET_POINT::concat).forEach(System.out::println);
75+
}
76+
if (f.hasBundleDependencies()) {
77+
System.out.println(hasFeatureDeps ? "and the following bundles:" : "This feature includes the following bundles:");
78+
f.formatBundleDependencies().map(BULLET_POINT::concat).forEach(System.out::println);
79+
}
80+
System.out.println();
81+
}
82+
}

src/main/java/io/openliberty/explore/LibertyExplorer.java

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,49 @@
1313
package io.openliberty.explore;
1414

1515

16-
import io.openliberty.inspect.Catalog;
17-
import io.openliberty.inspect.Element;
16+
import java.nio.file.Path;
17+
import java.util.Arrays;
18+
import static java.util.Collections.emptySet;
19+
import static java.util.Collections.unmodifiableSet;
20+
import java.util.HashSet;
21+
import java.util.List;
22+
import static java.util.Objects.requireNonNull;
23+
import java.util.Set;
24+
import static java.util.function.Predicate.not;
25+
import java.util.stream.Collectors;
26+
import static java.util.stream.Collectors.toUnmodifiableList;
27+
import static java.util.stream.Collectors.toUnmodifiableSet;
28+
import java.util.stream.Stream;
29+
1830
import org.jgrapht.Graph;
1931
import org.jgrapht.GraphPath;
2032
import org.jgrapht.alg.shortestpath.AllDirectedPaths;
2133
import org.jgrapht.graph.AsGraphUnion;
2234
import org.jgrapht.graph.AsSubgraph;
2335
import org.jgrapht.graph.DefaultEdge;
2436
import org.jgrapht.graph.EdgeReversedGraph;
37+
38+
import static io.openliberty.GraphCollectors.toUnionWith;
39+
import static io.openliberty.explore.LibertyExplorer.Direction.FORWARD;
40+
import static io.openliberty.explore.LibertyExplorer.Direction.REVERSE;
41+
import io.openliberty.inspect.Catalog;
42+
import io.openliberty.inspect.Element;
2543
import picocli.CommandLine;
2644
import picocli.CommandLine.Command;
2745
import picocli.CommandLine.HelpCommand;
2846
import picocli.CommandLine.Option;
2947
import picocli.CommandLine.PropertiesDefaultProvider;
3048

31-
import java.nio.file.Path;
32-
import java.util.HashSet;
33-
import java.util.List;
34-
import java.util.Set;
35-
import java.util.stream.Collectors;
36-
import java.util.stream.Stream;
37-
38-
import static io.openliberty.GraphCollectors.toUnionWith;
39-
import static io.openliberty.explore.LibertyExplorer.Direction.FORWARD;
40-
import static io.openliberty.explore.LibertyExplorer.Direction.REVERSE;
41-
import static java.util.Collections.emptySet;
42-
import static java.util.Collections.unmodifiableSet;
43-
import static java.util.Objects.requireNonNull;
44-
import static java.util.function.Predicate.not;
45-
import static java.util.stream.Collectors.toUnmodifiableList;
46-
import static java.util.stream.Collectors.toUnmodifiableSet;
47-
4849
@Command(
4950
name = "lx",
5051
description = "Liberty installation eXplorer",
5152
version = "Liberty installation eXplorer 0.5",
52-
subcommands = {DescribeCommand.class, ListCommand.class, GraphCommand.class, TreeCommand.class, HelpCommand.class},
53+
subcommands = {
54+
ExplainCommand.class,
55+
ListCommand.class,
56+
GraphCommand.class,
57+
TreeCommand.class,
58+
HelpCommand.class},
5359
defaultValueProvider = PropertiesDefaultProvider.class
5460
)
5561
public class LibertyExplorer {
@@ -92,6 +98,10 @@ void init(List<String> patterns) throws Exception {
9298
removeExcludedElements();
9399
}
94100

101+
void init(String...patterns) throws Exception {
102+
init(Arrays.asList(patterns));
103+
}
104+
95105
void removeExcludedElements() {
96106
// remove excluded features (and associated edges) from graph
97107
if (verbose) System.err.println("Exclude patterns:");

src/main/java/io/openliberty/inspect/Catalog.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ public static SimpleDirectedGraph<Element, DefaultEdge> newGraph() {
6161
public Catalog(Path libertyRoot, boolean includeBundles) throws IOException {
6262
validate(libertyRoot, "Not a valid directory: ");
6363
Path libDir = validate(libertyRoot.resolve("lib"), "No lib subdirectory found: ");
64+
Path devDir = validate(libertyRoot.resolve("dev"), "No dev subdirectory found: ");
6465
// parse bundles
65-
if (includeBundles) Files.list(libDir)
66+
if (includeBundles) Stream.concat(Files.walk(devDir),Files.list(libDir))
6667
.filter(Files::isRegularFile)
6768
.filter(p -> p.toString().endsWith(".jar"))
6869
.map(Bundle::new)

src/main/java/io/openliberty/inspect/feature/BundleSpec.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
import org.osgi.framework.VersionRange;
1818

1919
public class BundleSpec implements ContentSpec {
20+
private final static VersionRange DEFAULT_RANGE = VersionRange.valueOf("0.0");
2021
final String symbolicName;
2122
final VersionRange versionRange;
2223

2324
BundleSpec(ManifestValueEntry ve) {
2425
this.symbolicName = ve.id;
25-
this.versionRange = VersionRange.valueOf(ve.getQualifierOrDefault("version", "0.0"));
26+
this.versionRange = ve.getQualifierIfPresent("version").map(VersionRange::valueOf).orElse(DEFAULT_RANGE);
2627
}
2728

2829
@Override
@@ -40,4 +41,14 @@ public int compareMatches(Element f1, Element f2) {
4041
public String toString() {
4142
return symbolicName + ":" + versionRange;
4243
}
44+
45+
String describe() {
46+
if (DEFAULT_RANGE == versionRange) return symbolicName + " at any version.";
47+
if (versionRange.isExact()) return symbolicName + " version " + versionRange.getLeft();
48+
return symbolicName + " from version " + versionRange.getLeft()
49+
+ (versionRange.getRightType() == VersionRange.RIGHT_CLOSED ?
50+
" up to and including ":
51+
" up to but not including ")
52+
+ versionRange.getRight() + versionRange.getRightType();
53+
}
4354
}

0 commit comments

Comments
 (0)