org.jinq.orm.stream.JinqStream Maven / Gradle / Ivy
package org.jinq.orm.stream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import org.jinq.tuples.Pair;
import org.jinq.tuples.Tuple3;
import org.jinq.tuples.Tuple4;
import org.jinq.tuples.Tuple5;
public interface JinqStream extends Stream
{
public static interface Where extends Serializable {
public boolean where(U obj) throws E;
}
public JinqStream where(Where test);
public static interface Select extends Serializable {
public V select(U val);
}
public JinqStream select(Select select);
// TODO: Joins are somewhat dangerous because certain types of joins that are
// expressible here are NOT expressible in SQL. (Moving a join into
// a from clause is only possible if the join does not access variables from
// other things in the FROM clause *if* it ends up as a subquery. If we can
// express it as not a subquery, then it's ok.
// TODO: Perhaps only providing a join(DBSet other) is safer because
// I think it will translate into valid SQL code, but it prevents people from
// using navigational queries e.g. customers.join(customer -> customer.getPurchases);
public static interface Join extends Serializable {
public JinqStream join(U val);
}
public JinqStream> join(Join join);
public static interface JoinWithSource extends Serializable {
public JinqStream join(U val, InQueryStreamSource source);
}
public JinqStream> join(JoinWithSource join);
public JinqStream unique();
public static interface AggregateGroup extends Serializable {
public V aggregateSelect(W key, JinqStream val);
}
public JinqStream> group(Select select, AggregateGroup aggregate);
/** @see #group(Select, AggregateGroup) */
public JinqStream> group(Select select,
AggregateGroup aggregate1, AggregateGroup aggregate2);
/** @see #group(Select, AggregateGroup) */
public JinqStream> group(Select select,
AggregateGroup aggregate1, AggregateGroup aggregate2,
AggregateGroup aggregate3);
/** @see #group(Select, AggregateGroup) */
public JinqStream> group(Select select,
AggregateGroup aggregate1, AggregateGroup aggregate2,
AggregateGroup aggregate3, AggregateGroup aggregate4);
// TODO: This interface is a little iffy since the function can potentially return different number types
// and things can't be checked until runtime, but Java type inferencing currently can't
// disambiguate between different methods that take functions with different return types.
// In most cases, this should be fine as long as programmers define V as something specific
// like Integer or Double instead of something generic like Number.
// These interfaces are used to define the lambdas used as parameters to various aggregation
// operations.
public static interface CollectNumber> extends Serializable {
public V aggregate(U val);
}
public static interface CollectComparable> extends Serializable {
public V aggregate(U val);
}
public static interface CollectInteger extends CollectNumber {}
public static interface CollectLong extends CollectNumber {}
public static interface CollectDouble extends CollectNumber {}
public static interface CollectBigDecimal extends CollectNumber {}
public static interface CollectBigInteger extends CollectNumber {}
// Having separate sum() methods for different types is messy but due to problems
// with Java's type inferencing and the fact that JPQL uses different return types
// for a sum than the types being summed over, this is the only way to do sum
// operations in a type-safe way.
public Long sumInteger(CollectInteger aggregate);
public Long sumLong(CollectLong aggregate);
public Double sumDouble(CollectDouble aggregate);
public BigDecimal sumBigDecimal(CollectBigDecimal aggregate);
public BigInteger sumBigInteger(CollectBigInteger aggregate);
// TODO: It's more type-safe to have separate maxDouble(), maxDate(), etc. methods,
// but it's too messy, so I'll provide this simpler max() method for now
public > V max(CollectComparable aggregate);
public > V min(CollectComparable aggregate);
public > Double avg(CollectNumber aggregate);
public static interface AggregateSelect extends Serializable {
public V aggregateSelect(JinqStream val);
}
// public U selectAggregates(AggregateSelect aggregate);
// public U aggregate(AggregateSelect aggregate1);
public Pair aggregate(AggregateSelect aggregate1,
AggregateSelect aggregate2);
/**
* @see #aggregate(AggregateSelect, AggregateSelect)
*/
public Tuple3 aggregate(AggregateSelect aggregate1,
AggregateSelect aggregate2, AggregateSelect aggregate3);
/**
* @see #aggregate(AggregateSelect, AggregateSelect)
*/
public Tuple4 aggregate(AggregateSelect aggregate1,
AggregateSelect aggregate2, AggregateSelect aggregate3,
AggregateSelect aggregate4);
/**
* @see #aggregate(AggregateSelect, AggregateSelect)
*/
public Tuple5 aggregate(AggregateSelect aggregate1,
AggregateSelect aggregate2, AggregateSelect aggregate3,
AggregateSelect aggregate4, AggregateSelect aggregate5);
public > JinqStream sortedBy(CollectComparable sortField);
public > JinqStream sortedDescendingBy(CollectComparable sortField);
// Overriding the Stream API versions to return a JinqStream instead, so it's easier to chain them
@Override public JinqStream skip(long n);
@Override public JinqStream limit(long n);
public T getOnlyValue();
public JinqStream with(T toAdd);
// TODO: Should toList() throw an exception?
public List toList();
public String getDebugQueryString();
/**
* Used for recording an exception that occurred during processing
* somewhere in the stream chain.
*
* @param source lambda object that caused the exception (used so that
* if the same lambda causes multiple exceptions, only some of them
* need to be recorded in order to avoid memory issues)
* @param exception actual exception object
*/
public void propagateException(Object source, Throwable exception);
public Collection getExceptions();
/**
* Sets a hint on the stream for how the query should be executed
* @param name
* @param value
* @return this
*/
public JinqStream setHint(String name, Object value);
/**
* Easy way to get a JinqStream from a collection.
*/
public static JinqStream from(Collection collection)
{
return new NonQueryJinqStream<>(collection.stream());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy