r437 - in trunk: coser-business/src/main/java/fr/ifremer/coser coser-business/src/main/java/fr/ifremer/coser/services coser-business/src/main/resources/i18n coser-ui/src/main/java/fr/ifremer/coser/ui coser-ui/src/main/java/fr/ifremer/coser/ui/control coser-ui/src/main/java/fr/ifremer/coser/ui/result coser-ui/src/main/resources/i18n
Author: chatellier Date: 2010-12-22 15:17:39 +0000 (Wed, 22 Dec 2010) New Revision: 437 Log: Add result selection and upload to coser web frontend. Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/ResultHandler.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultRenderer.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultTreeModel.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/SelectUploadResultView.jaxx Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/CoserBusinessConfig.java trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.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-ui/src/main/java/fr/ifremer/coser/ui/CoserFrame.jaxx trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrameHandler.java trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlHandler.java trunk/coser-ui/src/main/resources/i18n/coser-ui_en_GB.properties trunk/coser-ui/src/main/resources/i18n/coser-ui_fr_FR.properties Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/CoserBusinessConfig.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/CoserBusinessConfig.java 2010-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/CoserBusinessConfig.java 2010-12-22 15:17:39 UTC (rev 437) @@ -117,6 +117,21 @@ return result; } + public String getWebUploadURL() { + String result = getOption(CoserBusinessOption.WEB_UPLOAD_URL.key); + return result; + } + + public String getWebUploadPassword() { + String result = getOption(CoserBusinessOption.WEB_UPLOAD_PASSWORD.key); + return result; + } + + public File getWebServerDirectory() { + File result = getOptionAsFile(CoserBusinessOption.WEB_SERVER_DIRECTORY.key); + return result; + } + public static enum CoserBusinessOption implements OptionDef { DATABASE_DIRECTORY("coser.database.directory", _("coser.config.database.directory.description"), "${user.home}" + File.separator + "coser", String.class, false, false), @@ -132,8 +147,16 @@ CONTROL_DIFF_CATCH_LENGTH("coser.control.diffcatchlength", _("coser.config.control.diffcatchlength.description"), "5.0", Double.class, false, false), CONTROL_TYPE_FISH("coser.control.typeFish", _("coser.config.control.typeFish.description"), "Pisces + Agnatha", String.class, false, false), SELECTION_FILTER_OCCURRENCE("coser.selection.occurrenceFilter", _("coser.config.selection.occurrenceFilter.description"), "5.0", Double.class, false, false), - SELECTION_FILTER_DENSITY("coser.selection.densityFilter", _("coser.config.selection.densityFilter.description"), "5.0", Double.class, false, false); + SELECTION_FILTER_DENSITY("coser.selection.densityFilter", _("coser.config.selection.densityFilter.description"), "5.0", Double.class, false, false), + /** Client side. */ + WEB_FRONT_END("coser.web.frontend", _("coser.config.web.frontend.description"), "http://www.ifremer.fr/coser", String.class, false, false), + WEB_UPLOAD_URL("coser.web.uploadurl", _("coser.config.web.uploadurl.description"), "${" + WEB_FRONT_END.key + "}/upload-result.action", String.class, false, false), + WEB_UPLOAD_PASSWORD("coser.web.uploadpassword", _("coser.config.web.uploadpassword.description"), "", String.class, false, false), + + /** Server side. */ + WEB_SERVER_DIRECTORY("coser.web.server.directory", _("coser.config.web.server.directory.description"), "${" + DATABASE_DIRECTORY.key + "}" + File.separator + "web", String.class, false, false); + protected String key; protected String description; protected String defaultValue; Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java 2010-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/services/ProjectService.java 2010-12-22 15:17:39 UTC (rev 437) @@ -31,6 +31,7 @@ import java.beans.Introspector; import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -38,6 +39,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -63,10 +65,21 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.math.util.MathUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.InputStreamBody; +import org.apache.http.entity.mime.content.StringBody; +import org.apache.http.impl.client.DefaultHttpClient; import org.nuiton.math.matrix.DimensionHelper; import org.nuiton.math.matrix.MatrixFactory; import org.nuiton.math.matrix.MatrixND; import org.nuiton.math.matrix.MatrixProvider; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; import fr.ifremer.coser.CoserBusinessConfig; import fr.ifremer.coser.CoserBusinessException; @@ -89,6 +102,7 @@ import fr.ifremer.coser.data.Strata; import fr.ifremer.coser.storage.DataStorage; import fr.ifremer.coser.util.ProgressMonitor; +import fr.ifremer.coser.util.ProgressStream; /** * Service business method relative to project. @@ -126,8 +140,10 @@ File[] projects = projectsDirectory.listFiles(); if (projects != null) { for (File existingProject : projects) { - String projectName = existingProject.getName(); - result.add(projectName); + if (existingProject.isDirectory()) { + String projectName = existingProject.getName(); + result.add(projectName); + } } } return result; @@ -387,9 +403,26 @@ * @throws CoserBusinessException */ public Project openProject(String projectName) throws CoserBusinessException { + return openProject(projectName, null); + } + /** + * Open project without loading data. + * + * Just load non category data (reftax). + * + * @param projectName project name to open + * @param parentDirectory optionnal custom parent directory (for results) + * @return loaded project with data + * @throws CoserBusinessException + */ + public Project openProject(String projectName, File parentDirectory) throws CoserBusinessException { + // check project existence - File projectsDirectory = config.getProjectsDirectory(); + File projectsDirectory = parentDirectory; + if (projectsDirectory == null) { + projectsDirectory = config.getProjectsDirectory(); + } File projectDirectory = new File(projectsDirectory, projectName); if (!projectDirectory.isDirectory()) { throw new CoserBusinessException(_("Project %s doesn't exists !", projectName)); @@ -501,10 +534,6 @@ return project; } - protected void readSelectionFile() { - - } - /** * Load rsufi result in specified directory. * @@ -2797,4 +2826,225 @@ return contents; } + + /** + * Retourne tous les projets qui ont des résultats. + * + * De la forme d'une liste de de path (à la tree path) : + * ProjetName/SelectionName/ResultName + * + * @return results path + */ + public List<String[]> findAllProjectWithResult() { + List<String[]> results = new ArrayList<String[]>(); + + // loop on projets + File projectsDirectory = config.getProjectsDirectory(); + File[] projects = projectsDirectory.listFiles(); + if (projects != null) { + for (File existingProject : projects) { + if (existingProject.isDirectory()) { + String projectName = existingProject.getName(); + Project p = new Project(); + p.setName(projectName); + + // loop on selections + File selectionsDirectory = new File(existingProject, CoserConstants.STORAGE_SELECTION_DIRECTORY); + File[] selections = selectionsDirectory.listFiles(); + if (selections != null) { + for (File existingSelection : selections) { + if (existingSelection.isDirectory()) { + String selectionName = existingSelection.getName(); + Selection s = new Selection(); + s.setName(selectionName); + + // loop on result + File rsufisDirectory = new File(existingSelection, CoserConstants.STORAGE_RESULTS_DIRECTORY); + File[] rSufiResults = rsufisDirectory.listFiles(); + if (rSufiResults != null) { + for (File rSufiResult : rSufiResults) { + if (rSufiResult.isDirectory()) { + String resultName = rSufiResult.getName(); + RSufiResult r = new RSufiResult(); + r.setName(resultName); + + String[] result = new String[] {projectName, selectionName, resultName}; + results.add(result); + } + } + } + } + } + } + } + } + } + + return results; + } + + /** + * Upload user selected result to coser web front-end using common http + * client. + * + * @param selectedResults selected result (collection of project/selection/rsufiresultname) + * @param progress progress monitor + * @throws CoserBusinessException + */ + public void performResultUpload(Collection<String[]> selectedResults, ProgressMonitor progress) throws CoserBusinessException { + + // first copy prepare directory with only necessary data + // ie project with only selected selections + // and selection with only selected results + + progress.setText(_("coser.business.uploadresult.preparezip")); + progress.setCurrent(0); + + File prepareZip = null; + try { + prepareZip = File.createTempFile("coserprepare-", ".zip"); + prepareZip.deleteOnExit(); + + // copy selectively all data to target directory + MultipleFileFilter mFileFilters = new MultipleFileFilter(); + for (String[] path : selectedResults) { + OneResultFileFilter oneRFF = new OneResultFileFilter(config, path[0], path[1], path[2]); + mFileFilters.add(oneRFF); + } + + // create zip temp file + File projectsDirectory = config.getProjectsDirectory(); + + //ZipUtil.compress(prepareZip, projectsDirectory, mFileFilters); + // compress les projets à la racines de l'archive + // sans le dossier "projects" + Collection<File> files = FileUtil.getFilteredElements(projectsDirectory, mFileFilters, true); + ZipUtil.compressFiles(prepareZip, projectsDirectory, files, false); + } catch (IOException ex) { + throw new CoserBusinessException("Can't prepare upload data", ex); + } + + progress.setText(_("coser.business.uploadresult.sendzip")); + progress.setTotal((int)prepareZip.length()); + + // then upload zip file to website + try { + HttpClient httpclient = new DefaultHttpClient(); + MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); + + // password param + StringBody passwordBody = new StringBody(config.getWebUploadPassword(), Charset.forName("UTF-8")); + reqEntity.addPart("password", passwordBody); + + // file param + ProgressStream stream = new ProgressStream(new FileInputStream(prepareZip), progress); + InputStreamBody fileBody = new InputStreamBody(stream, "application/zip", prepareZip.getName()); + reqEntity.addPart("resultFile", fileBody); + + HttpPost httppost = new HttpPost(config.getWebUploadURL()); + httppost.setEntity(reqEntity); + + if (log.isInfoEnabled()) { + log.info("Uploading " + prepareZip + " to " + httppost.getURI()); + } + + HttpResponse response = httpclient.execute(httppost); + + if (log.isDebugEnabled()) { + log.debug("Upload response code : " + response.getStatusLine()); + } + } catch (ClientProtocolException ex) { + throw new CoserBusinessException("Can't upload file", ex); + } catch (IOException ex) { + throw new CoserBusinessException("Can't upload file", ex); + } + } + + /** + * Aggrege plusieurs file filters. + */ + protected static class MultipleFileFilter implements FileFilter { + protected Collection<FileFilter> fileFilters = new ArrayList<FileFilter>(); + + public void add(FileFilter f) { + fileFilters.add(f); + } + + /* + * @see java.io.FileFilter#accept(java.io.File) + */ + @Override + public boolean accept(File pathname) { + + boolean result = false; + Iterator<FileFilter> it = fileFilters.iterator(); + while (it.hasNext() && !result) { + result = it.next().accept(pathname); + } + return result; + } + } + + /** + * Filter pour un resultat donné. + * + * Attention, implémentation que ne doit fonctionner que avec ZipUtil + * car meme si on refuse en répertoire, il redemande quand même + * les fils (et il faut qu'il les demande) + */ + protected static class OneResultFileFilter implements FileFilter { + protected CoserBusinessConfig config; + protected String project; + protected String selection; + protected String rsufi; + + public OneResultFileFilter(CoserBusinessConfig config, String project, String selection, String rsufi) { + this.config = config; + this.project = project; + this.selection = selection; + this.rsufi = rsufi; + } + + /* + * @see java.io.FileFilter#accept(java.io.File) + */ + @Override + public boolean accept(File pathname) { + + boolean result = false; + + try { + String currentPathName = pathname.getCanonicalPath() + File.separator; + + File projectDirectory = new File(config.getProjectsDirectory(), project); + File selectionsDirectory = new File(projectDirectory, CoserConstants.STORAGE_SELECTION_DIRECTORY); + File selectionDirectory = new File(selectionsDirectory, selection); + File resultsDirectory = new File(selectionDirectory, CoserConstants.STORAGE_RESULTS_DIRECTORY); + File resultDirectory = new File(resultsDirectory, rsufi); + + String projectPath = projectDirectory.getCanonicalPath() + File.separator; + String selectionsPath = selectionsDirectory.getCanonicalPath() + File.separator; + String selectionPath = selectionDirectory.getCanonicalPath() + File.separator; + String resultsPath = resultsDirectory.getCanonicalPath() + File.separator; + String resultPath = resultDirectory.getCanonicalPath() + File.separator; + + // on prend + // - tout ce qu'il y a dans le projet + // - sauf le répertoire "selections" + // - ou la selection entierement + // - sauf le répertoire result + // - ou le resultat entierrement + result = (currentPathName.startsWith(projectPath) + && !currentPathName.startsWith(selectionsPath)) + || (currentPathName.startsWith(selectionPath) + && !currentPathName.startsWith(resultsPath)) + || currentPathName.startsWith(resultPath); + + } catch (IOException ex) { + throw new RuntimeException("Can't get system canonical path"); + } + + return result; + } + } } 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-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties 2010-12-22 15:17:39 UTC (rev 437) @@ -90,6 +90,8 @@ coser.business.publication.stratafilename=Strata file name coser.business.result.rsufiResultAlreadyExists=Result %s already exists \! coser.business.selection.notValidatedControl=Not validated control \! +coser.business.uploadresult.preparezip=Preparing zip archive\u2026 +coser.business.uploadresult.sendzip=Sending zip archive\u2026 coser.config.control.diffcatchlength.description=Percentage difference allowed between catch and length (in percent, for example 5% set 5.0) coser.config.control.nobsmin.description=Minimal observation number coser.config.control.typeFish.description=Fish species code type @@ -101,6 +103,10 @@ coser.config.selection.densityFilter.description=Default density filter value coser.config.selection.occurrenceFilter.description=Default occurrence filter value coser.config.validator.directory.description=Validation files directory location +coser.config.web.frontend.description=Coser server url +coser.config.web.server.directory.description=Coser server storage directory +coser.config.web.uploadpassword.description=Coser server upload result admin password +coser.config.web.uploadurl.description=Coser server upload result url depth\ attribute\ is\ not\ a\ valid\ double= haul\ name\ is\ not\ valid= lat\ attribute\ is\ not\ a\ valid\ double= 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-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties 2010-12-22 15:17:39 UTC (rev 437) @@ -90,6 +90,8 @@ coser.business.publication.stratafilename=Nom du fichier strates coser.business.result.rsufiResultAlreadyExists=Le r\u00E9sultat %D existe d\u00E9j\u00E0 \! coser.business.selection.notValidatedControl=Contr\u00F4le non valid\u00E9 \! +coser.business.uploadresult.preparezip=Pr\u00E9paration de l'archive zip\u2026 +coser.business.uploadresult.sendzip=Envoi de l'archive zip\u2026 coser.config.control.diffcatchlength.description=Pourcentage d'\u00E9cart tol\u00E9r\u00E9 entre les captures et les tailles (en pourcent, par exemple pour 5% mettre 5.0) coser.config.control.nobsmin.description=Nombre minimal d'observation coser.config.control.typeFish.description=Nom du type d'esp\u00E8ces correspondant aux poissons @@ -101,6 +103,10 @@ coser.config.selection.densityFilter.description=Filtre par d\u00E9faut sur la moyenne des densit\u00E9s coser.config.selection.occurrenceFilter.description=Filtre par d\u00E9faut sur la moyenne des occurrences coser.config.validator.directory.description=Emplacement des fichiers de validations +coser.config.web.frontend.description=Adresse du serveur web coser +coser.config.web.server.directory.description=Dossier de stockage des projets sur le serveur +coser.config.web.uploadpassword.description=Mot de passe pour l'envoi des r\u00E9sultats +coser.config.web.uploadurl.description=Adresse d'envoi des r\u00E9sultats depth\ attribute\ is\ not\ a\ valid\ double=L'attribut ProfMoy n'est pas un r\u00E9el valide haul\ name\ is\ not\ valid=L'attribut Trait n'est pas valide lat\ attribute\ is\ not\ a\ valid\ double=L'attribut Lat n'est pas un r\u00E9el valide Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrame.jaxx =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrame.jaxx 2010-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrame.jaxx 2010-12-22 15:17:39 UTC (rev 437) @@ -36,6 +36,8 @@ <JMenuItem text="coser.ui.mainframe.menu.editProject" onActionPerformed="getHandler().showProjectEditView()" enabled="{getProject() != null}" /> <JMenuItem text="coser.ui.mainframe.menu.closeProject" onActionPerformed="getHandler().closeProject()" enabled="{getProject() != null}" /> <JSeparator/> + <JMenuItem text="coser.ui.mainframe.menu.uploadResult" onActionPerformed="getHandler().showUploadResultView()"/> + <JSeparator/> <JMenuItem text="coser.ui.mainframe.menu.quit" onActionPerformed="getHandler().quit()"/> </JMenu> @@ -48,7 +50,7 @@ <JMenu id='menuOptions' text="coser.ui.mainframe.menu.options"> <JMenuItem text="coser.ui.mainframe.menu.configuration" onActionPerformed="getHandler().showCoserConfiguration()"/> - <JMenuItem text="coser.ui.mainframe.menu.validators" onActionPerformed="getHandler().showValidatorsConfiguration()" enabled="false"/> + <JMenuItem text="coser.ui.mainframe.menu.validators" onActionPerformed="getHandler().showValidatorsConfiguration()" /> <JSeparator/> <JMenuItem actionIcon="i18n-fr" text="coser.ui.mainframe.menu.locale.fr" onActionPerformed="getHandler().switchLanguage(this, Locale.FRANCE)"/> <JMenuItem actionIcon="i18n-gb" text="coser.ui.mainframe.menu.locale.uk" onActionPerformed="getHandler().switchLanguage(this, Locale.UK)"/> Modified: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrameHandler.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrameHandler.java 2010-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/CoserFrameHandler.java 2010-12-22 15:17:39 UTC (rev 437) @@ -33,6 +33,7 @@ import java.io.IOException; import java.net.URI; import java.net.URL; +import java.util.List; import java.util.Locale; import javax.swing.JDialog; @@ -40,6 +41,7 @@ import javax.swing.JOptionPane; import javax.swing.filechooser.FileFilter; +import jaxx.runtime.SwingUtil; import jaxx.runtime.swing.editor.config.ConfigUI; import jaxx.runtime.swing.editor.config.ConfigUIHelper; @@ -63,6 +65,9 @@ import fr.ifremer.coser.ui.project.ProjectHandler; import fr.ifremer.coser.ui.project.ProjectOpenView; import fr.ifremer.coser.ui.project.ProjectSummaryView; +import fr.ifremer.coser.ui.result.ResultHandler; +import fr.ifremer.coser.ui.result.RsufiResultRenderer; +import fr.ifremer.coser.ui.result.SelectUploadResultView; import fr.ifremer.coser.ui.selection.SelectionHandler; import fr.ifremer.coser.ui.selection.SelectionView; import fr.ifremer.coser.ui.widgets.LookAndFeelViewMenuItem; @@ -166,6 +171,8 @@ modelBuilder.addOption(CoserBusinessConfig.CoserBusinessOption.PROJECTS_DIRECTORY); modelBuilder.addOption(CoserBusinessConfig.CoserBusinessOption.REFERENCE_SPECIES); modelBuilder.addOption(CoserBusinessConfig.CoserBusinessOption.REFERENCE_TYPE_ESPECES); + modelBuilder.addOption(CoserBusinessConfig.CoserBusinessOption.WEB_FRONT_END); + modelBuilder.addOption(CoserBusinessConfig.CoserBusinessOption.WEB_UPLOAD_PASSWORD); // category control modelBuilder.addCategory(_("coser.config.category.configuration"), _("coser.config.category.configuration.description")); @@ -475,4 +482,19 @@ } } } + + /** + * Display ui to select result to upload to website. + */ + public void showUploadResultView() { + ProjectService projectService = view.getContextValue(ProjectService.class); + List<String[]> results = projectService.findAllProjectWithResult(); + + SelectUploadResultView selectUploadResultView = new SelectUploadResultView(view); + selectUploadResultView.setHandler(new ResultHandler()); + SwingUtil.fixTableColumnWidth(selectUploadResultView.getSelectedProjectTable(), 1, 25); + selectUploadResultView.getSelectedProjectTable().setDefaultRenderer(String[].class, new RsufiResultRenderer()); + selectUploadResultView.getSelectedProjectTableModel().setResultPath(results); + setMainComponent(selectUploadResultView); + } } 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-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/control/ControlHandler.java 2010-12-22 15:17:39 UTC (rev 437) @@ -42,7 +42,6 @@ import java.util.Set; import java.util.UUID; -import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -53,7 +52,6 @@ import javax.swing.JTextField; import javax.swing.JViewport; import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -70,10 +68,6 @@ import org.apache.commons.logging.LogFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; -import org.nuiton.math.matrix.MatrixND; -import org.nuiton.math.matrix.viewer.MatrixViewerPanel; -import org.nuiton.math.matrix.viewer.renderer.MatrixChartRenderer; -import org.nuiton.math.matrix.viewer.renderer.MatrixInfoTableRenderer; import org.nuiton.widget.SwingSession; import fr.ifremer.coser.CoserBusinessException; @@ -385,12 +379,13 @@ long before = System.currentTimeMillis(); @Override - public List<ControlError> doInBackground() { + protected List<ControlError> doInBackground() { List<ControlError> validationErrors = validationService.validateData(project, project.getControl(), progressBar); return validationErrors; } + @Override protected void done() { if (log.isInfoEnabled()) { Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/ResultHandler.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/ResultHandler.java (rev 0) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/ResultHandler.java 2010-12-22 15:17:39 UTC (rev 437) @@ -0,0 +1,122 @@ +/* + * #%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.result; + +import static org.nuiton.i18n.I18n._; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jfree.chart.JFreeChart; + +import fr.ifremer.coser.CoserBusinessException; +import fr.ifremer.coser.CoserException; +import fr.ifremer.coser.CoserConstants.ValidationLevel; +import fr.ifremer.coser.control.ControlError; +import fr.ifremer.coser.services.ProjectService; +import fr.ifremer.coser.services.PublicationService; +import fr.ifremer.coser.ui.common.CommonHandler; +import fr.ifremer.coser.ui.util.CoserProgressBar; + +/** + * Handler for rsufi result management. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class ResultHandler extends CommonHandler { + + private static final Log log = LogFactory.getLog(ResultHandler.class); + + /** + * Perform file upload to coser server after selection by user. + * + * @param view view + */ + public void performResultUpload(final SelectUploadResultView view) { + + int response = JOptionPane.showConfirmDialog(view, _("coser.ui.uploadresult.confirmupload"), _("coser.ui.uploadresult.title"), + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (response == JOptionPane.YES_OPTION) { + + // get result selected by user + final Collection<String[]> selectedResult = view.getSelectedProjectTableModel().getSelectedResult(); + if (CollectionUtils.isNotEmpty(selectedResult)) { + + SwingWorker<Void, Void> task = new SwingWorker<Void, Void>() { + + @Override + protected Void doInBackground() { + + try { + // get progress bar + CoserProgressBar progressBar = view.getUploadProgressBar(); + ProjectService projectService = view.getContextValue(ProjectService.class); + projectService.performResultUpload(selectedResult, progressBar); + } + catch (CoserBusinessException ex) { + throw new CoserException("Can't send results", ex); + } + return null; + } + + @Override + protected void done() { + + // laisser cet appel, sinon les exceptions sont silencieuse + try { + get(); + } catch (Exception ex) { + throw new CoserException("Can't send results", ex); + } + + JOptionPane.showMessageDialog(view, _("coser.ui.uploadresult.resultsuploaded"), + _("coser.ui.uploadresult.title"), JOptionPane.INFORMATION_MESSAGE); + } + }; + task.execute(); + } + } + else { + if (log.isDebugEnabled()) { + log.debug("Upload result skipped"); + } + } + } +} Property changes on: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/ResultHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultRenderer.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultRenderer.java (rev 0) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultRenderer.java 2010-12-22 15:17:39 UTC (rev 437) @@ -0,0 +1,61 @@ +/* + * #%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.result; + +import java.awt.Component; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +import org.apache.commons.lang.StringUtils; + +/** + * TODO add comment here. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class RsufiResultRenderer extends DefaultTableCellRenderer { + + /** serialVersionUID. */ + private static final long serialVersionUID = -9030155088814184637L; + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int row, int column) { + + Object localValue = value; + if (value instanceof String[]) { + String[] arrayValue = (String[])value; + localValue = StringUtils.join(arrayValue, '/'); + } + return super.getTableCellRendererComponent(table, localValue, isSelected, hasFocus, + row, column); + } +} Property changes on: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultRenderer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultTreeModel.java =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultTreeModel.java (rev 0) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultTreeModel.java 2010-12-22 15:17:39 UTC (rev 437) @@ -0,0 +1,154 @@ +/* + * #%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.result; + +import static org.nuiton.i18n.I18n._; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.table.AbstractTableModel; + +/** + * Model represantant la liste de tous les resultats rsufi present + * dans le dossier de stockage de coser, tous projets confondu. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class RsufiResultTreeModel extends AbstractTableModel { + + /** serialVersionUID. */ + private static final long serialVersionUID = 6404018386062830677L; + + protected List<String[]> resultPath; + + protected Set<String[]> selectedResult; + + public void setResultPath(List<String[]> resultPath) { + this.resultPath = resultPath; + selectedResult = new HashSet<String[]>(); + fireTableDataChanged(); + } + + public Set<String[]> getSelectedResult() { + return selectedResult; + } + + /* + * @see javax.swing.table.TableModel#getRowCount() + */ + @Override + public int getRowCount() { + int result = 0; + if (resultPath != null) { + result = resultPath.size(); + } + return result; + } + + @Override + public String getColumnName(int column) { + String result = null; + switch(column) { + case 0: + result = _("coser.ui.uploadresult.path"); + break; + case 1: + result = _("coser.ui.uploadresult.selected"); + break; + } + return result; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + Class<?> result = null; + switch(columnIndex) { + case 0: + result = String[].class; + break; + case 1: + result = Boolean.class; + break; + } + return result; + } + + /* + * @see javax.swing.table.TableModel#getColumnCount() + */ + @Override + public int getColumnCount() { + return 2; + } + + /* + * @see javax.swing.table.TableModel#getValueAt(int, int) + */ + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + + Object result = null; + + String[] data = resultPath.get(rowIndex); + switch (columnIndex) { + case 0: + result = data; + break; + case 1: + // c'est pas tres safe tu les hashcode des tableaux + // mais bon... + result = selectedResult.contains(data); + } + + return result; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == 1; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + + if (aValue instanceof Boolean) { + String[] data = resultPath.get(rowIndex); + Boolean bValue = (Boolean)aValue; + if (bValue.booleanValue()) { + selectedResult.add(data); + } + else { + selectedResult.remove(data); + } + } + } +} Property changes on: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/RsufiResultTreeModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/SelectUploadResultView.jaxx =================================================================== --- trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/SelectUploadResultView.jaxx (rev 0) +++ trunk/coser-ui/src/main/java/fr/ifremer/coser/ui/result/SelectUploadResultView.jaxx 2010-12-22 15:17:39 UTC (rev 437) @@ -0,0 +1,52 @@ +<!-- + #%L + Coser :: UI + + $Id$ + $HeadURL$ + %% + Copyright (C) 2010 Ifremer, Codelutin, Chatellier Eric + %% + 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% + --> +<Table> + <ResultHandler id="handler" javaBean="null" /> + + <row> + <cell weightx="1" fill="horizontal"> + <JLabel text="coser.ui.uploadresult.explanation" /> + </cell> + </row> + <row> + <cell weightx="1" fill="both"> + <JScrollPane> + <RsufiResultTreeModel id="selectedProjectTableModel" /> + <JTable id="selectedProjectTable" model="{getSelectedProjectTableModel()}"/> + </JScrollPane> + </cell> + </row> + <row> + <cell weightx="1" anchor="east"> + <JButton text="coser.ui.uploadresult.upload" + onActionPerformed="getHandler().performResultUpload(this)"/> + </cell> + </row> + <row> + <cell weightx="1" fill="horizontal"> + <fr.ifremer.coser.ui.util.CoserProgressBar id="uploadProgressBar" stringPainted="true" /> + </cell> + </row> +</Table> Modified: trunk/coser-ui/src/main/resources/i18n/coser-ui_en_GB.properties =================================================================== --- trunk/coser-ui/src/main/resources/i18n/coser-ui_en_GB.properties 2010-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-ui/src/main/resources/i18n/coser-ui_en_GB.properties 2010-12-22 15:17:39 UTC (rev 437) @@ -83,6 +83,7 @@ coser.ui.mainframe.menu.openProject=Open project coser.ui.mainframe.menu.options=Options coser.ui.mainframe.menu.quit=Quit +coser.ui.mainframe.menu.uploadResult=Results publication coser.ui.mainframe.menu.validators=Controls coser.ui.mainframe.menu.view=View coser.ui.mainframe.menu.view.lookandfeel=Look and feel @@ -210,6 +211,13 @@ coser.ui.selection.tab.details=Selection details coser.ui.selection.tab.lists=Species lists coser.ui.selection.tab.rsufi=RSufi +coser.ui.uploadresult.confirmupload=Are you sure you want to upload this results ? +coser.ui.uploadresult.explanation=Welcome in results server publication interface. Only administrators with password can use this interface. +coser.ui.uploadresult.path=Result path +coser.ui.uploadresult.resultsuploaded=Results published. +coser.ui.uploadresult.selected=\u2026 +coser.ui.uploadresult.title=Results publication +coser.ui.uploadresult.upload=Send results coser.ui.validators.cancel=Cancel coser.ui.validators.deleteValidator=Delete coser.ui.validators.description=Application must be restarted after validators modification. Modified: trunk/coser-ui/src/main/resources/i18n/coser-ui_fr_FR.properties =================================================================== --- trunk/coser-ui/src/main/resources/i18n/coser-ui_fr_FR.properties 2010-12-22 15:14:42 UTC (rev 436) +++ trunk/coser-ui/src/main/resources/i18n/coser-ui_fr_FR.properties 2010-12-22 15:17:39 UTC (rev 437) @@ -83,6 +83,7 @@ coser.ui.mainframe.menu.openProject=Ouvrir un projet coser.ui.mainframe.menu.options=Options coser.ui.mainframe.menu.quit=Quitter +coser.ui.mainframe.menu.uploadResult=Publication des r\u00E9sultats coser.ui.mainframe.menu.validators=Contr\u00F4les coser.ui.mainframe.menu.view=Vue coser.ui.mainframe.menu.view.lookandfeel=Th\u00E8me @@ -210,6 +211,13 @@ coser.ui.selection.tab.details=D\u00E9tails de la s\u00E9lection coser.ui.selection.tab.lists=Listes des esp\u00E8ces coser.ui.selection.tab.rsufi=RSufi +coser.ui.uploadresult.confirmupload=\u00CAtes vous s\u00FBr de vouloir publier ces r\u00E9sultats ? +coser.ui.uploadresult.explanation=Bienvenue dans l'interface de s\u00E9lection des r\u00E9sultats \u00E0 envoyer sur le serveur Coser. Seul les administrateurs disposant du mot de passe peuvent effectuer cette action. +coser.ui.uploadresult.path=Chemin du r\u00E9sultats +coser.ui.uploadresult.resultsuploaded=R\u00E9sultats publi\u00E9s. +coser.ui.uploadresult.selected=\u2026 +coser.ui.uploadresult.title=Publication des r\u00E9sultats +coser.ui.uploadresult.upload=Envoyer les r\u00E9sultats coser.ui.validators.cancel=Annuler coser.ui.validators.deleteValidator=Supprimer coser.ui.validators.description=L'application doit \u00EAtre red\u00E9marr\u00E9e apr\u00E8s la modification des validateurs.
participants (1)
-
chatellier@users.labs.libre-entreprise.org