/**
* PermissionsEx
* Copyright (C) zml and PermissionsEx contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ninja.leaping.permissionsex.command;
import ninja.leaping.permissionsex.PermissionsEx;
import ninja.leaping.permissionsex.data.SubjectDataReference;
import ninja.leaping.permissionsex.subject.CalculatedSubject;
import ninja.leaping.permissionsex.util.Translatable;
import ninja.leaping.permissionsex.util.command.CommandContext;
import ninja.leaping.permissionsex.util.command.CommandException;
import ninja.leaping.permissionsex.util.command.CommandExecutor;
import ninja.leaping.permissionsex.util.command.Commander;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import static ninja.leaping.permissionsex.util.Translations.t;
public abstract class PermissionsExExecutor implements CommandExecutor {
protected final PermissionsEx pex;
protected PermissionsExExecutor(PermissionsEx pex) {
this.pex = pex;
}
protected <TextType> TextType formatContexts(Commander<TextType> src, Set<Map.Entry<String, String>> contexts) {
return src.fmt().hl(contexts.isEmpty() ? src.fmt().tr(t("Global")) : src.fmt().combined(contexts.toString()));
}
protected CalculatedSubject subjectOrSelf(Commander<?> src, CommandContext args) throws CommandException {
try {
if (args.hasAny("subject")) {
Map.Entry<String, String> ret = args.getOne("subject");
return pex.getSubjects(ret.getKey()).get(ret.getValue()).get();
} else {
Optional<Map.Entry<String, String>> ret = src.getSubjectIdentifier();
if (!ret.isPresent()) {
throw new CommandException(t("A subject must be provided for this command!"));
} else {
return pex.getSubjects(ret.get().getKey()).get(ret.get().getValue()).get();
}
}
} catch (InterruptedException | ExecutionException e) {
throw new CommandException(t("Unable to get subject"), e);
}
}
protected <TextType> SubjectDataReference getDataRef(Commander<TextType> src, CommandContext args, String permission) throws CommandException {
CalculatedSubject subject = subjectOrSelf(src, args);
checkSubjectPermission(src, subject.getIdentifier(), permission);
return args.hasAny("transient") ? subject.transientData() : subject.data();
}
protected void checkSubjectPermission(final Commander<?> src, Map.Entry<String, String> subject, String basePermission) throws CommandException {
if (!src.hasPermission(basePermission + '.' + subject.getKey() + '.' + subject.getValue())
&& (!subject.equals(src.getSubjectIdentifier().orElse(null)) || !src.hasPermission(basePermission + ".own"))) {
throw new CommandException(t("You do not have permission to use this command!"));
}
}
protected <TextType> void messageSubjectOnFuture(CompletableFuture<?> future, final Commander<TextType> src, final Translatable message) {
messageSubjectOnFuture(future, src, () -> message);
}
protected <TextType> void messageSubjectOnFuture(CompletableFuture<?> future, final Commander<TextType> src, final Supplier<Translatable> message) {
future.thenRun(() -> src.msg(message.get())).exceptionally(err -> {
if (err instanceof CompletionException && err.getCause() != null) {
err = err.getCause();
}
if (err instanceof RuntimeCommandException) {
src.error(((RuntimeCommandException) err).getTranslatedMessage());
} else {
src.error(t("Error (%s) occurred while performing command task! Please see console for details: %s", err.getClass().getSimpleName(), err.getMessage()));
pex.getLogger().error(t("Error occurred while executing command for user %s", src.getName()), err);
}
return null;
});
}
static class RuntimeCommandException extends RuntimeException {
private final Translatable message;
RuntimeCommandException(Translatable message) {
super(message.getUntranslated());
this.message = message;
}
public Translatable getTranslatedMessage() {
return this.message;
}
}
}