001package io.ebean.enhance.common;
002
003import java.util.HashSet;
004import java.util.List;
005import java.util.Set;
006import java.util.StringJoiner;
007import java.util.TreeSet;
008
009/**
010 * Summary of the enhancement.
011 */
012public class SummaryInfo {
013
014  private final List<String> loadedResources;
015  private final Set<String> entities = new HashSet<>();
016  private final Set<String> queryBeans = new HashSet<>();
017  private final Set<String> queryBeanCallers = new HashSet<>();
018  private final Set<String> fieldAccessUsers = new HashSet<>();
019  private final Set<String> transactional = new HashSet<>();
020
021  SummaryInfo(List<String> loadedResources) {
022    this.loadedResources = loadedResources;
023  }
024
025  /**
026   * Remove from queryBeanCallers the queryBeans (due to profile location enhancement).
027   */
028  SummaryInfo prepare() {
029    for (String queryBean : queryBeans) {
030      queryBeanCallers.remove(queryBean);
031      queryBeanCallers.remove(queryBean + "$Companion");
032    }
033    return this;
034  }
035
036  /**
037   * Return true if there was nothing enhanced.
038   */
039  public boolean isEmpty() {
040    return entities.isEmpty() && queryBeans.isEmpty() && queryBeanCallers.isEmpty() && transactional.isEmpty();
041  }
042
043  public boolean hasEntities() {
044    return !entities.isEmpty();
045  }
046
047  public boolean hasQueryBeans() {
048    return !queryBeans.isEmpty();
049  }
050
051  public boolean hasTransactional() {
052    return !transactional.isEmpty();
053  }
054
055  public boolean hasQueryCallers() {
056    return !queryBeanCallers.isEmpty();
057  }
058
059  public boolean hasFieldAccess() {
060    return !fieldAccessUsers.isEmpty();
061  }
062
063  public String toString() {
064    return " entities:" + entities + " queryBeans:" + queryBeans + " tqb:" + transactional;
065  }
066
067  void addTransactional(String className) {
068    transactional.add(className);
069  }
070
071  void addEntity(String className) {
072    entities.add(className);
073  }
074
075  void addQueryBean(String className) {
076    queryBeans.add(className);
077  }
078
079  void addQueryBeanCaller(String className) {
080    queryBeanCallers.add(className);
081  }
082
083  void addFieldAccessUser(String className) {
084    fieldAccessUsers.add(className);
085  }
086
087  private String summary(String prefix, Set<String> beans) {
088    return new SumOut(beans).summary(prefix);
089  }
090
091  /**
092   * Return the manifest resource paths that were loaded.
093   */
094  public List<String> loadedResources() {
095    return loadedResources;
096  }
097
098  /**
099   * Return a summary of the entities enhanced.
100   */
101  public String entities() {
102    return summary("     Entities", entities);
103  }
104
105  /**
106   * Return a summary of the query beans enhanced.
107   */
108  public String queryBeans() {
109    return summary("   QueryBeans", queryBeans);
110  }
111
112  /**
113   * Return a summary of the beans enhanced that call query beans.
114   */
115  public String queryCallers() {
116    return summary("Query Callers", queryBeanCallers);
117  }
118
119  /**
120   * Return a summary of the beans enhanced that call query beans.
121   */
122  public String fieldAccess() {
123    return summary(" Field Access", fieldAccessUsers);
124  }
125
126  /**
127   * Return a summary of the beans with transactional enhanced.
128   */
129  public String transactional() {
130    return summary("Transactional", transactional);
131  }
132
133  /**
134   * Helper that trims off the common package prefix to shorten the output.
135   */
136  static class SumOut {
137
138    private final Set<String> beans;
139    private final Set<String> trimmedBeans;
140    private String[] commonAsArray;
141    private String commonPrefix;
142
143    SumOut(Set<String> beans) {
144      this.beans = beans;
145      initCommonPrefix();
146      trimmedBeans = trimmedBeans();
147    }
148
149    String sizeOut(int size) {
150      return " (" + size + ")" + ((size < 9) ? " " : "");
151    }
152
153    String summary(String prefix) {
154      return prefix + sizeOut(beans.size()) + " pkgs[" + commonPrefix + "] beans" + trimmedBeans.toString();
155    }
156
157    String commonPackage() {
158      return commonPrefix;
159    }
160
161    String beans() {
162      return trimmedBeans.toString();
163    }
164
165    private void initCommonPrefix() {
166      if (beans.isEmpty()) {
167        commonPrefix = "";
168      } else {
169        for (String bean : beans) {
170          final String beanPrefix = prefix(bean);
171          if (commonPrefix == null) {
172            commonPrefix = beanPrefix;
173            commonAsArray = beanPrefix.split("/");
174          } else {
175            common(beanPrefix);
176          }
177        }
178      }
179    }
180
181    private void common(String beanPrefix) {
182      if (beanPrefix.equals(commonPrefix)) {
183        return;
184      }
185
186      final String[] elements = beanPrefix.split("/");
187      int min = Math.min(commonAsArray.length, elements.length);
188      for (int i = 0; i < min; i++) {
189        if (!elements[i].equals(commonAsArray[i])) {
190          commonFor(i);
191          return;
192        }
193      }
194      if (commonAsArray.length != min) {
195        commonFor(min);
196      }
197    }
198
199    private void setCommonPrefix(String beanPrefix) {
200      commonPrefix = beanPrefix;
201      commonAsArray = beanPrefix.split("/");
202    }
203
204    private void commonFor(int pos) {
205      StringJoiner joiner = new StringJoiner("/");
206      for (int i = 0; i < pos; i++) {
207        joiner.add(commonAsArray[i]);
208      }
209      setCommonPrefix(joiner.toString());
210    }
211
212    String prefix(String bean) {
213      final int pos = bean.lastIndexOf('/');
214      return (pos == -1) ? bean : bean.substring(0, pos);
215    }
216
217    private Set<String> trimmedBeans() {
218      if (beans.isEmpty()) {
219        return beans;
220      }
221      Set<String> temp = new TreeSet<>();
222      int trimLen = commonPrefix.length() + 1;
223      if (trimLen == 1) {
224        trimLen = 0;
225      }
226      for (String bean : beans) {
227        if (bean.length() > trimLen) {
228          bean = bean.substring(trimLen);
229        }
230        temp.add(bean);
231      }
232      return temp;
233    }
234
235  }
236}