package edu.washington.escience.myria.util; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import org.apache.commons.io.IOUtils; import org.joda.time.DateTime; import com.google.common.base.Preconditions; import edu.washington.escience.myria.io.AmazonS3Source; import edu.washington.escience.myria.io.UriSource; /** * Generic utilities for Myria. */ public final class MyriaUtils { private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(MyriaUtils.class); /** * Utility classes should not be instantiated. */ private MyriaUtils() {} /** * Get the only element in single-element list. * * @param input a non-null list of a single object. * @param <T> the type of the objects in the list. * @return the object. */ public static <T> T getSingleElement(final List<T> input) { Objects.requireNonNull(input); Preconditions.checkArgument(input.size() == 1, "list must contain a single element"); return input.get(0); } /** * Get the only element in single-element set. * * @param input a non-null set of a single object. * @param <T> the type of the objects in the set. * @return the object. */ public static <T> T getSingleElement(final Set<T> input) { Objects.requireNonNull(input); Preconditions.checkArgument(input.size() == 1, "list must contain a single element"); for (T e : input) { /* return only one time with the first element */ return e; } return null; } /** * Helper function that generates an array of the numbers 0..max-1. * * @param max the size of the array. * @return an array of the numbers 0..max-1. */ public static int[] range(final int max) { int[] ret = new int[max]; for (int i = 0; i < max; ++i) { ret[i] = i; } return ret; } /** * Throws an {@link IllegalArgumentException} if the specified iterable contains a null value. * * @param <T> any object type that extends Iterable * @param iter the iterable * @param message a message to be included with the exception * @return {@link IllegalArgumentException} if the iterable contains a null element. */ public static <T extends Iterable<?>> T checkHasNoNulls(final T iter, final String message) { Objects.requireNonNull(iter, message); int i = 0; for (Object o : iter) { Preconditions.checkNotNull(o, "%s [element %s]", message, i); ++i; } return iter; } /** * Copy all mappings from the source to the destination, ensuring that if any keys were already present, then the * values match. This is sort of a "map Union" operator. * * @param <K> the type of the keys. * @param <V> the type of the values. * @param source the new mappings to be added. * @param dest the destination for new mappings, which may already has some mappings. */ public static <K, V> void putNewVerifyOld(final Map<K, V> source, final Map<K, V> dest) { for (Map.Entry<K, V> entry : source.entrySet()) { K newK = entry.getKey(); V newV = entry.getValue(); V oldV = dest.get(newK); if (oldV == null) { dest.put(newK, newV); } else { Preconditions.checkArgument( oldV.equals(newV), "New value %s for key %s does not match old value %s", newV, newK, oldV); } } } /** * Ensure that the given object is a valid Myria object type and can be stored in e.g., a Column or a Field. * * @param o the object to be tested. * @return o. * @throws IllegalArgumentException if the object is not a valid Myria type. */ public static Object ensureObjectIsValidType(final Object o) throws IllegalArgumentException { if (o instanceof Boolean) { return o; } if (o instanceof Double || o instanceof Float) { return o; } if (o instanceof Integer || o instanceof Long) { return o; } if (o instanceof DateTime) { return o; } if (o instanceof String) { return o; } if (o instanceof ByteBuffer) { return o; } if (o == null) { // allow initialization with a null object -- needed for BlobType. return o; } throw new IllegalArgumentException( "Object of type " + o.getClass() + " is not a valid Myria type"); } /** * This function is called by DownloadBlob expression. It cannot throw an exception as it * is a complied expression, so, it returns null if there is an error in retriving the binary data. * @param filename uri of the binary data. * @return Binary data in ByteBuffer format. */ public static ByteBuffer getBlob(final String filename) { try { UriSource file = new UriSource(filename); InputStream is = file.getInputStream(); return ByteBuffer.wrap(IOUtils.toByteArray(is)); } catch (Exception e) { LOGGER.debug(e.getMessage()); return null; } } }