Author: fdesbois Date: 2010-03-19 16:05:04 +0100 (Fri, 19 Mar 2010) New Revision: 2951 Log: - Move SendMail thread in business module (started from PollenContext) - Evo #148 : improve pager (with icons) - Improve i18n managment for Tapestry integration (using tapestry-bundle goal from i18n plugin) - Continue refactor of VoteForPoll page Added: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/SendMail.java trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/SendMailTest.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollUri.java trunk/pollen-ui/src/main/webapp/img/1leftarrow.png trunk/pollen-ui/src/main/webapp/img/1rightarrow.png trunk/pollen-ui/src/main/webapp/img/2leftarrow.png trunk/pollen-ui/src/main/webapp/img/2rightarrow.png Removed: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java.orig trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/utils/SendMail.java trunk/pollen-ui/src/test/java/org/chorem/pollen/ui/utils/SendMailTest.java Modified: trunk/ trunk/doc/presentation-2010-03-11/Presentation-Pollen.odp trunk/pollen-business/pom.xml trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenBusinessException.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenContext.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenException.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataPollConverter.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataVoteCountingConverter.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/dto/PollDTO.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceListImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePoll.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePollImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceResultsImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceUserImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceVoteImpl.java trunk/pollen-business/src/main/java/org/chorem/pollen/business/utils/ContextUtil.java trunk/pollen-business/src/main/resources/i18n/pollen-business-en_GB.properties trunk/pollen-business/src/main/resources/i18n/pollen-business-fr_FR.properties trunk/pollen-business/src/main/resources/pollen.properties trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/ServicePollImplTest.java trunk/pollen-business/src/test/resources/pollen.properties trunk/pollen-ui/pom.xml trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Pager.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollHelper.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ConfirmPoll.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollModification.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/AppModule.java trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_en.properties trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_fr.properties trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_en.properties trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_fr.properties trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml trunk/pom.xml Property changes on: trunk ___________________________________________________________________ Modified: svn:ignore - target nbactions.xml .settings .classpath .project *.ipr *.iws *.iml + target nbactions.xml .settings .classpath .project *.ipr *.iws *.iml .pollen Modified: trunk/doc/presentation-2010-03-11/Presentation-Pollen.odp =================================================================== (Binary files differ) Modified: trunk/pollen-business/pom.xml =================================================================== --- trunk/pollen-business/pom.xml 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/pom.xml 2010-03-19 15:05:04 UTC (rev 2951) @@ -27,6 +27,10 @@ <artifactId>commons-logging</artifactId> </dependency> <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> </dependency> @@ -38,6 +42,10 @@ <groupId>org.nuiton</groupId> <artifactId>nuiton-utils</artifactId> </dependency> + <dependency> + <groupId>net.sf.opencsv</groupId> + <artifactId>opencsv</artifactId> + </dependency> <!-- <dependency> <groupId>org.chorem</groupId> <artifactId>chorem-commons</artifactId> @@ -138,6 +146,15 @@ <goal>gen</goal> </goals> </execution> + <execution> + <id>make-bundle</id> + <goals> + <goal>bundle</goal> + </goals> + <configuration> + <bundleOutputName>pollen-business</bundleOutputName> + </configuration> + </execution> </executions> </plugin> <!--<plugin> Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenBusinessException.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenBusinessException.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenBusinessException.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,6 +1,7 @@ package org.chorem.pollen.business; import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; /** * PollenBusinessException @@ -18,13 +19,21 @@ private static final long serialVersionUID = 1L; protected PollenExceptionType type; + + protected Object[] args; public PollenBusinessException(PollenExceptionType type) { super(type.getMessage()); } + public PollenBusinessException(PollenExceptionType type, Object... args) { + super(type.getMessage()); + this.args = args; + } + public enum PollenExceptionType { - LOAD_CONFIGURATION(_("pollen.exception.load_configuration")); + //LOAD_CONFIGURATION(n_("pollen.exception.load_configuration")), + POLL_NOT_EXIST(n_("pollen.exception.poll_not_exist")); private String message; @@ -35,6 +44,9 @@ public String getMessage() { return message; } + } + public Object[] getArgs() { + return args; } } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenContext.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenContext.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenContext.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -7,6 +7,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.pollen.business.persistence.PollenModelDAOHelper; +import org.chorem.pollen.business.services.SendMail; import org.chorem.pollen.business.services.ServiceUserImpl; import org.nuiton.i18n.I18n; import org.nuiton.topia.TopiaContext; @@ -16,6 +17,8 @@ import org.nuiton.util.ApplicationConfig; import org.nuiton.util.ArgumentsParserException; import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; +import org.nuiton.i18n.init.DefaultI18nInitializer; /** * PollenContext @@ -39,6 +42,8 @@ private static Date currentDate; + private static SendMail sendMail; + /** * Default configuration file will be loaded using * {@link org.nuiton.util.ApplicationConfig }. @@ -59,8 +64,8 @@ loadConfiguration(conf); } catch (ArgumentsParserException eee) { - doCatch(eee, - _("pollen.error.context.parse", PollenContext.DEFAULT_FILENAME)); + doCatch(eee, n_("pollen.error.context.parse"), + PollenContext.DEFAULT_FILENAME); } } @@ -94,7 +99,11 @@ * */ public static void start() { - try { + try { + if (log.isInfoEnabled()) { + log.info("Initialize i18n bundle"); + } + I18n.setInitializer(new DefaultI18nInitializer("pollen-business")); I18n.init(); ServiceUserImpl serviceUser = new ServiceUserImpl(); @@ -104,12 +113,15 @@ PollenProperty.ADMIN_EMAIL.getValue() ); + sendMail = new SendMail(); + sendMail.start(); + if (log.isInfoEnabled()) { log.info("pollen is started !"); } } catch (Exception eee) { - doCatch(eee, _("pollen.error.context.start")); + doCatch(eee, n_("pollen.error.context.start")); } } @@ -119,11 +131,16 @@ public static void stop() { try { getRootContext().closeContext(); + sendMail.stopExec(); } catch (Exception eee) { - doCatch(eee, _("pollen.error.context.stop")); + doCatch(eee, n_("pollen.error.context.stop")); } } + public static SendMail getSendMail() { + return sendMail; + } + /** * Get a property from the configuration. * @@ -179,7 +196,7 @@ try { return TopiaContextFactory.getContext(getProperties()); } catch (TopiaNotFoundException eee) { - doCatch(eee, _("pollen.error.context.getRootContext")); + doCatch(eee, n_("pollen.error.context.getRootContext")); } return null; } @@ -191,10 +208,11 @@ * * @param eee the exception to manage * @param message the message to add to the new PollenException + * @param args for message * @throws PollenException which contains the exception as the cause */ - public static void doCatch(Exception eee, String message) throws PollenException { - doCatch(eee, message, null); + public static void doCatch(Exception eee, String message, Object... args) throws PollenException { + doCatch(null, eee, message); } /** @@ -203,14 +221,15 @@ * {@code transaction} will be rollback. * Used in catch statement in services. * + * @param transaction the current TopiaContext * @param eee the exception to manage * @param message the message to add to the new PollenException - * @param transaction the current TopiaContext + * @param args for message * @throws PollenException */ - public static void doCatch(Exception eee, String message, TopiaContext transaction) throws PollenException { + public static void doCatch(TopiaContext transaction, Exception eee, String message, Object... args) throws PollenException { if (log.isErrorEnabled()) { - log.error(message, eee); + log.error(_(message, args), eee); } // rollback de la transaction courante @@ -225,7 +244,7 @@ } // PollenBusinessException must be managed (catch and throw) when needed // if (! (eee instanceof PollenBusinessException)) { - throw new PollenException(message, eee); + throw new PollenException(eee, message, args); // } } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenException.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenException.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/PollenException.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -16,8 +16,19 @@ private static final long serialVersionUID = 1L; - public PollenException(String message, Throwable eee) { + protected Object[] args; + +// public PollenException(Throwable eee, String message) { +// super(message, eee); +// } + + public PollenException(Throwable eee, String message, Object... args) { super(message, eee); + this.args = args; } + public Object[] getArgs() { + return args; + } + } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataPollConverter.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataPollConverter.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataPollConverter.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -88,7 +88,7 @@ pollDTO.setCreatorEmail(ePoll.getCreator().getEmail()); } if (ePoll.getChoice().size() > 0) { - pollDTO.setChoiceDTOs(choiceConverter.createChoiceDTOs(ePoll + pollDTO.setChoices(choiceConverter.createChoiceDTOs(ePoll .getChoice())); } // if (ePoll.getVote().size() > 0) { @@ -146,7 +146,7 @@ // mise à jour ou création des choix ServiceChoice sChoice = new ServiceChoiceImpl(); - for (ChoiceDTO choiceDTO : pollDTO.getChoiceDTOs()) { + for (ChoiceDTO choiceDTO : pollDTO.getChoices()) { boolean updated = sChoice.updateChoice(choiceDTO); if (!updated) { choiceDTO.setId(sChoice.createChoice(choiceDTO)); @@ -163,7 +163,7 @@ Iterator<Choice> itChoice = ePoll.getChoice().iterator(); while (itChoice.hasNext()) { Choice currentChoice = itChoice.next(); - for (ChoiceDTO choiceDTO : pollDTO.getChoiceDTOs()) { + for (ChoiceDTO choiceDTO : pollDTO.getChoices()) { if (currentChoice.getTopiaId().equals(choiceDTO.getId())) { validChoice = true; } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataVoteCountingConverter.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataVoteCountingConverter.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/converters/DataVoteCountingConverter.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -188,7 +188,7 @@ bPollDTO.getComments().add(createPollCommentDTO(comment)); } for (PollChoiceDTO choice : pollDTO.getChoices()) { - bPollDTO.getChoiceDTOs().add(createPollChoiceDTO(choice)); + bPollDTO.getChoices().add(createPollChoiceDTO(choice)); } // TODO conversion des groupes et des votes Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/dto/PollDTO.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/dto/PollDTO.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/dto/PollDTO.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -86,8 +86,6 @@ private List<VotingListDTO> votingListDTOs = new ArrayList<VotingListDTO>(); - private List<VoteDTO> voteDTOs = new ArrayList<VoteDTO>(); - private int nbVotes; private List<PreventRuleDTO> preventRuleDTOs = new ArrayList<PreventRuleDTO>(); @@ -362,14 +360,6 @@ this.votingListDTOs = votingListDTOs; } - public List<VoteDTO> getVoteDTOs() { - return voteDTOs; - } - - public void setVoteDTOs(List<VoteDTO> voteDTOs) { - this.voteDTOs = voteDTOs; - } - public int getNbVotes() { return nbVotes; } @@ -378,13 +368,6 @@ this.nbVotes = nbVotes; } - public void addVote(VoteDTO vote) { - if (voteDTOs == null) { - voteDTOs = new ArrayList<VoteDTO>(); - } - voteDTOs.add(vote); - } - public List<PreventRuleDTO> getPreventRuleDTOs() { return preventRuleDTOs; } @@ -400,11 +383,11 @@ preventRuleDTOs.add(rule); } - public List<ChoiceDTO> getChoiceDTOs() { + public List<ChoiceDTO> getChoices() { return choiceDTOs; } - public void setChoiceDTOs(List<ChoiceDTO> choiceDTOs) { + public void setChoices(List<ChoiceDTO> choiceDTOs) { this.choiceDTOs = choiceDTOs; } Copied: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/SendMail.java (from rev 2943, trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/utils/SendMail.java) =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/SendMail.java (rev 0) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/SendMail.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -0,0 +1,248 @@ +/* *##% Pollen + * Copyright (C) 2009 CodeLutin + * + * 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/>. ##%*/ + +package org.chorem.pollen.business.services; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.chorem.pollen.business.utils.MailUtil; +import org.nuiton.util.FileUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import au.com.bytecode.opencsv.CSVReader; +import au.com.bytecode.opencsv.CSVWriter; +import org.apache.commons.io.IOUtils; +import org.chorem.pollen.business.PollenProperty; + +/** + * Mass mail management class. + * + * This class store email to send in a csv file, and send it (one per second) in + * a second time. + * This class can restart to send mail at application restart. + * + * For a mass mail sending to start, following files must be present: + * <ul> + * <li>xxx.emails : CSV file ("email", "subject", "body")</li> + * <li>xxx.index : next index to manage ( inited at 0)</li> + * </ul> + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +public class SendMail extends Thread { + + /** logger. */ + private static final Logger log = LoggerFactory.getLogger(SendMail.class); + + public static final String EXTENSION_MAIL = ".mail"; + public static final String EXTENSION_INDEX = ".index"; + + /** Mail storage directory. */ + protected File mailStorageDirectory; + + protected volatile boolean stop; + + public SendMail() { + + // get email directory in configuration + // create it if not exists + String filename = PollenProperty.EMAIL_DIR.getValue(); + mailStorageDirectory = new File(filename); + if (!mailStorageDirectory.exists()) { + if (mailStorageDirectory.mkdirs()) { + if (log.isDebugEnabled()) { + log.debug("Email storage directory created in : " + mailStorageDirectory.getAbsolutePath()); + } + } + } + } + + public synchronized void stopExec() { + stop = true; + } + + /* + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + + // try to find existing files + while (!stop) { + try { + sendAllMails(); + + // bloque thread until next notify + sleep(); + } + catch (Exception ex) { + if (log.isErrorEnabled()) { + log.error("Error during SendMail main loop", ex); + } + } + } + } + + protected synchronized void sleep() throws InterruptedException { + wait(); + } + + public synchronized void wakeUp() { + notifyAll(); + } + + /** + * Look for all xx.index file, and restart mail sending on + * non ending mass mail sending. + * + * After execution, delete mail and index file. + * @throws IOException + */ + protected void sendAllMails() throws IOException { + + // don't do for, allways take the first found + // a new one can be created when managing one other + List<File> indexFiles = null; + do { + + // filter is java valid : .*\\.index + indexFiles = FileUtil.find(mailStorageDirectory, ".*\\" + EXTENSION_INDEX, false); + + if (!indexFiles.isEmpty()) { + File indexFile = indexFiles.get(0); + // convert index content to int + String indexContent = FileUtils.readFileToString(indexFile, "UTF-8"); + int index = Integer.parseInt(indexContent); + + // get mail content file + File mailFile = new File(indexFile.getAbsolutePath().replaceAll(EXTENSION_INDEX + "$", EXTENSION_MAIL)); + + if (log.isDebugEnabled()) { + log.debug("Managing mail file : " + mailFile + " (from index " + indexContent + ")"); + } + + Reader indexFileReader = new BufferedReader(new FileReader(mailFile)); + CSVReader cvsReader = new CSVReader(indexFileReader); + + int currentIndex = 0; + String[] currentLine = cvsReader.readNext(); + while (currentLine != null) { + String receiver = currentLine[0]; + String subject = currentLine[1]; + String body = currentLine[2]; + + // index contains next index to treat so == is ok + if (currentIndex >= index) { + String host = PollenProperty.EMAIL_HOST.getValue(); + int port = Integer.parseInt( + PollenProperty.EMAIL_PORT.getValue()); + String from = PollenProperty.EMAIL_FROM.getValue(); + MailUtil.sendMail(host, port, from, + receiver, subject, body); + + // index contains next index to treat + FileUtils.writeStringToFile(indexFile, String.valueOf(currentIndex + 1)); + + // wait 2 secondes between each mail to not + // load smtp server + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + if (log.isErrorEnabled()) { + log.error("Can't wait between mail", ex); + } + } + } + else { + if (log.isDebugEnabled()) { + log.debug("Mail to " + receiver + " already sent in a previous execution, skip."); + } + } + + currentIndex++; + currentLine = cvsReader.readNext(); + } + + // delete woth index and mail file + mailFile.delete(); + indexFile.delete(); + } + else { + if (log.isInfoEnabled()) { + log.info("No more index mail index file found, go to sleep a while :)"); + } + } + } while (!indexFiles.isEmpty()); + } + + /** + * Prepare mail list. + * + * TODO : improve configuration reading + * + * @param id + * @param mailData + * @throws IOException + */ + public void prepareMails(String id, List<Map<String, String>> mailData) throws IOException { + + Writer fileWriter = null; + CSVWriter cvsWriter = null; + try { + + // write CSV datas + File emailFile = new File(mailStorageDirectory, id + EXTENSION_MAIL); + fileWriter = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(emailFile))); + cvsWriter = new CSVWriter(fileWriter); + + for (Map<String, String> singleMailData : mailData) { + String[] nextLine = new String[] { + singleMailData.get("receiver"), + singleMailData.get("subject"), + singleMailData.get("body") + }; + cvsWriter.writeNext(nextLine); + } + + // write index (default to 0) + File indexFile = new File(mailStorageDirectory, id + EXTENSION_INDEX); + FileUtil.writeString(indexFile, "0"); + } + finally { + if (cvsWriter != null) { + cvsWriter.close(); + } + IOUtils.closeQuietly(fileWriter); + } + + } +} Property changes on: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/SendMail.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL" Added: svn:mergeinfo + Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceListImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceListImpl.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceListImpl.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -40,7 +40,7 @@ import org.chorem.pollen.business.persistence.VotingListDAO; import org.chorem.pollen.business.utils.ContextUtil; import org.nuiton.topia.TopiaContext; -import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; /** * Implémentation du service de gestion des listes. @@ -210,11 +210,9 @@ personList.addPollAccount(account); } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.serviceList.createAccountForPersonList", - personList.getName(), account.getVotingId()), - transaction - ); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.serviceList.createAccountForPersonList"), + personList.getName(), account.getVotingId()); } finally { PollenContext.doFinally(transaction); } @@ -247,11 +245,9 @@ personList.removePollAccount(accountId); } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.serviceList.deleteAccountFromPersonList", - accountId, personList.getName(), personList.getId()), - transaction - ); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.serviceList.deleteAccountFromPersonList"), + accountId, personList.getName(), personList.getId()); } finally { PollenContext.doFinally(transaction); } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePoll.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePoll.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePoll.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -78,16 +78,6 @@ public PollDTO findPollByPollId(String pollId); /** - * Récupération d'un sondage par son nom - * - * @param pollName nom du sondage - * @return liste de sondages - * @deprecated useless method : only used in tests - */ - @Deprecated - public List<PollDTO> findPollsByName(String pollName); - - /** * Récupération des sondages d'un utilisateur * * @param userId Le créateur du sondage @@ -137,7 +127,7 @@ public void createComment(PollDTO poll, CommentDTO comment); /** - * Delete a comment from a poll. + * Delete a comment from a {@code poll}. * * @param poll owner of the comment * @param commentId id of the comment to delete @@ -145,6 +135,15 @@ public void deleteComment(PollDTO poll, String commentId); /** + * Retrieve all comments for the {@code poll} + * + * @param poll owner of the comment + * @return the list of comments of the poll + */ + public List<CommentDTO> getComments(PollDTO poll); + + + /** * Return the pollAccount corresponding to the {@code accountUId} for the * restricted {@code poll}. * TODO : need JUnit test, must be done for 1.3 Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePollImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePollImpl.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServicePollImpl.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -53,6 +53,7 @@ import org.chorem.pollen.business.persistence.VotingListDAO; import org.chorem.pollen.business.utils.ContextUtil; import org.chorem.pollen.business.PollenContext; +import org.chorem.pollen.business.persistence.PersonToListDAO; import org.chorem.pollen.common.PollType; import org.chorem.pollen.common.VoteCountingType; import org.nuiton.topia.TopiaContext; @@ -60,6 +61,7 @@ import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.framework.TopiaQuery.Op; import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; /** * Implémentation du service de gestion des sondages. @@ -108,7 +110,7 @@ // ** Create new choices ChoiceDAO choiceDAO = PollenModelDAOHelper.getChoiceDAO(transaction); - for (ChoiceDTO choiceDTO : pollDTO.getChoiceDTOs()) { + for (ChoiceDTO choiceDTO : pollDTO.getChoices()) { Choice choice = PollenConverter.convert(choiceDTO, choiceDAO.create()); choice.setPoll(entity); @@ -143,9 +145,9 @@ PollenConverter.convert(entity, pollDTO); } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.createPoll", - pollDTO.getTitle(), pollDTO.getCreatorId()), transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.createPoll"), + pollDTO.getTitle(), pollDTO.getCreatorId()); } finally { PollenContext.doFinally(transaction); } @@ -252,7 +254,7 @@ ChoiceDAO choiceDAO = PollenModelDAOHelper.getChoiceDAO(transaction); // ** Update choices (no add, no remove) - for (ChoiceDTO choiceDTO : pollDTO.getChoiceDTOs()) { + for (ChoiceDTO choiceDTO : pollDTO.getChoices()) { Choice choice = choiceDAO.findByTopiaId(choiceDTO.getId()); PollenConverter.convert(choiceDTO, choice); choice.update(); @@ -272,9 +274,9 @@ return true; } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.updatePoll", - pollDTO.getTitle(), pollDTO.getPollId()), transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.updatePoll"), + pollDTO.getTitle(), pollDTO.getPollId()); return false; } finally { PollenContext.doFinally(transaction); @@ -315,9 +317,8 @@ return true; } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.deletePoll", pollId), - transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.deletePoll"), pollId); return false; } finally { PollenContext.doFinally(transaction); @@ -329,6 +330,10 @@ TopiaContext transaction = null; PollDTO result = null; try { + if (log.isInfoEnabled()) { + log.info("findPollByPollId : pollUId = " + pollId); + } + transaction = rootContext.beginTransaction(); pollDAO = PollenModelDAOHelper.getPollDAO(transaction); @@ -371,11 +376,11 @@ // } // Load comments - for (Comment comment : pollEntity.getComment()) { - CommentDTO dto = - PollenConverter.convert(comment, new CommentDTO()); - result.addComment(dto); - } +// for (Comment comment : pollEntity.getComment()) { +// CommentDTO dto = +// PollenConverter.convert(comment, new CommentDTO()); +// result.addComment(dto); +// } // Load preventRules for (PreventRule rule : pollEntity.getPreventRule()) { @@ -399,8 +404,8 @@ return result; } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.getPoll", pollId), transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.getPoll"), pollId); return null; } finally { PollenContext.doFinally(transaction); @@ -408,36 +413,6 @@ } @Override - public List<PollDTO> findPollsByName(String pollName) { - TopiaContext transaction = null; - List<PollDTO> results = null; - List<Poll> pollEntities = null; - try { - transaction = rootContext.beginTransaction(); - - pollDAO = PollenModelDAOHelper.getPollDAO(transaction); - - pollEntities = pollDAO.findAllByTitle(pollName); - - converter.setTransaction(transaction); - results = converter.createPollDTOs(pollEntities); - - transaction.commitTransaction(); - - if (log.isDebugEnabled()) { - log.debug("Entities found: " + ((results == null) ? "null" : results.size())); - } - - return results; - } catch (Exception e) { - ContextUtil.doCatch(e, transaction); - return null; - } finally { - PollenContext.doFinally(transaction); - } - } - - @Override public List<PollDTO> findPollsByUser(String userId) { TopiaContext transaction = null; List<PollDTO> results = null; @@ -640,8 +615,8 @@ return results; } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.getAllPolls"), transaction); + ContextUtil.doCatch(eee, transaction, + _("pollen.error.servicePoll.getAllPolls")); return null; } finally { PollenContext.doFinally(transaction); @@ -652,6 +627,10 @@ public void createComment(PollDTO poll, CommentDTO comment) { TopiaContext transaction = null; try { + if (log.isInfoEnabled()) { + log.info("createComment : pollUId = " + poll.getPollId() + + " _ comment = " + comment); + } transaction = rootContext.beginTransaction(); // Create the new comment @@ -673,10 +652,9 @@ poll.addComment(comment); } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.addComment", - comment.getAuthor(), poll.getTitle(), poll.getId()), - transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.addComment"), + comment.getAuthor(), poll.getTitle(), poll.getId()); } finally { PollenContext.doFinally(transaction); } @@ -686,6 +664,10 @@ public void deleteComment(PollDTO poll, String commentId) { TopiaContext transaction = null; try { + if (log.isInfoEnabled()) { + log.info("deleteComment : pollUId = " + poll.getPollId() + + " _ commentId = " + commentId); + } transaction = rootContext.beginTransaction(); // Find the comment @@ -706,15 +688,47 @@ poll.removeComment(commentId); } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.servicePoll.deleteComment", commentId, - poll.getTitle(), poll.getId()), transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.deleteComment"), commentId, + poll.getTitle(), poll.getId()); } finally { PollenContext.doFinally(transaction); } } @Override + public List<CommentDTO> getComments(PollDTO poll) { + TopiaContext transaction = null; + List<CommentDTO> results = new ArrayList<CommentDTO>(); + try { + if (log.isInfoEnabled()) { + log.info("getComments : pollUId = " + poll.getPollId()); + } + transaction = rootContext.beginTransaction(); + + CommentDAO dao = PollenModelDAOHelper.getCommentDAO(transaction); + TopiaQuery query = dao.createQuery(). + add(Comment.POLL + "." + Poll.POLL_ID, poll.getPollId()); + + List<Comment> entities = dao.findAllByQuery(query); + + for (Comment entity : entities) { + CommentDTO dto = + PollenConverter.convert(entity, new CommentDTO()); + results.add(dto); + } + + } catch (Exception eee) { + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.getComments"), + poll.getTitle(), poll.getId()); + } finally { + PollenContext.doFinally(transaction); + } + return results; + } + + @Override public PollAccountDTO getRestrictedAccount(String accountUId, PollDTO poll) { TopiaContext transaction = null; PollAccountDTO result = null; @@ -728,26 +742,34 @@ // Use PersonToList association entity to find coherence between // the poll and votingId - List<PersonToList> tmp = transaction.find( - "FROM " + PersonToList.class.getName() + - " WHERE pollAccount.accountId = :accountUId" + - " AND votingList.poll.pollId = :pollUId", - "accountUId", accountUId, - "pollUId", poll.getPollId()); +// List<PersonToList> tmp = transaction.find( +// "FROM " + PersonToList.class.getName() + +// " WHERE pollAccount.accountId = :accountUId" + +// " AND votingList.poll.pollId = :pollUId", +// "accountUId", accountUId, +// "pollUId", poll.getPollId()); - //PersonToListDAO dao = PollenModel + PersonToListDAO dao = + PollenModelDAOHelper.getPersonToListDAO(transaction); + TopiaQuery query = dao.createQuery(). + add(PersonToList.POLL_ACCOUNT + "." + + PollAccount.ACCOUNT_ID, accountUId). + add(PersonToList.VOTING_LIST + "." + + VotingList.POLL + "." + Poll.POLL_ID, poll.getPollId()); - if (tmp.size() > 0) { - PollAccount account = tmp.get(0).getPollAccount(); + PersonToList assoc = dao.findByQuery(query); + + if (assoc != null) { + PollAccount account = assoc.getPollAccount(); PollenConverter.convert(account, result); } } catch (Exception eee) { - ContextUtil.doCatch(eee, transaction, - "Unable to retrieve restricted account with accountUId = " + - accountUId + " and poll with uid = " + poll.getPollId()); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.servicePoll.getRestrictedAccount"), + accountUId, poll.getPollId()); } finally { - ContextUtil.doFinally(transaction); + PollenContext.doFinally(transaction); } return result; } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceResultsImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceResultsImpl.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceResultsImpl.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -45,7 +45,7 @@ import org.chorem.pollen.votecounting.services.ServiceVoteCounting; import org.chorem.pollen.votecounting.services.ServiceVoteCountingImpl; import org.nuiton.topia.TopiaContext; -import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; /** * Implémentation du service de gestion des résultats. @@ -297,7 +297,7 @@ } catch (Exception eee) { PollenContext.doCatch(eee, - _("pollen.error.serviceResults.importPoll")); + n_("pollen.error.serviceResults.importPoll")); } return topiaId; Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceUserImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceUserImpl.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceUserImpl.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -31,7 +31,7 @@ import org.chorem.pollen.business.utils.ContextUtil; import org.chorem.pollen.business.utils.MD5; import org.nuiton.topia.TopiaContext; -import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; /** * Implémentation du service de gestion des utilisateurs. @@ -335,9 +335,9 @@ transaction.commitTransaction(); } } catch (Exception eee) { - PollenContext.doCatch(eee, - _("pollen.error.serviceUser.createDefaultAdmin", - login, email), transaction); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.serviceUser.createDefaultAdmin"), + login, email); } finally { PollenContext.doFinally(transaction); } Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceVoteImpl.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceVoteImpl.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/services/ServiceVoteImpl.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -22,13 +22,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.business.PollenBusinessException; import org.chorem.pollen.business.PollenContext; import org.chorem.pollen.business.converters.DataPollAccountConverter; import org.chorem.pollen.business.converters.DataVoteConverter; import org.chorem.pollen.business.dto.PollAccountDTO; import org.chorem.pollen.business.dto.PollDTO; import org.chorem.pollen.business.dto.VoteDTO; +import org.chorem.pollen.business.persistence.Poll; import org.chorem.pollen.business.persistence.PollAccount; import org.chorem.pollen.business.persistence.PollAccountDAO; import org.chorem.pollen.business.persistence.PollenModelDAOHelper; @@ -36,6 +36,9 @@ import org.chorem.pollen.business.persistence.VoteDAO; import org.chorem.pollen.business.utils.ContextUtil; import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.framework.TopiaQuery; +import org.nuiton.topia.persistence.TopiaEntity; +import static org.nuiton.i18n.I18n.n_; /** * Implémentation du service de gestion des votes. @@ -46,7 +49,6 @@ public class ServiceVoteImpl implements ServiceVote { private TopiaContext rootContext; - private VoteDAO voteDAO = null; private DataVoteConverter converter = new DataVoteConverter(); /** log. */ @@ -77,7 +79,8 @@ // .getId()); if (pollAccountEntity == null) { log.debug("Nouveau compte associé au vote"); - pollAccountEntity = pollAccountDAO.create(ContextUtil.createPollenUrlId()); + pollAccountEntity = pollAccountDAO.create( + PollenContext.createPollenUrlId()); // EVO #108 : Migration to ToPIA 2.3, the entity must be // commited because an other findBy is called in the // converter (wtf ?! :/). This behavior doesn't work @@ -107,7 +110,7 @@ voteDTO.setPollAccountId(null); } - voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); + VoteDAO voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); Vote voteEntity = voteDAO.create(); converter.setTransaction(transaction); @@ -139,7 +142,7 @@ try { transaction = rootContext.beginTransaction(); - voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); + VoteDAO voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); Vote voteEntity = voteDAO.findByTopiaId(voteDTO.getId()); converter.setTransaction(transaction); converter.populateVoteEntity(voteDTO, voteEntity); @@ -166,7 +169,7 @@ try { transaction = rootContext.beginTransaction(); - voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); + VoteDAO voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); Vote voteEntity = voteDAO.findByTopiaId(voteId); voteEntity.delete(); @@ -191,33 +194,39 @@ TopiaContext transaction = null; List<VoteDTO> results = new ArrayList<VoteDTO>(); try { + if (log.isInfoEnabled()) { + log.info("getVotesByPoll : pollUId = " + poll.getPollId() + + " _ startIndex = " + startIndex + + " _ endIndex = " + endIndex); + } + // No need to load votes for an anonymous poll if (poll.isAnonymous()) { return results; } - // FIXME-FD20100309 : change model to suppress link from poll to vote + // FIXME-FD20100309 : change dto to suppress link from poll to vote // It's not necessary to have votes when retrieving the poll, this // method do this job only when it's needed + transaction = rootContext.beginTransaction(); - if (log.isDebugEnabled()) { - log.debug("Load votes for poll with uid = " + poll.getPollId()); - log.debug("LIMIT : startIndex = " + startIndex + " _ " + - "endIndex = " + endIndex); - } +// List<Vote> votes = transaction.find( +// "FROM " + Vote.class.getName() + +// " WHERE poll.pollId = :pollUId" + +// " ORDER BY topiaCreateDate", +// startIndex, endIndex, +// "pollUId", poll.getPollId()); - transaction = rootContext.beginTransaction(); - - // FIXME : refactor this to use TopiaQuery from ToPIA 2.3 + VoteDAO voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); // Order the results by creation date (the last vote done will be // at the end of the list) - List<Vote> votes = transaction.find( - "FROM " + Vote.class.getName() + - " WHERE poll.pollId = :pollUId" + - " ORDER BY topiaCreateDate", - startIndex, endIndex, - "pollUId", poll.getPollId()); + TopiaQuery query = voteDAO.createQuery(). + add(Vote.POLL + "." + Poll.POLL_ID, poll.getPollId()). + addOrder(TopiaEntity.TOPIA_CREATE_DATE). + setLimit(startIndex, endIndex); + List<Vote> votes = voteDAO.findAllByQuery(query); + if (log.isDebugEnabled()) { log.debug("Nb votes found : " + votes.size()); } @@ -225,11 +234,11 @@ results = converter.createVoteDTOs(votes); } catch (Exception eee) { - ContextUtil.doCatch(eee, transaction, - "Unable to load votes from poll with uid = " + + PollenContext.doCatch(transaction, eee, + n_("pollen.error.serviceVote.getVotesByPoll"), poll.getPollId()); } finally { - ContextUtil.doFinally(transaction); + PollenContext.doFinally(transaction); } return results; } @@ -239,30 +248,39 @@ TopiaContext transaction = null; boolean result = false; try { + if (log.isInfoEnabled()) { + log.info("hasAlreadyVoted : votingId = " + votingId + + " _ pollUId = " + poll.getPollId()); + } transaction = rootContext.beginTransaction(); + +// List<Long> tmp = transaction.find( +// "SELECT COUNT(*)" + +// " FROM " + Vote.class.getName() + +// " WHERE poll.pollId = :pollUId" + +// " AND pollAccount.votingId = :votingId", +// "pollUId", poll.getPollId(), +// "votingId", votingId); - // Test using a count(*) on votes - List<Long> tmp = transaction.find( - "SELECT COUNT(*)" + - " FROM " + Vote.class.getName() + - " WHERE poll.pollId = :pollUId" + - " AND pollAccount.votingId = :votingId", - "pollUId", poll.getPollId(), - "votingId", votingId); + // Test using a count on votes + TopiaQuery query = new TopiaQuery(Vote.class). + add(Vote.POLL + "." + Poll.POLL_ID, poll.getPollId()). + add(Vote.POLL_ACCOUNT + "." + PollAccount.VOTING_ID, + votingId); - int count = tmp.get(0).intValue(); + int count = query.executeCount(transaction); // If the count is greater than 0, there is an existing votingId // who has already voted for the poll result = count > 0; } catch (Exception eee) { - ContextUtil.doCatch(eee, transaction, - "Unable test vote existing for account with votingId = " + - votingId + " and poll with uid = " + poll.getPollId()); + PollenContext.doCatch(transaction, eee, + n_("pollen.error.serviceVote.hasAlreadyVoted"), + votingId, poll.getPollId()); } finally { - ContextUtil.doFinally(transaction); + PollenContext.doFinally(transaction); } return result; } @@ -275,7 +293,7 @@ try { transaction = rootContext.beginTransaction(); - voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); + VoteDAO voteDAO = PollenModelDAOHelper.getVoteDAO(transaction); if (properties == null) { voteEntities = voteDAO.findAll(); Modified: trunk/pollen-business/src/main/java/org/chorem/pollen/business/utils/ContextUtil.java =================================================================== --- trunk/pollen-business/src/main/java/org/chorem/pollen/business/utils/ContextUtil.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/java/org/chorem/pollen/business/utils/ContextUtil.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -353,7 +353,7 @@ } // PollenBusinessException must be managed (catch and throw) when needed // if (! (eee instanceof PollenBusinessException)) { - throw new PollenException(message, eee); + throw new PollenException(eee, message); // } } Modified: trunk/pollen-business/src/main/resources/i18n/pollen-business-en_GB.properties =================================================================== --- trunk/pollen-business/src/main/resources/i18n/pollen-business-en_GB.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/resources/i18n/pollen-business-en_GB.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -12,8 +12,13 @@ pollen.error.servicePoll.deleteComment= pollen.error.servicePoll.deletePoll= pollen.error.servicePoll.getAllPolls= +pollen.error.servicePoll.getComments= pollen.error.servicePoll.getPoll= +pollen.error.servicePoll.getRestrictedAccount=Unable to retrieve restricted account with accountUId \= %1$s and poll with uid \= %2$s pollen.error.servicePoll.updatePoll= pollen.error.serviceResults.importPoll= pollen.error.serviceUser.createDefaultAdmin= +pollen.error.serviceVote.getVotesByPoll=Unable to load votes from poll with uid \= %1$s +pollen.error.serviceVote.hasAlreadyVoted=Unable test vote existing for account with votingId \= %1$s and poll with uid \= %2$s pollen.exception.load_configuration= +pollen.exception.poll_not_exist=No such poll exists. Please make sure that you are using the correct link and copy it completely into your browser's address field. Modified: trunk/pollen-business/src/main/resources/i18n/pollen-business-fr_FR.properties =================================================================== --- trunk/pollen-business/src/main/resources/i18n/pollen-business-fr_FR.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/resources/i18n/pollen-business-fr_FR.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -9,10 +9,15 @@ pollen.error.servicePoll.addComment=Impossible d'ajouter un nouveau commentaire cr\u00E9\u00E9 par %1$s pour le sondage %2$s (%3$s) pollen.error.servicePoll.createPoll=Impossible d'enregistrer le sondage %1$s cr\u00E9\u00E9 par %2$s pollen.error.servicePoll.deleteComment=Impossible de supprimer le commentaire ayant pour identifiant "%1$s", appartenenant au sondage %2$s (%3$s) -pollen.error.servicePoll.deletePoll=Impossible de supprimer le sondage ayant pour identifiant "%1$s" +pollen.error.servicePoll.deletePoll=Impossible de supprimer le sondage ayant pou identifiant "%1$s" pollen.error.servicePoll.getAllPolls= +pollen.error.servicePoll.getComments= pollen.error.servicePoll.getPoll= +pollen.error.servicePoll.getRestrictedAccount=Unable to retrieve restricted account with accountUId \= %1$s and poll with uid \= %2$s pollen.error.servicePoll.updatePoll=Impossible de mettre \u00E0 jour le sondage %1$s (%2$s) pollen.error.serviceResults.importPoll= pollen.error.serviceUser.createDefaultAdmin=Impossible de cr\u00E9er l'administrateur par d\u00E9faut \: %1$s (%2$s) +pollen.error.serviceVote.getVotesByPoll= +pollen.error.serviceVote.hasAlreadyVoted= pollen.exception.load_configuration=La configuration n'a pas \u00E9t\u00E9 charg\u00E9e correctement \! Veuillez v\u00E9rifier le d\u00E9marrage de l'application. +pollen.exception.poll_not_exist=Il n'y a pas de sondage \u00E0 cette adresse. Veuillez verifier que vous utilisez le lien correcte et copiez-le compl\u00E8tement dans le champ d'adresse de votre navigateur. Modified: trunk/pollen-business/src/main/resources/pollen.properties =================================================================== --- trunk/pollen-business/src/main/resources/pollen.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/main/resources/pollen.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -49,7 +49,7 @@ pollen.emails.directory=.pollen/emails ## Nombre de votes a afficher par page -pollen.ui.nbVotesPerPage=50 +pollen.ui.nbVotesPerPage=25 ## Adresse du site (utilis\u00C3\u00A9e pour les emails de rappel) siteUrl= Copied: trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/SendMailTest.java (from rev 2943, trunk/pollen-ui/src/test/java/org/chorem/pollen/ui/utils/SendMailTest.java) =================================================================== --- trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/SendMailTest.java (rev 0) +++ trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/SendMailTest.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -0,0 +1,103 @@ +/* *##% Pollen + * Copyright (C) 2010 CodeLutin + * + * 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/>. ##%*/ + +package org.chorem.pollen.business.services; + +import org.chorem.pollen.business.services.SendMail; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.chorem.pollen.business.PollenContext; +import org.chorem.pollen.business.PollenProperty; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.nuiton.util.ApplicationConfig; + +/** + * Class for send mail storage class. + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ + * By : $Author$ + */ +@Ignore +public class SendMailTest { + + protected static SendMail sendMail; + + @BeforeClass + public static void init() throws InterruptedException { + + ApplicationConfig config = new ApplicationConfig(); + config.setOption(PollenProperty.EMAIL_DIR.getKey(), "target" + File.separator + "massmail"); + config.setOption(PollenProperty.EMAIL_HOST.getKey(), "smtp"); + config.setOption(PollenProperty.EMAIL_PORT.getKey(), "25"); + config.setOption(PollenProperty.EMAIL_FROM.getKey(), "pollenreminder@codelutin.com"); + + PollenContext.loadConfiguration(config); + + sendMail = new SendMail(); + sendMail.start(); + Thread.sleep(3000); + } + + /** + * Test to add mail and send mail. + * + * WARNING : This test really send mail, don't set it automatic. + * + * @throws IOException + * @throws InterruptedException + */ + @Test + public void testAddMail() throws IOException, InterruptedException { + List<Map<String, String>> mailList = new ArrayList<Map<String,String>>(); + + Map<String, String> mailMap = new HashMap<String, String>(); + mailMap.put("receiver", "chatellier+test@codelutin.com"); + mailMap.put("subject", "Test 18:00"); + mailMap.put("body", "Test body"); + + Map<String, String> mailMap2 = new HashMap<String, String>(); + mailMap2.put("receiver", "chorlet+test@codelutin.com"); + mailMap2.put("subject", "CR, CR CR !!! 18:00"); + mailMap2.put("body", "Des cr, encore des \"CRs\" !!!"); + + mailList.add(mailMap); + mailList.add(mailMap2); + + sendMail.prepareMails("test", mailList); + + String emailDir = PollenProperty.EMAIL_DIR.getValue(); + + Assert.assertTrue(new File(emailDir, "test.mail").exists()); + Assert.assertTrue(new File(emailDir, "test.index").exists()); + sendMail.wakeUp(); + + // TODO , en 5 secondes, il aura le temps d'envoyer 2 mails ? + Thread.sleep(5000); + Assert.assertFalse(new File(emailDir, "test.mail").exists()); + Assert.assertFalse(new File(emailDir, "test.index").exists()); + } +} Property changes on: trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/SendMailTest.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL" Added: svn:mergeinfo + Modified: trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/ServicePollImplTest.java =================================================================== --- trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/ServicePollImplTest.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/test/java/org/chorem/pollen/business/services/ServicePollImplTest.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -116,7 +116,7 @@ choice3.setName("choice3"); choices.add(choice3); - dto.setChoiceDTOs(choices); + dto.setChoices(choices); final String result = instance.createPoll(dto); if (log.isDebugEnabled()) { @@ -214,24 +214,24 @@ /** * Test of findPollsByName method, of class ServicePollImpl. */ - @Test - public void testFindPollsByName() throws Exception { - TestManager.start("testFindPollsByName"); - instance = new ServicePollImpl(); +// @Test +// public void testFindPollsByName() throws Exception { +// TestManager.start("testFindPollsByName"); +// instance = new ServicePollImpl(); +// +// PollDTO dto = instance.getNewPoll(); +// dto.setDescription("Test_findPollsByName"); +// dto.setCreatorId("erwan"); +// dto.setAnonymous(false); +// dto.setPollType(PollType.FREE); +// dto.setChoiceType(ChoiceType.TEXT); +// dto.setVoteCounting(VoteCountingType.NORMAL); +// dto.setTitle("Test_findPollsByName"); +// String pollId = instance.createPoll(dto); +// List<PollDTO> result = instance.findPollsByName("Test_findPollsByName"); +// assertEquals(result.size(), 1); +// } - PollDTO dto = instance.getNewPoll(); - dto.setDescription("Test_findPollsByName"); - dto.setCreatorId("erwan"); - dto.setAnonymous(false); - dto.setPollType(PollType.FREE); - dto.setChoiceType(ChoiceType.TEXT); - dto.setVoteCounting(VoteCountingType.NORMAL); - dto.setTitle("Test_findPollsByName"); - String pollId = instance.createPoll(dto); - List<PollDTO> result = instance.findPollsByName("Test_findPollsByName"); - assertEquals(result.size(), 1); - } - /** * Test of findPollsByUser method, of class ServicePollImpl. */ @@ -474,4 +474,28 @@ test.execute(); } + + /** + * Test of getRestrictedAccount method, of class ServicePollImpl. + */ + //@Test + public void testGetRestrictedAccount() throws IOException { + TestManager.start("testGetRestrictedAccount"); + instance = new ServicePollImpl(); + + /** PREPARE DATA **/ + PollDTO poll = instance.getNewPoll(); + poll.setTitle("restrictedAccount"); + poll.setPollType(PollType.RESTRICTED); + poll.setChoiceType(ChoiceType.TEXT); + poll.setVoteCounting(VoteCountingType.NORMAL); + String id = instance.createPoll(poll); + poll.setId(id); + + PollAccountDTO account = new PollAccountDTO(); + account.setVotingId("toto"); + + // TODO + + } } Modified: trunk/pollen-business/src/test/resources/pollen.properties =================================================================== --- trunk/pollen-business/src/test/resources/pollen.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-business/src/test/resources/pollen.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,4 +1,4 @@ -# Configuration de la base de données +# Configuration de la base de donn\u00C3\u00A9es hibernate.hbm2ddl.auto=update hibernate.show_sql=false hibernate.dialect=org.hibernate.dialect.H2Dialect @@ -7,9 +7,11 @@ hibernate.connection.driver_class=org.h2.Driver hibernate.connection.url=jdbc:h2:file:target/test-base/pollen -# Initialisation de la base de données +# Initialisation de la base de donn\u00C3\u00A9es choiceType=DATE,IMAGE,TEXT pollType=RESTRICTED,FREE,GROUP voteCounting=NORMAL,PERCENTAGE,CONDORCET adminLogin=admin -adminPassword=admin \ No newline at end of file +adminPassword=admin + +pollen.emails.directory=target/test-emails \ No newline at end of file Modified: trunk/pollen-ui/pom.xml =================================================================== --- trunk/pollen-ui/pom.xml 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/pom.xml 2010-03-19 15:05:04 UTC (rev 2951) @@ -132,7 +132,6 @@ <goal>tapestry-bundle</goal> </goals> </execution> - </executions> </plugin> Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Pager.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Pager.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/components/Pager.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,13 +1,13 @@ package org.chorem.pollen.ui.components; +import org.apache.tapestry5.Asset; import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.ComponentResources; -import org.apache.tapestry5.EventConstants; import org.apache.tapestry5.Link; import org.apache.tapestry5.MarkupWriter; -import org.apache.tapestry5.annotations.Log; import org.apache.tapestry5.annotations.Parameter; +import org.apache.tapestry5.annotations.Path; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.slf4j.Logger; @@ -42,11 +42,21 @@ private int currentPage; /** - * Number of rows to show per page. + * Number of rows to show per page, the page which contains the pager have + * to manage this property (using @Persist for exemple) to ensure that + * the pager will done its work correctly. */ @Parameter(required = true) private int nbRowsPerPage; + /** + * Number of rows for each range. Static value different from variable + * nbRowsPerPage. This parameter is used to show some links to change + * nbRowsPerPage. + */ + @Parameter("25") + private int range; + @Parameter(defaultPrefix = BindingConstants.LITERAL) private String noPagerText; @@ -59,6 +69,26 @@ @Inject private Logger log; + @Inject + @Path("context:img/1leftarrow.png") + private Asset leftarrow1; + + @Inject + @Path("context:img/2leftarrow.png") + private Asset leftarrow2; + + @Inject + @Path("context:img/1rightarrow.png") + private Asset rightarrow1; + + @Inject + @Path("context:img/2rightarrow.png") + private Asset rightarrow2; + + private static final String ACTION_CHANGE_PAGE = "changePage"; + + private static final String ACTION_CHANGE_NB_ROWS = "changeNbRows"; + void beginRender(MarkupWriter writer) { if (log.isDebugEnabled()) { log.debug("pager from : " + getFirstValue() + " to " + getLastValue()); @@ -77,10 +107,12 @@ if (hasPrevious()) { int previousPage = currentPage - 1; if (previousPage != getFirstPage()) { - writeLink(writer, getFirstPage(), "<<", "p-pager-first"); + writeChangePageLink(writer, getFirstPage(), leftarrow2, + "p-pager-first"); writer.write(" "); } - writeLink(writer, previousPage, "<", "p-pager-previous"); + writeChangePageLink(writer, previousPage, leftarrow1, + "p-pager-previous"); writer.write(" "); } // Text display for current page @@ -88,19 +120,32 @@ messages.format("rows-title", getFirstValue(), getLastValue(), nbTotalRows)); writer.element("strong"); - writer.write(messages.format("page", currentPage)); + writer.write(messages.format("page", currentPage, getLastPage())); writer.end(); writer.end(); if (hasNext()) { int nextPage = currentPage + 1; writer.write(" "); - writeLink(writer, nextPage, ">", "p-pager-next"); + writeChangePageLink(writer, nextPage, rightarrow1, "p-pager-next"); if (nextPage != getLastPage()) { writer.write(" "); - writeLink(writer, getLastPage(), ">>", "p-pager-last"); + writeChangePageLink(writer, getLastPage(), + rightarrow2, "p-pager-last"); } } + + int doubleNbPerPage = range * 2; + int quadrupleNbPerPage = range * 4; + writer.element("div", "class", "p-pager-nbrows"); + writer.write(messages.format("showPerPage")); + writer.write(" "); + writeChangeNbRowsLink(writer, range); + writer.write(", "); + writeChangeNbRowsLink(writer, doubleNbPerPage); + writer.write(", "); + writeChangeNbRowsLink(writer, quadrupleNbPerPage); + writer.end(); } writer.end(); } @@ -110,25 +155,43 @@ } /** - * Use an action event to change the current page. The link refresh the + * Use an changePage event to change the current page. The link refresh the * entire page, no zone is managed yet. * - * @param writer used to write a element + * @param writer used to write an element * @param index new page to change (argument of onAction method) - * @param text to write inside the a tag + * @param asset for action * @param style of the css (class) for the a tag */ - protected void writeLink(MarkupWriter writer, int index, - String text, String style) { - Link link = resources.createEventLink(EventConstants.ACTION, + protected void writeChangePageLink(MarkupWriter writer, int index, + Asset asset, String style) { + Link link = resources.createEventLink(ACTION_CHANGE_PAGE, new Object[] {index}); String title = messages.format("go-to", index); writer.element("a", "href", link, "class", style, "title", title); - writer.write(text); + writer.element("img", "src", asset, + "alt", style); writer.end(); + writer.end(); } /** + * Use an changeNbRows event to change the number of rows per page. The link + * refresh the entire page, no zone is managed yet. + * + * @param writer used to write an element + * @param nbRows to show and needed for the link + */ + protected void writeChangeNbRowsLink(MarkupWriter writer, int nbRows) { + Link link = resources.createEventLink(ACTION_CHANGE_NB_ROWS, + new Object[] {nbRows}); + String title = messages.format("change-nbrows", nbRows); + writer.element("a", "href", link, "title", title); + writer.write(String.valueOf(nbRows)); + writer.end(); + } + + /** * Get the start index of the range shown. * * @return the start index for elements to show @@ -190,8 +253,20 @@ * * @param newPage to set */ - void onAction(int newPage) { + void onChangePage(int newPage) { currentPage = newPage; } + /** + * Action event for changing nb rows. The nbRowsPerPage is changed to + * {@code nbRows}. + * + * @param nbRows to set + */ + void onChangeNbRows(int nbRows) { + nbRowsPerPage = nbRows; + // Reset to first page to avoid strange text like (Page 8/2) + currentPage = getFirstPage(); + } + } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollHelper.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollHelper.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollHelper.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -101,7 +101,7 @@ public static List<ChoiceDTO> getTextChoices(PollDTO oldPoll) { List<ChoiceDTO> choices = new ArrayList<ChoiceDTO>(); if (oldPoll.getChoiceType() == ChoiceType.TEXT) { - for (ChoiceDTO oldChoice : oldPoll.getChoiceDTOs()) { + for (ChoiceDTO oldChoice : oldPoll.getChoices()) { ChoiceDTO choice = new ChoiceDTO(); choice.setName(oldChoice.getName()); choice.setDescription(oldChoice.getDescription()); @@ -120,7 +120,7 @@ public static List<DateChoiceUIO> getDateChoices(PollDTO oldPoll) { List<DateChoiceUIO> choices = new ArrayList<DateChoiceUIO>(); if (oldPoll.getChoiceType() == ChoiceType.DATE) { - for (ChoiceDTO oldChoice : oldPoll.getChoiceDTOs()) { + for (ChoiceDTO oldChoice : oldPoll.getChoices()) { DateChoiceUIO choice = new DateChoiceUIO(); choice.setName(oldChoice.getName()); choice.setDescription(oldChoice.getDescription()); Added: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollUri.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollUri.java (rev 0) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollUri.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -0,0 +1,49 @@ + +package org.chorem.pollen.ui.data; + +import org.apache.tapestry5.ValueEncoder; + +/** + * PollUri + * + * Created: 15 mars 2010 + * + * @author fdesbois + * @version $Revision$ + * + * Mise a jour: $Date$ + * par : $Author$ + */ +public class PollUri { + + private static final String SEPARATOR = ":"; + + protected String pollUId; + + protected String accountUId; + + public PollUri(String uri) { + String[] tab = uri.split(SEPARATOR); + pollUId = tab[0]; + if (tab.length == 2) { + accountUId = tab[1]; + } + } + + public String getAccountUId() { + return accountUId; + } + + public String getPollUId() { + return pollUId; + } + + public String getUri() { + String uri = getPollUId(); + if (getAccountUId() != null) { + uri += SEPARATOR + getAccountUId(); + } + return uri; + } + +} Property changes on: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/data/PollUri.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL" Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ConfirmPoll.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ConfirmPoll.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ConfirmPoll.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -114,7 +114,7 @@ * @return la page de validation de cloture */ private Object closePoll() { - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + for (ChoiceDTO choice : poll.getChoices()) { choice.setValidate(true); } Date now = new Date(); Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/ImageDisplay.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -106,7 +106,7 @@ */ void onActivate() { choice = new ChoiceDTO(); - for (ChoiceDTO c : poll.getChoiceDTOs()) { + for (ChoiceDTO c : poll.getChoices()) { if (choiceId.equals(c.getId())) { choice = c; } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -48,6 +48,7 @@ import org.apache.tapestry5.ioc.services.PropertyAccess; import org.apache.tapestry5.json.JSONObject; import org.apache.tapestry5.upload.services.UploadSymbols; +import org.chorem.pollen.business.PollenContext; import org.chorem.pollen.business.PollenProperty; import org.chorem.pollen.business.business.PreventRuleManager; import org.chorem.pollen.business.dto.ChoiceDTO; @@ -74,7 +75,6 @@ import org.chorem.pollen.ui.data.uio.ImageChoiceUIO; import org.chorem.pollen.ui.utils.FeedUtil; import org.chorem.pollen.ui.utils.ImageUtil; -import org.chorem.pollen.ui.utils.SendMail; import org.chorem.pollen.ui.utils.UnitConverter; import org.slf4j.Logger; @@ -315,9 +315,6 @@ @Inject private ServiceList serviceList; -// @Inject -// private SendMail sendMailService; - /** * Méthode appelée lorsqu'on souhaite accéder à l'étape suivante de la * création de sondage. @@ -700,7 +697,7 @@ for (ChoiceDTO choice : choices) { if (choice.getName() != null) { choice.setValidate(true); - poll.getChoiceDTOs().add(choice); + poll.getChoices().add(choice); } } } else if (isDateChoices()) { @@ -708,7 +705,7 @@ if (choice.getDate() != null) { choice.setValidate(true); choice.setName(String.valueOf(choice.getDate().getTime())); - poll.getChoiceDTOs().add(choice); + poll.getChoices().add(choice); } } } else if (isImgChoices()) { @@ -719,7 +716,7 @@ "IMAGE")) { imgChoice.setValidate(true); imgChoice.setName(imgChoice.getImg().getFileName().replace(' ', '_')); - poll.getChoiceDTOs().add(imgChoice); + poll.getChoices().add(imgChoice); } else { return false; } @@ -737,8 +734,8 @@ if (poll.isContinuousResults()) { poll.setPublicResults(true); } - if (poll.getMaxChoiceNb() < 1 || poll.getMaxChoiceNb() > poll.getChoiceDTOs().size()) { - poll.setMaxChoiceNb(poll.getChoiceDTOs().size()); + if (poll.getMaxChoiceNb() < 1 || poll.getMaxChoiceNb() > poll.getChoices().size()) { + poll.setMaxChoiceNb(poll.getChoices().size()); } return true; @@ -854,14 +851,14 @@ } // send mail preparation -// try { -// sendMailService.prepareMails(poll.getId(), mailList); -// sendMailService.wakeUp(); -// } catch (IOException ex) { -// if (log.isErrorEnabled()) { -// log.error("Can't prepare send mail on disk, mail won't be send !!!", ex); -// } -// } + try { + PollenContext.getSendMail().prepareMails(poll.getId(), mailList); + PollenContext.getSendMail().wakeUp(); + } catch (IOException ex) { + if (log.isErrorEnabled()) { + log.error("Can't prepare send mail on disk, mail won't be send !!!", ex); + } + } } } Deleted: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java.orig =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java.orig 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollCreation.java.orig 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,1252 +0,0 @@ -/* *##% Pollen - * Copyright (C) 2009 CodeLutin - * - * 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/>. ##%*/ - -package org.chorem.pollen.ui.pages.poll; - -import java.io.File; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.lang.StringUtils; -import org.apache.tapestry5.BindingConstants; -import org.apache.tapestry5.ComponentResources; -import org.apache.tapestry5.Link; -import org.apache.tapestry5.ValidationException; -import org.apache.tapestry5.annotations.Component; -import org.apache.tapestry5.annotations.IncludeStylesheet; -import org.apache.tapestry5.annotations.InjectComponent; -import org.apache.tapestry5.annotations.InjectPage; -import org.apache.tapestry5.annotations.Log; -import org.apache.tapestry5.annotations.Parameter; -import org.apache.tapestry5.annotations.Persist; -import org.apache.tapestry5.annotations.Property; -import org.apache.tapestry5.annotations.SessionState; -import org.apache.tapestry5.corelib.components.Form; -import org.apache.tapestry5.corelib.components.Select; -import org.apache.tapestry5.corelib.components.Zone; -import org.apache.tapestry5.ioc.Messages; -import org.apache.tapestry5.ioc.annotations.Inject; -import org.apache.tapestry5.ioc.annotations.Symbol; -import org.apache.tapestry5.ioc.services.PropertyAccess; -import org.apache.tapestry5.json.JSONObject; -import org.apache.tapestry5.upload.services.UploadSymbols; -import org.chorem.pollen.business.PollenProperty; -import org.chorem.pollen.business.business.PreventRuleManager; -import org.chorem.pollen.business.dto.ChoiceDTO; -import org.chorem.pollen.business.dto.PersonListDTO; -import org.chorem.pollen.business.dto.PollAccountDTO; -import org.chorem.pollen.business.dto.PollDTO; -import org.chorem.pollen.business.dto.PreventRuleDTO; -import org.chorem.pollen.business.dto.UserDTO; -import org.chorem.pollen.business.dto.VotingListDTO; -import org.chorem.pollen.business.services.ServiceList; -import org.chorem.pollen.business.services.ServicePoll; -import org.chorem.pollen.business.services.ServicePollAccount; -import org.chorem.pollen.common.ChoiceType; -import org.chorem.pollen.common.PollType; -import org.chorem.pollen.common.VoteCountingType; -import org.chorem.pollen.ui.base.ContextLink; -import org.chorem.pollen.ui.components.FeedBack; -import org.chorem.pollen.ui.components.ImageContextLink; -import org.chorem.pollen.ui.data.GenericSelectModel; -import org.chorem.pollen.ui.data.AddressBarItem; -import org.chorem.pollen.ui.data.PollHelper; -import org.chorem.pollen.ui.data.PollStep; -import org.chorem.pollen.ui.data.uio.DateChoiceUIO; -import org.chorem.pollen.ui.data.uio.ImageChoiceUIO; -import org.chorem.pollen.ui.utils.FeedUtil; -import org.chorem.pollen.ui.utils.ImageUtil; -import org.chorem.pollen.ui.utils.UnitConverter; -import org.slf4j.Logger; - -/** - * Classe de la page de création d'un sondage. - * - * @author kmorin - * @author rannou - * @version $Id: PollCreation.java 2893 2010-03-02 20:14:34Z fdesbois $ - */ -@IncludeStylesheet("context:css/pollCreation.css") -public class PollCreation { - - @Inject - private Logger log; - - /** Étape courante du formulaire */ - @Persist - private PollStep step; - - /** - * Objet de session représentant l'utilisateur identifié. - */ - @SessionState - private UserDTO user; - @Property - private boolean userExists; - - /** - * Objet de session représentant l'url du site. - */ - @SessionState - @Property - private String siteURL; - - /** Date de début du sondage (utilisée pour la validation). */ - private Date beginDateValidation; - - /** Date de début d'ajout des choix (utilisée pour la validation). */ - private Date beginChoiceDateValidation; - - /** Mixin de selection de liste de favoris */ - @SuppressWarnings("unused") - private Select listSelect; - - @InjectComponent - private Zone pollCreationZone; - - /** - * Sondage créé par le formulaire - */ - @Property - @Persist - private PollDTO poll; - - /** - * Sondage copié pour créer un nouveau sondage - */ - @Persist - private PollDTO oldPoll; - - /** - * Sondage copié existe. - */ - private boolean oldPollExists = false; - - /** - * variable utilisée pour déterminer si le bouton cliqué mène à l'étape - * suivante - */ - private boolean noStepSubmitSelected = false; - - /** - * variable utilisée pour déterminer si le bouton d'ajout de choix a été - * cliqué - */ - @Persist - private boolean addChoiceSelected; - - /** - * variable utilisée pour déterminer le groupe à supprimer - */ - private int deleteGroupId = -1; - - /** - * variable utilisée pour déterminer s'il y a eu une exception lors de - * l'upload des images - */ - @Persist - private boolean uploadExceptionCatched; - - /** variable utilisée pour l'affichage de la choiceNbCheckBox */ - @Property - @Persist - private boolean choiceNbCheckBox; - - /** variable utilisée pour l'affichage de la notificationCheckBox */ - @Property - @Persist - private boolean notificationCheckBox; - - /** variable utilisée pour l'affichage de la reminderCheckBox */ - @Property - @Persist - private boolean reminderCheckBox; - - /** Règle de notification de vote */ - @Property - @Persist - private PreventRuleDTO notificationPreventRule; - - /** Règle de notification pour le rappel des votants */ - @Property - @Persist - private PreventRuleDTO reminderPreventRule; - - /** - * Groupes de votants à créer - */ - @Property - @Persist - private List<VotingListDTO> votingLists; - - /** - * Objet utilisé dans la boucle de parcours des listes de votants - */ - @Property - private VotingListDTO votingList; - - /** - * Objet utilisé dans la boucle de parcours de la liste de votants courante - */ - @SuppressWarnings("unused") - @Property - private PollAccountDTO votingListPerson; - - /** - * Nombre de votants affichés initialement - */ - @Property - private int nbVotingListPersons = 5; - - /** - * Liste modifiée actuellement - */ - @Persist - private int currentList; - - /** - * Listes de favoris de l'utilisateur. - */ - @Property - @Persist - private GenericSelectModel<PersonListDTO> personLists; - - /** - * Liste de favoris sélectionnée. - */ - @Property - private PersonListDTO personList; - - /** - * Nombre de choix affichés initialement - */ - @Property - private int nbChoices = 5; - - /** - * Objet utilisé dans la boucle de parcours de la liste des choix - */ - @SuppressWarnings("unused") - @Property - private ChoiceDTO choice; - - /** - * Objet utilisé dans la boucle de parcours de la liste des choix - */ - @SuppressWarnings("unused") - @Property - private DateChoiceUIO dateTypeChoice; - - /** - * Objet utilisé dans la boucle de parcours de la liste des choix - */ - @SuppressWarnings("unused") - @Property - private ImageChoiceUIO imgTypeChoice; - - /** - * Liste des choix à créer - */ - @Property - @Persist - private List<ChoiceDTO> choices; - - /** - * Liste des choix à créer - */ - @Property - @Persist - private List<DateChoiceUIO> dateTypeChoices; - - /** - * Liste des choix à créer - */ - @Property - @Persist - private List<ImageChoiceUIO> imgTypeChoices; - - /** - * Contexte pour l'upload des images (parametres definis dans .tml) - */ - @InjectComponent - private ImageContextLink imgContext; - - /** - * Contexte pour la gestion du flux RSS - */ - @InjectComponent - private ContextLink feedContext; - - /** - * Formulaire de création de sondage - */ - @Component(id = "pollCreationForm") - private Form pollCreationForm; - @Component(id = "choicesCreationForm") - private Form choicesCreationForm; - - @InjectPage - private CreationValidation creationValidation; - - @Parameter(defaultPrefix = BindingConstants.MESSAGE, value = "title") - @Property - private String title; - - @SuppressWarnings("unused") - @Property - private AddressBarItem[] address; - - @Inject - private PropertyAccess _propertyAccess; - - @Inject - private ComponentResources resources; - - /** Affichage des messages pour l'utilisateur */ - @Component(id = "feedback") - private FeedBack feedback; - - /** Tailles maximales des fichiers uploadés */ - @Inject - @Symbol(UploadSymbols.FILESIZE_MAX) - private int fileSizeMax; - @Inject - @Symbol(UploadSymbols.REQUESTSIZE_MAX) - private int requestSizeMax; - - @Inject - private Messages messages; - - @Inject - private Logger logger; - - /** Injection des services */ - @Inject - private ServicePoll servicePoll; - @Inject - private ServicePollAccount servicePollAccount; - @Inject - private ServiceList serviceList; - - /** - * Méthode appelée lorsqu'on souhaite accéder à l'étape suivante de la - * création de sondage. - */ - @Log - Object onSuccessFromPollCreationForm() { - if (log.isDebugEnabled()) { - log.debug("Step : " + step); - } - switch (step) { - case POLL: - adaptStepPoll(); - step = PollStep.OPTIONS; - break; - case OPTIONS: - adaptStepOptions(); - if (isFreePoll()) { - step = PollStep.CHOICES; - } else { - step = PollStep.LISTS; - } - break; - case LISTS: - if (deleteGroupId >= 0) { - votingLists.remove(deleteGroupId); - } - if (!noStepSubmitSelected) { - step = PollStep.CHOICES; - } - break; - case CHOICES: - break; - default: - step = PollStep.POLL; - break; - } - // Cas particulier, autre formulaire pour les choix - if (step.equals(PollStep.CHOICES)) { - return choicesCreationForm; - } - return pollCreationForm; - } - - /** - * Méthode appelée que le formulaire soit valide ou non. Il est nécessaire - * de la redéfinir pour qu'en cas d'erreur de validation, la zone soit tout - * de même mise à jour pour afficher l'erreur. - */ - @Log - Object onSubmitFromPollCreationForm() { - return pollCreationForm; - } - - /** - * Méthode appelée lorsqu'on souhaite valider la création du sondage. - */ - Object onSuccessFromChoicesCreationForm() { - if (!addChoiceSelected) { - - // Préparation et création du sondage - if (!preparePoll()) { - return this; - } - createPoll(); - - creationValidation.setPoll(poll); - return creationValidation; - } - - return this; - } - - /** - * Méthode appelée lorsqu'on souhaite accéder à l'étape précédente de la - * création de sondage. - */ - Object onPrevious() { - switch (step) { - case OPTIONS: - step = PollStep.POLL; - break; - case LISTS: - step = PollStep.OPTIONS; - break; - case CHOICES: - if (isFreePoll()) { - step = PollStep.OPTIONS; - } else { - step = PollStep.LISTS; - } - break; - default: - step = PollStep.POLL; - break; - } - return pollCreationForm; // Pas de gestion du formulaire des choix car derniere etape - } - - /** - * Méthode appelée lors de la validation du formulaire. Validation du champs - * beginDate. - * - * @throws ValidationException - */ - void onValidateFromBeginDate(Date value) throws ValidationException { - beginDateValidation = value; - if (value != null && value.before(new Date())) { - throw new ValidationException(messages.get("beginDate-validate")); - } - } - - /** - * Méthode appelée lors de la validation du formulaire. Validation du champs - * endDate. - * - * @throws ValidationException - */ - void onValidateFromEndDate(Date value) throws ValidationException { - if (beginDateValidation == null) { - beginDateValidation = new Date(); - } - - if (value != null && value.before(beginDateValidation)) { - throw new ValidationException(messages.get("endDate-validate")); - } - } - - /** - * Méthode appelée lors de la validation du formulaire. Validation du champs - * beginChoiceDate. - * - * @throws ValidationException - */ - void onValidateFromBeginChoiceDate(Date value) throws ValidationException { - if (beginDateValidation == null) { - beginDateValidation = new Date(); - } - beginChoiceDateValidation = value; - if (value != null && value.after(beginDateValidation)) { - throw new ValidationException(messages - .get("beginChoiceDate-validate")); - } - } - /** - * Méthode appelée lors de la validation du formulaire. Validation du champs - * endChoiceDate. - * - * @throws ValidationException - */ - void onValidateFromEndChoiceDate(Date value) throws ValidationException { - if (beginChoiceDateValidation == null) { - beginChoiceDateValidation = new Date(); - } - - if (value != null && value.before(beginChoiceDateValidation)) { - throw new ValidationException(messages.get("endChoiceDate-validate")); - } - } - - /** - * Méthode appelée lors de la validation du formulaire. Validation des - * listes de votants. - * - * @throws ValidationException - */ - void onValidateFormFromPollCreationForm() throws ValidationException { - if (noStepSubmitSelected) { - return; - } - - // Validation des votants - if (step == PollStep.LISTS) { - int nbListEqual = 0; - int nbEqual = 0; - int nbNotNull = 0; - - // Repérage des doublons (listes) - for (VotingListDTO list1 : votingLists) { - for (VotingListDTO list2 : votingLists) { - if (list1.getName().equals(list2.getName())) { - nbListEqual++; - } - } - } - - if (nbListEqual > votingLists.size()) { - throw new ValidationException(messages.get("lists-validate")); - } - - // Repérage des doublons (votants) - for (VotingListDTO list1 : votingLists) { - int nbLocalNotNull = 0; - for (PollAccountDTO account1 : list1.getPollAccountDTOs()) { - if (account1.getVotingId() != null - && account1.getVotingId() != "") { - nbNotNull++; - nbLocalNotNull++; - - // comparaison avec les autres votants - for (VotingListDTO list2 : votingLists) { - for (PollAccountDTO account2 : list2 - .getPollAccountDTOs()) { - if (account2.getVotingId() != null - && account1.getVotingId() != "") { - if (account1.getVotingId().equals( - account2.getVotingId())) { - nbEqual++; - } - } - } - } - } - } - if (nbLocalNotNull == 0) { - throw new ValidationException(messages - .get("noList-validate")); - } - } - - if (logger.isDebugEnabled()) { - logger.debug("Votants (equal/notNull) : " + nbEqual + "/" - + nbNotNull); - } - if (nbEqual > nbNotNull) { - throw new ValidationException(messages.get("list-validate")); - } - } - } - - /** - * Méthode appelée lors de la validation du formulaire. Validation de la - * liste de choix. - * - * @throws ValidationException - */ - void onValidateFormFromChoicesCreationForm() throws ValidationException { - int nbEqual = 0; - int nbNotNull = 0; - - // Validation des choix - if (step == PollStep.CHOICES) { - - // Repérage des doublons (type Texte) - if (isTextChoices()) { - for (ChoiceDTO choice1 : choices) { - if (choice1.getName() != null) { - nbNotNull++; - for (ChoiceDTO choice2 : choices) { - if (choice2.getName() != null) { - if (choice1.getName().equals(choice2.getName())) { - nbEqual++; - } - } - } - } - } - // Repérage des doublons (type Date) - } else if (isDateChoices()) { - for (DateChoiceUIO choice1 : dateTypeChoices) { - if (choice1.getDate() != null) { - nbNotNull++; - for (DateChoiceUIO choice2 : dateTypeChoices) { - if (choice2.getDate() != null) { - if (choice1.getDate().equals(choice2.getDate())) { - nbEqual++; - } - } - } - } - } - // Repérage des doublons (type Image) - } else if (isImgChoices()) { - for (ImageChoiceUIO choice1 : imgTypeChoices) { - if (choice1.getImg() != null) { - nbNotNull++; - for (ImageChoiceUIO choice2 : imgTypeChoices) { - if (choice2.getImg() != null) { - if (choice1.getImg().getFileName().equals( - choice2.getImg().getFileName())) { - nbEqual++; - } - } - } - } - } - } - - if (nbNotNull == 0) { - throw new ValidationException(messages.get("noChoice-validate")); - } - if (nbEqual > nbNotNull) { - throw new ValidationException(messages.get("choice-validate")); - } - } - } - - /** Echec lors du téléchargement */ - Object onUploadException(FileUploadException e) { - logger.error(e.getMessage()); - String fSize = UnitConverter.getFormattedFileSize(fileSizeMax); - String rSize = UnitConverter.getFormattedFileSize(requestSizeMax); - feedback.addError(messages.format("uploadError", fSize, rSize)); - uploadExceptionCatched = true; - return this; - } - - /** - * Réinitialisation des options en fonction des autres options. - */ - private void adaptStepOptions() { - if (poll.isAnonymous()) { - poll.setAnonymousVoteAllowed(true); - } - if (poll.isContinuousResults()) { - poll.setPublicResults(true); - } - } - - /** - * Réinitialisation des listes de votants en fonction du type de sondage. - */ - @Log - private void adaptStepPoll() { - - // Sondage libre : suppression de toutes les listes - if (isFreePoll()) { - votingLists.clear(); - } - - // Sondage restreint : suppression des listes supplémentaires - else if (isRestrictedPoll() && votingLists.size() > 1) { - for (int i = 1; i < votingLists.size(); i++) { - votingLists.remove(i); - } - currentList = 0; - } - - // Sondage non libre : création d'une liste initiale - else if (votingLists.isEmpty()) { - votingList = new VotingListDTO(); - for (int i = 0; i < nbVotingListPersons; i++) { - votingList.getPollAccountDTOs().add(new PollAccountDTO()); - } - votingLists.add(votingList); - currentList = getVotingListIndex(); - } - - if (poll.getBeginDate() != null) { - poll.setEndChoiceDate(poll.getBeginDate()); - } - } - - /** - * Préparation du sondage. - */ - @Log - private boolean preparePoll() { - - // Ajout de l'identifiant du créateur - if (userExists) { - poll.setUserId(user.getId()); - } - - // Ajout des règles de notification au sondage - if (notificationCheckBox) { - poll.getPreventRuleDTOs().add(notificationPreventRule); - } - if (reminderCheckBox) { - poll.getPreventRuleDTOs().add(reminderPreventRule); - } - - // Ajout des groupes de votants au sondage - // après suppression des entrées vides - if (!isFreePoll()) { - for (VotingListDTO list : votingLists) { - Iterator<PollAccountDTO> it = list.getPollAccountDTOs() - .iterator(); - while (it.hasNext()) { - if (it.next().getVotingId() == null) { - it.remove(); - } - } - } - poll.setVotingListDTOs(votingLists); - } - - - // Ajout des choix au sondage - if (isTextChoices()) { - for (ChoiceDTO choice : choices) { - if (choice.getName() != null) { - choice.setValidate(true); - poll.getChoiceDTOs().add(choice); - } - } - } else if (isDateChoices()) { - for (DateChoiceUIO choice : dateTypeChoices) { - if (choice.getDate() != null) { - choice.setValidate(true); - choice.setName(String.valueOf(choice.getDate().getTime())); - poll.getChoiceDTOs().add(choice); - } - } - } else if (isImgChoices()) { - for (ImageChoiceUIO imgChoice : imgTypeChoices) { - if (imgChoice.getImg() != null) { - logger.debug("Image: " + imgChoice.getImg().getFileName() - + ", type: " + imgChoice.getImg().getContentType()); - if (imgChoice.getImg().getContentType().contains("image") - || imgChoice.getImg().getContentType().contains( - "IMAGE")) { - imgChoice.setValidate(true); - imgChoice.setName(imgChoice.getImg().getFileName() - .replace(' ', '_')); - poll.getChoiceDTOs().add(imgChoice); - } else { - return false; - } - } - } - } - - // Retouche des attributs dépendants l'un de l'autre - if (poll.getBeginDate() == null) { - poll.setBeginDate(new Date()); - } - if (poll.isAnonymous()) { - poll.setAnonymousVoteAllowed(true); - } - if (poll.isContinuousResults()) { - poll.setPublicResults(true); - } - if (poll.getMaxChoiceNb() < 1 - || poll.getMaxChoiceNb() > poll.getChoiceDTOs().size()) { - poll.setMaxChoiceNb(poll.getChoiceDTOs().size()); - } - - return true; - } - - /** - * Création du sondage. - */ - private void createPoll() { - - // Création du sondage - servicePoll.createPoll(poll); - - // FD-20100226 : Can't be null, an exception will be thrown if a - // problem comes from createPoll - //if (poll.getId() != null) { - - // Création des images - if (poll.getChoiceType() == ChoiceType.IMAGE) { - File dir = imgContext.getImageDir(); - ImageUtil.saveImages(imgTypeChoices, dir); - } - - // FD-20100226 : not necessary, the service will update - // automatically the poll when it was created - // Mise à jour du sondage : - //poll = servicePoll.findPollById(poll.getId()); - - // Mise à jour du flux Atom et envoi d'un mail de confirmation - addFeedEntry(); - sendMailNotification(); - //} - } - - /** Ajout d'une entrée dans le flux de syndication */ - private void addFeedEntry() { - PollAccountDTO creator = servicePollAccount.findPollAccountById(poll - .getCreatorId()); - String voteURL = siteURL + "poll/VoteFor/" + poll.getPollId(); - File feedFile = feedContext.getFile(poll.getPollId()); - - FeedUtil.createFeed(feedFile, "atom_1.0", messages.format( - "pollFeed_title", poll.getTitle()), siteURL, messages.format( - "pollFeed_desc", poll.getDescription())); - FeedUtil.feedFeed(feedFile, messages.format("pollFeed_createTitle", - creator.getVotingId()), voteURL, messages - .get("pollFeed_createContent")); - } - - /** Envoi du mail de notification */ - private void sendMailNotification() { - PollAccountDTO creator = servicePollAccount.findPollAccountById(poll - .getCreatorId()); - String voteURL = siteURL + "poll/VoteFor/" + poll.getPollId(); - String modifURL = siteURL + "poll/Modification/" + poll.getPollId() - + ":" + creator.getAccountId(); - Map<String, String> data = new HashMap<String, String>(); - data.put("host", PollenProperty.EMAIL_HOST.getValue()); - data.put("port", PollenProperty.EMAIL_PORT.getValue()); - data.put("from", PollenProperty.EMAIL_FROM.getValue()); - - // Mail au créateur - if (poll.getCreatorEmail() != null) { - data.put("to", poll.getCreatorEmail()); - data.put("title", messages.format("creatorEmail_subject", poll - .getTitle())); - data.put("msg", messages.format("creatorEmail_msg", - poll.getTitle(), voteURL, modifURL)); - - PreventRuleManager.emailAction(data); - } - - // Mails aux votants - for (VotingListDTO list : poll.getVotingListDTOs()) { - for (PollAccountDTO account : list.getPollAccountDTOs()) { - if (account.getEmail() != null) { - String accountVoteURL = voteURL + ":" - + account.getAccountId(); - - data.put("to", account.getEmail()); - data.put("title", messages.format("votingEmail_subject", - poll.getTitle())); - data - .put("msg", messages.format("votingEmail_msg", poll - .getTitle(), account.getVotingId(), - accountVoteURL)); - - PreventRuleManager.emailAction(data); - } - } - } - } - - public String getChoiceDateDisplay() { - return poll.isChoiceAddAllowed() ? "display: block;" : "display: none;"; - } - - public String getChoiceNbDisplay() { - return choiceNbCheckBox ? "display: block;" : "display: none;"; - } - - public String getNotificationDisplay() { - return notificationCheckBox ? "display: block;" : "display: none;"; - } - - public String getReminderDisplay() { - return reminderCheckBox ? "display: block;" : "display: none;"; - } - - /** Retourne l'index de la liste courante */ - public int getVotingListIndex() { - return votingLists.indexOf(votingList); - } - - /** Retourne le numéro de la liste courante (index+1) */ - public int getVotingListNumber() { - return votingLists.indexOf(votingList) + 1; - } - - /** Retourne la chaîne correspondant à l'étape courante */ - public String getStepLegend() { - Integer index = step.getIndex(); - - // corrections selon le type de sondage - if (isFreePoll()) { - if (step == PollStep.CHOICES) { - index--; - } - } - - // mise en forme du message - switch (step) { - case POLL: - return messages.format("pollLegend", index); - case OPTIONS: - return messages.format("optionsLegend", index); - case LISTS: - return messages.format("listsLegend", index); - case CHOICES: - return messages.format("choicesLegend", index); - default: - return ""; - } - } - - /** Retourne la classe CSS correspondant au groupe courant */ - public String getCurrentListClass() { - if (votingLists.size() > 1 && getVotingListIndex() == currentList) { - return "currentGroupDiv"; - } - return "groupDiv"; - } - - /** - * Retourne s'il existe plusieurs groupes. - */ - public boolean isSeveralGroups() { - return votingLists.size() > 1; - } - - public boolean isInPoll() { - return step == PollStep.POLL; - } - - public boolean isInLists() { - return step == PollStep.LISTS; - } - - public boolean isInChoices() { - return step == PollStep.CHOICES; - } - - public boolean isInOptions() { - return step == PollStep.OPTIONS; - } - - public boolean isNormalVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.NORMAL; - } - - public boolean isPercentageVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.PERCENTAGE; - } - - public boolean isCondorcetVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.CONDORCET; - } - - public boolean isNumberVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.NUMBER; - } - - public boolean isFreePoll() { - return poll.getPollType() == PollType.FREE; - } - - public boolean isRestrictedPoll() { - return poll.getPollType() == PollType.RESTRICTED; - } - - public boolean isGroupPoll() { - return poll.getPollType() == PollType.GROUP; - } - - public boolean isTextChoices() { - return poll.getChoiceType() == ChoiceType.TEXT; - } - - public boolean isDateChoices() { - return poll.getChoiceType() == ChoiceType.DATE; - } - - public boolean isImgChoices() { - return poll.getChoiceType() == ChoiceType.IMAGE; - } - - /** - * Méthode appelée à la sélection d'une liste de votants. Le mixin - * ck/OnEvent ne permet pas de retourner le contenu d'une zone. Il faut donc - * passer par une fonction JavaScript pour activer un event link. Un lien - * est créé. Il sera retourné à la fonction JavaScript onCompleteCallback - * pour mettre à jour la zone. - * - * @param value - * @return un JSONObject contenant l'url de l'évènement mettant à jour la - * zone. - */ - public JSONObject onChangeFromListSelect(String value) { - if (StringUtils.isNotEmpty(value)) { - personList = serviceList.findPersonListById(value); - - // Copie des personnes de la liste de favoris dans la liste de votants - for (PollAccountDTO account : personList.getPollAccounts()) { - account.setId(""); - account.setPersonListId(""); - } - - votingLists.get(currentList).setPollAccountDTOs( - personList.getPollAccounts()); - } - return createParamsForCallback(); - } - - /** - * Méthode appelée à la sélection d'un type de choix. Le mixin ck/OnEvent ne - * permet pas de retourner le contenu d'une zone. Il faut donc passer par - * une fonction JavaScript pour activer un event link. Un lien est créé. Il - * sera retourné à la fonction JavaScript onCompleteCallback pour mettre à - * jour la zone. - * - * @return un JSONObject contenant l'url de l'évènement mettant à jour la - * zone. - */ - public JSONObject onChangeFromChoiceType(String value) { - poll.setChoiceType(ChoiceType.valueOf(value)); - return createParamsForCallback(); - } - - /** - * Création d'un JSONObject contenant un identifiant de zone et une url pour - * un évènement. - * - * @return un JSONObject contenant un zoneId et une url. - */ - private JSONObject createParamsForCallback() { - JSONObject json = new JSONObject(); - Link link = resources.createEventLink("updatePollCreationZone"); - json.put("link", link.toAbsoluteURI()); - json.put("zoneId", "pollCreationZone"); - return json; - } - - /** - * Méthode appelée par le callback JavaScript pour mettre à jour la zone. - * - * @return le contenu mis à jour de la zone. - */ - public Object onUpdatePollCreationZone() { - return pollCreationZone.getBody(); - } - - /** - * Méthode appelée pour l'ajout d'une ligne supplémentaire dans le - * formulaire des listes de votants. - */ - void onSelectedFromAddPerson(int i) { - votingLists.get(i).getPollAccountDTOs().add(new PollAccountDTO()); - noStepSubmitSelected = true; - } - - /** - * Méthode appelée pour l'ajout d'un groupe dans le formulaire des listes de - * votants. - */ - void onSelectedFromAddGroup() { - votingList = new VotingListDTO(); - for (int i = 0; i < nbVotingListPersons; i++) { - votingList.getPollAccountDTOs().add(new PollAccountDTO()); - } - votingLists.add(votingList); - currentList = getVotingListIndex(); - noStepSubmitSelected = true; - } - - /** - * Méthode appelée lors de la suppression d'un groupe dans le formulaire des - * listes de votants. - */ - void onSelectedFromDeleteGroup(int i) { - //votingLists.remove(i); - if (currentList == i) { - currentList = votingLists.size() - 1; - } else if (currentList > i) { - currentList--; - } - deleteGroupId = i; - noStepSubmitSelected = true; - } - - /** - * Méthode appelée à la selection d'un groupe dans le formulaire des listes - * de votants. - */ - void onSelectedFromEditGroup(int i) { - currentList = i; - noStepSubmitSelected = true; - } - - /** - * Méthode appelée pour l'ajout d'une ligne supplémentaire dans le - * formulaire des choix. - */ - void onSelectedFromAddChoice() { - if (poll.getChoiceType() == ChoiceType.DATE) { - dateTypeChoices.add(new DateChoiceUIO()); - } else if (poll.getChoiceType() == ChoiceType.IMAGE) { - imgTypeChoices.add(new ImageChoiceUIO()); - } else { - choices.add(new ChoiceDTO()); - } - addChoiceSelected = true; - } - - /** Retourne vrai si des listes de favoris existent */ - public boolean isPersonListsExists() { - return personLists != null && !personLists.getList().isEmpty(); - } - - /** - * Activation de la page - */ - void onActivate(String id) { - - // Si un sondage est fourni (copie de sondage) - if (id != null && !"".equals(id)) { - - // Réinitialisation des variables de session - // Si l'ancien sondage n'existe pas ou est différent de celui fourni - if (oldPoll == null || !id.equals(oldPoll.getPollId())) { - oldPoll = servicePoll.findPollByPollId(id); - if (oldPoll != null) { - initWithExistingPoll(oldPoll); - oldPoll = null; - oldPollExists = true; - } - } - } - } - - /** - * Initialisation de l'affichage - */ - void setupRender() { - address = new AddressBarItem[] { new AddressBarItem("Pollen", "Index"), - new AddressBarItem(title, null) }; - - if (!addChoiceSelected && !uploadExceptionCatched - && !choicesCreationForm.getHasErrors()) { - step = PollStep.POLL; - if (!oldPollExists) { - oldPoll = null; - initPoll(); - } - initPersonLists(); - } - - addChoiceSelected = false; - uploadExceptionCatched = false; - } - - /** - * Initialisation du sondage. - */ - private void initPoll() { - - // Initialisation du sondage - poll = new PollDTO(); - if (userExists) { - poll.setCreatorName(user.getLogin()); - poll.setCreatorEmail(user.getEmail()); - } - - // Initialisation des règles de notification - notificationPreventRule = new PreventRuleDTO("vote", 0, true, - PreventRuleManager.EMAIL_ACTION); - reminderPreventRule = new PreventRuleDTO("rappel", 0, false, - PreventRuleManager.EMAIL_ACTION); - - notificationCheckBox = false; - reminderCheckBox = false; - choiceNbCheckBox = false; - - // Initialisation des choix - choices = new ArrayList<ChoiceDTO>(); - dateTypeChoices = new ArrayList<DateChoiceUIO>(); - imgTypeChoices = new ArrayList<ImageChoiceUIO>(); - for (int i = 0; i < nbChoices; i++) { - choices.add(new ChoiceDTO()); - dateTypeChoices.add(new DateChoiceUIO()); - imgTypeChoices.add(new ImageChoiceUIO()); - } - - // Initialisation des listes de votants - votingLists = new ArrayList<VotingListDTO>(); - } - - /** - * Initialisation du sondage à partir d'un sondage existant. - */ - private void initWithExistingPoll(PollDTO oldPoll) { - - // Initialisation du sondage - poll = PollHelper.getPoll(oldPoll); - - // Initialisation du créateur du sondage -// PollAccountDTO creator = servicePollAccount.findPollAccountById(oldPoll -// .getCreatorId()); - //poll.setCreatorId(oldPoll.getCreatorId()); - poll.setCreatorName(oldPoll.getCreatorName()); - poll.setCreatorEmail(oldPoll.getCreatorEmail()); - - // Initialisation des règles de notification - notificationPreventRule = PollHelper - .getNotificationPreventRule(oldPoll); - notificationCheckBox = !"".equals(notificationPreventRule.getScope()); - reminderPreventRule = PollHelper.getReminderPreventRule(oldPoll); - reminderCheckBox = !"".equals(reminderPreventRule.getScope()); - - // Initialisation des choix - choices = PollHelper.getTextChoices(oldPoll); - dateTypeChoices = PollHelper.getDateChoices(oldPoll); - imgTypeChoices = PollHelper.getImageChoices(oldPoll); - - // Initialisation des listes de votants - votingLists = PollHelper.getVotingLists(oldPoll); - } - - /** - * Initialisation de la liste de favoris. - */ - private void initPersonLists() { - if (userExists) { - List<PersonListDTO> _personLists = serviceList - .findPersonListByUser(user.getId()); - personLists = new GenericSelectModel<PersonListDTO>(_personLists, - PersonListDTO.class, "name", "id", _propertyAccess); - } - } -} Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollForm.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -243,7 +243,7 @@ choices.add(ChoiceField.getChoiceText()); } } else { - for (ChoiceDTO current : getPoll().getChoiceDTOs()) { + for (ChoiceDTO current : getPoll().getChoices()) { choices.add((ChoiceField)current); } } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollModification.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollModification.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/PollModification.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -262,7 +262,7 @@ poll.setPublicResults(true); } - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + for (ChoiceDTO choice : poll.getChoices()) { choice.setValidate(true); } servicePoll.updatePoll(poll); Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/Results.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -349,7 +349,7 @@ String choiceId = ""; // Récupération du choix correspondant au résultat - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + for (ChoiceDTO choice : poll.getChoices()) { if (resultName.equals(choice.getName())) { choiceId = choice.getId(); } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/pages/poll/VoteForPoll.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -46,9 +46,11 @@ import org.apache.tapestry5.corelib.components.Zone; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.ioc.util.AbstractMessages; import org.apache.tapestry5.upload.services.UploadedFile; import org.chenillekit.tapestry.core.components.DateTimeField; import org.chorem.pollen.business.PollenBusinessException; +import org.chorem.pollen.business.PollenBusinessException.PollenExceptionType; import org.chorem.pollen.business.PollenProperty; import org.chorem.pollen.business.business.PreventRuleManager; import org.chorem.pollen.business.dto.ChoiceDTO; @@ -70,12 +72,14 @@ import org.chorem.pollen.common.PollType; import org.chorem.pollen.common.VoteCountingType; import org.chorem.pollen.ui.base.ContextLink; +import org.chorem.pollen.ui.components.Border; import org.chorem.pollen.ui.components.FeedBack; import org.chorem.pollen.ui.components.ImageContextLink; import org.chorem.pollen.ui.components.Pager; +import org.chorem.pollen.ui.data.AddressBar; import org.chorem.pollen.ui.data.EvenOdd; -import org.chorem.pollen.ui.data.AddressBarItem; import org.chorem.pollen.ui.data.PollAction; +import org.chorem.pollen.ui.data.PollUri; import org.chorem.pollen.ui.data.uio.DateChoiceUIO; import org.chorem.pollen.ui.data.uio.ImageChoiceUIO; import org.chorem.pollen.ui.utils.FeedUtil; @@ -101,10 +105,6 @@ @Property private String title; - @SuppressWarnings("unused") - @Property - private AddressBarItem[] address; - /** Paramètres de la page */ private String param; @@ -138,11 +138,6 @@ @Component(parameters = { "timePicker=true", "timePickerAdjacent=true" }) private DateTimeField dateDTF; - /** Format des dates */ - @Persist - @Property - private DateFormat dateFormat; - /** Locale courante */ @Inject private Locale currentLocale; @@ -154,13 +149,6 @@ private Messages messages; /** - * Sondage pour lequel l'utilisateur vote - */ - @Property - @Persist - private PollDTO poll; - - /** * Vote courant de l'utilisateur */ @Property @@ -191,9 +179,6 @@ @InjectComponent private Zone pollZone; - @InjectComponent - private Zone commentZone; - /** * Objet servant à changer la couleur à chaque ligne de la liste des * sondages @@ -237,17 +222,6 @@ @Persist private ImageChoiceUIO newImageChoice; - /** Commentaire courant pour l'affichage des commentaires */ - @SuppressWarnings("unused") - @Property - @Persist - private CommentDTO comment; - - /** Nouveau commentaire posté */ - @Property - @Persist - private CommentDTO newComment; - /** Injection des services */ @Inject private ServicePoll servicePoll; @@ -292,36 +266,36 @@ @InjectComponent private FeedBack voteFeedback; - public String getVoteSizeMessage() { + public String getVoteSizeMessage() throws PollenBusinessException { if (log.isDebugEnabled()) { log.debug("poll voteDTOs list size : " + getVotes().size()); - log.debug("poll nbVotes : " + poll.getNbVotes()); + log.debug("poll nbVotes : " + getPoll().getNbVotes()); } - return messages.format("vote-size", poll.getNbVotes()); + return messages.format("vote-size", getPoll().getNbVotes()); } /** Méthode appelée après la soumission du vote. */ @Log - Object onSuccessFromVoteForm() { + Object onSuccessFromVoteForm() throws PollenBusinessException { if (initPollAccount()) { List<ChoiceDTO> choiceDTOs = new ArrayList<ChoiceDTO>(); - if (poll.getVoteCounting() == VoteCountingType.NORMAL) { + if (getPoll().getVoteCounting() == VoteCountingType.NORMAL) { int nbChoices = 0; - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + for (ChoiceDTO choice : getPoll().getChoices()) { if (choice.getValue() == 1) { nbChoices++; } choiceDTOs.add(choice); } - if (nbChoices > poll.getMaxChoiceNb()) { + if (nbChoices > getPoll().getMaxChoiceNb()) { voteForm.recordError(messages.format(("tooManyChoices"), - poll.getMaxChoiceNb())); + getPoll().getMaxChoiceNb())); return pollZone.getBody(); } - } else if (poll.getVoteCounting() == VoteCountingType.PERCENTAGE) { + } else if (getPoll().getVoteCounting() == VoteCountingType.PERCENTAGE) { int total = 0; - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + for (ChoiceDTO choice : getPoll().getChoices()) { total = total + choice.getValue(); choiceDTOs.add(choice); } @@ -330,21 +304,21 @@ return pollZone.getBody(); } - } else if (poll.getVoteCounting() == VoteCountingType.CONDORCET) { - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + } else if (getPoll().getVoteCounting() == VoteCountingType.CONDORCET) { + for (ChoiceDTO choice : getPoll().getChoices()) { if (choice.getValue() == 0) { choice.setValue(100); } choiceDTOs.add(choice); } - } else if (poll.getVoteCounting() == VoteCountingType.NUMBER) { + } else if (getPoll().getVoteCounting() == VoteCountingType.NUMBER) { String votingId = pollAccount.getVotingId(); if (anonymousVote) { votingId = "anonymous" + UUID.randomUUID().toString().replaceAll("-", ""); } - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + for (ChoiceDTO choice : getPoll().getChoices()) { if (!choice.isHidden()) { choiceDTOs.add(choice); @@ -365,7 +339,7 @@ } } - VoteDTO vote = new VoteDTO(null, poll.getId(), null); + VoteDTO vote = new VoteDTO(null, getPoll().getId(), null); vote.setChoiceDTOs(choiceDTOs); vote.setWeight(pollAccount.getWeight()); vote.setAnonymous(anonymousVote); @@ -387,7 +361,8 @@ } // Mise à jour du sondage et des résultats - poll = servicePoll.findPollByPollId(poll.getPollId()); + //poll = servicePoll.findPollByPollId(getPoll().getPollId()); + poll = null; countPoll(); addFeedEntry(PollAction.ADDVOTE, pollAccount.getVotingId(), @@ -403,7 +378,7 @@ return pollZone.getBody(); } - private void deleteVote(String voteId) { + private void deleteVote(String voteId) throws PollenBusinessException { for (VoteDTO vote : getVotes()) { if (vote.getId().equals(voteId)) { @@ -423,11 +398,12 @@ } /** Méthode appelée lors de la suppression d'un vote. */ - Object onActionFromDeleteVote(String voteId) { + Object onActionFromDeleteVote(String voteId) throws PollenBusinessException { deleteVote(voteId); // Mise à jour du sondage et des résultats - poll = servicePoll.findPollByPollId(poll.getPollId()); +// poll = servicePoll.findPollByPollId(poll.getPollId()); + poll = null; countPoll(); return pollZone.getBody(); @@ -440,7 +416,7 @@ } /** Initialisation du pollAccount et contrôle du nom. */ - private boolean initPollAccount() { + private boolean initPollAccount() throws PollenBusinessException { //// Contrôle et définition du votingId alreadyVoted = false; @@ -474,14 +450,14 @@ // The calcul of alreadyVoted will be needed for no double votingId // Carefull, not correct for an anonymous vote - alreadyVoted = serviceVote.hasAlreadyVoted(votingId, poll); + alreadyVoted = serviceVote.hasAlreadyVoted(votingId, getPoll()); // Check for restricted poll if (!alreadyVoted && !isFreePoll()) { - if (getAccountUId() != null) { + if (uri.getAccountUId() != null) { // The accountUId must be valid for the poll PollAccountDTO restrictedAccount = - servicePoll.getRestrictedAccount(getAccountUId(), poll); + servicePoll.getRestrictedAccount(uri.getAccountUId(), getPoll()); if (restrictedAccount != null) { // PollAccount is replaced by the good account from db @@ -504,7 +480,7 @@ } // Génération d'un identifiant de vote (si le sondage est libre et anonyme) - if (poll.isAnonymous()) { + if (getPoll().isAnonymous()) { anonymousVote = true; if (isFreePoll()) { pollAccount.setVotingId("anonymous" @@ -540,19 +516,12 @@ * @param votingId le votant a rechercher * @return vrai si la modification du vote est autorisée */ - public boolean isModifAllowed(String votingId) { + public boolean isModifAllowed(String votingId) throws PollenBusinessException { boolean modifAllowed = false; int i = 0; // parcours des votes pour trouver celui correspondant au votingId // et contrôle du droit de modification - - if (log.isDebugEnabled()) { - log.debug("Nb votes : " + getVotes().size()); - log.debug("Nb votes in poll : " + poll.getNbVotes()); - } - - // FIXME !!!!!! SEEMS TO BE INDEFINITE while (i < getVotes().size() && !modifAllowed) { // account : compte associé au vote courant @@ -588,9 +557,9 @@ /** Ajout d'une entrée dans le flux de syndication */ private void addFeedEntry(PollAction pollAction, String titleStr, - String contentStr) { - String voteURL = siteURL + "poll/VoteFor/" + poll.getPollId(); - File feedFile = getFeedContext().getFile(poll.getPollId()); + String contentStr) throws PollenBusinessException { + String voteURL = siteURL + "poll/VoteFor/" + getPoll().getPollId(); + File feedFile = getFeedContext().getFile(getPoll().getPollId()); String title = null; String content = null; @@ -614,29 +583,29 @@ if (!feedFile.exists()) { FeedUtil.createFeed(feedFile, "atom_1.0", messages.format( - "pollFeed_title", poll.getTitle()), siteURL, messages - .format("pollFeed_desc", poll.getDescription())); + "pollFeed_title", getPoll().getTitle()), siteURL, messages + .format("pollFeed_desc", getPoll().getDescription())); } FeedUtil.feedFeed(feedFile, title, voteURL, content); } /** Envoi du mail de notification */ - private void sendMailNotification() { - String voteURL = siteURL + "poll/VoteFor/" + poll.getPollId(); - String modifURL = siteURL + "poll/Modification/" + poll.getPollId() - + ":" + MD5.encode(poll.getCreatorId()); + private void sendMailNotification() throws PollenBusinessException { + String voteURL = siteURL + "poll/VoteFor/" + getPoll().getPollId(); + String modifURL = siteURL + "poll/Modification/" + getPoll().getPollId() + + ":" + MD5.encode(getPoll().getCreatorId()); Map<String, String> data = new HashMap<String, String>(); data.put("host", PollenProperty.EMAIL_HOST.getValue()); data.put("port", PollenProperty.EMAIL_PORT.getValue()); data.put("from", PollenProperty.EMAIL_FROM.getValue()); // Mail au créateur - data.put("to", poll.getCreatorEmail()); - data.put("title", messages.format("voteEmail_subject", poll.getTitle())); - data.put("msg", messages.format("voteEmail_msg", poll.getTitle(), poll - .getVoteDTOs().size(), voteURL, modifURL)); + data.put("to", getPoll().getCreatorEmail()); + data.put("title", messages.format("voteEmail_subject", getPoll().getTitle())); + data.put("msg", messages.format("voteEmail_msg", getPoll().getTitle(), getPoll() + .getNbVotes(), voteURL, modifURL)); - for (PreventRuleDTO rule : poll.getPreventRuleDTOs()) { + for (PreventRuleDTO rule : getPoll().getPreventRuleDTOs()) { PreventRuleManager manager = new PreventRuleManager(rule); manager.execute("vote", getVotes().size(), data); } @@ -671,9 +640,9 @@ * @param choice le choix concerné * @return true si le choix est dans le vote */ - public Boolean isChoiceInVote(ChoiceDTO choice) { + public Boolean isChoiceInVote(ChoiceDTO choice) throws PollenBusinessException { if (choice != null) { - switch (poll.getVoteCounting()) { + switch (getPoll().getVoteCounting()) { case NORMAL: return choice.getValue() > 0; case PERCENTAGE: @@ -732,8 +701,8 @@ * @return vrai si le fichier existe */ @Log - public boolean isFeedFileExisting() { - File feedFile = getFeedContext().getFile(poll.getPollId()); + public boolean isFeedFileExisting() throws PollenBusinessException { + File feedFile = getFeedContext().getFile(getPoll().getPollId()); if (log.isDebugEnabled()) { log.debug("feed context path : " + getFeedContext().getContextPath()); log.debug("feed absolute path : " + feedFile.getAbsolutePath()); @@ -760,7 +729,7 @@ * * @return les résultats */ - public String getResultsAsString() { + public String getResultsAsString() throws PollenBusinessException { StringBuffer res = new StringBuffer(""); Iterator<ResultDTO> it = results.iterator(); while (it.hasNext()) { @@ -785,8 +754,8 @@ * * @return true si le vote est anonyme */ - public boolean isVoteAnonymous() { - return poll.isAnonymous() || anonymousVote; + public boolean isVoteAnonymous() throws PollenBusinessException { + return getPoll().isAnonymous() || anonymousVote; } /** @@ -795,42 +764,38 @@ * * @return true si le vote est anonyme */ - public boolean isCurrentVoteAnonymous() { - return poll.isAnonymous() || vote.isAnonymous(); + public boolean isCurrentVoteAnonymous() throws PollenBusinessException { + return getPoll().isAnonymous() || vote.isAnonymous(); } /** Retourne vrai si la checkbox anonymousVote doit être affichée. */ - public boolean isAnonymousVoteDisplayed() { - return poll.isAnonymousVoteAllowed() && !poll.isAnonymous(); + public boolean isAnonymousVoteDisplayed() throws PollenBusinessException { + return getPoll().isAnonymousVoteAllowed() && !getPoll().isAnonymous(); } /** Retourne l'identifiant du votant du vote courant */ - // FIXME !!!!!! DON'T DO A QUERY FOR THAT public String getCurrentVotingId() { -// String id = vote.getPollAccountId(); -// String votingId = servicePollAccount.findPollAccountById(id) -// .getVotingId(); return vote.getName(); } /** Validation du champs de saisie du choix (texte). */ - void onValidateFromTextName(String value) throws ValidationException { + void onValidateFromTextName(String value) throws ValidationException, PollenBusinessException { validateNewChoice(value); } /** Validation du champs de saisie du choix (date). */ - void onValidateFromDateDTF(Date value) throws ValidationException { + void onValidateFromDateDTF(Date value) throws ValidationException, PollenBusinessException { validateNewChoice(String.valueOf(value.getTime())); } /** Validation du champs de saisie du choix (image). */ - void onValidateFromImgFile(UploadedFile value) throws ValidationException { + void onValidateFromImgFile(UploadedFile value) throws ValidationException, PollenBusinessException { validateNewChoice(value.getFileName().replace(' ', '_')); } /** Validation du champs de saisie du choix. */ - private void validateNewChoice(String value) throws ValidationException { - for (ChoiceDTO choice : poll.getChoiceDTOs()) { + private void validateNewChoice(String value) throws ValidationException, PollenBusinessException { + for (ChoiceDTO choice : getPoll().getChoices()) { if (value.equals(choice.getName())) { throw new ValidationException(messages.format("choiceExists", value)); @@ -839,24 +804,24 @@ } /** Méthode appelée lors de l'ajout d'un choix. */ - Object onSuccessFromChoiceForm() { + Object onSuccessFromChoiceForm() throws PollenBusinessException { String choiceName = null; String choiceDesc = null; if (isTextType()) { if (newChoice.getName() != null) { newChoice.setValidate(true); - newChoice.setPollId(poll.getId()); - poll.getChoiceDTOs().add(newChoice); + newChoice.setPollId(getPoll().getId()); + getPoll().getChoices().add(newChoice); choiceName = newChoice.getName(); choiceDesc = newChoice.getDescription(); } } else if (isDateType()) { if (newDateChoice.getDate() != null) { newDateChoice.setValidate(true); - newDateChoice.setPollId(poll.getId()); + newDateChoice.setPollId(getPoll().getId()); newDateChoice.setName(String.valueOf(newDateChoice.getDate() .getTime())); - poll.getChoiceDTOs().add(newDateChoice); + getPoll().getChoices().add(newDateChoice); Date date = new Date(Long.parseLong(newDateChoice.getName())); choiceName = dateFormat.format(date); choiceDesc = newDateChoice.getDescription(); @@ -864,10 +829,10 @@ } else if (isImageType()) { if (newImageChoice.getImg() != null) { newImageChoice.setValidate(true); - newImageChoice.setPollId(poll.getId()); + newImageChoice.setPollId(getPoll().getId()); newImageChoice.setName(newImageChoice.getImg().getFileName() .replace(' ', '_')); - poll.getChoiceDTOs().add(newImageChoice); + getPoll().getChoices().add(newImageChoice); //File imgFile = getImgContext().getImageDir(); // dir set in getImgContext() File imgFile = getImgContext().getImageDir(); // dir set in getImgContext() ImageUtil.saveImage(newImageChoice, imgFile); @@ -876,82 +841,63 @@ } } - servicePoll.updatePoll(poll); - poll = servicePoll.findPollByPollId(poll.getPollId()); + servicePoll.updatePoll(getPoll()); + poll = null; + //poll = servicePoll.findPollByPollId(getPoll().getPollId()); addFeedEntry(PollAction.ADDCHOICE, choiceName, choiceDesc); - newChoice = new ChoiceDTO(); - newDateChoice = new DateChoiceUIO(); - newImageChoice = new ImageChoiceUIO(); +// newChoice = new ChoiceDTO(); +// newDateChoice = new DateChoiceUIO(); +// newImageChoice = new ImageChoiceUIO(); return this; } /** Méthode appelée lors de la suppression d'un choix. */ - Object onActionFromDeleteChoice(String choiceId) { - Iterator<ChoiceDTO> itChoice = poll.getChoiceDTOs().iterator(); + Object onActionFromDeleteChoice(String choiceId) throws PollenBusinessException { + Iterator<ChoiceDTO> itChoice = getPoll().getChoices().iterator(); while (itChoice.hasNext()) { ChoiceDTO choice = itChoice.next(); if (choiceId.equals(choice.getId())) { itChoice.remove(); } } - servicePoll.updatePoll(poll); - poll = servicePoll.findPollByPollId(poll.getPollId()); + servicePoll.updatePoll(getPoll()); + poll = null; +// poll = servicePoll.findPollByPollId(poll.getPollId()); return pollZone.getBody(); } - /** Méthode appelée lors de l'ajout d'un commentaire. */ - Object onSuccessFromCommentForm() { - //newComment.setPollId(poll.getId()); - newComment.setPostDate(new Date()); - servicePoll.createComment(poll, newComment); - //serviceComment.createComment(newComment); - //poll = servicePoll.findPollByPollId(poll.getPollId()); - addFeedEntry(PollAction.ADDCOMMENT, newComment.getAuthor(), - newComment.getText()); - newComment = new CommentDTO(); - return commentZone.getBody(); - } +// public boolean isPollNull() { +// return poll == null; +// } - /** Méthode appelée lors de la suppression d'un commentaire. */ - Object onActionFromDeleteComment(String commentId) { - //serviceComment.deleteComment(commentId); - //poll = servicePoll.findPollByPollId(poll.getPollId()); - servicePoll.deleteComment(poll, commentId); - return commentZone.getBody(); - } - - public boolean isPollNull() { - return poll == null; - } - - public boolean isPollChoiceStarted() { + public boolean isPollChoiceStarted() throws PollenBusinessException { Date now = new Date(); - boolean started = poll.getBeginChoiceDate() == null || poll.getBeginChoiceDate().before(now); - boolean ended = poll.getEndChoiceDate() != null && poll.getEndChoiceDate().before(now); + boolean started = getPoll().getBeginChoiceDate() == null || getPoll().getBeginChoiceDate().before(now); + boolean ended = getPoll().getEndChoiceDate() != null && getPoll().getEndChoiceDate().before(now); return started && !ended; } - public boolean isPollStarted() { + public boolean isPollStarted() throws PollenBusinessException { Date now = new Date(); - return poll.getBeginDate() == null || poll.getBeginDate().before(now); + return getPoll().getBeginDate() == null || getPoll().getBeginDate().before(now); } - public boolean isPollFinished() { + public boolean isPollFinished() throws PollenBusinessException { Date now = new Date(); - return poll.getEndDate() != null && poll.getEndDate().before(now); + return getPoll().getEndDate() != null && getPoll().getEndDate().before(now); } - public boolean isPollChoiceOrVoteStarted() { + public boolean isPollChoiceOrVoteStarted() throws PollenBusinessException { return isPollChoiceStarted() || isPollStarted(); } - public boolean isPollChoiceRunning() { - return poll.isChoiceAddAllowed() && isPollChoiceStarted(); + public boolean isPollChoiceRunning() throws PollenBusinessException { + return getPoll().isChoiceAddAllowed() && isPollChoiceStarted(); //&& !isPollStarted(); } - public boolean isPollRunning() { - return isPollStarted() && !isPollFinished() && !poll.isClosed(); + public boolean isPollRunning() throws PollenBusinessException { + return isPollStarted() && !isPollFinished() && !getPoll().isClosed(); } public boolean isDescNull() { @@ -960,74 +906,61 @@ } /** Retourne vrai si le champs pollAccount doit apparaître. */ - public boolean isAccountFieldDisplayed() { - return !poll.isAnonymous() || isRestrictedPoll() || isGroupPoll(); + public boolean isAccountFieldDisplayed() throws PollenBusinessException { + return !getPoll().isAnonymous() || isRestrictedPoll() || isGroupPoll(); } - public boolean isFreePoll() { - return poll.getPollType() == PollType.FREE; + public boolean isFreePoll() throws PollenBusinessException { + return getPoll().getPollType() == PollType.FREE; } - public boolean isRestrictedPoll() { - return poll.getPollType() == PollType.RESTRICTED; + public boolean isRestrictedPoll() throws PollenBusinessException { + return getPoll().getPollType() == PollType.RESTRICTED; } - public boolean isGroupPoll() { - return poll.getPollType() == PollType.GROUP; + public boolean isGroupPoll() throws PollenBusinessException { + return getPoll().getPollType() == PollType.GROUP; } - public boolean isTextType() { - return poll.getChoiceType() == ChoiceType.TEXT; + public boolean isTextType() throws PollenBusinessException { + return getPoll().getChoiceType() == ChoiceType.TEXT; } - public boolean isDateType() { - return poll.getChoiceType() == ChoiceType.DATE; + public boolean isDateType() throws PollenBusinessException { + return getPoll().getChoiceType() == ChoiceType.DATE; } - public boolean isImageType() { - return poll.getChoiceType() == ChoiceType.IMAGE; + public boolean isImageType() throws PollenBusinessException { + return getPoll().getChoiceType() == ChoiceType.IMAGE; } - public boolean isNormalVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.NORMAL; + public boolean isNormalVoteCounting() throws PollenBusinessException { + return getPoll().getVoteCounting() == VoteCountingType.NORMAL; } - public boolean isPercentageVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.PERCENTAGE; + public boolean isPercentageVoteCounting() throws PollenBusinessException { + return getPoll().getVoteCounting() == VoteCountingType.PERCENTAGE; } - public boolean isCondorcetVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.CONDORCET; + public boolean isCondorcetVoteCounting() throws PollenBusinessException { + return getPoll().getVoteCounting() == VoteCountingType.CONDORCET; } - public boolean isNumberVoteCounting() { - return poll.getVoteCounting() == VoteCountingType.NUMBER; + public boolean isNumberVoteCounting() throws PollenBusinessException { + return getPoll().getVoteCounting() == VoteCountingType.NUMBER; } /** retourne vrai si l'utilisateur est le créateur du sondage */ - public boolean isCreatorUser() { - PollAccountDTO creator = servicePollAccount.findPollAccountById(poll - .getCreatorId()); - if (userExists && user.getId().equals(creator.getUserId())) { + public boolean isCreatorUser() throws PollenBusinessException { + if (userExists && user.getId().equals(getPoll().getUserId())) { return true; } return false; } - /** - * Récupération du créateur du sondage. - * - * @return le nom du créateur du sondage. - */ - public String getCreatorName() { - PollAccountDTO pollAccount = servicePollAccount - .findPollAccountById(poll.getCreatorId()); - return pollAccount.getVotingId(); - } - /** Retourne le message d'aide correspondant au type de sondage. */ - public String getHelpMessage() { - switch (poll.getVoteCounting()) { + public String getHelpMessage() throws PollenBusinessException { + switch (getPoll().getVoteCounting()) { case NORMAL: return messages.get("normalVote-help"); case PERCENTAGE: @@ -1041,89 +974,152 @@ } } - /** Retourne la date correspondant au choix courant */ + /** + * Retourne la date correspondant au choix courant + * + * @return date + */ public Date getChoiceNameAsDate() { return new Date(Long.valueOf(choiceOfPoll.getName())); } - /** Action réalisée lorsqu'on clique sur l'image */ - /*Object onDisplayImage(String choiceId) { - imageDisplay.setPoll(poll); - imageDisplay.setChoiceId(choiceId); - imageDisplay.setPageStyle("Vote"); - return imageDisplay; - }*/ - - /** Affichage de "" plutôt que 0 pour le Condorcet */ - /*String onToClientFromCondorcetInput() { - if (choiceOfVote.getValue() == 0) { - return ""; - } - return null; - }*/ - - /** Récupération d'un entier plutôt que "" pour le Condorcet */ - /*Object onParseClientFromCondorcetInput(String input) { - if ("".equals(input)) return 0; //ne fonctionne pas - return null; - }*/ - /** Dépouillement du sondage. Mise à jour des résultats. */ - private void countPoll() { + private void countPoll() throws PollenBusinessException { ResultListDTO resultListDTO = null; - - if (isGroupPoll()) { - resultListDTO = serviceResults.getGroupResults(poll.getPollId()); - } else { - resultListDTO = serviceResults.getNormalResults(poll.getPollId()); - } + if (getPoll().getContinuousResults()) { - results = resultListDTO.getResultDTOs(); + if (isGroupPoll()) { + resultListDTO = serviceResults.getGroupResults(getPoll().getPollId()); + } else { + resultListDTO = serviceResults.getNormalResults(getPoll().getPollId()); + } - if (logger.isDebugEnabled()) { - for (ResultDTO res : results) { - logger.debug(res.getName() + ": " + res.getValue() - + ", (voteCounting=" + res.getVoteCounting() - + ", byGroup=" + res.isByGroup() + ")"); + results = resultListDTO.getResultDTOs(); + + if (logger.isDebugEnabled()) { + for (ResultDTO res : results) { + logger.debug(res.getName() + ": " + res.getValue() + + ", (voteCounting=" + res.getVoteCounting() + + ", byGroup=" + res.isByGroup() + ")"); + } } } } + @Property + private PollUri uri; + /** + * Sondage pour lequel l'utilisateur vote + */ + @Persist + private PollDTO poll; + + @Property + private boolean pollNull; + + @InjectComponent + private Border border; + + /** Format des dates */ + private DateFormat dateFormat; + + /** * Méthode appelée au moment de l'activation de la page * * @param id l'identifiant du sondage et du votant */ - void onActivate(EventContext ec) { - param = ec.get(String.class, 0); + @Log + void onActivate(EventContext ec) throws PollenBusinessException { + uri = ec.get(PollUri.class, 0); if (ec.getCount() > 1) { page = ec.get(Integer.class, 1); } + } - // Initialisation du sondage - if (param != null && !"".equals(param)) { - String pollId = param.split(":", 2)[0]; - poll = servicePoll.findPollByPollId(pollId); + /** + * Méthode appelée au moment de la désactivation de la page + * + * @return l'identifiant du sondage et du votant + */ + Object[] onPassivate() { + return new Object[]{uri, page}; + } + /** + * Initialisation de l'affichage + */ + @Log + void setupRender() { + try { + poll = null; + getPoll(); + + if (getPoll().isClosed()) { + feedback.addInfo(messages.get("pollClosed")); + } else if (!isPollStarted()) { + feedback.addInfo(messages.get("pollNotStarted")); + } else if (isPollFinished()) { + feedback.addInfo(messages.get("pollFinished")); + } + if (isPollChoiceRunning()) { + feedback.addInfo(messages.get("pollChoiceRunning")); + } + + countPoll(); + } catch (PollenBusinessException eee) { + feedback.addError(messages.get(eee.getMessage())); + pollNull = true; + } + } + + /** + * Address bar of the page. Display in Border layout component. + * + * @return the address bar of the page. + */ + public AddressBar getAddress() { +// address = new AddressBarItem[] { new AddressBarItem("Pollen", "Index"), +// new AddressBarItem(title, null) }; + return new AddressBar().appendCurrent(title); + } + + /** + * DateFormat used in the page. + * + * @return the DateFormat needed. + */ + public DateFormat getDateFormat() { + if (dateFormat == null) { + dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, + DateFormat.SHORT, currentLocale); + } + return dateFormat; + } + + public PollDTO getPoll() throws PollenBusinessException { + if (poll == null) { + poll = servicePoll.findPollByPollId(uri.getPollUId()); + if (poll != null) { // Identification du votant - if (getAccountUId() != null) { + if (uri.getAccountUId() != null) { pollAccount = servicePollAccount - .findPollAccountByAccountId(getAccountUId()); + .findPollAccountByAccountId(uri.getAccountUId()); pollAccountId = pollAccount.getId(); } - + if (pollAccount == null) { pollAccount = new PollAccountDTO(); if (userExists) { if (user.getFirstName() != null && user.getLastName() != null) { pollAccount.setVotingId( user.getFirstName() + " " + user.getLastName()); - + } else if (user.getFirstName() != null) { pollAccount.setVotingId(user.getFirstName()); - + } else if (user.getLastName() != null) { pollAccount.setVotingId(user.getLastName()); } @@ -1134,59 +1130,14 @@ newChoice = new ChoiceDTO(); newDateChoice = new DateChoiceUIO(); newImageChoice = new ImageChoiceUIO(); - newComment = new CommentDTO(); - - //newComment.setPollId(poll.getId()); + } else { + throw new PollenBusinessException( + PollenExceptionType.POLL_NOT_EXIST); } } - - // Affichage des erreurs - if (poll == null) { - feedback.addError(messages.get("pollNotFound")); - } else { - if (poll.isClosed()) { - feedback.addInfo(messages.get("pollClosed")); - } else if (!isPollStarted()) { - feedback.addInfo(messages.get("pollNotStarted")); - } else if (isPollFinished()) { - feedback.addInfo(messages.get("pollFinished")); - } - if (isPollChoiceRunning()) { - feedback.addInfo(messages.get("pollChoiceRunning")); - } - } + return poll; } - private String accountUId; - - public String getAccountUId() { - if (accountUId == null && param.split(":", 2).length == 2) { - accountUId = param.split(":", 2)[1]; - } - return accountUId; - } - - /** - * Méthode appelée au moment de la désactivation de la page - * - * @return l'identifiant du sondage et du votant - */ - Object[] onPassivate() { - return new Object[]{param, page}; - } - - /** - * Initialisation de l'affichage - */ - void setupRender() { - address = new AddressBarItem[] { new AddressBarItem("Pollen", "Index"), - new AddressBarItem(title, null) }; - dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, - DateFormat.SHORT, currentLocale); - - countPoll(); - } - /************** PAGER AND VOTES MANAGMENT *********************************/ @InjectComponent @@ -1196,6 +1147,9 @@ private Integer page; + @Persist + private Integer nbVotesPerPage; + public int getPage() { if (page == null) { page = pager.getFirstPage(); @@ -1214,11 +1168,22 @@ * @return the number of votes to display per page */ public int getNbVotesPerPage() { + if (nbVotesPerPage == null) { + nbVotesPerPage = getPagerRange(); + } + return nbVotesPerPage; + } + + public void setNbVotesPerPage(int nbVotesPerPage) { + this.nbVotesPerPage = nbVotesPerPage; + } + + public int getPagerRange() { return Integer.parseInt(PollenProperty.NB_VOTES_PER_PAGE.getValue()); } - public String getNoPagerText() { - return messages.format("vote-noPagerText", poll.getNbVotes()); + public String getNoPagerText() throws PollenBusinessException { + return messages.format("vote-noPagerText", getPoll().getNbVotes()); } /** @@ -1227,15 +1192,80 @@ * loaded depends on current page using pager component. * * @return the list of votes to display + * @throws PollenBusinessException */ - public List<VoteDTO> getVotes() { + public List<VoteDTO> getVotes() throws PollenBusinessException { if (votes == null) { - if (log.isInfoEnabled()) { - log.info("BUSINESS REQUEST [getVotesByPoll]"); - } - votes = serviceVote.getVotesByPoll(poll, + votes = serviceVote.getVotesByPoll(getPoll(), pager.getStartIndex(), pager.getEndIndex()); } return votes; } + + /************** COMMENTS **************************************************/ + + @InjectComponent + private Zone commentZone; + + private List<CommentDTO> comments; + + /** Commentaire courant pour l'affichage des commentaires */ + @SuppressWarnings("unused") + @Property + @Persist + private CommentDTO comment; + + /** Nouveau commentaire posté */ + private CommentDTO newComment; + + public List<CommentDTO> getComments() throws PollenBusinessException { + if (comments == null) { + comments = servicePoll.getComments(poll); + } + return comments; + } + + /** + * Accessor for newComment property. Instantiate a new comment if needed. + * + * @return the current newComment. + */ + public CommentDTO getNewComment() { + if (newComment == null) { + newComment = new CommentDTO(); + } + return newComment; + } + + /** + * ACTION EVENT :: delete a comment. + * + * @param commentId id of the comment to delete + * @return the commentZone + * @throws PollenBusinessException + */ + Object onActionFromDeleteComment(String commentId) throws PollenBusinessException { + servicePoll.deleteComment(getPoll(), commentId); + return commentZone.getBody(); + } + + /** + * SUCCESS EVENT :: submit form for adding a new comment. + * + * @return the commentZone + * @throws PollenBusinessException + */ + @Log + Object onSuccessFromCommentForm() throws PollenBusinessException { + if (log.isDebugEnabled()) { + log.debug("newComment author : " + getNewComment().getAuthor()); + log.debug("newComment text : " + getNewComment().getText()); + } + getNewComment().setPostDate(new Date()); + servicePoll.createComment(getPoll(), getNewComment()); + addFeedEntry(PollAction.ADDCOMMENT, + getNewComment().getAuthor(), + getNewComment().getText()); + return commentZone.getBody(); + } } Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/AppModule.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/AppModule.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/AppModule.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -16,13 +16,18 @@ package org.chorem.pollen.ui.services; +import java.math.BigDecimal; +import org.chorem.pollen.business.services.SendMail; import org.apache.tapestry5.SymbolConstants; +import org.apache.tapestry5.ioc.Configuration; import org.apache.tapestry5.ioc.MappedConfiguration; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.OrderedConfiguration; import org.apache.tapestry5.ioc.ServiceBinder; import org.apache.tapestry5.ioc.annotations.EagerLoad; import org.apache.tapestry5.ioc.annotations.InjectService; +import org.apache.tapestry5.ioc.services.Coercion; +import org.apache.tapestry5.ioc.services.CoercionTuple; import org.apache.tapestry5.ioc.services.RegistryShutdownHub; import org.apache.tapestry5.ioc.services.RegistryShutdownListener; import org.apache.tapestry5.ioc.services.SymbolProvider; @@ -36,7 +41,7 @@ import org.chorem.pollen.business.services.ServiceResults; import org.chorem.pollen.business.services.ServiceUser; import org.chorem.pollen.business.services.ServiceVote; -import org.chorem.pollen.ui.utils.SendMail; +import org.chorem.pollen.ui.data.PollUri; import org.slf4j.Logger; /** @@ -146,6 +151,27 @@ configuration.add("PollenStartup", new PollenManager()); } + public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration) { + Coercion<String, PollUri> coercion1 = new Coercion<String, PollUri>() { + + @Override + public PollUri coerce(String input) { + return new PollUri(input); + } + }; + + Coercion<PollUri, String> coercion2 = new Coercion<PollUri, String>() { + + @Override + public String coerce(PollUri input) { + return input.getUri(); + } + }; + + configuration.add(new CoercionTuple<String, PollUri>(String.class, PollUri.class, coercion1)); + configuration.add(new CoercionTuple<PollUri, String>(PollUri.class, String.class, coercion2)); + } + /** * This is the BackgroundWorker service definition. It build the service * giving a Messages object for localization in the service. @@ -177,12 +203,11 @@ * @param conf * @return */ -// @EagerLoad -// public SendMail buildSendMail(Configuration conf) { -// SendMail res = new SendMail(conf); -// res.start(); -// return res; -// } + @EagerLoad + public SendMail buildSendMail() { + SendMail res = new SendMail(); + return res; + } /** * Make configuration from a Properties file available as symbols. Modified: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/services/PollenManager.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -20,7 +20,6 @@ import org.apache.commons.logging.LogFactory; import org.apache.tapestry5.ioc.services.RegistryShutdownListener; import org.chorem.pollen.business.PollenContext; -import org.chorem.pollen.ui.utils.SendMail; /** * Service de gestion de l'arrêt du serveur. Ce service exécute une action à la @@ -33,16 +32,12 @@ private static final Log log = LogFactory.getLog(PollenManager.class); - protected SendMail sendMail; - @Override public void run() { if (log.isInfoEnabled()) { log.info("Start Pollen"); } PollenContext.start(); - sendMail = new SendMail(); - sendMail.start(); } @Override @@ -51,7 +46,6 @@ log.info("Stop Pollen"); } PollenContext.stop(); - sendMail.stopExec(); } } Deleted: trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/utils/SendMail.java =================================================================== --- trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/utils/SendMail.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/java/org/chorem/pollen/ui/utils/SendMail.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,248 +0,0 @@ -/* *##% Pollen - * Copyright (C) 2009 CodeLutin - * - * 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/>. ##%*/ - -package org.chorem.pollen.ui.utils; - -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import java.util.List; -import java.util.Map; - -import org.apache.commons.io.FileUtils; -import org.chorem.pollen.business.utils.MailUtil; -import org.nuiton.util.FileUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import au.com.bytecode.opencsv.CSVReader; -import au.com.bytecode.opencsv.CSVWriter; -import org.apache.commons.io.IOUtils; -import org.chorem.pollen.business.PollenProperty; - -/** - * Mass mail management class. - * - * This class store email to send in a csv file, and send it (one per second) in - * a second time. - * This class can restart to send mail at application restart. - * - * For a mass mail sending to start, following files must be present: - * <ul> - * <li>xxx.emails : CSV file ("email", "subject", "body")</li> - * <li>xxx.index : next index to manage ( inited at 0)</li> - * </ul> - * - * @author chatellier - * @version $Revision$ - * - * Last update : $Date$ - * By : $Author$ - */ -public class SendMail extends Thread { - - /** logger. */ - private static final Logger log = LoggerFactory.getLogger(SendMail.class); - - public static final String EXTENSION_MAIL = ".mail"; - public static final String EXTENSION_INDEX = ".index"; - - /** Mail storage directory. */ - protected File mailStorageDirectory; - - protected volatile boolean stop; - - public SendMail() { - - // get email directory in configuration - // create it if not exists - String filename = PollenProperty.EMAIL_DIR.getValue(); - mailStorageDirectory = new File(filename); - if (!mailStorageDirectory.exists()) { - if (mailStorageDirectory.mkdirs()) { - if (log.isDebugEnabled()) { - log.debug("Email storage directory created in : " + mailStorageDirectory.getAbsolutePath()); - } - } - } - } - - public synchronized void stopExec() { - stop = true; - } - - /* - * @see java.lang.Runnable#run() - */ - @Override - public void run() { - - // try to find existing files - while (!stop) { - try { - sendAllMails(); - - // bloque thread until next notify - sleep(); - } - catch (Exception ex) { - if (log.isErrorEnabled()) { - log.error("Error during SendMail main loop", ex); - } - } - } - } - - protected synchronized void sleep() throws InterruptedException { - wait(); - } - - public synchronized void wakeUp() { - notifyAll(); - } - - /** - * Look for all xx.index file, and restart mail sending on - * non ending mass mail sending. - * - * After execution, delete mail and index file. - * @throws IOException - */ - protected void sendAllMails() throws IOException { - - // don't do for, allways take the first found - // a new one can be created when managing one other - List<File> indexFiles = null; - do { - - // filter is java valid : .*\\.index - indexFiles = FileUtil.find(mailStorageDirectory, ".*\\" + EXTENSION_INDEX, false); - - if (!indexFiles.isEmpty()) { - File indexFile = indexFiles.get(0); - // convert index content to int - String indexContent = FileUtils.readFileToString(indexFile, "UTF-8"); - int index = Integer.parseInt(indexContent); - - // get mail content file - File mailFile = new File(indexFile.getAbsolutePath().replaceAll(EXTENSION_INDEX + "$", EXTENSION_MAIL)); - - if (log.isDebugEnabled()) { - log.debug("Managing mail file : " + mailFile + " (from index " + indexContent + ")"); - } - - Reader indexFileReader = new BufferedReader(new FileReader(mailFile)); - CSVReader cvsReader = new CSVReader(indexFileReader); - - int currentIndex = 0; - String[] currentLine = cvsReader.readNext(); - while (currentLine != null) { - String receiver = currentLine[0]; - String subject = currentLine[1]; - String body = currentLine[2]; - - // index contains next index to treat so == is ok - if (currentIndex >= index) { - String host = PollenProperty.EMAIL_HOST.getValue(); - int port = Integer.parseInt( - PollenProperty.EMAIL_PORT.getValue()); - String from = PollenProperty.EMAIL_FROM.getValue(); - MailUtil.sendMail(host, port, from, - receiver, subject, body); - - // index contains next index to treat - FileUtils.writeStringToFile(indexFile, String.valueOf(currentIndex + 1)); - - // wait 2 secondes between each mail to not - // load smtp server - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - if (log.isErrorEnabled()) { - log.error("Can't wait between mail", ex); - } - } - } - else { - if (log.isDebugEnabled()) { - log.debug("Mail to " + receiver + " already sent in a previous execution, skip."); - } - } - - currentIndex++; - currentLine = cvsReader.readNext(); - } - - // delete woth index and mail file - mailFile.delete(); - indexFile.delete(); - } - else { - if (log.isInfoEnabled()) { - log.info("No more index mail index file found, go to sleep a while :)"); - } - } - } while (!indexFiles.isEmpty()); - } - - /** - * Prepare mail list. - * - * TODO : improve configuration reading - * - * @param id - * @param mailData - * @throws IOException - */ - public void prepareMails(String id, List<Map<String, String>> mailData) throws IOException { - - Writer fileWriter = null; - CSVWriter cvsWriter = null; - try { - - // write CSV datas - File emailFile = new File(mailStorageDirectory, id + EXTENSION_MAIL); - fileWriter = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(emailFile))); - cvsWriter = new CSVWriter(fileWriter); - - for (Map<String, String> singleMailData : mailData) { - String[] nextLine = new String[] { - singleMailData.get("receiver"), - singleMailData.get("subject"), - singleMailData.get("body") - }; - cvsWriter.writeNext(nextLine); - } - - // write index (default to 0) - File indexFile = new File(mailStorageDirectory, id + EXTENSION_INDEX); - FileUtil.writeString(indexFile, "0"); - } - finally { - if (cvsWriter != null) { - cvsWriter.close(); - } - IOUtils.closeQuietly(fileWriter); - } - - } -} Modified: trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_en.properties =================================================================== --- trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_en.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_en.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,3 +1,5 @@ -page=Page %d +page=Page %d/%d go-to=Go to page %d -rows-title=Rows %d - %d over %d \ No newline at end of file +rows-title=Rows %d - %d over %d +showPerPage=Show on each page: +change-nbrows=Change to %d rows per page \ No newline at end of file Modified: trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_fr.properties =================================================================== --- trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_fr.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/components/Pager_fr.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,3 +1,5 @@ -page=Page %d +page=Page %d/%d go-to=Aller \u00E0 la page %d rows-title=Lignes %d - %d sur %d +showPerPage=Afficher par page : +change-nbrows=Afficher %d lignes par page Modified: trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_en.properties =================================================================== --- trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_en.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_en.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -19,8 +19,8 @@ pollAccountName-required-message=You must provide your name. anonymousVote-label=Anonymous vote submitVote=Vote -vote-success=Your vote has been correctly saved. -vote-noPagerText=%d existing votes. +vote-success=Your vote has been correctly saved +vote-noPagerText=%d existing votes #choices addChoice=Adding a choice @@ -49,7 +49,7 @@ submitComment=Add a comment #messages -pollNotFound=No such poll exists. Please make sure that you are using the correct link and copy it completely into your browser's address field. +#pollNotFound=No such poll exists. Please make sure that you are using the correct link and copy it completely into your browser's address field. anonymousForbidden=Anonymous vote is forbidden for this poll. Enter a name. restrictedListsForbidden=The poll is restricted and you are not allowed to vote. Check if you have correctly used the link sent to you by email. alreadyVoted=Someone has already used the name %s to vote. Modified: trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_fr.properties =================================================================== --- trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_fr.properties 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/resources/org/chorem/pollen/ui/pages/poll/VoteForPoll_fr.properties 2010-03-19 15:05:04 UTC (rev 2951) @@ -20,7 +20,7 @@ anonymousVote-label=Vote anonyme submitVote=Voter vote-success=Votre vote a bien \u00E9t\u00E9 enregistr\u00E9 -vote-noPagerText=%d votes existants. +vote-noPagerText=%d votes existants #choices addChoice=Ajout d'un choix @@ -49,7 +49,7 @@ submitComment=Ajouter un commentaire #messages -pollNotFound=Il n'y a pas de sondage \u00E0 cette adresse. Veuillez verifier que vous utilisez le lien correcte et copiez-le compl\u00E8tement dans le champ d'adresse de votre navigateur. +#pollNotFound=Il n'y a pas de sondage \u00E0 cette adresse. Veuillez verifier que vous utilisez le lien correcte et copiez-le compl\u00E8tement dans le champ d'adresse de votre navigateur. anonymousForbidden=Le vote anonyme est interdit pour ce sondage. Saisissez un nom. restrictedListsForbidden=Le sondage est restreint et vous n'\u00EAtes pas autoris\u00E9 \u00E0 voter. V\u00E9rifiez que vous avez bien utiliser le lien qui vous a \u00E9t\u00E9 envoy\u00E9. alreadyVoted=Une personne a d\u00E9j\u00E0 vot\u00E9 sous le nom %s. Added: trunk/pollen-ui/src/main/webapp/img/1leftarrow.png =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/1leftarrow.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/img/1rightarrow.png =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/1rightarrow.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/img/2leftarrow.png =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/2leftarrow.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/pollen-ui/src/main/webapp/img/2rightarrow.png =================================================================== (Binary files differ) Property changes on: trunk/pollen-ui/src/main/webapp/img/2rightarrow.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml =================================================================== --- trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/main/webapp/poll/VoteForPoll.tml 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,5 +1,5 @@ -<t:border t:address="address" t:pageLogo="literal:Vote" t:feedFilename="${poll.pollId}" +<t:border t:address="address.items" t:pageLogo="literal:Vote" t:feedFilename="prop:uri.pollUId" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter"> <t:feedback t:id="feedback"/> @@ -8,7 +8,6 @@ <!-- Informations sur le sondage --> - <div id="pollTop"> ${poll.description} <fieldset> @@ -26,7 +25,7 @@ </t:FileLink> </t:if> </div> - <label>${message:creator-label}</label> ${creatorName} + <label>${message:creator-label}</label> ${poll.creatorName} <br/> <label>${message:beginDate-label}</label> <t:output value="poll.beginDate" format="dateFormat"/> @@ -51,7 +50,7 @@ <t:feedback t:id="voteFeedback"/> <p:else> <t:pager t:nbRowsPerPage="nbVotesPerPage" t:nbTotalRows="poll.nbVotes" - t:currentPage="page" t:noPagerText="prop:noPagerText"/> + t:currentPage="page" t:noPagerText="prop:noPagerText" t:range="pagerRange"/> </p:else> </t:if> <t:form t:id="voteForm" t:zone="pollZone"> @@ -65,7 +64,7 @@ </p:else> </t:if> <t:if test="textType"> - <t:loop t:source="poll.choiceDTOs" t:value="choiceOfPoll" volatile="true"> + <t:loop t:source="poll.choices" t:value="choiceOfPoll" volatile="true"> <t:if test="!isChoiceHidden()"> <th> <t:unless test="isDescNull()"> @@ -88,26 +87,26 @@ </t:loop> </t:if> <t:if test="dateType"> - <t:loop t:source="poll.choiceDTOs" t:value="choiceOfPoll" volatile="true"> - <t:if test="!isChoiceHidden()"> - <t:unless test="isDescNull()"> - <th class="desc"> - <span t:type="ck/Tooltip" title="${message:description}" value="${choiceOfPoll.description}" effect="blind"> - <t:output value="choiceNameAsDate" format="dateFormat"/> - </span> - </th> - <p:else> - <th> - <t:output value="choiceNameAsDate" format="dateFormat"/> - </th> - </p:else> - </t:unless> - </t:if> + <t:loop t:source="poll.choices" t:value="choiceOfPoll" volatile="true"> + <t:unless test="choiceHidden"> + <t:unless test="isDescNull()"> + <th class="desc"> + <span t:type="ck/Tooltip" t:value="choiceOfPoll.description" t:effect="blind"> + <t:output value="choiceNameAsDate" format="dateFormat"/> + </span> + </th> + <p:else> + <th> + <t:output value="choiceNameAsDate" format="dateFormat"/> + </th> + </p:else> + </t:unless> + </t:unless> </t:loop> </t:if> <t:if test="imageType"> - <t:loop t:source="poll.choiceDTOs" t:value="choiceOfPoll" volatile="true"> + <t:loop t:source="poll.choices" t:value="choiceOfPoll" volatile="true"> <t:if test="!isChoiceHidden()"> <t:unless test="isDescNull()"> <th class="desc"> @@ -137,7 +136,7 @@ <th></th> </p:else> </t:if> - <t:loop t:source="poll.choiceDTOs" t:value="choiceOfVote" volatile="true"> + <t:loop t:source="poll.choices" t:value="choiceOfVote" volatile="true"> <t:if test="!choiceOfVote.hidden"> <th> <t:if test="isNormalVoteCounting()"> @@ -184,7 +183,7 @@ </t:if> </t:unless> </td> - <t:loop t:source="poll.choiceDTOs" t:value="choiceOfPoll" volatile="true"> + <t:loop t:source="poll.choices" t:value="choiceOfPoll" volatile="true"> <t:unless t:test="choiceHidden"> ${setCurrentVoteChoice()} <t:if t:test="poll.anonymous"> @@ -234,7 +233,7 @@ <td> <t:PageLink t:page="poll/results" t:context="${poll.pollId}">${message:results}</t:PageLink> </td> - <t:loop t:source="poll.choiceDTOs" t:value="choiceOfPoll" volatile="true"> + <t:loop t:source="poll.choices" t:value="choiceOfPoll" volatile="true"> <t:if test="!isChoiceHidden()"> <td class="result">${currentChoiceResult}</td> </t:if> @@ -304,7 +303,7 @@ <h3>${message:comments}</h3> <t:zone t:id="commentZone" show="show" update="show"> <div id="commentsDiv"> - <div t:type="loop" t:source="poll.comments" t:value="comment" class="${evenodd.next}"> + <div t:type="loop" t:source="comments" t:value="comment" class="${evenodd.next}"> <t:if test="creatorUser"> <span class="cmd"> <t:actionlink t:id="deleteComment" context="comment.id" t:zone="commentZone"> Deleted: trunk/pollen-ui/src/test/java/org/chorem/pollen/ui/utils/SendMailTest.java =================================================================== --- trunk/pollen-ui/src/test/java/org/chorem/pollen/ui/utils/SendMailTest.java 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pollen-ui/src/test/java/org/chorem/pollen/ui/utils/SendMailTest.java 2010-03-19 15:05:04 UTC (rev 2951) @@ -1,102 +0,0 @@ -/* *##% Pollen - * Copyright (C) 2010 CodeLutin - * - * 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/>. ##%*/ - -package org.chorem.pollen.ui.utils; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.chorem.pollen.business.PollenContext; -import org.chorem.pollen.business.PollenProperty; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.nuiton.util.ApplicationConfig; - -/** - * Class for send mail storage class. - * - * @author chatellier - * @version $Revision$ - * - * Last update : $Date$ - * By : $Author$ - */ -@Ignore -public class SendMailTest { - - protected static SendMail sendMail; - - @BeforeClass - public static void init() throws InterruptedException { - - ApplicationConfig config = new ApplicationConfig(); - config.setOption(PollenProperty.EMAIL_DIR.getKey(), "target" + File.separator + "massmail"); - config.setOption(PollenProperty.EMAIL_HOST.getKey(), "smtp"); - config.setOption(PollenProperty.EMAIL_PORT.getKey(), "25"); - config.setOption(PollenProperty.EMAIL_FROM.getKey(), "pollenreminder@codelutin.com"); - - PollenContext.loadConfiguration(config); - - sendMail = new SendMail(); - sendMail.start(); - Thread.sleep(3000); - } - - /** - * Test to add mail and send mail. - * - * WARNING : This test really send mail, don't set it automatic. - * - * @throws IOException - * @throws InterruptedException - */ - @Test - public void testAddMail() throws IOException, InterruptedException { - List<Map<String, String>> mailList = new ArrayList<Map<String,String>>(); - - Map<String, String> mailMap = new HashMap<String, String>(); - mailMap.put("receiver", "chatellier+test@codelutin.com"); - mailMap.put("subject", "Test 18:00"); - mailMap.put("body", "Test body"); - - Map<String, String> mailMap2 = new HashMap<String, String>(); - mailMap2.put("receiver", "chorlet+test@codelutin.com"); - mailMap2.put("subject", "CR, CR CR !!! 18:00"); - mailMap2.put("body", "Des cr, encore des \"CRs\" !!!"); - - mailList.add(mailMap); - mailList.add(mailMap2); - - sendMail.prepareMails("test", mailList); - - String emailDir = PollenProperty.EMAIL_DIR.getValue(); - - Assert.assertTrue(new File(emailDir, "test.mail").exists()); - Assert.assertTrue(new File(emailDir, "test.index").exists()); - sendMail.wakeUp(); - - // TODO , en 5 secondes, il aura le temps d'envoyer 2 mails ? - Thread.sleep(5000); - Assert.assertFalse(new File(emailDir, "test.mail").exists()); - Assert.assertFalse(new File(emailDir, "test.index").exists()); - } -} Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2010-03-19 10:17:45 UTC (rev 2950) +++ trunk/pom.xml 2010-03-19 15:05:04 UTC (rev 2951) @@ -41,6 +41,11 @@ <artifactId>commons-email</artifactId> <version>1.2</version> </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>1.4</version> + </dependency> <!-- <dependency> <groupId>org.chorem</groupId> <artifactId>chorem-commons</artifactId>