/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.sis.util.collection;

import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.Currency;
import java.util.ConcurrentModificationException;
import java.util.function.Predicate;
import java.io.IOException;
import java.text.Format;
import java.text.DecimalFormat;
import java.text.ParsePosition;
import java.text.ParseException;
import java.util.regex.Matcher;
import org.opengis.util.CodeList;
import java.nio.charset.Charset;
import org.opengis.util.Type;
import org.opengis.util.Record;
import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
import org.apache.sis.io.LineAppender;
import org.apache.sis.io.TableAppender;
import org.apache.sis.io.TabularFormat;
import org.apache.sis.io.CompoundFormat;
import org.apache.sis.measure.UnitFormat;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.Workaround;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.math.DecimalFunctions;
import org.apache.sis.internal.util.Acyclic;
import org.apache.sis.internal.util.MetadataServices;
import org.apache.sis.internal.util.LocalizedParseException;
import org.apache.sis.internal.util.TreeFormatCustomization;

import static org.apache.sis.util.Characters.NO_BREAK_SPACE;


/**
 * A parser and formatter for {@link TreeTable} instances.
 * This formatter is given an arbitrary number of {@link TableColumn}s
 * to use during the formatting. The first column is taken as the node label.
 * If a {@code TreeTable} is formatted with only that column,
 * then the {@link String} result is like the following example:
 *
 * {@preformat text
 *   Node #1
 *     ├─Node #2
 *     │   └─Node #4
 *     └─Node #3
 * }
 *
 * If the same {@code TreeTable} is formatted with two columns,
 * then the {@link String} result is like the following example:
 *
 * {@preformat text
 *   Node #1……………………… More #1
 *     ├─Node #2…………… More #2
 *     │   └─Node #4… More #4
 *     └─Node #3…………… More #3
 * }
 *
 * This representation can be printed to the {@linkplain java.io.Console#writer() console output}
 * (for example) if the stream uses a monospaced font and supports Unicode characters.
 *
 * <h2>Customization</h2>
 * Some formatting characteristics (indentation width, column where to draw the vertical line
 * below nodes) can be modified by calls to the setter methods defined in this formatter.
 * In particular, the dots joining the node labels to their values can be specified by the
 * {@linkplain #setColumnSeparatorPattern(String) column separator pattern}.
 * The default pattern is {@code "?……[…] "}, which means <cite>"If the next value is non-null,
 * then insert the {@code "……"} string, repeat the {@code '…'} character as many time as needed
 * (may be zero), and finally insert a space"</cite>.
 *
 * <h2>Safety against infinite recursivity</h2>
 * Some {@code TreeTable} implementations generate the nodes dynamically as wrappers around Java objects.
 * Such Java objects may contain cyclic associations (<var>A</var> contains <var>B</var> contains <var>C</var>
 * contains <var>A</var>), which result in a tree of infinite depth. Some examples can been found in ISO 19115
 * metadata. This {@code TreeTableFormat} class contains a safety against such cycles. The algorithm is based
 * on the assumption that for each node, the values and children are fully determined by the
 * {@linkplain TreeTable.Node#getUserObject() user object}, if non-null. Consequently for each node <var>C</var>
 * to be formatted, if the user object of that node is the same instance (in the sense of the {@code ==} operator)
 * than the user object of a parent node <var>A</var>, then the children of the <var>C</var> node will not be formatted.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 * @since   0.3
 * @module
 */
public class TreeTableFormat extends TabularFormat<TreeTable> {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 147992015470098561L;

    /**
     * Shared {@code TreeTableFormat} instance for {@link DefaultTreeTable#toString()} implementation.
     * Usage of this instance shall be done in a synchronized block. Note that metadata objects defined
     * as {@link org.apache.sis.metadata.AbstractMetadata} subclasses use their own format instance.
     */
    static final TreeTableFormat INSTANCE = new TreeTableFormat(null, null);

    /**
     * The table columns to format, or {@code null} for formatting all of them.
     * This map shall not be modified after creation, because it may be shared
     * by many tables.
     *
     * @see #getColumns()
     * @see #setColumns(TableColumn[])
     */
    private Map<TableColumn<?>,Integer> columnIndices;

    /**
     * The number of characters to add on the left side for each indentation level.
     * The default value is 4.
     *
     * @see #getIndentation()
     * @see #setIndentation(int)
     */
    private int indentation;

    /**
     * The position of the vertical line, relative to the position of the label of the parent node.
     * The default value is 2, which means that the vertical line is drawn below the third letter
     * of the node label.
     *
     * @see #getVerticalLinePosition()
     * @see #setVerticalLinePosition(int)
     */
    private int verticalLinePosition;

    /**
     * The tree symbols to write in the left margin, or {@code null} if not yet computed.
     * The default symbols are as below:
     *
     * <ul>
     *   <li>{@code treeBlank} = {@code "    "}</li>
     *   <li>{@code treeLine}  = {@code "  │ "}</li>
     *   <li>{@code treeCross} = {@code "  ├─"}</li>
     *   <li>{@code treeEnd}   = {@code "  └─"}</li>
     * </ul>
     *
     * @see #clearTreeSymbols()
     * @see #createTreeSymbols()
     */
    private transient String treeBlank, treeLine, treeCross, treeEnd;

    /**
     * A filter for specifying whether a node should be formatted, or {@code null} if no filtering is applied.
     * This is ignored at parsing time.
     *
     * @see #getNodeFilter()
     * @see #setNodeFilter(Predicate)
     */
    private Predicate<TreeTable.Node> nodeFilter;

    /**
     * The set to be given to {@link Writer} constructor,
     * created when first needed and reused for subsequent formatting.
     */
    private transient Set<TreeTable.Node> recursivityGuard;

    /**
     * A clone of the number format to be used with different settings (number of fraction digits, scientific notation).
     * We use a clone for avoiding to change the setting of potentially user-supplied number format. This is used only
     * for floating point numbers, not for integers.
     */
    private transient DecimalFormat adaptableFormat;

    /**
     * The default pattern used by {@link #adaptableFormat}.
     * Used for switching back to default mode after scientific notation.
     */
    private transient String defaultPattern;

    /**
     * Whether {@link #adaptableFormat} is using scientific notation.
     */
    private transient boolean usingScientificNotation;

    /**
     * Creates a new tree table format.
     *
     * @param locale    the locale to use for numbers, dates and angles formatting,
     *                  or {@code null} for the {@linkplain Locale#ROOT root locale}.
     * @param timezone  the timezone, or {@code null} for UTC.
     */
    public TreeTableFormat(final Locale locale, final TimeZone timezone) {
        super(locale, timezone);
        indentation          = 4;
        verticalLinePosition = 2;
        beforeFill           = "……";
        fillCharacter        = '…';
        omitTrailingNulls    = true;
    }

    /**
     * Clears the symbols used when writing the tree.
     * They will be computed again when first needed.
     *
     * @see #createTreeSymbols()
     */
    private void clearTreeSymbols() {
        treeBlank = null;
        treeLine  = null;
        treeCross = null;
        treeEnd   = null;
    }

    /**
     * Returns the type of objects formatted by this class.
     *
     * @return {@code TreeTable.class}
     */
    @Override
    public final Class<TreeTable> getValueType() {
        return TreeTable.class;
    }

    /**
     * Returns the table columns to parse and format, or {@code null} for the default list of columns.
     * The default is:
     *
     * <ul>
     *   <li>On parsing, a single column containing the node label as a {@link String}.</li>
     *   <li>On formatting, {@linkplain TreeTable#getColumns() all <code>TreeTable</code> columns}.</li>
     * </ul>
     *
     * @return the table columns to parse and format, or {@code null} for the default.
     */
    public TableColumn<?>[] getColumns() {
        return (columnIndices != null) ? DefaultTreeTable.getColumns(columnIndices) : null;
    }

    /**
     * Sets the table columns to parse and format. A {@code null} value means to use the default
     * list of columns, as defined in the {@link #getColumns()} method.
     *
     * @param  columns  the table columns to parse and format, or {@code null} for the default.
     * @throws IllegalArgumentException if the given array is empty, contains a null element
     *         or a duplicated value.
     */
    public void setColumns(final TableColumn<?>... columns) throws IllegalArgumentException {
        if (columns == null) {
            columnIndices = null;
        } else {
            ArgumentChecks.ensureNonEmpty("columns", columns);
            columnIndices = DefaultTreeTable.createColumnIndices(columns);
        }
    }

    /**
     * Returns the number of spaces to add on the left margin for each indentation level.
     * The default value is 4.
     *
     * @return the current indentation.
     */
    public int getIndentation() {
        return indentation;
    }

    /**
     * Sets the number of spaces to add on the left margin for each indentation level.
     * If the new indentation is smaller than the {@linkplain #getVerticalLinePosition()
     * vertical line position}, then the later is also set to the given indentation value.
     *
     * @param  indentation  the new indentation.
     * @throws IllegalArgumentException if the given value is negative.
     */
    public void setIndentation(final int indentation) throws IllegalArgumentException {
        ArgumentChecks.ensurePositive("indentation", indentation);
        this.indentation = indentation;
        if (verticalLinePosition > indentation) {
            verticalLinePosition = indentation;
        }
        clearTreeSymbols();
    }

    /**
     * Returns the position of the vertical line, relative to the position of the root label.
     * The default value is 2, which means that the vertical line is drawn below the third
     * letter of the root label.
     *
     * @return the current vertical line position.
     */
    public int getVerticalLinePosition() {
        return verticalLinePosition;
    }

    /**
     * Sets the position of the vertical line, relative to the position of the root label.
     * The given value can not be greater than the {@linkplain #getIndentation() indentation}.
     *
     * @param  verticalLinePosition  the new vertical line position.
     * @throws IllegalArgumentException if the given value is negative or greater than the indentation.
     */
    public void setVerticalLinePosition(final int verticalLinePosition) throws IllegalArgumentException {
        ArgumentChecks.ensureBetween("verticalLinePosition", 0, indentation, verticalLinePosition);
        this.verticalLinePosition = verticalLinePosition;
        clearTreeSymbols();
    }

    /**
     * Returns the filter that specify whether a node should be formatted or ignored.
     * This is the predicate specified in the last call to {@link #setNodeFilter(Predicate)}.
     * If no filter has been set, then this method returns {@code null}.
     *
     * @return a filter for specifying whether a node should be formatted, or {@code null} if no filtering is applied.
     *
     * @since 1.0
     */
    public Predicate<TreeTable.Node> getNodeFilter() {
        return nodeFilter;
    }

    /**
     * Sets a filter specifying whether a node should be formatted or ignored.
     * Filters are tested at formatting time for all children of the root node (but not for the root node itself).
     * Filters are ignored at parsing time.
     *
     * @param  filter  filter for specifying whether a node should be formatted, or {@code null} for no filtering.
     *
     * @since 1.0
     */
    public void setNodeFilter(final Predicate<TreeTable.Node> filter) {
        this.nodeFilter = filter;
    }

    /**
     * Returns the locale to use for code lists, international strings and exception messages.
     */
    final Locale getDisplayLocale() {
        return getLocale(Locale.Category.DISPLAY);
    }

    /**
     * Returns the formats to use for parsing and formatting the values of each column.
     * The returned array may contain {@code null} elements, which means that the values
     * in that column can be stored as {@code String}s.
     *
     * @param  mandatory  {@code true} if an exception shall be thrown for unrecognized types, or
     *                    {@code false} for storing a {@code null} value in the array instead.
     * @throws IllegalStateException if {@code mandatory} is {@code true} and a column
     *         contains values of an unsupported type.
     */
    final Format[] getFormats(final TableColumn<?>[] columns, final boolean mandatory) throws IllegalStateException {
        final Format[] formats = new Format[columns.length];
        for (int i=0; i<formats.length; i++) {
            final Class<?> valueType = columns[i].getElementType();
            if ((formats[i] = getFormat(valueType)) == null) {
                if (mandatory && !valueType.isAssignableFrom(String.class)) {
                    throw new IllegalStateException(Errors.format(
                            Errors.Keys.UnspecifiedFormatForClass_1, valueType));
                }
            }
        }
        return formats;
    }

    /**
     * Creates a tree from the given character sequence,
     * or returns {@code null} if the given text does not look like a tree for this method.
     * This method can parse the trees created by the {@code format(…)} methods
     * defined in this class.
     *
     * <h4>Parsing rules</h4>
     * <ul>
     *   <li>Each node shall be represented by a single line made of two parts, in that order:
     *     <ol>
     *       <li>white spaces and tree drawing characters ({@code '│'}, {@code '├'}, {@code '└'} or {@code '─'});</li>
     *       <li>string representations of node values, separated by the
     *           {@linkplain #getColumnSeparatorPattern() colunm separator}.</li>
     *     </ol>
     *   </li>
     *   <li>The number of spaces and drawing characters before the node values determines the node
     *       indentation. This indentation does not need to be a factor of the {@link #getIndentation()}
     *       value, but must be consistent across all the parsed tree.</li>
     *   <li>The indentation determines the parent of each node.</li>
     *   <li>Parsing stops at first empty line (ignoring whitespaces), or at the end of the given text.</li>
     * </ul>
     *
     * <h4>Error index</h4>
     * If the given text does not seem to be a tree table, then this method returns {@code null}.
     * Otherwise if parsing started but failed, then:
     *
     * <ul>
     *   <li>{@link ParsePosition#getErrorIndex()} will give the index at the beginning
     *       of line or beginning of cell where the error occurred, and</li>
     *   <li>{@link ParseException#getErrorOffset()} will give either the same value,
     *       or a slightly more accurate value inside the cell.</li>
     * </ul>
     *
     * @param  text  the character sequence for the tree to parse.
     * @param  pos   the position where to start the parsing.
     * @return the parsed tree, or {@code null} if the given character sequence can not be parsed.
     * @throws ParseException if an error occurred while parsing a node value.
     */
    @Override
    @SuppressWarnings("null")
    public TreeTable parse(final CharSequence text, final ParsePosition pos) throws ParseException {
        final Matcher matcher   = getColumnSeparatorMatcher(text);
        final int length        = text.length();
        int indexOfLineStart    = pos.getIndex();
        int indentationLevel    = 0;                // Current index in the 'indentations' array.
        int[] indentations      = new int[16];      // Number of spaces (ignoring drawing characters) for each level.
        TreeTable.Node lastNode = null;             // Last parsed node, having 'indentation[level]' characters before its content.
        TreeTable.Node root     = null;             // First node found while parsing.
        final DefaultTreeTable table = new DefaultTreeTable(columnIndices != null ? columnIndices : TableColumn.NAME_MAP);
        final TableColumn<?>[] columns = DefaultTreeTable.getColumns(table.columnIndices);
        final Format[] formats = getFormats(columns, true);
        do {
            final int startNextLine = CharSequences.indexOfLineStart(text, 1, indexOfLineStart);
            int endOfLine = startNextLine;
            while (endOfLine > indexOfLineStart) {
                final int c = text.charAt(endOfLine-1);
                if (c != '\r' && c != '\n') break;
                endOfLine--;                                    // Skip trailing '\r' and '\n'.
            }
            /*
             * Skip leading spaces using Character.isSpaceChar(…) instead than isWhitespace(…)
             * because we need to skip non-breaking spaces as well as ordinary space. We don't
             * need to consider line feeds since they were handled by the lines just above.
             */
            boolean hasChar = false;
            int i;                                              // The indentation of current line.
            for (i=indexOfLineStart; i<endOfLine;) {
                final int c = Character.codePointAt(text, i);
                if (!Character.isSpaceChar(c)) {
                    hasChar = true;
                    if ("─│└├".indexOf(c) < 0) {
                        break;
                    }
                }
                i += Character.charCount(c);
            }
            if (!hasChar) {
                break;                                          // The line contains only whitespaces.
            }
            /*
             * Go back to the fist non-space character (should be '─'). We do that in case the
             * user puts some spaces in the text of the node label, since we don't want those
             * user-spaces to interfer with the calculation of indentation.
             */
            int indexOfValue = i;
            i = CharSequences.skipTrailingWhitespaces(text, indexOfLineStart, i) - indexOfLineStart;
            /*
             * Found the first character which is not part of the indentation. Create a new root
             * (without parent for now) and parse the values for each column. Columns with empty
             * text are not parsed (the value is left to null).
             */
            final TreeTable.Node node = new DefaultTreeTable.Node(table);
            matcher.region(indexOfValue, endOfLine);
            for (int ci=0; ci<columns.length; ci++) {
                final boolean found = matcher.find();
                int endOfColumn = found ? matcher.start() : endOfLine;
                indexOfValue   = CharSequences.skipLeadingWhitespaces (text, indexOfValue, endOfColumn);
                int endOfValue = CharSequences.skipTrailingWhitespaces(text, indexOfValue, endOfColumn);
                if (endOfValue > indexOfValue) {
                    final String valueText = text.subSequence(indexOfValue, endOfValue).toString();
                    try {
                        parseValue(node, columns[ci], formats[ci], valueText);
                    } catch (ParseException | ClassCastException e) {
                        pos.setErrorIndex(indexOfValue);                                    // See method javadoc.
                        if (e instanceof ParseException) {
                            indexOfValue += ((ParseException) e).getErrorOffset();
                        }
                        throw new LocalizedParseException(getDisplayLocale(), Errors.Keys.UnparsableStringForClass_2,
                                new Object[] {columns[ci].getElementType(), valueText}, indexOfValue).initCause(e);
                    }
                }
                if (!found) break;
                /*
                 * The end of this column will be the beginning of the next column,
                 * after skipping the last character of the column separator.
                 */
                indexOfValue = matcher.end();
            }
            /*
             * If this is the first node created so far, it will be the root.
             */
            if (root == null) {
                indentations[0] = i;
                root = node;
            } else {
                int p;
                while (i < (p = indentations[indentationLevel])) {
                    /*
                     * Lower indentation level: go up in the tree until we find the new parent.
                     * Note that lastNode.getParent() should never return null, since only the
                     * node at 'indentationLevel == 0' has a null parent and we check that case.
                     */
                    if (--indentationLevel < 0) {
                        pos.setErrorIndex(indexOfLineStart);
                        throw new LocalizedParseException(getDisplayLocale(),
                                Errors.Keys.NodeHasNoParent_1, new Object[] {node}, indexOfLineStart);
                    }
                    lastNode = lastNode.getParent();
                }
                if (i == p) {
                    /*
                     * The node we just created is a sibling of the previous node. This is
                     * illegal if level==0, in which case we have no parent. Otherwise add
                     * the sibling to the common parent and let the indentation level unchanged.
                     */
                    final TreeTable.Node parent = lastNode.getParent();
                    if (parent == null) {
                        pos.setErrorIndex(indexOfLineStart);
                        throw new LocalizedParseException(getDisplayLocale(),
                                Errors.Keys.NodeHasNoParent_1, new Object[] {node}, indexOfLineStart);
                    }
                    parent.getChildren().add(node);
                } else if (i > p) {
                    /*
                     * The node we just created is a child of the previous node.
                     * Add a new indentation level.
                     */
                    lastNode.getChildren().add(node);
                    if (++indentationLevel == indentations.length) {
                        indentations = Arrays.copyOf(indentations, indentationLevel*2);
                    }
                    indentations[indentationLevel] = i;
                }
            }
            lastNode = node;
            indexOfLineStart = startNextLine;
        } while (indexOfLineStart != length);
        if (root == null) {
            return null;
        }
        pos.setIndex(indexOfLineStart);
        table.setRoot(root);
        return table;
    }

    /**
     * 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));
    }

    /**
     * Computes the {@code tree*} fields from the {@link #indentation} and
     * {@link #verticalLinePosition} current values.
     *
     * @see #clearTreeSymbols()
     */
    private void createTreeSymbols() {
        final int indentation = this.indentation;
        final int verticalLinePosition = this.verticalLinePosition;
        final char[] buffer = new char[indentation];
        for (int k=0; k<4; k++) {
            final char vc, hc;
            if ((k & 2) == 0) {
                // No horizontal line
                vc = (k & 1) == 0 ? NO_BREAK_SPACE : '│';
                hc = NO_BREAK_SPACE;
            } else {
                // With a horizontal line
                vc = (k & 1) == 0 ? '└' : '├';
                hc = '─';
            }
            Arrays.fill(buffer, 0, verticalLinePosition, NO_BREAK_SPACE);
            buffer[verticalLinePosition] = vc;
            Arrays.fill(buffer, verticalLinePosition + 1, indentation, hc);
            final String symbols = String.valueOf(buffer);
            switch (k) {
                case 0: treeBlank = symbols; break;
                case 1: treeLine  = symbols; break;
                case 2: treeEnd   = symbols; break;
                case 3: treeCross = symbols; break;
                default: throw new AssertionError(k);
            }
        }
    }

    /**
     * Returns the string to write before a node.
     *
     * @param isParent {@code true} for a parent node, or {@code false} for the actual node.
     * @param isLast   {@code true} if the node is the last children of its parent node.
     */
    final String getTreeSymbols(final boolean isParent, final boolean isLast) {
        return(isParent ? (isLast ? treeBlank : treeLine)
                        : (isLast ? treeEnd   : treeCross));
    }

    /**
     * Creates string representation of the node values. Tabulations are replaced by spaces,
     * and line feeds are replaced by the Pilcrow character. This is necessary in order to
     * avoid conflict with the characters expected by {@link TableAppender}.
     *
     * <p>Instances of {@link Writer} are created temporarily before to begin the formatting
     * of a node, and discarded when the formatting is finished.</p>
     */
    private final class Writer extends LineAppender {
        /**
         * Combination of {@link #nodeFilter} with other filter that may be specified by the tree table to format.
         * The {@code TreeTable}-specific filter is specified by {@link TreeFormatCustomization}.
         */
        private final Predicate<TreeTable.Node> filter;

        /**
         * The columns to write.
         */
        private final TableColumn<?>[] columns;

        /**
         * The format to use for each column.
         */
        private final Format[] formats;

        /**
         * The node values to format.
         */
        private final Object[] values;

        /**
         * For each indentation level, {@code true} if the previous levels are writing the last node.
         * This array will growth as needed.
         */
        private boolean[] isLast;

        /**
         * Whether to allows multi-lines cells instead than using Pilcrow character.
         * This is currently supported only if the number of columns is less than 2.
         */
        private final boolean multiLineCells;

        /**
         * The node that have already been formatted. We use this map as a safety against infinite recursivity.
         */
        private final Set<TreeTable.Node> recursivityGuard;

        /**
         * The format for the column in process of being written. This is a format to use for the column as a whole.
         * This field is updated for every new column to write. May be {@code null} if the format is unspecified.
         */
        private transient Format columnFormat;

        /**
         * Creates a new instance which will write to the given appendable.
         *
         * @param  out               where to format the tree.
         * @param  tree              the tree table to format.
         * @param  columns           the columns of the tree table to format.
         * @param  recursivityGuard  an initially empty set.
         */
        Writer(final Appendable out, final TreeTable tree, final TableColumn<?>[] columns,
               final Set<TreeTable.Node> recursivityGuard)
        {
            super(columns.length >= 2 ? new TableAppender(out, "") : out);
            multiLineCells = (super.out == out);
            this.columns = columns;
            this.formats = getFormats(columns, false);
            this.values  = new Object[columns.length];
            this.isLast  = new boolean[8];
            this.recursivityGuard = recursivityGuard;
            Predicate<TreeTable.Node> filter = nodeFilter;
            if (tree instanceof TreeFormatCustomization) {
                final TreeFormatCustomization custom = (TreeFormatCustomization) tree;
                final Predicate<TreeTable.Node> more = custom.filter();
                if (more != null) {
                    filter = (filter != null) ? more.and(filter) : more;
                }
            } else {
            }
            this.filter = filter;
            setTabulationExpanded(true);
            setLineSeparator(multiLineCells ? TreeTableFormat.this.getLineSeparator() : " ¶ ");
        }

        /**
         * Localizes the given name in the display locale, or returns "(Unnamed)" if no localized value is found.
         */
        private String toString(final GenericName name) {
            final Locale locale = getDisplayLocale();
            if (name != null) {
                final InternationalString i18n = name.toInternationalString();
                if (i18n != null) {
                    final String localized = i18n.toString(locale);
                    if (localized != null) {
                        return localized;
                    }
                }
                final String localized = name.toString();
                if (localized != null) {
                    return localized;
                }
            }
            return '(' + Vocabulary.getResources(locale).getString(Vocabulary.Keys.Unnamed) + ')';
        }

        /**
         * Appends a textual representation of the given value.
         *
         * @param  value      the value to format (may be {@code null}).
         * @param  recursive  {@code true} if this method is invoking itself for writing collection values.
         */
        private void formatValue(final Object value, final boolean recursive) throws IOException {
            final CharSequence text;
            if (value == null) {
                text = " ";                                             // String for missing value.
            } else if (columnFormat != null) {
                if (columnFormat instanceof CompoundFormat<?>) {
                    formatValue((CompoundFormat<?>) columnFormat, value);
                    return;
                }
                text = columnFormat.format(value);
            } else if (value instanceof InternationalString) {
                text = ((InternationalString) value).toString(getDisplayLocale());
            } else if (value instanceof CharSequence) {
                text = value.toString();
            } else if (value instanceof CodeList<?>) {
                text = MetadataServices.getInstance().getCodeTitle((CodeList<?>) value, getDisplayLocale());
            } else if (value instanceof Enum<?>) {
                text = CharSequences.upperCaseToSentence(((Enum<?>) value).name());
            } else if (value instanceof Type) {
                text = toString(((Type) value).getTypeName());
            } else if (value instanceof Locale) {
                final Locale locale = getDisplayLocale();
                text = (locale != Locale.ROOT) ? ((Locale) value).getDisplayName(locale) : value.toString();
            } else if (value instanceof TimeZone) {
                final Locale locale = getDisplayLocale();
                text = (locale != Locale.ROOT) ? ((TimeZone) value).getDisplayName(locale) : ((TimeZone) value).getID();
            } else if (value instanceof Charset) {
                final Locale locale = getDisplayLocale();
                text = (locale != Locale.ROOT) ? ((Charset) value).displayName(locale) : ((Charset) value).name();
            } else if (value instanceof Currency) {
                final Locale locale = getDisplayLocale();
                text = (locale != Locale.ROOT) ? ((Currency) value).getDisplayName(locale) : value.toString();
            } else if (value instanceof Record) {
                formatCollection(((Record) value).getAttributes().values(), recursive);
                return;
            } else if (value instanceof Iterable<?>) {
                formatCollection((Iterable<?>) value, recursive);
                return;
            } else if (value instanceof Object[]) {
                formatCollection(Arrays.asList((Object[]) value), recursive);
                return;
            } else if (value instanceof Map.Entry<?,?>) {
                final Map.Entry<?,?> entry = (Map.Entry<?,?>) value;
                final Object k = entry.getKey();
                final Object v = entry.getValue();
                if (k == null) {
                    append(null);
                } else {
                    formatValue(k, recursive);
                }
                if (v != null) {
                    append(" → ");
                    formatValue(v, recursive);
                }
                return;
            } else {
                /*
                 * Check for a value-by-value format only as last resort. If a column-wide format was specified by
                 * the 'columnFormat' field, that format should have been used by above code in order to produce a
                 * more uniform formatting.
                 */
                final Format format = getFormat(value.getClass());
                if (format instanceof DecimalFormat && Numbers.isFloat(value.getClass())) {
                    final double number = ((Number) value).doubleValue();
                    if (number != (int) number) {   // Cast to 'int' instead of 'long' as a way to limit to about 2E9.
                        /*
                         * The default floating point format uses only 3 fraction digits. We adjust that to the number
                         * of digits required by the number to format. We do that only if no NumberFormat was inferred
                         * for the whole column (in order to keep column format uniform).  We use enough precision for
                         * all fraction digits except the last 2, in order to let DecimalFormat round the number.
                         */
                        if (adaptableFormat == null) {
                            adaptableFormat = (DecimalFormat) format.clone();
                            defaultPattern = adaptableFormat.toPattern();
                        }
                        final int nf = DecimalFunctions.fractionDigitsForValue(number);
                        final boolean preferScientificNotation = (nf > 20 || nf < 7);       // == (value < 1E-4 || value > 1E+9)
                        if (preferScientificNotation != usingScientificNotation) {
                            usingScientificNotation = preferScientificNotation;
                            adaptableFormat.applyPattern(preferScientificNotation ? "0.0############E0" : defaultPattern);
                        }
                        if (!preferScientificNotation) {
                            adaptableFormat.setMaximumFractionDigits(nf - 2);       // All significand fraction digits except last two.
                        }
                        text = adaptableFormat.format(value);
                    } else {
                        text = format.format(value);
                    }
                } else {
                    text = (format != null) ? format.format(value) : value.toString();
                }
            }
            append(text);
        }

        /**
         * Writes the values of the given collection. A maximum of 10 values will be written.
         * If the collection contains other collections, the other collections will <strong>not</strong>
         * be written recursively.
         */
        private void formatCollection(final Iterable<?> values, final boolean recursive) throws IOException {
            if (values != null) {
                if (recursive) {
                    append('…');                                // Do not format collections inside collections.
                } else {
                    int count = 0;
                    for (final Object value : values) {
                        if (value != null) {
                            if (count != 0) append(", ");
                            formatValue(value, true);
                            if (++count == 10) {                // Arbitrary limit.
                                append(", …");
                                break;
                            }
                        }
                    }
                }
            }
        }

        /**
         * Work around for the inability to define the variable {@code <V>} locally.
         */
        @Workaround(library="JDK", version="1.7")
        private <V> void formatValue(final CompoundFormat<V> format, final Object value) throws IOException {
            format.format(format.getValueType().cast(value), this);
        }

        /**
         * Appends the string representation of the given node and all its children.
         * This method invokes itself recursively.
         *
         * @param  node   the node to format.
         * @param  level  indentation level. The first level is 0.
         */
        final void format(final TreeTable.Node node, final int level) throws IOException {
            /*
             * Draw the lines of the tree in the left margin for current row.
             */
            for (int i=0; i<level; i++) {
                out.append(getTreeSymbols(i != level-1, isLast[i]));
            }
            /*
             * Fetch the values to write in current row, but do not write them now. We fetch values in advance in order
             * to detect trailing null values, so we can avoid formatting trailing blank spaces. Note that a null value
             * may be followed by a non-null value, which is why we need to check all of them before to know how many
             * columns to omit.
             */
            for (int i=0; i<columns.length; i++) {
                values[i] = node.getValue(columns[i]);
            }
            int n = values.length - 1;
            if (omitTrailingNulls) {
                while (n > 0 && values[n] == null) n--;
            }
            /*
             * Format the values that we fetched in above loop.
             */
            for (int i=0; i<=n; i++) {
                if (i != 0) {
                    // We have a TableAppender instance if and only if there is 2 or more columns.
                    writeColumnSeparator(i, (TableAppender) out);
                }
                columnFormat = formats[i];
                formatValue(values[i], false);
                clear();
            }
            out.append(lineSeparator);
            if (level >= isLast.length) {
                isLast = Arrays.copyOf(isLast, level*2);
            }
            /*
             * Format the children only if we do not detect an infinite recursivity. Our recursivity detection
             * algorithm assumes that the Node.equals(Object) method has been implemented as specified in its javadoc.
             * In particular, the implementation may compare the values and children but shall not compare the parent.
             *
             * We skip the check for the particular case of DefaultTreeTable.Node implementation because it performs
             * a real check of values and children, which is a little bit costly and known to be unnecessary in that
             * particular case.
             */
            final boolean omitCheck = node.getClass().isAnnotationPresent(Acyclic.class);
            if (omitCheck || recursivityGuard.add(node)) {
                boolean needLineSeparator = multiLineCells;
                final String lineSeparator = needLineSeparator ? getLineSeparator() : null;
                final Iterator<? extends TreeTable.Node> it = node.getChildren().iterator();
                TreeTable.Node next = next(it);
                while (next != null) {
                    final TreeTable.Node child = next;
                    next = next(it);
                    needLineSeparator |= (isLast[level] = (next == null));
                    if (needLineSeparator && lineSeparator != null) {
                        setLineSeparator(lineSeparator + getTreeSymbols(true, isLast[level]));
                    }
                    format(child, level+1);                     // 'isLast' must be set before to call this method.
                }
                if (lineSeparator != null) {
                    setLineSeparator(lineSeparator);            // Restore previous state.
                }
                if (!omitCheck && !recursivityGuard.remove(node)) {
                    /*
                     * Assuming that Node.hashCode() and Node.equals(Object) implementation are not broken,
                     * this exception may happen only if the node content changed during this method execution.
                     */
                    throw new ConcurrentModificationException();
                }
            } else {
                /*
                 * Detected a recursivity. Format "(cycle omitted)" just below the node.
                 */
                for (int i=0; i<level; i++) {
                    out.append(getTreeSymbols(true, isLast[i]));
                }
                final Locale locale = getDisplayLocale();
                out.append(treeBlank).append('(').append(Vocabulary.getResources(locale)
                   .getString(Vocabulary.Keys.CycleOmitted).toLowerCase(locale))
                   .append(')').append(lineSeparator);
            }
        }

        /**
         * Returns the next filtered element from the given iterator, or {@code null} if none.
         * The filter applied by this method combines {@link #getNodeFilter()} with the filter
         * returned by {@link TreeFormatCustomization#filter()}.
         */
        private TreeTable.Node next(final Iterator<? extends TreeTable.Node> it) {
            while (it.hasNext()) {
                final TreeTable.Node next = it.next();
                if (next != null) {
                    if (filter == null || filter.test(next)) {
                        return next;
                    }
                }
            }
            return null;
        }
   }

    /**
     * Writes a graphical representation of the specified tree table in the given stream or buffer.
     * This method iterates recursively over all {@linkplain TreeTable.Node#getChildren() children}.
     * For each {@linkplain #getColumns() column to format} in each node, this method gets a textual
     * representation of the {@linkplain TreeTable.Node#getValue(TableColumn) value in that column}
     * using the formatter obtained by a call to {@link #getFormat(Class)}.
     *
     * @param  tree        the tree to format.
     * @param  toAppendTo  where to format the tree.
     * @throws IOException if an error occurred while writing to the given appendable.
     *
     * @see TreeTables#toString(TreeTable)
     */
    @Override
    public void format(final TreeTable tree, final Appendable toAppendTo) throws IOException {
        ArgumentChecks.ensureNonNull("tree", tree);
        if (treeBlank == null) {
            createTreeSymbols();
        }
        TableColumn<?>[] columns;
        if (columnIndices != null) {
            columns = DefaultTreeTable.getColumns(columnIndices);
        } else {
            final List<TableColumn<?>> c = tree.getColumns();
            columns = c.toArray(new TableColumn<?>[c.size()]);
        }
        if (recursivityGuard == null) {
            recursivityGuard = new HashSet<>();
        }
        try {
            final Writer out = new Writer(toAppendTo, tree, columns, recursivityGuard);
            out.format(tree.getRoot(), 0);
            out.flush();
        } finally {
            recursivityGuard.clear();
        }
    }

    /**
     * Creates a new format to use for parsing and formatting values of the given type.
     * This method is invoked by the first time that a format is needed for the given type.
     * Subclasses can override this method if they want to configure the way dates, numbers
     * or other objects are formatted.
     * See {@linkplain org.apache.sis.io.CompoundFormat#createFormat(Class) parent class documentation}
     * for more information.
     *
     * <p>The implementation in {@code TreeTableFormat} differs from the default implementation
     * in the following aspects:</p>
     * <ul>
     *   <li>{@code UnitFormat} uses {@link UnitFormat.Style#NAME}.</li>
     * </ul>
     *
     * @param  valueType  the base type of values to parse or format.
     * @return the format to use for parsing of formatting values of the given type, or {@code null} if none.
     */
    @Override
    protected Format createFormat(final Class<?> valueType) {
        final Format format = super.createFormat(valueType);
        if (format instanceof UnitFormat) {
            ((UnitFormat) format).setStyle(UnitFormat.Style.NAME);
        }
        return format;
    }

    /**
     * Writes characters between columns. The default implementation applies the configuration
     * specified by {@link #setColumnSeparatorPattern(String)} as below:
     *
     * <blockquote><code>
     * out.append({@linkplain #beforeFill beforeFill});
     * out.nextColumn({@linkplain #fillCharacter fillCharacter});
     * out.append({@linkplain #columnSeparator columnSeparator});
     * </code></blockquote>
     *
     * The output with default values is like below:
     *
     * {@preformat text
     *   root
     *     └─column0…… column1…… column2…… column3
     * }
     *
     * Subclasses can override this method if different column separators are desired.
     * Note however that doing so may prevent the {@link #parse parse(…)} method to work.
     *
     * @param  nextColumn  zero-based index of the column to be written after the separator.
     * @param  out         where to write the column separator.
     *
     * @see TableAppender#nextColumn(char)
     *
     * @since 1.0
     */
    protected void writeColumnSeparator(final int nextColumn, final TableAppender out) {
        out.append(beforeFill);
        out.nextColumn(fillCharacter);
        out.append(columnSeparator);
    }

    /**
     * Returns a clone of this format.
     *
     * @return a clone of this format.
     */
    @Override
    public TreeTableFormat clone() {
        final TreeTableFormat c = (TreeTableFormat) super.clone();
        c.recursivityGuard = null;
        return c;
    }
}
