/**
* 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 com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import ninja.leaping.permissionsex.PermissionsEx;
import ninja.leaping.permissionsex.data.SubjectCache;
import ninja.leaping.permissionsex.util.GuavaStartsWithPredicate;
import ninja.leaping.permissionsex.util.Util;
import ninja.leaping.permissionsex.util.command.ChildCommands;
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.CommandSpec;
import ninja.leaping.permissionsex.util.command.Commander;
import ninja.leaping.permissionsex.util.command.args.CommandElement;
import javax.annotation.Nullable;
import java.util.Set;
import java.util.regex.Pattern;
import static ninja.leaping.permissionsex.util.Translations.t;
import static ninja.leaping.permissionsex.util.command.args.GameArguments.*;
import static ninja.leaping.permissionsex.util.command.args.GenericArguments.*;
/**
* Commands used by PermissionsEx
*/
public class PermissionsExCommands {
public static CommandSpec createRootCommand(final PermissionsEx pex) {
final Set<CommandSpec> childrenList = ImmutableSet.<CommandSpec>builder()
.addAll(pex.getImplementationCommands())
.add(getDebugToggleCommand(pex))
.add(RankingCommands.getRankingCommand(pex))
.add(getImportCommand(pex))
.add(getReloadCommand(pex))
.build();
final CommandElement children = ChildCommands.args(childrenList.toArray(new CommandSpec[childrenList.size()]));
final CommandElement subjectChildren = ChildCommands.args(OptionCommands.getOptionCommand(pex),
PermissionsCommands.getPermissionCommand(pex),
PermissionsCommands.getPermissionDefaultCommand(pex),
InfoCommand.getInfoCommand(pex),
ParentCommands.getParentCommand(pex),
DeleteCommand.getDeleteCommand(pex));
return CommandSpec.builder()
.setAliases("pex", "permissionsex", "permissions")
.setDescription(t("Commands for PermissionsEx"))
.setArguments(optional(
firstParsing(
children,
Util.contextTransientFlags()
.buildWith(seq(subject(t("subject"), pex), subjectChildren)),
flags()
.flag("-transient")
.buildWith(seq(subjectType(t("subject-type"), pex), literal(t("list"), "list"), optional(string(t("filter")))))
)
)
)
.setExecutor(new CommandExecutor() {
@Override
public <TextType> void execute(final Commander<TextType> src, CommandContext args) throws CommandException {
if (args.hasAny("list")) {
final String subjectType = args.getOne("subject-type");
args.checkPermission(src, "permissionsex.command.list." + subjectType);
SubjectCache cache = args.hasAny("transient") ? pex.getSubjects(subjectType).transientData() : pex.getSubjects(subjectType).persistentData();
Iterable<String> iter = cache.getAllIdentifiers();
if (args.hasAny("filter")) {
iter = Iterables.filter(iter, new GuavaStartsWithPredicate(args.<String>getOne("filter")));
}
src.msgPaginated(t("%s subjects", subjectType), t("All subjects of type %s", subjectType), Iterables.transform(iter, new Function<String, TextType>() {
@Nullable
@Override
public TextType apply(String input) {
return src.fmt().subject(Maps.immutableEntry(subjectType, input));
}
}));
} else if (args.hasAny(subjectChildren.getKey().getUntranslated())) {
ChildCommands.executor(subjectChildren).execute(src, args);
} else if (args.hasAny(children.getKey().getUntranslated())) {
ChildCommands.executor(children).execute(src, args);
} else {
src.msg(src.fmt().combined("PermissionsEx ", src.fmt().hl(src.fmt().combined("v", pex.getVersion()))));
src.msg(args.getSpec().getUsage(src));
}
}
})
.build();
}
private static CommandSpec getDebugToggleCommand(final PermissionsEx pex) {
return CommandSpec.builder()
.setAliases("debug", "d")
.setDescription(t("Toggle debug mode"))
.setPermission("permissionsex.debug")
.setArguments(optional(string(t("filter"))))
.setExecutor(new CommandExecutor() {
@Override
public <TextType> void execute(Commander<TextType> src, CommandContext args) throws CommandException {
boolean debugEnabled = !pex.hasDebugMode();
String filter = args.getOne("filter");
if (filter != null) {
pex.setDebugMode(debugEnabled, Pattern.compile(filter));
src.msg(t("Debug mode enabled: %s with filter %s", src.fmt().booleanVal(debugEnabled), src.fmt().hl(src.fmt().combined(filter))));
} else {
pex.setDebugMode(debugEnabled);
src.msg(t("Debug mode enabled: %s", src.fmt().booleanVal(debugEnabled)));
}
}
})
.build();
}
private static CommandSpec getImportCommand(final PermissionsEx pex) {
return CommandSpec.builder()
.setAliases("import")
.setDescription(t("Import data into the current backend from another"))
.setArguments(string(t("backend")))
.setPermission("permissionsex.import")
.setExecutor(new PermissionsExExecutor(pex) {
@Override
public <TextType> void execute(Commander<TextType> src, CommandContext args) throws CommandException {
messageSubjectOnFuture(pex.importDataFrom(args.<String>getOne("backend")), src, t("Successfully imported data from backend %s into current backend", args.<String>getOne("backend")));
}
})
.build();
}
private static CommandSpec getReloadCommand(final PermissionsEx pex) {
return CommandSpec.builder()
.setAliases("reload", "rel")
.setDescription(t("Reload the PermissionsEx configuration"))
.setPermission("permissionsex.reload")
.setExecutor(new CommandExecutor() {
@Override
public <TextType> void execute(final Commander<TextType> src, CommandContext args) throws CommandException {
src.msg(t("Reloading PermissionsEx"));
pex.reload().thenRun(() -> {
src.msg(t("The reload was successful"));
}).exceptionally(t -> {
src.error(t("An error occurred while reloading PEX: %s\n " +
"Please see the server console for details", t.getLocalizedMessage()));
pex.getLogger().error(t("An error occurred while reloading PEX (triggered by %s's command): %s",
src.getName(), t.getLocalizedMessage()), t);
return null;
});
}
})
.build();
}
}