Class WKTDictionary
- All Implemented Interfaces:
org.opengis.referencing.AuthorityFactory
,org.opengis.util.Factory
create(…)
method is invoked for the first time for a given key.
Sub-classing and instantiation
Newly constructedWKTDictionary
are initially empty.
The dictionary can be populated in the following ways:
- Invoke
load(BufferedReader)
for reading definitions from file(s). - Invoke
addDefinitions(Stream)
for providing definitions from an arbitrary source. - Override
fetchDefinition(DefaultIdentifier)
in a subclass for fetching WKT definitions on-the-fly (for example from the"spatial_ref_sys"
table of a spatial database.
fetchDefinition(…)
is not overridden
because WKTDictionary
does not implement any of the
CRSAuthorityFactory
,
CSAuthorityFactory
or
DatumAuthorityFactory
.
The choice of interfaces to implement is left to subclasses.
CRS.forCode(String)
.
The additional CRS are defined by Well-Known Text strings in a "MyCRS.txt"
file.
First step is to create a CRS factory with those definitions:
The second step is to register this factory as a service with a
META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
file on the classpath.
That file shall contain the fully qualified class name of above MyCRS
class.Errors management
Well-Known Text parsing is performed in two steps, each of them executed at a different time:Early validation
WKT strings added byload(…)
or addDefinitions(…)
methods are verified
for matching quotes, balanced parenthesis or brackets, and valid number or date formats.
If a syntax error is detected, the loading process is interrupted at the point the error occurred;
CRS definitions after the error location are not loaded.
However, WKT keywords and geodetic parameters (e.g. map projections) are not validated at this stage.
Late validation
WKT keywords and geodetic parameters inside WKT elements are validated only whencreateObject(String)
is invoked. If an error occurs at this stage, only the CRS (or other geodetic object) for the code given to
the createFoo(…)
method become invalid. Objects associated to other codes are not impacted.
Multi-threading
This class is thread-safe but not necessarily concurrent. This class is designed for a relatively small amount of WKT; it is not a replacement for database-backed factory such asEPSGFactory
.- Since:
- 1.1
- Version:
- 1.1
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final class
A special kind of value used in thedefinitions
map when the same code is used by more than one authority and version.private final class
Implementation ofload(BufferedReader)
method. -
Field Summary
FieldsModifier and TypeFieldDescriptionAuthorities declared in all"ID[CITATION[…]]"
elements found in WKT definitions.private org.opengis.metadata.citation.Citation
The organization or specification that defines the codes recognized by this factory.Cache of authority codes computed bygetAuthorityCodes(Class)
.Code spaces of authority codes recognized by this factory.CRS definitions associated to authority:version:code keys.private final ReadWriteLock
The write lock forparser
and the read/write locks fordefinitions
accesses.protected final WKTFormat
The parser to use for creating geodetic objects from WKT definitions. -
Constructor Summary
ConstructorsConstructorDescriptionWKTDictionary
(org.opengis.metadata.citation.Citation authority) Creates an initially empty factory. -
Method Summary
Modifier and TypeMethodDescriptionprivate void
addDefinition
(StoredTree tree) Adds the definition of a CRS (or other geodetic objects) from a tree of WKT elements.void
addDefinitions
(Stream<String> objects) Adds definitions of CRS (or other geodetic objects) from Well-Known Texts.org.opengis.referencing.IdentifiedObject
createObject
(String code) Returns an arbitrary object from a code.protected String
fetchDefinition
(DefaultIdentifier identifier) Fetches the Well-Known Text for a user-specified identifier not found in thisWKTDictionary
.(package private) final void
forEachValue
(Consumer<Object> addTo) Adds all definition values to the given supplier.org.opengis.metadata.citation.Citation
Returns the authority or specification that defines the codes recognized by this factory.getAuthorityCodes
(Class<? extends org.opengis.referencing.IdentifiedObject> type) Returns the set of authority codes for objects of the given type.Returns all namespaces recognized by this factory.org.opengis.util.InternationalString
getDescriptionText
(String code) Gets a description of the object corresponding to a code.private Object
getOrCreate
(String code, boolean create) Returns the object associated to the given code.void
load
(BufferedReader source) Adds to this factory all definitions read from the given source.private org.opengis.referencing.IdentifiedObject
parseAndAdd
(String codespace, String version, String code, String wkt, DefaultIdentifier defaultIdentifier) Parses immediately the given WKT and caches the result under the given identifier.private Resources
Convenience methods for resources in the language used for error messages.private static String
trimOrNull
(Object value) Trims the leading and trailing spaces of the string representation of given object.private String
unexpectedText
(int lineNumber, String wkt, int end) Produces an error message for unexpected characters at the end of WKT string.private void
Ifauthority
is not yet defined, computes a value fromID[…]
found in all WKT strings.Methods inherited from class org.apache.sis.referencing.factory.GeodeticAuthorityFactory
createCartesianCS, createCompoundCRS, createCoordinateOperation, createCoordinateReferenceSystem, createCoordinateSystem, createCoordinateSystemAxis, createCylindricalCS, createDatum, createDerivedCRS, createEllipsoid, createEllipsoidalCS, createEngineeringCRS, createEngineeringDatum, createExtent, createFromCoordinateReferenceSystemCodes, createGeocentricCRS, createGeodeticDatum, createGeographicCRS, createImageCRS, createImageDatum, createOperationMethod, createParameterDescriptor, createParametricCRS, createParametricCS, createParametricDatum, createPolarCS, createPrimeMeridian, createProjectedCRS, createSphericalCS, createTemporalCRS, createTemporalDatum, createTimeCS, createUnit, createVerticalCRS, createVerticalCS, createVerticalDatum, newIdentifiedObjectFinder, toString, trimNamespace
Methods inherited from class org.apache.sis.util.iso.AbstractFactory
getVendor
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Methods inherited from interface org.opengis.util.Factory
getVendor
-
Field Details
-
authority
private volatile org.opengis.metadata.citation.Citation authorityThe organization or specification that defines the codes recognized by this factory. May benull
if not yet determined.- See Also:
-
authorities
-
codespaces
Code spaces of authority codes recognized by this factory. This set is computed from the"ID[…]"
elements found in WKT definitions.- See Also:
-
codeCaches
Cache of authority codes computed bygetAuthorityCodes(Class)
. This cache can be cleared at any time; values are recomputed when needed. -
parser
The parser to use for creating geodetic objects from WKT definitions. Subclasses can modify theWKTFormat
configuration in their constructor, but should not use it directly after construction (for thread safety reasons). -
lock
The write lock forparser
and the read/write locks fordefinitions
accesses. Allparser
usages afterWKTDictionary
construction shall be synchronized by theReadWriteLock.writeLock()
.Implementation note: we manage the locks ourselves instead of using aConcurrentHashMap
because if adefinitions
value needs to be computed, then we need to block all other threads anyway sinceparser
is not thread-safe. Consequently, the high concurrency capability provided byConcurrentHashMap
does not help us in this case. -
definitions
CRS definitions associated to authority:version:code keys. Keys are authority codes, ignoring code space (authority) and version. For example, in "EPSG:9.1:4326" the key would be only "4326". Values can be one of the following 4 types:StoredTree
: this is the initial state when there are no duplicated codes. This is the root of a tree of WKT keywords with their values as children. A tree can be parsed later as anIdentifiedObject
when first requested.IdentifiedObject
: the result of parsing theStoredTree
whencreateObject(String)
is invoked for a given authority code. The parsing result replaces the previousStoredTree
value.WKTDictionary.Disambiguation
: if the same code is used by two or more authorities or versions, then above-citedStoredTree
orIdentifiedObject
alternatives are wrapped in aWKTDictionary.Disambiguation
object.String
if parsing failed, in which case the string is the error message.
Synchronization
All read operations in this map shall be synchronized by thelock.readLock()
and write operations synchronized by thelock.writeLock()
.
-
-
Constructor Details
-
WKTDictionary
public WKTDictionary(org.opengis.metadata.citation.Citation authority) Creates an initially empty factory. The authority can specified explicitly or inferred from the WKTs. In the latter case (when the given authority isnull
), an authority will be inferred from allID[…]
orAUTHORITY[…]
elements found in WKT strings as below, in preference order:- Most frequent
CITATION[…]
value. - If there is no citation, then most frequent code space
in
ID[…]
orAUTHORITY[…]
elements.
load(BufferedReader)
oraddDefinitions(Stream)
after construction.- Parameters:
authority
- organization that defines the codes recognized by this factory, ornull
.
- Most frequent
-
-
Method Details
-
updateAuthority
private void updateAuthority()Ifauthority
is not yet defined, computes a value fromID[…]
found in all WKT strings. This method should be invoked after new WKTs have been added. -
load
Adds to this factory all definitions read from the given source. Each Coordinate Reference System (or other geodetic object) is defined by a string in WKT format. The key associated to each object is given by theID[…]
orAUTHORITY[…]
element, which is typically the last element of a WKT string and is mandatory for definitions in this file.WKT strings can span many lines. All lines after the first line shall be indented with at least one white space. Non-indented lines start new definitions.
Blank lines and lines starting with the
#
character (ignoring white spaces) are ignored.Aliases for WKT fragments
Files with more than one WKT definition tend to repeat the same WKT fragments many times. For example, the sameBaseGeogCRS[…]
element may be repeated in everyProjectedCRS
definitions. Redundant fragments can be replaced by aliases for making the file more compact, easier to read, faster to parse and with smaller memory footprint.Each line starting with "
SET <identifier>=<WKT>
" defines an alias for a fragment of WKT string. The WKT can span many lines as described above. Aliases are local to the file where they are defined. Aliases can be expanded in other WKT strings by "$<identifier>
".Validation
This method verifies that definitions have matching quotes, balanced parenthesis or brackets, and valid number or date formats. It does not verify WKT keywords or geodetic parameters. See class javadoc for more details.Example
An example is available here.- Parameters:
source
- the source of WKT definitions.- Throws:
org.opengis.util.FactoryException
- if the definition file cannot be read.
-
addDefinition
Adds the definition of a CRS (or other geodetic objects) from a tree of WKT elements. The authority code is inferred from theID[…]
orAUTHORITY[…]
element. Caller must own the write lock before to invoke this method.updateAuthority()
should be invoked after this method.- Parameters:
tree
- a tree of WKT elements.- Throws:
IllegalArgumentException
- if acodespace:version:code
tuple is assigned twice.FactoryDataException
- if the WKT does not have anID[…]
orAUTHORITY[…]
element.- See Also:
-
addDefinitions
Adds definitions of CRS (or other geodetic objects) from Well-Known Texts. Blank strings are ignored. Each non-blankString
shall contain the complete definition of exactly one geodetic object. A geodetic object cannot have its definition splitted in two or moreString
s.The key associated to each object is given by the
ID[…]
orAUTHORITY[…]
element, which is typically the last element of a WKT string and is mandatory. WKT strings can contain line separators for human readability.- Parameters:
objects
- CRS (or other geodetic objects) definitions as WKT strings.- Throws:
org.opengis.util.FactoryException
- if a WKT cannot be parsed, or does not contain anID[…]
orAUTHORITY[…]
element, or if the samecodespace:version:code
tuple is used for two objects.
-
parseAndAdd
private org.opengis.referencing.IdentifiedObject parseAndAdd(String codespace, String version, String code, String wkt, DefaultIdentifier defaultIdentifier) throws org.opengis.util.FactoryException Parses immediately the given WKT and caches the result under the given identifier. This method is invoked only if subclass overridesfetchDefinition(DefaultIdentifier)
for producing WKT on-the-fly.- Parameters:
codespace
- the authority (or other kind of code space) providing CRS definitions.version
- version of the CRS definition, ornull
if unspecified.code
- code allocated by the authority for the CRS definition.wkt
- the Well-Known Text to parse immediately.defaultIdentifier
- identifier to assign to the object if the WKT does not provide one.- Returns:
- the parsed object.
- Throws:
org.opengis.util.FactoryException
- if parsing failed.
-
fetchDefinition
protected String fetchDefinition(DefaultIdentifier identifier) throws org.opengis.util.FactoryException Fetches the Well-Known Text for a user-specified identifier not found in thisWKTDictionary
. Subclasses can override this method if WKT strings are not loaded or specified in advance, but instead fetched when first needed. An example of such scenario is WKTs provided by the"spatial_ref_sys"
table of a spatial database. If no WKT is found for the given identifier, then this method returnsnull
.On input,
identifier
contains only the pieces of information provided by user. For example if user invokedcreateGeographicCRS("Foo")
, then the identifier code will be"Foo"
but the codespace and version will be undefined (null
). On output,identifier
should be completed with missing code space and version (if available).Overriding
The default implementation returnsnull
. If a subclass overrides this method, then it should also overridegetAuthorityCodes(Class)
becauseWKTDictionary
does not know the codes that this method can recognize.- Parameters:
identifier
- the code specified by user, possible with code space and version.- Returns:
- Well-Known Text (WKT) for the given identifier, or
null
if none. - Throws:
org.opengis.util.FactoryException
- if an error occurred while fetching the WKT.
-
unexpectedText
Produces an error message for unexpected characters at the end of WKT string.- Parameters:
lineNumber
- line where the error occurred.wkt
- the WKT being parsed.end
- end of WKT parsing.- Returns:
- message to give to exception constructor.
-
resources
Convenience methods for resources in the language used for error messages. -
trimOrNull
Trims the leading and trailing spaces of the string representation of given object. If null, empty or contains only spaces, then this method returnsnull
. -
forEachValue
Adds all definition values to the given supplier. This is for testing purposes only. This method performs no locking because it is not needed for current JUnit tests.- See Also:
-
getAuthority
public org.opengis.metadata.citation.Citation getAuthority()Returns the authority or specification that defines the codes recognized by this factory. This is the first of the following values, in preference order:- The authority explicitly specified at construction time.
- A citation built from the most frequent value found in
CITATION
elements. - A citation built from the most frequent value found in
ID
orAUTHORITY
elements.
- Specified by:
getAuthority
in interfaceorg.opengis.referencing.AuthorityFactory
- Specified by:
getAuthority
in classGeodeticAuthorityFactory
- Returns:
- the organization responsible for CRS definitions, or
null
if unknown. - See Also:
-
getCodeSpaces
Returns all namespaces recognized by this factory. Those namespaces can appear before codes in calls tocreateFoo(String)
methods, for example"ESRI"
in"ESRI:102018"
. Namespaces are case-insensitive.- Overrides:
getCodeSpaces
in classGeodeticAuthorityFactory
- Returns:
- the namespaces recognized by this factory.
-
getAuthorityCodes
public Set<String> getAuthorityCodes(Class<? extends org.opengis.referencing.IdentifiedObject> type) throws org.opengis.util.FactoryException Returns the set of authority codes for objects of the given type. Thetype
argument specifies the base type of identified objects.- Parameters:
type
- the spatial reference objects type.- Returns:
- the set of authority codes for spatial reference objects of the given type.
- Throws:
org.opengis.util.FactoryException
- if an error occurred while fetching the codes.
-
getDescriptionText
public org.opengis.util.InternationalString getDescriptionText(String code) throws org.opengis.util.FactoryException Gets a description of the object corresponding to a code.- Specified by:
getDescriptionText
in interfaceorg.opengis.referencing.AuthorityFactory
- Overrides:
getDescriptionText
in classGeodeticAuthorityFactory
- Parameters:
code
- value allocated by authority.- Returns:
- a description of the object, or
null
ifnull
if none. - Throws:
org.opengis.referencing.NoSuchAuthorityCodeException
- if the specifiedcode
was not found.org.opengis.util.FactoryException
- if the query failed for some other reason.
-
createObject
public org.opengis.referencing.IdentifiedObject createObject(String code) throws org.opengis.util.FactoryException Returns an arbitrary object from a code.- Specified by:
createObject
in interfaceorg.opengis.referencing.AuthorityFactory
- Specified by:
createObject
in classGeodeticAuthorityFactory
- Parameters:
code
- value allocated by authority.- Returns:
- the object for the given code.
- Throws:
org.opengis.referencing.NoSuchAuthorityCodeException
- if the specifiedcode
was not found.org.opengis.util.FactoryException
- if the object creation failed for some other reason.- See Also:
-
getOrCreate
Returns the object associated to the given code.- Parameters:
code
- value allocated by authority.create
- whether to createIdentifiedObject
fromStoredTree
.- Returns:
- the object for the given code, possibly as a
StoredTree
ifcreate
isfalse
. - Throws:
org.opengis.referencing.NoSuchAuthorityCodeException
- if the specifiedcode
was not found.org.opengis.util.FactoryException
- if the object creation failed for some other reason.
-