001package conexp.fx.core.math;
002
003/*
004 * #%L
005 * Concept Explorer FX
006 * %%
007 * Copyright (C) 2010 - 2023 Francesco Kriegel
008 * %%
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as
011 * published by the Free Software Foundation, either version 3 of the
012 * License, or (at your option) any later version.
013 * 
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 * 
019 * You should have received a copy of the GNU General Public
020 * License along with this program.  If not, see
021 * <http://www.gnu.org/licenses/gpl-3.0.html>.
022 * #L%
023 */
024
025import com.google.common.base.Function;
026
027public abstract class GuavaIsomorphism<A, B> implements Function<A, B> {
028
029  public static final <A> GuavaIsomorphism<A, A> identity() {
030    return new GuavaIsomorphism<A, A>() {
031
032      @Override
033      public A apply(A a) {
034        return a;
035      }
036
037      @Override
038      public A invert(A a) {
039        return a;
040      }
041    };
042  }
043
044  public static final <A, B> GuavaIsomorphism<A, B> create(final Function<A, B> function, final Function<B, A> inverse) {
045    return new GuavaIsomorphism<A, B>() {
046
047      @Override
048      public final B apply(final A a) {
049        return function.apply(a);
050      }
051
052      @Override
053      public final A invert(final B b) {
054        return inverse.apply(b);
055      }
056
057      @Override
058      public Function<A, B> function() {
059        return function;
060      }
061
062      @Override
063      public Function<B, A> inverse() {
064        return inverse;
065      }
066    };
067  }
068
069  public static final <A, B> GuavaIsomorphism<B, A> invert(final GuavaIsomorphism<A, B> isomorphism) {
070    return new GuavaIsomorphism<B, A>() {
071
072      @Override
073      public final A apply(final B b) {
074        return isomorphism.invert(b);
075      }
076
077      @Override
078      public final B invert(final A a) {
079        return isomorphism.apply(a);
080      }
081
082      @Override
083      public Function<B, A> function() {
084        return isomorphism.inverse();
085      }
086
087      @Override
088      public Function<A, B> inverse() {
089        return isomorphism.function();
090      }
091    };
092  }
093
094  public static final <A, B, C> GuavaIsomorphism<A, C>
095      compose(final GuavaIsomorphism<A, B> isomorphism1, final GuavaIsomorphism<B, C> isomorphism2) {
096    return new GuavaIsomorphism<A, C>() {
097
098      @Override
099      public final C apply(final A a) {
100        return isomorphism2.apply(isomorphism1.apply(a));
101      }
102
103      @Override
104      public final A invert(final C c) {
105        return isomorphism1.invert(isomorphism2.invert(c));
106      }
107    };
108  }
109
110  public A invert(B b) {
111    throw new RuntimeException();
112  }
113
114  public Function<A, B> function() {
115    return this;
116  }
117
118  public Function<B, A> inverse() {
119    return new Function<B, A>() {
120
121      @Override
122      public final A apply(final B b) {
123        return GuavaIsomorphism.this.invert(b);
124      }
125    };
126  }
127
128  public final java.util.function.Function<A, B> toJavaFunction() {
129    return a -> apply(a);
130  }
131
132  public final java.util.function.Function<B, A> inverseToJavaFunction() {
133    return b -> invert(b);
134  }
135}