gitweb on Svarog
projekti pod git sistemom za održavanje verzija -- projects under the git version control systemdiff --git a/Stabla/konkretnoStablo/TreeIO.java b/Stabla/konkretnoStablo/TreeIO.java
--- /dev/null
@@ -0,0 +1,653 @@
+\r
+import java.lang.reflect.Constructor;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Modifier;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.svetovid.io.SvetovidReader;\r
+import org.svetovid.io.SvetovidWriter;\r
+\r
+public class TreeIO<T> {\r
+\r
+ public TreeIO(Class<T> type) {\r
+ this(type, null);\r
+ }\r
+\r
+ ////////////\r
+ // Config //\r
+ ////////////\r
+\r
+ public static class Config {\r
+\r
+ public final String nullSymbol;\r
+ public final int separation;\r
+ public final int length;\r
+\r
+ public Config() {\r
+ this(null, 1, 7);\r
+ }\r
+\r
+ public Config(String nullSymbol, int separation, int length) {\r
+ this.nullSymbol = nullSymbol;\r
+ this.separation = separation;\r
+ this.length = length;\r
+ }\r
+\r
+ public Config setNullSymbol(String nullSymbol) {\r
+ return new Config(nullSymbol, separation, length);\r
+ }\r
+\r
+ public Config setSeparation(int separation) {\r
+ return new Config(nullSymbol, separation, length);\r
+ }\r
+ \r
+ public Config setLength(int length) {\r
+ return new Config(nullSymbol, separation, length);\r
+ }\r
+ }\r
+\r
+ protected Config config;\r
+\r
+ public Config getConfig() {\r
+ return config;\r
+ }\r
+\r
+ public void setConfig(Config config) {\r
+ this.config = config;\r
+ }\r
+\r
+ //////////////\r
+ // Printing //\r
+ //////////////\r
+\r
+ public void print(SvetovidWriter out, T tree) {\r
+ Object root = getRoot(tree);\r
+ StringBuilder builder = new StringBuilder();\r
+ appendTree(builder, root, config);\r
+ out.print(builder.toString());\r
+ }\r
+\r
+ protected void appendTree(StringBuilder builder, Object tree, Config config) {\r
+ String[] buildingBlocks = generateBuildingBlocks(config);\r
+ appendRight(builder, tree, config, buildingBlocks, true, buildingBlocks[5]);\r
+ appendNode(builder, tree, config, buildingBlocks[4]);\r
+ appendLeft(builder, tree, config, buildingBlocks, false, buildingBlocks[5]);\r
+ }\r
+\r
+ protected void appendNode(StringBuilder builder, Object tree, Config config, String prefix) {\r
+ builder.append(prefix);\r
+ if (tree == null) {\r
+ builder.append(config.nullSymbol == null ? VERTICAL_SYMBOL : config.nullSymbol);\r
+ } else {\r
+ builder.append("(o)");\r
+ Object element = getElement(tree);\r
+ if (element != null) {\r
+ builder.append(" ");\r
+ builder.append(element.toString());\r
+ }\r
+ }\r
+ builder.append("\n");\r
+ }\r
+\r
+ protected void appendRight(StringBuilder builder, Object tree, Config config, String[] buildingBlocks, boolean isRight, String prefix) {\r
+ if (tree == null) {\r
+ return;\r
+ }\r
+ Object subtree = getRight(tree);\r
+ if ((config.nullSymbol != null) || (subtree != null)) {\r
+ appendSubtree(builder, subtree, config, buildingBlocks, true, prefix);\r
+ for (int i = 0; i < config.separation; i++) {\r
+ appendEmpty(builder, buildingBlocks, prefix);\r
+ }\r
+ }\r
+ }\r
+\r
+ protected void appendLeft(StringBuilder builder, Object tree, Config config, String[] buildingBlocks, boolean isRight, String prefix) {\r
+ if (tree == null) {\r
+ return;\r
+ }\r
+ Object subtree = getLeft(tree);\r
+ if ((config.nullSymbol != null) || (subtree != null)) {\r
+ for (int i = 0; i < config.separation; i++) {\r
+ appendEmpty(builder, buildingBlocks, prefix);\r
+ }\r
+ appendSubtree(builder, subtree, config, buildingBlocks, false, prefix);\r
+ }\r
+ }\r
+\r
+ protected void appendEmpty(StringBuilder builder, String[] buildingBlocks, String prefix) {\r
+ builder.append(prefix);\r
+ builder.append(buildingBlocks[2]);\r
+ builder.append("\n");\r
+ }\r
+\r
+ protected void appendSubtree(StringBuilder builder, Object tree, Config config, String[] buildingBlocks, boolean isRight, String prefix) {\r
+ String myPrefix = prefix;\r
+ if (isRight == true) {\r
+ myPrefix = myPrefix + buildingBlocks[1];\r
+ }\r
+ if (isRight == false) {\r
+ myPrefix = myPrefix + buildingBlocks[3];\r
+ }\r
+ String noviPrefix = prefix + (!isRight ? buildingBlocks[2] : buildingBlocks[0]);\r
+ appendRight(builder, tree, config, buildingBlocks, isRight, noviPrefix);\r
+ appendNode(builder, tree, config, myPrefix);\r
+ noviPrefix = prefix + (isRight ? buildingBlocks[2] : buildingBlocks[0]);\r
+ appendLeft(builder, tree, config, buildingBlocks, isRight, noviPrefix);\r
+ }\r
+\r
+ protected static final String EMPTY_SYMBOL = " ";\r
+ protected static final String RIGHT_SYMBOL = "/";\r
+ protected static final String VERTICAL_SYMBOL = "|";\r
+ protected static final String LEFT_SYMBOL = "\\";\r
+ protected static final String HORIZONTAL_SYMBOL = "-";\r
+\r
+ protected String[] generateBuildingBlocks(Config config) {\r
+ String[] blocks = new String[6];\r
+ blocks[0] = generateBlock(EMPTY_SYMBOL, EMPTY_SYMBOL, EMPTY_SYMBOL, config.length - 2);\r
+ blocks[1] = generateBlock(EMPTY_SYMBOL, RIGHT_SYMBOL, HORIZONTAL_SYMBOL, config.length - 2);\r
+ blocks[2] = generateBlock(EMPTY_SYMBOL, VERTICAL_SYMBOL, EMPTY_SYMBOL, config.length - 2);\r
+ blocks[3] = generateBlock(EMPTY_SYMBOL, LEFT_SYMBOL, HORIZONTAL_SYMBOL, config.length - 2);\r
+ blocks[4] = HORIZONTAL_SYMBOL;\r
+ blocks[5] = EMPTY_SYMBOL;\r
+ return blocks;\r
+ }\r
+\r
+ protected String generateBlock(String emptySymbol, String startSymbol, String repeatSymbol, int repeatCount) {\r
+ StringBuilder builder = new StringBuilder();\r
+ builder.append(emptySymbol);\r
+ builder.append(startSymbol);\r
+ for (int i = 0; i < repeatCount; i++) {\r
+ builder.append(repeatSymbol);\r
+ }\r
+ return builder.toString();\r
+ }\r
+\r
+ /////////////\r
+ // Reading //\r
+ /////////////\r
+\r
+ public T read(SvetovidReader in) {\r
+ return newTree(parseTree(in, config)); \r
+ }\r
+\r
+ protected Object parseTree(SvetovidReader in, Config config) {\r
+ List<Object> elements = new ArrayList<>();\r
+ List<Integer> levels = new ArrayList<>();\r
+ Pattern levelPattern = Pattern.compile("[\\Q" + LEFT_SYMBOL + HORIZONTAL_SYMBOL + RIGHT_SYMBOL + "\\E]");\r
+ String line = in.readLine();\r
+ while ((line != null) && !line.isEmpty()) {\r
+ Matcher matcher = levelPattern.matcher(line);\r
+ int level = -1;\r
+ if (matcher.find()) {\r
+ level = matcher.start();\r
+ }\r
+ if (level != -1 && (config.nullSymbol == null || !line.endsWith(config.nullSymbol))) {\r
+ Object tree = parseTree(line);\r
+ elements.add(tree);\r
+ levels.add(level);\r
+ }\r
+ line = in.readLine();\r
+ }\r
+ Object tree = formTree(0, elements.size(), levels, elements);\r
+ return tree;\r
+ }\r
+\r
+ protected Object parseTree(String line) {\r
+ String value;\r
+ int beginIndex = line.indexOf('(');\r
+ int endIndex = line.indexOf(')');\r
+ if ((beginIndex != -1) && (endIndex != -1) && (beginIndex < endIndex)) {\r
+ value = line.substring(endIndex + 1);\r
+ if (value.length() == 0) {\r
+ value = null;\r
+ } else {\r
+ value = value.substring(1);\r
+ }\r
+ } else {\r
+ throw new NumberFormatException(line);\r
+ }\r
+ Object element = null;\r
+ if (value != null) {\r
+ element = newElement(value);\r
+ }\r
+ Object tree = newNode(element);\r
+ return tree;\r
+ }\r
+\r
+ protected Object formTree(int beginIndex, int endIndex, List<Integer> levels, List<Object> elements) {\r
+ if (beginIndex >= endIndex) {\r
+ return null;\r
+ }\r
+ int minIndex = beginIndex;\r
+ int minLevel = levels.get(minIndex);\r
+ for (int i = beginIndex + 1; i < endIndex; i++) {\r
+ int level = levels.get(i);\r
+ if (level < minLevel) {\r
+ minLevel = level;\r
+ minIndex = i;\r
+ }\r
+ }\r
+ Object tree = elements.get(minIndex);\r
+ Object left = formTree(minIndex + 1, endIndex, levels, elements);\r
+ Object right = formTree(beginIndex, minIndex, levels, elements);\r
+ setLeft(tree, left);\r
+ setRight(tree, right);\r
+ return tree;\r
+ }\r
+\r
+ ///////////\r
+ // Magic //\r
+ ///////////\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public TreeIO(Class<T> type, Config config) {\r
+\r
+ // Tree type\r
+ if (type == null) {\r
+ throw new IllegalArgumentException("Prosledjena klasa je null");\r
+ }\r
+ this.treeType = type;\r
+ if (Modifier.isAbstract(this.treeType.getModifiers())) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " ne sme da bude apstraktna");\r
+ }\r
+\r
+ // Node type\r
+ Class<?>[] declaredClasses = treeType.getDeclaredClasses();\r
+ if (declaredClasses.length == 0) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " nema unutrasnju klasu koja predstavlja cvorove");\r
+ }\r
+ Class<?> staticOne = null;\r
+ boolean multiStatic = false;\r
+ for (Class<?> cl: declaredClasses) {\r
+ if (Modifier.isStatic(cl.getModifiers())) {\r
+ if (staticOne == null) {\r
+ staticOne = cl;\r
+ } else {\r
+ multiStatic = true;\r
+ }\r
+ }\r
+ }\r
+ if (staticOne == null) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " nema staticku unutrasnju klasu koja predstavlja cvorove");\r
+ }\r
+ if (multiStatic) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " ima vise unutrasnjih statickih klasa, a mora biti samo jedna");\r
+ }\r
+ this.nodeType = staticOne;\r
+ if (Modifier.isAbstract(this.nodeType.getModifiers())) {\r
+ throw new IllegalArgumentException("Klasa " + this.nodeType.getName() + " ne sme da bude apstraktna");\r
+ }\r
+ if (!Modifier.isStatic(this.nodeType.getModifiers())) {\r
+ throw new IllegalArgumentException("Klasa " + this.nodeType.getName() + " mora da bude staticka");\r
+ }\r
+\r
+ // Tree constructors\r
+ Constructor<?>[] declaredConstructors = this.treeType.getDeclaredConstructors();\r
+ Constructor<T> defaultTreeConstructor = null;\r
+ Constructor<T> treeConstructor = null;\r
+ for (Constructor<?> constructor : declaredConstructors) {\r
+ boolean throwingExceptions = false;\r
+ for (Class<?> exception : constructor.getExceptionTypes()) {\r
+ if (!RuntimeException.class.isAssignableFrom(exception)) {\r
+ throwingExceptions = true;\r
+ }\r
+ }\r
+ Class<?>[] parameters = constructor.getParameterTypes();\r
+ if (parameters.length == 0\r
+ && !throwingExceptions) {\r
+ defaultTreeConstructor = (Constructor<T>) constructor;\r
+ }\r
+ if (parameters.length == 1\r
+ && parameters[0].isAssignableFrom(this.nodeType)\r
+ && !throwingExceptions) {\r
+ treeConstructor = (Constructor<T>) constructor;\r
+ }\r
+ }\r
+ if (defaultTreeConstructor == null && treeConstructor == null) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " nema "\r
+ + this.nodeType.getSimpleName() + "() ili "\r
+ + this.nodeType.getSimpleName() + "(" + this.nodeType.getName() + ") konstruktor");\r
+ }\r
+ this.defaultTreeConstructor = defaultTreeConstructor;\r
+ if (this.defaultTreeConstructor != null) {\r
+ this.defaultTreeConstructor.setAccessible(true);\r
+ }\r
+ this.treeConstructor = treeConstructor;\r
+ if (this.treeConstructor != null) {\r
+ this.treeConstructor.setAccessible(true);\r
+ }\r
+\r
+ // Tree root field\r
+ Field[] declaredFields = this.treeType.getDeclaredFields();\r
+ Field rootField = null;\r
+ for (Field field : declaredFields) {\r
+ if (Modifier.isStatic(field.getModifiers())) {\r
+ continue;\r
+ }\r
+ if (field.getType().isAssignableFrom(this.nodeType)) {\r
+ if (rootField != null) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " ima vise polja koji bi mogli predstavljati koren stabla");\r
+ }\r
+ rootField = field;\r
+ }\r
+ }\r
+ if (rootField == null) {\r
+ throw new IllegalArgumentException("Klasa " + this.treeType.getName() + " nema polje za predstavljanje korena");\r
+ }\r
+ this.rootField = rootField;\r
+ if (Modifier.isStatic(this.rootField.getModifiers())) {\r
+ throw new IllegalArgumentException("Polje " + this.treeType.getName() + "." + this.rootField.getName() + " ne sme da bude staticko");\r
+ }\r
+ this.rootField.setAccessible(true);\r
+\r
+ // Node fields\r
+ declaredFields = this.nodeType.getDeclaredFields();\r
+ if (declaredFields.length == 0) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " nema deklarisanih polja");\r
+ }\r
+ Field elementField = null;\r
+ Field leftField = null;\r
+ Field rightField = null;\r
+ for (Field field : declaredFields) {\r
+ if (Modifier.isStatic(field.getModifiers())) {\r
+ continue;\r
+ }\r
+ String fieldName = field.getName();\r
+ if (fieldName.startsWith("e") || fieldName.startsWith("i") || fieldName.startsWith("o")) {\r
+ if (elementField != null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " ima vise polja za predstavljanje elementa");\r
+ }\r
+ elementField = field;\r
+ }\r
+ if (fieldName.startsWith("l")\r
+ && field.getType().isAssignableFrom(this.nodeType)) {\r
+ if (leftField != null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " ima vise polja za predstavljanje levog podstabla");\r
+ }\r
+ leftField = field;\r
+ }\r
+ if (fieldName.startsWith("d") || fieldName.startsWith("r")\r
+ && field.getType().isAssignableFrom(this.nodeType)) {\r
+ if (rightField != null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " ima vise polja za predstavljanje desnog podstabla");\r
+ }\r
+ rightField = field;\r
+ }\r
+ }\r
+ if (elementField == null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " nema polje za predstavljanje elementa");\r
+ }\r
+ if (leftField == null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " nema polje za predstavljanje levog podstabla");\r
+ }\r
+ if (rightField == null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " nema polje za predstavljanje desnog podstabla");\r
+ }\r
+ this.elementField = elementField;\r
+ if (Modifier.isStatic(this.elementField.getModifiers())) {\r
+ throw new IllegalArgumentException("Polje " + this.treeType.getName() + "." + this.elementField.getName() + " ne sme da bude staticko");\r
+ }\r
+ this.elementField.getModifiers();\r
+ \r
+ this.elementField.setAccessible(true);\r
+ this.leftField = leftField;\r
+ if (Modifier.isStatic(this.leftField.getModifiers())) {\r
+ throw new IllegalArgumentException("Polje " + this.treeType.getName() + "." + this.leftField.getName() + " ne sme da bude staticko");\r
+ }\r
+ this.leftField.setAccessible(true);\r
+ this.rightField = rightField;\r
+ if (Modifier.isStatic(this.rightField.getModifiers())) {\r
+ throw new IllegalArgumentException("Polje " + this.treeType.getName() + "." + this.rightField.getName() + " ne sme da bude staticko");\r
+ }\r
+ this.rightField.setAccessible(true);\r
+\r
+ // Element type\r
+ this.elementType = elementField.getType();\r
+\r
+ // Node constructors\r
+ declaredConstructors = this.nodeType.getDeclaredConstructors();\r
+ Constructor<?> defaultNodeConstructor = null;\r
+ Constructor<?> nodeConstructor = null;\r
+ Constructor<?> nodeConstructor3 = null;\r
+ for (Constructor<?> constructor : declaredConstructors) {\r
+ boolean throwingExceptions = false;\r
+ for (Class<?> exception : constructor.getExceptionTypes()) {\r
+ if (!RuntimeException.class.isAssignableFrom(exception)) {\r
+ throwingExceptions = true;\r
+ }\r
+ }\r
+ Class<?>[] parameters = constructor.getParameterTypes();\r
+ if (parameters.length == 0\r
+ && !throwingExceptions) {\r
+ defaultNodeConstructor = constructor;\r
+ }\r
+ if (parameters.length == 1\r
+ && parameters[0].isAssignableFrom(this.elementType)\r
+ && !throwingExceptions) {\r
+ nodeConstructor = constructor;\r
+ }\r
+ if (parameters.length == 3\r
+ && parameters[0].isAssignableFrom(this.elementType)\r
+ && parameters[1].isAssignableFrom(this.nodeType)\r
+ && parameters[2].isAssignableFrom(this.nodeType)\r
+ && !throwingExceptions) {\r
+ nodeConstructor3 = constructor;\r
+ }\r
+ }\r
+ if (defaultNodeConstructor == null && nodeConstructor == null && nodeConstructor3 == null) {\r
+ throw new IllegalArgumentException("Unutrasnja klasa " + this.nodeType.getName() + " nema "\r
+ + this.nodeType.getSimpleName() + "() ili "\r
+ + this.nodeType.getSimpleName() + "(" + this.elementType.getName() + ") ili "\r
+ + this.nodeType.getSimpleName() + "(" + this.elementType.getName() + ", " + this.nodeType.getSimpleName() + ", " + this.nodeType.getSimpleName() + ") konstruktor");\r
+ }\r
+ this.defaultNodeConstructor = defaultNodeConstructor;\r
+ if (this.defaultNodeConstructor != null) {\r
+ this.defaultNodeConstructor.setAccessible(true);\r
+ }\r
+ this.nodeConstructor = nodeConstructor;\r
+ if (this.nodeConstructor != null) {\r
+ this.nodeConstructor.setAccessible(true);\r
+ }\r
+ this.nodeConstructor3 = nodeConstructor3;\r
+ if (this.nodeConstructor3 != null) {\r
+ this.nodeConstructor3.setAccessible(true);\r
+ }\r
+\r
+ // Element methods\r
+ Method elementFactoryMethod = null;\r
+ Method[] declaredMethods = this.elementType.getDeclaredMethods();\r
+ for (Method method : declaredMethods) {\r
+ if (!Modifier.isStatic(method.getModifiers())) {\r
+ continue;\r
+ }\r
+ boolean throwingExceptions = false;\r
+ for (Class<?> exception : method.getExceptionTypes()) {\r
+ if (!RuntimeException.class.isAssignableFrom(exception)) {\r
+ throwingExceptions = true;\r
+ }\r
+ }\r
+ String methodName = method.getName();\r
+ boolean familiarName = methodName.equals("fromString")\r
+ || methodName.equals("valueOf")\r
+ || methodName.equals("parse" + this.elementType.getSimpleName());\r
+ boolean goodParameters = method.getParameterTypes().length == 1 && (method.getParameterTypes()[0] == String.class || method.getParameterTypes()[0] == Object.class);\r
+ if (familiarName\r
+ && goodParameters\r
+ && this.elementType.isAssignableFrom(method.getReturnType())\r
+ && !throwingExceptions) {\r
+ if (elementFactoryMethod != null) {\r
+ throw new IllegalArgumentException("Klasa " + this.elementType.getName() + " ima vise "\r
+ + this.elementType.getSimpleName() + " fromString(String), "\r
+ + this.elementType.getSimpleName() + " valueOf(String) i "\r
+ + this.elementType.getSimpleName() + " parse" + this.elementType.getSimpleName() + "(String) metoda");\r
+ }\r
+ elementFactoryMethod = method;\r
+ }\r
+ }\r
+ if (elementFactoryMethod == null) {\r
+ throw new IllegalArgumentException("Klasa " + this.elementType.getName() + " nema "\r
+ + this.elementType.getSimpleName() + " fromString(String), "\r
+ + this.elementType.getSimpleName() + " valueOf(String) ili "\r
+ + this.elementType.getSimpleName() + " parse" + this.elementType.getSimpleName() + "(String) metod");\r
+ }\r
+ this.elementFactoryMethod = elementFactoryMethod;\r
+ this.elementFactoryMethod.setAccessible(true);\r
+\r
+ // Config\r
+ if (config == null) {\r
+ config = new Config();\r
+ }\r
+ this.config = config;\r
+\r
+ }\r
+\r
+ protected final Class<T> treeType;\r
+ protected final Constructor<T> treeConstructor;\r
+ protected final Constructor<T> defaultTreeConstructor;\r
+ protected final Field rootField;\r
+ protected final Class<?> nodeType;\r
+ protected final Field elementField;\r
+ protected final Field leftField;\r
+ protected final Field rightField;\r
+ protected final Constructor<?> nodeConstructor3;\r
+ protected final Constructor<?> nodeConstructor;\r
+ protected final Constructor<?> defaultNodeConstructor;\r
+ protected final Class<?> elementType;\r
+ protected final Method elementFactoryMethod;\r
+\r
+ private Object getRoot(T tree) {\r
+ try {\r
+ Object value = rootField.get(tree);\r
+ return value;\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private void setRoot(T tree, Object root) {\r
+ try {\r
+ rootField.set(tree, root);\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ }\r
+ }\r
+\r
+ private Object getElement(Object node) {\r
+ try {\r
+ Object value = elementField.get(node);\r
+ return value;\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private void setElement(Object node, Object value) {\r
+ try {\r
+ elementField.set(node, value);\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ }\r
+ }\r
+\r
+ private Object getLeft(Object node) {\r
+ try {\r
+ Object value = leftField.get(node);\r
+ return value;\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ }\r
+ }\r
+\r
+ private void setLeft(Object node, Object value) {\r
+ try {\r
+ leftField.set(node, value);\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ }\r
+ }\r
+\r
+ private Object getRight(Object node) {\r
+ try {\r
+ Object value = rightField.get(node);\r
+ return value;\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ }\r
+ }\r
+\r
+ private void setRight(Object node, Object value) {\r
+ try {\r
+ rightField.set(node, value);\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ }\r
+ }\r
+\r
+ private Object newElement(String value) {\r
+ try {\r
+ return elementFactoryMethod.invoke(null, value);\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ } catch (InvocationTargetException e) {\r
+ // Will not be a checked exception\r
+ RuntimeException cause = (RuntimeException) e.getCause();\r
+ throw cause;\r
+ }\r
+ }\r
+\r
+ private Object newNode(Object element) {\r
+ try {\r
+ if (nodeConstructor != null) {\r
+ return nodeConstructor.newInstance(element);\r
+ }\r
+ if (nodeConstructor3 != null) {\r
+ return nodeConstructor3.newInstance(element, null, null);\r
+ }\r
+ Object node = defaultNodeConstructor.newInstance();\r
+ setElement(node, element);\r
+ return node;\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ } catch (InstantiationException e) {\r
+ // Will never happen\r
+ return null;\r
+ } catch (InvocationTargetException e) {\r
+ // Will not be a checked exception\r
+ RuntimeException cause = (RuntimeException) e.getCause();\r
+ throw cause;\r
+ }\r
+ }\r
+\r
+ private T newTree(Object root) {\r
+ try {\r
+ if (treeConstructor != null) {\r
+ return treeConstructor.newInstance(root);\r
+ }\r
+ T tree = defaultTreeConstructor.newInstance();\r
+ setRoot(tree, root);\r
+ return tree;\r
+ } catch (IllegalAccessException e) {\r
+ // Will never happen\r
+ return null;\r
+ } catch (InstantiationException e) {\r
+ // Will never happen\r
+ return null;\r
+ } catch (InvocationTargetException e) {\r
+ // Will not be a checked exception\r
+ RuntimeException cause = (RuntimeException) e.getCause();\r
+ throw cause;\r
+ }\r
+ }\r
+}\r