All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.softhouse.common.guavaextensions.Functions2 Maven / Gradle / Ivy

/* Copyright 2013 Jonatan Jönsson
 *
 *    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 se.softhouse.common.guavaextensions;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;

/**
 * Gives you static access to additional implementations of the {@link Function} interface, as a
 * complement to {@link Functions}
 */
@Immutable
public final class Functions2
{
	private Functions2()
	{
	}

	/**
	 * Runs several {@link Function}s in the same order as they are
	 * given as arguments here.
* If one of the {@link Function}s makes {@code T} {@link Immutable}, * make sure to pass it in last as it's hard to modify * an {@link Immutable} value. This works exactly like * {@link Functions#compose(Function, Function)} except that if {@code first} doesn't do * anything, {@code second} is returned directly instead. * * @param first a {@link Function} * @param second another {@link Function} * @return a merged {@link Function} */ @Nonnull public static Function compound(Function first, Function second) { checkNotNull(first); checkNotNull(second); if(first == Functions.identity()) return second; return new CompoundFunction(first, second); } private static final class CompoundFunction implements Function { @Nonnull private final Function first; @Nonnull private final Function second; private CompoundFunction(Function first, Function second) { this.first = first; this.second = second; } @Nullable @Override public T apply(@Nullable T value) { return second.apply(first.apply(value)); } } /** * Creates a {@link Function} that applies {@code elementTransformer} to each element of the * input {@link List} and puts the new elements in a new , immutable, list and returns it. */ @Nonnull public static Function, List> listTransformer(Function elementTransformer) { if(elementTransformer == Functions.identity()) return Functions.identity(); return new ListTransformer(elementTransformer); } private static final class ListTransformer implements Function, List> { private final Function elementTransformer; private ListTransformer(Function elementTransformer) { this.elementTransformer = checkNotNull(elementTransformer); } @Override public List apply(List values) { if(values == null) return null; return ImmutableList.copyOf(Lists.transform(values, elementTransformer)); } } /** * Creates a {@link Function} that applies {@code valueTransformer} to each value of the * input {@link Map} and puts them in a new , immutable, map and returns it. */ @Nonnull public static Function, Map> mapValueTransformer(Function valueTransformer) { if(valueTransformer == Functions.identity()) return Functions.identity(); return new MapValueTransformer(valueTransformer); } private static final class MapValueTransformer implements Function, Map> { private final Function valueTransformer; private MapValueTransformer(Function valueTransformer) { this.valueTransformer = checkNotNull(valueTransformer); } @Override public Map apply(Map map) { if(map == null) return null; return ImmutableMap.copyOf(Maps.transformValues(map, valueTransformer)); } } /** * Creates a {@link Function} that wraps {@link List}s with * {@link Collections#unmodifiableList(List)} */ @Nonnull public static Function, List> unmodifiableList() { return new UnmodifiableListMaker(); } private static final class UnmodifiableListMaker implements Function, List> { @Override public List apply(List value) { if(value == null) return null; return Collections.unmodifiableList(value); } } /** * Creates a {@link Function} that wraps {@link Map}s with * {@link Collections#unmodifiableMap(Map)} */ @Nonnull public static Function, Map> unmodifiableMap() { return new UnmodifiableMapMaker(); } private static final class UnmodifiableMapMaker implements Function, Map> { @Override public Map apply(Map value) { if(value == null) return null; return Collections.unmodifiableMap(value); } } /** * Runs {@code function} {@code times} times. * The result of the first call is passed to the next apply in the chain and so on. * For instance: * *
	 * 
	 * assertThat(Functions2.repeat(ADD_ONE, 2).apply(0)).isEqualTo(2);
	 * 
	 * 
*/ @Nonnull public static Function repeat(Function function, long times) { checkNotNull(function); checkArgument(times >= 0, "times (%s) must be positive", times); return new FunctionRepeater(function, times); } private static final class FunctionRepeater implements Function { private final long times; @Nonnull private final Function function; private FunctionRepeater(Function function, long times) { this.function = function; this.times = times; } @Override public T apply(T input) { T output = input; for(long i = 0; i < times; i++) { output = function.apply(output); } return output; } } /** * Returns a {@link Function} that reads whole {@link File}s into {@link String}s using the * {@link Charsets#UTF_8 UTF-8} charset. */ public static Function fileToString() { return FileToString.INSTANCE; } private static final class FileToString implements Function { private static final Function INSTANCE = new FileToString(); @Override public String apply(@Nonnull File input) { if(input.isDirectory()) throw new IllegalArgumentException(input.getAbsolutePath() + " is a directory, not a file"); try { return Files.toString(input, Charsets.UTF_8); } catch(IOException e) { throw new IllegalArgumentException("I/O error occured while reading: " + input.getAbsolutePath(), e); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy