1

I am using contentService.streamDirectory to get a callback containing all directories/files within a BitBucket project, then I am using a for loop and "callback.getFiles().get(i).toString()" to print out each filepath in a web page using a writer object. It looks something like this:

  • folder_1/file_1.txt
  • folder_1/file_2.txt
  • folder_2/folder_3/file_3.txt
  • folder_2/file_4.txt

What I want to do is generate something that resembles the directory structure and groups by folders, like this:

  • folder_1
    • file_1.txt
    • file_2.txt
  • folder_2
    • folder_3
      • file_3.txt
    • file_4.txt

I'm a bit unsure how to go about this. The current method for printing out is as follows:

resp.setContentType("text/html");
resp.getWriter().print("<html><body><p>Repository: " + repo.getName() +);
for (int i = 0; i < callback.getFiles().size(); i++) {
    resp.getWriter().println("<p><a href=\"/\">" + callback.getFiles().get(i).toString() + "</a></p>");
}
resp.getWriter().print("</body></html>");

I'm sure a whole lot of loops are required, I know there's a Files.walk() method but it looks like you point to the starting folder within the computer files, I do not know if its possible to point this to BitBucket? Thanks for any help you can give.

2
  • 1
    What is the type of callback.getFiles()? A list of java.io.File, java.nio.file.Path, or something different? Commented Jun 24, 2022 at 9:00
  • @Holger I believe its this: java.lang.Object -> com.atlassian.bitbucket.content.File Commented Jun 24, 2022 at 9:07

1 Answer 1

2

A simple approach is to store the elements into a small data structure reflecting the hierarchy first.

Let’s start with a simple stand-alone example to illustrate the approach.

public static void main(String[] args) throws IOException {
    List<Path> files = Arrays.asList(
        Paths.get("folder_1", "file_1.txt"),
        Paths.get("folder_1", "file_2.txt"),
        Paths.get("folder_2", "folder_3", "file_3.txt"),
        Paths.get("folder_2", "file_4.txt")
    );
    System.out.print("<html><body><p>Repository: " + "Test");
    Node root = new Node(null);
    for(Path f: files) root.add(f);
    root.writeTo(System.out);
    System.out.println("</body></html>");
}
static final class Node {
    final String name;
    final Map<String, Node> children = new LinkedHashMap<>();

    Node(String name) { this.name = name; }
    void add(Path path) {
        Node n = this;
        for(Path component: path)
            n = n.children.computeIfAbsent(component.toString(), Node::new);
    }
    void writeTo(Appendable w) throws IOException {
        if(name != null) w.append("<li>").append(name).append('\n');
        if(!children.isEmpty()) {
            w.append("<ul>\n");
            for(Node ch: children.values()) ch.writeTo(w);
            w.append("</ul>\n");
        }
    }
}

This produces

<html><body><p>Repository: Test<ul>
<li>folder_1
<ul>
<li>file_1.txt
<li>file_2.txt
</ul>
<li>folder_2
<ul>
<li>folder_3
<ul>
<li>file_3.txt
</ul>
<li>file_4.txt
</ul>
</ul>
</body></html>

To adapt it to your case, we have to change the add method. Assuming that you’re using this File class, it would be something like

void add(File file) {
    Node n = this;
    for(String component: file.getPath().getComponents())
        n = n.children.computeIfAbsent(component, Node::new);
}

and the adapted caller

resp.setContentType("text/html");
resp.getWriter().print("<html><body><p>Repository: " + repo.getName());
Node root = new Node(null);
for(int i = 0; i < callback.getFiles().size(); i++) root.add(callback.getFiles().get(i));
root.writeTo(resp.getWriter());
resp.getWriter().print("</body></html>");
Sign up to request clarification or add additional context in comments.

1 Comment

Hi @Holger , Thanks so much for this, I almost have it! I have tried what you suggested and realised I missed a bit about the callback which makes this not work. I have added a new question now I understand the issue a bit better and its a bit more direct to what I want. It is here if you would like to take a look and see if you can offer any help stackoverflow.com/questions/73123907/… . Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.