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}