Author: chatellier Date: 2010-11-18 11:06:46 +0000 (Thu, 18 Nov 2010) New Revision: 231 Log: Ajout du control de differences entre les captures et taille Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/services/ValidationService.java trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/services/ValidationService.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/services/ValidationService.java 2010-11-18 11:05:04 UTC (rev 230) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/services/ValidationService.java 2010-11-18 11:06:46 UTC (rev 231) @@ -35,6 +35,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.xwork.StringUtils; @@ -194,17 +196,8 @@ * @return les erreurs de validation */ public List<ValidationError> validateData(Project project, Control control, ProgressMonitor progress) { - - // compte le nombre de category a valider - int categoryCount = 0; - for (Category category : Category.values()) { - if (category.isDataCategory()) { - categoryCount++; - } - } - + // valide chaque category - int categoryIndex = 0; List<ValidationError> validationErrors = new ArrayList<ValidationError>(); for (Category category : Category.values()) { if (category.isDataCategory()) { @@ -221,6 +214,12 @@ } } + // validation entre catch et length (specific) + List<ValidationError> diffCatchLengthErrors = validateDiffCatchLength(control); + if (diffCatchLengthErrors != null) { + validationErrors.addAll(diffCatchLengthErrors); + } + // validation par croisement de fichiers List<ValidationError> crossFileErrors = validationCrossFiles(project, control, progress); if (crossFileErrors != null) { @@ -541,6 +540,133 @@ } /** + * Detecte des différences entre les nombres dans captures + * et les nombres dand taille. + * + * @see ChartService#getCompareCatchLengthGraph(Project, Control, String) for details + * @see CoserBusinessConfig#getControlDiffCatchLength() for option + * + * @return errors + */ + protected List<ValidationError> validateDiffCatchLength(Control control) { + + List<ValidationError> validationErrors = new ArrayList<ValidationError>(); + SortedSet<String> setYear = new TreeSet<String>(); + + // look for data (data summed over catch) + Map<String, Map<String, Double>> catchForSpeciesYears = new HashMap<String, Map<String, Double>>(); + Iterator<String[]> itCatchData = control.getCatch().iterator(); + itCatchData.next(); // header + while (itCatchData.hasNext()) { + String[] tuple = itCatchData.next(); + String species = tuple[Catch.INDEX_SPECIES]; + + Map<String, Double> speciesCatchForYears = catchForSpeciesYears.get(species); + if (speciesCatchForYears == null) { + speciesCatchForYears = new HashMap<String, Double>(); + catchForSpeciesYears.put(species, speciesCatchForYears); + } + + String year = tuple[Catch.INDEX_YEAR]; + setYear.add(year); + String nombreValue = tuple[Catch.INDEX_NUMBER]; + try { + Double nombreDouble = Double.valueOf(nombreValue); + + if (speciesCatchForYears.containsKey(year)) { + Double oldValue = speciesCatchForYears.get(year); + Double newValue = oldValue + nombreDouble; + speciesCatchForYears.put(year, newValue); + } + else { + speciesCatchForYears.put(year, nombreDouble); + } + } + catch (NumberFormatException ex) { + if (log.isWarnEnabled()) { + log.warn("Can't parse " + nombreValue + " as double"); + } + } + } + + // look for data (data summed over length) + Map<String, Map<String, Double>> lengthForSpeciesYears = new HashMap<String, Map<String, Double>>(); + Iterator<String[]> itLengthData = control.getLength().iterator(); + itLengthData.next(); // header + while (itLengthData.hasNext()) { + String[] tuple = itLengthData.next(); + String species = tuple[Length.INDEX_SPECIES]; + + Map<String, Double> speciesLengthForYears = lengthForSpeciesYears.get(species); + if (speciesLengthForYears == null) { + speciesLengthForYears = new HashMap<String, Double>(); + lengthForSpeciesYears.put(species, speciesLengthForYears); + } + + String year = tuple[Length.INDEX_YEAR]; + setYear.add(year); + String nombreValue = tuple[Length.INDEX_NUMBER]; + try { + Double nombreDouble = Double.valueOf(nombreValue); + + if (speciesLengthForYears.containsKey(year)) { + Double oldValue = speciesLengthForYears.get(year); + Double newValue = oldValue + nombreDouble; + speciesLengthForYears.put(year, newValue); + } + else { + speciesLengthForYears.put(year, nombreDouble); + } + } + catch (NumberFormatException ex) { + if (log.isWarnEnabled()) { + log.warn("Can't parse " + nombreValue + " as double"); + } + } + } + + // check for all species and years + for (Map.Entry<String, Map<String, Double>> catchEntries : catchForSpeciesYears.entrySet()) { + String species = catchEntries.getKey(); + Map<String, Double> catchNumbers = catchEntries.getValue(); + Map<String, Double> lengthNumbers = lengthForSpeciesYears.get(species); + + if (lengthNumbers == null) { + // on suppose que cette erreur est détectée par un autre controle + continue; + } + + Iterator<String> itYears = setYear.iterator(); + while (itYears.hasNext()) { + String year = itYears.next(); + + Double catchNumber = catchNumbers.get(year); + Double lengthNumber = lengthNumbers.get(year); + if (catchNumber == null) { + catchNumber = 0.0; // marche pou NA + } + if (lengthNumber == null) { + lengthNumber = 0.0; // marche pour NA + } + + // diff entre 4 et 5 = (5-4) * 100 / 5 + double diff = (Math.max(catchNumber, lengthNumber) - + Math.min(catchNumber, lengthNumber)) * 100 / Math.max(catchNumber, lengthNumber); + + if (diff > config.getControlDiffCatchLength()) { + ValidationError error = new ValidationError(); + error.setLevel(ValidationLevel.WARNING); + error.setMessage(_("coser.business.control.error.diffCatchLength")); + error.setMessage(_("coser.business.control.error.diffCatchLengthDetail", species, year)); + validationErrors.add(error); + } + } + } + + return validationErrors; + } + + /** * Alerte si Somme(TAILLES$Nombre par TAILLES$Annee|Strate|Espece) < nobsmin * * @param control @@ -774,6 +900,13 @@ // Vérifier que les mêmes années sont présentes dans fichiers captures // traits et tailles: CAPTURES$Annee, TRAITS$Annee, TAILLES$Annee. if (!catchYear.equals(lengthYear) || !haulYear.equals(lengthYear)) { + + if (log.isDebugEnabled()) { + log.debug("Catch year = " + catchYear); + log.debug("Length year = " + lengthYear); + log.debug("Haul year = " + haulYear); + } + ValidationError error = new ValidationError(); error.setLevel(ValidationLevel.FATAL); error.setMessage(_("coser.business.control.error.yearsNotEquals")); @@ -786,7 +919,7 @@ ValidationError error = new ValidationError(); error.setLevel(ValidationLevel.FATAL); error.setMessage(_("coser.business.control.error.surveyNotEquals")); - error.setDetailMessage(_("coser.business.control.error.surveyNotEquals")); + //error.setDetailMessage(_("coser.business.control.error.surveyNotEquals")); crossFilesErrors.add(error); } @@ -797,7 +930,7 @@ ValidationError error = new ValidationError(); error.setLevel(ValidationLevel.FATAL); error.setMessage(_("coser.business.control.error.incompleteHaulSpeciesData")); - error.setDetailMessage(_("coser.business.control.error.incompleteHaulSpeciesData")); + //error.setDetailMessage(_("coser.business.control.error.incompleteHaulSpeciesData")); crossFilesErrors.add(error); } @@ -808,7 +941,7 @@ ValidationError error = new ValidationError(); error.setLevel(ValidationLevel.FATAL); error.setMessage(_("coser.business.control.error.incompleteHaulDataLength")); - error.setDetailMessage(_("coser.business.control.error.incompleteHaulDataLength")); + //error.setDetailMessage(_("coser.business.control.error.incompleteHaulDataLength")); crossFilesErrors.add(error); } @@ -819,7 +952,7 @@ ValidationError error = new ValidationError(); error.setLevel(ValidationLevel.FATAL); error.setMessage(_("coser.business.control.error.incompleteHaulDataCatch")); - error.setDetailMessage(_("coser.business.control.error.incompleteHaulDataCatch")); + //error.setDetailMessage(_("coser.business.control.error.incompleteHaulDataCatch")); crossFilesErrors.add(error); } Modified: trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties =================================================================== --- trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties 2010-11-18 11:05:04 UTC (rev 230) +++ trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties 2010-11-18 11:06:46 UTC (rev 231) @@ -35,6 +35,7 @@ coser.business.common.number= coser.business.common.year= coser.business.control.error.diffCatchLength= +coser.business.control.error.diffCatchLengthDetail= coser.business.control.error.duplicatedLine= coser.business.control.error.incompleteHaulDataCatch= coser.business.control.error.incompleteHaulDataLength= Modified: trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties =================================================================== --- trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties 2010-11-18 11:05:04 UTC (rev 230) +++ trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties 2010-11-18 11:06:46 UTC (rev 231) @@ -34,7 +34,8 @@ coser.business.chart.compareCatchLengthNumberTitle=Comparaison des nombre dans Capture et Taille coser.business.common.number=Nombre coser.business.common.year=Ann\u00E9e -coser.business.control.error.diffCatchLength=Diff\u00E9rence entre les captures et taille pour l'esp\u00E8ce %s (ann\u00E9e %s) +coser.business.control.error.diffCatchLength=Diff\u00E9rence entre les captures et taille +coser.business.control.error.diffCatchLengthDetail=Diff\u00E9rence entre les captures et taille pour l'esp\u00E8ce %s (ann\u00E9e %s) coser.business.control.error.duplicatedLine=Ligne en doublon coser.business.control.error.incompleteHaulDataCatch=Certains couples Annee|Trait ne sont pas pr\u00E9sents dans les captures coser.business.control.error.incompleteHaulDataLength=Certains couples Annee|Trait ne sont pas pr\u00E9sents dans les tailles