/**
*
*/
package net.conselldemallorca.helium.core.helperv26;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.conselldemallorca.helium.core.model.hibernate.Expedient;
import net.conselldemallorca.helium.v3.core.api.dto.IntervalEventDto;
import net.conselldemallorca.helium.v3.core.api.dto.MesuraTemporalDto;
import net.conselldemallorca.helium.v3.core.api.dto.TascaCompleteDto;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
/**
* Helper per a mesurar intervals de temps i fer-ne estadístiques.
*
* @author Limit Tecnologies <limit@limit.es>
*/
@Component
public class MesuresTemporalsHelper {
private static int mesures = 0;
private static Boolean actiu = null;
private static Long inici = null;
private static Long fi = null;
private Map<String, Map<Clau, Estadistiques>> intervalsEstadistiques = new HashMap<String, Map<Clau, Estadistiques>>();
private Map<String, TascaComplete> tasquesComplete = new HashMap<String, TascaComplete>();
public MesuresTemporalsHelper(String sactiu, Integer imesures) {
super();
if (!"true".equalsIgnoreCase(sactiu))
actiu = false;
else
actiu = true;
mesures = imesures;
inici = new Long(System.currentTimeMillis());
}
public void mesuraIniciar(String nom, String familia) {
mesuraIniciar(nom, familia, null, null, null);
}
public void mesuraIniciar(String nom, String familia, String tipusExpedient) {
mesuraIniciar(nom, familia, tipusExpedient, null, null);
}
public void mesuraIniciar(String nom, String familia, String tipusExpedient, String tasca) {
mesuraIniciar(nom, familia, tipusExpedient, tasca, null);
}
public void mesuraIniciar(String nom, String familia, String tipusExpedient, String tasca, String detall) {
try {
if (actiu) {
Clau clau = new Clau(nom, tipusExpedient, tasca, detall);
if (!intervalsEstadistiques.containsKey(familia)) {
intervalsEstadistiques.put(familia, new HashMap<Clau, Estadistiques>());
}
Map<Clau, Estadistiques> mEstadistiques = intervalsEstadistiques.get(familia);
Estadistiques est = mEstadistiques.get(clau);
if (est == null) {
mEstadistiques.put(clau, new Estadistiques());
} else {
est.setInici(new Long(System.currentTimeMillis()));
}
}
} catch (Exception e) {
logger.error("No s'ha pogut iniciar la mesura de temps: " + nom, e);
}
}
public void mesuraCalcular(String nom, String familia) {
mesuraCalcular(nom, familia, null, null, null);
}
public void mesuraCalcular(String nom, String familia, String tipusExpedient) {
mesuraCalcular(nom, familia, tipusExpedient, null, null);
}
public void mesuraCalcular(String nom, String familia, String tipusExpedient, String tasca) {
mesuraCalcular(nom, familia, tipusExpedient, tasca, null);
}
public void mesuraCalcular(String nom, String familia, String tipusExpedient, String tasca, String detall) {
try {
if (actiu && intervalsEstadistiques.containsKey(familia)) {
Clau clau = new Clau(nom, tipusExpedient, tasca, detall);
Estadistiques est = intervalsEstadistiques.get(familia).get(clau);
if (est != null)
est.addNovaMesura();
}
} catch (Exception e) {
logger.error("No s'ha pogut calcular la mesura de temps: " + nom, e);
}
}
public void intervalNetejar(String nom, String familia, String tipusExpedient, String tasca, String detall) {
Clau clau = new Clau(nom, tipusExpedient, tasca, detall);
if (intervalsEstadistiques.containsKey(familia)) {
intervalsEstadistiques.get(familia).remove(clau);
}
}
public void tascaCompletarIniciar(Expedient exp, String tascaId, String tascaNom) {
tasquesComplete.put(tascaId, new TascaComplete(
tascaId,
exp.getId(),
exp.getTipus().getNom(),
exp.getIdentificador(),
tascaNom,
new Date()));
}
public void tascaCompletarFinalitzar(String tascaId) {
tasquesComplete.remove(tascaId);
}
public void tascaCompletarNetejar() {
tasquesComplete.clear();
}
public List<MesuraTemporalDto> getEstadistiques(String familia, boolean ambDetall) {
fi = System.currentTimeMillis();
Map<String, Map<Clau, Estadistiques>> estadistiquesFamilia = null;
if (familia == null || "".equals(familia)) {
estadistiquesFamilia = intervalsEstadistiques;
} else {
estadistiquesFamilia = new HashMap<String, Map<Clau, Estadistiques>>();
estadistiquesFamilia.put(familia, intervalsEstadistiques.get(familia));
}
List<MesuraTemporalDto> resposta = new ArrayList<MesuraTemporalDto>();
Long temps = fi - inici;
// SortedSet<String> families = new TreeSet<String>(estadistiquesFamilia.keySet());
// for (String family: families) {
for (String family: estadistiquesFamilia.keySet()) {
logger.debug("[TEMPS] >>>>>>>>>>> Obtenció estadístiques de la família " + family + " ... ");
Map<Clau, Estadistiques> estadistiques = estadistiquesFamilia.get(family);
if (estadistiques != null) {
// SortedSet<Clau> claus = new TreeSet<Clau>(estadistiques.keySet());
// for (Clau clau: claus) {
for (Clau clau: estadistiques.keySet()) {
if (ambDetall || clau.getDetall() == null) {
Estadistiques estadistica = estadistiques.get(clau);
if (estadistica != null && estadistica.getDarreraMesura() != null) {
MesuraTemporalDto dto = new MesuraTemporalDto();
dto.setClau(clau.getNom());
dto.setTipusExpedient(clau.getTipusExpedient());
dto.setTasca(clau.getTasca());
dto.setDetall(clau.getDetall());
dto.setDarrera(estadistica.getDarreraMesura());
dto.setMitja(estadistica.getMitja());
dto.setMinima(estadistica.getMinim());
dto.setMaxima(estadistica.getMaxim());
dto.setNumMesures(estadistica.getContador());
LinkedList<IntervalEventDto> intervalEvents = new LinkedList<IntervalEventDto>();
LinkedList<IntervalEvent> events = estadistica.getEvents();
for (int i = 0; i < events.size(); i++) {
// for (IntervalEvent event : events) {
try {
IntervalEvent event = events.get(i);
if (event != null && event.getDate() != null && event.getDuracio() != null) {
intervalEvents.add(new IntervalEventDto(event.getDate(), event.getDuracio()));
} else {
logger.error("ERROR ESTADISTIQUES: Mesura " + clau.getNom() + " amb events nulls.");
}
} catch(Exception e) {}
}
dto.setEvents(intervalEvents);
// Execucions per minut
dto.setPeriode((dto.getNumMesures() * 60000.0) / temps);
resposta.add(dto);
}
}
}
}
logger.debug("OK");
}
Collections.sort(resposta);
return resposta;
}
public List<MesuraTemporalDto> getEstadistiquesTipusExpedient() {
List<MesuraTemporalDto> estadistiques = findMesures(true);
Collections.sort(estadistiques, new Comparator<MesuraTemporalDto>() {
public int compare(MesuraTemporalDto o1, MesuraTemporalDto o2) {
int comp = compareStr(o1.getTipusExpedient(), o2.getTipusExpedient());
if (comp == 0) {
comp = compareStr(o1.getClau(), o2.getClau());
if (comp == 0) {
if (o1.getDetall() == null || o2.getDetall() == null)
return compareStr(o2.getDetall(), o1.getDetall());
else
return compareStr(o1.getDetall(), o2.getDetall());
}
}
return comp;
}
});
Long temps = fi - inici;
List<MesuraTemporalDto> resposta = new ArrayList<MesuraTemporalDto>();
MesuraTemporalDto ultima = null;
for (MesuraTemporalDto estadistica: estadistiques) {
if (ultima != null && ultima.getNomTE().equals(estadistica.getNomTE())) {
ultima.setMaxima(Math.max(ultima.getMaxima(), estadistica.getMaxima()));
ultima.setMinima(Math.min(ultima.getMinima(), estadistica.getMinima()));
ultima.setMitja(((ultima.getMitja() * ultima.getNumMesures()) + (estadistica.getMitja() * estadistica.getNumMesures())) / (ultima.getNumMesures() + estadistica.getNumMesures()));
ultima.setNumMesures(ultima.getNumMesures() + estadistica.getNumMesures());
ultima.setPeriode(((ultima.getNumMesures() + estadistica.getNumMesures()) * 60000.0) / temps);
} else {
resposta.add(estadistica);
ultima = estadistica;
}
}
return resposta;
}
public List<MesuraTemporalDto> getEstadistiquesTasca() {
List<MesuraTemporalDto> estadistiques = findMesures(false);
Collections.sort(estadistiques, new Comparator<MesuraTemporalDto>() {
public int compare(MesuraTemporalDto o1, MesuraTemporalDto o2) {
int comp = compareStr(o1.getTipusExpedient(), o2.getTipusExpedient());
if (comp == 0) {
comp = compareStr(o1.getTasca(), o2.getTasca());
}
if (comp == 0) {
comp = compareStr(o1.getClau(), o2.getClau());
if (comp == 0) {
if (o1.getDetall() == null || o2.getDetall() == null)
return compareStr(o2.getDetall(), o1.getDetall());
else
return compareStr(o1.getDetall(), o2.getDetall());
}
}
return comp;
}
});
return estadistiques;
}
private List<MesuraTemporalDto> findMesures(boolean ambTipus) {
fi = System.currentTimeMillis();
List<MesuraTemporalDto> resposta = new ArrayList<MesuraTemporalDto>();
Long temps = fi - inici;
boolean ambTasca = !ambTipus;
for (String family: intervalsEstadistiques.keySet()) {
Map<Clau, Estadistiques> estadistiques = intervalsEstadistiques.get(family);
for (Clau clau: estadistiques.keySet()) {
if ((ambTipus && clau.getTipusExpedient() != null) || (ambTasca && clau.getTasca() != null)) {
Estadistiques estadistica = estadistiques.get(clau);
if (estadistica != null && estadistica.getDarreraMesura() != null) {
MesuraTemporalDto dto = new MesuraTemporalDto();
dto.setClau(clau.getNom());
dto.setTipusExpedient(clau.getTipusExpedient());
dto.setTasca(clau.getTasca());
dto.setDetall(clau.getDetall());
dto.setDarrera(estadistica.getDarreraMesura());
dto.setMitja(estadistica.getMitja());
dto.setMinima(estadistica.getMinim());
dto.setMaxima(estadistica.getMaxim());
dto.setNumMesures(estadistica.getContador());
// Execucions per minut
dto.setPeriode((dto.getNumMesures() * 60000.0) / temps);
resposta.add(dto);
}
}
}
}
return resposta;
}
public List<TascaCompleteDto> getTasquesCompletar() {
fi = System.currentTimeMillis();
List<TascaCompleteDto> resposta = new ArrayList<TascaCompleteDto>();
for (TascaComplete tasca: tasquesComplete.values()) {
Double temps = Long.valueOf(fi - tasca.getInici().getTime()).doubleValue() / 1000.0;
TascaCompleteDto dto = new TascaCompleteDto();
dto.setExpedient(tasca.getExpedient());
dto.setExpedientId(tasca.getExpedientId());
dto.setInici(tasca.getInici());
dto.setTasca(tasca.getTasca());
dto.setTascaId(tasca.getTascaId());
dto.setTempsExecucio(temps);
dto.setTipusExpedient(tasca.getTipusExpedient());
resposta.add(dto);
}
return resposta;
}
public static Long getTemps() {
if (fi == null)
fi = System.currentTimeMillis();
return fi - inici;
}
public Set<String> getIntervalsFamilia() {
return intervalsEstadistiques.keySet();
}
public class IntervalEvent {
private Date date;
private Long duracio;
public IntervalEvent(Date date, Long duracio) {
super();
this.date = date;
this.duracio = duracio;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Long getDuracio() {
return duracio;
}
public void setDuracio(Long duracio) {
this.duracio = duracio;
}
}
protected class Clau implements Comparable<Clau> {
private String nom;
private String tipusExpedient;
private String tasca;
private String detall;
public Clau(String nom, String tipusExpedient, String tasca, String detall) {
super();
this.nom = nom;
this.tipusExpedient = tipusExpedient;
this.tasca = tasca;
this.detall = detall;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getTipusExpedient() {
return tipusExpedient;
}
public void setTipusExpedient(String tipusExpedient) {
this.tipusExpedient = tipusExpedient;
}
public String getTasca() {
return tasca;
}
public void setTasca(String tasca) {
this.tasca = tasca;
}
public String getDetall() {
return detall;
}
public void setDetall(String detall) {
this.detall = detall;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result
+ ((detall == null) ? 0 : detall.hashCode());
result = prime * result + ((nom == null) ? 0 : nom.hashCode());
result = prime * result + ((tasca == null) ? 0 : tasca.hashCode());
result = prime
* result
+ ((tipusExpedient == null) ? 0 : tipusExpedient.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Clau other = (Clau) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (detall == null) {
if (other.detall != null)
return false;
} else if (!detall.equals(other.detall))
return false;
if (nom == null) {
if (other.nom != null)
return false;
} else if (!nom.equals(other.nom))
return false;
if (tasca == null) {
if (other.tasca != null)
return false;
} else if (!tasca.equals(other.tasca))
return false;
if (tipusExpedient == null) {
if (other.tipusExpedient != null)
return false;
} else if (!tipusExpedient.equals(other.tipusExpedient))
return false;
return true;
}
public int compareTo(Clau o) {
int comp = compareStr(this.nom, o.nom);
if (comp == 0) {
comp = compareStr(this.tipusExpedient, o.tipusExpedient);
if (comp == 0) {
comp = compareStr(this.tasca, o.tasca);
return comp == 0 ? compareStr(this.detall, o.detall) : comp;
}
}
return comp;
}
private MesuresTemporalsHelper getOuterType() {
return MesuresTemporalsHelper.this;
}
}
protected class Estadistiques {
private Long inici;
private Long darreraMesura;
private Long minim;
private Long maxim;
private Double mitja;
private Long contador;
private LinkedList<IntervalEvent> events;
public Estadistiques() {
super();
this.inici = new Long(System.currentTimeMillis());
this.contador = 0L;
this.events = new LinkedList<IntervalEvent>();
}
public void addNovaMesura() {
Long diferencia = System.currentTimeMillis() - inici.longValue();
darreraMesura = diferencia;
if (minim == null || diferencia < minim)
minim = diferencia;
if (maxim == null || diferencia > maxim)
maxim = diferencia;
contador++;
if (events == null) events = new LinkedList<IntervalEvent>();
if (!events.isEmpty() && events.size() > 0 && events.size() == mesures)
try {
events.removeFirst();
} catch (Exception e) {}
events.add(new IntervalEvent(new Date(), diferencia));
if (mitja == null)
mitja = new Double(diferencia);
else
mitja = new Double((mitja * (contador - 1) + diferencia) / contador);
}
public Long getInici() {
return inici;
}
public void setInici(Long inici) {
this.inici = inici;
}
public Long getDarreraMesura() {
return darreraMesura;
}
public void setDarreraMesura(Long darreraMesura) {
this.darreraMesura = darreraMesura;
}
public Long getMinim() {
return minim;
}
public void setMinim(Long minim) {
this.minim = minim;
}
public Long getMaxim() {
return maxim;
}
public void setMaxim(Long maxim) {
this.maxim = maxim;
}
public Double getMitja() {
return mitja;
}
public void setMitja(Double mitja) {
this.mitja = mitja;
}
public Long getContador() {
return contador;
}
public void setContador(Long contador) {
this.contador = contador;
}
public LinkedList<IntervalEvent> getEvents() {
return events;
}
public void setEvents(LinkedList<IntervalEvent> events) {
this.events = events;
}
}
public static boolean isActiu() {
return actiu;
}
private int compareStr(String str1, String str2) {
return (str1 == null ? (str2 == null ? 0 : 1) : (str2 == null ? -1 : str1.compareTo(str2)));
}
protected class TascaComplete {
String tascaId;
Long expedientId;
String tipusExpedient;
String expedient;
String tasca;
Date inici;
public TascaComplete(String tascaId, Long expedientId, String tipusExpedient,
String expedient, String tasca, Date inici) {
super();
this.tascaId = tascaId;
this.expedientId = expedientId;
this.tipusExpedient = tipusExpedient;
this.expedient = expedient;
this.tasca = tasca;
this.inici = inici;
}
public String getTascaId() {
return tascaId;
}
public void setTascaId(String tascaId) {
this.tascaId = tascaId;
}
public Long getExpedientId() {
return expedientId;
}
public void setExpedientId(Long expedientId) {
this.expedientId = expedientId;
}
public String getTipusExpedient() {
return tipusExpedient;
}
public void setTipusExpedient(String tipusExpedient) {
this.tipusExpedient = tipusExpedient;
}
public String getExpedient() {
return expedient;
}
public void setExpedient(String expedient) {
this.expedient = expedient;
}
public String getTasca() {
return tasca;
}
public void setTasca(String tasca) {
this.tasca = tasca;
}
public Date getInici() {
return inici;
}
public void setInici(Date inici) {
this.inici = inici;
}
}
private static final Log logger = LogFactory.getLog(MesuresTemporalsHelper.class);
}