listAllMetrics() throws FileNotFoundException;
+}
diff --git a/src/main/java/us/muit/fs/a4i/config/doc-files/configPackage.GIF b/src/main/java/us/muit/fs/a4i/config/doc-files/configPackage.GIF
deleted file mode 100644
index 1f14908f..00000000
Binary files a/src/main/java/us/muit/fs/a4i/config/doc-files/configPackage.GIF and /dev/null differ
diff --git a/src/main/java/us/muit/fs/a4i/config/doc-files/configPackage.gif b/src/main/java/us/muit/fs/a4i/config/doc-files/configPackage.gif
new file mode 100644
index 00000000..bcba3513
Binary files /dev/null and b/src/main/java/us/muit/fs/a4i/config/doc-files/configPackage.gif differ
diff --git a/src/main/java/us/muit/fs/a4i/config/package-info.java b/src/main/java/us/muit/fs/a4i/config/package-info.java
index 86d6dc6f..7ec62cf2 100644
--- a/src/main/java/us/muit/fs/a4i/config/package-info.java
+++ b/src/main/java/us/muit/fs/a4i/config/package-info.java
@@ -1,11 +1,15 @@
/**
- * Clases encargadas del contexto de aplicación
- * Leen la configuración y la ponen disponible
- * Manejan la configuración básica en ficheros simples leídos a Properties y la referida a métricas e indicadores disponibles en ficheros json
- *
+ *
+ * Clases encargadas del contexto de aplicación Leen la configuración y la ponen
+ * disponible Manejan la configuración básica en ficheros simples leÃdos a
+ * Properties y la referida a métricas e indicadores disponibles en ficheros
+ * json
+ *
+ *
*
- * @author Isabel Román
- * @version 0.0
+ * @author Isabel Román
+ * @version V.0.2
*/
package us.muit.fs.a4i.config;
-
diff --git a/src/main/java/us/muit/fs/a4i/control/IndicatorStrategy.java b/src/main/java/us/muit/fs/a4i/control/IndicatorStrategy.java
new file mode 100644
index 00000000..608406fb
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/IndicatorStrategy.java
@@ -0,0 +1,37 @@
+package us.muit.fs.a4i.control;
+
+import java.util.List;
+
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+/**
+ * /**
+ *
+ * Interfaz para calcular indicadores
+ *
+ *
+ * @param
+ * @author celllarod
+ *
+ */
+public interface IndicatorStrategy {
+
+ /**
+ * Calcula un indicador a partir de las métricas proporcionadas.
+ *
+ * @param
+ * @param metrics
+ * @throws NotAvailableMetricException
+ * @return indicador
+ */
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException;
+
+ /**
+ * Obtiene las métricas necesarias
+ *
+ * @return listado de métricas
+ */
+ public List requiredMetrics();
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/IndicatorsCalculator.java b/src/main/java/us/muit/fs/a4i/control/IndicatorsCalculator.java
index 37631cc3..18fb4f46 100644
--- a/src/main/java/us/muit/fs/a4i/control/IndicatorsCalculator.java
+++ b/src/main/java/us/muit/fs/a4i/control/IndicatorsCalculator.java
@@ -1,39 +1,61 @@
/**
- * Algoritmos para el cálculo de indicadores específicos al tipo de informe
+ * Algoritmos para el c�lculo de indicadores espec�ficos al tipo de informe
*/
package us.muit.fs.a4i.control;
import us.muit.fs.a4i.exceptions.IndicatorException;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
import us.muit.fs.a4i.model.entities.ReportI;
+import us.muit.fs.a4i.control.IndicatorStrategy;
/**
*
- * Define los métodos para calcular cada indicador y añadirlo al informe
- * Puede hacerse uno a uno o todos a la vez
- * Las clases que la implementen serán específias para un tipo de informe
- * @author Isabel Román
+ *
+ * Define los métodos para calcular cada indicador y añadirlo al informe
+ *
+ *
+ * Puede hacerse uno a uno o todos a la vez
+ *
+ *
+ * Las clases que la implementen serán especÃfias para un tipo de informe
+ *
+ *
+ * @author Isabel Román
*
*/
public interface IndicatorsCalculator {
/**
- * Calcula el indicador con el nombre que se pasa y lo incluye en el informe
- * Si las métricas que necesita no están en el informe las busca y las añade
- * @param name Nombre del indicador a cálcular
- * @param report Informe sobre el que realizar el cálculo
- * @throws IndicatorException Si el indicador no está definido en la calculadora
+ *
+ * Calcula el indicador con el nombre que se pasa y lo incluye en el informe Si
+ * las métricas que necesita no están en el informe usa ReportManagerI para localizarla antes
+ *
+ *
+ * @param indicatorName Nombre del indicador a calcular
+ * @param reportManager Gestor del Informe sobre el que realizar el cálculo
+ * @throws IndicatorException Si el indicador no está definido en la calculadora
*/
-
- public void calcIndicator(String name,ReportI report) throws IndicatorException;
+
+ public void calcIndicator(String indicatorName, ReportManagerI reportManager) throws IndicatorException;
+
/**
- * Calcula todos los indicadores configurados para el tipo de informe que se pasa. Debe verificar primero que el tipo de informe que se pasa es correcto
- * @param report Informe sobre el que realizar el cálculo
- * @throws IndicatorException Si el tipo del informe no coincide con el de la calculadora
+ *
+ * Calcula todos los indicadores configurados para el tipo de informe que se
+ * pasa. Debe verificar primero que el tipo de informe que se pasa es correcto
+ *
+ *
+ * @param reportManager Informe sobre el que realizar el c�lculo
+ * @throws IndicatorException Si el tipo del informe no coincide con el de la
+ * calculadora
+ * @throws NotAvailableMetricException Si falta alguna métrica en el informe
*/
- public void calcAllIndicators(ReportI report) throws IndicatorException;
-
+ public void calcAllIndicators(ReportManagerI reportManager) throws IndicatorException;
+
/**
* Devuelve el tipo de informe que maneja esta calculadora de indicadores
+ *
* @return El tipo de informes
*/
- public ReportI.Type getReportType();
+ public ReportI.ReportType getReportType();
+
+ public void setIndicator(String indicatorName, IndicatorStrategy strategy);
}
diff --git a/src/main/java/us/muit/fs/a4i/control/ReportManager.java b/src/main/java/us/muit/fs/a4i/control/ReportManager.java
deleted file mode 100644
index f5aa6895..00000000
--- a/src/main/java/us/muit/fs/a4i/control/ReportManager.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- *
- */
-package us.muit.fs.a4i.control;
-
-import java.util.logging.Logger;
-
-import us.muit.fs.a4i.exceptions.ReportNotDefinedException;
-import us.muit.fs.a4i.model.entities.ReportI;
-import us.muit.fs.a4i.model.remote.RemoteEnquirer;
-import us.muit.fs.a4i.persistence.PersistenceManager;
-import us.muit.fs.a4i.persistence.ReportFormaterI;
-
-/**
- * @author isa
- *
- */
-public class ReportManager implements ReportManagerI {
- private static Logger log=Logger.getLogger(ReportManager.class.getName());
- private ReportI report;
- private PersistenceManager persister;
- private RemoteEnquirer enquirer;
- private ReportFormaterI formater;
- private IndicatorsCalculator calc;
- private String entityId;
-
-
-
- @Override
- public void setRemoteEnquirer(RemoteEnquirer remote) {
- this.enquirer=remote;
-
- }
-
- @Override
- public void setPersistenceManager(PersistenceManager persistence) {
- this.persister=persistence;
-
- }
-
- @Override
- public void setFormater(ReportFormaterI formater) {
- this.formater=formater;
-
- }
-
- @Override
- public void setIndicatorCalc(IndicatorsCalculator calc) {
- this.calc=calc;
-
- }
-
- @Override
- public void saveReport(ReportI report) {
- persister.setReport(report);
- persister.setFormater(formater);
- try {
- persister.saveReport();
- } catch (ReportNotDefinedException e) {
- log.info("No debería entrar aquí porque se acaba de establecer el informe");
- e.printStackTrace();
- }
- }
-
- @Override
- public void save() throws ReportNotDefinedException {
- if(report!=null) {
- saveReport(report);
- }else throw new ReportNotDefinedException();
-
- }
-
- @Override
- public ReportI createReport(String entityId) {
- report=enquirer.buildReport(entityId);
- return report;
- }
-
- @Override
- public void deleteReport(ReportI report) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void deleteReport() {
- // TODO Auto-generated method stub
-
- }
-
- /**
- * Devuelve el informe que está manejando este gestor
- */
- @Override
- public ReportI getReport() {
- return report;
- }
-
-}
diff --git a/src/main/java/us/muit/fs/a4i/control/ReportManagerI.java b/src/main/java/us/muit/fs/a4i/control/ReportManagerI.java
index f2c1c789..d7ba4c1e 100644
--- a/src/main/java/us/muit/fs/a4i/control/ReportManagerI.java
+++ b/src/main/java/us/muit/fs/a4i/control/ReportManagerI.java
@@ -3,72 +3,82 @@
*/
package us.muit.fs.a4i.control;
-import us.muit.fs.a4i.persistence.PersistenceManager;
import us.muit.fs.a4i.exceptions.ReportNotDefinedException;
import us.muit.fs.a4i.model.entities.ReportI;
-import us.muit.fs.a4i.model.remote.RemoteEnquirer;
+import us.muit.fs.a4i.model.entities.ReportItemI;
import us.muit.fs.a4i.persistence.ReportFormaterI;
/**
- * Interfaz con los métodos disponibles para manejar informes
- * No depende del sistema de persistencia utilizado
- * No depende del tipo de remoto del que se obtienen las métricas
- * No depende del modo de calcular los indicadores
- * En las primeras versiones sólo se leen desde remotos y se guardarán los informes localmente
- * Versiones posteriores permitirán leer y modificar informes
- * @author Isabel Román
+ *
+ * Interfaz con los métodos disponibles para manejar informes
+ *
+ *
+ * No depende del sistema de persistencia utilizado
+ *
+ *
+ * No depende del tipo de remoto del que se obtienen las métricas
+ *
+ *
+ * No depende del modo de calcular los indicadores
+ *
+ *
+ * En las primeras versiones sólo se leen desde remotos y se guardarán los
+ * informes localmente
+ *
+ *
+ * Versiones posteriores permitirán leer y modificar informes
+ *
+ *
+ * @author Isabel Román
*
*/
+
public interface ReportManagerI {
-
- /**
- * Recupera el informe que se están manejando
- * @return Devuelve el informe manejado
- */
- public ReportI getReport();
- /**
- * Establece el objeto que se usará para consultar al servidor remoto y obtener las métricas
- * @param remote Objeto RemoteEnquirer que consultará al servidor remoto
- */
-
- public void setRemoteEnquirer(RemoteEnquirer remote);
+
/**
- * Establece el objeto PersistenceManager que se encargará de guardar el informe localmente
- * @param persistence Objeto PersistenceManager concreto
+ *
+ * Recupera el informe que se está manejando
+ *
+ *
+ * @return Devuelve el informe manejado
*/
- public void setPersistenceManager(PersistenceManager persistence);
+ public ReportI getReport();
+
+ public void addMetric(String metricName);
+
+ public ReportItemI getMetric(String metricName);
+
+ public void addIndicator(String indicatorName);
+
+ public void getIndicator(String indicatorName);
+
+ public void saveReport() throws ReportNotDefinedException;
+
+ public void deleteReport();
+
/**
- * Establece el formateador a usar
+ *
+ * Establece el formateador a usar
+ *
+ *
* @param formater El gestor de formato a utilizar
*/
public void setFormater(ReportFormaterI formater);
- public void setIndicatorCalc(IndicatorsCalculator calc);
-
- /**
- * Persiste el informe que recibe como parámetro, según las reglas del gestor de persistencia y formateador establecidos
- * @param report El informe a persistir
- */
- public void saveReport(ReportI report);
- /**
- * Establecer el informe que se quiere crear
- * @throws ReportNotDefinedException Si no se había establecido un informe
- */
- public void save() throws ReportNotDefinedException;
-
+
/**
- * Crea un informe para la entidad indicada como parámetro, según las reglas del RemoteBuilder Establecido
- * El id debe identificar unívocamente a la entidad en el remoto
- * @param id Identificador de la entidad a la que se refiere el informe
+ *
+ * Crea un informe para la entidad indicada como parámetro, según las reglas del
+ * RemoteBuilder Establecido
+ *
+ *
+ * El id debe identificar unÃvocamente a la entidad en el remoto
+ *
+ *
+ * @param entityId Identificador de la entidad a la que se refiere el informe
+ * @param reportType El tipo de informe
* @return el informe creado
+ * @throws Exception el tipo de informe no coincide con el del manager
*/
- public ReportI createReport(String id);
- /**
- * Borra el informe pasado como parámetro, según las reglas establecidas por el gestor de persistencia
- * @param report El informe que se quiere borrar
- */
- public void deleteReport(ReportI report);
- /**
- * Borra el informe que se está manejando actualmente, si la referencia no era nula, según las reglas establecidas por el gestor de persistencia
- */
- public void deleteReport();
+ public ReportI newReport(String entityId, ReportI.ReportType reportType) throws Exception;
+
}
diff --git a/src/main/java/us/muit/fs/a4i/control/RepositoryCalculator.java b/src/main/java/us/muit/fs/a4i/control/RepositoryCalculator.java
deleted file mode 100644
index b5efe228..00000000
--- a/src/main/java/us/muit/fs/a4i/control/RepositoryCalculator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- *
- */
-package us.muit.fs.a4i.control;
-
-import java.util.logging.Logger;
-
-import us.muit.fs.a4i.model.entities.Indicator;
-
-import us.muit.fs.a4i.model.entities.ReportI;
-
-/**
- * Implementa los métodos para calcular indicadores referidos a un repositorio repositorio
- * Puede hacerse uno a uno o todos a la vez
- * @author Isabel Román
- *
- */
-public class RepositoryCalculator implements IndicatorsCalculator {
- private static Logger log=Logger.getLogger(RepositoryCalculator.class.getName());
- @Override
- public void calcIndicator(String name, ReportI report) {
- log.info("Calcula el indicador de nombre "+name);
- /**
- * Tiene que mirar si están ya las métricas que necesita
- * Si están lo calcula
- * Si no están busca las métricas, las añade y lo calcula
- *
- */
-
- }
-/**
- * Calcula todos los indicadores definidos para un repositorio
- * Recupera todas las métricas que necesite y que no estén en el informe y las añade al mismo
- *
- */
- @Override
- public void calcAllIndicators(ReportI report) {
- log.info("Calcula todos los indicadores del repositorio y los incluye en el informe");
- }
- private Indicator commitsPerUser(ReportI report) {
- Indicator indicator=null;
-
- return indicator;
- }
- @Override
- public ReportI.Type getReportType() {
- return ReportI.Type.REPOSITORY;
- }
-}
diff --git a/src/main/java/us/muit/fs/a4i/control/calculators/RepositoryCalculator.java b/src/main/java/us/muit/fs/a4i/control/calculators/RepositoryCalculator.java
new file mode 100644
index 00000000..5081609f
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/calculators/RepositoryCalculator.java
@@ -0,0 +1,96 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.calculators;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.control.IndicatorsCalculator;
+import us.muit.fs.a4i.control.ReportManagerI;
+import us.muit.fs.a4i.exceptions.IndicatorException;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.ReportI;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * Implementa los métodos para calcular indicadores referidos a un repositorio
+ *
+ *
+ * Puede hacerse uno a uno o todos a la vez
+ *
+ * RECUERDA: los indicadores tienen que estar incluidos en el fichero de
+ * configuración a4iDefault.json
+ *
+ * @author Isabel Román
+ *
+ */
+public class RepositoryCalculator implements IndicatorsCalculator {
+ private static Logger log = Logger.getLogger(RepositoryCalculator.class.getName());
+ private static ReportI.ReportType reportType = ReportI.ReportType.REPOSITORY;
+ private static HashMap strategies = new HashMap<>();
+
+ @Override
+ public void calcIndicator(String indicatorName, ReportManagerI reportManager) throws IndicatorException {
+ log.info("Calcula el indicador de nombre " + indicatorName);
+ /**
+ * Tiene que mirar si están ya las métricas que necesita Si están lo calcula Si
+ * no están busca las métricas, las añade al informe y lo calcula
+ *
+ */
+ IndicatorStrategy indicatorStrategy = strategies.get(indicatorName);
+ List requiredMetrics = indicatorStrategy.requiredMetrics();
+ log.fine("Las métricas necesarias son: " + requiredMetrics.toString());
+ List metrics = reportManager.getReport().getAllMetrics().stream().collect(Collectors.toList());
+ List metricsName = metrics.stream().map(ReportItemI::getName).collect(Collectors.toList());
+ for (String metric : requiredMetrics) {
+ if (!metricsName.contains(metric)) {
+ log.fine("se añade la métrica " + metric + " que no estaba disponible aún en el informe");
+ reportManager.addMetric(metric);
+ }
+ }
+
+ try {
+ // añadir el indicador al informe
+ reportManager.getReport().addIndicator(indicatorStrategy.calcIndicator(reportManager.getReport().getAllMetrics().stream().collect(Collectors.toList())));
+ log.info("Añadido al informe indicador");
+ } catch (NotAvailableMetricException e) {
+ log.info("No se han proporcionado todas las métricas necesarias");
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Calcula todos los indicadores definidos para un repositorio Recupera todas
+ * las métricas que necesite y que no estén en el informe y las añade al mismo
+ *
+ */
+ @Override
+ public void calcAllIndicators(ReportManagerI reportManager) throws IndicatorException {
+ log.info("Calcula todos los indicadores del repositorio y los incluye en el informe");
+ }
+
+ private Indicator commitsPerUser(ReportI report) {
+ Indicator indicator = null;
+
+ return indicator;
+ }
+
+ @Override
+ public ReportI.ReportType getReportType() {
+ return reportType;
+ }
+
+ @Override
+ public void setIndicator(String indicatorName, IndicatorStrategy strategy) {
+ strategies.put(indicatorName, strategy);
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/control/managers/ReportManager.java b/src/main/java/us/muit/fs/a4i/control/managers/ReportManager.java
new file mode 100644
index 00000000..f580b415
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/managers/ReportManager.java
@@ -0,0 +1,235 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.managers;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.config.Context;
+import us.muit.fs.a4i.control.IndicatorsCalculator;
+import us.muit.fs.a4i.control.ReportManagerI;
+import us.muit.fs.a4i.control.calculators.RepositoryCalculator;
+import us.muit.fs.a4i.exceptions.ReportNotDefinedException;
+import us.muit.fs.a4i.model.entities.ReportI;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+import us.muit.fs.a4i.model.remote.GitHubRepositoryEnquirer;
+import us.muit.fs.a4i.model.remote.RemoteEnquirer;
+import us.muit.fs.a4i.persistence.ExcelReportManager;
+import us.muit.fs.a4i.persistence.PersistenceManager;
+import us.muit.fs.a4i.persistence.ReportFormater;
+import us.muit.fs.a4i.persistence.ReportFormaterI;
+
+/**
+ * @author Isabel Román
+ *
+ */
+public class ReportManager implements ReportManagerI {
+
+ private static Logger log = Logger.getLogger(ReportManager.class.getName());
+ private ReportI report;
+ private PersistenceManager persister;
+ private RemoteEnquirer enquirer;
+ private ReportFormaterI formater;
+ private IndicatorsCalculator calc;
+ private String entityId;
+ private ReportI.ReportType reportType;
+
+ public ReportManager(ReportI.ReportType reportType) throws IOException {
+
+ this.reportType = reportType;
+ this.formater = new ReportFormater();
+ // Selecting the RemoteEnquierer
+ RemoteEnquirer.RemoteType remote = null;
+
+ remote = RemoteEnquirer.RemoteType.valueOf(Context.getContext().getRemoteType());
+ log.info("Tipo de remoto configurado: " + remote);
+ switch (remote) {
+ case GITHUB:
+ setGHEnquierer();
+ break;
+ default:
+ log.info("Tipo de persistencia no implementando");
+
+ }
+ // Selecting the persister
+ PersistenceManager.PersistenceType persistence = null;
+ persistence = PersistenceManager.PersistenceType.valueOf(Context.getContext().getPersistenceType());
+ switch (persistence) {
+ case DDBB:
+ log.info("La persistencia para base de datos a�n no est� implemetnada");
+ break;
+ case EXCEL:
+ this.persister = new ExcelReportManager();
+ log.info("Se instancia el objeto para persistir informes en excel");
+ break;
+ default:
+ break;
+
+ }
+ // Selecting the IndicatorCalculator
+ switch (this.reportType) {
+ case DEVELOPER:
+ log.info("La calculadora para indicadores de desarrolladores no está implementada");
+ break;
+ case ORGANIZATION:
+ log.info("La calculadora para indicadores de organización no está implementada");
+ break;
+ case PROJECT:
+ log.info("La calculadora para indicadores de proyecto no está implementada");
+ break;
+ case REPOSITORY:
+ this.calc = new RepositoryCalculator();
+ log.info("Se instancia la calculadora para indicadores de respositorio");
+ break;
+ default:
+ break;
+
+ }
+
+ }
+
+ /**
+ *
+ * Borra el informe pasado como parámetro, según las reglas establecidas por el
+ * gestor de persistencia
+ *
+ *
+ * @param report El informe que se quiere borrar
+ */
+ public static void deleteReport(ReportI report) {
+ log.info("deleteReport No implementado");
+
+ }
+
+ /**
+ *
+ * Establece el objeto que se usará para consultar al servidor remoto y obtener
+ * las métricas
+ *
+ *
+ * @param remote Objeto RemoteEnquirer que consultará al servidor remoto
+ */
+ public void setRemoteEnquirer(RemoteEnquirer remote) {
+ this.enquirer = remote;
+
+ }
+
+ public void setPersistenceManager(PersistenceManager persistence) {
+ this.persister = persistence;
+
+ }
+
+ @Override
+ public void setFormater(ReportFormaterI formater) {
+ this.formater = formater;
+
+ }
+
+ public void setIndicatorCalc(IndicatorsCalculator calc) {
+ this.calc = calc;
+
+ }
+
+ /**
+ *
+ * Persiste el informe que recibe como parámetro, según las reglas del gestor de
+ * persistencia y formateador establecidos
+ *
+ *
+ * @param report
+ *
+ * El informe a persistir
+ *
+ */
+ public void saveReport(ReportI report) {
+
+ persister.setFormater(formater);
+ try {
+ persister.saveReport(report);
+ } catch (ReportNotDefinedException e) {
+ log.info("El informe que se quiere guardar no está definido");
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void saveReport() throws ReportNotDefinedException {
+ if (report != null) {
+ saveReport(report);
+ } else
+ throw new ReportNotDefinedException();
+
+ }
+
+ @Override
+ public ReportI newReport(String entityId, ReportI.ReportType reportType) throws Exception {
+ if (reportType != this.reportType) {
+ log.info("Se está intentando crear un tipo de informe diferente al ReportManager usado");
+ throw new Exception("El tipo de informe no coincide con el del ReportManager");
+ }
+
+ report = enquirer.buildReport(entityId);
+ return report;
+ }
+
+ @Override
+ public void deleteReport() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Devuelve el informe que está manejando este gestor
+ */
+ @Override
+ public ReportI getReport() {
+ return report;
+ }
+
+ @Override
+ public void addMetric(String metricName) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public ReportItemI getMetric(String metricName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void addIndicator(String indicatorName) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void getIndicator(String indicatorName) {
+ // TODO Auto-generated method stub
+
+ }
+
+ private void setGHEnquierer() {
+ switch (this.reportType) {
+ case REPOSITORY:
+ this.enquirer = new GitHubRepositoryEnquirer();
+ log.info("Se instancia el enquierer para informes de repositorio con info de github");
+ break;
+ case DEVELOPER:
+ log.info("El enquierer para los informes de desarrolladores con info de github aún no está implementado");
+ break;
+ case ORGANIZATION:
+ log.info("El enquierer para los informes de la organización con info de github aún no está implementado");
+ break;
+ case PROJECT:
+ log.info("El enquierer para los informes de proyecto con info de github aún no está implementado");
+ break;
+ default:
+ log.info("El tipo de informe que se está solicitando no está implementado");
+ break;
+ }
+ }
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/package-info.java b/src/main/java/us/muit/fs/a4i/control/package-info.java
index 8df25b6e..f01fe61d 100644
--- a/src/main/java/us/muit/fs/a4i/control/package-info.java
+++ b/src/main/java/us/muit/fs/a4i/control/package-info.java
@@ -1,8 +1,13 @@
/**
+ *
* Clases e interfaces controladoras
- *
- * @author Isabel Román
- * @version 0.0
+ * Facilitan el cálculo de indicadores y la gestión de informes
+ *
+ *
+ *
+ * @author Isabel Román
+ * @version V.0.2
*/
package us.muit.fs.a4i.control;
-
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/ConventionsCompliantStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/ConventionsCompliantStrategy.java
new file mode 100644
index 00000000..d12a7b6f
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/ConventionsCompliantStrategy.java
@@ -0,0 +1,152 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+/**
+ *
+ */
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+import java.util.Optional;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+public class ConventionsCompliantStrategy implements IndicatorStrategy {
+ // MARK: - Attributes
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+ // The metrics needed to calculate the indicator output
+ private static final List REQUIRED_METRICS = Arrays.asList("conventionalCommits", "commitsWithDescription",
+ "issuesWithLabels", "gitFlowBranches", "conventionalPullRequests");
+ public static final String ID = "conventionsCompliant";
+
+ // Weights for each metric
+ private double WEIGHT_CONVENTIONAL_COMMITS = 0.2;
+ private double WEIGHT_COMMITS_WITH_DESCRIPTION = 0.2;
+ private double WEIGHT_ISSUES_WITH_LABELS = 0.2;
+ private double WEIGHT_GIT_FLOW_BRANCHES = 0.2;
+ private double WEIGHT_CONVENTIONAL_PULL_REQUESTS = 0.2;
+
+ // MARK: - Constructor
+ /**
+ * Constructor. Default weights are equal for all metrics (0.2).
+ */
+ public ConventionsCompliantStrategy() {
+ super();
+ }
+
+ /**
+ * Constructor. Set the weights for each metric. The sum of the weights must be
+ * equal to 1.
+ *
+ * @param weightConventionalCommits the weight for the conventional commits
+ * metric
+ * @param weightCommitsWithDescription the weight for the commits with
+ * description metric
+ * @param weightIssuesWithLabels the weight for the issues with labels
+ * metric
+ * @param weightGitFlowBranches the weight for the git flow branches
+ * metric
+ * @param weightConventionalPullRequests the weight for the conventional pull
+ * requests metric
+ */
+ public ConventionsCompliantStrategy(Double weightConventionalCommits, Double weightCommitsWithDescription,
+ Double weightIssuesWithLabels, Double weightGitFlowBranches, Double weightConventionalPullRequests)
+ throws IllegalArgumentException {
+ // Control that the sum of the weights is equal to 1
+ if (weightConventionalCommits + weightCommitsWithDescription + weightIssuesWithLabels + weightGitFlowBranches
+ + weightConventionalPullRequests != 1) {
+ throw new IllegalArgumentException("The sum of the weights must be equal to 1");
+ }
+
+ // Set the weights
+ this.WEIGHT_CONVENTIONAL_COMMITS = weightConventionalCommits;
+ this.WEIGHT_COMMITS_WITH_DESCRIPTION = weightCommitsWithDescription;
+ this.WEIGHT_ISSUES_WITH_LABELS = weightIssuesWithLabels;
+ this.WEIGHT_GIT_FLOW_BRANCHES = weightGitFlowBranches;
+ this.WEIGHT_CONVENTIONAL_PULL_REQUESTS = weightConventionalPullRequests;
+ }
+
+ // MARK: - Implemented methods
+ // Calculate the indicator output based on the provided metrics
+ @Override
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException {
+ // Attributes
+ Optional> conventionalCommits = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(0).equals(m.getName())).findAny();
+ Optional> commitsWithDescription = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(1).equals(m.getName())).findAny();
+ Optional> issuesWithLabels = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(2).equals(m.getName())).findAny();
+ Optional> gitFlowBranches = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(3).equals(m.getName())).findAny();
+ Optional> conventionalPullRequests = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(4).equals(m.getName())).findAny();
+ ReportItemI indicatorReport = null;
+
+ // Check if the required metrics are present
+ if (conventionalCommits.isPresent() && commitsWithDescription.isPresent() && issuesWithLabels.isPresent()
+ && gitFlowBranches.isPresent() && conventionalPullRequests.isPresent()) {
+ // Calculate the indicator
+ Double metric1, metric2, metric3, metric4, metric5;
+ // Initialize the metrics
+ if (conventionalCommits.get().getValue() >= 0.8499)
+ metric1 = conventionalCommits.get().getValue();
+ else
+ metric1 = 0.0;
+ if (commitsWithDescription.get().getValue() >= 0.8499)
+ metric2 = commitsWithDescription.get().getValue();
+ else
+ metric2 = 0.0;
+ if (issuesWithLabels.get().getValue() >= 0.8499)
+ metric3 = issuesWithLabels.get().getValue();
+ else
+ metric3 = 0.0;
+ if (gitFlowBranches.get().getValue() >= 0.999)
+ metric4 = 1.0;
+ else
+ metric4 = 0.0;
+ if (conventionalPullRequests.get().getValue() >= 0.8499)
+ metric5 = conventionalPullRequests.get().getValue();
+ else
+ metric5 = 0.0;
+
+ Double indicatorValue = WEIGHT_CONVENTIONAL_COMMITS * metric1 + WEIGHT_COMMITS_WITH_DESCRIPTION * metric2
+ + WEIGHT_ISSUES_WITH_LABELS * metric3 + WEIGHT_GIT_FLOW_BRANCHES * metric4
+ + WEIGHT_CONVENTIONAL_PULL_REQUESTS * metric5;
+
+ try {
+ // Create the indicator
+ indicatorReport = new ReportItem.ReportItemBuilder(ID, indicatorValue)
+ .metrics(Arrays.asList(conventionalCommits.get(), commitsWithDescription.get(),
+ issuesWithLabels.get(), gitFlowBranches.get(), conventionalPullRequests.get()))
+ .indicator(IndicatorState.UNDEFINED).build();
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder.");
+ e.printStackTrace();
+ }
+
+ } else {
+ log.info("No se han proporcionado las métricas necesarias");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ // Temporarily throw
+ return indicatorReport;
+ }
+
+ // Return the metrics required to calculate the indicator output
+ @Override
+ public List requiredMetrics() {
+ return REQUIRED_METRICS;
+ }
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/DeveloperPerformanceStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/DeveloperPerformanceStrategy.java
new file mode 100644
index 00000000..78f310bb
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/DeveloperPerformanceStrategy.java
@@ -0,0 +1,89 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+/**
+ * Strategy for the calculation of a developer performance comparing him with
+ * the rest of developers
+ *
+ * @author fracrusan (year 23/24)
+ * @author Isabel Román RECUERDA: los indicadores tienen que estar incluidos en
+ * el fichero de configuración a4iDefault.json
+ */
+public class DeveloperPerformanceStrategy implements IndicatorStrategy {
+
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+ // M�tricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("issuesLastMonth", "closedIssuesLastMonth",
+ "issues4DevLastMonth", "meanClosedIssuesLastMonth");
+
+ @Override
+ public ReportItemI calcIndicator(List metrics) throws NotAvailableMetricException {
+ // Se obtienen y se comprueba que se pasan las m�tricas necesarias para calcular
+ // el indicador.
+ Optional> issuesLastMonth = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(0).equals(((ReportItemI) m).getName())).findAny();
+ Optional> closedIssuesLastMonth = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(1).equals(((ReportItemI) m).getName())).findAny();
+ Optional> issues4DevLastMonth = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(2).equals(((ReportItemI) m).getName())).findAny();
+ Optional> meanClosedIssuesLastMonth = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(3).equals(((ReportItemI) m).getName())).findAny();
+ ReportItemI indicatorReport = null;
+
+ if (issuesLastMonth.isPresent() && closedIssuesLastMonth.isPresent() && issues4DevLastMonth.isPresent()
+ && meanClosedIssuesLastMonth.isPresent()) {
+ Double rendimientoMiembro;
+
+ // calculating indicator
+ if (issuesLastMonth.get().getValue() != 0 && issues4DevLastMonth.get().getValue() != 0
+ && meanClosedIssuesLastMonth.get().getValue() != 0)
+ rendimientoMiembro = (closedIssuesLastMonth.get().getValue() / issuesLastMonth.get().getValue())
+ / (meanClosedIssuesLastMonth.get().getValue() / issues4DevLastMonth.get().getValue());
+ else if (meanClosedIssuesLastMonth.get().getValue() != 0)
+ rendimientoMiembro = 1.0;
+ else
+ rendimientoMiembro = 0.0;
+
+ try {
+ // Se crea el indicador
+ indicatorReport = new ReportItem.ReportItemBuilder("developerPerformance", rendimientoMiembro)
+ .metrics(Arrays.asList(issuesLastMonth.get(), closedIssuesLastMonth.get(),
+ issues4DevLastMonth.get(), meanClosedIssuesLastMonth.get()))
+ .indicator(IndicatorState.UNDEFINED).build();
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder.");
+ e.printStackTrace();
+ }
+
+ } else {
+ log.info("No se han proporcionado las m�tricas necesarias");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+ }
+
+ @Override
+ public List requiredMetrics() {
+ // Para calcular el indicador "rendimientoMiembro", ser�n necesarias las
+ // m�tricas
+ // "openIssues" y "closedIssues".
+ return REQUIRED_METRICS;
+ }
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/FixTimeStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/FixTimeStrategy.java
new file mode 100644
index 00000000..7014d677
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/FixTimeStrategy.java
@@ -0,0 +1,84 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+/**
+ *
+ */
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+/**
+ * Estrategia de indicador equipo 6 del curso 23/24, no coincide con lo que
+ * decÃan ni las métricas están incluidas en ningún Enquirer Aparece una clase
+ * Equirer MetricasG6.java pero es una copia incompleta del que se les da y no
+ * añade los indicadores que aquà aparecen
+ * REMEMBER: metrics and indicators must be included in a4iDefault.json
+ */
+
+public class FixTimeStrategy implements IndicatorStrategy {
+
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+
+ // M�tricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("clasificacion", "correccion", "num_errores");
+
+ @Override
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException {
+ // Se obtienen y se comprueba que se pasan las m�tricas necesarias para calcular
+ // el indicador.
+ Optional> clasificacion = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(0).equals(m.getName())).findAny();
+ Optional> correccion = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(1).equals(m.getName())).findAny();
+ Optional> num_errores = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(2).equals(m.getName())).findAny();
+ ReportItemI indicatorReport = null;
+
+ if (clasificacion.isPresent() && correccion.isPresent() && num_errores.isPresent()) {
+ Double procesoDeIssues;
+
+ // Se realiza el c�lculo del indicador
+ if (clasificacion.get().getValue() != 0 && correccion.get().getValue() != 0
+ && num_errores.get().getValue() != 0)
+ procesoDeIssues = (clasificacion.get().getValue() + correccion.get().getValue())
+ / num_errores.get().getValue();
+ else
+ procesoDeIssues = 0.0;
+
+ try {
+ // Se crea el indicador
+ indicatorReport = new ReportItem.ReportItemBuilder("fixTime", procesoDeIssues)
+ .metrics(Arrays.asList(clasificacion.get(), correccion.get(), num_errores.get()))
+ .indicator(IndicatorState.UNDEFINED).build();
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder.");
+ e.printStackTrace();
+ }
+
+ } else {
+ log.info("No se han proporcionado las m�tricas necesarias");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+ }
+
+ @Override
+ public List requiredMetrics() {
+ // Para calcular el indicador "IssuesRatio", ser�n necesarias las m�tricas
+ // "openIssues" y "closedIssues".
+ return REQUIRED_METRICS;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/IEFStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/IEFStrategy.java
new file mode 100644
index 00000000..627c8127
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/IEFStrategy.java
@@ -0,0 +1,86 @@
+package us.muit.fs.a4i.control.strategies;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.Collection;
+
+
+/**
+ * Estrategia para calcular el Ãndice de Eficiencia del Flujo (IEF).
+ */
+public class IEFStrategy implements IndicatorStrategy {
+ private static final Logger log = Logger.getLogger(IEFStrategy.class.getName());
+
+ private static final List REQUIRED = List.of(
+ "cycleTime", "waitTime", "throughput", "WIP"
+ );
+
+ private final double w1 = 0.25, w2 = 0.25, w3 = 0.25, w4 = 0.25;
+ private final double maxC = 160.0, maxW = 80.0, maxT = 50.0, maxP = 20.0;
+
+ @Override
+ public ReportItemI calcIndicator(List> metrics)
+ throws NotAvailableMetricException {
+ log.info("Calculando IEF con métricas: " + metrics);
+ Map m = metrics.stream()
+ .collect(Collectors.toMap(ReportItemI::getName, ReportItemI::getValue));
+
+ for (String req : REQUIRED) {
+ if (!m.containsKey(req)) {
+ throw new NotAvailableMetricException("Falta métrica " + req);
+ }
+ }
+
+ double cycle = m.get("cycleTime"),
+ wait = m.get("waitTime"),
+ thr = m.get("throughput"),
+ wip = m.get("WIP");
+
+ double normC = clamp(cycle / maxC),
+ normW = clamp(wait / maxW),
+ normT = clamp(thr / maxT),
+ normP = clamp(wip / maxP);
+
+ double score = w1 * (1 - normC)
+ + w2 * (1 - normW)
+ + w3 * normT
+ + w4 * (1 - normP);
+
+ IndicatorState state = classify(score);
+
+ try {
+ return new ReportItem.ReportItemBuilder("IEF", score)
+ .metrics((Collection) metrics)
+ .indicator(state)
+ .build();
+ } catch (ReportItemException e) {
+ throw new NotAvailableMetricException("Error building IEF ReportItem: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public List requiredMetrics() {
+ return REQUIRED;
+ }
+
+ private double clamp(double v) {
+ return v < 0 ? 0 : (v > 1 ? 1 : v);
+ }
+
+ private IndicatorState classify(double x) {
+ if (x >= 0.8) return IndicatorState.OK;
+ if (x >= 0.6) return IndicatorState.OK;
+ if (x >= 0.4) return IndicatorState.WARNING;
+ return IndicatorState.CRITICAL;
+ }
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/IssuesRatioIndicatorStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/IssuesRatioIndicatorStrategy.java
new file mode 100644
index 00000000..38f62f4c
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/IssuesRatioIndicatorStrategy.java
@@ -0,0 +1,70 @@
+package us.muit.fs.a4i.control.strategies;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+/**
+ * @author alumnos del curso 23/24, grupo 3 RECUERDA: los indicadores tienen que
+ * estar incluidos en el fichero de configuración a4iDefault.json
+ */
+public class IssuesRatioIndicatorStrategy implements IndicatorStrategy {
+
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+
+ // M�tricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("openIssues", "closedIssues");
+
+ @Override
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException {
+ // Se obtienen y se comprueba que se pasan las m�tricas necesarias para calcular
+ // el indicador.
+ Optional> openIssues = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(0).equals(m.getName())).findAny();
+ Optional> closedIssues = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(1).equals(m.getName())).findAny();
+ ReportItemI indicatorReport = null;
+
+ if (openIssues.isPresent() && closedIssues.isPresent()) {
+ Double issuesRatio;
+
+ // Se realiza el c�lculo del indicador
+ if (closedIssues.get().getValue() != 0)
+ issuesRatio = openIssues.get().getValue() / closedIssues.get().getValue();
+ else
+ issuesRatio = openIssues.get().getValue();
+
+ try {
+ // Se crea el indicador
+ indicatorReport = new ReportItem.ReportItemBuilder("issuesRatio", issuesRatio)
+ .metrics(Arrays.asList(openIssues.get(), closedIssues.get()))
+ .indicator(IndicatorState.UNDEFINED).build();
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder.");
+ e.printStackTrace();
+ }
+
+ } else {
+ log.info("No se han proporcionado las m�tricas necesarias");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+ }
+
+ @Override
+ public List requiredMetrics() {
+ // Para calcular el indicador "IssuesRatio", ser�n necesarias las m�tricas
+ // "openIssues" y "closedIssues".
+ return REQUIRED_METRICS;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/PRPerformanceStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/PRPerformanceStrategy.java
new file mode 100644
index 00000000..e6c8ab9f
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/PRPerformanceStrategy.java
@@ -0,0 +1,92 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+/**
+ * Strategy for the calculation of the indicator PRPerformance
+ * REMEMBER: metrics must be included in a4iDefault.json
+ */
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+public class PRPerformanceStrategy implements IndicatorStrategy {
+
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+
+ // M�tricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("pullRequestsAcceptedLastYear",
+ "pullRequestsAcceptedLastMonth", "pullRequestsRejectedLastMonth", "pullRequestsRejectedLastYear");
+
+ @Override
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException {
+
+ // Obtener las métricas necesarias
+ Optional> pullRequestsAcceptedLastYear = metrics.stream()
+ .filter(m -> "pullRequestsAcceptedLastYear".equals(m.getName())).findAny();
+ Optional> pullRequestsAcceptedLastMonth = metrics.stream()
+ .filter(m -> "pullRequestsAcceptedLastMonth".equals(m.getName())).findAny();
+ Optional> pullRequestsRejectedLastYear = metrics.stream()
+ .filter(m -> "pullRequestsRejectedLastYear".equals(m.getName())).findAny();
+ Optional> pullRequestsRejectedLastMonth = metrics.stream()
+ .filter(m -> "pullRequestsRejectedLastMonth".equals(m.getName())).findAny();
+
+ ReportItemI indicatorReport = null;
+
+ // Comprobar que todas las métricas necesarias están presentes
+ if (pullRequestsAcceptedLastYear.isPresent() && pullRequestsAcceptedLastMonth.isPresent()
+ && pullRequestsRejectedLastYear.isPresent() && pullRequestsRejectedLastMonth.isPresent()) {
+
+ // Obtener los valores de las métricas
+ Double acceptedLastYear = pullRequestsAcceptedLastYear.get().getValue();
+ Double acceptedLastMonth = pullRequestsAcceptedLastMonth.get().getValue();
+ Double rejectedLastYear = pullRequestsRejectedLastYear.get().getValue();
+ Double rejectedLastMonth = pullRequestsRejectedLastMonth.get().getValue();
+
+ // Calcular el ratio de issues
+ Double pullRequestsAcceptance = 0.0;
+ if (acceptedLastYear != 0 && acceptedLastMonth != 0) {
+ pullRequestsAcceptance = rejectedLastYear / acceptedLastYear - rejectedLastMonth / acceptedLastMonth;
+ } else {
+ // Si una compañÃa productora de software no ha hecho un PR en el último mes,
+ // mal va.
+ pullRequestsAcceptance = 1.0;
+ }
+
+ try {
+ // Crear el indicador
+ indicatorReport = new ReportItem.ReportItemBuilder("PRPerformance", pullRequestsAcceptance)
+ .metrics(Arrays.asList(pullRequestsAcceptedLastYear.get(), pullRequestsAcceptedLastMonth.get(),
+ pullRequestsRejectedLastYear.get(), pullRequestsRejectedLastMonth.get()))
+ .indicator(IndicatorState.OK).build();
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder.");
+ e.printStackTrace();
+ }
+
+ } else {
+ log.info("No se han proporcionado las métricas necesarias");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+ }
+
+ @Override
+ public List requiredMetrics() {
+ // Para calcular el indicador "IssuesRatio", ser�n necesarias las m�tricas
+ // "openIssues" y "closedIssues".
+ return REQUIRED_METRICS;
+ }
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/PullRequestIndicatorStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/PullRequestIndicatorStrategy.java
new file mode 100644
index 00000000..f83562e9
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/PullRequestIndicatorStrategy.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+/**
+ * % de pull requests cerrados, sobre el total
+ *
+ * @author Sergio GarcÃa López (equipo 4 del curso 23/24) RECUERDA: los
+ * indicadores tienen que estar incluidos en el fichero de configuración
+ * a4iDefault.json
+ *
+ */
+public class PullRequestIndicatorStrategy implements IndicatorStrategy {
+ private static Logger log = Logger.getLogger(PullRequestIndicatorStrategy.class.getName());
+
+ // Métricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("totalPullReq", "closedPullReq");
+
+ @Override
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException {
+
+ // Indicador a devolver
+ ReportItemI indicatorReport = null;
+
+ // Estado del indicador
+ IndicatorState estado = IndicatorState.UNDEFINED;
+
+ Optional> totalPullReq = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(0).equals(m.getName())).findAny();
+ Optional> closedPullReq = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(1).equals(m.getName())).findAny();
+
+ if (totalPullReq.isPresent() && closedPullReq.isPresent()) {
+
+ // Calculamos el indicador
+ Double pullRequestCompletion = 0.0;
+
+ if (totalPullReq.get().getValue() > 0) {
+ pullRequestCompletion = 100 * closedPullReq.get().getValue() / totalPullReq.get().getValue();
+
+ // Criterios de calidad (porcentuales)
+ // estos lÃmites deben estar configurados en el fichero a4iDefault.json, no aquÃ
+ if (pullRequestCompletion > 75) {
+ estado = IndicatorState.OK;
+ } else if (pullRequestCompletion > 50) {
+ estado = IndicatorState.WARNING;
+ } else {
+ estado = IndicatorState.CRITICAL;
+ }
+ }
+
+ try {
+
+ indicatorReport = new ReportItem.ReportItemBuilder("pullRequestCompletion",
+ pullRequestCompletion).metrics(Arrays.asList(totalPullReq.get(), closedPullReq.get()))
+ .indicator(estado).build();
+
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder: " + e);
+ }
+
+ } else {
+ log.info("Falta alguna de las métricas");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+
+ }
+
+ @Override
+ public List requiredMetrics() {
+ return REQUIRED_METRICS;
+ }
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/RepoActivityStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/RepoActivityStrategy.java
new file mode 100644
index 00000000..82ce0fc8
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/RepoActivityStrategy.java
@@ -0,0 +1,124 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+/**
+ * Clase para calcular el indicador compuesto de issues, pull requests y
+ * contribuyentes.
+ *
+ * @param Tipo de dato del indicador.
+ */
+public class RepoActivityStrategy implements IndicatorStrategy {
+ private static Logger log = Logger.getLogger(RepoActivityStrategy.class.getName());
+
+ // Métricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("closedIssues", "issues", "closedPullReq",
+ "totalPullReq", "activeContributor", "totalContributor");
+
+ @Override
+ public ReportItemI calcIndicator(List> metricas) throws NotAvailableMetricException {
+
+ // Variables para almacenar las métricas
+ ReportItemI issuesCerrados = null;
+ ReportItemI issuesTotales = null;
+ ReportItemI pullRequestsCerrados = null;
+ ReportItemI pullRequestsTotales = null;
+ ReportItemI contribuyentesActivos = null;
+ ReportItemI contribuyentesTotales = null;
+
+ // Indicador a devolver
+ ReportItemI indicatorReport = null;
+
+ // Estado del indicador
+ IndicatorState estado = IndicatorState.UNDEFINED;
+
+ // Buscamos las métricas en la lista
+ for (ReportItemI metrica : metricas) {
+ switch (metrica.getName()) {
+ case "closedIssues":
+ issuesCerrados = metrica;
+ break;
+ case "issues":
+ issuesTotales = metrica;
+ break;
+ case "closedPullReq":
+ pullRequestsCerrados = metrica;
+ break;
+ case "totalPullReq":
+ pullRequestsTotales = metrica;
+ break;
+ case "activeContributor":
+ contribuyentesActivos = metrica;
+ break;
+ case "totalContributor":
+ contribuyentesTotales = metrica;
+ break;
+ }
+ }
+
+ if (issuesCerrados != null && issuesTotales != null && pullRequestsCerrados != null
+ && pullRequestsTotales != null && contribuyentesActivos != null && contribuyentesTotales != null) {
+
+ // Verificamos que los valores totales no sean cero para evitar divisiones por
+ // cero
+ if (issuesTotales.getValue() == 0 || pullRequestsTotales.getValue() == 0
+ || contribuyentesTotales.getValue() == 0) {
+ throw new NotAvailableMetricException("Los valores totales no pueden ser cero.");
+ }
+
+ // Calculamos el indicador
+ double issuesRatio = (issuesCerrados.getValue() / issuesTotales.getValue()) * 40;
+ double pullRequestsRatio = (pullRequestsCerrados.getValue() / pullRequestsTotales.getValue()) * 40;
+ double contribuyentesRatio = (contribuyentesActivos.getValue() / contribuyentesTotales.getValue()) * 20;
+
+ double indicador = issuesRatio + pullRequestsRatio + contribuyentesRatio;
+
+ // Criterios de calidad
+ if (indicador >= 90) {
+ estado = IndicatorState.OK;
+ } else if (indicador >= 80) {
+ estado = IndicatorState.WARNING;
+ } else if (indicador >= 70) {
+ estado = IndicatorState.WARNING;
+ } else if (indicador >= 50) {
+ estado = IndicatorState.CRITICAL;
+ } else if (indicador >= 26) {
+ estado = IndicatorState.CRITICAL;
+ } else {
+ estado = IndicatorState.UNDEFINED;
+ }
+
+ try {
+ indicatorReport = new ReportItem.ReportItemBuilder("repoActivity", indicador)
+ .metrics(Arrays.asList(issuesCerrados, issuesTotales, pullRequestsCerrados, pullRequestsTotales,
+ contribuyentesActivos, contribuyentesTotales))
+ .indicator(estado).build();
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder: " + e);
+ }
+
+ } else {
+ log.info("Falta alguna de las métricas");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+ }
+
+ @Override
+ public List requiredMetrics() {
+ return REQUIRED_METRICS;
+ }
+}
diff --git a/src/main/java/us/muit/fs/a4i/control/strategies/TeamsBalanceStrategy.java b/src/main/java/us/muit/fs/a4i/control/strategies/TeamsBalanceStrategy.java
new file mode 100644
index 00000000..5c568713
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/control/strategies/TeamsBalanceStrategy.java
@@ -0,0 +1,79 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.control.strategies;
+
+import us.muit.fs.a4i.control.IndicatorStrategy;
+/**
+ *
+ */
+import us.muit.fs.a4i.exceptions.NotAvailableMetricException;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Indicator;
+import us.muit.fs.a4i.model.entities.IndicatorI.IndicatorState;
+
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItemI;
+
+import java.util.logging.Logger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.lang.Math;
+import java.lang.Double;
+
+public class TeamsBalanceStrategy implements IndicatorStrategy {
+
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+
+ // M�tricas necesarias para calcular el indicador
+ private static final List REQUIRED_METRICS = Arrays.asList("teamsBalance", "repositories");
+
+ @Override
+ public ReportItemI calcIndicator(List> metrics) throws NotAvailableMetricException {
+ // Se obtienen y se comprueba que se pasan las m�tricas necesarias para calcular
+ // el indicador.
+ Optional> teamsBalance = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(0).equals(m.getName())).findAny();
+ Optional> repositories = metrics.stream()
+ .filter(m -> REQUIRED_METRICS.get(1).equals(m.getName())).findAny();
+ ReportItemI indicatorReport = null;
+ log.info("Teamsbalance: " + teamsBalance.toString());
+ log.info("Repositories: " + repositories.toString());
+ if (teamsBalance.isPresent() && repositories.isPresent()) {
+ Double teamsBalanceResult;
+
+ // Se realiza el c�lculo del indicador
+ teamsBalanceResult = (Double) teamsBalance.get().getValue() * 100 / repositories.get().getValue();
+
+ log.info("teamsBalanceResult: " + teamsBalanceResult.toString());
+ try {
+ // Se crea el indicador
+ // No se entiende por qué el indicador tiene el mismo nombere que una de las
+ // métricas
+ indicatorReport = new ReportItem.ReportItemBuilder("teamsBalance", teamsBalanceResult)
+ .metrics(Arrays.asList(teamsBalance.get(), repositories.get()))
+ .indicator(IndicatorState.UNDEFINED).build();
+
+ log.info("IndicatorReport: " + indicatorReport.toString());
+ } catch (ReportItemException e) {
+ log.info("Error en ReportItemBuilder.");
+ e.printStackTrace();
+ }
+
+ } else {
+ log.info("No se han proporcionado las métricas necesarias");
+ throw new NotAvailableMetricException(REQUIRED_METRICS.toString());
+ }
+
+ return indicatorReport;
+ }
+
+ @Override
+ public List requiredMetrics() {
+ // Para calcular el indicador "IssuesRatio", ser�n necesarias las m�tricas
+ // "openIssues" y "closedIssues".
+ return REQUIRED_METRICS;
+ }
+}
diff --git a/src/main/java/us/muit/fs/a4i/exceptions/IndicatorException.java b/src/main/java/us/muit/fs/a4i/exceptions/IndicatorException.java
index f8da006b..1e714cbe 100644
--- a/src/main/java/us/muit/fs/a4i/exceptions/IndicatorException.java
+++ b/src/main/java/us/muit/fs/a4i/exceptions/IndicatorException.java
@@ -1,28 +1,32 @@
package us.muit.fs.a4i.exceptions;
/**
- * @author Isabel Román
+ * @author Isabel Román
*
*/
public class IndicatorException extends Exception {
- /**
- * Excepción que indica que se está intentando recuperar una entidad sin haber establecido su id
+ /**
+ * Excepción al manejar Indicador
*/
private static final long serialVersionUID = 1L;
/**
- * Información sobre el error
+ * Información sobre el error
*/
private String message;
+
/**
- * Constructor
+ *
+ * Constructor
+ *
+ *
* @param info Mensaje definiendo el error
*/
- public IndicatorException(String info){
- message=info;
+ public IndicatorException(String info) {
+ message = info;
}
@Override
- public String getMessage(){
- return message;
- }
+ public String getMessage() {
+ return message;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/exceptions/MetricException.java b/src/main/java/us/muit/fs/a4i/exceptions/MetricException.java
index cfbe3837..84cef6fe 100644
--- a/src/main/java/us/muit/fs/a4i/exceptions/MetricException.java
+++ b/src/main/java/us/muit/fs/a4i/exceptions/MetricException.java
@@ -1,28 +1,32 @@
package us.muit.fs.a4i.exceptions;
/**
- * @author Isabel Román
+ * @author Isabel Román
*
*/
-public class MetricException extends Exception {
- /**
- * Excepción que indica que se está intentando recuperar una entidad sin haber establecido su id
+public class MetricException extends RuntimeException {
+ /**
+ * Excepción al manejar métrica
*/
private static final long serialVersionUID = 1L;
/**
- * Información sobre el error
+ * Información sobre el error
*/
private String message;
+
/**
- * Constructor
+ *
+ * Constructor
+ *
+ *
* @param info Mensaje definiendo el error
*/
- public MetricException(String info){
- message=info;
+ public MetricException(String info) {
+ message = info;
}
@Override
- public String getMessage(){
- return message;
- }
+ public String getMessage() {
+ return message;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/exceptions/NotAvailableMetricException.java b/src/main/java/us/muit/fs/a4i/exceptions/NotAvailableMetricException.java
new file mode 100644
index 00000000..d704b701
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/exceptions/NotAvailableMetricException.java
@@ -0,0 +1,29 @@
+package us.muit.fs.a4i.exceptions;
+
+public class NotAvailableMetricException extends Exception{
+
+ /**
+ * Excepcion que ocurre cuando se quiere calcular un indicador pero no se proporcionan las m�tricas adecuadas.
+ */
+ private static final long serialVersionUID = 1L;
+ /**
+ * Informacion sobre el error
+ */
+ private String message;
+
+ /**
+ *
+ * Constructor
+ *
+ *
+ * @param info Mensaje definiendo el error
+ */
+ public NotAvailableMetricException(String info) {
+ message = "No se dispone de las métricas necesiarias " + info;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/exceptions/ReportItemException.java b/src/main/java/us/muit/fs/a4i/exceptions/ReportItemException.java
new file mode 100644
index 00000000..0ad53e37
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/exceptions/ReportItemException.java
@@ -0,0 +1,32 @@
+package us.muit.fs.a4i.exceptions;
+
+/**
+ * @author Isabel Román
+ *
+ */
+public class ReportItemException extends Exception {
+ /**
+ * Excepción al manejar ReportItem
+ */
+ private static final long serialVersionUID = 1L;
+ /**
+ * Información sobre el error
+ */
+ private String message;
+
+ /**
+ *
+ * Constructor
+ *
+ *
+ * @param info Mensaje definiendo el error
+ */
+ public ReportItemException(String info) {
+ message = info;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/exceptions/ReportNotDefinedException.java b/src/main/java/us/muit/fs/a4i/exceptions/ReportNotDefinedException.java
index f5bd135e..fae3bc0a 100644
--- a/src/main/java/us/muit/fs/a4i/exceptions/ReportNotDefinedException.java
+++ b/src/main/java/us/muit/fs/a4i/exceptions/ReportNotDefinedException.java
@@ -8,13 +8,14 @@
*
*/
public class ReportNotDefinedException extends Exception {
- /**
- * Excepción que indica que se está intentando recuperar una entidad sin haber establecido su id
+ /**
+ * Excepción que indica que se está intentando recuperar una entidad sin haber
+ * establecido su id
*/
private static final long serialVersionUID = 1L;
@Override
- public String getMessage(){
- return "No se ha establecido aún un informe";
- }
+ public String getMessage() {
+ return "No se ha establecido aún un informe";
+ }
}
diff --git a/src/main/java/us/muit/fs/a4i/exceptions/package-info.java b/src/main/java/us/muit/fs/a4i/exceptions/package-info.java
index 95b08f69..868de094 100644
--- a/src/main/java/us/muit/fs/a4i/exceptions/package-info.java
+++ b/src/main/java/us/muit/fs/a4i/exceptions/package-info.java
@@ -1,8 +1,9 @@
/**
- * Excepciones propias de la aplicación
- *
- * @author Isabel Román
- * @version 0.0
+ *
+ * Excepciones propias de la aplicación
+ *
+ *
+ * @author Isabel Román
+ * @version V.0.2
*/
package us.muit.fs.a4i.exceptions;
-
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/Font.java b/src/main/java/us/muit/fs/a4i/model/entities/Font.java
new file mode 100644
index 00000000..f0024ecd
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/model/entities/Font.java
@@ -0,0 +1,75 @@
+package us.muit.fs.a4i.model.entities;
+import java.awt.Color;
+import java.util.logging.Logger;
+
+
+public class Font {
+ private static Logger log = Logger.getLogger(Font.class.getName());
+ private Color color;
+ private java.awt.Font font;
+ /**
+ * Todos los valores por defecto
+ */
+ public Font() {
+ this.color = Color.black;
+ this.font = new java.awt.Font ("Serif", java.awt.Font.PLAIN , 10);
+ }
+ /**
+ * Personalizando el color
+ * @param color color
+ */
+ public Font (String color) {
+ this.font = new java.awt.Font ("Serif", java.awt.Font.PLAIN , 10);
+ setColor(color);
+ }
+ /**
+ * Todos los Valores personalizados salvo el estilo
+ * @param family tipo de letra
+ * @param size tamaño
+ * @param color color
+ */
+ public Font (String family, int size, String color) {
+ log.info("Creando fuente con valores familia "+family+" tamano "+size+" color "+color);
+ this.font=new java.awt.Font (family.toLowerCase(), java.awt.Font.PLAIN , size);
+ setColor(color);
+ log.info("Se ha creado fuente con el tipo "+font.getFamily()+" y el color "+color);
+ }
+ /**
+ * Todos los Valores personalizados
+ * @param family tipo de letra
+ * @param format formato
+ * @param size tamaño
+ * @param color color
+ */
+ public Font (String family, int style, int size, String color) {
+ this.font=new java.awt.Font (family.toLowerCase(), style , size);
+ setColor(color);
+ }
+
+ public Color getColor() {
+ return this.color;
+ }
+ public java.awt.Font getFont() {
+ return this.font;
+ }
+
+ private void setColor(String color) {
+ switch(color.toLowerCase()){
+ case "red","rojo":
+ this.color=Color.RED;
+ break;
+ case "green","verde":
+ this.color=Color.GREEN;
+ break;
+ case "blue","azul":
+ this.color=Color.BLUE;
+ break;
+ case "orange","naranja":
+ this.color=Color.ORANGE;
+ break;
+ default:
+ this.color=Color.BLACK;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/Indicator.java b/src/main/java/us/muit/fs/a4i/model/entities/Indicator.java
index f8af021b..a1e10a9e 100644
--- a/src/main/java/us/muit/fs/a4i/model/entities/Indicator.java
+++ b/src/main/java/us/muit/fs/a4i/model/entities/Indicator.java
@@ -3,167 +3,60 @@
*/
package us.muit.fs.a4i.model.entities;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
+import java.util.Collection;
import java.util.Date;
import java.util.logging.Logger;
-
/**
- * @author Isabel Román
+ * @author Isabel Román
*
*/
-public class Indicator {
- private static Logger log=Logger.getLogger(Indicator.class.getName());
- private Date date;
- private String source;
- private String description;
- private String name;
- private T value;
- private String unit;
- private State state;
+public class Indicator implements IndicatorI{
+ private static Logger log = Logger.getLogger(Indicator.class.getName());
+ private Collection metrics;
+ private IndicatorState state;
/**
- * Estados posibles del indicador, indican el grado de atención que requiere por parte del analista
- * @author Isabel Román
- *
- */
- public static enum State{
- OK,
- WARNING,
- CRITICAL
- };
- /**
- * Constructor privado, para construir desde fuera hay que usar el método build de IndicatorBuilder. Implementación patrón constructor
- * @param builder Clase constructora
- */
- private Indicator(IndicatorBuilder builder){
-
- this.description=builder.description;
- this.name=builder.name;
- this.value=builder.value;
- this.source=builder.source;
- this.unit=builder.unit;
- this.date=builder.date;
- this.state=builder.state;
- }
- /**
- *
- * @return Descripción del indicador
- */
- public String getDescription() {
- return description;
- }
- /**
- *
- * @return Nombre del indicador
+ * Constructor
*/
- public String getName() {
- return name;
+ public Indicator() {
+ this.state = IndicatorState.UNDEFINED;
}
+
/**
- *
- * @return Unidades de medida del indicador
+ * @param state Estado del nuevo indicador
+ * @param metrics Colección de métricas en las que se basa el indicador
*/
- public String getUnit() {
- return unit;
+ public Indicator(IndicatorState state, Collection metrics) {
+ this.metrics = metrics;
+ this.state = state;
}
- /**
- *
- * @return Valor del indicador
- */
- public T getValue() {
- return value;
+
+ public void setMetrics(Collection metrics) {
+ this.metrics = metrics;
}
- /**
- * Clase constructora, se usará el método build para crear un objeto Indicator desde fuera
- * @author Isabel Román
- *
- * @param Tipo utilizado en el valor del indicador que va a construir
- */
- public static class IndicatorBuilder{
- private String description;
- private String name;
- private Date date;
- private T value;
- private String source;
- private String unit;
- private State state;
- /**
- * Constructor de la clase constructora, recibe los parámetros obligatgorios nombre y valor del indicador
- * @param indicatorName Nombre del indicador
- * @param indicatorValue Valor del indicador
- */
- public IndicatorBuilder(String indicatorName, T indicatorValue) {
- this.name=indicatorName;
- this.value=indicatorValue;
- this.date=Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
- }
- /**
- * Establece la descripción en el constructor
- * @param description descripción del indicador
- * @return el objeto constructor
- */
- public IndicatorBuilder description(String description){
- this.description=description;
- return this;
- }
- /**
- *
- * @param source Fuente de la que se obtuvo el indicador
- * @return el objeto constructor
- */
- public IndicatorBuilder source(String source){
- this.source=source;
- return this;
- }
- /**
- *
- * @param unit Unidad de medida del indicador
- * @return el objeto constructor
- */
- public IndicatorBuilder unit(String unit){
- this.unit=unit;
- return this;
- }
- /**
- *
- * @param state Estado del indicador. Grado de atención que necesita por parte del analista
- * @return el objeto constructor
- */
- public IndicatorBuilder state(State state){
- this.state=state;
- return this;
- }
- /**
- * Método de construcción del indicador, patrón constructor
- * @return El indicador construido
- */
- public Indicator build(){
- return new Indicator(this);
- }
+
+ public void setState(IndicatorState state) {
+ this.state = state;
}
+
@Override
public String toString() {
String info;
- info="Indicador para "+description+", con valor=" + value + ", source=" + source
- + ", unit=" + unit +" fecha de cálculo= "+ date+" Estado= "+state;
+ info = "Indicador estado " + state + ", a partir de las metricas: " + metrics;
return info;
}
- /**
- *
- * @return Fecha de creación del indicador
- */
- public Date getDate() {
- return date;
+
+ @Override
+ public IndicatorState getState() {
+
+ return state;
}
-
- /**
- *
- * @return Fuente de los datos para obtener el indicador
- */
- public String getSource() {
- return source;
+
+ @Override
+ public Collection getMetrics() {
+
+ return metrics;
}
-
+
}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/IndicatorI.java b/src/main/java/us/muit/fs/a4i/model/entities/IndicatorI.java
new file mode 100644
index 00000000..75385477
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/model/entities/IndicatorI.java
@@ -0,0 +1,54 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.model.entities;
+
+import java.util.Collection;
+
+/**
+ * @author Isabel Román Interfaz para manejar los indicadores
+ *
+ */
+public interface IndicatorI {
+ /**
+ *
+ * Estados posibles del indicador, indican el grado de atención que requiere por
+ * parte del analista
+ *
+ *
+ * @author Isabel Román
+ *
+ */
+ public static enum IndicatorState {
+ OK, WARNING, CRITICAL, UNDEFINED
+ }
+
+ /**
+ * Devuelve el estado en el que se encuentra este indicador
+ *
+ * @return estado del indicador
+ */
+ public IndicatorState getState();
+
+ /**
+ * Devuelve el conjunto de métricas en las que se basa este indicador
+ *
+ * @return colección de métricas en las que se basa el indicador
+ */
+ public Collection getMetrics();
+
+ /**
+ * Establece el conjunto de métricas en las que se basa este indicador
+ *
+ * @param metrics conjunto de métricas en las que se basa el indicador
+ */
+ public void setMetrics(Collection metrics);
+
+ /**
+ * Establece el estado en el que se encuentra este indicador
+ *
+ * @param state, estado del indicador
+ */
+ public void setState(IndicatorState state);
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/Metric.java b/src/main/java/us/muit/fs/a4i/model/entities/Metric.java
deleted file mode 100644
index 44dfd0c9..00000000
--- a/src/main/java/us/muit/fs/a4i/model/entities/Metric.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- *
- */
-package us.muit.fs.a4i.model.entities;
-
-import java.io.IOException;
-import java.time.LocalDateTime;
-
-import java.time.ZoneOffset;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.logging.Logger;
-
-import us.muit.fs.a4i.config.Context;
-import us.muit.fs.a4i.exceptions.MetricException;
-
-/**
- * @author Isabel Román
- *
- */
-public class Metric {
- private static Logger log=Logger.getLogger(Metric.class.getName());
- /**
- * Obligatorio
- */
- private String name;
- /**
- * Obligatorio
- */
- private T value;
- /**
- * Obligatorio
- * Fecha en la que se tomó la medida (por defecto cuando se crea el objeto)
- */
- private Date date;
-
- private String description;
- private String source;
- private String unit;
- /**
- * Construye un objeto métrica a partir de un constructor, previamente configurado
- * Sólo lo utiliza el propio constructor, es privado, nadie, que no sea el constructor, puede crear una métrica
- * @param builder Constructor de la métrica
- */
- private Metric(MetricBuilder builder){
-
- this.description=builder.description;
- this.name=builder.name;
- this.value=builder.value;
- this.source=builder.source;
- this.unit=builder.unit;
- this.date=builder.date;
- }
-
- /**
- * Obtiene la descripción de la métrica
- * @return Descripción del significado de la métrica
- */
- public String getDescription() {
- return description;
- }
-
-
- /**
- * Consulta el nombre de la métrica
- * @return Nombre de la métrica
- */
- public String getName() {
- return name;
- }
- /**
- * Consulta el valor de la métrica
- * @return Medida
- */
- public T getValue() {
- return value;
- }
- /**
- * Consulta la fuente de información
- * @return Origen de la medida
- */
- public String getSource() {
- return source;
- }
- /***
- * Establece la fuente de la información para la medida
- * @param source fuente de información origen
- */
- public void setSource(String source) {
- this.source = source;
- }
- /**
- * Consulta las unidades de medida
- * @return la unidad usada en la medida
- */
- public String getUnit() {
- return unit;
- }
-
- /**
- * Consulta cuando se obtuvo la métrica
- * @return Fecha de consulta de la métrica
- */
- public Date getDate() {
- return date;
- }
-
- /**
- * Clase para construir métricas. Verifica las métricas antes de crearlas
- *
- */
- public static class MetricBuilder{
- private String description;
- private String name;
- private Date date;
- private T value;
- private String source;
- private String unit;
- public MetricBuilder(String metricName, T metricValue) throws MetricException {
- HashMap metricDefinition=null;
- //el nombre incluye java.lang, si puede eliminar si se manipula la cadena
- //hay que quedarse sólo con lo que va detrás del último punto o meter en el fichero el nombre completo
- //Pero ¿y si se usan tipos definidos en otras librerías? usar el nombre completo "desambigua" mejor
- log.info("Verifico La métrica de nombre "+metricName+" con valor de tipo "+metricValue.getClass().getName());
- try {
- metricDefinition=Context.getContext().getChecker().definedMetric(metricName,metricValue.getClass().getName());
-
- if(metricDefinition!=null) {
- this.name=metricName;
- this.value=metricValue;
- this.date=Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
- this.description=metricDefinition.get("description");
- this.unit=metricDefinition.get("unit");
- }else {
- throw new MetricException("Métrica "+metricName+" no definida o tipo "+metricValue.getClass().getName()+" incorrecto");
- }
- }catch(IOException e) {
- throw new MetricException("El fichero de configuración de métricas no se puede abrir");
- }
-
-
- }
- /**
- * Establece la descripción de la métrica
- * @param description Breve descripción del significado de la métrica
- * @return El propio constructor
- */
- public MetricBuilder description(String description){
- this.description=description;
- return this;
- }
- /**
- * Establece la fuente de información
- * @param source Fuente de la que se extrajeron los datos
- * @return El propio constructor
- */
- public MetricBuilder source(String source){
- this.source=source;
- return this;
- }
- /**
- * Establece las unidades de medida
- * @param unit Unidades de medida de la métrica
- * @return El propio constructor
- */
- public MetricBuilder unit(String unit){
- this.unit=unit;
- return this;
- }
- public Metric build(){
- return new Metric(this);
- }
- }
-
- @Override
- public String toString() {
- String info;
- info="Métrica para "+description+", con valor=" + value + ", source=" + source
- + ", unit=" + unit +" fecha de la medida= "+ date;
- return info;
- }
-
-}
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/Report.java b/src/main/java/us/muit/fs/a4i/model/entities/Report.java
index c13a4c65..9b2ae71a 100644
--- a/src/main/java/us/muit/fs/a4i/model/entities/Report.java
+++ b/src/main/java/us/muit/fs/a4i/model/entities/Report.java
@@ -4,189 +4,183 @@
package us.muit.fs.a4i.model.entities;
import java.util.Collection;
-import java.util.Date;
import java.util.HashMap;
-import java.util.List;
import java.util.logging.Logger;
import us.muit.fs.a4i.control.IndicatorsCalculator;
-import us.muit.fs.a4i.exceptions.IndicatorException;
/**
- * Aspectos generales de todos los informes
- * Todos incluirán un conjunto de métricas de tipo numérico y otro de tipo Date
- * @author Isabel Román
+ *
+ * Aspectos generales de todos los informes
+ *
+ *
+ * Todos incluyen un conjunto de métricas de tipo numérico y otro de tipo Date
+ *
+ *
+ * @author Isabel Román
*
*/
public class Report implements ReportI {
- private static Logger log=Logger.getLogger(Report.class.getName());
- /**
- * Identificador unívoco de la entidad a la que se refire el informe en el servidor remoto que se va a utilizar
- */
- private String id;
+ private static Logger log = Logger.getLogger(Report.class.getName());
/**
- * Los objetos que implementen esta interfaz recurren a calcuadoras con los algoritmos para el cálculo de indicadores
- *
Los algoritmos de cálculo de indicadores serán específicos para un tipo de informe
+ *
+ * Identificador unÃvoco de la entidad a la que se refire el informe en el
+ * servidor remoto que se va a utilizar
+ *
*/
- private IndicatorsCalculator calc;
-
-
-
-
- private ReportI.Type type=null;
+ private String entityId;
+
+ private ReportI.ReportType type = null;
/**
- * Mapa de Métricas
+ * Mapa de Métricas
*
- * */
-
- private HashMap metrics;
-
+ */
+
+ private HashMap metrics;
+
/**
* Mapa de indicadores
*/
-
- private HashMap indicators;
-
- public Report(){
+
+ private HashMap indicators;
+
+ public Report() {
createMaps();
-
+
}
- public Report(String id){
+
+ public Report(String entityId) {
createMaps();
- this.id=id;
+ this.entityId = entityId;
}
- public Report(Type type){
+
+ public Report(ReportType type) {
createMaps();
- this.type=type;
+ this.type = type;
}
- public Report(Type type,String id){
+
+ public Report(ReportType type, String entityId) {
createMaps();
- this.type=type;
- this.id=id;
- }
+ this.type = type;
+ this.entityId = entityId;
+ }
+
private void createMaps() {
- metrics=new HashMap();
- indicators=new HashMap();
+ metrics = new HashMap();
+ indicators = new HashMap();
}
+
/**
- * Busca la métrica solicita en el informe y la devuelve
- * Si no existe devuelve null
- * @param name Nombre de la métrica buscada
- * @return la métrica localizada
+ *
+ * Busca la métrica solicita en el informe y la devuelve
+ *
+ *
+ * Si no existe devuelve null
+ *
+ *
+ * @param name Nombre de la métrica buscada
+ * @return la métrica localizada
*/
@Override
- public Metric getMetricByName(String name) {
- log.info("solicitada métrica de nombre "+name);
- Metric metric=null;
-
- if (metrics.containsKey(name)){
- log.info("La métrica está en el informe");
- metric=metrics.get(name);
+ public ReportItemI getMetricByName(String name) {
+ log.info("solicitada m�trica de nombre " + name);
+ ReportItemI metric = null;
+
+ if (metrics.containsKey(name)) {
+ log.info("La m�trica est� en el informe");
+ metric = metrics.get(name);
}
return metric;
}
+
/**
- * Añade una métrica al informe
+ *
+ * Añade una métrica al informe
+ *
*/
@Override
- public void addMetric(Metric met) {
+ public void addMetric(ReportItemI met) {
metrics.put(met.getName(), met);
- log.info("Añadida métrica "+met+" Con nombre "+met.getName());
+ log.info("A�adida m�trica " + met + " Con nombre " + met.getName());
}
+
/**
- * Busca el indicador solicitado en el informe y lo devuelve
- * Si no existe devuelve null
+ *
+ * Busca el indicador solicitado en el informe y lo devuelve
+ *
+ *
+ * Si no existe devuelve null
+ *
+ *
* @param name Nombre del indicador buscado
* @return el indicador localizado
*/
@Override
- public Indicator getIndicatorByName(String name) {
- log.info("solicitado indicador de nombre "+name);
- Indicator indicator=null;
-
- if (indicators.containsKey(name)){
- indicator=indicators.get(name);
+ public ReportItemI getIndicatorByName(String name) {
+ log.info("solicitado indicador de nombre " + name);
+ ReportItemI indicator = null;
+
+ if (indicators.containsKey(name)) {
+ indicator = indicators.get(name);
}
return indicator;
}
-/**
- * Añade un indicador al informe
- *
- */
+
+ /**
+ *
+ * A�ade un indicador al informe
+ *
+ *
+ */
@Override
- public void addIndicator(Indicator ind) {
-
+ public void addIndicator(ReportItemI ind) {
+
indicators.put(ind.getName(), ind);
- log.info("Añadido indicador "+ind);
+ log.info("Añadido indicador " + ind);
}
+
/**
- * Calcula el indicador solicitado y lo incluye en el informe, si se necesita alguna métrica que no exista la calculadora la busca y la incluye
+ *
+ * Calcula el indicador solicitado y lo incluye en el informe, si se necesita
+ * alguna métrica que no exista la calculadora la busca y la incluye
+ *
*/
@Override
- public void calcIndicator(String name) {
- try {
- calc.calcIndicator(name, this);
- } catch (IndicatorException e) {
- log.info("No se puede calcular esta indicador, no se incluirá");
- }
+ public String getEntityId() {
+ return entityId;
}
- @Override
- public void setId(String id) {
- this.id=id;
- }
- @Override
- public String getId() {
- return id;
- }
- @Override
- public void setIndicatorsCalculator(IndicatorsCalculator calc) throws IndicatorException {
- log.info("Se establece la calculadora de indicadores que va a usar este informe");
- if(this.type==null) {
- this.type=calc.getReportType();
- log.info("El tipo del informe será "+this.type);
- }else if(this.type!=calc.getReportType()){
- throw new IndicatorException("La calculadora no concuerda con el tipo de informe");
- }
- this.calc=calc;
- }
-
+
@Override
public String toString() {
String repoinfo;
- repoinfo="Información del Informe:\n - Métricas: ";
- for (String clave:metrics.keySet()) {
- repoinfo+="\n Clave: " + clave + metrics.get(clave);
+ repoinfo = "Información del Informe:\n - Métricas: ";
+ for (String clave : metrics.keySet()) {
+ repoinfo += "\n Clave: " + clave + metrics.get(clave);
}
- repoinfo+="\n - Indicadores: ";
- for (String clave:indicators.keySet()) {
- repoinfo+="\n Clave: " + clave + indicators.get(clave);
+ repoinfo += "\n - Indicadores: ";
+ for (String clave : indicators.keySet()) {
+ repoinfo += "\n Clave: " + clave + indicators.get(clave);
}
return repoinfo;
}
+
@Override
- public Collection getAllMetrics() {
- // TODO Auto-generated method stub
+ public Collection getAllMetrics() {
+
return metrics.values();
}
+
@Override
- public ReportI.Type getType() {
- return type;
- }
- @Override
- public void setType(ReportI.Type type) {
- //Sólo se puede cambiar si no estaba aún establecido
- //Un informe no puede cambiar de tipo
- if (this.type==null) {
- this.type = type;
- }
+ public Collection getAllIndicators() {
+
+ return indicators.values();
}
+
@Override
- public void calcAllIndicators() {
- // TODO Auto-generated method stub
-
+ public ReportType getType() {
+ return type;
}
-
}
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/ReportI.java b/src/main/java/us/muit/fs/a4i/model/entities/ReportI.java
index 1b152edf..fbbaeb20 100644
--- a/src/main/java/us/muit/fs/a4i/model/entities/ReportI.java
+++ b/src/main/java/us/muit/fs/a4i/model/entities/ReportI.java
@@ -1,93 +1,94 @@
package us.muit.fs.a4i.model.entities;
import java.util.Collection;
-import java.util.List;
-
-import us.muit.fs.a4i.control.IndicatorsCalculator;
-import us.muit.fs.a4i.exceptions.IndicatorException;
+/**
+ * Interfaz para la gestión de informes
+ * @author Isabel Román
+ *
+ */
public interface ReportI {
/**
- * Tipos de informes, puede necesitarse cuando los algoritmos de cálculo de indicadores difieran según el tipo de informe
- * Un informe sólo es de un tipo y no se puede modificar una vez establecido
+ *
+ * Tipos de informes, puede necesitarse cuando los algoritmos de cálculo de
+ * indicadores difieran según el tipo de informe
+ *
+ *
+ * Un informe sólo es de un tipo y no se puede modificar una vez establecido
+ *
*
*/
- public static enum Type{
- REPOSITORY,
- DEVELOPER,
- PROJECT,
- ORGANIZATION
- }
-
- /**
- * Consulta una métrica de un informe a partir del nombre
- * @param name Nombre de la métrica solicitada
- * @return Métrica solicitada
- */
- Metric getMetricByName(String name);
+ public static enum ReportType {
+ REPOSITORY, DEVELOPER, PROJECT, ORGANIZATION
+ }
+
/**
- * Obtiene todas las métricas del informe
- * @return Colleción de métricas que contiene el informe
+ * Consulta el tipo del informe
+ *
+ * @return tipo del informe
*/
- Collection getAllMetrics();
- /**
- * Añade una métrica al informe
- * @param met Nueva métrica
- */
- void addMetric(Metric met);
+ ReportI.ReportType getType();
+
/**
- * Obtiene un indicador del informe a partir del nombre del mismo
- * @param name Nombre del indicador consultado
- * @return El indicador
+ * Obtiene el identificador de la entidad a la que se refiere el informe
+ *
+ * @return Identificador unóvoco de la entidad a la que se refiere el informe en
+ * el remoto
*/
+ String getEntityId();
- Indicator getIndicatorByName(String name);
/**
- * Añade un indicador al informe
- * @param ind Nuevo indicador
+ * Consulta una métrica de un informe a partir del nombre
+ *
+ * @param name Nombre de la métrica solicitada
+ * @return Métrica solicitada
*/
+ ReportItemI getMetricByName(String name);
- void addIndicator(Indicator ind);
/**
- * Calcula un indicador a partir de su nombre y lo añade al informe
- * Si se basa en métricas que no están aún incluidas en el informe las incluye
- * @param name Nombre del indicador que se quiere calcular
+ * Obtiene todas las métricas del informe
+ *
+ * @return Colecciónn de métricas que contiene el informe
*/
-
- void calcIndicator(String name);
+ Collection getAllMetrics();
/**
- * Establede el identificador unívoco de la entidad a la que se refiere el informe, debe ser el identificador usado en el remoto
- * @param id Identificador unívoco de la entidad a la que se refiere el informe en el remoto
+ * Añade una métrica al informe
+ *
+ * @param metric Nueva métrica
*/
- void setId(String id);
-
- /**
- * Obtiene el identificador de la entidad a la que se refiere el informe
- * @return Identificador unívoco de la entidad a la que se refiere el informe en el remoto
- */
- String getId();
+ void addMetric(ReportItemI metric);
+
/**
- * Establece la calculadora de indicadores, debe ser específica para el tipo de informe
- * @param calc calculadora a utilizar para el cálculo de indicadores
- * @throws IndicatorException Si el tipo de la calculadora no coincide con el tipo de informe
+ * Obtiene un indicador del informe a partir del nombre del mismo
+ *
+ * @param indicatorName Nombre del indicador consultado
+ * @return El indicador
*/
- void setIndicatorsCalculator(IndicatorsCalculator calc) throws IndicatorException;
+
+ ReportItemI getIndicatorByName(String indicatorName);
+
/**
- * Calcula todos los indicadores especificados por defecto para el tipo de informe y los incluye en el informe
- * También incluye las métricas utiizadas
+ * Obtiene todos los indicadores del informe
+ *
+ * @return el conjunto de indicadores del informe
*/
- void calcAllIndicators();
+ Collection getAllIndicators();
+
/**
- * Establece el tipo del informe, sólo se puede establecer una vez y debe coincidir con la el tipo de la calculadora usada
- * @param type Tipo del informe
+ * Añaade un indicador al informe
+ *
+ * @param newIndicator nuevo indicador
*/
- void setType(ReportI.Type type);
+
+ void addIndicator(ReportItemI newIndicator);
+
/**
- * Obtiene el tipo del informe
- * @return Tipo del informe
+ * Calcula un indicador a partir de su nombre y lo añade al informe Si se basa
+ * en métricas que no están aún incluidas en el informe las incluye
+ *
+ * @param name Nombre del indicador que se quiere calcular
*/
- ReportI.Type getType();
}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/ReportItem.java b/src/main/java/us/muit/fs/a4i/model/entities/ReportItem.java
new file mode 100644
index 00000000..39635410
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/model/entities/ReportItem.java
@@ -0,0 +1,296 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.model.entities;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.logging.Logger;
+
+import us.muit.fs.a4i.config.Context;
+import us.muit.fs.a4i.exceptions.ReportItemException;
+
+/**
+ * @author Isabel Rom�n Entidad para guardar la informaci�n de un indicador o
+ * una m�trica, elementos de un informe
+ *
+ */
+public class ReportItem implements ReportItemI {
+ private IndicatorI indicator = null;
+ private static Logger log = Logger.getLogger(ReportItem.class.getName());
+ /**
+ * Nombre del indicador/métrica
+ */
+ private String name;
+ /**
+ * Valor del indicador/métrica
+ */
+ private T value;
+ /**
+ * Obligatorio Fecha en la que se construye el objeto o se toma la medida
+ */
+ private Date date;
+ /**
+ * Descripción del elemento del informe
+ */
+ private String description;
+ /**
+ * Origen del elemento
+ */
+ private String source;
+ /**
+ * Unidades de medida
+ */
+ private String unit;
+
+ /**
+ * Construye un objeto ReportItem a partir de un constructor, previamente
+ * configurado Sólo lo utiliza el propio constructor, es privado, nadie, que no
+ * sea el constructor, puede crear una ReportItem
+ *
+ * @param builder Constructor del ReportItem
+ */
+ private ReportItem(ReportItemBuilder builder) {
+
+ this.description = builder.description;
+ this.name = builder.name;
+ this.value = builder.value;
+ this.source = builder.source;
+ this.unit = builder.unit;
+ this.date = builder.date;
+ }
+
+ /**
+ * Obtiene la descripción del ReportItem
+ *
+ * @return Descripción del significado del ReportItem
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Consulta el nombre del ReportItem
+ *
+ * @return Nombre del ReportItem
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Consulta el valor del ReportItem
+ *
+ * @return ReportItem
+ */
+ public T getValue() {
+ return value;
+ }
+
+ /**
+ * Consulta la fuente de información
+ *
+ * @return Origen del ReportItem
+ */
+ public String getSource() {
+ return source;
+ }
+
+ /**
+ * Consulta las unidades del ReportItem
+ *
+ * @return la unidad usada en el ReportItem
+ */
+ public String getUnit() {
+ return unit;
+ }
+
+ /**
+ * Consulta el indicador de ReportItem
+ *
+ * @return indicador de ReportItem
+ */
+ public IndicatorI getIndicator() {
+ return this.indicator;
+ }
+
+ /**
+ * Consulta cuando se obtuvo el ReportItem
+ *
+ * @return Fecha de consulta del ReportItem
+ */
+ public Date getDate() {
+ return this.date;
+ }
+
+ /**
+ *
+ * Clase para construir ReportItem. Verifica los ReportItem antes de crearlos
+ *
+ *
+ */
+ public static class ReportItemBuilder {
+ private String description;
+ private String name;
+ private Date date;
+ private T value;
+ private String source;
+ private String unit;
+ private IndicatorI indicator = null;
+
+ public ReportItemBuilder(String name, T value) throws ReportItemException {
+ HashMap reportItemDefinition = null;
+ /**
+ * Verifico si el elemento está definido y el tipo es correcto
+ */
+ // el nombre incluye java.lang, si puede eliminar si se manipula la cadena
+ // hay que quedarse sólo con lo que va detrás del último punto o meter en el
+ // fichero el nombre completo
+ // Pero ¿y si se usan tipos definidos en otras librerÃas? usar el nombre
+ // completo "desambigua" mejor
+ log.info("Verifico el ReportItem de nombre " + name + " con valor de tipo " + value.getClass().getName());
+ try {
+ // Compruebo si es un indicador
+ reportItemDefinition = Context.getContext().getChecker().getIndicatorConfiguration()
+ .definedIndicator(name, value.getClass().getName());
+
+ if (reportItemDefinition != null) {
+ this.indicator = new Indicator();
+ } else {
+ // Si no lo era, compruebo si es una métrica
+ reportItemDefinition = Context.getContext().getChecker().getMetricConfiguration()
+ .definedMetric(name, value.getClass().getName());
+ }
+ if (reportItemDefinition != null) {
+ this.name = name;
+ this.value = value;
+ this.date = Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC));
+ this.description = reportItemDefinition.get("description");
+ this.unit = reportItemDefinition.get("unit");
+ } else {
+ throw new ReportItemException(
+ "ReportItem " + name + " no definido o tipo " + value.getClass().getName() + " incorrecto");
+ }
+ } catch (IOException e) {
+ throw new ReportItemException("El fichero de configuración de ReportItem no se puede abrir");
+ }
+ /*
+ * Si el ReportItem era un indicador este se ha creado vacÃo, con el campo state
+ * a UNDEFINED Si era una métrica el indicador está null Si no era ninguno de
+ * los dos se ha lanzado una excepción
+ */
+
+ }
+
+ /**
+ *
+ * Establece la descripción del ReportItem
+ *
+ *
+ * @param description Breve descripción del significado del ReportItem
+ * @return El propio constructor
+ */
+ public ReportItemBuilder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ *
+ * Establece la fecha del ReportItem
+ *
+ *
+ * @param date Fecha del ReportItem
+ * @return El propio constructor
+ */
+ public ReportItemBuilder date(Date date) {
+ this.date = date;
+ return this;
+ }
+
+ /**
+ *
+ * Establece el estado del ReportItem si era un indicador
+ *
+ *
+ * @param state Estado del indicador
+ * @return El propio constructor
+ * @throws ReportItemException intenta establecer datos de tipo indicador en una
+ * métrica
+ */
+ public ReportItemBuilder indicator(IndicatorI.IndicatorState state) throws ReportItemException {
+ if (this.indicator != null) {
+ this.indicator.setState(state);
+ } else {
+ throw new ReportItemException("El Report Item no es un indicador, no puede contener estado");
+ }
+
+ return this;
+ }
+
+ /**
+ *
+ * Establece el conjunto de métricas si el ReportItem es un indicador
+ *
+ *
+ * @param metrics
+ * @return El propio constructor
+ * @throws ReportItemException
+ */
+ public ReportItemBuilder metrics(Collection metrics) throws ReportItemException {
+ if (this.indicator != null) {
+ this.indicator.setMetrics(metrics);
+ } else {
+ throw new ReportItemException("El Report Item no es un indicador, no puede contener más metricas");
+ }
+ return this;
+ }
+
+ /**
+ *
+ * Establece la fuente de información
+ *
+ *
+ * @param source Fuente de la que se extrajeron los datos
+ * @return El propio constructor
+ */
+ public ReportItemBuilder source(String source) {
+ this.source = source;
+ return this;
+ }
+
+ /**
+ *
+ * Establece las unidades de medida
+ *
+ *
+ * @param unit Unidades de medida del ReportItem
+ * @return El propio constructor
+ */
+ public ReportItemBuilder unit(String unit) {
+ this.unit = unit;
+ return this;
+ }
+
+ public ReportItem build() {
+ return new ReportItem(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String info = "ReportItem ";
+ if (this.indicator != null) {
+ info = "De tipo Indicador ";
+ }
+ info = info + "para " + description + ", con valor=" + value + ", source=" + source + ", unit=" + unit
+ + " fecha de la medida= " + date;
+
+ return info;
+ }
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/ReportItemI.java b/src/main/java/us/muit/fs/a4i/model/entities/ReportItemI.java
new file mode 100644
index 00000000..96601451
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/model/entities/ReportItemI.java
@@ -0,0 +1,56 @@
+package us.muit.fs.a4i.model.entities;
+
+import java.util.Date;
+
+public interface ReportItemI {
+
+ /**
+ * Consulta el nombre de la métrica
+ *
+ * @return Nombre de la métrica
+ */
+ public String getName();
+
+ /**
+ * Consulta el valor de la métrica
+ *
+ * @return Medida
+ */
+ public T getValue();
+
+ /**
+ * Consulta cuando se obtuvo la métrica
+ *
+ * @return Fecha de consulta de la métrica
+ */
+ public Date getDate();
+
+ /**
+ * Obtiene la descripción de la métrica
+ *
+ * @return Descripción del significado de la métrica
+ */
+ public String getDescription();
+
+ /**
+ * Consulta la fuente de información
+ *
+ * @return Origen de la medida
+ */
+ public String getSource();
+
+ /**
+ * Consulta las unidades de medida
+ *
+ * @return la unidad usada en la medida
+ */
+ public String getUnit();
+
+ /**
+ * Consulta el indicador
+ *
+ * @return el indicador
+ */
+ public IndicatorI getIndicator();
+
+}
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/doc-files/entitiesPackage.GIF b/src/main/java/us/muit/fs/a4i/model/entities/doc-files/entitiesPackage.GIF
deleted file mode 100644
index 4ea1fd86..00000000
Binary files a/src/main/java/us/muit/fs/a4i/model/entities/doc-files/entitiesPackage.GIF and /dev/null differ
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/doc-files/entitiesPackage.gif b/src/main/java/us/muit/fs/a4i/model/entities/doc-files/entitiesPackage.gif
new file mode 100644
index 00000000..214f3c8a
Binary files /dev/null and b/src/main/java/us/muit/fs/a4i/model/entities/doc-files/entitiesPackage.gif differ
diff --git a/src/main/java/us/muit/fs/a4i/model/entities/package-info.java b/src/main/java/us/muit/fs/a4i/model/entities/package-info.java
index d39ec279..2ee672c3 100644
--- a/src/main/java/us/muit/fs/a4i/model/entities/package-info.java
+++ b/src/main/java/us/muit/fs/a4i/model/entities/package-info.java
@@ -1,9 +1,14 @@
/**
- * Este paquete contiene las clases de tipo entidad, que representan la información manejada
- *
+ *
+ * Este paquete contiene las clases de tipo entidad, que representan la
+ * información manejada
+ *
+ *
*
- * @author Isabel Román
- * @version 0.0
+ * @author Isabel Román
+ * @version V.0.2
*/
package us.muit.fs.a4i.model.entities;
\ No newline at end of file
diff --git a/src/main/java/us/muit/fs/a4i/model/remote/GitHubDeveloperEnquirer.java b/src/main/java/us/muit/fs/a4i/model/remote/GitHubDeveloperEnquirer.java
new file mode 100644
index 00000000..7b1aed2e
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/model/remote/GitHubDeveloperEnquirer.java
@@ -0,0 +1,131 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.model.remote;
+
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.kohsuke.github.GHEvent;
+import org.kohsuke.github.GHEventInfo;
+import org.kohsuke.github.GHEventPayload;
+import org.kohsuke.github.GHProject;
+import org.kohsuke.github.GHRepository;
+import org.kohsuke.github.GHUser;
+import org.kohsuke.github.GitHub;
+import org.kohsuke.github.PagedIterable;
+
+import us.muit.fs.a4i.exceptions.MetricException;
+import us.muit.fs.a4i.model.entities.ReportI;
+import us.muit.fs.a4i.model.entities.ReportItem;
+
+import us.muit.fs.a4i.model.entities.ReportItem.ReportItemBuilder;
+
+/**
+ * Deuda técnica Esta clase debe consultar datos sobre un desarrollador concreto
+ * de github Ahora mismo está en estado lamentable Simplemente busca los eventos
+ * de un desarrollador No localiza eventos de tipo ISSUE, que son los que se
+ * querÃa RECUERDA: las métricas tienen que estar incluidas en el fichero de
+ * configuración a4iDefault.json
+ */
+public class GitHubDeveloperEnquirer extends GitHubEnquirer {
+ public GitHubDeveloperEnquirer() {
+ super();
+ myQueries.put("closedIssuesLastMonth",GitHubDeveloperEnquirer::getClosedIssuesLastMonth);
+ myQueries.put("assignedIssuesLastMonth",GitHubDeveloperEnquirer::getAssignedIssuesLastMonth);
+ log.info("Incluidos nombres metricas en Enquirer");
+ }
+
+ private static Logger log = Logger.getLogger(GitHubDeveloperEnquirer.class.getName());
+ /**
+ *
+ * Identificador unÃvoco de la entidad a la que se refire el informe en el
+ * servidor remoto que se va a utilizar
+ *
+ */
+ private String entityId;
+
+ @Override
+ public ReportI buildReport(String developerId) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ReportItem getMetric(String metricName, String developerId) throws MetricException {
+ GHUser developer;
+
+ GitHub gb = getConnection();
+ try {
+ developer = gb.getUser(developerId);
+ log.info("Localizado el desarrollador " + developer.getName());
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new MetricException("No se puede acceder al desarrollador " + developerId + " para recuperarlo");
+ }
+
+ return getMetric(metricName, developer);
+ }
+
+ private ReportItem getMetric(String metricName, GHUser developer) throws MetricException {
+ log.info("Localizando la metrica " + metricName);
+ ReportItem metric;
+ if (developer == null) {
+ throw new MetricException(
+ "Intenta obtener una métrica de desarrollador sin haber obtenido el desarrollador");
+ }
+ /*
+ switch (metricName) {
+ case "closedIssuesLastMonth":
+ metric = getClosedIssuesLastMonth(developer);
+ break;
+ case "assignedIssuesLastMonth":
+ metric = getAssignedIssuesLastMonth(developer);
+ break;
+ default:
+ throw new MetricException("La métrica " + metricName + " no está definida para un repositorio");
+ }
+ */
+
+ return myQueries.get(metricName).apply(developer);
+ }
+
+ static private ReportItem getClosedIssuesLastMonth(GHUser developer) {
+ log.info("Consultando los issues asignados a un desarrollador");
+ ReportItemBuilder builder = null;
+ int issues = 0;
+
+ try {
+ PagedIterable events = developer.listEvents();
+ for (GHEventInfo event : events) {
+ log.info("Evento tipo" + event.getType() + " en la fecha " + event.getCreatedAt());
+ if (event.getType() == GHEvent.ISSUES) {
+
+ GHEventPayload.Issue payload = event.getPayload(GHEventPayload.Issue.class);
+ log.info(payload.getAction());
+ issues++;
+
+ }
+
+ }
+ builder = new ReportItem.ReportItemBuilder("closedIssuesLastMonth", issues);
+ builder.source("GitHub");
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getAssignedIssuesLastMonth(GHUser developer) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public RemoteType getRemoteType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/src/main/java/us/muit/fs/a4i/model/remote/GitHubEnquirer.java b/src/main/java/us/muit/fs/a4i/model/remote/GitHubEnquirer.java
index fedad8d6..fc624a38 100644
--- a/src/main/java/us/muit/fs/a4i/model/remote/GitHubEnquirer.java
+++ b/src/main/java/us/muit/fs/a4i/model/remote/GitHubEnquirer.java
@@ -4,60 +4,103 @@
package us.muit.fs.a4i.model.remote;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;
+import java.util.function.*;
+import java.util.Map;
+import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubBuilder;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.remote.RemoteEnquirer.RemoteType;
+
/**
- * Clase abstracta con los métodos comunes a los constructores que recogen la información del servicio GitHub
- * Para las consultas a github se recurre a la API github-API
- * Actualmente sólo incluye el establecimiento del identificador de entidad y la obtención del objeto GitHub para las consultas
- * @author Isabel Román
+ *
+ * Clase abstracta con los métodos comunes a los constructores que consultan la
+ * información del servicio GitHub. Usan Github como backend
+ *
+ *
+ * Para las consultas a github se recurre a la API github-API
+ *
+ *
+ * Actualmente sólo incluye el establecimiento del identificador de entidad y la
+ * obtención del objeto GitHub para las consultas.
+ *
+ * protected Map> myQueries; será un mapa de
+ * funciones, en el que la clave es el nombre de la métrica y el valor es la
+ * referencia a la función que permite recuperar esa métrica
+ *
+ *
+ *
+ * @author Isabel Román
+ * @param
*
*/
-public abstract class GitHubEnquirer implements RemoteEnquirer {
- private static Logger log=Logger.getLogger(GitHubEnquirer.class.getName());
- protected List metricNames;
-
+public abstract class GitHubEnquirer implements RemoteEnquirer {
+ private static Logger log = Logger.getLogger(GitHubEnquirer.class.getName());
+ protected Map> myQueries;
+ private RemoteEnquirer.RemoteType type = RemoteEnquirer.RemoteType.GITHUB;
/**
- * Referencia al objeto GitHub que permite hacer consultas al servidor Github
- * Se crea al invocar por primera vez getConnectiony se mantiene mientras el GHBuilder esté vivo
+ *
+ * Referencia al objeto GitHub que permite hacer consultas al servidor Github
+ *
+ *
+ * Se crea al invocar por primera vez getConnectiony se mantiene mientras el
+ * GHBuilder está vivo
+ *
*/
- private GitHub github=null;
-
-
-
+ private GitHub github = null;
+
public GitHubEnquirer() {
- metricNames=new ArrayList();
+ myQueries = new HashMap>();
}
-
-
+
/**
- * El objeto para contectarse al GitHub se crea la primera vez que se invoca getConnection
+ *
+ * El objeto para contectarse al GitHub se crea la primera vez que se invoca
+ * getConnection
+ *
+ *
* @return devuelve un objeto GitHub que permite la consulta al remoto
*/
protected GitHub getConnection() {
-
- if(github==null) try {
-
- log.info("Creando el objeto GitHub");
- github = GitHubBuilder.fromEnvironment().build();
-
-
- }catch(Exception e) {
- log.info(e+" No se puede crear la instancia GitHub\n");
- log.info("Recuerde que debe configurar las variables de entorno GITHUB_LOGIN y GITHUB_OAUTH con su nombre de usuario y token respectivamente");
- }
+
+ if (github == null)
+ try {
+ github = GitHubBuilder.fromEnvironment().build();
+ log.info("Creado el objeto GitHub");
+
+ } catch (Exception e) {
+ log.info(e + " No se puede crear la instancia GitHub\n");
+ log.info(
+ "Recuerde que debe configurar las variables de entorno GITHUB_LOGIN y GITHUB_OAUTH con su nombre de usuario y token respectivamente");
+ e.printStackTrace();
+ }
return github;
}
- protected void setMetric(String newMetric) {
- metricNames.add(newMetric);
+
+ /**
+ * Permite añadir una nueva función de búsqueda de métrica al mapa
+ *
+ * @param newMetric Nombre de la métrica nueva
+ * @param functionPointer Referencia a la función que implementa el algoritmo
+ * para recuperar la métrica
+ */
+ protected void setMetric(String newMetric, Function functionPointer) {
+ myQueries.put(newMetric, functionPointer);
}
- public List getAvailableMetrics(){
- return metricNames;
+
+ public List getAvailableMetrics() {
+ List metrics = new ArrayList(myQueries.keySet());
+ return metrics;
+ }
+
+ public RemoteType getRemoteType() {
+ return type;
}
}
diff --git a/src/main/java/us/muit/fs/a4i/model/remote/GitHubOrganizationEnquirer.java b/src/main/java/us/muit/fs/a4i/model/remote/GitHubOrganizationEnquirer.java
new file mode 100644
index 00000000..2cb833b7
--- /dev/null
+++ b/src/main/java/us/muit/fs/a4i/model/remote/GitHubOrganizationEnquirer.java
@@ -0,0 +1,422 @@
+/**
+ *
+ */
+package us.muit.fs.a4i.model.remote;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.kohsuke.github.GHIssueState;
+import org.kohsuke.github.GHOrganization;
+
+import org.kohsuke.github.GitHub;
+import org.kohsuke.github.PagedIterable;
+import org.kohsuke.github.GHProject;
+import org.kohsuke.github.GHRepository;
+
+import us.muit.fs.a4i.exceptions.MetricException;
+
+import us.muit.fs.a4i.exceptions.ReportItemException;
+import us.muit.fs.a4i.model.entities.Report;
+import us.muit.fs.a4i.model.entities.ReportI;
+import us.muit.fs.a4i.model.entities.ReportItem;
+import us.muit.fs.a4i.model.entities.ReportItem.ReportItemBuilder;
+
+/**
+ *
+ * Esta clase permite consultar métricas sobre una organización GitHub
+ *
+ *
+ * Deuda técnica: serÃa necesario verificar mejor el funcionamiento de las
+ * consultas de proyectos cerrados y abiertos, no parece hacer lo esperado
+ * HabrÃa que incluir más métricas y algún indicador RECUERDA: las métricas
+ * tienen que estar incluidas en el fichero de configuración a4iDefault.json
+ *
+ *
+ * @author Isabel Román
+ *
+ */
+
+public class GitHubOrganizationEnquirer extends GitHubEnquirer {
+ private static Logger log = Logger.getLogger(GitHubOrganizationEnquirer.class.getName());
+ /**
+ *
+ * Identificador unÃvoco de la entidad a la que se refire el informe en el
+ * servidor remoto que se va a utilizar
+ *
+ */
+ private String entityId;
+
+ public GitHubOrganizationEnquirer() {
+ super();
+ myQueries.put("repositoriesWithOpenPullRequest",GitHubOrganizationEnquirer::getRepositoriesWithOpenPullRequest);
+ myQueries.put("repositories",GitHubOrganizationEnquirer::getRepositories);
+ myQueries.put("pullRequests",GitHubOrganizationEnquirer::getPullRequests);
+ myQueries.put("members",GitHubOrganizationEnquirer::getMembers);
+ myQueries.put("teams",GitHubOrganizationEnquirer::getTeams);
+ myQueries.put("openProjects",GitHubOrganizationEnquirer::getOpenProjects);
+ myQueries.put("closedProjects",GitHubOrganizationEnquirer::getClosedProjects);
+ myQueries.put("followers",GitHubOrganizationEnquirer::getFollowers);
+
+ //Equipo 7 23/24
+ myQueries.put("teamsBalance",GitHubOrganizationEnquirer::getTeamsBalance);
+
+ log.info("Incluidas métricas en Enquirer");
+ }
+
+ @Override
+ public ReportI buildReport(String organizationId) {
+ ReportI report = null;
+ log.info("Invocado el metodo que construye un informe de organización, para la organizacion " + organizationId);
+ /**
+ *
+ * Información sobre la organizacion de GitHub
+ *
+ */
+ GHOrganization organization;
+ /**
+ *
+ * En estos momentos cada vez que se invoca construyeObjeto se crea y rellena
+ * uno nuevo
+ *
+ *
+ * Deuda técnica: se puede optimizar consultando sólo las diferencias respecto a
+ * la fecha de la última representación local
+ *
+ */
+
+ try {
+ log.info("Nombre organizacion = " + organizationId);
+
+ GitHub gb = getConnection();
+ organization = gb.getOrganization(organizationId);
+
+ log.info("La organizacion es de la empresa " + organization.getCompany() + " fue creada en "
+ + organization.getCreatedAt() + " se puede contactar en " + organization.getEmail());
+ log.info("leidos datos de la " + organization);
+ report = new Report(organizationId);
+
+ /**
+ * Métricas directas de tipo conteo
+ */
+
+ report.addMetric(getMembers(organization));
+ log.info("Incluida metrica members ");
+
+ report.addMetric(getTeams(organization));
+ log.info("Incluida metrica teams ");
+
+ report.addMetric(getFollowers(organization));
+ log.info("Incluida metrica followers ");
+
+ report.addMetric(getPullRequests(organization));
+ log.info("Incluida metrica pullRequests ");
+
+ report.addMetric(getRepositories(organization));
+ log.info("Incluida metrica repositories ");
+
+ report.addMetric(getRepositoriesWithOpenPullRequest(organization));
+ log.info("Incluida metrica repositoriesWithPullRequest ");
+
+ report.addMetric(getOpenProjects(organization));
+ log.info("Incluida metrica openProjects ");
+
+ report.addMetric(getClosedProjects(organization));
+ log.info("Incluida metrica closedProjects ");
+
+ } catch (Exception e) {
+ log.severe("Problemas en la conexión " + e);
+ }
+
+ return report;
+ }
+
+ /**
+ * Permite consultar desde fuera una única métrica de la organización con el id
+ * que se pase como parámetro
+ */
+ @Override
+ public ReportItem getMetric(String metricName, String organizationId) throws MetricException {
+ log.info("Invocado getMetric para buscar " + metricName);
+ GHOrganization organization;
+
+ GitHub gb = getConnection();
+ try {
+ organization = gb.getOrganization(organizationId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new MetricException(
+ "No se puede acceder a la organizacion remota " + organizationId + " para recuperarla");
+ }
+
+ return getMetric(metricName, organization);
+ }
+
+ /**
+ *
+ * Crea la métrica solicitada consultando la organizacion que se pasa como
+ * parámetro
+ *
+ *
+ * @param metricName Métrica solicitada
+ * @param organization Organizacion
+ * @return La métrica creada
+ * @throws MetricException Si la métrica no está definida se lanzará una
+ * excepción
+ */
+ private ReportItem getMetric(String metricName, GHOrganization organization) throws MetricException {
+ ReportItem metric = null;
+ if (organization == null) {
+ throw new MetricException("Intenta obtener una métrica sin haber obtenido los datos de la organizacion");
+ }
+ switch (metricName) {
+ case "repositoriesWithOpenPullRequest":
+ metric = getRepositoriesWithOpenPullRequest(organization);
+ break;
+ case "repositories":
+ metric = getRepositories(organization);
+ break;
+ case "pullRequests":
+ metric = getPullRequests(organization);
+ break;
+ case "members":
+ metric = getMembers(organization);
+ break;
+ case "teams":
+ metric = getTeams(organization);
+ break;
+ case "openProjects":
+ metric = getOpenProjects(organization);
+ break;
+ case "closedProjects":
+ metric = getClosedProjects(organization);
+ break;
+ case "followers":
+ metric = getFollowers(organization);
+ break;
+ case "teamsBalance":
+ metric=getTeamsBalance(organization);
+ break;
+ default:
+ throw new MetricException("La métrica " + metricName + " no está definida para un repositorio");
+ }
+
+ return metric;
+ }
+
+ static private ReportItem getRepositoriesWithOpenPullRequest(GHOrganization organization) {
+ log.info("Consultando los repositorios con pull requests abiertos");
+ ReportItemBuilder builder = null;
+ try {
+ builder = new ReportItem.ReportItemBuilder("repositoriesWithOpenPullRequest",
+ organization.getRepositoriesWithOpenPullRequests().size());
+ builder.source("GitHub");
+ } catch (ReportItemException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getRepositories(GHOrganization organization) {
+ log.info("Consultando los repositorios");
+ ReportItemBuilder builder = null;
+ try {
+ builder = new ReportItem.ReportItemBuilder("repositories", organization.getPublicRepoCount());
+ builder.source("GitHub");
+ } catch (ReportItemException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getMembers(GHOrganization organization) {
+ log.info("Consultando los miembros");
+ ReportItemBuilder builder = null;
+ try {
+ builder = new ReportItem.ReportItemBuilder("members", organization.listMembers().toList().size());
+ builder.source("GitHub");
+ } catch (ReportItemException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getTeams(GHOrganization organization) {
+ log.info("Consultando los equipos");
+ ReportItemBuilder builder = null;
+ try {
+ int size = organization.getTeams().size();
+ log.info("Numero de equipos" + size);
+ builder = new ReportItem.ReportItemBuilder("teams", organization.getTeams().size());
+ builder.source("GitHub");
+ } catch (ReportItemException | IOException e) {
+ log.fine("unable to retry teams");
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getFollowers(GHOrganization organization) {
+ log.info("Consultando los seguidores");
+ ReportItemBuilder builder = null;
+ try {
+ builder = new ReportItem.ReportItemBuilder("followers", organization.getFollowersCount());
+ builder.source("GitHub");
+ } catch (ReportItemException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getPullRequests(GHOrganization organization) {
+ log.info("Consultando los pull requests");
+ ReportItemBuilder builder = null;
+ try {
+ builder = new ReportItem.ReportItemBuilder("pullRequests", organization.getPullRequests().size());
+ builder.source("GitHub");
+ } catch (ReportItemException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getOpenProjects(GHOrganization organization) {
+
+ ReportItemBuilder builder = null;
+ try {
+ log.info("Consultando los proyectos abiertos en " + organization.getUrl());
+ int number = 0;
+ // first we look for projects associated with the organization
+ PagedIterable pagina = organization.listProjects(GHProject.ProjectStateFilter.OPEN);
+ List proyectos = pagina.toList();
+ number = number + proyectos.size();
+ // second we look for projects associated with the repos
+ PagedIterable repositories = organization.listRepositories();
+
+ for (GHRepository repo : repositories) {
+ PagedIterable repoproyects = repo.listProjects(GHProject.ProjectStateFilter.OPEN);
+ number = number + repoproyects.toList().size();
+ }
+
+ log.info("Open projects " + number);
+ builder = new ReportItem.ReportItemBuilder("openProjects", number);
+
+ for (GHProject pro : proyectos) {
+ log.info("Proyecto " + pro.getName() + " en estado " + pro.getState());
+ }
+ builder.source("GitHub");
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+ }
+
+ static private ReportItem getClosedProjects(GHOrganization organization) {
+ ReportItemBuilder builder = null;
+ try {
+ log.info("Consultando los proyectos cerrados en " + organization.getUrl());
+ int number = 0;
+ // first we look for projects associated with the organization
+ PagedIterable pagina = organization.listProjects(GHProject.ProjectStateFilter.CLOSED);
+ List proyectos = pagina.toList();
+ number = number + proyectos.size();
+ // second we look for projects associated with the repos
+ PagedIterable repositories = organization.listRepositories();
+
+ for (GHRepository repo : repositories) {
+ PagedIterable repoproyects = repo.listProjects(GHProject.ProjectStateFilter.CLOSED);
+ number = number + repoproyects.toList().size();
+ }
+
+ log.info("Closed projects " + number);
+ builder = new ReportItem.ReportItemBuilder("closedProjects", number);
+
+ for (GHProject pro : proyectos) {
+ log.info("Proyecto " + pro.getName() + " en estado " + pro.getState());
+ }
+ builder.source("GitHub");
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return builder.build();
+
+ }
+ static private Map getIssuesPerRepository(GHOrganization organization) {
+ log.info("Consultando los issues de cada uno de los repositorios de la organización");
+ Map mapa = new HashMap<>();
+ try {
+
+ PagedIterable repositorios = organization.listRepositories();
+ for (GHRepository repo : repositorios) {
+ mapa.put(repo,repo.getIssues(GHIssueState.OPEN).size());
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return mapa;
+ }
+
+ static private Map getTeamsPerRepository(GHOrganization organization) {
+ log.info("Consultando el número de equipos por repositorio");
+ ReportItemBuilder