BrightSide Workbench Full Report + Source Code
ProcessRanking.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2020 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.ranking;
20 
21 import java.util.List;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
24 import java.util.stream.Stream;
25 import org.turro.action.IProcess;
26 import org.turro.elephant.context.ElephantContext;
27 import org.turro.elephant.db.WhereClause;
28 import org.turro.indicator.Formulas;
29 import org.turro.indicator.IElephantIndicator;
30 import org.turro.indicator.IPreprocessor;
31 import org.turro.indicator.IndicatorVariable;
32 import org.turro.indicator.Indicators;
33 import org.turro.indicator.VariableType;
34 import org.turro.jpa.Dao;
35 import org.turro.math.Zero;
36 
41 public abstract class ProcessRanking<T> implements IProcess, IPreprocessor {
42 
43  @Override
44  public void startProcess() {
45  Logger.getLogger(ProcessRanking.class.getName())
46  .log(Level.INFO, ElephantContext.logMsg("Start " + instanceClass().getSimpleName() + "..."));
47  start();
48  truncate();
49  Logger.getLogger(ProcessRanking.class.getName())
50  .log(Level.INFO, ElephantContext.logMsg("Truncated"));
51  List<IndicatorVariable> vars = Indicators.getRankingVariables(indicatorsRoot());
52  prepareProcess(vars);
53  Logger.getLogger(ProcessRanking.class.getName())
54  .log(Level.INFO, ElephantContext.logMsg("Preprocessed"));
55  if(Indicators.hasDirectProcess(vars)) {
56  try(Stream<T> entities = getEntityStream()) {
57  process(entities, vars);
58  }
59  }
60  Logger.getLogger(ProcessRanking.class.getName())
61  .log(Level.INFO, ElephantContext.logMsg("Processed"));
62  postProcess(vars);
63  Logger.getLogger(ProcessRanking.class.getName())
64  .log(Level.INFO, ElephantContext.logMsg("Postprocessed"));
65  calculateRanking();
66  end();
67  Logger.getLogger(ProcessRanking.class.getName())
68  .log(Level.INFO, ElephantContext.logMsg("End " + instanceClass().getSimpleName()));
69  }
70 
71  @Override
72  public void startProcessFor(Object entity) {
73  String entityPath = getDao().getPath(entity);
74  WhereClause wc = new WhereClause();
75  wc.addClause("delete from " + instanceClass().getSimpleName());
76  wc.addClause("where entityPath = :entityPath");
77  wc.addNamedValue("entityPath", entityPath);
78  getDao().executeUpdate(wc);
80  }
81 
82  public void process(Stream<T> stream, List<IndicatorVariable> variables) {
83  try {
84  stream.forEach(t -> {
85  processFor(t, variables);
86  });
87  } catch(Exception ex) {
88  Logger.getLogger(ProcessRanking.class.getName())
89  .log(Level.SEVERE, ElephantContext.logMsg("Processing"), ex);
90  }
91  }
92 
93  public void processFor(T entity, List<IndicatorVariable> variables) {
94  prepareEntity(entity);
95  variables.forEach(v -> {
96  if(!v.isPreprocess()) {
97  process(entity, v);
98  }
99  });
100  }
101 
102  protected void start() {}
103  protected void end() {}
104 
105  protected void truncate() {
106  getDao().executeNativeUpdate("truncate table " + instanceClass().getSimpleName());
107  }
108 
109  protected IRanking process(T entity, IndicatorVariable variable) {
110  IRanking ranking = createRankingInstance(getDao().getPath(entity), variable);
111  ranking.setRanking(Indicators.getValue(entity, variable));
112  if(!Zero.near(ranking.getRanking(), 2)) {
113  ranking = getDao().saveObject(ranking);
114  }
115  return ranking;
116  }
117 
118  protected void prepareProcess(List<IndicatorVariable> variables) {
119  variables.forEach(v -> {
120  if(v.isPreprocess()) {
121  IElephantIndicator ei = Indicators.getIndicator(v);
122  ei.preprocess(v, this, entitiesRoot(), null);
123  }
124  });
125  }
126 
127  protected void postProcess(List<IndicatorVariable> variables) {
128  variables.forEach(v -> {
130  ei.postprocess(v, this, entitiesRoot(), null);
131  });
132  }
133 
134  protected void prepareEntity(T entity) { }
135 
136  protected double calculate(RankingSet set) {
137  return set.applyFrom(Formulas.load().getFormula(instanceClass()));
138  }
139 
140  protected IRanking createRankingInstance(String entityPath, IndicatorVariable variable) {
141  IRanking ranking = createRankingInstance();
142  ranking.setEntityPath(entityPath);
143  ranking.setConcept(variable.getName());
144  ranking.setRanking(0);
145  return ranking;
146  }
147 
148  protected abstract Stream<T> getEntityStream();
149  protected abstract IRanking createRankingInstance();
150  protected abstract Class instanceClass();
151  protected abstract String indicatorsRoot();
152  protected abstract String entitiesRoot();
153  protected abstract Dao createDao();
154 
155  /* Results */
156 
157  private IRanking previous;
158  private RankingSet set;
159  private List<IndicatorVariable> variables;
160 
161  private void calculateRanking() {
162  previous = null;
163  set = new RankingSet();
165  try(Stream<IRanking> tuples = getIndicatorTuples()) {
166  tuples.forEach(t -> doCalculate(t));
167  }
168  if(!set.isEmpty()) {
169  doCalculate(null);
170  }
171  getDao().finishPool();
172  }
173 
174  private Stream<IRanking> getIndicatorTuples() {
175  WhereClause wc = new WhereClause();
176  wc.addClause("select m from " + instanceClass().getSimpleName() + " m");
177  wc.addClause("order by entityPath, concept");
178  return createDao().stream(IRanking.class, wc, 1000);
179  }
180 
181  private void doCalculate(IRanking ranking) {
182  if(ranking == null || (previous != null && !sameTuple(previous, ranking))) {
183  set.addMissing(variables);
184  IRanking result = createRankingInstance(previous.getEntityPath(),
185  IndicatorVariable.result(indicatorsRoot(), VariableType.RANKING_VARIABLE));
186  result.setRanking(calculate(set));
187  if(!Zero.near(result.getRanking(), 2)) {
188  getDao().poolObject(result, 1000);
189  }
190  set = new RankingSet();
191  }
192  if(ranking != null) {
193  set.add(ranking);
194  previous = ranking;
195  }
196  }
197 
198  private boolean sameTuple(IRanking ranking1, IRanking ranking2) {
199  if(ranking1 == null || ranking2 == null) {
200  return false;
201  }
202  return ranking1.getEntityPath().equals(ranking2.getEntityPath());
203  }
204 
205  /* Preprocessor */
206 
207  @Override
208  public Object createInstance() {
209  return createRankingInstance();
210  }
211 
212  @Override
213  public void poolInstance(Object value) {
214  getDao().poolObject(value, 1000);
215  }
216 
217  @Override
218  public void finishPreprocessor() {
219  getDao().finishPool();
220  }
221 
222  @Override
223  public String tableName() {
224  return instanceClass().getSimpleName();
225  }
226 
227  /* Dao */
228 
229  private Dao _dao;
230 
231  protected Dao getDao() {
232  if(_dao == null) {
233  _dao = createDao();
234  }
235  return _dao;
236  }
237 
238 }
void addNamedValue(String name, Object value)
static Formulas load()
Definition: Formulas.java:90
String getFormula(Class javaClass)
Definition: Formulas.java:38
static boolean hasDirectProcess(List< IndicatorVariable > variables)
Definition: Indicators.java:38
static double getValue(Object entity, IndicatorVariable variable)
Definition: Indicators.java:87
static List< IndicatorVariable > getRankingVariables(String root)
Definition: Indicators.java:42
static IElephantIndicator getIndicator(String root)
Definition: Indicators.java:69
abstract String getPath(Object object)
int executeUpdate(String query)
Definition: Dao.java:463
void poolObject(Object obj, int poolSize)
Definition: Dao.java:581
void finishPool()
Definition: Dao.java:592
int executeNativeUpdate(SqlClause sc, Object... pars)
Definition: Dao.java:536
static boolean near(double value, int digits)
Definition: Zero.java:30
abstract Stream< T > getEntityStream()
void startProcessFor(Object entity)
void process(Stream< T > stream, List< IndicatorVariable > variables)
void processFor(T entity, List< IndicatorVariable > variables)
abstract String entitiesRoot()
void prepareProcess(List< IndicatorVariable > variables)
void postProcess(List< IndicatorVariable > variables)
abstract IRanking createRankingInstance()
abstract String indicatorsRoot()
IRanking process(T entity, IndicatorVariable variable)
IRanking createRankingInstance(String entityPath, IndicatorVariable variable)
double calculate(RankingSet set)
void postprocess(IndicatorVariable variable, IPreprocessor preprocessor, String entityRoot, String relatedRoot)
void setConcept(String concept)
void setEntityPath(String entityPath)
void setRanking(double value)