package org.quaere.operations; import org.quaere.dsl.*; import org.quaere.QueryableIterable; import org.quaere.Queryable; import org.quaere.QueryEngine; import org.quaere.operations.DefaultOperations; import org.quaere.objects.ObjectQueryEngine; import org.quaere.expressions.Identifier; import org.quaere.expressions.Statement; import java.util.Arrays; import java.util.Iterator; import java.util.Map; /** * @author mh14 @ jexp.de * @since 11.11.2007 02:31:19 (c) 2007 jexp.de */ public class FirstOperationImpl implements FirstOperation { public static final FirstOperation FIRST = new FirstOperationImpl(); public <T> ElementOperatorArgumentDefinitionBuilder in(T[] source) { return in(Arrays.asList(source)); } public <T> ElementOperatorArgumentDefinitionBuilder in(Iterable<T> source) { return in(new QueryableIterable<T>(source)); } public <T> ElementOperatorArgumentDefinitionBuilder in(Queryable<T> source) { ElementOperatorBuilder builder = new ElementOperatorBuilderImpl("first"); return builder.in(source); } public static <R> R firstInIterable(Iterable<R> source) { Iterator<R> iter = source.iterator(); if (iter.hasNext()) { return iter.next(); } else { return null; } } public static <R> R firstInQueryable(Queryable<R> source) { Identifier sourceIdentifier = Identifier.createUniqueIdentfier(); Statement query = DefaultOperations.createMethodCallStatement(sourceIdentifier, "first"); QueryEngine queryEngine = DefaultOperations.createEngineAndAddSource(sourceIdentifier, source); //noinspection RedundantTypeArguments return queryEngine.<R>evaluate(query); // <-- IntelliJ suggests that <R> can be inferred, but this leads to a compilation error. } public static <R> R firstInQueryBodyBuilder(QueryBodyBuilder<?> query) { QueryExpressionBuilderImpl<R> impl = (QueryExpressionBuilderImpl<R>) query; Statement statement = DefaultOperations.createMethodCallStatement(query.getQueryExpression(), "first"); ObjectQueryEngine engine = new ObjectQueryEngine(); for (Map.Entry<Identifier, Queryable> sourceEntry : impl.getSources().entrySet()) { engine.addSource(sourceEntry.getValue().getSourceIdentifier(sourceEntry.getKey()), sourceEntry.getValue()); } //noinspection RedundantTypeArguments return engine.<R>evaluate(statement); // <-- IntelliJ suggests that <R> can be inferred, but we get a compilation error if its not specified. } public static <R> R first(final Object source) { // NOTE: Explicit type argument is required in the following section support Eclipse. if (source instanceof QueryBodyBuilder<?>) { return FirstOperationImpl.<R>firstInQueryBodyBuilder((QueryBodyBuilder) source); } else if (source instanceof Queryable<?>) { // NOTE: The unchecked casts is required for IDEA to build the module while the call is redirected to // an explicitly typed method on the DSL class. return firstInQueryable((Queryable<R>) source); } else if (source instanceof Iterable<?>) { return firstInIterable((Iterable<R>) source); } throw new IllegalArgumentException("Cannot retrieve first element from " + source.getClass().getName()); } public static <R> R firstFromArray(final R... source) { if (source.length > 0) { return source[0]; } else { return null; } } }