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

io.ebeaninternal.api.NaturalKeyQueryData Maven / Gradle / Ivy

There is a newer version: 15.6.0
Show newest version
package io.ebeaninternal.api;

import io.ebean.Pairs;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Collects the data for processing the natural key cache processing.
 */
public class NaturalKeyQueryData {

  private final String[] naturalKey;

  /**
   * Only one of IN or IN PAIRS is allowed.
   */
  private boolean hasIn;

  // IN Pairs clause - only one allowed
  private String inProperty0, inProperty1;
  private List inPairs;

  // IN clause - only one allowed
  private Collection inValues;
  private String inProperty;

  // normal EQ expressions
  private List eqList;

  private NaturalKeySet set;

  private int hitCount;

  public NaturalKeyQueryData(String[] naturalKey) {
    this.naturalKey = naturalKey;
  }

  private boolean matchProperty(String propName) {

    for (String key : naturalKey) {
      if (key.equals(propName)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Match for In Pairs expression. We only allow one IN clause.
   */
  public boolean matchInPairs(Pairs pairs) {
    if (hasIn) {
      // only 1 IN allowed (to project naturalIds)
      return false;
    }
    if (matchProperty(pairs.getProperty0()) && matchProperty(pairs.getProperty1())) {
      this.hasIn = true;
      this.inProperty0 = pairs.getProperty0();
      this.inProperty1 = pairs.getProperty1();
      this.inPairs = pairs.getEntries();
      return true;
    }
    return false;
  }

  /**
   * Match for IN expression. We only allow one IN clause.
   */
  public boolean matchIn(String propName, Collection sourceValues) {
    if (hasIn) {
      // only 1 IN allowed (to project naturalIds)
      return false;
    }
    if (matchProperty(propName)) {
      this.hasIn = true;
      this.inProperty = propName;
      this.inValues = sourceValues;
      return true;
    }
    return false;
  }

  /**
   * Match for an EQ expression.
   */
  public boolean matchEq(String propName, Object bindValue) {
    if (matchProperty(propName)) {
      if (eqList == null) {
        eqList = new ArrayList<>();
      }
      eqList.add(new NaturalKeyEq(propName, bindValue));
      return true;
    }
    return false;
  }

  /**
   * Build and return the set of natural keys we will use.
   */
  public NaturalKeySet buildKeys() {

    if (!expressionCount() || !matchProperties()) {
      return null;
    }

    this.set = new NaturalKeySet();
    if (inValues != null) {
      // a findList() with an IN clause so we project
      // for every IN value a natural key combination
      for (Object inValue : inValues) {
        set.add(new NaturalKeyEntry(naturalKey, eqList, inProperty, inValue));
      }
    } else if (inPairs != null) {
      // a findList() with an IN Map clause so we project
      // for every IN value a natural key combination
      for (Pairs.Entry entry : inPairs) {
        set.add(new NaturalKeyEntry(naturalKey, eqList, inProperty0, inProperty1, entry));
      }

    } else {
      // only one - a findOne()
      set.add(new NaturalKeyEntry(naturalKey, eqList));
    }

    return set;
  }

  /**
   * Return true if the properties match the natural key properties.
   */
  private boolean matchProperties() {
    if (naturalKey.length == 1) {
      // simple single property case
      if (inProperty != null) {
        return inProperty.equals(naturalKey[0]);
      } else {
        return eqList.get(0).property.equals(naturalKey[0]);
      }
    }

    // multiple properties case
    Set exprProps = new HashSet<>();
    if (inProperty != null) {
      exprProps.add(inProperty);
    }
    if (inProperty0 != null) {
      exprProps.add(inProperty0);
    }
    if (inProperty1 != null) {
      exprProps.add(inProperty1);
    }
    if (eqList != null) {
      for (NaturalKeyEq eq : eqList) {
        exprProps.add(eq.property);
      }
    }
    if (exprProps.size() != naturalKey.length) {
      return false;
    }
    for (String key : naturalKey) {
      if (!exprProps.remove(key)) {
        return false;
      }
    }

    return exprProps.isEmpty();
  }

  /**
   * Check that all the natural key properties are defined.
   */
  private boolean expressionCount() {

    int defined = (inValues == null) ? 0 : 1;
    defined += (inPairs == null) ? 0 : 2;
    defined += (eqList == null) ? 0 : eqList.size();
    return defined == naturalKey.length;
  }

  /**
   * Return the number of entries in the IN clause left remaining (to hit the DB with).
   */
  public boolean allHits() {
    return hitCount > 0
      && hitCount == set.size()
      && (inValues == null || inValues.isEmpty());
  }

  /**
   * Adjust the IN clause removing the hit entry.
   */
  public List removeHits(BeanCacheResult cacheResult) {

    List> hits = cacheResult.hits();
    this.hitCount = hits.size();

    List beans = new ArrayList<>(hitCount);

    for (BeanCacheResult.Entry hit : hits) {
      if (inValues != null) {
        Object naturalKey = hit.getKey();
        Object inValue = set.getInValue(naturalKey);
        inValues.remove(inValue);

      } else if (inPairs != null) {
        Object naturalKey = hit.getKey();
        Pairs.Entry inValue = (Pairs.Entry)set.getInValue(naturalKey);
        inPairs.remove(inValue);
      }
      beans.add(hit.getBean());
    }

    return beans;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy