<commit_before>/**
 * This file is part of the Android DependencyManager project hosted at
 * http://code.google.com/p/android-dependencymanager/
 *
 * Copyright (C) 2009 <NAME> <<EMAIL>>
 *
 * 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 de.finkhaeuser.dm;

import android.database.Cursor;
import android.database.AbstractCursor;
import android.database.CursorWindow;
import android.database.CursorIndexOutOfBoundsException;

import java.util.ArrayList;

import android.util.Log;

/**
 * Merges the results of other cursors into it's own data set.
 *
 * Similar in some ways to MergeCursor. The difference is that the Cursors from
 * which data is taken need not exist before AggregateCursor is created. Data
 * is merged into AggregateCursor, and AggregateCursor's result list stays
 * sorted.
 *
 * (see http://developer.android.com/reference/android/database/MergeCursor.html)
 *
 * This code is based on the MatrixCursor implementation.
 **/
class AggregateCursor extends AbstractCursor
{
  /***************************************************************************
   * Private constants
   **/
  private static final String LTAG = "AggregateCursor";



  /***************************************************************************
   * Private data
   **/
  private final String[] columnNames;
  private Object[] data;
  private int rowCount = 0;
  private final int columnCount;
  private RowComparator comparator;
  private boolean unique = false;


  /***************************************************************************
   * Inner classes
   **/

  /**
   * Abstract base for comparator objects.
   **/
  public static abstract class RowComparator
  {
    /**
     * Given the current row for c1 and c2, return
     * < 0 if c1 is to be sorted before c2
     * = 0 if c1 and c2 can be considered equal
     * > 0 if c1 is to be sorted after c2
     **/
    public abstract int compareCurrentRows(Cursor c1, Cursor c2);
  }



  /***************************************************************************
   * Implementation
   **/

  /**
   * Constructs a new cursor with the given initial capacity.
   *
   * @param columnNames names of the columns, the ordering of which
   *  determines column ordering elsewhere in this cursor
   * @param comparator RowComparator-derived instance used to determine where
   *  to sort newly merged rows.
   * @param uniqe if set, duplicate rows are merged
   * @param initialCapacity in rows
   */
  public AggregateCursor(String[] columnNames, RowComparator comparator,
      boolean unique, int initialCapacity)
  {
    this.columnNames = columnNames;
    this.columnCount = columnNames.length;
    this.comparator = comparator;
    this.unique = unique;

    if (initialCapacity < 1) {
      initialCapacity = 1;
    }

    this.data = new Object[columnCount * initialCapacity];
  }



  /**
   * Constructs a new cursor.
   *
   * @param columnNames names of the columns, the ordering of which
   *  determines column ordering elsewhere in this cursor
   * @param comparator RowComparator-derived instance used to determine where
   *  to sort newly merged rows.
   * @param uniqe if set, duplicate rows are merged
   */
  public AggregateCursor(String[] columnNames, RowComparator comparator,
      boolean unique)
  {
    this(columnNames, comparator, unique, 16);
  }



  /**
   * Constructs a new non-unique cursor.
   *
   * @param columnNames names of the columns, the ordering of which
   *  determines column ordering elsewhere in this cursor
   * @param comparator RowComparator-derived instance used to determine where
   *  to sort newly merged rows.
   */
  public AggregateCursor(String[] columnNames, RowComparator comparator)
  {
    this(columnNames, comparator, false, 16);
  }



  /**
   * Merges data from the given cursor into this cursor. Not safe for concurrent
   * use. IllegalArgumentException if columNames and columnCount do not match.
   **/
  public void merge(Cursor other)
  {
    if (null == other || 0 >= other.getCount()) {
      return;
    }

    if (columnCount != other.getColumnCount()) {
      throw new IllegalArgumentException("Cannot update AggregateCursor "
          + "from a cursor with different column count.");
    }
    for (int i = 0 ; i < columnCount ; ++i) {
      String otherName = other.getColumnName(i);
      if (!columnNames[i].equals(otherName)) {
        throw new IllegalArgumentException("Invalid cursor to update from; "
            + "expected column '" + columnNames[i] + "' but got column '"
            + otherName + "'!");
      }
    }

    // Expand capacity to fit the other cursor's data as well.
    int newCapacity = rowCount + other.getCount();
    ensureCapacity(newCapacity * columnCount);

    // Store current position, so we can restore the cursor position at the end
    // of this function.
    int current = getPosition();

    // Append other's rows.
    other.moveToFirst();
    for ( ; !other.isAfterLast() ; other.moveToNext()) {
      int idx = insertIndex(other, 0, rowCount);
      if (-1 == idx) {
        // Only happens when unique is set. The current row is a duplicate we<commit_msg>Fix AggregateCursor's merge: we don't want to require the same *order* of columns in Cursors to be merged, just that the columns exist.<commit_after>/**
 * This file is part of the Android DependencyManager project hosted at
 * http://code.google.com/p/android-dependencymanager/
 *
 * Copyright (C) 2009 <NAME> <<EMAIL>>
 *
 * 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 de.finkhaeuser.dm;

import android.database.Cursor;
import android.database.AbstractCursor;
import android.database.CursorWindow;
import android.database.CursorIndexOutOfBoundsException;

import java.util.ArrayList;

import android.util.Log;

/**
 * Merges the results of other cursors into it's own data set.
 *
 * Similar in some ways to MergeCursor. The difference is that the Cursors from
 * which data is taken need not exist before AggregateCursor is created. Data
 * is merged into AggregateCursor, and AggregateCursor's result list stays
 * sorted.
 *
 * (see http://developer.android.com/reference/android/database/MergeCursor.html)
 *
 * This code is based on the MatrixCursor implementation.
 **/
class AggregateCursor extends AbstractCursor
{
  /***************************************************************************
   * Private constants
   **/
  private static final String LTAG = "AggregateCursor";



  /***************************************************************************
   * Private data
   **/
  private final String[] columnNames;
  private Object[] data;
  private int rowCount = 0;
  private final int columnCount;
  private RowComparator comparator;
  private boolean unique = false;


  /***************************************************************************
   * Inner classes
   **/

  /**
   * Abstract base for comparator objects.
   **/
  public static abstract class RowComparator
  {
    /**
     * Given the current row for c1 and c2, return
     * < 0 if c1 is to be sorted before c2
     * = 0 if c1 and c2 can be considered equal
     * > 0 if c1 is to be sorted after c2
     **/
    public abstract int compareCurrentRows(Cursor c1, Cursor c2);
  }



  /***************************************************************************
   * Implementation
   **/

  /**
   * Constructs a new cursor with the given initial capacity.
   *
   * @param columnNames names of the columns, the ordering of which
   *  determines column ordering elsewhere in this cursor
   * @param comparator RowComparator-derived instance used to determine where
   *  to sort newly merged rows.
   * @param uniqe if set, duplicate rows are merged
   * @param initialCapacity in rows
   */
  public AggregateCursor(String[] columnNames, RowComparator comparator,
      boolean unique, int initialCapacity)
  {
    this.columnNames = columnNames;
    this.columnCount = columnNames.length;
    this.comparator = comparator;
    this.unique = unique;

    if (initialCapacity < 1) {
      initialCapacity = 1;
    }

    this.data = new Object[columnCount * initialCapacity];
  }



  /**
   * Constructs a new cursor.
   *
   * @param columnNames names of the columns, the ordering of which
   *  determines column ordering elsewhere in this cursor
   * @param comparator RowComparator-derived instance used to determine where
   *  to sort newly merged rows.
   * @param uniqe if set, duplicate rows are merged
   */
  public AggregateCursor(String[] columnNames, RowComparator comparator,
      boolean unique)
  {
    this(columnNames, comparator, unique, 16);
  }



  /**
   * Constructs a new non-unique cursor.
   *
   * @param columnNames names of the columns, the ordering of which
   *  determines column ordering elsewhere in this cursor
   * @param comparator RowComparator-derived instance used to determine where
   *  to sort newly merged rows.
   */
  public AggregateCursor(String[] columnNames, RowComparator comparator)
  {
    this(columnNames, comparator, false, 16);
  }



  /**
   * Merges data from the given cursor into this cursor. Not safe for concurrent
   * use. IllegalArgumentException if columNames and columnCount do not match.
   **/
  public void merge(Cursor other)
  {
    if (null == other || 0 >= other.getCount()) {
      return;
    }

    if (columnCount != other.getColumnCount()) {
      throw new IllegalArgumentException("Cannot update AggregateCursor "
          + "from a cursor with different column count.");
    }
    for (int i = 0 ; i < columnCount ; ++i) {
      int otherIndex = other.getColumnIndex(columnNames[i]);
      if (-1 == otherIndex) {
        throw new IllegalArgumentException("Invalid cursor to update from; "
            + "expected column '" + columnNames[i] + "' not found!");
      }
    }

    // Expand capacity to fit the other cursor's data as well.
    int newCapacity = rowCount + other.getCount();
    ensureCapacity(newCapacity * columnCount);

    // Store current position, so we can restore the cursor position at the end
    // of this function.
    int current = getPosition();

    // Append other's rows.
    other.moveToFirst();
    for ( ; !other.isAfterLast() ; other.moveToNext()) {
      int idx = insertIndex(other, 0, rowCount);
      if (-1 == idx) {
        // Only happens when unique is set. The current row is a duplicate we
{'fraction_non_alphanumeric': 0.13384723195515066, 'fraction_numerical': 0.005693763139453399, 'mean_word_length': 3.331183611532625, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5934333', 'n_tokens_mistral': 3065, 'n_tokens_neox': 2924, 'n_words': 1156}