Package mil.nga.giat.geowave.store.data

Source Code of mil.nga.giat.geowave.store.data.PersistenceEncoding$DimensionRangePair

package mil.nga.giat.geowave.store.data;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;

import mil.nga.giat.geowave.index.ByteArrayId;
import mil.nga.giat.geowave.index.sfc.data.BasicNumericDataset;
import mil.nga.giat.geowave.index.sfc.data.MultiDimensionalNumericData;
import mil.nga.giat.geowave.index.sfc.data.NumericData;
import mil.nga.giat.geowave.index.sfc.data.NumericRange;
import mil.nga.giat.geowave.store.dimension.DimensionField;
import mil.nga.giat.geowave.store.index.CommonIndexValue;
import mil.nga.giat.geowave.store.index.Index;

/**
* This class models all of the necessary information for persisting data in
* Accumulo (following the common index model) and is used internally within
* GeoWave as an intermediary object between the direct storage format and the
* native data format. It is the responsibility of the data adapter to convert
* to and from this object and the native object. It does not contain any
* information about the entry in a particular index and is used when writing an
* entry, prior to its existence in an index.
*/
public class PersistenceEncoding
{
  private final ByteArrayId adapterId;
  private final ByteArrayId dataId;
  private final PersistentDataset<? extends CommonIndexValue> commonData;
  private final static Logger LOGGER = Logger.getLogger(PersistenceEncoding.class);

  public PersistenceEncoding(
      final ByteArrayId adapterId,
      final ByteArrayId dataId,
      final PersistentDataset<? extends CommonIndexValue> commonData ) {
    this.adapterId = adapterId;
    this.dataId = dataId;
    this.commonData = commonData;
  }

  /**
   * Return the common index data that has been persisted
   *
   * @return the common index data
   */
  public PersistentDataset<? extends CommonIndexValue> getCommonData() {
    return commonData;
  }

  /**
   * Return the data adapter ID
   *
   * @return the adapter ID
   */
  public ByteArrayId getAdapterId() {
    return adapterId;
  }

  /**
   * Return the data ID, data ID's should be unique per adapter
   *
   * @return the data ID
   */
  public ByteArrayId getDataId() {
    return dataId;
  }

  /**
   * Given an ordered set of dimensions, convert this persistent encoding
   * common index data into a MultiDimensionalNumericData object that can then
   * be used by the Index
   *
   * @param dimensions
   * @return
   */
  @SuppressWarnings({
    "rawtypes",
    "unchecked"
  })
  public MultiDimensionalNumericData getNumericData(
      final DimensionField[] dimensions ) {
    final NumericData[] dataPerDimension = new NumericData[dimensions.length];
    for (int d = 0; d < dimensions.length; d++) {
      dataPerDimension[d] = dimensions[d].getNumericData(commonData.getValue(dimensions[d].getFieldId()));
    }
    return new BasicNumericDataset(
        dataPerDimension);
  }

  private class DimensionRangePair
  {
    DimensionField[] dimensions;
    NumericData[] dataPerDimension;

    DimensionRangePair(
        DimensionField field,
        NumericData data ) {
      dimensions = new DimensionField[] {
        field
      };
      dataPerDimension = new NumericData[] {
        data
      };
    }

    void add(
        DimensionField field,
        NumericData data ) {
      dimensions = ArrayUtils.add(
          dimensions,
          field);
      dataPerDimension = ArrayUtils.add(
          dataPerDimension,
          data);
    }
  }

 
  // Subclasses may want to override this behavior if the belief that the index strategy is optimal
  // to avoid the extra cost of checking the result
  protected boolean overlaps(
      final NumericData[] insertTileRange,
      final Index index ) {
    @SuppressWarnings("rawtypes")
    final DimensionField[] dimensions = index.getIndexModel().getDimensions();

    // Recall that each numeric data instance is extracted by a {@link
    // DimensionField}. More than one DimensionField
    // is associated with a {@link CommonIndexValue} entry (e.g. Lat/Long,
    // start/end). These DimensionField's share the
    // fieldId.
    // The infrastructure does not guarantee that CommonIndexValue can be
    // reconstructed fully from the NumericData.
    // However, provided in the correct order for interpretation, the
    // CommonIndexValue can use those numeric data items
    // to judge an overlap of range data.
    Map<ByteArrayId, DimensionRangePair> fieldsRangeData = new HashMap<ByteArrayId, DimensionRangePair>(
        dimensions.length);

    for (int d = 0; d < dimensions.length; d++) {
      final ByteArrayId fieldId = dimensions[d].getFieldId();
      DimensionRangePair fieldData = fieldsRangeData.get(fieldId);
      if (fieldData == null) {
        fieldsRangeData.put(
            fieldId,
            new DimensionRangePair(
                dimensions[d],
                insertTileRange[d]));
      }
      else {
        fieldData.add(
            dimensions[d],
            insertTileRange[d]);
      }
    }

    boolean ok = true;
    for (Entry<ByteArrayId, DimensionRangePair> entry : fieldsRangeData.entrySet()) {
      ok &= commonData.getValue(
          entry.getKey()).overlaps(
          entry.getValue().dimensions,
          entry.getValue().dataPerDimension);
    }
    return ok;
  }

  /**
   * Given an index, convert this persistent encoding to a set of insertion
   * IDs for that index
   *
   * @param index
   *            the index
   * @return The insertions IDs for this object in the index
   */
  public List<ByteArrayId> getInsertionIds(
      final Index index ) {
    MultiDimensionalNumericData boxRangeData = getNumericData(index.getIndexModel().getDimensions());
    List<ByteArrayId> untrimmedResult = index.getIndexStrategy().getInsertionIds(
        boxRangeData);
    final int size = untrimmedResult.size();
    if (size > 2) {
      Iterator<ByteArrayId> it = untrimmedResult.iterator();
      while (it.hasNext()) {
        ByteArrayId insertionId = it.next();
        MultiDimensionalNumericData md = correctForNormalizationError(index.getIndexStrategy().getRangeForId(
            insertionId));
        // used to check the result of the index strategy
        if (LOGGER.isDebugEnabled() && checkCoverage(
            boxRangeData,
            md)) {
          LOGGER.error("Index strategy produced an unmatching tile during encoding and storing an entry");
        }
        if (!overlaps(
            md.getDataPerDimension(),
            index)) it.remove();
      }
    }
    return untrimmedResult;
  }

  private MultiDimensionalNumericData correctForNormalizationError(
      MultiDimensionalNumericData boxRangeData ) {
    final NumericData[] currentDataSet = boxRangeData.getDataPerDimension();
    final NumericData[] dataPerDimension = new NumericData[currentDataSet.length];
    for (int d = 0; d < currentDataSet.length; d++) {
      dataPerDimension[d] = new NumericRange(
          currentDataSet[d].getMin() - 1E-12d,
          currentDataSet[d].getMax() + 1E-12d);
    }
    return new BasicNumericDataset(
        dataPerDimension);
  }

  /**
   * Tool can be used custom index strategies to check if the tiles actual
   * intersect with the provided bounding box.
   *
   * @param boxRangeData
   * @param innerTile
   * @return
   */
  private boolean checkCoverage(
      MultiDimensionalNumericData boxRangeData,
      MultiDimensionalNumericData innerTile ) {
    for (int i = 0; i < boxRangeData.getDimensionCount(); i++) {
      double t0 = innerTile.getDataPerDimension()[i].getMax() - boxRangeData.getDataPerDimension()[i].getMin();
      double t1 = boxRangeData.getDataPerDimension()[i].getMax() - innerTile.getDataPerDimension()[i].getMin();
      if (Math.abs(t0 - t1) > (t0 + t1)) {
        return false;
      }
    }
    return true;
  }
}
TOP

Related Classes of mil.nga.giat.geowave.store.data.PersistenceEncoding$DimensionRangePair

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.