diff --git a/cli/src/main/java/com/devonfw/tools/ide/common/Tag.java b/cli/src/main/java/com/devonfw/tools/ide/common/Tag.java new file mode 100644 index 000000000..d7ef85640 --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/common/Tag.java @@ -0,0 +1,564 @@ +package com.devonfw.tools.ide.common; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * A {@link Tag} represents a classifier or category. A tool and plugin can be associated with {@link Tag}s allowing end + * users to find them. + */ +public final class Tag { + + private static final Tag[] NO_TAGS = new Tag[0]; + + private static final Map TAG_MAP = new HashMap<>(128); + + private static final Collection ALL_TAGS = Collections.unmodifiableCollection(TAG_MAP.values()); + + /** The root {@link Tag}. */ + public static final Tag ROOT = new Tag(); + + static { + TAG_MAP.put(ROOT.id, ROOT); + } + + /** {@link #getParent() Parent} for miscellaneous (undefined) tags. */ + public static final Tag MISC = create("miscellaneous", ROOT, true, "misc"); + + /** {@link #getParent() Parent} for programming-languages. */ + public static final Tag LANGUAGE = create("language", ROOT, true, "programming"); + + /** {@link Tag} for JVM (Java Virtual Machine). */ + public static final Tag JVM = create("java-virtual-machine", LANGUAGE, false, "jvm"); + + /** {@link Tag} for Java. */ + public static final Tag JAVA = create("java", JVM); + + /** {@link Tag} for Kotlin. */ + public static final Tag KOTLIN = create("kotlin", JVM); + + /** {@link Tag} for Scala. */ + public static final Tag SCALA = create("scala", JVM); + + /** {@link Tag} for DotNet (.NET). */ + public static final Tag DOTNET = create("dotnet", LANGUAGE, false, "net"); + + /** {@link Tag} for C#. */ + public static final Tag CS = create("c#", DOTNET, false, "cs", "csharp"); + + /** {@link Tag} for C. */ + public static final Tag C = create("c", LANGUAGE); + + /** {@link Tag} for Rust. */ + public static final Tag RUST = create("rust", LANGUAGE, false, "rs"); + + /** {@link Tag} for C++. */ + public static final Tag CPP = create("c++", LANGUAGE, false, "cpp"); + + /** {@link Tag} for Python. */ + public static final Tag PYTHON = create("python", LANGUAGE); + + /** {@link Tag} for Ruby. */ + public static final Tag RUBY = create("ruby", LANGUAGE); + + /** {@link Tag} for Perl. */ + public static final Tag PERL = create("perl", LANGUAGE); + + /** {@link Tag} for Shell scripting. */ + public static final Tag SHELL = create("shell", JVM, false, "script"); + + /** {@link Tag} for Bash. */ + public static final Tag BASH = create("bash", SHELL, false, "terminal"); + + /** {@link Tag} for TypeScript. */ + public static final Tag JAVA_SCRIPT = create("javascript", LANGUAGE, false, "js"); + + /** {@link Tag} for TypeScript. */ + public static final Tag TYPE_SCRIPT = create("typescript", JAVA_SCRIPT, false, "ts"); + + /** {@link #getParent() Parent} for programming-languages. */ + public static final Tag IDE = create("ide", ROOT); + + /** {@link Tag} for Eclipse. */ + public static final Tag ECLIPSE = create("eclipse", IDE); + + /** {@link Tag} for IDEA (JetBrains IDE Platform). */ + public static final Tag IDEA = create("idea", IDE); + + /** {@link Tag} for IntelliJ. */ + public static final Tag INTELLIJ = create("intellij", IDEA); + + /** {@link Tag} for IntelliJ. */ + public static final Tag ANDROID_STUDIO = create("android-studio", IDEA); + + /** {@link Tag} for VS-Code. */ + public static final Tag VS_CODE = create("vscode", IDE, false, "visualstudiocode"); + + /** {@link Tag} for (code-)generators (including template-engines, etc.). */ + public static final Tag GENERATOR = create("generator", ROOT); + + /** {@link #getParent() Parent} for frameworks. */ + public static final Tag FRAMEWORK = create("framework", ROOT, true); + + /** {@link Tag} for Spring(framework). */ + public static final Tag SPRING = create("spring", FRAMEWORK, false, new String[] { "springframework", "springboot" }, + JAVA); + + /** {@link Tag} for Quarkus. */ + public static final Tag QUARKUS = create("quarkus", FRAMEWORK, false, null, JAVA); + + /** {@link Tag} for Micronaut. */ + public static final Tag MICRONAUT = create("micronaut", FRAMEWORK, false, null, JAVA); + + /** {@link Tag} for Angular. */ + public static final Tag ANGULAR = create("angular", FRAMEWORK, false, new String[] { "ng", "angularjs" }, + TYPE_SCRIPT); + + /** {@link Tag} for React. */ + public static final Tag REACT = create("react", FRAMEWORK, false, null, TYPE_SCRIPT); + + /** {@link Tag} for Vue. */ + public static final Tag VUE = create("vue", FRAMEWORK, false, null, TYPE_SCRIPT); + + /** {@link Tag} for Cordova. */ + public static final Tag CORDOVA = create("cordova", FRAMEWORK, false, null, JAVA_SCRIPT); + + /** {@link Tag} for Ionic. */ + public static final Tag IONIC = create("ionic", CORDOVA, false); + + /** {@link #getParent() Parent} for quality-assurance. */ + public static final Tag QA = create("quality-assurance", ROOT, false, "qa", "quality"); + + /** {@link Tag} for everything related to testing. */ + public static final Tag TEST = create("testing", QA, false, "test"); + + /** {@link Tag} for everything related to testing. */ + public static final Tag MOCK = create("mocking", TEST, false, "mock"); + + /** {@link Tag} for everything related to testing. */ + public static final Tag CODE_QA = create("static-code-analysis", QA, false, "codeqa"); + + /** {@link #getParent() Parent} for linters. */ + public static final Tag LINTING = create("linter", QA, false, "lint", "linting"); + + /** {@link Tag} for everything related to documentation. */ + public static final Tag DOCUMENTATION = create("documentation", ROOT, false, "doc"); + + /** {@link #getParent() Parent} for file formats. */ + public static final Tag FORMAT = create("format", ROOT, true); + + /** {@link Tag} for JSON. */ + public static final Tag JSON = create("json", FORMAT); + + /** {@link Tag} for YAML. */ + public static final Tag YAML = create("yaml", FORMAT, false, "yml"); + + /** {@link Tag} for CSS. */ + public static final Tag CSS = create("css", FORMAT); + + /** {@link Tag} for Properties. */ + public static final Tag PROPERTIES = create("properties", FORMAT); + + /** {@link Tag} for AsciiDoc. */ + public static final Tag ASCII_DOC = create("ascii-doc", FORMAT, false, new String[] { "adoc" }, DOCUMENTATION); + + /** {@link Tag} for MarkDown. */ + public static final Tag MARK_DOWN = create("markdown", DOCUMENTATION, false, new String[] { "md" }, DOCUMENTATION); + + /** {@link Tag} for YAML. */ + public static final Tag PDF = create("pdf", FORMAT, false, null, DOCUMENTATION); + + /** {@link Tag} for HTML. */ + public static final Tag HTML = create("html", FORMAT, false, null, DOCUMENTATION); + + /** {@link Tag} for machine-learning. */ + public static final Tag MACHINE_LEARNING = create("machine-learning", ROOT, false, "ml"); + + /** {@link Tag} for artificial-intelligence. */ + public static final Tag ARTIFICIAL_INTELLIGENCE = create("artificial-intelligence", MACHINE_LEARNING, false, "ai"); + + /** {@link Tag} for data-science. */ + public static final Tag DATA_SCIENCE = create("data-science", ROOT); + + /** {@link Tag} for business-intelligence. */ + public static final Tag BUSINESS_INTELLIGENCE = create("business-intelligence", ROOT, false, "bi", "datawarehouse", + "dwh"); + + /** {@link #Tag} for productivity. */ + public static final Tag ARCHITECTURE = create("architecture", ROOT); + + /** {@link Tag} for AsciiDoc. */ + public static final Tag UML = create("uml", ARCHITECTURE, false, null, DOCUMENTATION); + + /** {@link #Tag} for security. */ + public static final Tag SECURITY = create("security", ROOT, false, "cve"); + + /** {@link #Tag} for collaboration. */ + public static final Tag COLLABORATION = create("collaboration", ROOT, false, "collab"); + + /** {@link #Tag} for virtualization. */ + public static final Tag VIRTUALIZATION = create("virtualization", ROOT, false, "vm"); + + /** {@link #Tag} for docker. */ + public static final Tag DOCKER = create("docker", VIRTUALIZATION); + + /** {@link #Tag} for docker. */ + public static final Tag KUBERNETES = create("kubernetes", DOCKER, false, "k8s"); + + /** {@link #Tag} for WSL. */ + public static final Tag WSL = create("wsl", VIRTUALIZATION); + + /** {@link #Tag} for network. */ + public static final Tag NETWORK = create("network", ROOT, false, "remote"); + + /** {@link #Tag} for HTTP. */ + public static final Tag HTTP = create("http", NETWORK); + + /** {@link #Tag} for REST. */ + public static final Tag REST = create("rest", HTTP); + + /** {@link #Tag} for secure-shell. */ + public static final Tag SSH = create("secure-shell", NETWORK, false, "ssh", "scp"); + + /** {@link #Tag} for capture. */ + public static final Tag CAPTURE = create("capture", ROOT, false, "capturing"); + + /** {@link #Tag} for capture. */ + public static final Tag SCREENSHOT = create("screenshot", CAPTURE); + + /** {@link #Tag} for capture. */ + public static final Tag SCREEN_RECORDING = create("screenrecording", CAPTURE, false, "videocapture"); + + /** {@link #Tag} for productivity. */ + public static final Tag PRODUCTIVITY = create("productivity", ROOT); + + /** {@link #Tag} for regular-expression. */ + public static final Tag REGEX = create("regular-expression", PRODUCTIVITY, false, "regex", "regexp"); + + /** {@link #Tag} for search. */ + public static final Tag SEARCH = create("search", PRODUCTIVITY, false, "find"); + + /** {@link #Tag} for spellchecker. */ + public static final Tag SPELLCHECKER = create("spellchecker", PRODUCTIVITY, false, "spellcheck", "spellchecking"); + + /** {@link #Tag} for analyse. */ + public static final Tag ANALYSE = create("analyse", ROOT, false, "analyze", "analysis"); + + /** {@link #Tag} for monitoring. */ + public static final Tag MONITORING = create("monitoring", ANALYSE, false, "monitor"); + + /** {@link #Tag} for formatter. */ + public static final Tag FORMATTER = create("formatter", ROOT, false, "codeformat", "codeformatter"); + + /** {@link #Tag} for user-experience. */ + public static final Tag UX = create("user-experience", PRODUCTIVITY, false, "ux"); + + /** {@link #Tag} for style. */ + public static final Tag STYLE = create("style", UX, false, "theme", "icon", "skin"); + + /** {@link #Tag} for style. */ + public static final Tag KEYBINDING = create("keybinding", UX, false, "keybindings", "keymap"); + + /** {@link #Tag} for draw(ing). */ + public static final Tag DRAW = create("draw", UX, false, "diagram", "paint"); + + /** {@link #Tag} for cloud. */ + public static final Tag CLOUD = create("cloud", ROOT); + + /** {@link #Tag} for infrastructure-as-code. */ + public static final Tag IAC = create("infrastructure-as-code", CLOUD, false, "iac"); + + /** {@link #Tag} for software-configuration-management. */ + public static final Tag CONFIG_MANAGEMENT = create("software-configuration-management", ROOT, false, + "configmanagement", "configurationmanagement"); + + /** {@link #Tag} for build-management. */ + public static final Tag BUILD = create("build-management", CONFIG_MANAGEMENT, false, "build"); + + /** {@link #Tag} for version-control. */ + public static final Tag VCS = create("version-control", CONFIG_MANAGEMENT, false, "vcs", "versioncontrolsystem"); + + /** {@link #Tag} for issue-management. */ + public static final Tag ISSUE = create("issue-management", CONFIG_MANAGEMENT, false, "issue"); + + /** {@link #Tag} for git. */ + public static final Tag GIT = create("git", VCS); + + /** {@link #Tag} for github. */ + public static final Tag GITHUB = create("github", GIT); + + /** {@link #Tag} for diff (tools that compare files and determine the difference). */ + public static final Tag DIFF = create("diff", CONFIG_MANAGEMENT, false, "patch"); + + /** {@link #Tag} for diff (tools that compare files and determine the difference). */ + public static final Tag RUNTIME = create("runtime", ROOT); + + /** {@link #getParent() Parent} for operating-system. */ + public static final Tag OS = create("operating-system", ROOT, true, "os"); + + /** {@link #Tag} for Windows. */ + public static final Tag WINDOWS = create("windows", OS); + + /** {@link #Tag} for Mac. */ + public static final Tag MAC = create("mac", OS, false, "macos", "osx"); + + /** {@link #Tag} for Linux. */ + public static final Tag LINUX = create("linux", OS, false); + + private final String id; + + private final Tag parent; + + private final boolean isAbstract; + + private final Tag[] additionalParents; + + private Tag() { + + this.id = ""; + this.parent = null; + this.isAbstract = true; + this.additionalParents = NO_TAGS; + } + + private Tag(String id, Tag parent, boolean isAbstract, Tag... additionalParents) { + + super(); + Objects.requireNonNull(id); + Objects.requireNonNull(parent); + assert (id.toLowerCase(Locale.ROOT).equals(id)); + this.id = id; + this.parent = parent; + this.isAbstract = isAbstract; + this.additionalParents = additionalParents; + } + + /** + * @return the identifier and name of this tag. + */ + public String getId() { + + return this.id; + } + + /** + * @return the parent {@link Tag} or {@code null} if this is the root tag. + */ + public Tag getParent() { + + return this.parent; + } + + /** + * @param i the index of the requested parent. Should be in the range from {@code 0} to + * {@link #getParentCount()}-1. + * @return the requested {@link Tag}. + */ + public Tag getParent(int i) { + + if (i == 0) { + return this.parent; + } + return this.additionalParents[i - 1]; + } + + /** + * @return the number of {@link #getParent(int) parents} available. + */ + public int getParentCount() { + + if (this.parent == null) { + return 0; + } + return this.additionalParents.length + 1; + } + + /** + * @return {@code true} if this {@link Tag} is abstract and cannot be selected since it is just a generic parent + * container, {@code false} otherwise. + */ + public boolean isAbstract() { + + return this.isAbstract; + } + + public boolean isAncestorOf(Tag tag) { + + return isAncestorOf(tag, false); + } + + /** + * @param tag the {@link Tag} to check. + * @param includeAdditionalParents - {@code true} if {@link #getParent(int) additional parents} should be included, + * {@code false} otherwise (only consider {@link #getParent() primary parent}). + * @return {@code true} if the given {@link Tag} is an ancestor of this tag, {@code false} otherwise. An ancestor is + * a direct or indirect {@link #getParent() parent}. Therefore, if {@link #ROOT} is given as {@link Tag} parameter, + * this method should always return {@code true}. + */ + public boolean isAncestorOf(Tag tag, boolean includeAdditionalParents) { + + Tag ancestor = this.parent; + while (ancestor != null) { + if (ancestor == tag) { + return true; + } + ancestor = ancestor.parent; + } + if (includeAdditionalParents) { + for (Tag p : this.additionalParents) { + do { + if (p == tag) { + return true; + } + p = p.parent; + } while (p != null); + } + } + return false; + } + + @Override + public String toString() { + + return this.id; + } + + /** + * @param id the {@link #getId() ID} of the tag. + * @param parent the {@link #getParent() parent tag}. + * @param isAbstract the {@link #isAbstract() abstract flag}. + * @return the new {@link Tag}. + */ + static Tag create(String id, Tag parent) { + + return create(id, parent, false); + } + + /** + * @param id the {@link #getId() ID} of the tag. + * @param parent the {@link #getParent() parent tag}. + * @param isAbstract the {@link #isAbstract() abstract flag}. + * @return the new {@link Tag}. + */ + static Tag create(String id, Tag parent, boolean isAbstract) { + + return create(id, parent, isAbstract, null, NO_TAGS); + } + + /** + * @param id the {@link #getId() ID} of the tag. + * @param parent the {@link #getParent() parent tag}. + * @param isAbstract the {@link #isAbstract() abstract flag}. + * @return the new {@link Tag}. + */ + static Tag create(String id, Tag parent, boolean isAbstract, String synonym) { + + return create(id, parent, isAbstract, new String[] { synonym }, NO_TAGS); + } + + /** + * @param id the {@link #getId() ID} of the tag. + * @param parent the {@link #getParent() parent tag}. + * @param isAbstract the {@link #isAbstract() abstract flag}. + * @return the new {@link Tag}. + */ + static Tag create(String id, Tag parent, boolean isAbstract, String... synonyms) { + + return create(id, parent, isAbstract, synonyms, NO_TAGS); + } + + /** + * @param id the {@link #getId() ID} of the tag. + * @param parent the {@link #getParent() parent tag}. + * @param isAbstract the {@link #isAbstract() abstract flag}. + * @return the new {@link Tag}. + */ + static Tag create(String id, Tag parent, boolean isAbstract, String[] synonyms, Tag... additionalParents) { + + Tag tag = new Tag(id, parent, isAbstract, additionalParents); + add(id, tag); + if (synonyms != null) { + for (String synonym : synonyms) { + add(synonym, tag); + } + } + return tag; + } + + private static void add(String key, Tag tag) { + + Tag duplicate = TAG_MAP.put(normalizeKey(key), tag); + if (duplicate != null) { + throw new IllegalStateException("Duplicate tag for " + key); + } + } + + private static String normalizeKey(String key) { + + return key.replace("-", "").replace(".", ""); + } + + private static Tag require(String key) { + + Tag tag = TAG_MAP.get(normalizeKey(key)); + if (tag == null) { + throw new IllegalStateException("Could not find required tag " + key); + } + return tag; + } + + /** + * @param id the {@link #getId() ID} of the requested {@link Tag}. + * @return the {@link Tag} with the given {@link #getId() ID}. Will be lazily created as child of {@link #MISC} if not + * already exists. + */ + public static Tag of(String id) { + + final String tagId = id.trim(); + int slash = tagId.indexOf('/'); + if (slash >= 0) { + String parentId = tagId.substring(0, slash); + Tag parent = require(parentId); + String childId = tagId.substring(slash + 1); + return TAG_MAP.computeIfAbsent(normalizeKey(childId), i -> new Tag(childId, parent, false, NO_TAGS)); + } + return TAG_MAP.computeIfAbsent(normalizeKey(tagId), i -> new Tag(tagId, MISC, false, NO_TAGS)); + } + + /** + * @return the {@link Collections} of all available {@link Tag}s. + */ + public static Collection getAll() { + + return ALL_TAGS; + } + + /** + * @param tagsCsv the tags as {@link String} in CSV format («first-tag»,...,«last-tag»). May be {@code null} or empty. + * @return the parsed {@link Set} of {@link Tag}s. + */ + public static Set parseCsv(String tagsCsv) { + + if (tagsCsv == null) { + return Collections.emptySet(); + } + tagsCsv = tagsCsv.trim().toLowerCase(Locale.ROOT); + if (tagsCsv.isEmpty()) { + return Collections.emptySet(); + } + String[] tagArray = tagsCsv.split(","); + Set tags = new HashSet<>(tagArray.length); + for (String tag : tagArray) { + tags.add(of(tag)); + } + assert (tags.size() == tagArray.length); + return Set.of(tags.toArray(new Tag[tags.size()])); + } + +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/common/Tags.java b/cli/src/main/java/com/devonfw/tools/ide/common/Tags.java index ae80a5891..7f7fdfea9 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/common/Tags.java +++ b/cli/src/main/java/com/devonfw/tools/ide/common/Tags.java @@ -3,65 +3,14 @@ import java.util.Set; /** - * TODO hohwille This type ... - * + * Interface for an object that {@link #getTags() has} {@link Tag}s. */ public interface Tags { - /** {@link #getTags() Tag} for Java and JVM related tools. */ - String TAG_JAVA = "java"; - - /** {@link #getTags() Tag} for build tools. */ - String TAG_BUILD = "build"; - - /** {@link #getTags() Tag} for quality assurance (QA) tools. */ - String TAG_QA = "qa"; - - /** {@link #getTags() Tag} for artificial intelligence (AI) and machine learning (ML) tools. */ - String TAG_AI = "ai"; - - /** {@link #getTags() Tag} for documentation tools. */ - String TAG_DOCUMENTATION = "doc"; - - /** {@link #getTags() Tag} for tools supporting AsciiDoc. */ - String TAG_ASCIIDOC = "adoc"; - - /** {@link #getTags() Tag} for angular related tools. */ - String TAG_ANGULAR = "angular"; - - /** {@link #getTags() Tag} for TypeScript related tools. */ - String TAG_TYPE_SCRIPT = "ts"; - - /** {@link #getTags() Tag} for generic tools that increase productivity. */ - String TAG_PRODUCTIVITY = "productivity"; - - /** {@link #getTags() Tag} for DotNet related tools. */ - String TAG_DOT_NET = ".net"; - - /** {@link #getTags() Tag} for Python related tools. */ - String TAG_PYTHON = "python"; - - /** {@link #getTags() Tag} for tools that actually represent an IDE (Integrated Development Environment). */ - String TAG_IDE = "ide"; - - /** {@link #getTags() Tag} for tools providing a runtime environment (the core of a programming language). */ - String TAG_RUNTIME = "runtime"; - /** - * {@link #getTags() Tag} for cloud tools (e.g. CLI to manage infrastructure in the cloud). This is not limited to the - * hyper-scalers but also used for other platforms providing automation like openshift or even github. + * @return a {@link Set} with the tags classifying this object. E.g. for mvn (maven) the tags {@link Tag#JAVA java} + * and {@link Tag#BUILD build} could be associated. */ - String TAG_CLOUD = "cloud"; + Set getTags(); - /** {@link #getTags() Tag} for infrastructure-as-code (IAC) tools. */ - String TAG_IAC = "iac"; - - /** {@link #getTags() Tag} for frameworks. */ - String TAG_FRAMEWORK = "framework"; - - /** - * @return a {@link Set} with the tags classifying this object. E.g. for mvn (maven) the tags {@link #TAG_JAVA java} - * and {@link #TAG_BUILD build} could be associated. - */ - Set getTags(); } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java index 8c83a16a1..62cf0dcdf 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/GlobalToolCommandlet.java @@ -1,5 +1,6 @@ package com.devonfw.tools.ide.tool; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.process.ProcessContext; @@ -24,7 +25,7 @@ public abstract class GlobalToolCommandlet extends ToolCommandlet { * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} * method. */ - public GlobalToolCommandlet(IdeContext context, String tool, Set tags) { + public GlobalToolCommandlet(IdeContext context, String tool, Set tags) { super(context, tool, tags); } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java index 8505dead7..1159f375a 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/LocalToolCommandlet.java @@ -1,6 +1,13 @@ package com.devonfw.tools.ide.tool; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Set; + import com.devonfw.tools.ide.commandlet.Commandlet; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.io.FileCopyMode; @@ -8,12 +15,6 @@ import com.devonfw.tools.ide.repo.ToolRepository; import com.devonfw.tools.ide.version.VersionIdentifier; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.Set; - /** * {@link ToolCommandlet} that is installed locally into the IDE. */ @@ -27,12 +28,11 @@ public abstract class LocalToolCommandlet extends ToolCommandlet { * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} * method. */ - public LocalToolCommandlet(IdeContext context, String tool, Set tags) { + public LocalToolCommandlet(IdeContext context, String tool, Set tags) { super(context, tool, tags); } - /** * @return the {@link Path} where the tool is located (installed). */ diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java index f5ab8b3be..b6220334b 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java @@ -10,6 +10,7 @@ import com.devonfw.tools.ide.cli.CliException; import com.devonfw.tools.ide.commandlet.Commandlet; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.common.Tags; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.environment.EnvironmentVariables; @@ -31,7 +32,7 @@ public abstract class ToolCommandlet extends Commandlet implements Tags { /** @see #getName() */ protected final String tool; - private final Set tags; + private final Set tags; /** The commandline arguments to pass to the tool. */ public final StringListProperty arguments; @@ -46,7 +47,7 @@ public abstract class ToolCommandlet extends Commandlet implements Tags { * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} * method. */ - public ToolCommandlet(IdeContext context, String tool, Set tags) { + public ToolCommandlet(IdeContext context, String tool, Set tags) { super(context); this.tool = tool; @@ -73,7 +74,7 @@ protected String getBinaryName() { } @Override - public final Set getTags() { + public final Set getTags() { return this.tags; } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/az/Azure.java b/cli/src/main/java/com/devonfw/tools/ide/tool/az/Azure.java index 12937026a..195ccf922 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/az/Azure.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/az/Azure.java @@ -3,6 +3,7 @@ import java.nio.file.Paths; import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.environment.EnvironmentVariables; import com.devonfw.tools.ide.environment.EnvironmentVariablesType; @@ -22,7 +23,7 @@ public class Azure extends LocalToolCommandlet { */ public Azure(IdeContext context) { - super(context, "az", Set.of(TAG_CLOUD)); + super(context, "az", Set.of(Tag.CLOUD)); } @Override @@ -34,6 +35,6 @@ public void postInstall() { EnvironmentVariables typeVariables = variables.getByType(EnvironmentVariablesType.CONF); typeVariables.set("AZURE_CONFIG_DIR", this.context.getConfPath().resolve(".azure").toString(), true); typeVariables.save(); - this.context.getFileAccess().symlink(Paths.get("wbin"), this.getToolPath().resolve("bin")); + this.context.getFileAccess().symlink(Paths.get("wbin"), getToolPath().resolve("bin")); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/eclipse/Eclipse.java b/cli/src/main/java/com/devonfw/tools/ide/tool/eclipse/Eclipse.java index 38116d067..5d91ad304 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/eclipse/Eclipse.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/eclipse/Eclipse.java @@ -11,6 +11,7 @@ import com.devonfw.tools.ide.cli.CliArgument; import com.devonfw.tools.ide.cli.CliException; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.log.IdeLogLevel; import com.devonfw.tools.ide.process.ProcessContext; @@ -32,7 +33,7 @@ public class Eclipse extends IdeToolCommandlet { */ public Eclipse(IdeContext context) { - super(context, "eclipse", Set.of(TAG_JAVA, TAG_IDE)); + super(context, "eclipse", Set.of(Tag.ECLIPSE)); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/gh/Gh.java b/cli/src/main/java/com/devonfw/tools/ide/tool/gh/Gh.java index 65383ed92..f9d2af057 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/gh/Gh.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/gh/Gh.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -18,7 +19,7 @@ public class Gh extends LocalToolCommandlet { */ public Gh(IdeContext context) { - super(context, "gh", Set.of(TAG_CLOUD)); + super(context, "gh", Set.of(Tag.CLOUD)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/gradle/Gradle.java b/cli/src/main/java/com/devonfw/tools/ide/tool/gradle/Gradle.java index f0405ce14..476cc1ce8 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/gradle/Gradle.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/gradle/Gradle.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -19,7 +20,7 @@ public class Gradle extends LocalToolCommandlet { */ public Gradle(IdeContext context) { - super(context, "gradle", Set.of(TAG_JAVA, TAG_BUILD)); + super(context, "gradle", Set.of(Tag.JAVA, Tag.BUILD)); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/helm/Helm.java b/cli/src/main/java/com/devonfw/tools/ide/tool/helm/Helm.java index 1f4a2a41b..8125315df 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/helm/Helm.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/helm/Helm.java @@ -1,11 +1,12 @@ package com.devonfw.tools.ide.tool.helm; +import java.util.Set; + +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; -import java.util.Set; - /** * {@link ToolCommandlet} for Helm, the package manager for Kubernetes. */ @@ -17,7 +18,7 @@ public class Helm extends LocalToolCommandlet { */ public Helm(IdeContext context) { - super(context, "helm", Set.of(TAG_CLOUD)); + super(context, "helm", Set.of(Tag.KUBERNETES)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java index 44c2cdd3f..2cd8ec18b 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java @@ -12,6 +12,7 @@ import java.util.stream.Stream; import com.devonfw.tools.ide.cli.CliException; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.tool.LocalToolCommandlet; @@ -38,10 +39,20 @@ public abstract class IdeToolCommandlet extends LocalToolCommandlet { * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} * method. */ - public IdeToolCommandlet(IdeContext context, String tool, Set tags) { + public IdeToolCommandlet(IdeContext context, String tool, Set tags) { super(context, tool, tags); - assert (tags.contains(TAG_IDE)); + assert (hasIde(tags)); + } + + private boolean hasIde(Set tags) { + + for (Tag tag : tags) { + if (tag.isAncestorOf(Tag.IDE)) { + return true; + } + } + throw new IllegalStateException("Tags of IdeTool hat to be connected with tag IDE: " + tags); } private Map getPluginsMap() { diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/ide/PluginDescriptorImpl.java b/cli/src/main/java/com/devonfw/tools/ide/tool/ide/PluginDescriptorImpl.java index 3abf8d70c..6b32d1061 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/ide/PluginDescriptorImpl.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/ide/PluginDescriptorImpl.java @@ -4,11 +4,11 @@ import java.io.Reader; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; import java.util.Locale; import java.util.Properties; import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.log.IdeLogger; @@ -25,7 +25,7 @@ public class PluginDescriptorImpl implements PluginDescriptor { private final boolean active; - private final Set tags; + private final Set tags; /** * The constructor. @@ -36,7 +36,7 @@ public class PluginDescriptorImpl implements PluginDescriptor { * @param active the {@link #isActive() active flag}. * @param tags the {@link #getTags() tags}. */ - public PluginDescriptorImpl(String id, String name, String url, boolean active, Set tags) { + public PluginDescriptorImpl(String id, String name, String url, boolean active, Set tags) { super(); this.id = id; @@ -71,7 +71,7 @@ public boolean isActive() { } @Override - public Set getTags() { + public Set getTags() { return this.tags; } @@ -100,12 +100,7 @@ public static PluginDescriptor of(Path propertiesFile, IdeLogger logger, boolean } boolean active = getBoolean(properties, "active", "plugin_active", propertiesFile, logger); String tagsCsv = getString(properties, "tags", "plugin_tags"); - Set tags; - if ((tagsCsv == null) || tagsCsv.isBlank()) { - tags = Collections.emptySet(); - } else { - tags = Set.of(tagsCsv.split(",")); - } + Set tags = Tag.parseCsv(tagsCsv); return new PluginDescriptorImpl(id, name, url, active, tags); } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/intellij/Intellij.java b/cli/src/main/java/com/devonfw/tools/ide/tool/intellij/Intellij.java index cbab7deef..2c1f6b5cc 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/intellij/Intellij.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/intellij/Intellij.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.ide.IdeToolCommandlet; import com.devonfw.tools.ide.tool.ide.PluginDescriptor; @@ -19,7 +20,7 @@ public class Intellij extends IdeToolCommandlet { */ public Intellij(IdeContext context) { - super(context, "intellij", Set.of(TAG_JAVA, TAG_IDE)); + super(context, "intellij", Set.of(Tag.INTELLIJ)); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/java/Java.java b/cli/src/main/java/com/devonfw/tools/ide/tool/java/Java.java index e26c7308a..e40c1707c 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/java/Java.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/java/Java.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -18,7 +19,7 @@ public class Java extends LocalToolCommandlet { */ public Java(IdeContext context) { - super(context, "java", Set.of(TAG_JAVA, TAG_RUNTIME)); + super(context, "java", Set.of(Tag.JAVA, Tag.RUNTIME)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/Kotlinc.java b/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/Kotlinc.java index 744d051f0..c0d32d2bf 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/Kotlinc.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/Kotlinc.java @@ -2,12 +2,14 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; /** - * {@link ToolCommandlet} for Kotlin command-line compiler (kotlinc). + * {@link ToolCommandlet} for Kotlin command-line compiler + * (kotlinc). */ public class Kotlinc extends LocalToolCommandlet { @@ -18,6 +20,6 @@ public class Kotlinc extends LocalToolCommandlet { */ public Kotlinc(IdeContext context) { - super(context, "kotlinc", Set.of(TAG_JAVA, TAG_RUNTIME)); + super(context, "kotlinc", Set.of(Tag.KOTLIN, Tag.RUNTIME)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/KotlincNative.java b/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/KotlincNative.java index b8ed74b58..cc9073a33 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/KotlincNative.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/kotlinc/KotlincNative.java @@ -2,12 +2,14 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; /** - * {@link ToolCommandlet} for Kotlin Native (kotlincnative). + * {@link ToolCommandlet} for Kotlin Native + * (kotlincnative). */ public class KotlincNative extends LocalToolCommandlet { @@ -18,6 +20,6 @@ public class KotlincNative extends LocalToolCommandlet { */ public KotlincNative(IdeContext context) { - super(context, "kotlincnative", Set.of(TAG_JAVA, TAG_RUNTIME)); + super(context, "kotlincnative", Set.of(Tag.KOTLIN, Tag.RUNTIME)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java b/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java index 5ef339f7c..d99aa227c 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -19,7 +20,7 @@ public class Mvn extends LocalToolCommandlet { */ public Mvn(IdeContext context) { - super(context, "mvn", Set.of(TAG_JAVA, TAG_BUILD)); + super(context, "mvn", Set.of(Tag.JAVA, Tag.BUILD)); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/node/Node.java b/cli/src/main/java/com/devonfw/tools/ide/tool/node/Node.java index a3f9c976e..7d4ad94fa 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/node/Node.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/node/Node.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -18,7 +19,7 @@ public class Node extends LocalToolCommandlet { */ public Node(IdeContext context) { - super(context, "node", Set.of(TAG_RUNTIME)); + super(context, "node", Set.of(Tag.JAVA_SCRIPT, Tag.RUNTIME)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/oc/Oc.java b/cli/src/main/java/com/devonfw/tools/ide/tool/oc/Oc.java index 31a7f1b9f..527b40bbc 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/oc/Oc.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/oc/Oc.java @@ -1,11 +1,12 @@ package com.devonfw.tools.ide.tool.oc; +import java.util.Set; + +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; -import java.util.Set; - /** * {@link ToolCommandlet} for Openshift CLI. */ @@ -18,7 +19,7 @@ public class Oc extends LocalToolCommandlet { */ public Oc(IdeContext context) { - super(context, "oc", Set.of(TAG_CLOUD)); + super(context, "oc", Set.of(Tag.CLOUD)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/quarkus/Quarkus.java b/cli/src/main/java/com/devonfw/tools/ide/tool/quarkus/Quarkus.java index d135d9abc..70c8d7263 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/quarkus/Quarkus.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/quarkus/Quarkus.java @@ -1,11 +1,12 @@ package com.devonfw.tools.ide.tool.quarkus; +import java.util.Set; + +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; -import java.util.Set; - /** * {@link ToolCommandlet} for Quarkus. */ @@ -17,7 +18,7 @@ public class Quarkus extends LocalToolCommandlet { */ public Quarkus(IdeContext context) { - super(context, "quarkus", Set.of(TAG_CLOUD, TAG_FRAMEWORK)); + super(context, "quarkus", Set.of(Tag.JAVA, Tag.FRAMEWORK)); } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/terraform/Terraform.java b/cli/src/main/java/com/devonfw/tools/ide/tool/terraform/Terraform.java index 56174c0c7..745ececde 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/terraform/Terraform.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/terraform/Terraform.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -18,7 +19,7 @@ public class Terraform extends LocalToolCommandlet { */ public Terraform(IdeContext context) { - super(context, "terraform", Set.of(TAG_CLOUD, TAG_IAC)); + super(context, "terraform", Set.of(Tag.IAC)); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/vscode/Vscode.java b/cli/src/main/java/com/devonfw/tools/ide/tool/vscode/Vscode.java index a7e85da00..563a6586a 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/vscode/Vscode.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/vscode/Vscode.java @@ -2,6 +2,7 @@ import java.util.Set; +import com.devonfw.tools.ide.common.Tag; import com.devonfw.tools.ide.context.IdeContext; import com.devonfw.tools.ide.tool.LocalToolCommandlet; import com.devonfw.tools.ide.tool.ToolCommandlet; @@ -16,9 +17,9 @@ public class Vscode extends LocalToolCommandlet { * * @param context the {@link IdeContext}. */ - public Vscode (IdeContext context) { + public Vscode(IdeContext context) { - super(context, "vscode", Set.of(TAG_IDE)); + super(context, "vscode", Set.of(Tag.VS_CODE)); } @Override diff --git a/cli/src/test/java/com/devonfw/tools/ide/common/TagTest.java b/cli/src/test/java/com/devonfw/tools/ide/common/TagTest.java new file mode 100644 index 000000000..bfa7d1ce0 --- /dev/null +++ b/cli/src/test/java/com/devonfw/tools/ide/common/TagTest.java @@ -0,0 +1,151 @@ +package com.devonfw.tools.ide.common; + +import java.util.Collection; +import java.util.Set; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test of {@link Tag}. + */ +public class TagTest extends Assertions { + + /** + * Test various predefined {@link Tag}s. + */ + @Test + public void testTags() { + + checkTag(Tag.ROOT, "", null, true); + checkTag(Tag.MACHINE_LEARNING, "machine-learning", Tag.ROOT); + checkTag(Tag.ARTIFICIAL_INTELLIGENCE, "artificial-intelligence", Tag.MACHINE_LEARNING); + } + + private void checkTag(Tag tag, String id, Tag parent) { + + checkTag(tag, id, parent, false); + } + + private void checkTag(Tag tag, String id, Tag parent, boolean isAbstract) { + + assertThat(tag.getId()).isEqualTo(id); + assertThat(tag.getParent()).isSameAs(parent); + assertThat(tag.isAbstract()).isEqualTo(isAbstract); + assertThat(tag.toString()).isEqualTo(id); + } + + /** + * Test of {@link Tag#of(String)}. + */ + @Test + public void testOf() { + + checkOf(Tag.ROOT); + checkOf(Tag.MACHINE_LEARNING, "ml", "machinelearning"); + checkOf(Tag.ARTIFICIAL_INTELLIGENCE, "ai", "artificialintelligence"); + } + + private void checkOf(Tag tag, String... synonyms) { + + assertThat(Tag.of(tag.getId())).isSameAs(tag); + for (String synonym : synonyms) { + assertThat(Tag.of(synonym)).isSameAs(tag); + } + } + + /** + * Test of {@link Tag#of(String)} with new tag that do not yet exist. + */ + @Test + public void testOfNew() { + + // arrange + String id = "undefined"; + // act + Tag tag = Tag.of(id); + // assert + checkTag(tag, id, Tag.MISC); + } + + /** + * Test of {@link Tag#of(String)} with new tags that do not yet exist and given parent. + */ + @Test + public void testOfNewWithParent() { + + // arrange + String id = "brandnew"; + // act + Tag tag = Tag.of("ide/" + id); + // assert + checkTag(tag, id, Tag.IDE); + } + + /** + * Test of {@link Tag#getAll()}. + */ + @Test + public void testGetAll() { + + // act + Collection tags = Tag.getAll(); + // assert + assertThat(tags).contains(Tag.ROOT, Tag.ANDROID_STUDIO, Tag.ECLIPSE, Tag.IDE, Tag.VS_CODE); + assertThat(tags.size()).isGreaterThan(150); + } + + /** + * Test of {@link Tag#parseCsv(String)}. + */ + @Test + public void testParseCsv() { + + // arrange + String csv = " c,c++, c# "; // also test trimming + // act + Set tags = Tag.parseCsv(csv); + // assert + assertThat(tags).containsExactlyInAnyOrder(Tag.C, Tag.CPP, Tag.CS); + } + + /** + * Test of {@link Tag#parseCsv(String)} with empty CSV. + */ + @Test + public void testParseCsvEmpty() { + + assertThat(Tag.parseCsv(null)).isEmpty(); + assertThat(Tag.parseCsv("")).isEmpty(); + assertThat(Tag.parseCsv(" ")).isEmpty(); + } + + /** + * Test of {@link Tag#getParent(int)} and {@link Tag#getParentCount()}. + */ + @Test + public void testGetParents() { + + assertThat(Tag.ROOT.getParentCount()).isZero(); + assertThat(Tag.DOCUMENTATION.getParentCount()).isOne(); + assertThat(Tag.DOCUMENTATION.getParent(0)).isSameAs(Tag.ROOT); + assertThat(Tag.ASCII_DOC.getParentCount()).isEqualTo(2); + assertThat(Tag.ASCII_DOC.getParent(0)).isSameAs(Tag.FORMAT); + assertThat(Tag.ASCII_DOC.getParent(1)).isSameAs(Tag.DOCUMENTATION); + } + + /** + * Test of {@link Tag#isAncestorOf(Tag)}. + */ + @Test + public void testIsAncestorOf() { + + assertThat(Tag.QUARKUS.isAncestorOf(Tag.ROOT)).isTrue(); + assertThat(Tag.QUARKUS.isAncestorOf(Tag.DOCUMENTATION)).isFalse(); + assertThat(Tag.QUARKUS.isAncestorOf(Tag.JAVA)).isFalse(); + assertThat(Tag.QUARKUS.isAncestorOf(Tag.QUARKUS)).isFalse(); + boolean includeAdditionalParents = true; + assertThat(Tag.QUARKUS.isAncestorOf(Tag.JAVA, includeAdditionalParents)).isTrue(); + assertThat(Tag.QUARKUS.isAncestorOf(Tag.LANGUAGE, includeAdditionalParents)).isTrue(); + } +}