Author: chatellier Date: 2010-10-29 15:43:38 +0000 (Fri, 29 Oct 2010) New Revision: 135 Log: Amelioration du storage pour acceder rapidement aux donn?\195?\169es en fonction de leur num?\195?\169ro de ligne Added: trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryDataStorage.java Removed: trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryListStorage.java Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/command/DeleteLineCommand.java trunk/coser-business/src/main/java/fr/ifremer/coser/command/ModifyFieldCommand.java trunk/coser-business/src/main/java/fr/ifremer/coser/services/ImportService.java trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorage.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 trunk/coser-business/src/test/java/fr/ifremer/coser/services/CommandServiceTest.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 Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/command/DeleteLineCommand.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/command/DeleteLineCommand.java 2010-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/command/DeleteLineCommand.java 2010-10-29 15:43:38 UTC (rev 135) @@ -27,8 +27,6 @@ import static org.nuiton.i18n.I18n._; -import java.util.Iterator; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,7 +34,6 @@ import fr.ifremer.coser.CoserConstants.Category; import fr.ifremer.coser.bean.AbstractDataContainer; import fr.ifremer.coser.bean.Project; -import fr.ifremer.coser.data.AbstractDataEntity; import fr.ifremer.coser.storage.DataStorage; /** @@ -101,24 +98,13 @@ } // parcourt des lignes - boolean dataLineFound = false; - Iterator<String[]> itDataStorage = dataStorage.iterator(); - itDataStorage.next(); // skip header - while (itDataStorage.hasNext()) { - String[] dataLine = itDataStorage.next(); - String dataLineIndex = dataLine[AbstractDataEntity.INDEX_LINE]; - if (dataLineIndex.equals(lineNumber)) { - if (log.isDebugEnabled()) { - log.debug("Removing line " + dataLineIndex); - } - dataLineFound = true; - deletedDataStorage.add(dataLine); - itDataStorage.remove(); - } + int index = dataStorage.indexOf(lineNumber); + if (index >= 0) { + String[] data = dataStorage.remove(index); + deletedDataStorage.add(data); } - - // if not found, throw business exception - if (!dataLineFound) { + else { + // if not found, throw business exception throw new CoserBusinessException(_("Can't find line %s for deletion", lineNumber)); } } @@ -149,45 +135,38 @@ break; } - // parcourt des lignes - boolean dataLineFound = false; - Iterator<String[]> itDeletedDataStorage = deletedDataStorage.iterator(); - itDeletedDataStorage.next(); //skip header - while (itDeletedDataStorage.hasNext()) { - String[] deletedDataLine = itDeletedDataStorage.next(); - String deletedDataLineIndex = deletedDataLine[AbstractDataEntity.INDEX_LINE]; - if (deletedDataLineIndex.equals(lineNumber)) { - dataLineFound = true; - itDeletedDataStorage.remove(); + int indexDeletedData = deletedDataStorage.indexOf(lineNumber); + + if (indexDeletedData != -1) { + String[] deletedDataLine = deletedDataStorage.get(indexDeletedData); + + // search for new insert point + int lineNumberInt = Integer.parseInt(lineNumber); - // search new insert point - int originalDataLine = Integer.parseInt(deletedDataLineIndex); - Iterator<String[]> itDataStorage = dataStorage.iterator(); - itDataStorage.next(); //skip header - int index = 1; // due to header - while (itDataStorage.hasNext()) { - String[] dataLine = itDataStorage.next(); - String dataLineIndex = dataLine[AbstractDataEntity.INDEX_LINE]; - int dataLineInt = Integer.parseInt(dataLineIndex); - if (dataLineInt == originalDataLine) { - throw new CoserBusinessException(_("Original line already exists!")); - } - else if (dataLineInt > originalDataLine) { - break; - } - index++; - } - - // insert line at specified index - dataStorage.add(index, deletedDataLine); - if (log.isDebugEnabled()) { - log.debug("Restore line " + index); - } + // check que la ligne a restaurer n'existe pas deja + int indexData = dataStorage.indexOf(String.valueOf(lineNumberInt)); + if (indexData != -1) { + throw new CoserBusinessException("Original line already exists !"); } + + do { + lineNumberInt--; + indexData = dataStorage.indexOf(String.valueOf(lineNumberInt)); + } while (indexData < 0 && lineNumberInt > 0); + + // re add deleted data + if (indexData >= 0) { + // +1 car on l'insert apres la ligne qu'on a trouvé + dataStorage.add(indexData + 1, deletedDataLine); + } + else { + dataStorage.add(0, deletedDataLine); + } + deletedDataStorage.remove(indexDeletedData); } // if not found, throw business exception - if (!dataLineFound) { + else { throw new CoserBusinessException(_("Can't find line %s for undeletion", lineNumber)); } } Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/command/ModifyFieldCommand.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/command/ModifyFieldCommand.java 2010-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/command/ModifyFieldCommand.java 2010-10-29 15:43:38 UTC (rev 135) @@ -27,7 +27,6 @@ import static org.nuiton.i18n.I18n._; -import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import org.apache.commons.beanutils.PropertyUtils; Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/services/ImportService.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/services/ImportService.java 2010-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/services/ImportService.java 2010-10-29 15:43:38 UTC (rev 135) @@ -58,7 +58,7 @@ import fr.ifremer.coser.data.Length; import fr.ifremer.coser.data.Strata; import fr.ifremer.coser.storage.DataStorage; -import fr.ifremer.coser.storage.MemoryListStorage; +import fr.ifremer.coser.storage.MemoryDataStorage; /** * File import/export service. @@ -90,7 +90,7 @@ */ public DataStorage loadCSVFile(Project project, Category category, File file, boolean originalLoading) throws CoserBusinessException { - DataStorage content = new MemoryListStorage(); + DataStorage content = new MemoryDataStorage(); Reader reader = null; CSVReader csvReader = null; @@ -200,7 +200,7 @@ */ public DataStorage getEmptyStorage(Project project, Category category) { - DataStorage dataStorage = new MemoryListStorage(); + DataStorage dataStorage = new MemoryDataStorage(); switch (category) { case CATCH: dataStorage.add(Catch.EN_HEADERS); Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorage.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorage.java 2010-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorage.java 2010-10-29 15:43:38 UTC (rev 135) @@ -69,4 +69,6 @@ String[] set(int index, String[] data); String[] remove(int index); + + public int indexOf(String lineNumber); } Copied: trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryDataStorage.java (from rev 103, trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryListStorage.java) =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryDataStorage.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryDataStorage.java 2010-10-29 15:43:38 UTC (rev 135) @@ -0,0 +1,197 @@ +/* + * #%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.storage; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import au.com.bytecode.opencsv.CSVReader; +import au.com.bytecode.opencsv.CSVWriter; + +/** + * Stockage mémoire des String[] sous forme de String simple. + * + * Beaucoup moins couteux en mémoire que les String[] sans pour antant + * que le temps de parcours soit augmenté. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class MemoryDataStorage implements DataStorage { + + public List<String> listStorage; + public List<String> lineIndexStorage; + + public MemoryDataStorage() { + listStorage = new ArrayList<String>(); + lineIndexStorage = new ArrayList<String>(); + } + + public class StringListIterator implements Iterator<String[]> { + + protected Iterator<String> listIterator; + protected Iterator<String> lineIndexIterator; + + public StringListIterator(Iterator<String> internalIterator, Iterator<String> lineIndexIterator) { + this.listIterator = internalIterator; + this.lineIndexIterator = lineIndexIterator; + } + + /* + * @see java.util.Iterator#hasNext() + */ + @Override + public boolean hasNext() { + return listIterator.hasNext(); + } + + /* + * @see java.util.Iterator#next() + */ + @Override + public String[] next() { + + String nextString = listIterator.next(); + String[] nextArray = stringToArray(nextString); + + lineIndexIterator.next(); + + return nextArray; + } + + /* + * @see java.util.Iterator#remove() + */ + @Override + public void remove() { + listIterator.remove(); + lineIndexIterator.remove(); + } + } + + /* + * @see java.lang.Iterable#iterator() + */ + @Override + public Iterator<String[]> iterator() { + return new StringListIterator(listStorage.iterator(), lineIndexStorage.iterator()); + } + + /* + * @see fr.ifremer.coser.storage.DataStorage#addData(java.lang.String[]) + */ + @Override + public void add(String[] data) { + + String stringData = arrayToString(data); + listStorage.add(stringData); + lineIndexStorage.add(data[0]); + } + + /* + * @see fr.ifremer.coser.storage.DataStorage#addData(java.lang.String[]) + */ + @Override + public void add(int index, String[] data) { + + String stringData = arrayToString(data); + listStorage.add(index, stringData); + lineIndexStorage.add(index, data[0]); + } + + protected String arrayToString(String[] data) { + StringWriter writer = new StringWriter(); + CSVWriter csvWriter = new CSVWriter(writer); + csvWriter.writeNext(data); + //TODO echatellier 20101022 replace with custom parsing code + try { + csvWriter.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return writer.toString(); + } + + protected String[] stringToArray(String data) { + StringReader reader = new StringReader(data); + CSVReader csvReader = new CSVReader(reader); + String[] dataArray = null; + //TODO echatellier 20101022 replace with custom parsing code + try { + dataArray = csvReader.readNext(); + csvReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return dataArray; + } + + /* + * @see fr.ifremer.coser.storage.DataStorage#getData(int) + */ + @Override + public String[] get(int index) { + String stringData = listStorage.get(index); + String[] dataArray = stringToArray(stringData); + return dataArray; + } + + public int indexOf(String lineNumber) { + return lineIndexStorage.indexOf(lineNumber); + } + + public int size() { + return listStorage.size(); + } + + public String[] set(int index, String[] element) { + String data = arrayToString(element); + String old = listStorage.set(index, data); + String[] oldArray = stringToArray(old); + lineIndexStorage.set(index, element[0]); + return oldArray; + } + + public String[] remove(int index) { + String old = listStorage.remove(index); + String[] oldArray = stringToArray(old); + lineIndexStorage.remove(index); + return oldArray; + } + + @Override + public String toString() { + return listStorage.toString(); + } +} Deleted: trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryListStorage.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryListStorage.java 2010-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/storage/MemoryListStorage.java 2010-10-29 15:43:38 UTC (rev 135) @@ -1,182 +0,0 @@ -/* - * #%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.storage; - -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import au.com.bytecode.opencsv.CSVReader; -import au.com.bytecode.opencsv.CSVWriter; - -/** - * Stockage mémoire des String[] sous forme de String simple. - * - * Beaucoup moins couteux en mémoire que les String[] sans pour antant - * que le temps de parcours soit augmenté. - * - * @author chatellier - * @version $Revision$ - * - * Last update : $Date$ - * By : $Author$ - */ -public class MemoryListStorage implements DataStorage { - - public List<String> internalStorage; - - public MemoryListStorage() { - internalStorage = new ArrayList<String>(); - } - - public class StringListIterator implements Iterator<String[]> { - - protected Iterator<String> internalIterator; - - public StringListIterator(Iterator<String> internalIterator) { - this.internalIterator = internalIterator; - } - - /* - * @see java.util.Iterator#hasNext() - */ - @Override - public boolean hasNext() { - return internalIterator.hasNext(); - } - - /* - * @see java.util.Iterator#next() - */ - @Override - public String[] next() { - - String nextString = internalIterator.next(); - String[] nextArray = stringToArray(nextString); - - return nextArray; - } - - /* - * @see java.util.Iterator#remove() - */ - @Override - public void remove() { - internalIterator.remove(); - } - } - - /* - * @see java.lang.Iterable#iterator() - */ - @Override - public Iterator<String[]> iterator() { - return new StringListIterator(internalStorage.iterator()); - } - - /* - * @see fr.ifremer.coser.storage.DataStorage#addData(java.lang.String[]) - */ - @Override - public void add(String[] data) { - - String stringData = arrayToString(data); - internalStorage.add(stringData); - } - - /* - * @see fr.ifremer.coser.storage.DataStorage#addData(java.lang.String[]) - */ - @Override - public void add(int index, String[] data) { - - String stringData = arrayToString(data); - internalStorage.add(index, stringData); - } - - protected String arrayToString(String[] data) { - StringWriter writer = new StringWriter(); - CSVWriter csvWriter = new CSVWriter(writer); - csvWriter.writeNext(data); - //TODO echatellier 20101022 replace with custom parsing code - try { - csvWriter.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return writer.toString(); - } - - protected String[] stringToArray(String data) { - StringReader reader = new StringReader(data); - CSVReader csvReader = new CSVReader(reader); - String[] dataArray = null; - //TODO echatellier 20101022 replace with custom parsing code - try { - dataArray = csvReader.readNext(); - csvReader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return dataArray; - } - - /* - * @see fr.ifremer.coser.storage.DataStorage#getData(int) - */ - @Override - public String[] get(int index) { - String stringData = internalStorage.get(index); - String[] dataArray = stringToArray(stringData); - return dataArray; - } - - public int size() { - return internalStorage.size(); - } - - public String[] set(int index, String[] element) { - String data = arrayToString(element); - String old = internalStorage.set(index, data); - String[] oldArray = stringToArray(old); - return oldArray; - } - - public String[] remove(int index) { - String old = internalStorage.remove(index); - String[] oldArray = stringToArray(old); - return oldArray; - } - - @Override - public String toString() { - return internalStorage.toString(); - } -} 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-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/resources/i18n/coser-business-en_GB.properties 2010-10-29 15:43:38 UTC (rev 135) @@ -8,7 +8,6 @@ Maturity\ attribute\ is\ required= Missing\ file\ %s= Number\ attribute\ is\ not\ a\ valid\ double= -Original\ line\ already\ exists\!= Project\ %s\ already\ exist= Project\ %s\ doesn't\ exists\ \!= Project\ name\ is\ required= @@ -53,3 +52,4 @@ long\ must\ contains\ at\ least\ 5\ decimal= number\ attribute\ is\ not\ a\ valid\ double= sweptSurface\ attribute\ is\ not\ a\ valid\ double= +year\ is\ not\ valid= 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-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/main/resources/i18n/coser-business-fr_FR.properties 2010-10-29 15:43:38 UTC (rev 135) @@ -8,7 +8,6 @@ Maturity\ attribute\ is\ required= Missing\ file\ %s=Fichier manquant \: %s Number\ attribute\ is\ not\ a\ valid\ double= -Original\ line\ already\ exists\!= Project\ %s\ already\ exist=Le projet %s existe d\u00E9j\u00E0 \! Project\ %s\ doesn't\ exists\ \!=Le projet %s n'existe pas \! Project\ name\ is\ required= @@ -53,3 +52,4 @@ long\ must\ contains\ at\ least\ 5\ decimal= number\ attribute\ is\ not\ a\ valid\ double= sweptSurface\ attribute\ is\ not\ a\ valid\ double= +year\ is\ not\ valid= Modified: trunk/coser-business/src/test/java/fr/ifremer/coser/services/CommandServiceTest.java =================================================================== --- trunk/coser-business/src/test/java/fr/ifremer/coser/services/CommandServiceTest.java 2010-10-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/test/java/fr/ifremer/coser/services/CommandServiceTest.java 2010-10-29 15:43:38 UTC (rev 135) @@ -108,6 +108,24 @@ Assert.assertEquals("4", project.getControl().getLength().get(4)[Length.INDEX_LINE]); commandService.undoAction(project, project.getControl()); Assert.assertEquals("3", project.getControl().getLength().get(4)[Length.INDEX_LINE]); - } + + /** + * Test que la double annulation d'un retablissement de ligne + * lance une exception. + * + * @throws CoserBusinessException + */ + @Test(expected=CoserBusinessException.class) + public void testDeleteLineUndoAlreadyExists() throws CoserBusinessException { + Project project = createTestProject(projectService); + DeleteLineCommand command = new DeleteLineCommand(); + command.setLineNumber("3"); + command.setCategory(Category.LENGTH); + + commandService.doAction(command, project, project.getControl()); + commandService.undoAction(project, project.getControl()); + project.getControl().getHistoryCommand().add(command); + commandService.undoAction(project, project.getControl()); + } } 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-29 15:32:52 UTC (rev 134) +++ trunk/coser-business/src/test/java/fr/ifremer/coser/services/ValidationServiceTest.java 2010-10-29 15:43:38 UTC (rev 135) @@ -38,7 +38,7 @@ import fr.ifremer.coser.data.Catch; import fr.ifremer.coser.data.Haul; import fr.ifremer.coser.storage.DataStorage; -import fr.ifremer.coser.storage.MemoryListStorage; +import fr.ifremer.coser.storage.MemoryDataStorage; /** * Test abour validation. @@ -106,7 +106,7 @@ @Test public void testWeigthWithNonCapture() { Control control = new Control(); - DataStorage dataCatch = new MemoryListStorage(); + DataStorage dataCatch = new MemoryDataStorage(); dataCatch.add(new String[]{"Line", "Campagne","Annee","Trait","Espece","Nombre","Poids"}); dataCatch.add(new String[]{"1", "Test survey","1999","Test trait","Test sp","0","12"}); control.setCatch(dataCatch); 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-29 15:32:52 UTC (rev 134) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlDataTableModel.java 2010-10-29 15:43:38 UTC (rev 135) @@ -134,21 +134,8 @@ * @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; - } - - if (log.isDebugEnabled()) { - log.debug("Real line for " + lineNumber + " = " + index); - } + // -1 because header is table header + int result = data.indexOf(lineNumber) - 1; return result; } }