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

com.github.helenusdriver.driver.ObjectSet Maven / Gradle / Ivy

Go to download

JPA-like syntax for annotating POJO classes for persistence via Cassandra's Java driver - API

The newest version!
/*
 * Copyright (C) 2015-2015 The Helenus Driver Project Authors.
 *
 * 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 com.github.helenusdriver.driver;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.ExecutionInfo;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.google.common.util.concurrent.ListenableFuture;

/**
 * The ObjectSet class extends Cassandra's
 * {@link com.datastax.driver.core.ResultSet} class in order to provide support
 * for POJOs.
 *
 * @copyright 2015-2015 The Helenus Driver Project Authors
 *
 * @author  The Helenus Driver Project Authors
 * @version 1 - Jan 15, 2015 - paouelle - Creation
 *
 * @param  The type of POJO associated with this object set.
 *
 * @since 1.0
 */
public class ObjectSet implements Iterable {
  /**
   * Holds the statement context associated with this object set.
   *
   * @author paouelle
   */
  private final StatementManager.Context context;

  /**
   * Holds the raw future set.
   *
   * @author paouelle
   */
  private final com.datastax.driver.core.ResultSet result;

  /**
   * Instantiates a new ObjectSet object.
   *
   * @author paouelle
   *
   * @param context the non-null statement context associated with
   *        this object set
   * @param result the non-null result set
   */
  ObjectSet(StatementManager.Context context, ResultSet result) {
    this.context = context;
    this.result = result;
  }

  /**
   * Gets the columns returned in this object set.
   *
   * @author paouelle
   *
   * @return the columns returned in this object set.
   */
  public ColumnDefinitions getColumnDefinitions() {
    return result.getColumnDefinitions();
  }

  /**
   * Gets whether this object set has more POJOs.
   *
   * @author paouelle
   *
   * @return whether this object set has more POJOs.
   */
  public boolean isExhausted() {
    return result.isExhausted();
  }

  /**
   * Gets the the next POJO from this object set.
   *
   * @author paouelle
   *
   * @return the next POJO in this object set or null if this
   *         object set is exhausted
   * @throws ObjectConversionException if unable to convert to a POJO
   */
  public T one() {
    return context.getObject(result.one());
  }

  /**
   * Gets a stream of all the remaining POJOs in this object set.
   * 

* The returned stream will throw {@link ObjectConversionException} when * walked and we were unable to convert to a POJO. * * @author paouelle * * @return a non-null stream containing the remaining POJOs of * this object set */ public Stream stream() { return StreamSupport.stream(Spliterators.spliteratorUnknownSize( iterator(), Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL ), false); } /** * Gets a list of all the remaining POJOs in this object set. * * @author paouelle * * @return a non-null list containing the remaining POJOs of * this object set. The returned list is empty if and only the result * set is exhausted * @throws ObjectConversionException if unable to convert to POJOs */ public List all() { final List rows = result.all(); final List ts = new ArrayList<>(rows.size()); for (final Row row: rows) { final T obj = context.getObject(row); if (obj != null) { ts.add(obj); } } return ts; } /** * {@inheritDoc} *

* Gets an iterator over the POJOs contained in this object set. * * The {@link Iterator#next} method is equivalent to calling {@link #one}. So * this iterator will consume POJOs from this object set and after a full * iteration, the object set will be empty. * * The returned iterator does not support the {@link Iterator#remove} method * and will throw {@link ObjectConversionException} when calling * {@link Iterator#hasNext} or {@link Iterator#next} and we were unable to * convert to a POJO. * * @author paouelle * * @see java.lang.Iterable#iterator() */ @Override public Iterator iterator() { final Iterator i = result.iterator(); return new Iterator() { private T next = null; @Override @SuppressWarnings("synthetic-access") public boolean hasNext() { while ((next == null) && i.hasNext()) { // skip over all invalid type result this.next = context.getObject(i.next()); } return next != null; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException("ObjectSet Iterator"); } final T obj = next; this.next = null; return obj; } }; } /** * Gets the number of POJOs that can be retrieved from this object set without * blocking to fetch. * * @author paouelle * * @return the number of POJOs readily available in this object set. If * {@link #isFullyFetched()}, this is the total number of POJOs * remaining in this object set (after which the object set will be * exhausted) */ public int getAvailableWithoutFetching() { return result.getAvailableWithoutFetching(); } /** * Checks whether all POJOs from this object set has been fetched from the * database. *

* Note that if {@code isFullyFetched()}, then * {@link #getAvailableWithoutFetching} will return how many POJOs remains in * the object set before exhaustion. But please note that * {@code !isFullyFetched()} never guarantees that the object set is not * exhausted (you should call {@code isExhausted()} to make sure of it). * * @author paouelle * * @return whether all POJOs have been fetched */ public boolean isFullyFetched() { return result.isFullyFetched(); } /** * Force the fetching the next page of POJOs for this object set, if any. *

* This method is entirely optional. It will be called automatically while the * object set is consumed (through {@link #one}, {@link #all} or iteration) * when needed (i.e. when {@code getAvailableWithoutFetching() == 0} and * {@code isFullyFetched() == false}). *

* You can however call this method manually to force the fetching of the next * page of POJOs. This can allow to prefetch POJOs before they are strictly * needed. For instance, if you want to prefetch the next page of POJOs as * soon as there is less than 100 POJOs readily available in this object set, * you can do: * *

   *   final ObjectSet<T> os = statement.execute(...);
   *   final Iterator<T> i = os.iterator();
   *
   *   while (i.hasNext()) {
   *       if (os.getAvailableWithoutFetching() == 100 & !os.isFullyFetched())
   *           os.fetchMoreObjects();
   *       final T t = i.next()
   *
   *       ... process the POJO ...
   *   }
   * 
* * This method is not blocking, so in the example above, the call to * {@code fetchMoreObjects} will not block the processing of the 100 currently * available POJOs (but {@code i.hasNext()} will block once those POJOs have * been processed until the fetch query returns, if it hasn't yet). *

* Only one page of POJOs (for a given object set) can be fetched at any * given time. If this method is called twice and the query triggered by the * first call has not returned yet when the second one is performed, then the * 2nd call will simply return a future on the currently in progress query. * * @author paouelle * * @return a future on the completion of fetching the next page of POJOs. If * the object set is already fully retrieved ( * {@code isFullyFetched() == true}), then the returned future will * return immediately but not particular error will be thrown (you * should thus call {@code isFullyFetched() to know if calling this * method can be of any use}). */ public ListenableFuture fetchMoreObjects() { return result.fetchMoreResults(); } /** * Gets information on the execution of the last query made for this object * set. *

* Note that in most cases, an object set is fetched with only one query, but * large object sets can be paged and thus be retrieved by multiple queries. * If that is the case, that method return that {@code ExecutionInfo} for the * last query performed. To retrieve the informations for all queries, use * {@link #getAllExecutionInfo}. *

* The returned object includes basic information such as the queried hosts, * but also the Cassandra query trace if tracing was enabled for the query. * * @author paouelle * * @return the execution info for the last query made for this object set */ public ExecutionInfo getExecutionInfo() { return result.getExecutionInfo(); } /** * Gets the execution informations for all queries made to retrieve this * object set. *

* Unless the object set is large enough to get paged underneath, the returned * list will be a singleton. If paging has been used however, the returned list * contains the {@code ExecutionInfo} for all the queries done to obtain this * object set (at the time of the call) in the order those queries were made. * * @author paouelle * * @return a list of the execution info for all the queries made for this * object set */ public List getAllExecutionInfo() { return result.getAllExecutionInfo(); } /** * {@inheritDoc} * * @author paouelle * * @see java.lang.Object#toString() */ @Override public String toString() { return result.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy