From 95b6e6dcb14f4d281da009e049090f7e86220871 Mon Sep 17 00:00:00 2001 From: Pavel Date: Tue, 8 Oct 2024 08:30:30 -0400 Subject: [PATCH] Traversing class hierarchy for mixins subcommands parentcommands annot --- .../nasdanika/cli/MixInCapabilityFactory.java | 33 +++++++++++++------ .../cli/SubCommandCapabilityFactory.java | 30 +++++++++++------ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/cli/src/main/java/org/nasdanika/cli/MixInCapabilityFactory.java b/cli/src/main/java/org/nasdanika/cli/MixInCapabilityFactory.java index 3e60bcc2..2c0f949e 100644 --- a/cli/src/main/java/org/nasdanika/cli/MixInCapabilityFactory.java +++ b/cli/src/main/java/org/nasdanika/cli/MixInCapabilityFactory.java @@ -2,6 +2,7 @@ import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -9,6 +10,7 @@ import org.nasdanika.capability.ServiceCapabilityFactory; import org.nasdanika.common.Adaptable; import org.nasdanika.common.ProgressMonitor; +import org.nasdanika.common.Util; import picocli.CommandLine; @@ -51,22 +53,33 @@ protected boolean match(List commandPath) { CommandLine parent = commandPath.get(commandPath.size() - 1); Object userObject = parent.getCommandSpec().userObject(); if (userObject != null) { - MixIns mixInsAnnotation = userObject.getClass().getAnnotation(MixIns.class); Class mixInType = getMixInType(); - if (mixInsAnnotation != null && mixInType != null) { - for (Class at: mixInsAnnotation.value()) { - if (at.isAssignableFrom(mixInType)) { - return true; + if (mixInType != null) { + List mixInsAnnotations = Util.lineage(userObject.getClass()) + .stream() + .map(c -> c.getAnnotation(MixIns.class)) + .filter(Objects::nonNull) + .toList(); + for (MixIns mixInsAnnotation: mixInsAnnotations) { + List> lineage = Util.lineage(mixInType); + for (Class at: mixInsAnnotation.value()) { + for (Class le: lineage) { + if (at.isAssignableFrom(le)) { + return true; + } + } } } } if (mixInType != null) { - ParentCommands parentCommands = mixInType.getAnnotation(ParentCommands.class); - if (parentCommands != null) { - for (Class pt: parentCommands.value()) { - if (Adaptable.adaptTo(userObject, pt) != null) { - return true; + for (Class le: Util.lineage(mixInType)) { + ParentCommands parentCommands = le.getAnnotation(ParentCommands.class); + if (parentCommands != null) { + for (Class pt: parentCommands.value()) { + if (Adaptable.adaptTo(userObject, pt) != null) { + return true; + } } } } diff --git a/cli/src/main/java/org/nasdanika/cli/SubCommandCapabilityFactory.java b/cli/src/main/java/org/nasdanika/cli/SubCommandCapabilityFactory.java index 9308b978..905ae648 100644 --- a/cli/src/main/java/org/nasdanika/cli/SubCommandCapabilityFactory.java +++ b/cli/src/main/java/org/nasdanika/cli/SubCommandCapabilityFactory.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -217,22 +218,31 @@ protected boolean match(List parentPath) { CommandLine parent = parentPath.get(parentPath.size() - 1); Object userObject = parent.getCommandSpec().userObject(); if (userObject != null) { - SubCommands subCommandsAnnotation = userObject.getClass().getAnnotation(SubCommands.class); Class commandType = getCommandType(); - if (subCommandsAnnotation != null && commandType != null) { - for (Class at: subCommandsAnnotation.value()) { - if (at.isAssignableFrom(commandType)) { - return true; + if (commandType != null) { + List subCommandsAnnotations = Util.lineage(userObject.getClass()) + .stream() + .map(c -> c.getAnnotation(SubCommands.class)) + .filter(Objects::nonNull) + .toList(); + + for (SubCommands subCommandsAnnotation: subCommandsAnnotations) { + for (Class at: subCommandsAnnotation.value()) { + if (at.isAssignableFrom(commandType)) { + return true; + } } } } if (commandType != null) { - ParentCommands parentCommands = commandType.getAnnotation(ParentCommands.class); - if (parentCommands != null) { - for (Class pt: parentCommands.value()) { - if (Adaptable.adaptTo(userObject, pt) != null) { - return true; + for (Class le: Util.lineage(commandType)) { + ParentCommands parentCommands = le.getAnnotation(ParentCommands.class); + if (parentCommands != null) { + for (Class pt: parentCommands.value()) { + if (Adaptable.adaptTo(userObject, pt) != null) { + return true; + } } } }