BrightSide Workbench Full Report + Source Code
ProcessMatching.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.matching;
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 ProcessMatching<T> implements IProcess, IPreprocessor {
42 
43  @Override
44  public void startProcess() {
45  Logger.getLogger(ProcessMatching.class.getName())
46  .log(Level.INFO, ElephantContext.logMsg("Start " + instanceClass().getSimpleName() + "..."));
47  start();
48  truncate();
49  Logger.getLogger(ProcessMatching.class.getName())
50  .log(Level.INFO, ElephantContext.logMsg("Truncated"));
51  List<IndicatorVariable> vars = Indicators.getMatchingVariables(indicatorsRoot());
52  prepareProcess(vars);
53  Logger.getLogger(ProcessMatching.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(ProcessMatching.class.getName())
61  .log(Level.INFO, ElephantContext.logMsg("Processed"));
62  postProcess(vars);
63  Logger.getLogger(ProcessMatching.class.getName())
64  .log(Level.INFO, ElephantContext.logMsg("Postprocessed"));
65  calculateMatching();
66  end();
67  Logger.getLogger(ProcessMatching.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  stream.forEach(t -> {
84  processFor(t, variables);
85  });
86  }
87 
88  public void processFor(T entity, List<IndicatorVariable> variables) {
89  prepareEntity(entity);
90  try(Stream<String> related = Indicators.getIndicator("generic").getEntityPaths(relatedRoot())) {
91  related.forEach(r -> {
92  variables.forEach(v -> {
93  if(!v.isPreprocess()) {
94  process(entity, r, v);
95  }
96  });
97  });
98  }
99  }
100 
101  protected void start() {}
102  protected void end() {}
103 
104  protected void truncate() {
105  if(getSelectedPaths() == null) {
106  getDao().executeNativeUpdate("truncate table " + instanceClass().getSimpleName());
107  } else {
108  WhereClause wc = new WhereClause();
109  wc.addClause("delete from " + instanceClass().getSimpleName());
110  wc.addIn("where", "entityPath", getSelectedPaths());
111  getDao().executeUpdate(wc);
112  }
113  }
114 
115  protected List<String> getSelectedPaths() {
116  return null;
117  }
118 
119  protected IMatching process(T entity, String relatedPath, IndicatorVariable variable) {
120  IMatching matching = createMatchingInstance(getDao().getPath(entity), relatedPath, variable);
121  matching.setMatching(Indicators.getValue(entity, relatedPath, variable));
122  if(!Zero.near(matching.getMatching(), 2)) {
123  matching = getDao().saveObject(matching);
124  }
125  return matching;
126  }
127 
128  protected void prepareProcess(List<IndicatorVariable> variables) {
129  variables.forEach(v -> {
130  if(v.isPreprocess()) {
131  IElephantIndicator ei = Indicators.getIndicator(v);
132  ei.preprocess(v, this, entitiesRoot(), relatedRoot());
133  }
134  });
135  }
136 
137  protected void postProcess(List<IndicatorVariable> variables) {
138  variables.forEach(v -> {
140  ei.postprocess(v, this, entitiesRoot(), relatedRoot());
141  });
142  }
143 
144  protected void prepareEntity(T entity) { }
145 
146  protected double calculate(MatchingSet set) {
147  return set.applyFrom(Formulas.load().getFormula(instanceClass()));
148  }
149 
150  protected IMatching createMatchingInstance(String entityPath, String relatedPath, IndicatorVariable variable) {
151  IMatching matching = createMatchingInstance();
152  matching.setEntityPath(entityPath);
153  matching.setRelatedPath(relatedPath);
154  matching.setConcept(variable.getName());
155  matching.setMatching(0);
156  return matching;
157  }
158 
159  protected abstract Stream<T> getEntityStream();
160  protected abstract IMatching createMatchingInstance();
161  protected abstract Class instanceClass();
162  protected abstract String indicatorsRoot();
163  protected abstract String entitiesRoot();
164  protected abstract String relatedRoot();
165  protected abstract Dao createDao();
166 
167  /* Results */
168 
169  private IMatching previous;
170  private MatchingSet set;
171  private List<IndicatorVariable> variables;
172 
173  private void calculateMatching() {
174  previous = null;
175  set = new MatchingSet();
177  try(Stream<IMatching> tuples = getIndicatorTuples()) {
178  tuples.forEach(t -> {
179  doCalculate(t);
180  });
181  }
182  if(!set.isEmpty()) {
183  doCalculate(null);
184  }
185  getDao().finishPool();
186  }
187 
188  private Stream<IMatching> getIndicatorTuples() {
189  WhereClause wc = new WhereClause();
190  wc.addClause("select m from " + instanceClass().getSimpleName() + " m");
191  if(getSelectedPaths() != null) {
192  wc.addIn("where", "entityPath", getSelectedPaths());
193  }
194  wc.addClause("order by entityPath, relatedPath, concept");
195  return createDao().stream(IMatching.class, wc, 1000);
196  }
197 
198  private void doCalculate(IMatching matching) {
199  if(matching == null || (previous != null && !sameTuple(previous, matching))) {
200  set.addMissing(variables);
201  IMatching result = createMatchingInstance(previous.getEntityPath(), previous.getRelatedPath(),
202  IndicatorVariable.result(indicatorsRoot(), VariableType.MATCHING_VARIABLE));
203  result.setMatching(calculate(set));
204  if(!Zero.near(result.getMatching(), 2)) {
205  getDao().poolObject(result, 1000);
206  }
207  set = new MatchingSet();
208  }
209  if(matching != null) {
210  set.add(matching);
211  previous = matching;
212  }
213  }
214 
215  private boolean sameTuple(IMatching matching1, IMatching matching2) {
216  if(matching1 == null || matching2 == null) {
217  return false;
218  }
219  return matching1.getEntityPath().equals(matching2.getEntityPath()) &&
220  matching1.getRelatedPath().equals(matching2.getRelatedPath());
221  }
222 
223  /* Preprocessor */
224 
225  @Override
226  public Object createInstance() {
227  return createMatchingInstance();
228  }
229 
230  @Override
231  public void poolInstance(Object value) {
232  getDao().poolObject(value, 1000);
233  }
234 
235  @Override
236  public void finishPreprocessor() {
237  getDao().finishPool();
238  }
239 
240  @Override
241  public String tableName() {
242  return instanceClass().getSimpleName();
243  }
244 
245  /* Dao */
246 
247  private Dao _dao;
248 
249  protected Dao getDao() {
250  if(_dao == null) {
251  _dao = createDao();
252  }
253  return _dao;
254  }
255 
256 }
void addIn(String operator, String field, List values)
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 > getMatchingVariables(String root)
Definition: Indicators.java:47
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
void postProcess(List< IndicatorVariable > variables)
void processFor(T entity, List< IndicatorVariable > variables)
abstract IMatching createMatchingInstance()
abstract Stream< T > getEntityStream()
IMatching createMatchingInstance(String entityPath, String relatedPath, IndicatorVariable variable)
void process(Stream< T > stream, List< IndicatorVariable > variables)
void prepareProcess(List< IndicatorVariable > variables)
IMatching process(T entity, String relatedPath, IndicatorVariable variable)
static boolean near(double value, int digits)
Definition: Zero.java:30
void postprocess(IndicatorVariable variable, IPreprocessor preprocessor, String entityRoot, String relatedRoot)
Stream< String > getEntityPaths(String entityRoot)
void setRelatedPath(String relatedPath)
void setConcept(String concept)
void setMatching(double value)
void setEntityPath(String entityPath)