package com.getbase.android.db.cursors;

import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;

import android.database.Cursor;
import android.database.CursorWrapper;

import java.util.NoSuchElementException;

public class FluentCursor extends CursorWrapper {

  public FluentCursor(Cursor cursor) {
    super(Cursors.returnSameOrEmptyIfNull(cursor));
  }

  /**
   * Transforms Cursor to FluentIterable of T applying given function
   * WARNING: This method closes cursor. Do not use this from onLoadFinished()
   *
   * @param singleRowTransform Function to apply on every single row of this cursor
   * @param <T> Type of Iterable's single element
   * @return Transformed iterable
   */
  public <T> FluentIterable<T> toFluentIterable(Function<? super Cursor, T> singleRowTransform) {
    try {
      return Cursors.toFluentIterable(this, singleRowTransform);
    } finally {
      close();
    }
  }

  /**
   * Returns the only row of this cursor transformed using the given function.
   * WARNING: This method closes cursor. Do not use this from onLoadFinished()
   *
   * @param singleRowTransform Function to apply on the only row of this cursor
   * @param <T> Type of returned element
   * @return Transformed first row of the cursor. If the cursor is empty,
   * NoSuchElementException is thrown. If the cursor contains more than one
   * row, IllegalArgumentException is thrown.
   */
  public <T> T toOnlyElement(Function<? super Cursor, T> singleRowTransform) {
    try {
      switch (getCount()) {
      case 0:
        throw new NoSuchElementException();
      case 1:
        moveToFirst();
        return singleRowTransform.apply(this);
      default:
        throw new IllegalArgumentException("expected one element but was: " + getCount());
      }
    } finally {
      close();
    }
  }

  /**
   * Returns the only row of this cursor transformed using the given function,
   * or the supplied default value if cursor is empty.
   * WARNING: This method closes cursor. Do not use this from onLoadFinished()
   *
   * @param singleRowTransform Function to apply on the only row of this cursor
   * @param <T> Type of returned element
   * @return Transformed first row of the cursor or the supplied default
   * value if the cursor is empty. If the cursor contains more than one
   * row, IllegalArgumentException is thrown.
   */
  public <T> T toOnlyElement(Function<? super Cursor, T> singleRowTransform, T defaultValue) {
    if (moveToFirst()) {
      return toOnlyElement(singleRowTransform);
    } else {
      close();
      return defaultValue;
    }
  }

  /**
   * Returns number of rows in this cursor and closes it.
   * WARNING: This method closes cursor. Do not use this from onLoadFinished()
   *
   * @return Row count from this cursor
   */
  public int toRowCount() {
    try {
      return getCount();
    } finally {
      close();
    }
  }
}

@@ -122,16 +122,69 @@
 terable;
+%0Aimport com.google.common.collect.LinkedHashMultimap;
 %0A%0Aimport
@@ -979,32 +979,1201 @@
 e();%0A    %7D%0A  %7D%0A%0A
+  /**%0A   * Transforms Cursor to LinkedHashMap%3CTKey, TValue%3E by applying given%0A   * functions. The iteration order for the returned map is the same as%0A   * the iteration order over rows of Cursor.%0A   * WARNING: This method closes cursor. Do not use this from onLoadFinished()%0A   *%0A   * @param keyTransform Function to apply on every single row of this cursor%0A   * to get the key of the entry representing this row.%0A   * @param valueTransform Function to apply on every single row of this cursor%0A   * to get the value of the entry representing this row.%0A   * @param %3CTKey%3E Type of keys in the returned multimap%0A   * @param %3CTValue%3E Type of values in the returned multimap%0A   * @return Transformed map%0A   */%0A  public %3CTKey, TValue%3E LinkedHashMultimap%3CTKey, TValue%3E toMap(Function%3C? super Cursor, TKey%3E keyTransform, Function%3C? super Cursor, TValue%3E valueTransform) %7B%0A    try %7B%0A      LinkedHashMultimap%3CTKey, TValue%3E result = LinkedHashMultimap.create(getCount(), 1);%0A%0A      for (moveToFirst(); !isAfterLast(); moveToNext()) %7B%0A        result.put(keyTransform.apply(this), valueTransform.apply(this));%0A      %7D%0A%0A      return result;%0A    %7D finally %7B%0A      close();%0A    %7D%0A  %7D%0A%0A
   /**%0A   * Retur

Add FluentCursor.toMap() method