/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.jooby; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.SortedSet; import com.google.common.primitives.Primitives; import com.google.inject.TypeLiteral; import com.google.inject.util.Types; /** * <p> * A type safe {@link Mutant} useful for reading parameters/headers/session attributes, etc.. * </p> * * <pre> * // str param * String value = request.param("str").value(); * * // optional str * String value = request.param("str").value("defs"); * * // int param * int value = request.param("some").intValue(); * * // optional int param * Optional{@literal <}Integer{@literal >} value = request.param("some").toOptional(Integer.class); * // list param * List{@literal <}String{@literal >} values = request.param("some").toList(String.class); * * // file upload * Upload upload = request.param("file").to(Upload.class); * </pre> * * @author edgar * @since 0.1.0 * @see Request#param(String) * @see Request#header(String) */ public interface Mutant { /** * @return Get a boolean when possible. */ default boolean booleanValue() { return to(boolean.class); } /** * @param value Default value to use. * @return Get a boolean. */ default boolean booleanValue(final boolean value) { return toOptional(Boolean.class).orElse(value); } /** * @return Get a byte when possible. */ default byte byteValue() { return to(byte.class); } /** * @param value Default value to use. * @return Get a byte. */ default byte byteValue(final byte value) { return toOptional(Byte.class).orElse(value); } /** * @return Get a byte when possible. */ default char charValue() { return to(char.class); } /** * @param value Default value to use. * @return Get a char. */ default char charValue(final char value) { return toOptional(Character.class).orElse(value); } /** * @return Get a short when possible. */ default short shortValue() { return to(short.class); } /** * @param value Default value to use. * @return Get a short value. */ default short shortValue(final short value) { return toOptional(Short.class).orElse(value); } /** * @return Get an integer when possible. */ default int intValue() { return to(int.class); } /** * @param value Default value to use. * @return Get an integer. */ default int intValue(final int value) { return toOptional(Integer.class).orElse(value); } /** * @return Get a long when possible. */ default long longValue() { return to(long.class); } /** * @param value Default value to use. * @return Get a long. */ default long longValue(final long value) { return toOptional(Long.class).orElse(value); } /** * @return Get a string when possible. */ default String value() { return to(String.class); } /** * @param value Default value to use. * @return Get a string. */ default String value(final String value) { return toOptional().orElse(value); } /** * @return Get a float when possible. */ default float floatValue() { return to(float.class); } /** * @param value Default value to use. * @return Get a float. */ default float floatValue(final float value) { return toOptional(Float.class).orElse(value); } /** * @return Get a double when possible. */ default double doubleValue() { return to(double.class); } /** * @param value Default value to use. * @return Get a double. */ default double doubleValue(final double value) { return toOptional(Double.class).orElse(value); } /** * @param type The enum type. * @param <T> Enum type. * @return Get an enum when possible. */ default <T extends Enum<T>> T toEnum(final Class<T> type) { return to(type); } /** * @param value Default value to use. * @param <T> Enum type. * @return Get an enum. */ @SuppressWarnings("unchecked") default <T extends Enum<T>> T toEnum(final T value) { Optional<T> optional = (Optional<T>) toOptional(value.getClass()); return optional.orElse(value); } /** * @param type The element type. * @param <T> List type. * @return Get list of values when possible. */ @SuppressWarnings("unchecked") default <T> List<T> toList(final Class<T> type) { return (List<T>) to(TypeLiteral.get(Types.listOf(Primitives.wrap(type)))); } /** * @return Get list of values when possible. */ default List<String> toList() { return toList(String.class); } /** * @return Get set of values when possible. */ default Set<String> toSet() { return toSet(String.class); } /** * @param type The element type. * @param <T> Set type. * @return Get set of values when possible. */ @SuppressWarnings("unchecked") default <T> Set<T> toSet(final Class<T> type) { return (Set<T>) to(TypeLiteral.get(Types.setOf(Primitives.wrap(type)))); } /** * @return Get sorted set of values when possible. */ default SortedSet<String> toSortedSet() { return toSortedSet(String.class); } /** * @param type The element type. * @param <T> Set type. * @return Get sorted set of values when possible. */ @SuppressWarnings("unchecked") default <T extends Comparable<T>> SortedSet<T> toSortedSet(final Class<T> type) { return (SortedSet<T>) to(TypeLiteral.get( Types.newParameterizedType(SortedSet.class, Primitives.wrap(type)) )); } /** * @return An optional string value. */ default Optional<String> toOptional() { return toOptional(String.class); } /** * @param type The optional type. * @param <T> Optional type. * @return Get an optional value when possible. */ @SuppressWarnings("unchecked") default <T> Optional<T> toOptional(final Class<T> type) { return (Optional<T>) to(TypeLiteral.get( Types.newParameterizedType(Optional.class, Primitives.wrap(type)) )); } /** * Convert a form field to file {@link Upload}. * * @return A file {@link Upload}. */ default Upload toUpload() { return to(Upload.class); } /** * Convert a raw value to the given type. * * @param type The type to convert to. * @param <T> Target type. * @return Get a value when possible. */ default <T> T to(final Class<T> type) { return to(TypeLiteral.get(type)); } /** * Convert a raw value to the given type. * * @param type The type to convert to. * @param <T> Target type. * @return Get a value when possible. */ <T> T to(TypeLiteral<T> type); /** * Convert a raw value to the given type. This method will temporary set {@link MediaType} before * parsing a value, useful if a form field from a HTTP POST was send as json (or any other data). * * @param type The type to convert to. * @param mtype A media type to hint a parser. * @param <T> Target type. * @return Get a value when possible. */ default <T> T to(final Class<T> type, final String mtype) { return to(type, MediaType.valueOf(mtype)); } /** * Convert a raw value to the given type. This method will temporary set {@link MediaType} before * parsing a value, useful if a form field from a HTTP POST was send as json (or any other data). * * @param type The type to convert to. * @param mtype A media type to hint a parser. * @param <T> Target type. * @return Get a value when possible. */ default <T> T to(final Class<T> type, final MediaType mtype) { return to(TypeLiteral.get(type), mtype); } /** * Convert a raw value to the given type. This method will temporary set {@link MediaType} before * parsing a value, useful if a form field from a HTTP POST was send as json (or any other data). * * @param type The type to convert to. * @param mtype A media type to hint a parser. * @param <T> Target type. * @return Get a value when possible. */ default <T> T to(final TypeLiteral<T> type, final String mtype) { return to(type, MediaType.valueOf(mtype)); } /** * Convert a raw value to the given type. This method will temporary set {@link MediaType} before * parsing a value, useful if a form field from a HTTP POST was send as json (or any other data). * * @param type The type to convert to. * @param mtype A media type to hint a parser. * @param <T> Target type. * @return Get a value when possible. */ <T> T to(TypeLiteral<T> type, MediaType mtype); /** * A map view of this mutant. * * If this mutant is the result of {@link Request#params()} the resulting map will have all the * available parameter names. * * If the mutant is the result of {@link Request#param(String)} the resulting map will have just * one entry, with the name as key. * * If the mutant is the result of {@link Request#body()} the resulting map will have just * one entry, with a key of <code>body</code>. * * @return A map view of this mutant. */ Map<String, Mutant> toMap(); /** * @return True if this mutant has a value (param, header, body, etc...). */ boolean isSet(); }