001package io.ebean.enhance.querybean;
002
003import java.util.HashSet;
004import java.util.Set;
005
006/**
007 * Detects if a class is a query bean.
008 * <p>
009 * Used by enhancement to detect when GETFIELD access on query beans should be replaced by
010 * appropriate method calls.
011 * </p>
012 */
013public class DetectQueryBean {
014
015  private final Set<String> entityPackages = new HashSet<>();
016
017  public DetectQueryBean() {
018  }
019
020  public void addAll(Set<String> rawEntityPackages) {
021    for (String rawEntityPackage : rawEntityPackages) {
022      entityPackages.add(convert(rawEntityPackage));
023    }
024  }
025
026  /**
027   * Convert package to slash notation taking into account trailing wildcard.
028   */
029  private static String convert(String pkg) {
030    pkg = pkg.trim();
031    if (pkg.endsWith("*")) {
032      pkg = pkg.substring(0, pkg.length() - 1);
033    }
034    if (pkg.endsWith(".query")) {
035      // always work with entity bean packages so trim
036      pkg = pkg.substring(0, pkg.length() - 6);
037    }
038    pkg = pkg.replace('.', '/');
039    return pkg.endsWith("/") ? pkg : pkg + "/";
040  }
041
042
043  @Override
044  public String toString() {
045    return entityPackages.toString();
046  }
047
048  /**
049   * Return true if there are no known packages.
050   */
051  public boolean isEmpty() {
052    return entityPackages.isEmpty();
053  }
054
055  /**
056   * Return true if this class is a query bean using naming conventions for query beans.
057   */
058  public boolean isQueryBean(String owner) {
059    int subPackagePos = owner.lastIndexOf("/query/");
060    if (subPackagePos > -1) {
061      String suffix = owner.substring(subPackagePos);
062      if (isQueryBeanSuffix(suffix)) {
063        String domainPackage = owner.substring(0, subPackagePos + 1);
064        return isEntityBeanPackage(domainPackage);
065      }
066    }
067    return false;
068  }
069
070  private boolean isEntityBeanPackage(String domainPackage) {
071    for (String pkg : entityPackages) {
072      if (domainPackage.startsWith(pkg)) {
073        return true;
074      }
075    }
076    return false;
077  }
078
079  public boolean isEntityBean(String owner) {
080    return isEntityBeanPackage(owner);
081  }
082
083  /**
084   * Check that the class follows query bean naming convention.
085   */
086  private boolean isQueryBeanSuffix(String suffix) {
087    return (suffix.startsWith("/query/Q") || suffix.startsWith("/query/assoc/Q"));
088  }
089}