TreeUtil with non-recursive methods to convert TreePath

This commit is contained in:
Sergey Malenkov
2017-07-17 04:01:14 +03:00
parent 193497b3aa
commit c81422564d
3 changed files with 280 additions and 7 deletions
@@ -116,11 +116,7 @@ abstract class AbstractTreeWalker<N> {
TreePath result = null;
if (node != null) {
try {
Object component = converter.apply(node);
TreePath path = parent != null
? parent.pathByAddingChild(component)
: new TreePath(component);
TreePath path = TreeUtil.createTreePath(parent, converter.apply(node));
switch (visitor.accept(path)) {
case CONTINUE:
update(null, State.REQUESTED);
@@ -175,8 +171,7 @@ abstract class AbstractTreeWalker<N> {
current = path.getParentPath();
}
else {
Object component = converter.apply(node);
TreePath path = this.current.pathByAddingChild(component);
TreePath path = TreeUtil.createTreePath(current, converter.apply(node));
switch (visitor.accept(path)) {
case CONTINUE:
update(State.STARTED, State.REQUESTED);
@@ -0,0 +1,129 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* 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 com.intellij.ui.tree;
import org.jetbrains.annotations.NotNull;
import javax.swing.tree.TreePath;
import java.lang.reflect.Array;
import java.util.function.Function;
public class TreeUtil {
/**
* @param parent the parent path or {@code null} to indicate the root
* @param component the last path component
* @return a tree path with all the parent components plus the given component
*/
@NotNull
public static TreePath createTreePath(TreePath parent, @NotNull Object component) {
return parent != null
? parent.pathByAddingChild(component)
: new TreePath(component);
}
/**
* @param path a tree path to convert
* @return an array with the string representations of path components or {@code null}
* if the specified path is wrong
* or a path component is {@code null}
* or its string representation is {@code null}
*/
public static String[] convertTreePathToStrings(@NotNull TreePath path) {
return convertTreePathToArray(path, Object::toString, String.class);
}
/**
* @param path a tree path to convert
* @return an array with the same path components or {@code null}
* if the specified path is wrong
* or a path component is {@code null}
*/
public static Object[] convertTreePathToArray(@NotNull TreePath path) {
return convertTreePathToArray(path, Function.identity(), Object.class);
}
/**
* @param path a tree path to convert
* @param function a function to convert path components
* @return an array with the converted path components or {@code null}
* if the specified path is wrong
* or a path component is {@code null}
* or a path component is converted to {@code null}
*/
public static Object[] convertTreePathToArray(@NotNull TreePath path, @NotNull Function<Object, Object> converter) {
return convertTreePathToArray(path, converter, Object.class);
}
/**
* @param path a tree path to convert
* @param function a function to convert path components
* @param type a type of components of the new array
* @return an array of the specified type with the converted path components or {@code null}
* if the specified path is wrong
* or a path component is {@code null}
* or a path component is converted to {@code null}
*/
public static <T> T[] convertTreePathToArray(@NotNull TreePath path, @NotNull Function<Object, T> converter, @NotNull Class<T> type) {
int count = path.getPathCount();
if (count <= 0) return null;
//noinspection unchecked
T[] array = (T[])Array.newInstance(type, count);
while (path != null && count > 0) {
Object component = path.getLastPathComponent();
if (component == null) return null;
T object = convert(component, converter);
if (object == null) return null;
array[--count] = object;
path = path.getParentPath();
}
return path != null || count > 0 ? null : array;
}
/**
* @param array an array of path components to convert
* @return a tree path with the same path components or {@code null}
* if the specified array is empty
* or a path component is {@code null}
* or a path component is converted to {@code null}
*/
public static <T> TreePath convertArrayToTreePath(@NotNull T... array) {
return convertArrayToTreePath(array, Function.identity());
}
/**
* @param array an array of path components to convert
* @param function a function to convert path components
* @return a tree path with the converted path components or {@code null}
* if the specified array is empty
* or a path component is {@code null}
* or a path component is converted to {@code null}
*/
public static <T> TreePath convertArrayToTreePath(@NotNull T[] array, @NotNull Function<T, Object> converter) {
int count = array.length;
if (count <= 0) return null;
TreePath path = null;
for (T object : array) {
Object component = convert(object, converter);
if (component == null) return null;
path = createTreePath(path, component);
}
return path;
}
private static <I, O> O convert(I object, @NotNull Function<I, O> converter) {
return object == null ? null : converter.apply(object);
}
}
@@ -0,0 +1,149 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* 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 com.intellij.ui.tree;
import org.junit.Assert;
import org.junit.Test;
import javax.swing.tree.TreePath;
public class TreeUtilTest {
@Test
public void createTreePath() {
Object root = new Object();
TreePath parent = TreeUtil.createTreePath(null, root);
Assert.assertNotNull(parent);
Assert.assertNull(parent.getParentPath());
Assert.assertSame(root, parent.getLastPathComponent());
Object node = new Object();
TreePath path = TreeUtil.createTreePath(parent, node);
Assert.assertNotNull(path);
Assert.assertNotNull(path.getParentPath());
Assert.assertNotSame(path, parent);
Assert.assertSame(parent, path.getParentPath());
Assert.assertSame(node, path.getLastPathComponent());
}
@Test
public void convertTreePathToStrings() {
String[] strings = TreeUtil.convertTreePathToStrings(new TreePath(new Object[]{2, 1, 0}));
Assert.assertNotNull(strings);
Assert.assertEquals(3, strings.length);
Assert.assertEquals("2", strings[0]);
Assert.assertEquals("1", strings[1]);
Assert.assertEquals("0", strings[2]);
}
@Test
public void convertTreePathToArrayWrongConverter() {
Assert.assertNull(TreeUtil.convertTreePathToArray(new TreePath(new Object[]{2, 1, 0}), component -> null));
}
@Test
public void convertTreePathToArrayWrongPathCount() {
Assert.assertNull(TreeUtil.convertTreePathToArray(new TreePath() {
}));
}
@Test
public void convertTreePathToArrayWrongPathComponent() {
Assert.assertNull(TreeUtil.convertTreePathToArray(new TreePath(new Object[]{2, 1, 0}) {
@Override
public Object getLastPathComponent() {
return null;
}
}));
}
@Test
public void convertTreePathToArrayDeep() {
convertTreePathToArrayDeep(1);
convertTreePathToArrayDeep(10);
convertTreePathToArrayDeep(100);
convertTreePathToArrayDeep(1000);
convertTreePathToArrayDeep(10000);
convertTreePathToArrayDeep(100000);
convertTreePathToArrayDeep(1000000);
}
private static void convertTreePathToArrayDeep(int count) {
TreePath path = null;
for (int i = 0; i < count; i++) path = TreeUtil.createTreePath(path, i);
Assert.assertEquals(count, path.getPathCount());
Assert.assertEquals(count - 1, path.getLastPathComponent());
Object[] array = TreeUtil.convertTreePathToArray(path);
Assert.assertEquals(count, array.length);
}
@Test
public void convertArrayToTreePath() {
TreePath path = TreeUtil.convertArrayToTreePath("2", "1", "0");
Assert.assertNotNull(path);
Assert.assertEquals("0", path.getLastPathComponent());
Assert.assertNotNull(path.getParentPath());
Assert.assertEquals("1", path.getParentPath().getLastPathComponent());
Assert.assertNotNull(path.getParentPath().getParentPath());
Assert.assertEquals("2", path.getParentPath().getParentPath().getLastPathComponent());
Assert.assertNull(path.getParentPath().getParentPath().getParentPath());
}
@Test
public void convertArrayToTreePathConverter() {
TreePath path = TreeUtil.convertArrayToTreePath(new Object[]{2, 1, 0}, Object::toString);
Assert.assertNotNull(path);
Assert.assertEquals("0", path.getLastPathComponent());
Assert.assertNotNull(path.getParentPath());
Assert.assertEquals("1", path.getParentPath().getLastPathComponent());
Assert.assertNotNull(path.getParentPath().getParentPath());
Assert.assertEquals("2", path.getParentPath().getParentPath().getLastPathComponent());
Assert.assertNull(path.getParentPath().getParentPath().getParentPath());
}
@Test
public void convertArrayToTreePathEmptyArray() {
Assert.assertNull(TreeUtil.convertArrayToTreePath());
}
@Test
public void convertArrayToTreePathWrongComponent() {
Assert.assertNull(TreeUtil.convertArrayToTreePath("2", null, "0"));
}
@Test
public void convertArrayToTreePathWrongConverter() {
Assert.assertNull(TreeUtil.convertArrayToTreePath(new String[]{"2", "1", "0"}, component -> null));
}
@Test
public void convertArrayToTreePathDeep() {
convertArrayToTreePathDeep(1);
convertArrayToTreePathDeep(10);
convertArrayToTreePathDeep(100);
convertArrayToTreePathDeep(1000);
convertArrayToTreePathDeep(10000);
convertArrayToTreePathDeep(100000);
convertArrayToTreePathDeep(1000000);
}
private static void convertArrayToTreePathDeep(int count) {
Object[] array = new Object[count];
for (int i = 0; i < count; i++) array[i] = i;
TreePath path = TreeUtil.convertArrayToTreePath(array);
Assert.assertEquals(count, path.getPathCount());
Assert.assertEquals(count - 1, path.getLastPathComponent());
}
}