This is an automated email from the git hooks/post-receive script. New commit to branch feature/7498 in repository observe. See http://git.codelutin.com/observe.git commit 03f553a27fc3a6ac65237091e973e4d6800e1f8f Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Thu Sep 3 10:09:52 2015 +0200 implantation du service de generation des rapport + test (refs #7498) --- .../fr/ird/observe/AbstractObserveTopiaDao.java | 18 + observe-services-api/pom.xml | 24 +- .../service/actions/report/ReportBuilder.java | 489 +++++++++++++++++++++ .../service/actions/report/ReportService.java | 20 + .../service/actions/report/model/DataMatrix.java | 259 +++++++++++ .../service/actions/report/model/Report.java | 157 +++++++ .../actions/report/model/ReportOperation.java | 106 +++++ .../actions/report/model/ReportRequest.java | 406 +++++++++++++++++ .../actions/report/model/ReportVariable.java | 80 ++++ .../report/model/operations/ExecuteRequests.java | 120 +++++ .../report/model/operations/GroupByLength.java | 111 +++++ .../actions/report/model/operations/SumColumn.java | 129 ++++++ .../report/model/operations/SumIntColumn.java | 129 ++++++ .../actions/report/model/operations/SumIntRow.java | 129 ++++++ .../actions/report/model/operations/SumRow.java | 129 ++++++ ...es.service.actions.report.model.ReportOperation | 6 + .../service/actions/report/ReportBuilderTest.java | 130 ++++++ .../actions/report/observe-reports-test.properties | 27 ++ .../service/actions/report/ReportServiceTopia.java | 207 +++++++++ 19 files changed, 2675 insertions(+), 1 deletion(-) diff --git a/observe-entities/src/main/java/fr/ird/observe/AbstractObserveTopiaDao.java b/observe-entities/src/main/java/fr/ird/observe/AbstractObserveTopiaDao.java new file mode 100644 index 0000000..d8e110f --- /dev/null +++ b/observe-entities/src/main/java/fr/ird/observe/AbstractObserveTopiaDao.java @@ -0,0 +1,18 @@ +package fr.ird.observe; + +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.internal.AbstractTopiaDao; + +import java.util.List; +import java.util.Map; + +public abstract class AbstractObserveTopiaDao<E extends TopiaEntity> extends AbstractTopiaDao<E> { + + public <O> List<O> findAllFromHql(String hql, Map<String, Object> hqlParameters) { + + return findAll(hql, hqlParameters); + + } + + +} \ No newline at end of file diff --git a/observe-services-api/pom.xml b/observe-services-api/pom.xml index 1fdd594..0c63736 100644 --- a/observe-services-api/pom.xml +++ b/observe-services-api/pom.xml @@ -64,7 +64,29 @@ </dependencies> <build> - + <resources> + <resource> + <directory>src/main/resources</directory> + <includes> + <include>**/*</include> + </includes> + </resource> + <resource> + <directory>src/main/filters</directory> + <filtering>true</filtering> + <includes> + <include>*.properties</include> + </includes> + </resource> + </resources> + <testResources> + <testResource> + <directory>src/test/resources</directory> + <includes> + <include>**/*</include> + </includes> + </testResource> + </testResources> <plugins> <plugin> <groupId>com.thoughtworks.paranamer</groupId> diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/ReportBuilder.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/ReportBuilder.java new file mode 100644 index 0000000..55b40b3 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/ReportBuilder.java @@ -0,0 +1,489 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report; + + +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import fr.ird.observe.services.service.actions.report.model.ReportRequest; +import fr.ird.observe.services.service.actions.report.model.ReportVariable; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.SortedProperties; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Classe responsable de la construction d'un report à partir de sa définition + * lue dans un fichier de propriétés. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class ReportBuilder { + + public static final Pattern REPORT_DEFINITION_PATTERN = Pattern.compile("report.(\\w+).name"); + + public static final String REQUEST_PREFIX = "request."; + + public static final String OPERATION_PREFIX = "operations."; + + public static final String VARIABLE_PREFIX = "variable."; + + public static final String REPEAT_VARIABLE_PREFIX = "repeatVariable."; + + /** Logger */ + private static final Log log = LogFactory.getLog(ReportBuilder.class); + + /** les propriétés chargées par le builder pour construire les reports */ + protected Properties properties; + + /** la liste des lastName sde reports connus par le système */ + protected List<String> reportNames; + + /** les operations connues par le système */ + protected static Map<String, Class<?>> operations; + + public static Map<String, Class<?>> getOperations() { + if (operations == null) { + operations = new TreeMap<String, Class<?>>(); + ServiceLoader<ReportOperation> loader = + ServiceLoader.load(ReportOperation.class); + for (ReportOperation op : loader) { + if (log.isInfoEnabled()) { + log.info("Detected operations : " + op.getOperationName()); + } + operations.put(op.getOperationName(), op.getClass()); + } + } + return operations; + } + + public static ReportOperation newOperation(String operationsName) { + Class<?> operationsType = getOperations().get(operationsName); + if (operationsType == null) { + throw new IllegalArgumentException("No such operations [" + operationsName + "], available operationss : " + getOperations().keySet()); + } + try { + Object result = operationsType.newInstance(); + return (ReportOperation) result; + } catch (Exception e) { + throw new IllegalStateException("Could not instanciate operations [" + operationsType + "]", e); + } + } + + public List<String> getReportNames() { + return reportNames; + } + + public List<Report> load(URL definition) throws IOException { + properties = new SortedProperties(); + InputStream in = definition.openStream(); + try { + properties.load(in); + } finally { + in.close(); + } + + reportNames = detectReportNames(); + if (log.isInfoEnabled()) { + log.info("Detected report names : " + reportNames); + } + + List<Report> reports = new ArrayList<Report>(); + for (String reportName : reportNames) { + Report report = build(reportName); + reports.add(report); + } + + return reports; + } + + + protected List<String> detectReportNames() { + List<String> reportNames = new ArrayList<String>(); + Enumeration<Object> keys = properties.keys(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + Matcher matcher = REPORT_DEFINITION_PATTERN.matcher(key); + if (!matcher.matches()) { + + // pas de match + continue; + } + String reportName = matcher.group(1); + if (log.isInfoEnabled()) { + log.info("Discover a new report : " + reportName); + } + reportNames.add(reportName); + } + return reportNames; + } + + protected Report build(String reportName) { + + Map<String, String> dico = detectReportProperties(reportName); + + if (log.isDebugEnabled()) { + log.debug("Will build report [" + reportName + "] with " + dico.size() + " properties (" + dico + ")."); + } + + String name = getValue(dico, "name").trim(); + String description = getValue(dico, "description").trim(); + String rows = getValue(dico, "rows"); + String columns = getValue(dico, "columns"); + String[] rowHeaders = rows == null ? null : rows.split(","); + if (rowHeaders != null) { + for (int i = 0; i < rowHeaders.length; i++) { + String rowHeader = rowHeaders[i]; + rowHeaders[i] = rowHeader.trim(); + } + } + String[] columnHeaders = columns == null ? null : columns.split(","); + if (columnHeaders != null) { + for (int i = 0; i < columnHeaders.length; i++) { + String columnHeader = columnHeaders[i]; + columnHeaders[i] = columnHeader.trim(); + } + } + ReportRequest[] requests = getRequests(reportName, dico); + ReportOperation[] operationss = getOperations(reportName, dico); + ReportVariable[] variables = getVariables(reportName, dico); + ReportVariable[] repeatVariables = getRepeatVariables(reportName, dico); + + // a la fin il ne devrait plus y avoir de propriétés pour le report + if (!dico.isEmpty()) { + if (log.isWarnEnabled()) { + log.warn("Il reste des propriétés non utilisées pour le report [" + reportName + "] : " + dico); + } + } + + Report report = new Report(reportName, + name, + description, + rowHeaders, + columnHeaders, + operationss, + variables, + repeatVariables, + requests + ); + + return report; + } + + protected Map<String, String> detectReportProperties(String reportName) { + + Map<String, String> dico = new TreeMap<String, String>(); + + // pour chaque report, on récupère ses informations + String reportKeyPrefix = "report." + reportName + "."; + int reportKeyPrefixLength = reportKeyPrefix.length(); + + Enumeration<Object> keys = properties.keys(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + if (!key.startsWith(reportKeyPrefix)) { + // pas de match + continue; + } + String realKey = key.substring(reportKeyPrefixLength); + dico.put(realKey, (String) properties.get(key)); + } + + return dico; + } + + protected ReportRequest[] getRequests(String reportName, Map<String, String> dico) { + + Map<Integer, String> requestDico = new TreeMap<Integer, String>(); + Map<Integer, String> requestRepeatDico = new TreeMap<Integer, String>(); + Iterator<Map.Entry<String, String>> itr = dico.entrySet().iterator(); + while (itr.hasNext()) { + Map.Entry<String, String> entry = itr.next(); + String key = entry.getKey(); + if (!key.startsWith(REQUEST_PREFIX)) { + + continue; + } + String REQUEST_REPEAT_SUFFIX = ".repeat"; + if (key.endsWith(REQUEST_REPEAT_SUFFIX)) { + + // definition d'un repeat + String request = entry.getValue(); + String requestId = key.substring(REQUEST_PREFIX.length()); + requestId = requestId.substring(0, requestId.length() - REQUEST_REPEAT_SUFFIX.length()); + Integer id = Integer.valueOf(requestId); + if (log.isInfoEnabled()) { + log.info("Detects a request repeat [" + reportName + ":" + id + "] = " + request); + } + requestRepeatDico.put(id, request); + itr.remove(); + continue; + } + String request = entry.getValue(); + String requestId = key.substring(REQUEST_PREFIX.length()); + Integer id = Integer.valueOf(requestId); + if (log.isDebugEnabled()) { + log.debug("Detects a request [" + reportName + ":" + id + "] = " + request); + } + requestDico.put(id, request); + itr.remove(); + + } + + // On trie les request + List<Integer> ids = new ArrayList<Integer>(requestDico.keySet()); + Collections.sort(ids); + + // on construit (dans le bon ordre la liste des requetes) + List<ReportRequest> result = new ArrayList<ReportRequest>(); + for (Integer id : ids) { + + String requestDef = requestDico.get(id); + String requestRepeatDef = requestRepeatDico.get(id); + + ReportRequest def = getRequest(requestDef, requestRepeatDef); + if (log.isInfoEnabled()) { + log.info("Detects a request : " + def); + } + result.add(def); + + } + return result.toArray(new ReportRequest[result.size()]); + } + + protected ReportRequest getRequest(String requestDef, + String requestRepeatDef) { + + String[] parts = requestDef.split("\\|"); + if (parts.length != 3) { + throw new IllegalArgumentException("La définition de la requete doit etre de type 'X,Y|layout|hql' mais est : " + requestDef); + } + String[] coords = parts[0].split(","); + String layout = parts[1]; + String hql = parts[2]; + + if (coords.length != 2) { + throw new IllegalArgumentException("La définition des coordonées doit etre de type 'X,Y' mais est : " + parts[0]); + } + + int x = Integer.valueOf(coords[0]); + int y = Integer.valueOf(coords[1]); + ReportRequest.RequestLayout realLayout = ReportRequest.RequestLayout.valueOf(layout); + + ReportRequest.RequestRepeat repeat = null; + if (requestRepeatDef != null) { + + // il y a un repeat + String[] repeatParts = requestRepeatDef.split("\\|"); + if (repeatParts.length != 2) { + throw new IllegalArgumentException("La définition d'un repéteur de requete doit etre de type 'repeatName|layout' mais est : " + requestRepeatDef); + } + String repeatName = repeatParts[0].trim(); + String repeatLayout = repeatParts[1].trim(); + ReportRequest.RequestLayout realRepeatLayout = + ReportRequest.RequestLayout.valueOf(repeatLayout); + repeat = new ReportRequest.RequestRepeat(repeatName, realRepeatLayout); + + } + ReportRequest def = new ReportRequest(realLayout, x, y, hql, repeat); + return def; + } + + protected ReportOperation[] getOperations(String reportName, Map<String, String> dico) { + + Map<Integer, String> requestDico = new TreeMap<Integer, String>(); + Iterator<Map.Entry<String, String>> itr = dico.entrySet().iterator(); + while (itr.hasNext()) { + Map.Entry<String, String> entry = itr.next(); + String key = entry.getKey(); + if (!key.startsWith(OPERATION_PREFIX)) { + + continue; + } + String operations = entry.getValue(); + String requestId = key.substring(OPERATION_PREFIX.length()); + Integer id = Integer.valueOf(requestId); + if (log.isDebugEnabled()) { + log.debug("Detects a operations [" + reportName + ":" + id + "] = " + operations); + } + requestDico.put(id, operations); + itr.remove(); + } + + // On trie les request + List<Integer> ids = new ArrayList<Integer>(requestDico.keySet()); + Collections.sort(ids); + + // on construit (dans le bon ordre la liste des requetes) + List<ReportOperation> result = new ArrayList<ReportOperation>(); + for (Integer id : ids) { + + String operationsDef = requestDico.get(id); + + ReportOperation def = getOperation(operationsDef); + if (log.isInfoEnabled()) { + log.info("Detects a operations : " + def); + } + result.add(def); + } + return result.toArray(new ReportOperation[result.size()]); + } + + protected ReportVariable[] getVariables(String reportName, Map<String, String> dico) { + List<ReportVariable> result = new ArrayList<ReportVariable>(); + Iterator<Map.Entry<String, String>> itr = dico.entrySet().iterator(); + List<String> ids = new ArrayList<String>(); + while (itr.hasNext()) { + Map.Entry<String, String> entry = itr.next(); + String key = entry.getKey(); + if (!key.startsWith(VARIABLE_PREFIX)) { + + continue; + } + String operations = entry.getValue(); + String id = key.substring(VARIABLE_PREFIX.length()); + + // on interdit la surcharge d'une variable déjà trouvée pour le report + if (ids.contains(id)) { + throw new IllegalArgumentException("La variable " + id + " est déjà définie pour le report " + reportName); + } + + // on interdit l'utilisation de la variable tripId + if (ReportRequest.TRIP_ID_VARIABLE.equals(id)) { + throw new IllegalArgumentException("La variable tripId n'est pas utilisable (c'est uen variable réservée) pour le report " + reportName); + } + ids.add(id); + String[] parts = operations.split("\\|"); + + if (parts.length != 2) { + throw new IllegalArgumentException("La définition d'une variable doit etre de la forme 'type|hql' mais est : " + operations); + } + String typeStr = parts[0].trim(); + String request = parts[1].trim(); + Class<?> type = null; + try { + type = Class.forName(typeStr); + } catch (ClassNotFoundException eee) { + throw new IllegalArgumentException("Le type " + typeStr + " n'est pas connu", eee); + } + ReportVariable variable = new ReportVariable(id, type, request); + if (log.isInfoEnabled()) { + log.info("Detects a variable : [" + reportName + ":" + variable.getName() + "] = " + variable.getRequest() + " (type = " + variable.getType().getName() + ")"); + } + result.add(variable); + itr.remove(); + } + return result.toArray(new ReportVariable[result.size()]); + } + + protected ReportVariable[] getRepeatVariables(String reportName, Map<String, String> dico) { + List<ReportVariable> result = new ArrayList<ReportVariable>(); + Iterator<Map.Entry<String, String>> itr = dico.entrySet().iterator(); + List<String> ids = new ArrayList<String>(); + while (itr.hasNext()) { + Map.Entry<String, String> entry = itr.next(); + String key = entry.getKey(); + if (!key.startsWith(REPEAT_VARIABLE_PREFIX)) { + + continue; + } + String operations = entry.getValue(); + String id = key.substring(REPEAT_VARIABLE_PREFIX.length()); + + // on interdit la surcharge d'une variable déjà trouvée pour le report + if (ids.contains(id)) { + throw new IllegalArgumentException("La variable de répétition " + id + " est déjà définie pour le report " + reportName); + } + + // on interdit l'utilisation de la variable tripId + if (ReportRequest.TRIP_ID_VARIABLE.equals(id)) { + throw new IllegalArgumentException("La variable de répétition tripId n'est pas utilisable (c'est uen variable réservée) pour le report " + reportName); + } + ids.add(id); + String[] parts = operations.split("\\|"); + + if (parts.length != 2) { + throw new IllegalArgumentException("La définition d'une variable de répétition doit etre de la forme 'type|hql' mais est : " + operations); + } + String typeStr = parts[0].trim(); + String request = parts[1].trim(); + Class<?> type = null; + try { + type = Class.forName(typeStr); + } catch (ClassNotFoundException eee) { + throw new IllegalArgumentException("Le type " + type + " n'est pas connu", eee); + } + ReportVariable variable = new ReportVariable(id, type, request); + if (log.isInfoEnabled()) { + log.info("Detects a variable : [" + reportName + ":" + variable.getName() + "] = " + variable.getRequest() + " (type = " + variable.getType().getName() + ")"); + } + result.add(variable); + itr.remove(); + } + return result.toArray(new ReportVariable[result.size()]); + } + + protected ReportOperation getOperation(String operationsDef) { + + // pour le moment, une operations n'a qu'une seule valeur : celle + // du lastName de l'opération + String operationsName = operationsDef; + + ReportOperation def = newOperation(operationsName); + return def; + } + + protected String getValue(Map<String, String> dico, String key) { + + String value = dico.get(key); + if (value != null) { + dico.remove(key); + } + return value; + } + + public void clear() { + if (reportNames != null) { + reportNames.clear(); + reportNames = null; + } + if (properties != null) { + properties.clear(); + properties = null; + } + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/ReportService.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/ReportService.java new file mode 100644 index 0000000..e184862 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/ReportService.java @@ -0,0 +1,20 @@ +package fr.ird.observe.services.service.actions.report; + +import fr.ird.observe.services.ObserveService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; + +import java.util.List; +import java.util.Map; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public interface ReportService extends ObserveService { + + Report populateVariables(Report report, String tripId); + + DataMatrix executeReport(Report report, String tripId); + + <R> List<R> executeRequest(String request, Map<String, Object> params); +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/DataMatrix.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/DataMatrix.java new file mode 100644 index 0000000..c7c8bc6 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/DataMatrix.java @@ -0,0 +1,259 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; + +/** + * Une matrice de données + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class DataMatrix { + + /** Logger */ + private static final Log log = LogFactory.getLog(DataMatrix.class); + + protected Object[][] data; + + protected int width; + + protected int height; + + protected int x; + + protected int y; + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public Object[][] getData() { + return data; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setX(int x) { + this.x = x; + } + + public void setY(int y) { + this.y = y; + } + + public void createData() { + data = new Object[height][width]; + } + + public void setData(Object[][] data) { + this.data = data; + } + + public void copyData(DataMatrix incoming) { + + int x = incoming.getX(); + int y = incoming.getY(); + + Integer height = incoming.getHeight(); + Integer width = incoming.getWidth(); + + if (log.isDebugEnabled()) { + log.debug("copying incoming matrix (dim: " + + incoming.getDimension() + ", location: " + + incoming.getLocation() + ")"); + } + + for (int i = 0; i < width; i++) { + + for (int j = 0; j < height; j++) { + + Serializable value = incoming.getValue(i, j); + setValue(x + i, y + j, value); + } + } + } + + public Dimension getDimension() { + return new Dimension(width, height); + } + + public void setDimension(Dimension dim) { + height = (int) dim.getHeight(); + width = (int) dim.getWidth(); + } + + public Point getLocation() { + return new Point(x, y); + } + + public void setLocation(Point location) { + x = (int) location.getX(); + y = (int) location.getY(); + } + + public Serializable getValue(int x, int y) { + return data == null ? null : (Serializable) data[y][x]; + } + + public void setValue(int x, int y, Object data) { + + String cellData = data == null ? null : String.valueOf(data); + if (log.isDebugEnabled()) { + log.debug("Put data [" + x + "," + y + "] = " + cellData); + } + this.data[y][x] = cellData; + } + + public static Dimension getDimension(DataMatrix... datas) { + int width = 0; + int height = 0; + + for (DataMatrix request : datas) { + + int nWidth = request.getX() + request.getWidth(); + int nHeight = request.getY() + request.getHeight(); + if (nWidth > width) { + width = nWidth; + } + if (nHeight > height) { + height = nHeight; + } + } + return new Dimension(width, height); + } + + public static DataMatrix merge(DataMatrix... incomings) { + DataMatrix result = merge(-1, -1, incomings); + return result; + } + + public static DataMatrix merge(int rows, + int columns, + DataMatrix... incomings) { + Dimension dimension = getDimension(incomings); + + if (log.isDebugEnabled()) { + log.debug("Merge dimension : " + dimension); + } + + if (rows != -1) { + int height = (int) dimension.getHeight(); + // on verifie que récupère bien le bon count de lignes + if (rows != height) { + if (log.isWarnEnabled()) { + log.warn("No matching rows number : should have " + rows + + ", but was " + height); + } + } + } + + if (columns != -1) { + int width = (int) dimension.getWidth(); + // on verifie que récupère bien le bon count de colonnes + if (columns != width) { + if (log.isWarnEnabled()) { + log.warn("No matching columns number : should have " + + columns + ", but was " + width); + } + } + } + + DataMatrix result = new DataMatrix(); + result.setDimension(dimension); + result.createData(); + for (DataMatrix incoming : incomings) { + result.copyData(incoming); + } + return result; + } + + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this); + builder.append("dimension", getDimension()); + builder.append("location", getLocation()); + return builder.toString(); + } + + public String getClipbordContent(boolean copyRowHeaders, + boolean copyColumnHeaders) { + + if (getWidth() <= 0 || getHeight() <= 0) { + return ""; + } + + StringBuilder buffer = new StringBuilder(); + + char sep = '\t'; + char eol = '\n'; + + for (int y = copyColumnHeaders ? 0 : 1, rows = getHeight(); y < rows; y++) { + + Serializable value; + + // nouvell ligne + + int x = copyRowHeaders ? 0 : 1; + + for (int columns = getWidth() - 1; x < columns; x++) { + + // sur chaque cellule (sauf la dernière) + value = getValue(x, y); + buffer.append(value).append(sep); + } + + // dernière cellule + value = getValue(x, y); + buffer.append(value); + + // fin de ligne + buffer.append(eol); + } + return buffer.toString(); + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/Report.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/Report.java new file mode 100644 index 0000000..ea12c0e --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/Report.java @@ -0,0 +1,157 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.Serializable; + +import static org.nuiton.i18n.I18n.t; + +public class Report implements Serializable { + + /** Logger. */ + private static final Log log = LogFactory.getLog(Report.class); + + /** l'id du report. */ + protected final String id; + + /** le libellé court du report. */ + protected final String name; + + /** la description du report. */ + protected final String description; + + /** les libellés des colonnes du report. */ + protected final String[] columnHeaders; + + /** les libellés des lignes du report. */ + protected final String[] rowHeaders; + + /** la liste des requêtes à jouer. */ + protected final ReportRequest[] requests; + + /** la liste des opérations à jouer. */ + protected final ReportOperation[] operations; + + /** la liste des variables du report. */ + protected final ReportVariable[] variables; + + /** la liste des variables de type repeat du report */ + protected final ReportVariable[] repeatVariables; + + private static final long serialVersionUID = 1L; + + public Report(String id, + String name, + String description, + String[] rowHeaders, + String[] columnHeaders, + ReportOperation[] operations, + ReportVariable[] variables, + ReportVariable[] repeatVariables, + ReportRequest... requests) { + this.id = id; + this.name = name; + this.description = description; + this.rowHeaders = rowHeaders; + this.columnHeaders = columnHeaders; + this.requests = requests; + this.operations = operations; + this.variables = variables; + this.repeatVariables = repeatVariables; + if (log.isDebugEnabled()) { + log.debug("New report [" + id + ":" + name + "], nb requests : " + + requests.length + ", nb objectOperations : " + + operations.length + ", nb variables : " + + variables.length + ", nb repeat variables : " + + repeatVariables.length); + } + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public int getRows() { + return rowHeaders == null ? -1 : rowHeaders.length; + } + + public int getColumns() { + return columnHeaders == null ? -1 : columnHeaders.length; + } + + public String[] getColumnHeaders() { + return columnHeaders; + } + + public String[] getRowHeaders() { + return rowHeaders; + } + + public ReportRequest[] getRequests() { + return requests; + } + + public ReportOperation[] getOperations() { + return operations; + } + + public ReportVariable[] getVariables() { + return variables; + } + + public ReportVariable[] getRepeatVariables() { + return repeatVariables; + } + + public boolean isVariableRequired() { + return variables.length > 0; + } + + @Override + public String toString() { + return t(name); + } + + public ReportVariable getRepeatVariable(final String name) { + return Iterables.find(Lists.newArrayList(repeatVariables), new Predicate<ReportVariable>() { + @Override + public boolean apply(ReportVariable reportVariable) { + return name.equals(reportVariable.getName()); + } + }); + } + +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportOperation.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportOperation.java new file mode 100644 index 0000000..c7da96e --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportOperation.java @@ -0,0 +1,106 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model; + +import fr.ird.observe.services.service.actions.report.ReportService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; + +/** + * Pour caractériser une opération à lancer dans un report. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public abstract class ReportOperation implements Serializable { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static final Log log = LogFactory.getLog(ReportOperation.class); + + public abstract String getOperationName(); + + /** + * Calcule la position où positionner le rsultat dans la matrice sortante. + * + * @param model le report + * @param incoming la matrice entrante + * @return la position de la première cellule + */ + protected abstract Point computeLocation(Report model, + DataMatrix incoming); + + /** + * Calcule la dimension du résultat de l'opération. + * + * @param model le report + * @param incoming la matrice entrante + * @return la dimension des données de l'opération + */ + protected abstract Dimension computeDimension(Report model, + DataMatrix incoming); + + /** + * Pour executer l'opération. + * + * @param reportService le service de raport + * @param model le modèle + * @param tripId l'identifiant du la maré + * @param incoming la matrice entrante + * @return la matrice sortante + * @pour toute erreur de manipulation de base + */ + public abstract DataMatrix execute(ReportService reportService, + Report model, + String tripId, + DataMatrix incoming); + + protected ReportOperation() { + } + + protected DataMatrix createTmpMatrix(Report model, DataMatrix incoming) { + + DataMatrix result = new DataMatrix(); + + // calcul de la position des résultats de l'opération + Point location = computeLocation(model, incoming); + result.setLocation(location); + + // calcul de la taille des résultats de l'opération + Dimension dim = computeDimension(model, incoming); + result.setDimension(dim); + + // creation de la matrice + result.createData(); + + if (log.isDebugEnabled()) { + log.debug("Operation [" + getOperationName() + "] tmp matrix : " + result); + } + return result; + } + +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportRequest.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportRequest.java new file mode 100644 index 0000000..bdc6acc --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportRequest.java @@ -0,0 +1,406 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model; + +import com.google.common.collect.Maps; +import fr.ird.observe.services.service.actions.report.ReportService; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Pour caractériser une requète à lancer dans un report. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class ReportRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = LogFactory.getLog(ReportRequest.class); + + public static final String TRIP_ID_VARIABLE = "tripId"; + + /** le layout de la requete. */ + public enum RequestLayout { + /** lorsque les résultats de la requète sont les lignes du résultat. */ + row, + /** lorsque les résultats de la requète sont les colonnes du résultat. */ + column + } + + /** Un repeater optionnel sur la requête. */ + public static class RequestRepeat implements Serializable { + + protected final String variableName; + + protected final RequestLayout layout; + + private static final long serialVersionUID = 1L; + + public RequestRepeat(String variableName, RequestLayout layout) { + this.variableName = variableName; + this.layout = layout; + } + + public String getVariableName() { + return variableName; + } + + public RequestLayout getLayout() { + return layout; + } + + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this); + builder.append("variableName", getVariableName()); + builder.append("layout", getLayout()); + return builder.toString(); + } + } + + /** layout de la requète. */ + protected final RequestLayout layout; + + /** la requète à exécuter. */ + protected final String request; + + /** la position de la requète. */ + protected final Point location; + + /** le repeater optionel. */ + protected final RequestRepeat repeat; + + public ReportRequest(RequestLayout layout, + int x, + int y, + String request, + RequestRepeat repeat) { + this.layout = layout; + this.request = request; + this.repeat = repeat; + location = new Point(x, y); + } + + public RequestLayout getLayout() { + return layout; + } + + public int getX() { + return (int) location.getX(); + } + + public int getY() { + return (int) location.getY(); + } + + public Point getLocation() { + return location; + } + + public String getRequest() { + return request; + } + + public RequestRepeat getRepeat() { + return repeat; + } + + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + ReportVariable repeatValues) { + + DataMatrix result = new DataMatrix(); + + Map<String, Object> params = extractParams(report, tripId); + + for (Object repeatValue : repeatValues.getValues()) { + params.put(repeat.getVariableName(), repeatValue); + DataMatrix tmp = execute(reportService, params); + if (result == null) { + + // premiere requete executee + result = tmp; + result.setX(0); + result.setY(0); + } else { + switch (repeat.getLayout()) { + + case row: + + // on ajoute le resultat a droite de celui deja present + tmp.setX(result.getX() + result.getWidth()); + tmp.setY(result.getY()); + break; + + case column: + + // on ajoute le resultat en dessous de celui deja present + tmp.setX(result.getX()); + tmp.setY(result.getY() + result.getHeight()); + break; + } + result = DataMatrix.merge(result, tmp); + } + } + result.setX(getX()); + result.setY(getY()); + if (log.isDebugEnabled()) { + log.debug("Result location : " + result.getLocation()); + log.debug("Result data :\n" + result.getClipbordContent(true, true)); + } + return result; + } + + public DataMatrix execute(ReportService reportService, + Report report, + String tripId) { + Map<String, Object> params = extractParams(report, tripId); + + DataMatrix dataMatrix = execute(reportService, params); + + return dataMatrix; + + + } + + public static Map<String, Object> extractParams(Report report, String tripId) { + + Map<String, Object> params = Maps.newHashMap(); + + params.put(TRIP_ID_VARIABLE, tripId); + + for (ReportVariable variable : report.getVariables()) { + + String name = variable.getName(); + + Object value = variable.getSelectedValue(); + + params.put(name, value); + + } + return params; + + } + + + protected DataMatrix execute(ReportService reportService, Map<String, Object> params) { + + // création des paramètres : couples (key, value) + if (log.isDebugEnabled()) { + log.debug("Request : " + request); + log.debug("Available params : " + params.keySet()); + log.debug("Params to use : " + params); + } + + // lancement de la requête + List<?> list = reportService.executeRequest(request, params); + if (log.isDebugEnabled()) { + log.debug("Result size : " + list.size()); + } + + // determination des dimensions du résultat + Dimension dimension = computeDimension(list); + if (log.isDebugEnabled()) { + log.debug("Result dimension : " + dimension); + } + + // construction du resultat + DataMatrix result = computeResult(dimension, list); + if (log.isDebugEnabled()) { + log.debug("Result location : " + result.getLocation()); + log.debug("Result data :\n" + result.getClipbordContent(true, true)); + } + return result; + } + + protected DataMatrix computeResult(Dimension dimension, List<?> list) { + + DataMatrix result = new DataMatrix(); + result.setDimension(dimension); + result.createData(); + + // le seul cas différent est le n-* (une ligne correspond à une colonne) + + int y = 0; + int x = 0; + + switch (layout) { + + case row: + + boolean uniqueColumn = result.getWidth() == 1; + + // les lignes du résultat sont les lignes du tableau + + for (Object row : list) { + + if (uniqueColumn) { + + // une seule colonne + result.setValue(0, y, row); + } else { + + x = 0; + Object[] cells = (Object[]) row; + for (Object cell : cells) { + result.setValue(x++, y, cell); + } + } + + // on passage a la ligne suivante + y++; + } + break; + case column: + + // les lignes du résultat sont les colonnes du tableau + + boolean uniqueRow = result.getHeight() == 1; + + for (Object col : list) { + + if (uniqueRow) { + + // une seule ligne + result.setValue(x, 0, col); + } else { + + y = 0; + Object[] cells = (Object[]) col; + for (Object cell : cells) { + result.setValue(x, y++, cell); + } + } + + // on passage a la colonne suivante + x++; + } + break; + } + + // on pousse la position du résultat + result.setX(getX()); + result.setY(getY()); + return result; + } + + protected Dimension computeDimension(List<?> list) { + + int height = 0; + int width = 0; + + switch (layout) { + + case row: + + // le count de result est le lastNamebre de lignes + height = list.size(); + + if (list.isEmpty()) { + + // vu qu'il n'y a pas de résultat, on ne peut rien dire + width = 0; + } else { + + Object o = list.get(0); + + if (o == null || !o.getClass().isArray()) { + + // une seule colonne + width = 1; + } else { + width = ((Object[]) o).length; + } + } + + break; + case column: + + // le count de result est le lastNamebre de colonnes + width = list.size(); + + if (list.isEmpty()) { + + // vu qu'il n'y a pas de résultat, on ne peut rien dire + height = 0; + } else { + + Object o = list.get(0); + + if (o == null || !o.getClass().isArray()) { + + // une seule ligne + height = 1; + } else { + height = ((Object[]) o).length; + } + } + + break; + } + return new Dimension(width, height); + } + + public static Object[] getParams(String request, Map<String, Object> params) { + + // on parcourt la liste de tous les paramètres pour savoir si on doit + // les inclure pour la requête donnée : + List<String> namesToUsed = new ArrayList<String>(); + for (String paramName : params.keySet()) { + if (request.contains(":" + paramName)) { + namesToUsed.add(paramName); + } + } + Object[] datas = new Object[namesToUsed.size() * 2]; + int index = 0; + for (String name : namesToUsed) { + Object value = params.get(name); + datas[index * 2] = name; + datas[index * 2 + 1] = value; + index++; + } + namesToUsed.clear(); + return datas; + } + + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this); + builder.append("request", getRequest()); + builder.append("layout", getLayout()); + builder.append("location", getLocation()); + builder.append("repeatVariable", getRepeat()); + return builder.toString(); + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportVariable.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportVariable.java new file mode 100644 index 0000000..a06f6a0 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/ReportVariable.java @@ -0,0 +1,80 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model; + +import java.io.Serializable; +import java.util.Set; + +/** + * La définition d'une variable utilisable dans un report. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.7 + */ +public class ReportVariable implements Serializable { + + private static final long serialVersionUID = 1L; + + protected String name; + + protected Class type; + + protected String request; + + protected Set values; + + protected Object selectedValue; + + public ReportVariable(String name, Class type, String request) { + this.name = name; + this.type = type; + this.request = request; + } + + public String getName() { + return name; + } + + public Class<?> getType() { + return type; + } + + public String getRequest() { + return request; + } + + public Set getValues() { + return values; + } + + public void setValues(Set values) { + this.values = values; + } + + public Object getSelectedValue() { + return selectedValue; + } + + public void setSelectedValue(Object selectedValue) { + this.selectedValue = selectedValue; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/ExecuteRequests.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/ExecuteRequests.java new file mode 100644 index 0000000..075a7c3 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/ExecuteRequests.java @@ -0,0 +1,120 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model.operations; + +import fr.ird.observe.services.service.actions.report.ReportService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import fr.ird.observe.services.service.actions.report.model.ReportRequest; +import fr.ird.observe.services.service.actions.report.model.ReportVariable; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; + +/** + * Opération pour lancer les requètes d'un report. + * <p/> + * Cette opération est toujours exécuter en premier lors de la construction + * du résultat d'un report. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class ExecuteRequests extends ReportOperation { + + /** Logger */ + private static final Log log = LogFactory.getLog(ExecuteRequests.class); + + private static final long serialVersionUID = 1L; + + public static final String OPERATION_NAME = "ExecuteRequests"; + + public ExecuteRequests() { + } + + public String getOperationName() { + return OPERATION_NAME; + } + + @Override + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + DataMatrix incoming) { + + if (log.isDebugEnabled()) { + log.debug("Launch " + this); + } + + ReportRequest[] requests = report.getRequests(); + + DataMatrix[] requestResults = new DataMatrix[requests.length]; + + int i = 0; + for (ReportRequest request : requests) { + + ReportRequest.RequestRepeat repeatVariable = request.getRepeat(); + + DataMatrix result; + + if (repeatVariable == null) { + + // requete simple sans repetition + result = request.execute(reportService, report, tripId); + } else { + + // on a une requete avec repetition + String repeatVariableName = repeatVariable.getVariableName(); + ReportVariable repeat = report.getRepeatVariable(repeatVariableName); + + + result = request.execute(reportService, report, tripId, repeat); + + + } + + requestResults[i++] = result; + } + + int rows = report.getRows(); + int columns = report.getColumns(); + + DataMatrix result = DataMatrix.merge(rows, columns, requestResults); + return result; + } + + @Override + protected Point computeLocation(Report model, DataMatrix incoming) { + Point result = new Point(0, 0); + return result; + } + + @Override + protected Dimension computeDimension(Report model, DataMatrix incoming) { + + Dimension result = new Dimension(0, 0); + return result; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/GroupByLength.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/GroupByLength.java new file mode 100644 index 0000000..effca69 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/GroupByLength.java @@ -0,0 +1,111 @@ +package fr.ird.observe.services.service.actions.report.model.operations; + +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2015 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + + +import fr.ird.observe.services.service.actions.report.ReportService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import org.apache.commons.lang3.mutable.MutableInt; + +import java.awt.Dimension; +import java.awt.Point; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * To group by legnth (first column, second row is count). + * + * I don't know how to make this with hibernate the group by + sum does not work :(. + * + * Created on 5/23/15. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.0 + */ +public class GroupByLength extends ReportOperation { + + private static final long serialVersionUID = 1L; + + private static final String OPERATION_NAME = "GroupByLength"; + + @Override + public String getOperationName() { + return OPERATION_NAME; + } + + @Override + protected Point computeLocation(Report model, DataMatrix incoming) { + Point result = new Point(0, incoming.getHeight()); + return result; + } + + @Override + protected Dimension computeDimension(Report model, DataMatrix incoming) { + Set<String> lengths = new HashSet<String>(); + for (int i = 0; i < incoming.getHeight(); i++) { + lengths.add((String) incoming.getValue(0, i)); + } + Dimension result = new Dimension(incoming.getWidth(), lengths.size()); + return result; + } + + @Override + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + DataMatrix incoming) { + + // Première passe pour grouper par classe de taille + Map<String, MutableInt> data = new LinkedHashMap<String, MutableInt>(); + for (int i = 0, nbRows = incoming.getHeight(); i < nbRows; i++) { + + String length = (String) incoming.getValue(0, i); + Integer count = Integer.valueOf(incoming.getValue(1, i).toString()); + + MutableInt mutableInt = data.get(length); + if (mutableInt == null) { + mutableInt = new MutableInt(); + data.put(length, mutableInt); + } + mutableInt.add(count); + + } + + // Deuxième passe pour remplir la matrice + DataMatrix result = createTmpMatrix(report, incoming); + int row = 0; + for (Map.Entry<String, MutableInt> entry : data.entrySet()) { + String length = entry.getKey(); + MutableInt mutableInt = entry.getValue(); + result.setValue(0, row, length); + result.setValue(1, row, mutableInt.intValue()); + row++; + } + + return result; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumColumn.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumColumn.java new file mode 100644 index 0000000..eb88fd2 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumColumn.java @@ -0,0 +1,129 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model.operations; + + +import fr.ird.observe.services.service.actions.report.ReportService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; + +/** + * Opération pour calculer la somme de toutes les cellules d'une colonne. + * <p/> + * Le résultat de l'opération vient se placer dans une nouvelle ligne en bas + * du tableau. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class SumColumn extends ReportOperation { + + /** Logger */ + private static final Log log = + LogFactory.getLog(SumColumn.class); + + private static final long serialVersionUID = 1L; + + private static final String OPERATION_NAME = "SumColumn"; + + + public SumColumn() { + } + + public String getOperationName() { + return OPERATION_NAME; + } + + @Override + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + DataMatrix incoming) { + + if (log.isDebugEnabled()) { + log.debug("Launch " + this); + } + + // construction du resultat + + DataMatrix tmpMatrix = createTmpMatrix(report, incoming); + + for (int i = 0, nbColumns = incoming.getWidth(); i < nbColumns; i++) { + + Object result = getColumnData(i, incoming); + tmpMatrix.setValue(i, 0, result); + if (log.isDebugEnabled()) { + log.debug("objectOperation [" + i + ",0] = " + result); + } + } + + DataMatrix result = DataMatrix.merge(incoming, tmpMatrix); + return result; + } + + protected Object getColumnData(int column, DataMatrix incoming) { + Double result = 0d; + + int nbRows = incoming.getHeight(); + + for (int row = 0; row < nbRows; row++) { + Serializable o = incoming.getValue(column, row); + + if (o == null || "null".equals(o)) { + o = 0; + } + Double d; + try { + d = Double.valueOf(o.toString()); + } catch (NumberFormatException e) { + // une des données de la colonne n'est pas un count + // on sort directement + if (log.isDebugEnabled()) { + log.debug("Could not convert " + o + " to number", e); + } + return "-"; + } + result += d; + } + + return result; + } + + @Override + protected Point computeLocation(Report model, DataMatrix incoming) { + Point result = new Point(0, incoming.getHeight()); + return result; + } + + @Override + protected Dimension computeDimension(Report model, DataMatrix incoming) { + Dimension result = new Dimension(incoming.getWidth(), 1); + return result; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumIntColumn.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumIntColumn.java new file mode 100644 index 0000000..364a07a --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumIntColumn.java @@ -0,0 +1,129 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model.operations; + + +import fr.ird.observe.services.service.actions.report.ReportService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; + +/** + * Opération pour calculer la somme entière de toutes les cellules d'une colonne. + * <p/> + * Le résultat de l'opération vient se placer dans une nouvelle ligne en bas + * du tableau. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class SumIntColumn extends ReportOperation { + + /** Logger */ + private static final Log log = + LogFactory.getLog(SumIntColumn.class); + + private static final long serialVersionUID = 1L; + + private static final String OPERATION_NAME = "SumIntColumn"; + + + public SumIntColumn() { + } + + public String getOperationName() { + return OPERATION_NAME; + } + + @Override + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + DataMatrix incoming) { + + if (log.isDebugEnabled()) { + log.debug("Launch " + this); + } + + // construction du resultat + + DataMatrix tmpMatrix = createTmpMatrix(report, incoming); + + for (int i = 0, nbColumns = incoming.getWidth(); i < nbColumns; i++) { + + Object result = getColumnData(i, incoming); + tmpMatrix.setValue(i, 0, result); + if (log.isDebugEnabled()) { + log.debug("objectOperation [" + i + ",0] = " + result); + } + } + + DataMatrix result = DataMatrix.merge(incoming, tmpMatrix); + return result; + } + + protected Object getColumnData(int column, DataMatrix incoming) { + Double result = 0d; + + int nbRows = incoming.getHeight(); + + for (int row = 0; row < nbRows; row++) { + Serializable o = incoming.getValue(column, row); + + if (o == null || "null".equals(o)) { + o = 0; + } + Double d; + try { + d = Double.valueOf(o.toString()); + } catch (NumberFormatException e) { + // une des données de la colonne n'est pas un count + // on sort directement + if (log.isDebugEnabled()) { + log.debug("Could not convert " + o + " to number", e); + } + return "-"; + } + result += d; + } + + return result.intValue(); + } + + @Override + protected Point computeLocation(Report model, DataMatrix incoming) { + Point result = new Point(0, incoming.getHeight()); + return result; + } + + @Override + protected Dimension computeDimension(Report model, DataMatrix incoming) { + Dimension result = new Dimension(incoming.getWidth(), 1); + return result; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumIntRow.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumIntRow.java new file mode 100644 index 0000000..66d2038 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumIntRow.java @@ -0,0 +1,129 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model.operations; + + +import fr.ird.observe.services.service.actions.report.ReportService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; + +/** + * Opération pour calculer la somme entière de toutes les cellules d'une ligne. + * <p/> + * Le résultat de l'opération vient se placer dans une nouvelle colonne à + * droite du tableau. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class SumIntRow extends ReportOperation { + + /** Logger */ + private static final Log log = LogFactory.getLog(SumIntRow.class); + + public static final String OPERATION_NAME = "SumIntRow"; + + private static final long serialVersionUID = 1L; + + public SumIntRow() { + } + + public String getOperationName() { + return OPERATION_NAME; + } + + @Override + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + DataMatrix incoming) { + if (log.isDebugEnabled()) { + log.debug("Launch " + this); + } + + // construction du result + + DataMatrix tmpMatrix = createTmpMatrix(report, incoming); + + for (int i = 0, nbRows = incoming.getHeight(); i < nbRows; i++) { + + Object result = getRowData(i, incoming); + tmpMatrix.setValue(0, i, result); + if (log.isDebugEnabled()) { + log.debug("objectOperation [0, " + i + "] = " + result); + } + } + + DataMatrix result = DataMatrix.merge(incoming, tmpMatrix); + return result; + } + + + protected Object getRowData(int row, DataMatrix incoming) { + + Double result = 0d; + + int nbColumns = incoming.getWidth(); + + for (int col = 0; col < nbColumns; col++) { + Serializable o = incoming.getValue(col, row); + + if (o == null || "null".equals(o)) { + o = 0; + } + Double d; + try { + d = Double.valueOf(o.toString()); + } catch (NumberFormatException e) { + // une des données de la colonne n'est pas un count + // on sort directement + if (log.isDebugEnabled()) { + log.debug("Could not convert " + o + " to number", e); + } + return "-"; + } + result += d; + } + + return result.intValue(); + } + + @Override + protected Point computeLocation(Report model, DataMatrix incoming) { + Point result = new Point(incoming.getWidth(), 0); + return result; + } + + @Override + protected Dimension computeDimension(Report model, DataMatrix incoming) { + + Dimension result = new Dimension(1, incoming.getHeight()); + return result; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumRow.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumRow.java new file mode 100644 index 0000000..438da89 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/report/model/operations/SumRow.java @@ -0,0 +1,129 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ +package fr.ird.observe.services.service.actions.report.model.operations; + + +import fr.ird.observe.services.service.actions.report.ReportService; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.io.Serializable; + +/** + * Opération pour calculer la somme de toutes les cellules d'une ligne. + * <p/> + * Le résultat de l'opération vient se placer dans une nouvelle colonne à + * droite du tableau. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class SumRow extends ReportOperation { + + /** Logger */ + private static final Log log = LogFactory.getLog(SumRow.class); + + public static final String OPERATION_NAME = "SumRow"; + + private static final long serialVersionUID = 1L; + + public SumRow() { + } + + public String getOperationName() { + return OPERATION_NAME; + } + + @Override + public DataMatrix execute(ReportService reportService, + Report report, + String tripId, + DataMatrix incoming) { + if (log.isDebugEnabled()) { + log.debug("Launch " + this); + } + + // construction du result + + DataMatrix tmpMatrix = createTmpMatrix(report, incoming); + + for (int i = 0, nbRows = incoming.getHeight(); i < nbRows; i++) { + + Object result = getRowData(i, incoming); + tmpMatrix.setValue(0, i, result); + if (log.isDebugEnabled()) { + log.debug("objectOperation [0, " + i + "] = " + result); + } + } + + DataMatrix result = DataMatrix.merge(incoming, tmpMatrix); + return result; + } + + + protected Object getRowData(int row, DataMatrix incoming) { + + Double result = 0d; + + int nbColumns = incoming.getWidth(); + + for (int col = 0; col < nbColumns; col++) { + Serializable o = incoming.getValue(col, row); + + if (o == null || "null".equals(o)) { + o = 0; + } + Double d; + try { + d = Double.valueOf(o.toString()); + } catch (NumberFormatException e) { + // une des données de la colonne n'est pas un count + // on sort directement + if (log.isDebugEnabled()) { + log.debug("Could not convert " + o + " to number", e); + } + return "-"; + } + result += d; + } + + return result; + } + + @Override + protected Point computeLocation(Report model, DataMatrix incoming) { + Point result = new Point(incoming.getWidth(), 0); + return result; + } + + @Override + protected Dimension computeDimension(Report model, DataMatrix incoming) { + + Dimension result = new Dimension(1, incoming.getHeight()); + return result; + } +} diff --git a/observe-services-api/src/main/resources/META-INF/services/fr.ird.observe.services.service.actions.report.model.ReportOperation b/observe-services-api/src/main/resources/META-INF/services/fr.ird.observe.services.service.actions.report.model.ReportOperation new file mode 100644 index 0000000..10334f3 --- /dev/null +++ b/observe-services-api/src/main/resources/META-INF/services/fr.ird.observe.services.service.actions.report.model.ReportOperation @@ -0,0 +1,6 @@ +fr.ird.observe.services.service.actions.report.model.operations.SumIntColumn +fr.ird.observe.services.service.actions.report.model.operations.SumColumn +fr.ird.observe.services.service.actions.report.model.operations.SumIntRow +fr.ird.observe.services.service.actions.report.model.operations.SumRow +fr.ird.observe.services.service.actions.report.model.operations.ExecuteRequests +fr.ird.observe.services.service.actions.report.model.operations.GroupByLength \ No newline at end of file diff --git a/observe-services-api/src/test/java/fr/ird/observe/services/service/actions/report/ReportBuilderTest.java b/observe-services-api/src/test/java/fr/ird/observe/services/service/actions/report/ReportBuilderTest.java new file mode 100644 index 0000000..d63920f --- /dev/null +++ b/observe-services-api/src/test/java/fr/ird/observe/services/service/actions/report/ReportBuilderTest.java @@ -0,0 +1,130 @@ +package fr.ird.observe.services.service.actions.report; + +import fr.ird.observe.services.dto.referential.SpeciesGroupDto; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import fr.ird.observe.services.service.actions.report.model.ReportRequest; +import fr.ird.observe.services.service.actions.report.model.ReportVariable; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.net.URL; +import java.util.List; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ReportBuilderTest { + + ReportBuilder reportBuilder; + + @Before + public void beforeTest() { + reportBuilder = new ReportBuilder(); + } + + + @Test + public void loadTest() throws Exception { + URL reportFileUrl = getClass().getResource("observe-reports-test.properties"); + + List<Report> reports = reportBuilder.load(reportFileUrl); + + Assert.assertNotNull(reports); + Assert.assertEquals(2, reports.size()); + + /* + Report 1 + */ + + Report report1 = reports.get(0); + + Assert.assertNotNull(report1); + Assert.assertEquals("reportOne", report1.getId()); + Assert.assertEquals("Rapport numéro 1", report1.getName()); + Assert.assertEquals("Description du rapport numéro 1", report1.getDescription()); + Assert.assertEquals(4, report1.getColumns()); + Assert.assertEquals("Colonne 1", report1.getColumnHeaders()[0]); + Assert.assertEquals("Colonne 2", report1.getColumnHeaders()[1]); + Assert.assertEquals("Colonne 3", report1.getColumnHeaders()[2]); + Assert.assertEquals("Dernière colonne", report1.getColumnHeaders()[3]); + + Assert.assertEquals(0, report1.getVariables().length); + Assert.assertEquals(0, report1.getRepeatVariables().length); + Assert.assertEquals(0, report1.getOperations().length); + Assert.assertEquals(1, report1.getRequests().length); + + ReportRequest request1_1 = report1.getRequests()[0]; + Assert.assertNotNull(request1_1); + Assert.assertEquals(0, request1_1.getX()); + Assert.assertEquals(0, request1_1.getY()); + Assert.assertEquals("Select * from uneTable;", request1_1.getRequest()); + + /* + Report 2 + */ + + Report report2 = reports.get(1); + + Assert.assertNotNull(report2); + Assert.assertEquals("reportTwo", report2.getId()); + Assert.assertEquals("Rapport numéro 2", report2.getName()); + Assert.assertEquals("Description du rapport numéro 2", report2.getDescription()); + Assert.assertEquals(5, report2.getColumns()); + Assert.assertEquals("Colonne 1", report2.getColumnHeaders()[0]); + Assert.assertEquals("Colonne 2", report2.getColumnHeaders()[1]); + Assert.assertEquals("Colonne 3", report2.getColumnHeaders()[2]); + Assert.assertEquals("Avant dernière colonne", report2.getColumnHeaders()[3]); + Assert.assertEquals("Total", report2.getColumnHeaders()[4]); + + Assert.assertEquals(1, report2.getVariables().length); + ReportVariable variable = report2.getVariables()[0]; + Assert.assertNotNull(variable); + Assert.assertEquals("groupId", variable.getName()); + Assert.assertEquals(SpeciesGroupDto.class, variable.getType()); + Assert.assertEquals("From SpeciesGroupImpl ge Order By ge.code", variable.getRequest()); + Assert.assertNull(variable.getValues()); + Assert.assertNull(variable.getSelectedValue()); + + Assert.assertEquals(1, report2.getRepeatVariables().length); + ReportVariable repeatVariable = report2.getRepeatVariables()[0]; + Assert.assertNotNull(repeatVariable); + Assert.assertEquals("typeObjetId", repeatVariable.getName()); + Assert.assertEquals(String.class, repeatVariable.getType()); + Assert.assertEquals("Select id from uneTable where group = :groupId order By code;", repeatVariable.getRequest()); + Assert.assertNull(repeatVariable.getValues()); + Assert.assertNull(repeatVariable.getSelectedValue()); + + + Assert.assertEquals(1, report2.getOperations().length); + ReportOperation operation = report2.getOperations()[0]; + Assert.assertNotNull(operation); + Assert.assertEquals("SumRow", operation.getOperationName()); + + + Assert.assertEquals(2, report2.getRequests().length); + + ReportRequest request2_1 = report2.getRequests()[0]; + Assert.assertNotNull(request2_1); + Assert.assertEquals(0, request2_1.getX()); + Assert.assertEquals(0, request2_1.getY()); + Assert.assertEquals("Select * from uneTable where id = :typeObjectId;", request2_1.getRequest()); + ReportRequest.RequestRepeat repeat1 = request2_1.getRepeat(); + Assert.assertNotNull(repeat1); + Assert.assertEquals("typeObjetId", repeat1.getVariableName()); + Assert.assertEquals(ReportRequest.RequestLayout.column, repeat1.getLayout()); + + ReportRequest request2_2 = report2.getRequests()[0]; + Assert.assertNotNull(request2_2); + Assert.assertEquals(0, request2_2.getX()); + Assert.assertEquals(0, request2_2.getY()); + Assert.assertEquals("Select * from uneTable where id = :typeObjectId;", request2_2.getRequest()); + ReportRequest.RequestRepeat repeat2 = request2_2.getRepeat(); + Assert.assertNotNull(repeat2); + Assert.assertEquals("typeObjetId", repeat2.getVariableName()); + Assert.assertEquals(ReportRequest.RequestLayout.column, repeat2.getLayout()); + + } + +} diff --git a/observe-services-api/src/test/resources/fr/ird/observe/services/service/actions/report/observe-reports-test.properties b/observe-services-api/src/test/resources/fr/ird/observe/services/service/actions/report/observe-reports-test.properties new file mode 100644 index 0000000..fe3a896 --- /dev/null +++ b/observe-services-api/src/test/resources/fr/ird/observe/services/service/actions/report/observe-reports-test.properties @@ -0,0 +1,27 @@ +################################################################################ +## Rapport 1 : +################################################################################ + +report.reportOne.name=Rapport num\u00e9ro 1 +report.reportOne.description=Description du rapport num\u00e9ro 1 +report.reportOne.columns=Colonne 1, Colonne 2, Colonne 3, Derni\u00e8re colonne +report.reportOne.request.1=0,0|row|\ + Select * from uneTable; + +################################################################################ +## Rapport 2 : +################################################################################ + +report.reportTwo.name=Rapport num\u00e9ro 2 +report.reportTwo.description=Description du rapport num\u00e9ro 2 +report.reportTwo.columns=Colonne 1, Colonne 2, Colonne 3, Avant derni\u00e8re colonne, Total +report.reportTwo.operations.1=SumRow +report.reportTwo.variable.groupId=fr.ird.observe.services.dto.referential.SpeciesGroupDto|From SpeciesGroupImpl ge Order By ge.code +report.reportTwo.repeatVariable.typeObjetId=java.lang.String|\ + Select id from uneTable where group = :groupId order By code; +report.reportTwo.request.1=0,0|row|\ + Select * from uneTable where id = :typeObjectId; +report.reportTwo.request.1.repeat=typeObjetId|column +report.reportTwo.request.2=1,0|row|\ + Select * from uneAutreTable where id = :typeObjectId; +report.reportTwo.request.2.repeat=typeObjetId|column \ No newline at end of file diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/report/ReportServiceTopia.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/report/ReportServiceTopia.java new file mode 100644 index 0000000..00a26de --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/report/ReportServiceTopia.java @@ -0,0 +1,207 @@ +package fr.ird.observe.services.service.actions.report; + +import com.google.common.collect.Maps; +import fr.ird.observe.AbstractObserveTopiaDao; +import fr.ird.observe.entities.seine.TripSeine; +import fr.ird.observe.services.ObserveServiceTopia; +import fr.ird.observe.services.dto.IdDto; +import fr.ird.observe.services.dto.ReferenceDto; +import fr.ird.observe.services.service.actions.report.model.DataMatrix; +import fr.ird.observe.services.service.actions.report.model.Report; +import fr.ird.observe.services.service.actions.report.model.ReportOperation; +import fr.ird.observe.services.service.actions.report.model.ReportRequest; +import fr.ird.observe.services.service.actions.report.model.ReportVariable; +import fr.ird.observe.services.service.actions.report.model.operations.ExecuteRequests; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.persistence.TopiaEntity; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ReportServiceTopia extends ObserveServiceTopia implements ReportService { + + private static final Log log = LogFactory.getLog(ReportServiceTopia.class); + + @Override + public Report populateVariables(Report report, String tripId) { + + Map<String, Object> vars = new TreeMap<String, Object>(); + + vars.put(ReportRequest.TRIP_ID_VARIABLE, tripId); + + for (ReportVariable variable : report.getVariables()) { + + LinkedHashSet<Object> values = new LinkedHashSet<>(); + + String hql = variable.getRequest(); + + Class<?> type = variable.getType(); + + if (IdDto.class.isAssignableFrom(type)) { + + Class<? extends IdDto> dtoType = (Class<? extends IdDto>) type; + + List<TopiaEntity> universe = executeRequest(hql, vars); + + for (TopiaEntity entity : universe) { + + ReferenceDto<?> dto = entityToReferenceDto(dtoType, entity); + + values.add(dto); + + } + + } else { + + List<Object> universe = executeRequest(hql, vars); + + values.addAll(universe); + + } + + variable.setValues(values); + } + + return report; + + } + + @Override + public DataMatrix executeReport(Report report, String tripId) { + + if (report == null) { + + // pas de report selectionne, donc pas de résultat + return null; + } + + if (!canExecute(report)) { + + // la requete n'est pas exécutable + return null; + } + + // remplissage des variables de répétition si nécessaire + doPopulateRepeatVariables(report, tripId); + + if (log.isDebugEnabled()) { + log.debug("Build result for report [" + report.getName() + + "] on " + tripId); + } + + int rows = report.getRows(); + int columns = report.getColumns(); + + if (log.isDebugEnabled()) { + log.debug("Dimension : [" + rows + "," + columns + "]"); + } + + + + // creation de la première opération qui exécute les requètes + ReportOperation firstRequest = ReportBuilder.newOperation(ExecuteRequests.OPERATION_NAME); + + // lancement de la première opération et la matrice de resultat + DataMatrix result = firstRequest.execute( + this, + report, + tripId, + new DataMatrix()); + + // lancement des opérations supplémentaires + for (ReportOperation objectOperation : report.getOperations()) { + + DataMatrix tmp = result; + if (log.isDebugEnabled()) { + log.debug("Apply objectOperation " + objectOperation + " to " + tmp); + } + result = objectOperation.execute( + this, + report, + tripId, + tmp); + } + if (log.isDebugEnabled()) { + log.debug("Final result : " + result); + } + return result; + } + + @Override + public <R> List<R> executeRequest(String request, Map<String, Object> params) { + + // si il y a des references de DTO dans les valeur des paramètres on les remplace par leur id + // on copie pour ne pas modifier le paramètre de la méthode + Map<String, Object> paramsFixes = Maps.newHashMap(); + + for (Map.Entry<String, Object> entry : params.entrySet()) { + + String name = entry.getKey(); + + if (request.contains(":" + name)) { + + Object value = entry.getValue(); + + if (value instanceof ReferenceDto) { + ReferenceDto referenceDto = (ReferenceDto) value; + + value = referenceDto.getId(); + + } + + paramsFixes.put(name, value); + } + + } + + AbstractObserveTopiaDao dao = (AbstractObserveTopiaDao) getTopiaPersistenceContext().getDao(TripSeine.class); + + List<R> result = dao.findAllFromHql(request, paramsFixes); + + return result; + } + + public boolean canExecute(Report report) { + + for (ReportVariable variable : report.getVariables()) { + + // on verifie qu'on a bien cette variable + String name = variable.getName(); + if (variable.getSelectedValue() == null) { + + if (log.isInfoEnabled()) { + log.info("variable " + name + " is missing"); + } + return false; + } + } + + // le report peut-être executé + return true; + } + + protected void doPopulateRepeatVariables(Report report, String tripId) { + + Map<String, Object> vars = ReportRequest.extractParams(report, tripId); + + for (ReportVariable variable : report.getRepeatVariables()) { + + String hql = variable.getRequest(); + + List<Object> universe = executeRequest(hql, vars); + + LinkedHashSet<Object> values = new LinkedHashSet<>(universe); + + variable.setValues(values); + } + + + } + +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.