content/developer-guide/utility/ObjectConverters.html (88 lines of code) (raw):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<!--
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.
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>ObjectConverters</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" type="text/css" href="../book.css"/>
</head>
<body>
<!--
Content below this point is copied in "/asf-staging/book/en/developer-guide.html" file
by the `org.apache.sis.buildtools.book` class in `buildSrc`.
-->
<section>
<header>
<h2 id="ObjectConverters">Object converters</h2>
</header>
<p>
There is sometimes a need to convert instances from a <var>source</var> Java type to a <var>target</var> Java type
while those types are unknown at compile time.
Various projects (Apache Common Convert, Spring, <i>etc.</i>)
have created their own interface for performing object conversions between types known only at runtime.
Details vary, but such interfaces typically look like below:
</p>
<pre><code>interface ObjectConverter<S,T> { // Some projects use only "Converter" as interface name.
T apply(S object); // Another method name commonly found in other projects is "convert".
}</code></pre>
<p>
Like other projects, Apache <abbr>SIS</abbr> also defines its own <code>ObjectConverter</code> interface.
The main difference between <abbr>SIS</abbr> converter interface and the interfaces found in other projects
is that <abbr>SIS</abbr> converters provide some information about their mathematical properties.
An Apache <abbr>SIS</abbr> converter can have zero, one or many of the following properties:
</p>
<dl>
<dt><dfn>Injective</dfn></dt>
<dd>A function is injective if no pair of <var>S</var> values can produce the same <var>T</var> value.
<div class="example"><p><b>Example:</b>
the <code>Integer</code> → <code>String</code> conversion performed by <code>Integer.toString()</code>
is an <dfn>injective</dfn> function because if two <code>Integer</code> values are not equal,
then it is guaranteed that their conversions will result in different <code>String</code> values.
However the <code>String</code> → <code>Integer</code> conversion performed by <code>Integer.valueOf(String)</code>
is <strong>not</strong> an injective function
because many distinct <code>String</code> values can be converted to the same <code>Integer</code> value.
For example converting the "42", "+42" and "0042" character strings all result in the same 42 integer value.
</p></div>
</dd>
<dt><dfn>Surjective</dfn></dt>
<dd>A function is surjective if each values of <var>T</var> can be created from at least one value of <var>S</var>.
<div class="example"><p><b>Example:</b>
the <code>String</code> → <code>Integer</code> conversion performed by <code>Integer.valueOf(String)</code>
is a <dfn>surjective</dfn> function because every <code>Integer</code> value can be created from at least one <code>String</code> value.
However the <code>Integer</code> → <code>String</code> conversion performed by <code>Integer.toString()</code>
is <strong>not</strong> a surjective function because it cannot produce all possible <code>String</code> values.
For example there is no way to produce the "ABC" value with the <code>Integer.toString()</code> method.
</p></div>
</dd>
<dt><dfn>Bijective</dfn></dt>
<dd>A function is bijective if there is a one-to-one relationship between <var>S</var> and <var>T</var> values.
<div class="example"><p><b>Note:</b>
the <dfn>bijective</dfn> property is defined here for clarity, but actually does not have an explicit item
in Apache <abbr>SIS</abbr> <code>FunctionProperty</code> enumeration.
It is not necessary since a function that is both <dfn>injective</dfn> and <dfn>surjective</dfn> is necessarily bijective.
</p></div>
</dd>
<dt><dfn>Order preserving</dfn></dt>
<dd>A function is order preserving if any sequence of increasing <var>S</var> values is mapped to a sequence of increasing <var>T</var> values.
<div class="example"><p><b>Example:</b>
conversion from <code>Integer</code> to <code>Long</code> preserve the natural ordering of elements.
However conversions from <code>Integer</code> to <code>String</code> do <strong>not</strong> preserve natural ordering,
because some sequences of increasing integer values are ordered differently when their string representations are sorted by lexicographic order.
For example 1, 2, 10 become "1", "10", "2".
</p></div>
</dd>
<dt><dfn>Order reversing</dfn></dt>
<dd>A function is order reversing if any sequence of increasing <var>S</var> values is mapped to a sequence of decreasing <var>T</var> values.
<div class="example"><p><b>Example:</b>
a conversion that reverses the sign of numbers.
</p></div>
</dd>
</dl>
<p>
Above information may seem unnecessary when values are converted without taking in account the context in which the values appear.
But when the value to convert is part of a bigger object, then above information can affect the way the converted value will be used.
For example conversion of a [<var>min</var> … <var>max</var>] range is straightforward when the converter is <dfn>order preserving</dfn>.
But if the converter is <dfn>order reversing</dfn>, then the minimum and maximum values need to be interchanged.
For example if the converter reverses the sign of values, then the converted range is [-<var>max</var> … -<var>min</var>].
If the converter is neither order preserving or order reversing, then range conversion is not allowed at all
(because it does not contain the same set of values) even if the minimum and maximum values could be converted individually.
</p>
</section>
</body>
</html>