Package org.kiji.schema.impl

Source Code of org.kiji.schema.impl.MaterializedKijiResult

/**
* (c) Copyright 2014 WibiData, Inc.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* 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 org.kiji.schema.impl;

import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import org.kiji.annotations.ApiAudience;
import org.kiji.schema.EntityId;
import org.kiji.schema.KijiCell;
import org.kiji.schema.KijiColumnName;
import org.kiji.schema.KijiDataRequest;
import org.kiji.schema.KijiDataRequest.Column;
import org.kiji.schema.KijiResult;
import org.kiji.schema.layout.KijiTableLayout;

/**
* A {@link KijiResult} backed by a map of {@code KijiColumnName} to
* {@code List<KijiCell<T>>}.
*
* @param <T> The type of {@code KijiCell} values in the view.
*/
@ApiAudience.Private
public final class MaterializedKijiResult<T> implements KijiResult<T> {
  private final EntityId mEntityId;
  private final KijiDataRequest mDataRequest;
  private final SortedMap<KijiColumnName, List<KijiCell<T>>> mColumns;

  /**
   * Create a {@code MaterializedKijiResult}.
   *
   * @param entityId The entity ID of the row containing this result.
   * @param dataRequest The Kiji data request which defines the columns in this result.
   * @param columns The materialized results.
   */
  private MaterializedKijiResult(
      final EntityId entityId,
      final KijiDataRequest dataRequest,
      final SortedMap<KijiColumnName, List<KijiCell<T>>> columns
  ) {
    mEntityId = entityId;
    mDataRequest = dataRequest;
    mColumns = columns;
  }

  /**
   * Create a new materialized {@code KijiResult} backed by the provided {@code KijiCell}s.
   *
   * @param entityId The entity ID of the row containing this result.
   * @param dataRequest The Kiji data request which defines the columns in this result.
   * @param layout The Kiji table layout of the table.
   * @param columns The materialized results. The cells must be in the order guaranteed by
   *     {@code KijiResult}. Must be mutable, and should not be modified after passing in.
   * @param <T> The type of {@code KijiCell} values in the view.
   * @return A new materialized {@code KijiResult} backed by {@code KijiCell}s.
   */
  public static <T> MaterializedKijiResult<T> create(
      final EntityId entityId,
      final KijiDataRequest dataRequest,
      final KijiTableLayout layout,
      final SortedMap<KijiColumnName, List<KijiCell<T>>> columns
  ) {
    // We have to sort the results from group-type column families because the KijiResult API does
    // not specify the order of columns in a group-type family.  We rely on the columns being
    // ordered so that we can use binary search.

    final List<Map.Entry<KijiColumnName, List<KijiCell<T>>>> groupFamilyEntries =
        Lists.newArrayListWithCapacity(columns.size());
    for (Map.Entry<KijiColumnName, List<KijiCell<T>>> entry : columns.entrySet()) {
      final KijiColumnName column = entry.getKey();
      if (!column.isFullyQualified()
          && layout.getFamilyMap().get(column.getFamily()).isGroupType()) {
        groupFamilyEntries.add(entry);
      }
    }

    if (groupFamilyEntries.isEmpty()) {
      return new MaterializedKijiResult<T>(entityId, dataRequest, columns);
    }

    for (Map.Entry<KijiColumnName, List<KijiCell<T>>> entry : groupFamilyEntries) {
      final KijiColumnName groupFamily = entry.getKey();
      final List<KijiCell<T>> sortedColumn = entry.getValue();
      Collections.sort(sortedColumn, KijiCell.getKeyComparator());
      columns.put(groupFamily, sortedColumn);
    }

    return new MaterializedKijiResult<T>(entityId, dataRequest, columns);
  }

  /** {@inheritDoc} */
  @Override
  public EntityId getEntityId() {
    return mEntityId;
  }

  /** {@inheritDoc} */
  @Override
  public KijiDataRequest getDataRequest() {
    return mDataRequest;
  }

  /** {@inheritDoc} */
  @Override
  public Iterator<KijiCell<T>> iterator() {
    return Iterables.concat(mColumns.values()).iterator();
  }

  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  @Override
  public <U extends T> KijiResult<U> narrowView(final KijiColumnName column) {
    final KijiDataRequest narrowRequest = DefaultKijiResult.narrowRequest(column, mDataRequest);
    if (narrowRequest.equals(mDataRequest)) {
      return (KijiResult<U>) this;
    }

    final ImmutableSortedMap.Builder<KijiColumnName, List<KijiCell<U>>> narrowedColumns =
        ImmutableSortedMap.naturalOrder();

    for (Column columnRequest : narrowRequest.getColumns()) {
      final KijiColumnName requestedColumn = columnRequest.getColumnName();

      // (Object) cast is necessary. Might be: http://bugs.java.com/view_bug.do?bug_id=6548436
      final List<KijiCell<U>> exactColumn =
          (List<KijiCell<U>>) (Object) mColumns.get(requestedColumn);
      if (exactColumn != null) {

        // We get here IF

        // `column` is a family, and `mDataRequest` contains a column request for the entire family.

        // OR

        // `column` is a family, and `mDataRequest` contains a column request for a qualified column
        // in the family.

        // OR

        // `column` is a qualified-column, and `mDataRequest` contains a request for the qualified
        // column.

        narrowedColumns.put(requestedColumn, exactColumn);
      } else {

        // `column` is a qualified-column, and `mDataRequest` contains a column request for the
        // column's family.

        final List<KijiCell<T>> familyCells =
            mColumns.get(KijiColumnName.create(requestedColumn.getFamily(), null));
        final List<KijiCell<T>> qualifierCells = getQualifierCells(requestedColumn, familyCells);
        narrowedColumns.put(requestedColumn, (List<KijiCell<U>>) (Object) qualifierCells);
      }
    }

    return new MaterializedKijiResult<U>(
        mEntityId,
        narrowRequest,
        narrowedColumns.build());
  }

  /** {@inheritDoc} */
  @Override
  public void close() throws IOException {
    // No-op
  }

  /**
   * Get the {@code KijiCell}s in a list of cells from a family which belong to the specified
   * fully-qualified column.
   *
   * @param column The fully-qualified column to retrieve cells for.
   * @param familyCells The sorted list of cells belonging to a Kiji family.
   * @return The {@code Cell}s for the qualified column.
   * @param <T> The type of {@code KijiCell}s in the family.
   */
  private static <T> List<KijiCell<T>> getQualifierCells(
      final KijiColumnName column,
      final List<KijiCell<T>> familyCells
  ) {
    if (familyCells.size() == 0) {
      return ImmutableList.of();
    }

    final KijiCell<T> start = KijiCell.create(column, Long.MAX_VALUE, null);
    final KijiCell<T> end = KijiCell.create(column, -1L, null);

    int startIndex =
        Collections.binarySearch(familyCells, start, KijiCell.getKeyComparator());
    if (startIndex < 0) {
      startIndex = -1 - startIndex;
    }

    int endIndex =
        Collections.binarySearch(familyCells, end, KijiCell.getKeyComparator());
    if (endIndex < 0) {
      endIndex = -1 - endIndex;
    }

    return familyCells.subList(startIndex, endIndex);
  }
}
TOP

Related Classes of org.kiji.schema.impl.MaterializedKijiResult

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.