/** * Appends a single line as a node in the current section. */ private void writeNode(final CharSequence line) { String text = line.toString().trim(); if (!text.isEmpty()) { section.newChild().setValue(TableColumn.VALUE_AS_TEXT, text); } }
/** * Formats a graphical representation of an object for debugging purpose. This representation * can be printed to the {@linkplain System#out standard output stream} (for example) * if the output device uses a monospaced font and supports Unicode. */ static String toString(final Object owner, final Consumer<TreeTable.Node> appender) { final DefaultTreeTable table = new DefaultTreeTable(TableColumn.NAME); final TreeTable.Node root = table.getRoot(); root.setValue(TableColumn.NAME, owner.getClass().getSimpleName()); appender.accept(root); return table.toString(); }
/** * If a file path in the given node or any children follow the Maven pattern, remove the * artifact name and version numbers redundancies in order to make the name more compact. * For example this method replaces {@code "org/opengis/geoapi/3.0.0/geoapi-3.0.0.jar"} * by {@code "org/opengis/(…)/geoapi-3.0.0.jar"}. */ private static void omitMavenRedundancy(final TreeTable.Node node) { for (final TreeTable.Node child : node.getChildren()) { omitMavenRedundancy(child); } final CharSequence name = node.getValue(NAME); final int length = name.length(); final int s2 = CharSequences.lastIndexOf(name, File.separatorChar, 0, length); if (s2 >= 0) { final int s1 = CharSequences.lastIndexOf(name, File.separatorChar, 0, s2); if (s1 >= 0) { final int s0 = CharSequences.lastIndexOf(name, File.separatorChar, 0, s1) + 1; final StringBuilder buffer = new StringBuilder(s2 - s0).append(name, s0, s2); buffer.setCharAt(s1 - s0, '-'); if (CharSequences.regionMatches(name, s2+1, buffer)) { buffer.setLength(0); node.setValue(NAME, buffer.append(name, 0, s0).append("(…)").append(name, s2, length)); } } } }
/** * Formats the current {@code Coupled} and all its children as a tree in the given tree table node. * This method is used for {@link StorageConnector#toString()} implementation only and may change * in any future version. * * @param appendTo where to write name, value and children. * @param views reference to the {@link StorageConnector#views} map. Will be read only. */ @Debug final void append(final TreeTable.Node appendTo, final Map<Class<?>, Coupled> views) { Class<?> type = null; for (final Map.Entry<Class<?>, Coupled> entry : views.entrySet()) { if (entry.getValue() == this) { final Class<?> t = Classes.findCommonClass(type, entry.getKey()); if (t != Object.class) type = t; } } appendTo.setValue(TableColumn.NAME, Classes.getShortName(type)); appendTo.setValue(TableColumn.VALUE, Classes.getShortClassName(view)); if (wrappedBy != null) { for (final Coupled c : wrappedBy) { c.append(appendTo.newChild(), views); } } } }
/** * Formats the current {@code Coupled} and all its children as a tree in the given tree table node. * This method is used for {@link StorageConnector#toString()} implementation only and may change * in any future version. * * @param appendTo where to write name, value and children. * @param views reference to the {@link StorageConnector#views} map. Will be read only. */ @Debug final void append(final TreeTable.Node appendTo, final Map<Class<?>, Coupled> views) { Class<?> type = null; for (final Map.Entry<Class<?>, Coupled> entry : views.entrySet()) { if (entry.getValue() == this) { final Class<?> t = Classes.findCommonClass(type, entry.getKey()); if (t != Object.class) type = t; } } appendTo.setValue(TableColumn.NAME, Classes.getShortName(type)); appendTo.setValue(TableColumn.VALUE, Classes.getShortClassName(view)); if (wrappedBy != null) { for (final Coupled c : wrappedBy) { c.append(appendTo.newChild(), views); } } } }
/** * Returns a string representation of this {@code StorageConnector} for debugging purpose. * This string representation is for debugging purpose only and may change in any future version. * * @return a string representation of this {@code StorageConnector} for debugging purpose. */ @Override public String toString() { final TreeTable table = new DefaultTreeTable(TableColumn.NAME, TableColumn.VALUE); final TreeTable.Node root = table.getRoot(); root.setValue(TableColumn.NAME, Classes.getShortClassName(this)); root.setValue(TableColumn.VALUE, getStorageName()); if (options != null) { final TreeTable.Node op = root.newChild(); op.setValue(TableColumn.NAME, "options"); op.setValue(TableColumn.VALUE, options); } final Coupled c = getView(null); if (c != null) { c.append(root.newChild(), views); } return table.toString(); } }
/** * Returns a string representation of this {@code StorageConnector} for debugging purpose. * This string representation is for debugging purpose only and may change in any future version. * * @return a string representation of this {@code StorageConnector} for debugging purpose. */ @Debug @Override public String toString() { final TreeTable table = new DefaultTreeTable(TableColumn.NAME, TableColumn.VALUE); final TreeTable.Node root = table.getRoot(); root.setValue(TableColumn.NAME, Classes.getShortClassName(this)); root.setValue(TableColumn.VALUE, getStorageName()); if (options != null) { final TreeTable.Node op = root.newChild(); op.setValue(TableColumn.NAME, "options"); op.setValue(TableColumn.VALUE, options); } final Coupled c = getView(null); if (c != null) { c.append(root.newChild(), views); } return table.toString(); } }
/** * The {@code concatenateSingletons(…)} example documented in the {@link TreeTables} class javadoc. * This simple code assumes that the children collection in the given node is a {@link List}. * * @param node the root of the node to simplify. * @return the root of the simplified tree. May be the given {@code node} or a child. */ public static TreeTable.Node concatenateSingletons(final TreeTable.Node node) { final List<TreeTable.Node> children = (List<TreeTable.Node>) node.getChildren(); final int size = children.size(); for (int i=0; i<size; i++) { children.set(i, concatenateSingletons(children.get(i))); } if (size == 1) { final TreeTable.Node child = children.get(0); if (node.getValue(VALUE_AS_TEXT) == null) { children.remove(0); child.setValue(NAME, node.getValue(NAME) + File.separator + child.getValue(NAME)); return child; } } return node; }
/** * Parses the given string using a format appropriate for the type of values in * the given column, and stores the value in the given node. * * <p>This work is done in a separated method instead than inlined in the * {@code parse(…)} method because of the {@code <V>} parametric value.</p> * * @param <V> the type of values in the given column. * @param node the node in which to set the value. * @param column the column in which to set the value. * @param format the format to use for parsing the value, or {@code null}. * @param text the textual representation of the value. * @throws ParseException if an error occurred while parsing. * @throws ClassCastException if the parsed value is not of the expected type. */ private <V> void parseValue(final TreeTable.Node node, final TableColumn<V> column, final Format format, final String text) throws ParseException { final Object value; if (format != null) { value = format.parseObject(text); } else { value = text; } node.setValue(column, column.getElementType().cast(value)); }
/** * Tests {@link DefaultTreeTable#clone()}. * This will also indirectly tests {@link DefaultTreeTable#equals(Object)}. * * <p>This method is part of a chain. * The previous method is {@link #testNodeDisplacement(TreeTable.Node)}.</p> * * @param table the table to clone. * @throws CloneNotSupportedException if the table can not be cloned. */ @TestStep public static void testClone(final DefaultTreeTable table) throws CloneNotSupportedException { final TreeTable newTable = table.clone(); assertNotSame("clone", table, newTable); assertEquals("newTable.equals(table)", table, newTable); assertEquals("hashCode", table.hashCode(), newTable.hashCode()); getChildrenList(newTable).get(1).setValue(NAME, "New name"); assertFalse("newTable.equals(table)", newTable.equals(table)); }
/** * Search in given tree node direct children for a node with a table column equals to some specific value. * If we cannot find any matching, we add a new child into input node, initiated with the wanted value. * @param <T> Table column value type. * @param parent Node to search into (only direct children) * @param searchCriteria The table column to search in. * @param searchValue Searched value. * @return A matching node, created if necessary. */ public static <T> TreeTable.Node getOrCreateNode(final TreeTable.Node parent, final TableColumn<T> searchCriteria, final T searchValue) { for (final TreeTable.Node n : parent.getChildren()) { if (searchValue.equals(n.getValue(searchCriteria))) { return n; } } final TreeTable.Node newChild = parent.newChild(); newChild.setValue(searchCriteria, searchValue); return newChild; } }
/** * Returns a tree representation of some elements of this grid geometry. * The tree representation is for debugging purpose only and may change * in any future SIS version. * * @param locale the locale to use for textual labels. * @param bitmask combination of {@link #EXTENT}, {@link #ENVELOPE}, * {@link #CRS}, {@link #GRID_TO_CRS} and {@link #RESOLUTION}. * @return a tree representation of the specified elements. */ @Debug public TreeTable toTree(final Locale locale, final int bitmask) { final TreeTable tree = new DefaultTreeTable(TableColumn.VALUE_AS_TEXT); final TreeTable.Node root = tree.getRoot(); root.setValue(TableColumn.VALUE_AS_TEXT, Classes.getShortClassName(this)); formatTo(locale, Vocabulary.getResources(locale), bitmask, root); return tree; }
/** * Tests {@link DefaultTreeTable} serialization. * * <p>This method is part of a chain. * The previous method is {@link #testNodeDisplacement(TreeTable.Node)}.</p> * * @param table the table to serialize. */ @TestStep public static void testSerialization(final TreeTable table) { final TreeTable newTable = assertSerializedEquals(table); getChildrenList(newTable).get(1).setValue(NAME, "New name"); assertFalse("newTable.equals(table)", newTable.equals(table)); }
/** * Tests {@link DefaultTreeTable.Node#setValue(TableColumn, Object)}. */ @Test public void testNodeValues() { final DefaultTreeTable table = new DefaultTreeTable(NAME, TYPE); final TreeTable.Node node = new DefaultTreeTable.Node(table); assertNull(node.getValue(NAME)); assertNull(node.getValue(TYPE)); node.setValue(NAME, "A number"); node.setValue(TYPE, Number.class); assertEquals("A number", node.getValue(NAME)); assertEquals(Number.class, node.getValue(TYPE)); } }
/** * Adds a simplified tree representation of this {@code FallbackConverter} to the given node. * * @param addTo the node in which to add the converter. * @param isNew {@code true} if {@code addTo} is a newly created node. */ final void toTree(final TreeTable.Node addTo, final boolean isNew) { if (isNew) { addTo.setValue(Column.SOURCE, sourceClass); addTo.setValue(Column.TARGET, targetClass); } toTree(primary, addTo); toTree(fallback, addTo); }
/** * Invoked recursively for formatting the given type in the given tree. * This method does not perform any check against infinite recursivity * on the assumption that subclasses verified this constraint by calls * to {@link #checkForCycles()}. */ private static void format(final AbstractLocationType type, final TreeTable.Node node) { node.setValue(TableColumn.NAME, type.getName()); node.setValue(TableColumn.VALUE_AS_TEXT, type.getDefinition()); for (final AbstractLocationType child : type.getChildren()) { format(child, node.newChild()); } } }
/** * Adds a child of the given name to the given parent node. * This is a convenience method for {@code toString()} implementations. * * @param parent the node where to add a child. * @param name the name to assign to the child. * @return the child added to the parent. */ @Debug static TreeTable.Node newChild(final TreeTable.Node parent, final String name) { final TreeTable.Node child = parent.newChild(); child.setValue(TableColumn.NAME, name); return child; }
/** * Creates a node for the given converter and adds it to the given tree. * Used by {@link FallbackConverter} and {@link ConverterRegistry} for * implementing their {@code toString()} method. * * @param converter the converter for which to create a tree. * @param addTo the node in which to add the converter. */ static void toTree(final ObjectConverter<?,?> converter, final TreeTable.Node addTo) { final TreeTable.Node node = addTo.newChild(); node.setValue(SOURCE, converter.getSourceClass()); node.setValue(TARGET, converter.getTargetClass()); }
/** * Adds a simplified tree representation of this {@code FallbackConverter} to the given node. * * @param addTo the node in which to add the converter. * @param isNew {@code true} if {@code addTo} is a newly created node. */ final void toTree(final TreeTable.Node addTo, final boolean isNew) { if (isNew) { addTo.setValue(Column.SOURCE, sourceClass); addTo.setValue(Column.TARGET, targetClass); } toTree(primary, addTo); toTree(fallback, addTo); }
/** * Creates a node for the given converter and adds it to the given tree. * Used by {@link FallbackConverter} and {@link ConverterRegistry} for * implementing their {@code toString()} method. * * @param converter the converter for which to create a tree. * @param addTo the node in which to add the converter. */ static void toTree(final ObjectConverter<?,?> converter, final TreeTable.Node addTo) { final TreeTable.Node node = addTo.newChild(); node.setValue(SOURCE, converter.getSourceClass()); node.setValue(TARGET, converter.getTargetClass()); }