| /* |
| * Copyright (c) 2010, Rickard Öberg. All Rights Reserved. |
| * |
| * 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 org.qi4j.functional; |
| |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * Utility functions. Combine these with methods in Iterables, for example. See FunctionsTest for usages. |
| */ |
| public final class Functions |
| { |
| public static <A, B, C> Function2<Function<? super B, C>, Function<A, B>, Function<A, C>> compose() |
| { |
| return new Function2<Function<? super B, C>, Function<A, B>, Function<A, C>>() |
| { |
| @Override |
| public Function<A, C> map( Function<? super B, C> bcFunction, Function<A, B> abFunction ) |
| { |
| return compose( bcFunction, abFunction ); |
| } |
| }; |
| } |
| |
| /** |
| * compose(F1(M,T),F2(F,M)) = F1(F2(F)) -> T |
| * |
| * @param outer The outer/encapsulating function |
| * @param inner The inner/encapsulated function |
| * |
| * @return A function that is a composition of an outer and inner function. |
| */ |
| public static <FROM, MIDDLE, TO> Function<FROM, TO> compose( final Function<? super MIDDLE, TO> outer, |
| final Function<FROM, MIDDLE> inner |
| ) |
| { |
| return new Function<FROM, TO>() |
| { |
| @Override |
| public TO map( FROM from ) |
| { |
| return outer.map( inner.map( from ) ); |
| } |
| }; |
| } |
| |
| public static <TO, FROM extends TO> Function<FROM, TO> identity() |
| { |
| return new Function<FROM, TO>() |
| { |
| @Override |
| public TO map( FROM from ) |
| { |
| return from; |
| } |
| }; |
| } |
| |
| public static <FROM, TO> Function<FROM, TO> fromMap( final Map<FROM, TO> map ) |
| { |
| return new Function<FROM, TO>() |
| { |
| @Override |
| public TO map( FROM from ) |
| { |
| return map.get( from ); |
| } |
| }; |
| } |
| |
| public static <T> Function<T, T> withDefault( final T defaultValue ) |
| { |
| return new Function<T, T>() |
| { |
| @Override |
| public T map( T from ) |
| { |
| if( from == null ) |
| { |
| return defaultValue; |
| } |
| else |
| { |
| return from; |
| } |
| } |
| }; |
| } |
| |
| public static Function<Number, Long> longSum() |
| { |
| return new Function<Number, Long>() |
| { |
| long sum; |
| |
| @Override |
| public Long map( Number number ) |
| { |
| sum += number.longValue(); |
| return sum; |
| } |
| }; |
| } |
| |
| public static Function<Number, Integer> intSum() |
| { |
| return new Function<Number, Integer>() |
| { |
| int sum; |
| |
| @Override |
| public Integer map( Number number ) |
| { |
| sum += number.intValue(); |
| return sum; |
| } |
| }; |
| } |
| |
| /** |
| * Count the number of items in an iterable that matches a given specification. |
| * |
| * Sample usage: last( map( count( in( "X" ) ), iterable( "X","Y","X","X","Y" ) ) ) |
| * Returns: 3 |
| * |
| * @param specification The items that adhere to the Specification is counted. |
| * @param <T> The type of the items. |
| * |
| * @return A Function that can count items adhering to a Specification. |
| */ |
| public static <T> Function<T, Integer> count( final Specification<T> specification ) |
| { |
| return new Function<T, Integer>() |
| { |
| int count; |
| |
| @Override |
| public Integer map( T item ) |
| { |
| if( specification.satisfiedBy( item ) ) |
| { |
| count++; |
| } |
| |
| return count; |
| } |
| }; |
| } |
| |
| /** |
| * Find out the index of an item matching a given specification in an iterable. |
| * Returns -1 if it is not found. |
| * |
| * @param specification The Specification that specifies what to look for. |
| * @param <T> The type of the items. |
| * |
| * @return A Function that will provide the 'index' where the Specifcation is fulfilled. The Function will |
| * return -1 if the current item doesn't fulfill the Specification. |
| */ |
| public static <T> Function<T, Integer> indexOf( final Specification<T> specification ) |
| { |
| return new Function<T, Integer>() |
| { |
| int index = -1; |
| int current = 0; |
| |
| @Override |
| public Integer map( T item ) |
| { |
| if( index == -1 && specification.satisfiedBy( item ) ) |
| { |
| index = current; |
| } |
| |
| current++; |
| |
| return index; |
| } |
| }; |
| } |
| |
| /** |
| * Find out the index of an item in an iterable. |
| * |
| * @param item The item to look for. |
| * @param iterable The Iterable to search. |
| * @param <T> The type of the items. |
| * |
| * @return The index in the Iterable where the item is located. |
| */ |
| @SuppressWarnings( "unchecked" ) |
| public static <T> int indexOf( T item, Iterable<T> iterable ) |
| { |
| return Iterables.first( Iterables.filter( Specifications.not( Specifications.in( -1 ) ), |
| Iterables.map( indexOf( Specifications.in( item ) ), iterable ) ) ); |
| } |
| |
| /** |
| * Only apply given function on objects that satisfies the given specification. |
| * |
| * @param specification A Specification that specifies what should be included in the filtered result. |
| * @param function The function to be applied to items that fulfills the Specification |
| * @param <T> The type of the items. |
| * |
| * @return A Function that performs the filter operation when applied to Iterables. |
| */ |
| public static <T> Function<T, T> filteredMap( final Specification<T> specification, final Function<T, T> function ) |
| { |
| return new Function<T, T>() |
| { |
| @Override |
| public T map( T from ) |
| { |
| return specification.satisfiedBy( from ) ? function.map( from ) : from; |
| } |
| }; |
| } |
| |
| /** |
| * Creates a comparator that takes a function as input. The returned comparator will use the |
| * function once for each item in the list to be sorted by Collections.sort. |
| * |
| * This should be used if the function to generate the sort key from an object is expensive, so |
| * that it is not done many times for each item in a list. |
| * |
| * @param comparableFunction The Function that the Comparator will delegate to. |
| * @param <T> The generic type to be used. |
| * |
| * @return A comparator that uses a Function for the compare operation. |
| */ |
| @SuppressWarnings( "raw" ) |
| public static <T> Comparator<T> comparator( final Function<T, Comparable> comparableFunction ) |
| { |
| return new Comparator<T>() |
| { |
| Map<T, Comparable> compareKeys = new HashMap<>(); |
| |
| @Override |
| @SuppressWarnings( "unchecked" ) |
| public int compare( T o1, T o2 ) |
| { |
| Comparable key1 = compareKeys.get( o1 ); |
| if( key1 == null ) |
| { |
| key1 = comparableFunction.map( o1 ); |
| compareKeys.put( o1, key1 ); |
| } |
| |
| Comparable key2 = compareKeys.get( o2 ); |
| if( key2 == null ) |
| { |
| key2 = comparableFunction.map( o2 ); |
| compareKeys.put( o2, key2 ); |
| } |
| |
| return key1.compareTo( key2 ); |
| } |
| }; |
| } |
| |
| private Functions() |
| { |
| } |
| } |