Author: chatellier Date: 2010-10-28 13:42:45 +0000 (Thu, 28 Oct 2010) New Revision: 115 Log: Gestion des doublons Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlValidationRenderer.java Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/control/ProgressMonitor.java trunk/coser-business/src/main/java/fr/ifremer/coser/control/ValidationError.java trunk/coser-business/src/main/java/fr/ifremer/coser/services/ValidationService.java trunk/coser-business/src/test/java/fr/ifremer/coser/services/ValidationServiceTest.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlDataTableModel.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlHandler.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlProgressBar.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlView.jaxx trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/GlobalValidationModel.java Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/control/ProgressMonitor.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/control/ProgressMonitor.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/control/ProgressMonitor.java 2010-10-28 13:42:45 UTC (rev 115) @@ -39,4 +39,6 @@ void setCurrent(int current); void setTotal(int total); + + void setText(String text); } Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/control/ValidationError.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/control/ValidationError.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/control/ValidationError.java 2010-10-28 13:42:45 UTC (rev 115) @@ -48,27 +48,16 @@ /** Niveau de l'erreur (fatal, error, warning, info). */ protected ValidationLevel level; - /** Champ sur lequel porte l'erreur de validation. */ - protected String field; - /** Message explicitant l'erreur de validation. */ protected String message; /** Numero de la ligne dans le fichier CSV (header non compté). */ - protected int lineNumber; + protected String lineNumber; public ValidationError() { super(); } - public ValidationError(ValidationLevel level, String field, String message, int lineNumber) { - this(); - this.level = level; - this.field = field; - this.message = message; - this.lineNumber = lineNumber; - } - /** * Niveau de l'erreur (fatal, error, warning, info). * @@ -88,24 +77,6 @@ } /** - * Champ sur lequel porte l'erreur de validation. - * - * @return field - */ - public String getField() { - return field; - } - - /** - * Champ sur lequel porte l'erreur de validation. - * - * @param field - */ - public void setField(String field) { - this.field = field; - } - - /** * Message explicitant l'erreur de validation. * * @return message @@ -124,20 +95,20 @@ } /** - * Numero de la ligne dans le fichier CSV (header non compté). + * Numero de la ligne dans le fichier CSV. * * @return line number */ - public int getLineNumber() { + public String getLineNumber() { return lineNumber; } /** - * Numero de la ligne dans le fichier CSV (header non compté). + * Numero de la ligne dans le fichier CSV. * * @param lineNumber line number */ - public void setLineNumber(int lineNumber) { + public void setLineNumber(String lineNumber) { this.lineNumber = lineNumber; } 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-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/services/ValidationService.java 2010-10-28 13:42:45 UTC (rev 115) @@ -25,10 +25,14 @@ package fr.ifremer.coser.services; +import static org.nuiton.i18n.I18n._; + import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.commons.lang.xwork.StringUtils; import org.apache.commons.logging.Log; @@ -52,6 +56,7 @@ import fr.ifremer.coser.bean.Control; import fr.ifremer.coser.control.ProgressMonitor; import fr.ifremer.coser.control.ValidationError; +import fr.ifremer.coser.data.AbstractDataEntity; import fr.ifremer.coser.data.Catch; import fr.ifremer.coser.data.Haul; import fr.ifremer.coser.data.Length; @@ -111,10 +116,10 @@ /** * Valide un seul bean, retourne la liste des erreurs trouvées. * - * @param bean - * @return + * @param bean bean to validate + * @return */ - protected List<ValidationError> validate(Object bean) { + protected List<ValidationError> validate(AbstractDataEntity bean) { List<ValidationError> result = null; try { // obligatoire pour les appel dans les thread et swing EDT @@ -131,20 +136,21 @@ } Map<String, List<String>> fieldErrors = validationContext.getFieldErrors(); - for (Map.Entry<String, List<String>> fieldError : fieldErrors.entrySet()) { - String fieldName = fieldError.getKey(); - List<String> errors = fieldError.getValue(); - + for (List<String> errors : fieldErrors.values()) { ValidationError error = new ValidationError(); String messages = StringUtils.join(errors, ", "); - error.setField(fieldName); error.setMessage(messages); error.setLevel(validationLevel); + + // add error line + error.setLineNumber(bean.getLine()); + result.add(error); } } } finally { + // vidage par log level validationSupport.clearFieldErrors(); } } @@ -170,11 +176,13 @@ */ public List<ValidationError> validateCategory(Control control, Category category, ProgressMonitor progress) { + // instance des bean utilisé lors de la validation Catch beanCatch = new Catch(); Haul beanHaul = new Haul(); Length beanLength = new Length(); Strata beanStrata = new Strata(); + // get content depending on category DataStorage dataToCheck = null; switch (category) { case CATCH: @@ -190,20 +198,30 @@ dataToCheck = control.getStrata(); break; } - + + // update progress + int total = dataToCheck.size() - 1; if (progress != null) { - progress.setTotal(dataToCheck.size() - 1); + progress.setText(_("coser.business.control.step.xworks", 0)); + progress.setTotal(total); } - + + Set<String> uniqueDataKeys = new HashSet<String>(); List<ValidationError> validationErrors = new ArrayList<ValidationError>(); - Iterator<String[]> itDataToCheck = dataToCheck.iterator(); - int lineNumber = 1; // 1 = skip header + int lineIndex = 1; // 1 = skip header itDataToCheck.next(); // skip header while (itDataToCheck.hasNext()) { + + // update progress if (progress != null) { - progress.setCurrent(lineNumber); + int progressPercent = (int)((double)lineIndex / (double)total * 100.0); + progress.setText(_("coser.business.control.step.xworks", progressPercent)); + progress.setCurrent(lineIndex); + ++lineIndex; } + + // first, do single bean validation String[] line = itDataToCheck.next(); List<ValidationError> errors = null; switch (category) { @@ -224,16 +242,43 @@ errors = validate(beanStrata); break; } - if (errors != null) { - for (ValidationError error : errors) { - error.setLineNumber(lineNumber - 1); - } validationErrors.addAll(errors); } - ++lineNumber; + + // check for duplicated lines + String uniqueDataKey = getSignificantData(line); + System.out.println(uniqueDataKey); + if (uniqueDataKeys.contains(uniqueDataKey)) { + ValidationError error = new ValidationError(); + error.setLevel(ValidationLevel.ERROR); + error.setLineNumber(line[AbstractDataEntity.INDEX_LINE]); + error.setMessage(_("coser.business.control.error.duplicatedLine")); + validationErrors.add(error); + } + else { + uniqueDataKeys.add(uniqueDataKey); + } } return validationErrors; } + + /** + * Retourne sous forme de clé la partie significative des données. + * + * Donc sans le numéro de ligne. + * + * @param data data + * @return string key + */ + protected String getSignificantData(String[] data) { + StringBuilder sb = new StringBuilder(); + for (int index = 0 ; index < data.length ; ++index) { + if (index != AbstractDataEntity.INDEX_LINE) { + sb.append(data[index]).append(';'); + } + } + return sb.toString(); + } } Modified: trunk/coser-business/src/test/java/fr/ifremer/coser/services/ValidationServiceTest.java =================================================================== --- trunk/coser-business/src/test/java/fr/ifremer/coser/services/ValidationServiceTest.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-business/src/test/java/fr/ifremer/coser/services/ValidationServiceTest.java 2010-10-28 13:42:45 UTC (rev 115) @@ -34,6 +34,7 @@ import fr.ifremer.coser.control.ValidationError; import fr.ifremer.coser.data.Catch; +import fr.ifremer.coser.data.Haul; /** * Test abour validation. @@ -64,7 +65,7 @@ log.debug("Validation errors = " + errors); } Assert.assertNotNull(errors); - Assert.assertFalse(errors.isEmpty()); + Assert.assertEquals(4, errors.size()); myCatch.setData(new String[]{"1", "Toto","","","","999",""}); errors = validationService.validate(myCatch); @@ -72,7 +73,7 @@ log.debug("Validation errors = " + errors); } Assert.assertNotNull(errors); - Assert.assertFalse(errors.isEmpty()); + Assert.assertEquals(3, errors.size()); } /** @@ -88,4 +89,20 @@ } Assert.assertNull(errors); } + + /** + * Test que certains double ont 5 decimales de définie. + */ + @Test + public void test5DecimalValidation() { + Haul haulBean = new Haul(); + haulBean.setData(new String[]{"1", "COSER_TEST","2010","TRAIT3","10","STR3","0.06","43.89","-1.73","115.00"}); + List<ValidationError> errors = validationService.validate(haulBean); + Assert.assertEquals(3, errors.size()); + + haulBean.setData(new String[]{"1","COSER_TEST","2010","TRAIT3","10","STR3","0.06000","43.89000","-1.73234","115.00"}); + errors = validationService.validate(haulBean); + System.out.println(errors); + Assert.assertNull(errors); + } } Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlDataTableModel.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlDataTableModel.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlDataTableModel.java 2010-10-28 13:42:45 UTC (rev 115) @@ -25,10 +25,13 @@ import static org.nuiton.i18n.I18n._; +import java.util.Iterator; + import javax.swing.table.AbstractTableModel; import fr.ifremer.coser.CoserConstants.Category; import fr.ifremer.coser.bean.Project; +import fr.ifremer.coser.data.AbstractDataEntity; import fr.ifremer.coser.storage.DataStorage; /** @@ -54,7 +57,7 @@ public void updateData(ControlView controlView) { Project project = controlView.getContextValue(Project.class); - Category category = (Category)controlView.getCategoryComboBox().getSelectedItem(); + Category category = (Category)controlView.getCategoryComboBoxModel().getSelectedItem(); switch (category) { case CATCH: @@ -107,8 +110,36 @@ return result; } - + + /** + * Retourne la donnée (toutes le String[]) à la ligne demandée. + * + * @param rowIndex + * @return String[] + */ public String[] getDataAt(int rowIndex) { return data.get(rowIndex + 1); } + + /** + * Retourne l'index dans la liste des données du numero de ligne + * demandé. + * + * @param lineNumber le numero de données + * @return l'index + */ + public int getRealIndexOfLine(String lineNumber) { + Iterator<String[]> itData = data.iterator(); + itData.next(); // skip header + int result = -1; + int index = 0; + while (itData.hasNext() && result == -1) { + String currentLineNumber = itData.next()[AbstractDataEntity.INDEX_LINE]; + if (lineNumber.equals(currentLineNumber)) { + result = index; + } + ++index; + } + return result; + } } Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlHandler.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlHandler.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlHandler.java 2010-10-28 13:42:45 UTC (rev 115) @@ -239,7 +239,8 @@ } /** - * Select + * Selectionne, dans la table des données, la ligne correspondant + * a l'erreur selectionnée dans la table des erreurs. * * @param view view * @param event selection event @@ -248,12 +249,20 @@ int selectedError = view.getValidationGlobalErrorsTable().getSelectedRow(); if (selectedError != -1) { ValidationError error = view.getGlobalValidationModel().getErrorAt(selectedError); - int dataErrorLine = error.getLineNumber(); - view.getControlDataTableSelectionModel().setSelectionInterval(dataErrorLine, dataErrorLine); - scrollToVisible(view.getControlDataTable(), dataErrorLine, 0); + String errorLineNumber = error.getLineNumber(); + int errorLineIndex = view.getControlDataTableModel().getRealIndexOfLine(errorLineNumber); + view.getControlDataTableSelectionModel().setSelectionInterval(errorLineIndex, errorLineIndex); + scrollToVisible(view.getControlDataTable(), errorLineIndex, 0); } } + /** + * Scroll le viewport de la table à la ligne demandée. + * + * @param table table + * @param rowIndex ligne + * @param vColIndex colonne + */ protected void scrollToVisible(JTable table, int rowIndex, int vColIndex) { if (!(table.getParent() instanceof JViewport)) { return; Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlProgressBar.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlProgressBar.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlProgressBar.java 2010-10-28 13:42:45 UTC (rev 115) @@ -24,11 +24,10 @@ package fr.ifremer.coser.ui.control; import javax.swing.JProgressBar; - import fr.ifremer.coser.control.ProgressMonitor; /** - * TODO add comment here. + * Control progress bar. * * @author chatellier * @version $Revision$ @@ -59,4 +58,8 @@ setMaximum(total); } + @Override + public void setText(String text) { + setString(text); + } } Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlValidationRenderer.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlValidationRenderer.java (rev 0) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlValidationRenderer.java 2010-10-28 13:42:45 UTC (rev 115) @@ -0,0 +1,107 @@ +/* + * #%L + * + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2010 Codelutin, Chatellier Eric + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package fr.ifremer.coser.ui.control; + +import static org.nuiton.i18n.I18n._; + +import java.awt.Component; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +import jaxx.runtime.validator.swing.SwingValidatorUtil; +import fr.ifremer.coser.CoserConstants.ValidationLevel; + +/** + * Renderer pour le table des erreurs globales. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class ControlValidationRenderer extends DefaultTableCellRenderer { + + /** serialVersionUID. */ + private static final long serialVersionUID = -6423364126451874968L; + + protected ImageIcon fatalIcon = null; + protected ImageIcon errorIcon = null; + protected ImageIcon warningIcon = null; + protected ImageIcon infoIcon = null; + + public ControlValidationRenderer() { + // use icon in jaxx + fatalIcon = SwingValidatorUtil.getFatalIcon(); + errorIcon = SwingValidatorUtil.getErrorIcon(); + warningIcon = SwingValidatorUtil.getWarningIcon(); + infoIcon = SwingValidatorUtil.getInfoIcon(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int row, int column) { + + JLabel component = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + ImageIcon icon = null; + String text = null; + + switch (column) { + case 0: + ValidationLevel level = (ValidationLevel)value; + switch (level) { + case FATAL: + icon = fatalIcon; + break; + case ERROR: + icon = errorIcon; + break; + case WARNING: + icon = warningIcon; + break; + case INFO: + icon = infoIcon; + break; + } + break; + case 1: + String message = (String)value; + text = _(message); + break; + } + + component.setIcon(icon); + component.setText(text); + + return component; + } + + +} Property changes on: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlValidationRenderer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlView.jaxx =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlView.jaxx 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlView.jaxx 2010-10-28 13:42:45 UTC (rev 115) @@ -25,8 +25,14 @@ <Table> <script><![CDATA[ void $afterCompleteSetup() { + // bean validation jaxx.runtime.validator.swing.SwingValidatorUtil.installUI(validationMessagesTable, new jaxx.runtime.validator.swing.SwingValidatorMessageTableRenderer()); + + // global validation + SwingUtil.fixTableColumnWidth(validationGlobalErrorsTable, 0, 25); + validationGlobalErrorsTable.getRowSorter().setSortKeys(Arrays.asList(new RowSorter.SortKey(0, SortOrder.DESCENDING))); + validationGlobalErrorsTable.setDefaultRenderer(Object.class, new ControlValidationRenderer()); } ]]></script> @@ -35,7 +41,8 @@ <row> <cell fill="horizontal" insets="0" anchor="west" columns="2"> <JToolBar floatable="false"> - <JComboBox id="categoryComboBox" model="{new fr.ifremer.coser.ui.control.ControlCategoryListModel()}" + <fr.ifremer.coser.ui.control.ControlCategoryListModel id="categoryComboBoxModel" /> + <JComboBox id="categoryComboBox" model="{categoryComboBoxModel}" renderer="{new fr.ifremer.coser.ui.control.ControlCategoryListRenderer()}" onActionPerformed="getHandler().categoryChanged(this, event)"/> <JSeparator /> @@ -46,7 +53,8 @@ <row> <cell fill="both" weightx="1" weighty="2" columns="2"> <JScrollPane> - <JTable id='controlDataTable' model="{new fr.ifremer.coser.ui.control.ControlDataTableModel(this)}" + <fr.ifremer.coser.ui.control.ControlDataTableModel id="controlDataTableModel" constructorParams="this" /> + <JTable id='controlDataTable' model="{controlDataTableModel}" onMouseClicked="getHandler().showDataTableContextMenu(this, event)"/> <ListSelectionModel id="controlDataTableSelectionModel" javaBean="controlDataTable.getSelectionModel()" onValueChanged="getHandler().controlDataTableSelectionChanged(this, event)" /> @@ -116,6 +124,7 @@ <JScrollPane> <GlobalValidationModel id="globalValidationModel" /> <JTable id='validationGlobalErrorsTable' model="{globalValidationModel}" + autoCreateRowSorter="true" selectionMode="{ListSelectionModel.SINGLE_SELECTION}"/> <ListSelectionModel id="globalValidationTableSelectionModel" javaBean="validationGlobalErrorsTable.getSelectionModel()" @@ -125,7 +134,7 @@ </row> <row> <cell anchor="center" weightx="1" fill="horizontal"> - <ControlProgressBar id="checkProgressBar" /> + <ControlProgressBar id="checkProgressBar" stringPainted="true" /> </cell> <cell anchor="center" weightx="1"> <JButton text="coser.ui.validation.checkData" onActionPerformed="getHandler().checkData(this)" /> Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/GlobalValidationModel.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/GlobalValidationModel.java 2010-10-28 13:41:57 UTC (rev 114) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/GlobalValidationModel.java 2010-10-28 13:42:45 UTC (rev 115) @@ -74,7 +74,7 @@ */ @Override public int getColumnCount() { - return 3; + return 2; } @@ -88,9 +88,6 @@ result = _("coser.ui.control.global.level"); break; case 1: - result = _("coser.ui.control.global.field"); - break; - case 2: result = _("coser.ui.control.global.message"); break; } @@ -108,9 +105,6 @@ case 1: result = String.class; break; - case 2: - result = String.class; - break; } return result; } @@ -130,9 +124,6 @@ result = validationError.getLevel(); break; case 1: - result = validationError.getField(); - break; - case 2: result = validationError.getMessage(); break; }