Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.microsoft.azure.toolkit.lib.common.action.Action Maven / Gradle / Ivy
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
package com.microsoft.azure.toolkit.lib.common.action;
import com.microsoft.azure.toolkit.lib.account.IAccount;
import com.microsoft.azure.toolkit.lib.common.bundle.AzureString;
import com.microsoft.azure.toolkit.lib.common.model.AbstractAzResource;
import com.microsoft.azure.toolkit.lib.common.operation.OperationBase;
import com.microsoft.azure.toolkit.lib.common.operation.OperationBundle;
import com.microsoft.azure.toolkit.lib.common.view.IView;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.PropertyKey;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@SuppressWarnings({"unused", "UnresolvedPropertyKey"})
@Slf4j
@Accessors(chain = true)
public class Action implements Cloneable {
public static final String SOURCE = "ACTION_SOURCE";
public static final String PLACE = "action_place";
public static final String EMPTY_PLACE = "empty";
public static final String RESOURCE_TYPE = "resourceType";
public static final Id AUTHENTICATE = Id.of("user/account.authenticate");
public static final Id> REQUIRE_AUTH = Id.of("user/common.authorize_action");
public static final Id TRY_AZURE = Action.Id.of("user/account.try_azure");
public static final Id SELECT_SUBS = Action.Id.of("user/account.select_subs");
public static final Id OPEN_AZURE_SETTINGS = Action.Id.of("user/common.open_azure_settings");
public static final Id DISABLE_AUTH_CACHE = Action.Id.of("user/account.disable_auth_cache");
public static final Action.Id SIGN_IN = Action.Id.of("user/common.sign_in");
public static final Action.Id SIGN_OUT = Action.Id.of("user/common.sign_out");
public static final Action.Id OPEN_URL = Action.Id.of("user/common.open_url.url");
public static final String COMMON_PLACE = "common";
@Getter
@Nonnull
private final Id id;
@Nonnull
private List, BiConsumer>> handlers = new ArrayList<>();
protected D target;
@Nonnull
Predicate enableWhen = o -> true;
BiPredicate visibleWhen = (o, place) -> true;
Function iconProvider;
Function labelProvider;
Function titleProvider;
@Nonnull
List> titleParamProviders = new ArrayList<>();
Function sourceProvider;
Predicate authRequiredProvider = Action::isAuthRequiredForAzureResource;
/**
* shortcuts for this action.
* 1. directly bound to this action if it's IDE-specific type of shortcuts (e.g. {@code ShortcutSet} in IntelliJ).
* 2. interpreted into native shortcuts first and then bound to this action if it's {@code String[]/String} (e.g. {@code "alt X"}).
* 3. copy shortcuts from actions specified by this action id and then bound to this action if it's {@link Id} of another action.
*/
@Setter
@Getter
private Object shortcut;
public Action(@Nonnull Id id) {
this.id = id;
}
public IView.Label getView(D s) {
return getView(s, COMMON_PLACE);
}
@Nonnull
public IView.Label getView(D s, final String place) {
final ActionInstance instance = this.instantiate(s, null);
return instance.getView(place);
}
/**
* perform asynchronously
*/
public void handle(D s) {
this.handle(s, null);
}
/**
* perform asynchronously
*/
public void handle(D s, Object e) {
final ActionInstance instance = this.instantiate(s, e);
instance.performAsync();
}
/**
* perform asynchronously
*/
public void handleSync(D s) {
this.handleSync(s, null);
}
/**
* perform asynchronously
*/
public void handleSync(D s, Object e) {
final ActionInstance instance = this.instantiate(s, e);
instance.perform();
}
public Action enableWhen(@Nonnull Predicate enableWhen) {
this.enableWhen = enableWhen;
return this;
}
public Action visibleWhen(@Nonnull Predicate visibleWhen) {
this.visibleWhen = (object, ignore) -> visibleWhen.test(object);
return this;
}
public Action visibleWhen(@Nonnull BiPredicate visibleWhen) {
this.visibleWhen = visibleWhen;
return this;
}
public Action withLabel(@Nonnull final String label) {
this.labelProvider = (any) -> label;
return this;
}
public Action withLabel(@Nonnull final Function labelProvider) {
this.labelProvider = labelProvider;
return this;
}
public Action withIcon(@Nonnull final String icon) {
this.iconProvider = (any) -> icon;
return this;
}
public Action withIcon(@Nonnull final Function iconProvider) {
this.iconProvider = iconProvider;
return this;
}
public Action withTitle(@Nonnull final AzureString title) {
this.titleProvider = (any) -> title;
return this;
}
public Action withShortcut(@Nonnull final Object shortcut) {
this.shortcut = shortcut;
return this;
}
public Action withHandler(@Nonnull Consumer handler) {
this.handlers.add(Pair.of((d, e) -> true, (d, e) -> handler.accept(d)));
return this;
}
public Action withHandler(@Nonnull BiConsumer handler) {
this.handlers.add(Pair.of((d, e) -> true, handler));
return this;
}
public Action withHandler(@Nonnull Predicate condition, @Nonnull Consumer handler) {
this.handlers.add(Pair.of((d, e) -> condition.test(d), (d, e) -> handler.accept(d)));
return this;
}
public Action withHandler(@Nonnull BiPredicate condition, @Nonnull BiConsumer handler) {
this.handlers.add(Pair.of(condition, handler));
return this;
}
public Action withAuthRequired(boolean authRequired) {
this.authRequiredProvider = ignore -> authRequired;
return this;
}
public Action withAuthRequired(@Nonnull Predicate authRequiredProvider) {
this.authRequiredProvider = authRequiredProvider;
return this;
}
public Action withIdParam(@Nonnull final String titleParam) {
this.titleParamProviders.add((d) -> titleParam);
return this;
}
public Action withIdParam(@Nonnull final Function titleParamProvider) {
this.titleParamProviders.add(titleParamProvider);
return this;
}
public Action withSource(@Nonnull final Object source) {
this.sourceProvider = (any) -> source;
return this;
}
public Action withSource(@Nonnull final Function sourceProvider) {
this.sourceProvider = sourceProvider;
return this;
}
@Nullable
@SuppressWarnings("unchecked")
BiConsumer getHandler(D s, Object e) {
if (!this.visibleWhen.test(s, COMMON_PLACE) && !this.enableWhen.test(s)) {
return null;
}
for (int i = this.handlers.size() - 1; i >= 0; i--) {
final Pair, BiConsumer> p = this.handlers.get(i);
final BiPredicate condition = (BiPredicate) p.getKey();
final BiConsumer handler = (BiConsumer) p.getValue();
try {
if (condition.test(s, e)) {
return handler;
}
} catch (final Exception ignored) {
}
}
return null;
}
public Action bind(D s) { // TODO: remove this method and use `instantiate` instead
try {
// noinspection unchecked
final Action clone = (Action) this.clone();
clone.handlers = new ArrayList<>(this.handlers);
clone.titleParamProviders = new ArrayList<>(this.titleParamProviders);
clone.target = s;
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Nonnull
public ActionInstance instantiate(D s) {
return this.instantiate(s, null);
}
@Nonnull
public ActionInstance instantiate(D s, Object event) {
final D target = Optional.ofNullable(this.target).orElse(s);
return new ActionInstance<>(this, target, event);
}
public void register(AzureActionManager am) {
am.registerAction(this);
}
@Override
public String toString() {
return String.format("Action {id:'%s', bindTo: %s}", this.getId(), this.target);
}
@Getter
public static class Id extends OperationBase.Id {
@Nonnull
private final String id;
private Id(@Nonnull String id) {
super(id);
this.id = id;
}
public static Id of(@PropertyKey(resourceBundle = OperationBundle.BUNDLE) @Nonnull String id) {
assert StringUtils.isNotBlank(id) : "action id can not be blank";
return new Id<>(id);
}
public String toString() {
return id;
}
}
@Getter
@RequiredArgsConstructor
@AllArgsConstructor
public static class View implements IView.Label {
public static View INVISIBLE = new View("", "", false, false, null);
@Nonnull
private final String label;
private final String iconPath;
private final boolean enabled;
private boolean visible = true;
@Nullable
private AzureString title;
public View(@Nonnull String label, String iconPath, boolean enabled, @Nullable AzureString title) {
this(label, iconPath, enabled, true, title);
}
@Override
public String getDescription() {
return Optional.ofNullable(this.title).map(AzureString::toString).orElse(null);
}
@Override
public void dispose() {
}
}
public static Action retryFromFailure(@Nonnull Runnable handler) {
return new Action<>(Id.of("user/common.retry"))
.withHandler((v) -> handler.run())
.withLabel("Retry");
}
public static Boolean isAuthRequiredForAzureResource(@Nullable final D resource) {
return resource instanceof AbstractAzResource && ((AbstractAzResource, ?, ?>) resource).isAuthRequired();
}
}