Package org.apache.sis.io.wkt

Source Code of org.apache.sis.io.wkt.FormattableObject

/*
* 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.io.wkt;

import java.io.Console;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicReference;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.sis.util.Debug;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.internal.util.X364;


/**
* Base class for objects that can be formatted as <cite>Well Known Text</cite> (WKT).
* {@link WKTFormat} checks for this class at formatting time for each element to format.
* When a {@code FormattableObject} element is found, its {@link #formatTo(Formatter)} method
* is invoked for allowing the element to control its formatting.
*
* <p>This class provides two methods for getting a default <cite>Well Known Text</cite>
* representation of this object:</p>
*
* <ul>
*   <li>{@link #toWKT()} returns a strictly compliant WKT or throws {@link UnformattableObjectException}
*       if this object contains elements not defined by the ISO 19162 standard.</li>
*   <li>{@link #toString()} returns a WKT with some redundant information omitted and some constraints relaxed.
*       This method never throw {@code UnformattableObjectException};
*       it will rather use non-standard representation if necessary.</li>
* </ul>
*
* {@section Syntax coloring}
* A convenience {@link #print()} method is provided, which is roughly equivalent to
* {@code System.out.println(this)} except that syntax coloring is automatically applied
* if the terminal seems to support the ANSI escape codes.
*
* {@section Non-standard WKT}
* If this object can not be formatted without violating some WKT constraints,
* then the behavior depends on the method invoked:
*
* <ul>
*   <li>{@link #toWKT()} will throw a {@link UnformattableObjectException}.</li>
*   <li>{@link #toString()} will ignore the problem and uses non-standard elements if needed.</li>
*   <li>{@link #print()} will show the non-standard elements in red if syntax coloring is enabled.</li>
* </ul>
*
* @author  Martin Desruisseaux (IRD, Geomatys)
* @since   0.4 (derived from geotk-2.0)
* @version 0.4
* @module
*/
@XmlTransient
public abstract class FormattableObject {
    /**
     * The formatter for the {@link #toWKT()} and {@link #toString()} methods. Formatters are not
     * thread-safe, consequently we must make sure that only one thread uses a given instance.
     *
     * <div class="note"><b>Note 1:</b>
     * We do not use synchronization because the formatter will call back user's code, which
     * introduce a risk of thread lock if the user performs his own synchronization.</div>
     *
     * <div class="note"><b>Note 2:</b>
     * We do not use {@link ThreadLocal} because {@code Formatter} is not reentrant neither,
     * so it may produce very confusing behavior when debugging a code that perform WKT formatting
     * (some debuggers seem to invoke {@code toString()} for their own purpose in the same thread).
     * Since {@code toString()} is typically invoked for debugging purpose, a single formatter for
     * any thread is presumed sufficient.</div>
     */
    private static final AtomicReference<Formatter> FORMATTER = new AtomicReference<Formatter>();

    /**
     * Default constructor.
     */
    protected FormattableObject() {
    }

    /**
     * Returns a strictly compliant <cite>Well Known Text</cite> (WKT) using the default convention,
     * symbols and indentation. If this object can not be represented in a standard way, then this
     * method throws an {@link UnformattableObjectException}.
     *
     * <p>By default this method formats this object according the {@link Convention#WKT2} rules.</p>
     *
     * @return The default Well Know Text representation of this object.
     * @throws UnformattableObjectException If this object can not be formatted as a standard WKT.
     *
     * @see org.opengis.referencing.IdentifiedObject#toWKT()
     */
    public String toWKT() throws UnformattableObjectException {
        return formatWKT(Convention.DEFAULT, false, true);
    }

    /**
     * Returns a <cite>Well Known Text</cite> (WKT) or an alternative text representation for this object.
     * If this object can not be represented in a standard way, then this method fallbacks on a non-standard
     * representation.
     *
     * <p>By default this method formats this object according the {@link Convention#WKT2_SIMPLIFIED} rules.</p>
     *
     * @return The Well Known Text (WKT) or an alternative representation of this object.
     */
    @Override
    public String toString() {
        return formatWKT(Convention.WKT2_SIMPLIFIED, false, false);
    }

    /**
     * Returns a <cite>Well Known Text</cite> (WKT) for this object using the specified convention.
     *
     * @param  convention The WKT convention to use.
     * @return The Well Known Text (WKT) or a pseudo-WKT representation of this object.
     */
    public String toString(final Convention convention) {
        ArgumentChecks.ensureNonNull("convention", convention);
        return formatWKT(convention, false, false);
    }

    /**
     * Prints a string representation of this object to the {@linkplain System#out standard output stream}.
     * If a {@linkplain Console console} is attached to the running JVM (i.e. if the application is run
     * from the command-line and the output is not redirected to a file) and if Apache SIS thinks that
     * the console supports the ANSI escape codes (a.k.a. X3.64), then a syntax coloring will be applied.
     *
     * <p>This is a convenience method for debugging purpose and for console applications.</p>
     */
    @Debug
    public void print() {
        final Console console = System.console();
        final PrintWriter out = (console != null) ? console.writer() : null;
        final String wkt = formatWKT(Convention.WKT2_SIMPLIFIED, (out != null) && X364.isAnsiSupported(), false);
        if (out != null) {
            out.println(wkt);
        } else {
            System.out.println(wkt);
        }
    }

    /**
     * Returns a WKT for this object using the specified convention.
     * If {@code strict} is true, then an exception is thrown if the WKT is not standard-compliant.
     *
     * @param  convention  The convention for choosing WKT element names.
     * @param  colorize    {@code true} for applying syntax coloring, or {@code false} otherwise.
     * @param  strict      {@code true} if an exception shall be thrown for unformattable objects,
     *                     or {@code false} for providing a non-standard formatting instead.
     * @return The Well Known Text (WKT) or a pseudo-WKT representation of this object.
     * @throws UnformattableObjectException If {@code strict} is {@code true} and this object can not be formatted.
     */
    final String formatWKT(final Convention convention, final boolean colorize, final boolean strict)
             throws UnformattableObjectException
    {
        Formatter formatter = FORMATTER.getAndSet(null);
        if (formatter == null) {
            formatter = new Formatter();
        }
        formatter.configure(convention, null, colorize ? Colors.DEFAULT : null,
                convention.majorVersion() == 1, WKTFormat.DEFAULT_INDENTATION);
        final String wkt;
        try {
            formatter.append(this);
            if (strict) {
                final String message = formatter.getErrorMessage();
                if (message != null) {
                    throw new UnformattableObjectException(message, formatter.getErrorCause());
                }
            }
            wkt = formatter.toWKT();
        } finally {
            formatter.clear();
        }
        FORMATTER.set(formatter);
        return wkt;
    }

    /**
     * Formats the inner part of this <cite>Well Known Text</cite> (WKT) element into the given formatter.
     * This method is automatically invoked by {@link WKTFormat} when a formattable element is found.
     *
     * <p>Keywords, opening and closing brackets shall not be formatted here.
     * For example if this formattable element is for a {@code GeodeticCRS[…]} element,
     * then this method shall write the content starting at the insertion point shown below:</p>
     *
     * {@preformat text
     *   GeodeticCRS[ ]
     *               ↑
     *       (insertion point)
     * }
     *
     * {@section Formatting non-standard WKT}
     * If the implementation can not represent this object without violating some WKT constraints,
     * it can uses its own (non-standard) keywords but shall declare that it did so by invoking one
     * of the {@link Formatter#setInvalidWKT(IdentifiedObject, Exception) Formatter.setInvalidWKT(…)}
     * methods.
     *
     * <p>Alternatively, the implementation may also have no WKT keyword for this object.
     * This happen frequently when an abstract class defines a base implementation,
     * while the keyword needs to be defined by the concrete subclasses.
     * In such case, the method in the abstract class shall return {@code null}.</p>
     *
     * @param  formatter The formatter where to format the inner content of this WKT element.
     * @return The {@linkplain KeywordCase#CAMEL_CASE CamelCase} keyword for the WKT element, or {@code null} if unknown.
     *
     * @see #toWKT()
     * @see #toString()
     */
    protected abstract String formatTo(Formatter formatter);
}
TOP

Related Classes of org.apache.sis.io.wkt.FormattableObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.