package tc.oc.api.minecraft.model; import java.util.List; import java.util.Optional; import javax.annotation.Nullable; import javax.inject.Inject; import com.google.gson.Gson; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.NestedCommand; import tc.oc.api.docs.virtual.Model; import tc.oc.minecraft.scheduler.SyncExecutor; import tc.oc.api.model.ModelMeta; import tc.oc.api.model.ModelRegistry; import tc.oc.api.serialization.Pretty; import tc.oc.api.util.Permissions; import tc.oc.commons.core.chat.Component; import tc.oc.commons.core.commands.Commands; import tc.oc.commons.core.commands.NestedCommands; import tc.oc.commons.core.formatting.StringUtils; import tc.oc.minecraft.api.command.CommandSender; class ModelCommands implements NestedCommands { public static class Parent implements Commands { @Command( aliases = "model", desc = "Commands related to API models", min = 1, max = -1 ) @NestedCommand(ModelCommands.class) @CommandPermissions(Permissions.DEVELOPER) public void model(CommandContext args, CommandSender sender) throws CommandException {} } private final ModelRegistry registry; private final Gson prettyGson; private final SyncExecutor syncExecutor; @Inject ModelCommands(ModelRegistry registry, @Pretty Gson prettyGson, SyncExecutor syncExecutor) { this.registry = registry; this.prettyGson = prettyGson; this.syncExecutor = syncExecutor; } private List<String> completeModel(String name) { return StringUtils.complete(name, registry.all() .stream() .filter(meta -> meta.store().isPresent()) .map(ModelMeta::name)); } private ModelMeta<?, ?> parseModel(@Nullable String name) throws CommandException { if(name == null) return null; for(ModelMeta<?, ?> meta : registry.all()) { if(meta.store().isPresent() && name.equalsIgnoreCase(meta.name())) { return meta; } } throw new CommandException("Unknown model '" + name + "'"); } @Command( aliases = "list", desc = "List all stored models", max = 0 ) public void list(CommandContext args, CommandSender sender) throws CommandException { for(ModelMeta<?, ?> meta : registry.all()) { if(meta.store().isPresent()) { sender.sendMessage(new Component(meta.name() + " (" + meta.store().get().count() + ")")); } } } @Command( aliases = "all", usage = "<model>", desc = "List all stored instances of a model", min = 1, max = 1 ) public List<String> all(CommandContext args, CommandSender sender) throws CommandException { final String modelName = args.getString(0, ""); if(args.getSuggestionContext() != null) { return completeModel(modelName); } for(Model doc : parseModel(modelName).store().get().set()) { sender.sendMessage(new Component(doc._id() + " " + doc.toShortString())); } return null; } @Command( aliases = "show", usage = "<model> <id>", desc = "Show the contents of a single document", min = 2, max = 2 ) public List<String> show(CommandContext args, CommandSender sender) throws CommandException { final String modelName = args.getString(0, ""); final String id = args.getString(1, ""); if(args.getSuggestionContext() != null) { switch(args.getSuggestionContext().getIndex()) { case 0: return completeModel(modelName); case 1: final ModelMeta<?, ?> meta = parseModel(modelName); return StringUtils.complete(id, meta.store().get().set().stream().map(Model::_id)); default: return null; } } final ModelMeta<?, ?> meta = parseModel(modelName); final Optional<?> doc = meta.store().get().tryId(id); if(!doc.isPresent()) { throw new CommandException("No " + meta.name() + " with _id " + id); } sender.sendMessage(new Component(prettyGson.toJson(doc.get()))); return null; } @Command( aliases = "refresh", usage = "<model>", desc = "Refresh a model store from the API", min = 1, max = 1 ) public List<String> refresh(CommandContext args, CommandSender sender) throws CommandException { final String modelName = args.getString(0, ""); if(args.getSuggestionContext() != null) { return completeModel(modelName); } final ModelMeta<?, ?> model = parseModel(modelName); sender.sendMessage("Refreshing model " + model.name() + "..."); syncExecutor.callback( model.store().get().refreshAll(), response -> sender.sendMessage("Refreshed " + response.documents().size() + " " + model.name() + " document(s)") ); return null; } }