Class WKTFormat

All Implemented Interfaces:
Serializable, Cloneable, Localized
Direct Known Subclasses:
StoreFormat

public class WKTFormat extends CompoundFormat<Object>
Parser and formatter for Well Known Text (WKT) strings. This format handles a pair of Parser and Formatter, used by the parse(…) and format(…) methods respectively. WKTFormat objects allow the following configuration:
  • The preferred authority of object name to format (see Formatter.getNameAuthority() for more information).
  • The symbols to use (curly braces or brackets, etc).
  • The transliterator to use for replacing Unicode characters by ASCII ones.
  • Whether ANSI X3.64 colors are allowed or not (default is not).
  • The indentation.

String expansion

Because the strings to be parsed by this class are long and tend to contain repetitive substrings, WKTFormat provides a mechanism for performing string substitutions before the parsing take place. Long strings can be assigned short names by calls to the addFragment(String, String) method. After fragments have been added, any call to a parsing method will replace all occurrences (except in quoted text) of tokens like $foo by the WKT fragment named "foo".
Example: In the example below, the $WGS84 substring which appear in the argument given to the parseObject(…) method will be expanded into the full GeodeticCRS[“WGS84”, …] string before the parsing proceed.
addFragment("deg", "AngleUnit[“degree”, 0.0174532925199433]");
addFragment("lat", "Axis[“Latitude”, NORTH, $deg]");
addFragment("lon", "Axis[“Longitude”, EAST, $deg]");
addFragment("MyBaseCRS", "GeodeticCRS[“WGS84”, Datum[
…etc… ], CS[ …etc… ], $lat, $lon]");
Object crs = parseObject("ProjectedCRS[“Mercator_1SP”, $MyBaseCRS,
…etc… ]");
Note that the parsing of WKT fragment does not always produce the same object. In particular, the default linear and angular units depend on the context in which the WKT fragment appears.

Limitations

  • The WKT format is not lossless! Objects formatted by WKTFormat are not guaranteed to be identical after parsing. Some metadata may be lost or altered, but the coordinate operations between two CRS should produce the same numerical results provided that the two CRS were formatted independently (do not rely on GeneralDerivedCRS.getConversionFromBase() for instance).
  • Instances of this class are not synchronized for multi-threading. It is recommended to create separated format instances for each thread. If multiple threads access a WKTFormat concurrently, it must be synchronized externally.
  • Serialized objects of this class are not guaranteed to be compatible with future Apache SIS releases. Serialization support is appropriate for short term storage or RMI between applications running the same version of Apache SIS.
Since:
0.4
Version:
1.1
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      For cross-version compatibility.
      See Also:
    • SINGLE_LINE

      public static final int SINGLE_LINE
      The indentation value to give to the setIndentation(int) method for formatting the complete object on a single line.
      See Also:
    • symbols

      private Symbols symbols
      The immutable set of symbols to use for this formatter. The same object is also referenced in the parser and formatter. It appears here for serialization purpose.
      See Also:
    • colors

      private Colors colors
      The immutable set of colors to use for this formatter, or null for no syntax coloring. The default value is null. The same object is also referenced in the formatter. It appears here for serialization purpose.
      See Also:
    • convention

      private Convention convention
      The convention to use. The same object is also referenced in the formatter. It appears here for serialization purpose.
    • authority

      private org.opengis.metadata.citation.Citation authority
      The preferred authority for objects or parameter names. A null value means that the authority shall be inferred from the convention.
    • keywordCase

      private KeywordCase keywordCase
      Whether WKT keywords shall be formatted in upper case.
    • keywordStyle

      private KeywordStyle keywordStyle
      Whether to use short or long WKT keywords.
    • transliterator

      private Transliterator transliterator
      Transliterator.IDENTITY for preserving non-ASCII characters. The default value is Transliterator.DEFAULT, which causes replacements like "é" → "e" in all elements except REMARKS["…"]. May also be a user supplied transliterator.

      A null value means to infer this property from the convention.

    • indentation

      private byte indentation
      The amount of spaces to use in indentation, or -1 if indentation is disabled. The same value is also stored in the formatter. It appears here for serialization purpose.
    • listSizeLimit

      private int listSizeLimit
      Maximum number of elements to show in lists, or Integer.MAX_VALUE if unlimited. If a list is longer than this length, only the first and the last elements will be shown. This limit applies in particular to MathTransform parameter values of double[] type, since those parameters may be large interpolation tables.
      See Also:
    • defaultIdentifier

      private transient DefaultIdentifier defaultIdentifier
      Identifier to assign to parsed IdentifiedObject if the WKT does not contain an explicit ID[…] or AUTHORITY[…] element. The main use case is for implementing a CRSAuthorityFactory backed by definitions in WKT format.

      This field is transient because this is not yet a public API. The transient keyword may be removed in a future version if we commit to this API.

      See Also:
    • fragments

      private Map<String,StoredTree> fragments
      WKT fragments that can be inserted in longer WKT strings, or null if none. Keys are short identifiers and values are WKT subtrees to substitute to the identifiers when they are found in a WKT to parse. The same map instance may be shared by different clones as long as they are not modified.
      See Also:
    • isCloned

      private transient boolean isCloned
      true if the fragments map is shared by two or more WKTFormat instances. In such case, the map shall not be modified; instead it must be copied before any modification.

      Use case

      This flag allows to clone the fragments map only when first needed. In use cases where WKTFormat is cloned for multi-threading purposes without change in its configuration, this flag avoids completely the need to clone the fragments map.
      See Also:
    • sharedValues

      private transient Map<Object,Object> sharedValues
      Temporary map used by addFragment(String, String) for reusing existing instances when possible. Keys and values are the same String, Boolean, Number or Date instances.

      This reference is set to null when we assume that no more fragments will be added to this format. It is not a problem if this map is destroyed too aggressively, since it will be recreated when needed. The only cost of destroying the map too aggressively is that we may have more instance duplications than what we would otherwise have.

    • formatter

      private transient Formatter formatter
      A formatter using the same symbols than the parser. Will be created by the format(Object, Appendable) method when first needed.
    • parser

      private transient AbstractParser parser
      The parser. Will be created when first needed.
    • factories

      private transient ReferencingFactoryContainer factories
      The factories needed by the parser. Those factories are currently not serialized (because usually not serializable), so any value that users may have specified with setFactory(Class, Factory) will be lost at serialization time.
      See Also:
    • warnings

      private transient Warnings warnings
      The warning produced by the last parsing or formatting operation, or null if none.
      See Also:
  • Constructor Details

    • WKTFormat

      public WKTFormat(Locale locale, TimeZone timezone)
      Creates a format for the given locale and timezone. The given locale will be used for InternationalString localization; this is not the locale for number format.
      Parameters:
      locale - the locale for the new Format, or null for Locale.ROOT.
      timezone - the timezone, or null for UTC.
  • Method Details

    • fragments

      private Map<String,StoredTree> fragments(boolean modifiable)
      Returns the fragments map, creating it when first needed. Caller shall not modify the returned map, unless the modifiable parameter is true.
      Parameters:
      modifiable - whether the caller intents to modify the map.
    • factories

      private ReferencingFactoryContainer factories()
      Returns the container of factories, creating it when first needed. This container is needed at parsing time but not at formatting time.
    • getLocale

      public Locale getLocale(Locale.Category category)
      Returns the locale for the given category. This method implements the following mapping:
      Overrides:
      getLocale in class CompoundFormat<Object>
      Parameters:
      category - the category for which a locale is desired.
      Returns:
      the locale for the given category (never null).
    • getErrorLocale

      final Locale getErrorLocale()
      Returns the locale to use for error messages. Other CompoundFormat classes use the system default. But this class uses a compromise: not exactly the locale used for InternationalString because that locale is often fixed to English, and not exactly the system default neither because this "error locale" is also used for warnings. The compromise implemented in this method may change in any future version.
      See Also:
    • getSymbols

      public Symbols getSymbols()
      Returns the symbols used for parsing and formatting WKT. This method returns an unmodifiable instance. Modifications, if desired, should be applied on a clone of the returned object.
      Returns:
      the current set of symbols used for parsing and formatting WKT.
    • setSymbols

      public void setSymbols(Symbols symbols)
      Sets the symbols used for parsing and formatting WKT.
      Parameters:
      symbols - the new set of symbols to use for parsing and formatting WKT.
    • getTransliterator

      public Transliterator getTransliterator()
      Returns a mapper between Java character sequences and the characters to write in WKT. The intent is to specify how to write characters that are not allowed in WKT strings according ISO 19162 specification. Return values can be:
      Returns:
      the mapper between Java character sequences and the characters to write in WKT.
      Since:
      0.6
    • setTransliterator

      public void setTransliterator(Transliterator transliterator)
      Sets the mapper between Java character sequences and the characters to write in WKT.

      If this method is never invoked, or if this method is invoked with a null value, then the default mapper is Transliterator.DEFAULT except for WKT formatted according the internal convention.

      Parameters:
      transliterator - the new mapper to use, or null for restoring the default value.
      Since:
      0.6
    • getKeywordCase

      public KeywordCase getKeywordCase()
      Returns whether WKT keywords should be written with upper cases or camel cases.
      Returns:
      the case to use for formatting keywords.
    • setKeywordCase

      public void setKeywordCase(KeywordCase keywordCase)
      Sets whether WKT keywords should be written with upper cases or camel cases.
      Parameters:
      keywordCase - the case to use for formatting keywords.
    • getKeywordStyle

      public KeywordStyle getKeywordStyle()
      Returns whether to use short or long WKT keywords.
      Returns:
      the style used for formatting keywords.
      Since:
      0.6
    • setKeywordStyle

      public void setKeywordStyle(KeywordStyle keywordStyle)
      Sets whether to use short or long WKT keywords.
      Parameters:
      keywordStyle - the style to use for formatting keywords.
      Since:
      0.6
    • getColors

      public Colors getColors()
      Returns the colors to use for syntax coloring, or null if none. This method returns an unmodifiable instance. Modifications, if desired, should be applied on a clone of the returned object. By default there is no syntax coloring.
      Returns:
      the colors for syntax coloring, or null if none.
    • setColors

      public void setColors(Colors colors)
      Sets the colors to use for syntax coloring. This property applies only when formatting text.

      Newly created WKTFormats have no syntax coloring. If a non-null argument like Colors.DEFAULT is given to this method, then the format(…) method tries to highlight most of the elements that are relevant to Utilities.equalsIgnoreMetadata(Object, Object).

      Parameters:
      colors - the colors for syntax coloring, or null if none.
    • getConvention

      public Convention getConvention()
      Returns the convention for parsing and formatting WKT elements. The default value is Convention.WKT2.
      Returns:
      the convention to use for formatting WKT elements (never null).
    • setConvention

      public void setConvention(Convention convention)
      Sets the convention for parsing and formatting WKT elements.
      Parameters:
      convention - the new convention to use for parsing and formatting WKT elements.
    • getNameAuthority

      public org.opengis.metadata.citation.Citation getNameAuthority()
      Returns the preferred authority to look for when fetching identified object names and identifiers. The difference between various authorities are most easily seen in projection and parameter names.
      Example: The following table shows the names given by various organizations or projects for the same projection:
      Projection name examples
      Authority Projection name
      EPSG Mercator (variant A)
      OGC Mercator_1SP
      GEOTIFF CT_Mercator
      If no authority has been explicitly set, then this method returns the default authority for the current convention.
      Returns:
      the organization, standard or project to look for when fetching projection and parameter names.
      See Also:
    • setNameAuthority

      public void setNameAuthority(org.opengis.metadata.citation.Citation authority)
      Sets the preferred authority for choosing the projection and parameter names. If non-null, the given priority will have precedence over the authority usually associated to the convention. A null value restore the default behavior.
      Parameters:
      authority - the new authority, or null for inferring it from the convention.
      See Also:
    • updateFormatter

      private void updateFormatter(Formatter formatter)
      Updates the formatter convention, authority, colors and indentation according the current state of this WKTFormat. The authority may be null, in which case it will be inferred from the convention when first needed.
    • getIndentation

      public int getIndentation()
      Returns the current indentation to be used for formatting objects. The -1 value means that the whole WKT is to be formatted on a single line.
      Returns:
      the current indentation.
    • setIndentation

      public void setIndentation(int indentation)
      Sets a new indentation to be used for formatting objects. The -1 value means that the whole WKT is to be formatted on a single line.
      Parameters:
      indentation - the new indentation to use.
      See Also:
    • getMaximumListElements

      public int getMaximumListElements()
      Returns the maximum number of elements to show in lists of values. If a list length is greater than this limit, then only the first and last elements will be shown together with a message saying that some elements were omitted. This limit is useful in particular with MathTransform parameter values of double[] type, since those parameters may be large interpolation tables.
      Returns:
      the current lists size limit, or Integer.MAX_VALUE if unlimited.
      Since:
      1.0
    • setMaximumListElements

      public void setMaximumListElements(int limit)
      Sets a new limit for the number of elements to show in lists. If this method is never invoked, then the default is unlimited.
      Parameters:
      limit - the new lists size limit, or Integer.MAX_VALUE if unlimited.
      Since:
      1.0
    • setDefaultIdentifier

      final void setDefaultIdentifier(DefaultIdentifier identifier)
      Sets the identifier to assign to parsed IdentifiedObject if the WKT does not contain an explicit ID[…] or AUTHORITY[…] element. The main use case is for implementing a CRSAuthorityFactory backed by definitions in WKT format.

      Note that this identifier apply to all objects to be created, which is generally not desirable. Callers should invoke setDefaultIdentifier(null) in a finally block.

      This is not a publicly committed API. If we want to make this functionality public in a future version, we should investigate if we should make it applicable to a wider range of properties and how to handle the fact that the a given identifier should be used for only one object.

      Parameters:
      identifier - the default identifier, or null if none.
    • ensureValidFactoryType

      private void ensureValidFactoryType(Class<?> type) throws IllegalArgumentException
      Verifies if the given type is a valid key for the factories map.
      Throws:
      IllegalArgumentException
    • getFactory

      public <T extends org.opengis.util.Factory> T getFactory(Class<T> type)
      Returns one of the factories used by this WKTFormat for parsing WKT. The given type argument can be one of the following values:
      • CRSFactory.class
      • CSFactory.class
      • DatumFactory.class
      • MathTransformFactory.class
      • CoordinateOperationFactory.class
      Type Parameters:
      T - the compile-time type of the type argument.
      Parameters:
      type - the factory type.
      Returns:
      the factory used by this WKTFormat for the given type.
      Throws:
      IllegalArgumentException - if the type argument is not one of the valid values.
    • setFactory

      public <T extends org.opengis.util.Factory> void setFactory(Class<T> type, T factory)
      Sets one of the factories to be used by this WKTFormat for parsing WKT. The given type argument can be one of the following values:
      • CRSFactory.class
      • CSFactory.class
      • DatumFactory.class
      • MathTransformFactory.class
      • CoordinateOperationFactory.class

      Limitation

      The current implementation does not serialize the given factories, because they are usually not Serializable. The factories used by WKTFormat instances after deserialization are the default ones.
      Type Parameters:
      T - the compile-time type of the type argument.
      Parameters:
      type - the factory type.
      factory - the factory to be used by this WKTFormat for the given type.
      Throws:
      IllegalArgumentException - if the type argument is not one of the valid values.
    • getValueType

      public final Class<Object> getValueType()
      Returns the type of objects formatted by this class. This method has to return Object.class since it is the only common parent to all object types accepted by this formatter.
      Specified by:
      getValueType in class CompoundFormat<Object>
      Returns:
      Object.class
    • getFragmentNames

      public Set<String> getFragmentNames()
      Returns the name of all WKT fragments known to this WKTFormat. The returned collection is initially empty. WKT fragments can be added by call to addFragment(String, String).

      The returned collection is modifiable. In particular, a call to Set.clear() removes all fragments from this WKTFormat.

      Returns:
      the name of all fragments known to this WKTFormat.
    • addFragment

      public void addFragment(String name, String wkt) throws IllegalArgumentException, ParseException
      Adds a fragment of Well Know Text (WKT). The wkt argument given to this method can contains itself other fragments specified in some previous calls to this method.
      Example if the following method is invoked: Then other WKT strings parsed by this WKTFormat instance can refer to the above fragment as below (WKT after the ellipsoid omitted for brevity):
      For removing a fragment, use getFragmentNames().remove(name).
      Parameters:
      name - the name to assign to the WKT fragment (case-sensitive). Must be a valid Unicode identifier.
      wkt - the Well Know Text (WKT) fragment represented by the given identifier.
      Throws:
      IllegalArgumentException - if the given name is not a valid Unicode identifier or if a fragment is already associated to that name.
      ParseException - if an error occurred while parsing the given WKT.
    • addFragment

      final void addFragment(String name, StoredTree definition)
      Adds a fragment of Well Know Text (WKT). Caller must have verified that name is a valid Unicode identifier.
      Parameters:
      name - the Unicode identifier to assign to the WKT fragment.
      definition - root of the WKT fragment to add.
      Throws:
      IllegalArgumentException - if a fragment is already associated to the given name.
    • textToTree

      final StoredTree textToTree(String wkt, ParsePosition pos, String aliasKey) throws ParseException
      Parses a Well Know Text (WKT) for a fragment or an entire object definition. This method should be invoked only for WKT trees to be stored for a long time. It should not be invoked for immediate IdentifiedObject parsing.

      If aliasKey is non-null, this method may return a multi-roots tree. See StoredTree.root for a discussion. Note that in both cases (single root or multi-roots), we may have some unparsed characters at the end of the string.

      Parameters:
      wkt - the Well Know Text (WKT) fragment to parse.
      pos - index of the first character to parse (on input) or after last parsed character (on output).
      aliasKey - key of the alias, or null if this method is not invoked for defining a fragment.
      Returns:
      root of the tree of elements.
      Throws:
      ParseException
    • clear

      final void clear()
      Clears warnings and cache of shared values.
    • parse

      public Object parse(CharSequence wkt, ParsePosition pos) throws ParseException
      Creates an object from the given character sequence. The parsing begins at the index given by the pos argument. After successful parsing, ParsePosition.getIndex() gives the position after the last parsed character. In case of error, ParseException.getErrorOffset() gives the position of the first illegal character.
      Specified by:
      parse in class CompoundFormat<Object>
      Parameters:
      wkt - the character sequence for the object to parse.
      pos - index of the first character to parse (on input) or after last parsed character (on output).
      Returns:
      the parsed object (never null).
      Throws:
      ParseException - if an error occurred while parsing the WKT.
    • buildFromTree

      final Object buildFromTree(StoredTree tree) throws ParseException
      Parses a tree of Elements to produce a geodetic object. The tree argument should be a value returned by textToTree(String, ParsePosition, String). This method is for WKTDictionary.createObject(String) usage.
      Parameters:
      tree - the tree of WKT elements.
      Returns:
      the parsed object (never null).
      Throws:
      ParseException - if the tree cannot be parsed.
    • parser

      private AbstractParser parser(boolean modifiable)
      Returns the parser, created when first needed.
      Parameters:
      modifiable - whether the caller intents to modify the fragments map.
    • format

      public void format(Object object, Appendable toAppendTo) throws IOException
      Formats the specified object as a Well Know Text. The formatter accepts at least the following types: FormattableObject, IdentifiedObject, MathTransform, GeographicBoundingBox, VerticalExtent, TemporalExtent, Envelope, Position and Unit.
      Specified by:
      format in class CompoundFormat<Object>
      Parameters:
      object - the object to format.
      toAppendTo - where the text is to be appended.
      Throws:
      IOException - if an error occurred while writing to toAppendTo.
      See Also:
    • createFormat

      protected Format createFormat(Class<?> valueType)
      Creates a new format to use for parsing and formatting values of the given type. This method is invoked the first time that a format is needed for the given type. The valueType can be any types declared in the parent class.
      Overrides:
      createFormat in class CompoundFormat<Object>
      Parameters:
      valueType - the base type of values to parse or format.
      Returns:
      the format to use for parsing of formatting values of the given type, or null if none.
    • getWarnings

      public Warnings getWarnings()
      If warnings occurred during the last WKT parsing or formatting, returns the warnings. Otherwise returns null. The warnings are cleared every time a new object is parsed or formatted.
      Returns:
      the warnings of the last parsing of formatting operation, or null if none.
      Since:
      0.6
    • logWarnings

      final void logWarnings(Class<?> classe, String method)
      If a warning occurred, logs it.
      Parameters:
      classe - the class to report as the source of the logging message.
      method - the method to report as the source of the logging message.
    • errors

      final Errors errors()
      Convenience methods for resources for error message in the locale given by CompoundFormat.getLocale().
    • clone

      public WKTFormat clone()
      Returns a clone of this format. The clone has the same configuration (including any added fragments), except the warnings.
      Overrides:
      clone in class CompoundFormat<Object>
      Returns:
      a clone of this format.