refactor: simplify collection.toArray()
[egit/eclipse.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / synchronize / model / TreeBuilder.java
blob57a479d2be99d82acd9405bbbde74b2a12d41e12
1 /*******************************************************************************
2 * Copyright (C) 2013 Robin Stocker <robin@nibor.org>
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
10 *******************************************************************************/
11 package org.eclipse.egit.ui.internal.synchronize.model;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
18 import org.eclipse.core.runtime.IPath;
19 import org.eclipse.core.runtime.Path;
20 import org.eclipse.egit.core.synchronize.GitCommitsModelCache.Change;
21 import org.eclipse.jgit.lib.Repository;
23 /**
24 * For building trees of directory and file nodes out of a flat list of changes.
26 class TreeBuilder {
28 /**
29 * This interface enables creating the right instances of
30 * {@link GitModelBlob} for files.
32 interface FileModelFactory {
33 /**
34 * Creates proper instance of {@link GitModelBlob} for file nodes
36 * @param parent
37 * parent object
38 * @param repo
39 * repository associated with file that will be created
40 * @param change
41 * change associated with file that will be created
42 * @param fullPath
43 * absolute path
44 * @return instance of {@link GitModelBlob}
46 GitModelBlob createFileModel(GitModelObjectContainer parent,
47 Repository repo, Change change, IPath fullPath);
49 /**
50 * Distinguish working tree from changed/staged tree
52 * @return {@code true} when this tree is working tree, {@code false}
53 * when it is a cached tree
55 boolean isWorkingTree();
58 /**
59 * Interface for creating the desired instances of {@link GitModelTree}.
61 interface TreeModelFactory {
62 GitModelTree createTreeModel(GitModelObjectContainer parent,
63 IPath fullPath, int kind);
66 /**
68 * @param root
69 * the root node of the tree to build, which will become the
70 * parent of the first level of children
71 * @param repo
72 * @param changes
73 * @param fileFactory
74 * @param treeFactory
75 * @return the children of the root nodes
77 public static GitModelObject[] build(final GitModelObjectContainer root,
78 final Repository repo, final Map<String, Change> changes,
79 final FileModelFactory fileFactory,
80 final TreeModelFactory treeFactory) {
82 if (changes == null || changes.isEmpty())
83 return new GitModelObject[] {};
85 final IPath rootPath = new Path(repo.getWorkTree()
86 .getAbsolutePath());
87 final List<GitModelObject> rootChildren = new ArrayList<>();
89 final Map<IPath, Node> nodes = new HashMap<>();
91 for (Map.Entry<String, Change> entry : changes.entrySet()) {
92 String repoRelativePath = entry.getKey();
93 Change change = entry.getValue();
95 GitModelObjectContainer parent = root;
96 List<GitModelObject> children = rootChildren;
97 IPath path = rootPath;
99 String[] segments = repoRelativePath.split("/"); //$NON-NLS-1$
101 for (int i = 0; i < segments.length; i++) {
102 path = path.append(segments[i]);
104 // Changes represent files, so the last segment is the file name
105 boolean fileNode = (i == segments.length - 1);
106 if (!fileNode) {
107 Node node = nodes.get(path);
108 if (node == null) {
109 GitModelTree tree = treeFactory.createTreeModel(parent,
110 path, change.getKind());
111 node = new Node(tree);
112 nodes.put(path, node);
113 children.add(tree);
115 parent = node.tree;
116 children = node.children;
117 } else {
118 GitModelBlob file = fileFactory.createFileModel(parent,
119 repo, change, path);
120 children.add(file);
125 for (Node object : nodes.values()) {
126 GitModelTree tree = object.tree;
127 tree.setChildren(object.children);
130 return rootChildren.toArray(new GitModelObject[0]);
133 private static class Node {
134 private final GitModelTree tree;
136 private final List<GitModelObject> children = new ArrayList<>();
138 public Node(GitModelTree tree) {
139 this.tree = tree;