/**
* Copyright (C) 2011
* Michael Mosmann <michael@mosmann.de>
* Jan Bernitt <unknown@email.de>
*
* with contributions from
* nobody yet
*
* Licensed 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.
*/
package de.flapdoodle.functions;
/**
* function aggregation helper
*/
public class Functions {
private Functions() {
// no instance
}
/**
* joins two functions with matching types to a new function
* converts T to X to R
*
* @param outer
* the last applied function
* @param inner
* the first applied function
* @return a new function
*/
public static <R, X, T> Function1<R, T> join(Function1<R, ? super X> outer, Function1<X, ? super T> inner) {
return new JoinedFunction1<R, X, T>(outer, inner);
}
/**
* joins to functions with matching types to a new function
* converts T2 to X and T1 to R
* @param outer
* the last applied function
* @param inner
* the first applied function
* @return a new function
*/
public static <R, T1, T2, X> Function2<R, T1, T2> join(Function2<R, ? super T1, ? super X> outer, Function1<X, ? super T2> inner) {
return new JoinedFunction2<R, T1, T2, X>(outer, inner);
}
/**
* joins to functions with matching types to a new function
* converts T2 and T3 to X and T1 to R
* @param outer
* the last applied function
* @param inner
* the first applied function
* @return a new function
*/
public static <R, T1, T2, T3, X> Function3<R, T1, T2, T3> join(Function2<R, ? super T1, ? super X> outer, Function2<X, ? super T2, ? super T3> inner) {
return new JoinedFunction3<R, T1, T2, T3, X>(outer, inner);
}
/**
* joins to functions with matching types to a new function
* converts T2 and T3 to X and T1 to R
* @param outer
* the last applied function
* @param inner
* the first applied function
* @return a new function
*/
public static <R, T1, T2, T3, A, B> Function3<R, T1, T2, T3> join(Function2<R, ? super A, ? super B> outer, Function2<A, ? super T1, ? super T2> left, Function2<B, ? super T2, ? super T3> right) {
return new JoinedFunction33<R, T1, T2, T3, A, B>(outer, left, right);
}
/**
* swap function type signature without changing behavior
*
* @param source
* source function
* @return function adapter with flipped types
*/
public static <R, T1, T2> Function2<R, T1, T2> swap(Function2<R, ? super T2, ? super T1> source) {
return new SwappedTypeFunction<R, T1, T2>(source);
}
static class JoinedFunction1<R, X, T> implements Function1<R, T> {
private final Function1<R, ? super X> _outer;
private final Function1<X, ? super T> _inner;
public JoinedFunction1(Function1<R, ? super X> a, Function1<X, ? super T> b) {
_outer = a;
_inner = b;
}
@Override
public R apply(T value) {
return _outer.apply(_inner.apply(value));
}
}
static class JoinedFunction2<R, T1, T2, X> implements Function2<R, T1, T2> {
private final Function2<R, ? super T1, ? super X> _outer;
private final Function1<X, ? super T2> _inner;
public JoinedFunction2(Function2<R, ? super T1, ? super X> outer, Function1<X, ? super T2> inner) {
_outer = outer;
_inner = inner;
}
@Override
public R apply(T1 a, T2 b) {
return _outer.apply(a, _inner.apply(b));
}
}
static class JoinedFunction3<R, T1, T2, T3, X> implements Function3<R, T1, T2, T3> {
private final Function2<R, ? super T1, ? super X> _outer;
private final Function2<X, ? super T2, ? super T3> _inner;
public JoinedFunction3(Function2<R, ? super T1, ? super X> outer, Function2<X, ? super T2, ? super T3> inner) {
_outer = outer;
_inner = inner;
}
@Override
public R apply(T1 a, T2 b, T3 c) {
return _outer.apply(a, _inner.apply(b, c));
}
}
static class JoinedFunction33<R, T1, T2, T3, A, B> implements Function3<R, T1, T2, T3> {
private final Function2<R, ? super A, ? super B> _outer;
private final Function2<A, ? super T1, ? super T2> _left;
private final Function2<B, ? super T2, ? super T3> _right;
public JoinedFunction33(Function2<R, ? super A, ? super B> outer, Function2<A, ? super T1, ? super T2> left, Function2<B, ? super T2, ? super T3> right) {
_outer = outer;
_left = left;
_right = right;
}
@Override
public R apply(T1 a, T2 b, T3 c) {
return _outer.apply(_left.apply(a, b),_right.apply(b, c));
}
}
static class SwappedTypeFunction<R, T1, T2> implements Function2<R, T1, T2> {
private final Function2<R, ? super T2, ? super T1> _source;
public SwappedTypeFunction(Function2<R, ? super T2, ? super T1> source) {
_source = source;
}
@Override
public R apply(T1 a, T2 b) {
return _source.apply(b, a);
}
}
}