Skip to content

Commit

Permalink
#438: add ValidationState (#569)
Browse files Browse the repository at this point in the history
  • Loading branch information
slskiba authored Sep 9, 2024
1 parent a7f892a commit bd82ae0
Show file tree
Hide file tree
Showing 21 changed files with 243 additions and 93 deletions.
17 changes: 6 additions & 11 deletions cli/src/main/java/com/devonfw/tools/ide/commandlet/Commandlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import com.devonfw.tools.ide.property.Property;
import com.devonfw.tools.ide.tool.ToolCommandlet;
import com.devonfw.tools.ide.tool.plugin.PluginDescriptor;
import com.devonfw.tools.ide.validation.ValidationResult;
import com.devonfw.tools.ide.validation.ValidationState;
import com.devonfw.tools.ide.version.VersionIdentifier;

/**
Expand Down Expand Up @@ -219,20 +221,13 @@ public boolean isProcessableOutput() {
* @return {@code true} if this {@link Commandlet} is the valid candidate to be {@link #run()}, {@code false} otherwise.
* @see Property#validate()
*/
public boolean validate() {

public ValidationResult validate() {
ValidationState state = new ValidationState(null);
// avoid validation exception if not a candidate to be run.
for (Property<?> property : this.propertiesList) {
if (property.isRequired() && (property.getValue() == null)) {
return false;
}
}
for (Property<?> property : this.propertiesList) {
if (!property.validate()) {
return false;
}
state.add(property.validate());
}
return true;
return state;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.devonfw.tools.ide.property.ToolProperty;
import com.devonfw.tools.ide.property.VersionProperty;
import com.devonfw.tools.ide.tool.ToolCommandlet;
import com.devonfw.tools.ide.validation.ValidationState;
import com.devonfw.tools.ide.version.VersionIdentifier;

/**
Expand All @@ -29,7 +30,12 @@ public InstallCommandlet(IdeContext context) {
super(context);
addKeyword(getName());
this.tool = add(new ToolProperty("", true, "tool"));
this.version = add(new VersionProperty("", false, "version"));
this.version = add(new VersionProperty("", false, "version",
(v, state) -> {
if (!v.isValid()) {
state.addErrorMessage("Given version " + v + " is not a valid version");
}
}));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,6 @@ private boolean apply(CliArgument argument, Commandlet commandlet) {
}
currentArgument = currentArgument.getNext(!endOpts);
}
return commandlet.validate();
return commandlet.validate().isValid();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
import com.devonfw.tools.ide.step.Step;
import com.devonfw.tools.ide.step.StepImpl;
import com.devonfw.tools.ide.url.model.UrlMetadata;
import com.devonfw.tools.ide.validation.ValidationResult;
import com.devonfw.tools.ide.validation.ValidationState;
import com.devonfw.tools.ide.variable.IdeVariables;

/**
Expand Down Expand Up @@ -774,25 +776,28 @@ public int run(CliArguments arguments) {
if (!current.isEnd()) {
String keyword = current.get();
firstCandidate = this.commandletManager.getCommandletByFirstKeyword(keyword);
boolean matches;
ValidationResult firstResult = null;
if (firstCandidate != null) {
matches = applyAndRun(arguments.copy(), firstCandidate);
if (matches) {
firstResult = applyAndRun(arguments.copy(), firstCandidate);
if (firstResult.isValid()) {
supressStepSuccess = firstCandidate.isSuppressStepSuccess();
step.success();
return ProcessResult.SUCCESS;
}
}
for (Commandlet cmd : this.commandletManager.getCommandlets()) {
if (cmd != firstCandidate) {
matches = applyAndRun(arguments.copy(), cmd);
if (matches) {
ValidationResult result = applyAndRun(arguments.copy(), cmd);
if (result.isValid()) {
supressStepSuccess = cmd.isSuppressStepSuccess();
step.success();
return ProcessResult.SUCCESS;
}
}
}
if (firstResult != null) {
throw new CliException(firstResult.getErrorMessage());
}
step.error("Invalid arguments: {}", current.getArgs());
}

Expand All @@ -818,15 +823,15 @@ public int run(CliArguments arguments) {
* @return {@code true} if the given {@link Commandlet} matched and did {@link Commandlet#run() run} successfully, {@code false} otherwise (the
* {@link Commandlet} did not match and we have to try a different candidate).
*/
private boolean applyAndRun(CliArguments arguments, Commandlet cmd) {
private ValidationResult applyAndRun(CliArguments arguments, Commandlet cmd) {

cmd.clearProperties();

boolean matches = apply(arguments, cmd, null);
if (matches) {
matches = cmd.validate();
ValidationResult result = apply(arguments, cmd, null);
if (result.isValid()) {
result = cmd.validate();
}
if (matches) {
if (result.isValid()) {
debug("Running commandlet {}", cmd);
if (cmd.isIdeHomeRequired() && (this.ideHome == null)) {
throw new CliException(getMessageIdeHomeNotFound(), ProcessResult.NO_IDE_HOME);
Expand Down Expand Up @@ -868,7 +873,7 @@ private boolean applyAndRun(CliArguments arguments, Commandlet cmd) {
} else {
trace("Commandlet did not match");
}
return matches;
return result;
}

/**
Expand Down Expand Up @@ -914,7 +919,7 @@ private boolean completeCommandlet(CliArguments arguments, Commandlet cmd, Compl
if (cmd.isIdeHomeRequired() && (this.ideHome == null)) {
return false;
} else {
return apply(arguments.copy(), cmd, collector);
return apply(arguments.copy(), cmd, collector).isValid();
}
}

Expand All @@ -927,7 +932,7 @@ private boolean completeCommandlet(CliArguments arguments, Commandlet cmd, Compl
* @return {@code true} if the given {@link Commandlet} matches to the given {@link CliArgument}(s) and those have been applied (set in the {@link Commandlet}
* and {@link Commandlet#validate() validated}), {@code false} otherwise (the {@link Commandlet} did not match and we have to try a different candidate).
*/
public boolean apply(CliArguments arguments, Commandlet cmd, CompletionCandidateCollector collector) {
public ValidationResult apply(CliArguments arguments, Commandlet cmd, CompletionCandidateCollector collector) {

trace("Trying to match arguments to commandlet {}", cmd.getName());
CliArgument currentArgument = arguments.current();
Expand All @@ -952,7 +957,9 @@ public boolean apply(CliArguments arguments, Commandlet cmd, CompletionCandidate
}
if (currentProperty == null) {
trace("No option or next value found");
return false;
ValidationState state = new ValidationState(null);
state.addErrorMessage("No matching property found");
return state;
}
trace("Next property candidate to match argument is {}", currentProperty);
if (currentProperty == property) {
Expand All @@ -969,11 +976,13 @@ public boolean apply(CliArguments arguments, Commandlet cmd, CompletionCandidate
}
boolean matches = currentProperty.apply(arguments, this, cmd, collector);
if (!matches || currentArgument.isCompletion()) {
return false;
ValidationState state = new ValidationState(null);
state.addErrorMessage("No matching property found");
return state;
}
currentArgument = arguments.current();
}
return true;
return new ValidationState(null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.devonfw.tools.ide.property;

import java.util.function.Consumer;

import com.devonfw.tools.ide.commandlet.Commandlet;
import com.devonfw.tools.ide.completion.CompletionCandidateCollector;
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.validation.PropertyValidator;

/**
* {@link Property} with {@link #getValueType() value type} {@link Commandlet}.
Expand All @@ -29,9 +28,9 @@ public CommandletProperty(String name, boolean required, String alias) {
* @param name the {@link #getName() property name}.
* @param required the {@link #isRequired() required flag}.
* @param alias the {@link #getAlias() property alias}.
* @param validator the {@link Consumer} used to {@link #validate() validate} the {@link #getValue() value}.
* @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
*/
public CommandletProperty(String name, boolean required, String alias, Consumer<Commandlet> validator) {
public CommandletProperty(String name, boolean required, String alias, PropertyValidator<Commandlet> validator) {

super(name, required, alias, false, validator);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.devonfw.tools.ide.property;

import java.util.function.Consumer;

import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.validation.PropertyValidator;

public class EditionProperty extends Property<String> {

Expand All @@ -24,9 +23,9 @@ public EditionProperty(String name, boolean required, String alias) {
* @param name the {@link #getName() property name}.
* @param required the {@link #isRequired() required flag}.
* @param alias the {@link #getAlias() property alias}.
* @param validator the {@link Consumer} used to {@link #validate() validate} the {@link #getValue() value}.
* @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
*/
public EditionProperty(String name, boolean required, String alias, Consumer<String> validator) {
public EditionProperty(String name, boolean required, String alias, PropertyValidator<String> validator) {

super(name, required, alias, false, validator);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.devonfw.tools.ide.property;

import java.nio.file.Path;
import java.util.function.Consumer;

import com.devonfw.tools.ide.validation.PropertyValidator;

/**
* {@link PathProperty} for a file.
Expand All @@ -28,9 +29,9 @@ public FileProperty(String name, boolean required, String alias, boolean mustExi
* @param required the {@link #isRequired() required flag}.
* @param alias the {@link #getAlias() property alias}.
* @param mustExist the {@link #isPathRequiredToExist() required to exist flag}.
* @param validator the {@link Consumer} used to {@link #validate() validate} the {@link #getValue() value}.
* @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
*/
public FileProperty(String name, boolean required, String alias, boolean mustExist, Consumer<Path> validator) {
public FileProperty(String name, boolean required, String alias, boolean mustExist, PropertyValidator<Path> validator) {

super(name, required, alias, mustExist, validator);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.devonfw.tools.ide.property;

import java.nio.file.Path;
import java.util.function.Consumer;

import com.devonfw.tools.ide.validation.PropertyValidator;

/**
* {@link PathProperty} for a folder (directory).
Expand All @@ -28,9 +29,9 @@ public FolderProperty(String name, boolean required, String alias, boolean mustE
* @param required the {@link #isRequired() required flag}.
* @param alias the {@link #getAlias() property alias}.
* @param mustExist the {@link #isPathRequiredToExist() required to exist flag}.
* @param validator the {@link Consumer} used to {@link #validate() validate} the {@link #getValue() value}.
* @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
*/
public FolderProperty(String name, boolean required, String alias, boolean mustExist, Consumer<Path> validator) {
public FolderProperty(String name, boolean required, String alias, boolean mustExist, PropertyValidator<Path> validator) {

super(name, required, alias, mustExist, validator);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import java.util.Arrays;
import java.util.Locale;
import java.util.function.Consumer;

import com.devonfw.tools.ide.commandlet.Commandlet;
import com.devonfw.tools.ide.completion.CompletionCandidateCollector;
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.validation.PropertyValidator;

/**
* {@link Property} with {@link Locale} as {@link #getValueType() value type}.
Expand All @@ -33,9 +33,9 @@ public LocaleProperty(String name, boolean required, String alias) {
* @param name the {@link #getName() property name}.
* @param required the {@link #isRequired() required flag}.
* @param alias the {@link #getAlias() property alias}.
* @param validator the {@link Consumer} used to {@link #validate() validate} the {@link #getValue() value}.
* @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
*/
public LocaleProperty(String name, boolean required, String alias, Consumer<Locale> validator) {
public LocaleProperty(String name, boolean required, String alias, PropertyValidator<Locale> validator) {

super(name, required, alias, false, validator);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.devonfw.tools.ide.property;

import java.util.function.Consumer;

import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.validation.PropertyValidator;

/**
* {@link Property} with {@link #getValueType() value type} {@link Long}.
Expand All @@ -27,9 +26,9 @@ public NumberProperty(String name, boolean required, String alias) {
* @param name the {@link #getName() property name}.
* @param required the {@link #isRequired() required flag}.
* @param alias the {@link #getAlias() property alias}.
* @param validator the {@link Consumer} used to {@link #validate() validate} the {@link #getValue() value}.
* @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
*/
public NumberProperty(String name, boolean required, String alias, Consumer<Long> validator) {
public NumberProperty(String name, boolean required, String alias, PropertyValidator<Long> validator) {

super(name, required, alias, false, validator);
}
Expand Down
Loading

0 comments on commit bd82ae0

Please sign in to comment.