Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support nested tables #104

Open
rmannibucau opened this issue Apr 4, 2022 · 0 comments
Open

Support nested tables #104

rmannibucau opened this issue Apr 4, 2022 · 0 comments

Comments

@rmannibucau
Copy link
Contributor

rmannibucau commented Apr 4, 2022

Right now to support nested table we must either reimplement it or reuse TableInterceptor with some plumbing:

@Command
@ApplicationScoped
public class Commands {
    @Inject
    private JiraService jira;

    @Table(border = asciiSeparated)
    @Command(value = "list-projects")
    public List<FormattedProject> listProjects(@Option("jira-login") final JiraService.JiraLogin login,
                                                                       @Option("jira-client") final JiraService.JiraClient configuration) {
        final var formatter = new TableInterceptor();
        return jira.findProjectsWithTasks(login, configuration).stream()
                .map(p -> new FormattedProject(p.id(), p.label(), asTable(formatter, p.tasks())))
                .collect(toList());
    }

    @Table(border = asciiSeparated)
    private String asTable(final TableInterceptor formatter, final List<JiraService.Task> tasks) {
        final var formatted = formatter.intercept(new CrestContext() {
            @Override
            public Object proceed() {
                return tasks;
            }

            @Override
            public Method getMethod() {
                try {
                    return Commands.class.getDeclaredMethod("asTable", TableInterceptor.class, List.class);
                } catch (final NoSuchMethodException e) {
                    throw new IllegalStateException(e);
                }
            }

            @Override
            public List<Object> getParameters() {
                return List.of();
            }

            @Override
            public String getName() {
                return "formatAsTable";
            }

            @Override
            public List<ParameterMetadata> getParameterMetadata() {
                return List.of();
            }
        });
        if (formatted instanceof PrintOutput po) {
            final var out = new ByteArrayOutputStream();
            try (final var ps = new PrintStream(out)) {
                po.write(ps);
            } catch (final IOException e) {
                throw new IllegalStateException(e);
            }
            return out.toString(UTF_8);
        }
        throw new IllegalStateException("Unknown type: " + formatted);
    }

    public record FormattedProject(String id, String label, String tasks) {
    }
}

This works but I would expect asTable to be replacable by @Table on the nested type (public record Project(String id, String label, @Table(...config...) List<Task> tasks) { }) which would make it simpler but would also avoid to depend on the implementation module in commands.

Tip if you need the same feature: you can move this code in an utility class and call it to preformat your data before the rendering:

@Table(border = asciiSeparated)
@Command(value = "list-projects")
public List<FormattedProject> listProjects(....) {
    return jira.findProjects(login, configuration).stream()
            .map(p -> new FormattedProject(p.id(), p.label(), AsTable.asTable(p.tasks()))) // here is the trick, AsTable is previous code in a static utility class
            .collect(toList());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant