Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2008 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.base;
     18 
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import com.google.common.annotations.Beta;
     22 import com.google.common.annotations.GwtCompatible;
     23 
     24 import java.io.Serializable;
     25 import java.util.Iterator;
     26 
     27 import javax.annotation.Nullable;
     28 
     29 /**
     30  * A function from {@code A} to {@code B} with an associated <i>reverse</i> function from {@code B}
     31  * to {@code A}; used for converting back and forth between <i>different representations of the same
     32  * information</i>.
     33  *
     34  * <h3>Invertibility</h3>
     35  *
     36  * <p>The reverse operation <b>may</b> be a strict <i>inverse</i> (meaning that {@code
     37  * converter.reverse().convert(converter.convert(a)).equals(a)} is always true). However, it is
     38  * very common (perhaps <i>more</i> common) for round-trip conversion to be <i>lossy</i>. Consider
     39  * an example round-trip using {@link com.google.common.primitives.Doubles#stringConverter}:
     40  *
     41  * <ol>
     42  * <li>{@code stringConverter().convert("1.00")} returns the {@code Double} value {@code 1.0}
     43  * <li>{@code stringConverter().reverse().convert(1.0)} returns the string {@code "1.0"} --
     44  *     <i>not</i> the same string ({@code "1.00"}) we started with
     45  * </ol>
     46  *
     47  * <p>Note that it should still be the case that the round-tripped and original objects are
     48  * <i>similar</i>.
     49  *
     50  * <h3>Nullability</h3>
     51  *
     52  * <p>A converter always converts {@code null} to {@code null} and non-null references to non-null
     53  * references. It would not make sense to consider {@code null} and a non-null reference to be
     54  * "different representations of the same information", since one is distinguishable from
     55  * <i>missing</i> information and the other is not. The {@link #convert} method handles this null
     56  * behavior for all converters; implementations of {@link #doForward} and {@link #doBackward} are
     57  * guaranteed to never be passed {@code null}, and must never return {@code null}.
     58  *
     59 
     60  * <h3>Common ways to use</h3>
     61  *
     62  * <p>Getting a converter:
     63  *
     64  * <ul>
     65  * <li>Use a provided converter implementation, such as {@link Enums#stringConverter}, {@link
     66  *     com.google.common.primitives.Ints#stringConverter Ints.stringConverter} or the {@linkplain
     67  *     #reverse reverse} views of these.
     68  * <li>Convert between specific preset values using {@link
     69  *     com.google.common.collect.Maps#asConverter Maps.asConverter}. For example, use this to create
     70  *     a "fake" converter for a unit test. It is unnecessary (and confusing) to <i>mock</i> the
     71  *     {@code Converter} type using a mocking framework.
     72  * <li>Otherwise, extend this class and implement its {@link #doForward} and {@link #doBackward}
     73  *     methods.
     74  * </ul>
     75  *
     76  * <p>Using a converter:
     77  *
     78  * <ul>
     79  * <li>Convert one instance in the "forward" direction using {@code converter.convert(a)}.
     80  * <li>Convert multiple instances "forward" using {@code converter.convertAll(as)}.
     81  * <li>Convert in the "backward" direction using {@code converter.reverse().convert(b)} or {@code
     82  *     converter.reverse().convertAll(bs)}.
     83  * <li>Use {@code converter} or {@code converter.reverse()} anywhere a {@link Function} is accepted
     84  * <li><b>Do not</b> call {@link #doForward} or {@link #doBackward} directly; these exist only to be
     85  *     overridden.
     86  * </ul>
     87  *
     88  * @author Mike Ward
     89  * @author Kurt Alfred Kluever
     90  * @author Gregory Kick
     91  * @since 16.0
     92  */
     93 @Beta
     94 @GwtCompatible
     95 public abstract class Converter<A, B> implements Function<A, B> {
     96   private final boolean handleNullAutomatically;
     97 
     98   // We lazily cache the reverse view to avoid allocating on every call to reverse().
     99   private transient Converter<B, A> reverse;
    100 
    101   /** Constructor for use by subclasses. */
    102   protected Converter() {
    103     this(true);
    104   }
    105 
    106   /**
    107    * Constructor used only by {@code LegacyConverter} to suspend automatic null-handling.
    108    */
    109   Converter(boolean handleNullAutomatically) {
    110     this.handleNullAutomatically = handleNullAutomatically;
    111   }
    112 
    113   // SPI methods (what subclasses must implement)
    114 
    115   /**
    116    * Returns a representation of {@code a} as an instance of type {@code B}. If {@code a} cannot be
    117    * converted, an unchecked exception (such as {@link IllegalArgumentException}) should be thrown.
    118    *
    119    * @param a the instance to convert; will never be null
    120    * @return the converted instance; <b>must not</b> be null
    121    */
    122   protected abstract B doForward(A a);
    123 
    124   /**
    125    * Returns a representation of {@code b} as an instance of type {@code A}. If {@code b} cannot be
    126    * converted, an unchecked exception (such as {@link IllegalArgumentException}) should be thrown.
    127    *
    128    * @param b the instance to convert; will never be null
    129    * @return the converted instance; <b>must not</b> be null
    130    * @throws UnsupportedOperationException if backward conversion is not implemented; this should be
    131    *     very rare. Note that if backward conversion is not only unimplemented but
    132    *     unimplement<i>able</i> (for example, consider a {@code Converter<Chicken, ChickenNugget>}),
    133    *     then this is not logically a {@code Converter} at all, and should just implement {@link
    134    *     Function}.
    135    */
    136   protected abstract A doBackward(B b);
    137 
    138   // API (consumer-side) methods
    139 
    140   /**
    141    * Returns a representation of {@code a} as an instance of type {@code B}.
    142    *
    143    * @return the converted value; is null <i>if and only if</i> {@code a} is null
    144    */
    145   @Nullable
    146   public final B convert(@Nullable A a) {
    147     return correctedDoForward(a);
    148   }
    149 
    150   @Nullable
    151   B correctedDoForward(@Nullable A a) {
    152     if (handleNullAutomatically) {
    153       // TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
    154       return a == null ? null : checkNotNull(doForward(a));
    155     } else {
    156       return doForward(a);
    157     }
    158   }
    159 
    160   @Nullable
    161   A correctedDoBackward(@Nullable B b) {
    162     if (handleNullAutomatically) {
    163       // TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
    164       return b == null ? null : checkNotNull(doBackward(b));
    165     } else {
    166       return doBackward(b);
    167     }
    168   }
    169 
    170   /**
    171    * Returns an iterable that applies {@code convert} to each element of {@code fromIterable}. The
    172    * conversion is done lazily.
    173    *
    174    * <p>The returned iterable's iterator supports {@code remove()} if the input iterator does. After
    175    * a successful {@code remove()} call, {@code fromIterable} no longer contains the corresponding
    176    * element.
    177    */
    178   public Iterable<B> convertAll(final Iterable<? extends A> fromIterable) {
    179     checkNotNull(fromIterable, "fromIterable");
    180     return new Iterable<B>() {
    181       @Override public Iterator<B> iterator() {
    182         return new Iterator<B>() {
    183           private final Iterator<? extends A> fromIterator = fromIterable.iterator();
    184 
    185           @Override
    186           public boolean hasNext() {
    187             return fromIterator.hasNext();
    188           }
    189 
    190           @Override
    191           public B next() {
    192             return convert(fromIterator.next());
    193           }
    194 
    195           @Override
    196           public void remove() {
    197             fromIterator.remove();
    198           }
    199         };
    200       }
    201     };
    202   }
    203 
    204   /**
    205    * Returns the reversed view of this converter, which converts {@code this.convert(a)} back to a
    206    * value roughly equivalent to {@code a}.
    207    *
    208    * <p>The returned converter is serializable if {@code this} converter is.
    209    */
    210   // TODO(user): Make this method final
    211   public Converter<B, A> reverse() {
    212     Converter<B, A> result = reverse;
    213     return (result == null) ? reverse = new ReverseConverter<A, B>(this) : result;
    214   }
    215 
    216   private static final class ReverseConverter<A, B>
    217       extends Converter<B, A> implements Serializable {
    218     final Converter<A, B> original;
    219 
    220     ReverseConverter(Converter<A, B> original) {
    221       this.original = original;
    222     }
    223 
    224     /*
    225      * These gymnastics are a little confusing. Basically this class has neither legacy nor
    226      * non-legacy behavior; it just needs to let the behavior of the backing converter shine
    227      * through. So, we override the correctedDo* methods, after which the do* methods should never
    228      * be reached.
    229      */
    230 
    231     @Override
    232     protected A doForward(B b) {
    233       throw new AssertionError();
    234     }
    235 
    236     @Override
    237     protected B doBackward(A a) {
    238       throw new AssertionError();
    239     }
    240 
    241     @Override
    242     @Nullable
    243     A correctedDoForward(@Nullable B b) {
    244       return original.correctedDoBackward(b);
    245     }
    246 
    247     @Override
    248     @Nullable
    249     B correctedDoBackward(@Nullable A a) {
    250       return original.correctedDoForward(a);
    251     }
    252 
    253     @Override
    254     public Converter<A, B> reverse() {
    255       return original;
    256     }
    257 
    258     @Override
    259     public boolean equals(@Nullable Object object) {
    260       if (object instanceof ReverseConverter) {
    261         ReverseConverter<?, ?> that = (ReverseConverter<?, ?>) object;
    262         return this.original.equals(that.original);
    263       }
    264       return false;
    265     }
    266 
    267     @Override
    268     public int hashCode() {
    269       return ~original.hashCode();
    270     }
    271 
    272     @Override
    273     public String toString() {
    274       return original + ".reverse()";
    275     }
    276 
    277     private static final long serialVersionUID = 0L;
    278   }
    279 
    280   /**
    281    * Returns a converter whose {@code convert} method applies {@code secondConverter} to the result
    282    * of this converter. Its {@code reverse} method applies the converters in reverse order.
    283    *
    284    * <p>The returned converter is serializable if {@code this} converter and {@code secondConverter}
    285    * are.
    286    */
    287   public final <C> Converter<A, C> andThen(Converter<B, C> secondConverter) {
    288     return doAndThen(secondConverter);
    289   }
    290 
    291   /**
    292    * Package-private non-final implementation of andThen() so only we can override it.
    293    */
    294   <C> Converter<A, C> doAndThen(Converter<B, C> secondConverter) {
    295     return new ConverterComposition<A, B, C>(this, checkNotNull(secondConverter));
    296   }
    297 
    298   private static final class ConverterComposition<A, B, C>
    299       extends Converter<A, C> implements Serializable {
    300     final Converter<A, B> first;
    301     final Converter<B, C> second;
    302 
    303     ConverterComposition(Converter<A, B> first, Converter<B, C> second) {
    304       this.first = first;
    305       this.second = second;
    306     }
    307 
    308     /*
    309      * These gymnastics are a little confusing. Basically this class has neither legacy nor
    310      * non-legacy behavior; it just needs to let the behaviors of the backing converters shine
    311      * through (which might even differ from each other!). So, we override the correctedDo* methods,
    312      * after which the do* methods should never be reached.
    313      */
    314 
    315     @Override
    316     protected C doForward(A a) {
    317       throw new AssertionError();
    318     }
    319 
    320     @Override
    321     protected A doBackward(C c) {
    322       throw new AssertionError();
    323     }
    324 
    325     @Override
    326     @Nullable
    327     C correctedDoForward(@Nullable A a) {
    328       return second.correctedDoForward(first.correctedDoForward(a));
    329     }
    330 
    331     @Override
    332     @Nullable
    333     A correctedDoBackward(@Nullable C c) {
    334       return first.correctedDoBackward(second.correctedDoBackward(c));
    335     }
    336 
    337     @Override
    338     public boolean equals(@Nullable Object object) {
    339       if (object instanceof ConverterComposition) {
    340         ConverterComposition<?, ?, ?> that = (ConverterComposition<?, ?, ?>) object;
    341         return this.first.equals(that.first)
    342             && this.second.equals(that.second);
    343       }
    344       return false;
    345     }
    346 
    347     @Override
    348     public int hashCode() {
    349       return 31 * first.hashCode() + second.hashCode();
    350     }
    351 
    352     @Override
    353     public String toString() {
    354       return first + ".andThen(" + second + ")";
    355     }
    356 
    357     private static final long serialVersionUID = 0L;
    358   }
    359 
    360   /**
    361    * @deprecated Provided to satisfy the {@code Function} interface; use {@link #convert} instead.
    362    */
    363   @Deprecated
    364   @Override
    365   @Nullable
    366   public final B apply(@Nullable A a) {
    367     return convert(a);
    368   }
    369 
    370   /**
    371    * Indicates whether another object is equal to this converter.
    372    *
    373    * <p>Most implementations will have no reason to override the behavior of {@link Object#equals}.
    374    * However, an implementation may also choose to return {@code true} whenever {@code object} is a
    375    * {@link Converter} that it considers <i>interchangeable</i> with this one. "Interchangeable"
    376    * <i>typically</i> means that {@code Objects.equal(this.convert(a), that.convert(a))} is true for
    377    * all {@code a} of type {@code A} (and similarly for {@code reverse}). Note that a {@code false}
    378    * result from this method does not imply that the converters are known <i>not</i> to be
    379    * interchangeable.
    380    */
    381   @Override
    382   public boolean equals(@Nullable Object object) {
    383     return super.equals(object);
    384   }
    385 
    386   // Static converters
    387 
    388   /**
    389    * Returns a converter based on <i>existing</i> forward and backward functions. Note that it is
    390    * unnecessary to create <i>new</i> classes implementing {@code Function} just to pass them in
    391    * here. Instead, simply subclass {@code Converter} and implement its {@link #doForward} and
    392    * {@link #doBackward} methods directly.
    393    *
    394    * <p>These functions will never be passed {@code null} and must not under any circumstances
    395    * return {@code null}. If a value cannot be converted, the function should throw an unchecked
    396    * exception (typically, but not necessarily, {@link IllegalArgumentException}).
    397    *
    398    * <p>The returned converter is serializable if both provided functions are.
    399    *
    400    * @since 17.0
    401    */
    402   public static <A, B> Converter<A, B> from(
    403       Function<? super A, ? extends B> forwardFunction,
    404       Function<? super B, ? extends A> backwardFunction) {
    405     return new FunctionBasedConverter<A, B>(forwardFunction, backwardFunction);
    406   }
    407 
    408   private static final class FunctionBasedConverter<A, B>
    409       extends Converter<A, B> implements Serializable {
    410     private final Function<? super A, ? extends B> forwardFunction;
    411     private final Function<? super B, ? extends A> backwardFunction;
    412 
    413     private FunctionBasedConverter(
    414         Function<? super A, ? extends B> forwardFunction,
    415         Function<? super B, ? extends A> backwardFunction) {
    416       this.forwardFunction = checkNotNull(forwardFunction);
    417       this.backwardFunction = checkNotNull(backwardFunction);
    418     }
    419 
    420     @Override
    421     protected B doForward(A a) {
    422       return forwardFunction.apply(a);
    423     }
    424 
    425     @Override
    426     protected A doBackward(B b) {
    427       return backwardFunction.apply(b);
    428     }
    429 
    430     @Override
    431     public boolean equals(@Nullable Object object) {
    432       if (object instanceof FunctionBasedConverter) {
    433         FunctionBasedConverter<?, ?> that = (FunctionBasedConverter<?, ?>) object;
    434         return this.forwardFunction.equals(that.forwardFunction)
    435             && this.backwardFunction.equals(that.backwardFunction);
    436       }
    437       return false;
    438     }
    439 
    440     @Override
    441     public int hashCode() {
    442       return forwardFunction.hashCode() * 31 + backwardFunction.hashCode();
    443     }
    444 
    445     @Override
    446     public String toString() {
    447       return "Converter.from(" + forwardFunction + ", " + backwardFunction + ")";
    448     }
    449   }
    450 
    451   /**
    452    * Returns a serializable converter that always converts or reverses an object to itself.
    453    */
    454   @SuppressWarnings("unchecked") // implementation is "fully variant"
    455   public static <T> Converter<T, T> identity() {
    456     return (IdentityConverter<T>) IdentityConverter.INSTANCE;
    457   }
    458 
    459   /**
    460    * A converter that always converts or reverses an object to itself. Note that T is now a
    461    * "pass-through type".
    462    */
    463   private static final class IdentityConverter<T> extends Converter<T, T> implements Serializable {
    464     static final IdentityConverter INSTANCE = new IdentityConverter();
    465 
    466     @Override
    467     protected T doForward(T t) {
    468       return t;
    469     }
    470 
    471     @Override
    472     protected T doBackward(T t) {
    473       return t;
    474     }
    475 
    476     @Override
    477     public IdentityConverter<T> reverse() {
    478       return this;
    479     }
    480 
    481     @Override
    482     <S> Converter<T, S> doAndThen(Converter<T, S> otherConverter) {
    483       return checkNotNull(otherConverter, "otherConverter");
    484     }
    485 
    486     /*
    487      * We *could* override convertAll() to return its input, but it's a rather pointless
    488      * optimization and opened up a weird type-safety problem.
    489      */
    490 
    491     @Override
    492     public String toString() {
    493       return "Converter.identity()";
    494     }
    495 
    496     private Object readResolve() {
    497       return INSTANCE;
    498     }
    499 
    500     private static final long serialVersionUID = 0L;
    501   }
    502 }
    503