Class FallbackConverter<S,T>

Type Parameters:
S - the base type of source objects.
T - the base type of converted objects.
All Implemented Interfaces:
Serializable, Function<S,T>, ObjectConverter<S,T>

final class FallbackConverter<S,T> extends SystemConverter<S,T>
Fallback to be used when the first converter failed. In case of failure, the error of the first (primary) converter is reported.

The primary converter is expected more generic than the fallback converter. We try the generic converter first because we expect that if the user wanted the specific subclass, he would have asked explicitly for it. Trying the generic converter first is both closer to what the user asked and less likely to throw many exceptions before we found a successful conversion.

All converters in a FallbackConverter tree have the same source class <S>, and different target classes <? extends T> not equal to <T>. The tree should never have two classes <T1> and <T2> such as one is assignable from the other.

Instances are created by the merge(ObjectConverter, ObjectConverter) method. It is invoked when a new converter is registered for the same source and target class than an existing converter.

Immutability and thread safety

This class is immutable, and thus inherently thread-safe, if the converters given to the static factory method are also immutable.
Since:
0.3
Version:
0.3
  • Field Details

    • serialVersionUID

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

      final ObjectConverter<S,? extends T> primary
      The primary converter, to be tried first.
    • fallback

      final ObjectConverter<S,? extends T> fallback
      The fallback converter. Its target type should not be assignable from the primary target type, except if both converters have the same target type. We intend primary to be the most generic converter, because we assume that if the user wanted a more specific type he would have asked explicitly for it. In addition this layout reduces the amount of exceptions to be thrown and caught before we found a successful conversion.
  • Constructor Details

  • Method Details

    • needSwap

      private static <S> boolean needSwap(ObjectConverter<S,?> primary, Class<?> fallbackClass)
      Returns true if the given primary and fallback converters should be interchanged. This method may invoke itself recursively.
      Parameters:
      primary - the primary converter to test.
      fallbackClass - the target class of the fallback converter to test.
      Returns:
      true if the given primary and fallback converters should be interchanged.
    • merge

      public static <S, T> ObjectConverter<S,? extends T> merge(ObjectConverter<S,? extends T> primary, ObjectConverter<S,? extends T> fallback)
      Appends the given converter in the given tree of fallback converters. This method may create a new FallbackConverter if the given converter cannot be inserted in the given tree.

      This method has no information about <T> type because of parameterized types erasure, and should not need that information if we didn't made a mistake in this class. Nevertheless for safety, callers are encouraged to verify themselves as below:

      In the current implementation, the primary converter can be either an arbitrary ObjectConverter, or a previously created FallbackConverter. However, the fallback converter shall not be a FallbackConverter. This restriction exists because the tree built in such case would probably not be the desired one. It should be okay if only SIS code deal with FallbackConverter.
      Type Parameters:
      S - the base type of source objects.
      T - the base type of converted objects.
      Parameters:
      primary - the first converter, which may be a Fallback tree.
      fallback - a new fallback to insert in the converters tree.
      Returns:
      a tree of converters which contains the given converter. May be either existing, converter or a new FallbackConverter instance.
    • mergeIfSubtype

      private static <S, T> ObjectConverter<S,? extends T> mergeIfSubtype(ObjectConverter<S,T> branch, ObjectConverter<S,?> converter, Class<? super T> parentTarget)
      Merges if the converter target class of is a subtype of the branch target class. Otherwise returns null.

      The branch can be either an arbitrary ObjectConverter, or a previously created FallbackConverter. However, the converter shall be a new instance, not a FallbackConverter instance. See merge(ObjectConverter, ObjectConverter) javadoc for more information.

      Type Parameters:
      S - the source class of the branch converter.
      T - the target class of the branch converter
      Parameters:
      branch - the converter to eventually merge with converter.
      converter - the converter to eventually merge with branch.
      parentTarget - to be given verbatim to merge(ObjectConverter, Class).
      Returns:
      the merged converter, or null if the converter target class is not a subtype of the branch target class.
    • merge

      private ObjectConverter<S,? extends T> merge(ObjectConverter<S,? extends T> converter, Class<? super T> parentTarget)
      Merge this with another converter whose target class is a subtype of this ClassPair.targetClass. If either fallback or primary are other FallbackConverter instances, then this method will follow those branches.
      Parameters:
      converter - the converter to merge with this.
      parentTarget - if this method is invoked recursively, the target class of the parent FallbackConverter. Otherwise null.
      Returns:
      the merged converter.
    • properties

      public final Set<FunctionProperty> properties()
      Returns the manner in which source values (S) are mapped to target values. This is the intersection of the properties of the primary and fallback converters.
      Returns:
      the manners in which source values are mapped to target values. May be an empty set, but never null.
    • apply

      public T apply(S source) throws UnconvertibleObjectException
      Converts the given object, using the fallback if needed.
      Parameters:
      source - the object to convert, or null.
      Returns:
      the converted object, or null.
      Throws:
      UnconvertibleObjectException - if the given object is not an element of the function domain.
    • toTree

      private void toTree(ObjectConverter<?,?> converter, TreeTable.Node addTo)
      Creates a node for the given converter and adds it to the given tree. This method invokes itself recursively for scanning through fallbacks.
      Parameters:
      converter - the converter for which to create a tree.
      addTo - the node in which to add the converter.
    • toTree

      final void toTree(TreeTable.Node addTo, boolean isNew)
      Adds a simplified tree representation of this FallbackConverter to the given node.
      Parameters:
      addTo - the node in which to add the converter.
      isNew - true if addTo is a newly created node.
    • toString

      public String toString()
      Returns a tree representation of this converter. The tree leaves represent the backing converters.
      Overrides:
      toString in class ClassPair<S,T>