Author: tchemit Date: 2014-05-08 14:57:53 +0200 (Thu, 08 May 2014) New Revision: 3923 Url: http://forge.chorem.org/projects/pollen/repository/revisions/3923 Log: - use a visitor to copy services objects (outside the services everything should be transient) - review validation (to avoir multiple redundant codes) Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/TopiaEntityCopyVisitor.java Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChoiceTopiaDao.java trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipalTopiaDao.java trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipals.java trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/Jsons.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverter.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityConverter.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollApiTest.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserApiTest.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverterTest.java trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityConverterTest.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ErrorMap.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenPrincipalRef.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java trunk/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties trunk/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChoiceTopiaDao.java =================================================================== --- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChoiceTopiaDao.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ChoiceTopiaDao.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.persistence.entity; +/* + * #%L + * Pollen :: Persistence + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import com.google.common.collect.ImmutableList; import java.util.List; Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipalTopiaDao.java =================================================================== --- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipalTopiaDao.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipalTopiaDao.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.persistence.entity; +/* + * #%L + * Pollen :: Persistence + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + public class PollenPrincipalTopiaDao extends AbstractPollenPrincipalTopiaDao<PollenPrincipal> { public PollenPrincipal findByPermissionToken(String permissionToken) { Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipals.java =================================================================== --- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipals.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenPrincipals.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.persistence.entity; +/* + * #%L + * Pollen :: Persistence + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import org.nuiton.topia.persistence.TopiaEntity; /** Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java =================================================================== --- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.persistence.entity; +/* + * #%L + * Pollen :: Persistence + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + public class SessionTokenTopiaDao extends AbstractSessionTokenTopiaDao<SessionToken> { public SessionToken findUniqueOrNullByToken(String token) { Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/Jsons.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/Jsons.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/Jsons.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.rest.api; +/* + * #%L + * Pollen :: Rest Api + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -25,37 +25,20 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.chorem.pollen.persistence.PollenEntityEnum; -import org.chorem.pollen.services.PollenTechnicalException; import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollenPrincipalRef; import org.debux.webmotion.server.call.Call; import org.debux.webmotion.server.call.HttpContext; import org.debux.webmotion.server.mapping.Mapping; import org.debux.webmotion.server.render.Render; -import org.nuiton.topia.persistence.TopiaEntity; -import org.nuiton.util.ObjectUtil; -import org.nuiton.util.beans.Binder; -import org.nuiton.util.beans.BinderFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -66,19 +49,19 @@ */ public class PollenRender<T> extends Render { - /** - * To specify entity collections to include in binded entities. - * - * @author tchemit <chemit@codelutin.com> - * @since 2.0 - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - public @interface ExposeCollection { +// /** +// * To specify entity collections to include in binded entities. +// * +// * @author tchemit <chemit@codelutin.com> +// * @since 2.0 +// */ +// @Retention(RetentionPolicy.RUNTIME) +// @Target(ElementType.METHOD) +// public @interface ExposeCollection { +// +// public String[] values() default {}; +// } - public String[] values() default {}; - } - protected T model; public PollenRender(T model) { @@ -120,22 +103,6 @@ map = toMap(model); -// GsonBuilder gsonBuilder = new GsonBuilder().registerTypeAdapter(Date.class, new JsonSerializer<Date>() { -// @Override -// public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext c) { -// JsonElement result; -// -// if (src == null) { -// result = JsonNull.INSTANCE; -// } else { -// result = new JsonPrimitive(src.getTime()); -// } -// -// return result; -// -// } -// }); - PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(context.getServletContext()); boolean devMode = applicationContext.getApplicationConfig().isDevMode(); @@ -146,7 +113,6 @@ ObjectWriter objectWriter = mapper.writerWithDefaultPrettyPrinter(); json = objectWriter.writeValueAsString(map); -// gsonBuilder.setPrettyPrinting(); } else { @@ -154,15 +120,13 @@ } -// Gson gson = gsonBuilder.create(); -// -// String json = gson.toJson(map); PrintWriter out = context.getOut(); out.print(json); } - protected <M> Object toMap(M model, String... includeCollection) { + // protected <M> Object toMap(M model, String... includeCollection) { + protected <M> Object toMap(M model) { if (model instanceof InvalidFormException) { @@ -191,140 +155,142 @@ } - if (model instanceof Iterable<?>) { - - // collection of objects - Iterable<?> objects = (Iterable<?>) model; - List<Object> result = Lists.newArrayList(); - for (Object object : objects) { - Object objectMap = toMap(object, includeCollection); - result.add(objectMap); - } - - return result; - - } - - // single object - // FIXME Do this in service, not here - - if (model instanceof TopiaEntity) { - - // entity need to transform it - - TopiaEntity topiaEntity = (TopiaEntity) model; - - Class<? extends TopiaEntity> entitytype = PollenEntityEnum.getContractClass(topiaEntity.getClass()); - PollenEntityBinder<TopiaEntity> binder = BinderFactory.newBinder(entitytype, entitytype, null, PollenEntityBinder.class); - Map<String, Object> map = binder.obtainProperties(topiaEntity); - Map<String, Object> result = Maps.newTreeMap(); - - for (Map.Entry<String, Object> entry : map.entrySet()) { - String propertyName = entry.getKey(); - Object propertyValue = entry.getValue(); - if (propertyValue instanceof TopiaEntity) { - result.put(propertyName, toMap(propertyValue)); - continue; - } - - result.put(propertyName, propertyValue); - - } - - // treat collections - - if (includeCollection != null) { - for (String propertyName : includeCollection) { - Iterable<?> collectionValue = binder.getCollectionValue(topiaEntity, propertyName); - result.put(propertyName, toMap(collectionValue)); - - } - } - - return result; - - } - return model; - } +// if (model instanceof Iterable<?>) { +// +// // collection of objects +// Iterable<?> objects = (Iterable<?>) model; +// List<Object> result = Lists.newArrayList(); +// for (Object object : objects) { +// Object objectMap = toMap(object, includeCollection); +// result.add(objectMap); +// } +// +// return result; +// +// } +// +// // single object +// // FIXME Do this in service, not here +// +// if (model instanceof TopiaEntity) { +// +// // entity need to transform it +// +// TopiaEntity topiaEntity = (TopiaEntity) model; +// +// Class<? extends TopiaEntity> entitytype = PollenEntityEnum.getContractClass(topiaEntity.getClass()); +// PollenEntityBinder<TopiaEntity> binder = BinderFactory.newBinder(entitytype, entitytype, null, PollenEntityBinder.class); +// Map<String, Object> map = binder.obtainProperties(topiaEntity); +// Map<String, Object> result = Maps.newTreeMap(); +// +// for (Map.Entry<String, Object> entry : map.entrySet()) { +// String propertyName = entry.getKey(); +// Object propertyValue = entry.getValue(); +// if (propertyValue instanceof TopiaEntity) { +// result.put(propertyName, toMap(propertyValue)); +// continue; +// } +// +// result.put(propertyName, propertyValue); +// +// } +// +// // treat collections +// +// if (includeCollection != null) { +// for (String propertyName : includeCollection) { +// Iterable<?> collectionValue = binder.getCollectionValue(topiaEntity, propertyName); +// result.put(propertyName, toMap(collectionValue)); +// +// } +// } +// +// return result; +// +// } - protected static class PollenEntityBinder<E extends TopiaEntity> extends Binder<E, E> { +// return model; - /** Logger. */ - private static final Log log = - LogFactory.getLog(PollenEntityBinder.class); - - private static final long serialVersionUID = 1L; - - protected List<String> simpleProperties; - - public PollenEntityBinder() { - } - - @Override - protected void setModel(BinderModel<E, E> model) { - super.setModel(model); - this.simpleProperties = Lists.newArrayList(); - for (String property : model.getSourceDescriptors()) { - if (model.getCollectionType(property) == null) { - simpleProperties.add(property); - } - } - } - - /** - * Obtain from the given object all properties registered in the binder - * model. - * - * @param source the bean to read - * @return the map of properties obtained indexed by their property name, - * or an empty map is the given {@code from} is {@code null}. - * @since 2.3 - */ - public Map<String, Object> obtainProperties(E source) { - if (source == null) { - // special limit case - return Collections.emptyMap(); - } - - Map<String, Object> result = Maps.newTreeMap(); - for (String sourceProperty : simpleProperties) { - - - try { - Object read; - Method readMethod = model.getSourceReadMethod(sourceProperty); - read = readMethod.invoke(source); - if (log.isDebugEnabled()) { - log.debug("property " + sourceProperty + ", type : " + - readMethod.getReturnType() + ", value = " + read); - } - if (readMethod.getReturnType().isPrimitive() && - ObjectUtil.getNullValue( - readMethod.getReturnType()).equals(read)) { - // for primitive type case, force nullity - read = null; - } - - if (read != null) { - result.put(sourceProperty, read); - } - } catch (IllegalAccessException | InvocationTargetException e) { - throw new PollenTechnicalException(e); - } - } - return result; - } - - public Iterable<?> getCollectionValue(E source, String sourceProperty) { - try { - Method readMethod = model.getSourceReadMethod(sourceProperty); - Object result = readMethod.invoke(source); - return (Iterable<?>) result; - } catch (IllegalAccessException | InvocationTargetException e) { - throw new PollenTechnicalException(e); - } - } } + +// protected static class PollenEntityBinder<E extends TopiaEntity> extends Binder<E, E> { +// +// /** Logger. */ +// private static final Log log = +// LogFactory.getLog(PollenEntityBinder.class); +// +// private static final long serialVersionUID = 1L; +// +// protected List<String> simpleProperties; +// +// public PollenEntityBinder() { +// } +// +// @Override +// protected void setModel(BinderModel<E, E> model) { +// super.setModel(model); +// this.simpleProperties = Lists.newArrayList(); +// for (String property : model.getSourceDescriptors()) { +// if (model.getCollectionType(property) == null) { +// simpleProperties.add(property); +// } +// } +// } +// +// /** +// * Obtain from the given object all properties registered in the binder +// * model. +// * +// * @param source the bean to read +// * @return the map of properties obtained indexed by their property name, +// * or an empty map is the given {@code from} is {@code null}. +// * @since 2.3 +// */ +// public Map<String, Object> obtainProperties(E source) { +// if (source == null) { +// // special limit case +// return Collections.emptyMap(); +// } +// +// Map<String, Object> result = Maps.newTreeMap(); +// for (String sourceProperty : simpleProperties) { +// +// +// try { +// Object read; +// Method readMethod = model.getSourceReadMethod(sourceProperty); +// read = readMethod.invoke(source); +// if (log.isDebugEnabled()) { +// log.debug("property " + sourceProperty + ", type : " + +// readMethod.getReturnType() + ", value = " + read); +// } +// if (readMethod.getReturnType().isPrimitive() && +// ObjectUtil.getNullValue( +// readMethod.getReturnType()).equals(read)) { +// // for primitive type case, force nullity +// read = null; +// } +// +// if (read != null) { +// result.put(sourceProperty, read); +// } +// } catch (IllegalAccessException | InvocationTargetException e) { +// throw new PollenTechnicalException(e); +// } +// } +// return result; +// } +// +// public Iterable<?> getCollectionValue(E source, String sourceProperty) { +// try { +// Method readMethod = model.getSourceReadMethod(sourceProperty); +// Object result = readMethod.invoke(source); +// return (Iterable<?>) result; +// } catch (IllegalAccessException | InvocationTargetException e) { +// throw new PollenTechnicalException(e); +// } +// } +// } } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverter.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverter.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverter.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.rest.api; +/* + * #%L + * Pollen :: Rest Api + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.beanutils.converters.AbstractConverter; import org.chorem.pollen.services.PollenTechnicalException; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityConverter.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityConverter.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/TopiaEntityConverter.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.rest.api; +/* + * #%L + * Pollen :: Rest Api + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import org.apache.commons.beanutils.converters.AbstractConverter; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -32,8 +32,8 @@ import org.debux.webmotion.server.WebMotionController; import java.io.File; -import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; /** * TODO @@ -92,9 +92,9 @@ } - public LinkedHashSet<FavoriteListMember> getMembers(FavoriteListService favoriteListService, String favoriteListId) { + public Set<FavoriteListMember> getMembers(FavoriteListService favoriteListService, String favoriteListId) { - LinkedHashSet<FavoriteListMember> members = favoriteListService.getFavoriteListMembers(favoriteListId); + Set<FavoriteListMember> members = favoriteListService.getFavoriteListMembers(favoriteListId); return members; } @@ -123,7 +123,7 @@ public void removeMember(FavoriteListService favoriteListService, String favoriteListId, String memberId) { - favoriteListService.removeFavoriteListMember(favoriteListId, memberId); + favoriteListService.deleteFavoriteListMember(favoriteListId, memberId); } } Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollApiTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollApiTest.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollApiTest.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -49,7 +49,6 @@ * @author Tony Chemit <chemit@codelutin.com> * @since 2.0 */ -@Ignore public class PollApiTest extends AbstractPollenRestApiTest { @Before @@ -106,12 +105,14 @@ @Test public void getPoll() throws URISyntaxException, IOException { + Poll poll = fixture(PollenFixtures.POLL_NORMAL_ID); String pollId = poll.getTopiaId(); Request request = createRequest("/v1/polls/" + pollId).Get(); String content = request.execute().returnContent().asString(); showTestResult(content); assertNotNull(content); + } @Test Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserApiTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserApiTest.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserApiTest.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -24,6 +24,7 @@ */ import org.apache.http.client.fluent.Request; +import org.chorem.pollen.persistence.entity.PollenUser; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -36,7 +37,6 @@ * @author tchemit <chemit@codelutin.com> * @since 2.0 */ -@Ignore public class PollenUserApiTest extends AbstractPollenRestApiTest { @Before @@ -52,50 +52,65 @@ String content = request.execute().returnContent().asString(); showTestResult(content); assertTrue(content.contains("email")); + } @Test public void getUser() throws Exception { - String userId = ""; + + PollenUser pollenUser = fixture("user_jean"); + String userId = pollenUser.getTopiaId(); Request request = createRequest("/v1/users/" + userId).Get(); String content = request.execute().returnContent().asString(); showTestResult(content); assertTrue(content.contains("email")); + assertTrue(content.contains("jean@pollen.fake")); + } @Ignore @Test public void postUser() throws Exception { + Request request = createRequest("/v1/users").Post(); String content = request.execute().returnContent().asString(); showTestResult(content); assertTrue(content.contains("email2")); + } @Ignore @Test public void putUser() throws Exception { - String userId = ""; + + PollenUser pollenUser = fixture("user_jean"); + String userId = pollenUser.getTopiaId(); Request request = createRequest("/v1/users/" + userId).Get(); String content = request.execute().returnContent().asString(); showTestResult(content); assertTrue(content.contains("email3")); + } @Ignore @Test public void deleteUser() throws Exception { - String userId = ""; + + PollenUser pollenUser = fixture("user_jean"); + String userId = pollenUser.getTopiaId(); Request request = createRequest("/v1/users/" + userId).Delete(); String content = request.execute().returnContent().asString(); showTestResult(content); assertTrue(content.contains("OK!")); + } @Ignore @Test public void validateUserEmail() throws Exception { - String userId = ""; + + PollenUser pollenUser = fixture("user_jean"); + String userId = pollenUser.getTopiaId(); String token = ""; Request request = createRequest("/v1/users/" + userId + "?token=" + token).Put(); String content = request.execute().returnContent().asString(); Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverterTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverterTest.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityArrayConverterTest.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.rest.api; +/* + * #%L + * Pollen :: Rest Api + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import org.chorem.pollen.persistence.entity.Choice; import org.chorem.pollen.persistence.entity.ChoiceType; import org.junit.Assert; Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityConverterTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityConverterTest.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/TopiaEntityConverterTest.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.rest.api; +/* + * #%L + * Pollen :: Rest Api + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import org.chorem.pollen.persistence.entity.CommentVisibility; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollType; Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/TopiaEntityCopyVisitor.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/TopiaEntityCopyVisitor.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/TopiaEntityCopyVisitor.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -0,0 +1,348 @@ +package org.chorem.pollen.services; + +/* + * #%L + * Pollen :: Service + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.apache.commons.beanutils.PropertyUtilsBean; +import org.nuiton.topia.persistence.TopiaApplicationContext; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityVisitor; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * To copy entities. + * FIXME-tchemit-2014-05-08 (Could we move this in ToPIA ?). + * <p/> + * Created on 5/8/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.0 + */ +public class TopiaEntityCopyVisitor<T extends TopiaApplicationContext> implements TopiaEntityVisitor { + + /** + * Stack of entities to copy. + * <p/> + * When a entity is started, the previous current entity goes at the top of the stack. + * <p/> + * When a entity is ended, the current entity goes is marked as the last ended, + * and the last entity of the stack goes back to the current state. + */ + protected Deque<TopiaEntity> stack = new ArrayDeque<>(); + + /** + * The current entity (means the last entity entering in the {@link #start(TopiaEntity)} method). + */ + protected TopiaEntity current; + + /** + * The last ended entity (means the last entity entering in the {@link #end(TopiaEntity)} method). + */ + protected TopiaEntity lastEnded; + + /** + * To get entity concrete class from a entity instance. + */ + protected final T topiaApplicationContext; + + /** + * To get and set properties. + */ + protected final PropertyUtilsBean propertyUtilsBean; + + /** + * Cache of already explored entities. + */ + protected Collection<String> alreadyExplored; + + public static <T extends TopiaApplicationContext, E extends TopiaEntity> E copy(T topiaApplicationContext, E source) { + + Preconditions.checkNotNull(topiaApplicationContext); + Preconditions.checkNotNull(source); + + TopiaEntityCopyVisitor<T> visitor = new TopiaEntityCopyVisitor<>(topiaApplicationContext); + + try { + + source.accept(visitor); + + E target = (E) visitor.lastEnded; + + return target; + + } finally { + + visitor.clear(); + + } + + + } + + public static <T extends TopiaApplicationContext, E extends TopiaEntity> Collection<E> copy(T topiaApplicationContext, Collection<E> sources) { + + Preconditions.checkNotNull(topiaApplicationContext); + Preconditions.checkNotNull(sources); + + TopiaEntityCopyVisitor<T> visitor = new TopiaEntityCopyVisitor<>(topiaApplicationContext); + + Collection<E> targets = createCollectionInstance(sources); + + for (E source : sources) { + + source.accept(visitor); + + try { + + E target = (E) visitor.lastEnded; + + targets.add(target); + + } finally { + + visitor.clear(); + + } + + } + + return targets; + + } + + protected TopiaEntityCopyVisitor(T topiaApplicationContext) { + this.topiaApplicationContext = topiaApplicationContext; + this.alreadyExplored = new ArrayList<>(); + this.propertyUtilsBean = new PropertyUtilsBean(); + } + + @Override + public void start(TopiaEntity source) { + + boolean accept = acceptEntity(source); + + if (accept) { + + if (current != null) { + + stack.push(current); + + } + + try { + + Class<? extends TopiaEntity> entityClass = source.getClass(); + + Class<?> implementationClass = topiaApplicationContext.getImplementationClass(entityClass); + + current = (TopiaEntity) implementationClass.newInstance(); + current.setTopiaId(source.getTopiaId()); + current.setTopiaCreateDate(source.getTopiaCreateDate()); + current.setTopiaVersion(source.getTopiaVersion()); + //FIXME Deal with technical properties (deleted) + + } catch (InstantiationException | IllegalAccessException e) { + + throw new PollenTechnicalException("could not create a new entity", e); + + } + + } + + + } + + @Override + public void end(TopiaEntity source) { + + boolean accept = acceptEntity(source); + + if (accept) { + + lastEnded = current; + + if (!stack.isEmpty()) { + + current = stack.pop(); + } + + } + } + + @Override + public void visit(TopiaEntity entity, String propertyName, Class<?> type, Object source) { + + if (source != null) { + + Object target = copy(source); + + if (target != null) { + + setPropertyValue(propertyName, target); + + } + + } + } + + @Override + public void visit(TopiaEntity entity, String propertyName, Class<?> collectionType, Class<?> type, Object source) { + + if (source != null) { + + Object target = createCollectionInstance(source); + + setPropertyValue(propertyName, target); + + } + + } + + @Override + public void visit(TopiaEntity entity, String propertyName, Class<?> collectionType, Class<?> type, int index, Object source) { + + if (source != null) { + + Object target = copy(source); + + // get the collection + + Collection<?> collection; + try { + + collection = (Collection<?>) propertyUtilsBean.getSimpleProperty(current, propertyName); + + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + + throw new PollenTechnicalException("Could not get property " + propertyName, e); + + } + + // ensure size is ok + + while (collection.size() <= index) { + + collection.add(null); + + } + + try { + + propertyUtilsBean.setIndexedProperty(current, propertyName, index, target); + + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + + throw new PollenTechnicalException("Could not set indexed property " + propertyName + " at index " + index, e); + + } + + } + } + + @Override + public void clear() { + + stack.clear(); + alreadyExplored.clear(); + lastEnded = null; + current = null; + + } + + protected Object copy(Object source) { + + Object target; + + if (acceptEntity(source)) { + + ((TopiaEntity) source).accept(this); + + target = lastEnded; + + } else { + + target = source; + + } + + return target; + + } + + protected void setPropertyValue(String propertyName, Object valueToCopy) { + + try { + + propertyUtilsBean.setSimpleProperty(current, propertyName, valueToCopy); + + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + + throw new PollenTechnicalException("Could not set property " + propertyName, e); + + } + + } + + protected static <E> Collection<E> createCollectionInstance(Object value) { + + Collection<E> valueToCopy; + + if (value instanceof LinkedHashSet) { + + valueToCopy = new LinkedHashSet<>(); + + } else if (value instanceof SortedSet) { + + valueToCopy = new TreeSet<>(); + + } else if (value instanceof Set) { + + valueToCopy = new HashSet<>(); + + } else { + + valueToCopy = new ArrayList<>(); + + } + + return valueToCopy; + + } + + protected boolean acceptEntity(Object entity) { + + boolean add = entity instanceof TopiaEntity && + alreadyExplored.add(((TopiaEntity) entity).getTopiaId()); + return add; + + } +} Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/TopiaEntityCopyVisitor.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -29,6 +29,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.shiro.crypto.hash.Sha512Hash; +import org.chorem.pollen.persistence.entity.ChoiceType; import org.chorem.pollen.persistence.entity.CommentVisibility; import org.chorem.pollen.persistence.entity.PollType; import org.chorem.pollen.persistence.entity.VoteVisibility; @@ -148,6 +149,13 @@ return result; } + public ChoiceType getDefaultChoiceType() { + ChoiceType result = applicationConfig.getOption( + ChoiceType.class, + PollenServiceConfigOption.DEFAULT_CHOICE_TYPE.key); + return result; + } + /** * @return Le nom d'hôte du serveur SMTP. */ Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,6 +23,7 @@ * #L% */ +import org.chorem.pollen.persistence.entity.ChoiceType; import org.chorem.pollen.persistence.entity.CommentVisibility; import org.chorem.pollen.persistence.entity.PollType; import org.chorem.pollen.persistence.entity.VoteVisibility; @@ -95,6 +96,17 @@ CommentVisibility.EVERYBODY.name(), CommentVisibility.class), + /** + * Default poll choice type to use at a new choice creation. + * + * @since 2.0 + */ + DEFAULT_CHOICE_TYPE( + "pollen.default.pollChoiceType", + n("pollen.configuration.pollChoiceType"), + ChoiceType.TEXT.name(), + ChoiceType.class), + SMTP_HOST( "pollen.smtp.host", "Nom d'hôte du serveur SMTP", Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -55,6 +55,7 @@ SessionToken.PROPERTY_POLLEN_TOKEN, pollenToken, SessionToken.PROPERTY_POLLEN_USER, user); commit(); + return sessionToken; } @@ -63,8 +64,10 @@ SessionToken sessionToken = getSecurityService().logout(); if (sessionToken != null) { + getSessionTokenDao().delete(sessionToken); commit(); + } } @@ -73,17 +76,14 @@ Preconditions.checkNotNull(login); - PollenUser user = getUserService().getUserByLogin(login); + PollenUser user = getPollenUserDao().forLoginEquals(login).findUnique(); String newPassword = serviceContext.generatePassword(); getSecurityService().setUserPassword(user, newPassword); commit(); - //TODO Notifiy Password changed to user - if (log.isDebugEnabled()) { - log.debug("Notify Password changed"); - } + getNotificationService().onUserLostPasswordAsked(user, newPassword); } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,15 +23,14 @@ * #L% */ -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import org.apache.commons.collections4.CollectionUtils; import org.chorem.pollen.persistence.entity.Choice; import org.chorem.pollen.persistence.entity.ChoiceTopiaDao; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollenPrincipal; +import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.services.service.security.PermissionVerb; import java.util.List; @@ -69,6 +68,31 @@ } + public Choice getNewChoice() { + + Choice result = getChoiceDao().newInstance(); + + // -- default values -- // + + result.setChoiceType(getPollenServiceConfig().getDefaultChoiceType()); + + // -- creator -- // + + PollenPrincipal creator = getPollenPrincipalDao().newInstance(); + result.setCreator(creator); + + PollenUser connectedUser = getConnectedUser(); + + if (connectedUser != null) { + + creator.setName(connectedUser.getName()); + creator.setEmail(connectedUser.getEmail()); + } + + return result; + + } + public Choice addChoice(String pollId, Choice choice) throws InvalidFormException { checkNotNull(pollId); @@ -86,11 +110,10 @@ choice.setChoiceOrder(existingChoices.size()); Choice result = saveChoice(poll, choice); - - getPollDao().update(poll); commit(); - //TODO Notify Choice added + getNotificationService().onChoiceAdded(poll, result); + return result; } @@ -108,11 +131,10 @@ errorMap.failIfNotEmpty(); Choice result = saveChoice(poll, choice); - - getChoiceDao().update(choice); commit(); - //TODO Notify Choice edited + getNotificationService().onChoiceEdited(poll, result); + return result; } @@ -128,8 +150,10 @@ getChoiceDao().delete(choice); commit(); - //TODO Notify Choice deleted + getNotificationService().onChoiceDeleted(poll, choice); + + } protected Choice getChoice(Poll poll, String choiceId) { @@ -152,17 +176,17 @@ boolean choiceExists = choice.isPersisted(); - Choice choiceToPersist; + Choice toSave; if (choiceExists) { // get existing choice - choiceToPersist = getChoice(poll, choice.getTopiaId()); + toSave = getChoice(poll, choice.getTopiaId()); } else { // create a new choice - choiceToPersist = choiceDao.create(); + toSave = choiceDao.create(); // create a new principal PollenPrincipal principal = getSecurityService().generatePollenPrincipal(); @@ -173,91 +197,36 @@ principal.setEmail(creator.getEmail()); } - choiceToPersist.setChoiceType(choice.getChoiceType()); - choiceToPersist.setCreator(principal); - choiceToPersist.setPoll(poll); - choiceToPersist.setChoiceOrder(choice.getChoiceOrder()); + toSave.setChoiceType(choice.getChoiceType()); + toSave.setCreator(principal); + toSave.setPoll(poll); + toSave.setChoiceOrder(choice.getChoiceOrder()); } - switch (choiceToPersist.getChoiceType()) { + switch (toSave.getChoiceType()) { case TEXT: - choiceToPersist.setName(choice.getName()); - choiceToPersist.setDescription(choice.getDescription()); - choiceToPersist.setCreator(poll.getCreator()); + toSave.setName(choice.getName()); + toSave.setDescription(choice.getDescription()); + toSave.setCreator(poll.getCreator()); + break; case DATE: + throw new IllegalStateException("Not implemented"); case IMAGE: + throw new IllegalStateException("Not implemented"); } - return choiceToPersist; + return toSave; + } -// protected void checkChoiceForm(List<Choice> existingChoices, Choice choice) throws InvalidFormException { -// -// //TODO use nuiton validator ? -// Multimap<String, String> errors = ArrayListMultimap.create(); -// -// boolean choiceExists = choice.isPersisted(); -// -// Set<String> choiceNames = Sets.newHashSet(); -// -// checkNotNull(errors, "choiceType", choice.getChoiceType(), "choiceType can not be null"); -// -// if (CollectionUtils.isNotEmpty(existingChoices)) { -// -// // get all used names -// -// for (Choice choice1 : existingChoices) { -// -// if (choiceExists && -// choice1.getTopiaId().equals(choice.getTopiaId())) { -// continue; -// } -// choiceNames.add(choice1.getName()); -// -// } -// } -// -// switch (choice.getChoiceType()) { -// -// case TEXT: -// -// String choiceName = choice.getName(); -// boolean nameNotBlank = checkNotBlank(errors, -// "name", -// choiceName, -// "choice name can not be empty"); -// -// if (nameNotBlank) { -// boolean nameAdded = choiceNames.add(choiceName); -// check(errors, "name", nameAdded, "choice name already used in this list"); -// } -// -// break; -// case DATE: -// -// throw new IllegalStateException("Not implemented"); -// -// case IMAGE: -// -// throw new IllegalStateException("Not implemented"); -// } -// -// if (!errors.isEmpty()) { -// -// throw new InvalidFormException(errors); -// -// } -// -// } - protected ErrorMap checkChoice(List<Choice> existingChoices, Choice choice) { ErrorMap errors = new ErrorMap(); @@ -276,8 +245,11 @@ if (choiceExists && choice1.getTopiaId().equals(choice.getTopiaId())) { + continue; + } + choiceNames.add(choice1.getName()); } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,9 +23,7 @@ * #L% */ -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimap; import org.apache.commons.lang3.StringUtils; import org.chorem.pollen.persistence.entity.Comment; import org.chorem.pollen.persistence.entity.Poll; @@ -72,15 +70,15 @@ checkIsNotPersisted(comment); checkPermission(PermissionVerb.addComment, pollId); - Poll poll = getPollService().getPoll(pollId); + ErrorMap errorMap = checkComment(comment); + errorMap.failIfNotEmpty(); - checkCommentForm(comment); - + Poll poll = getPollService().getPoll(pollId); Comment result = saveComment(poll, comment); - - getPollDao().update(poll); commit(); + getNotificationService().onCommentAdded(poll, result); + return result; } @@ -92,15 +90,15 @@ checkIsPersisted(comment); checkPermission(PermissionVerb.editComment, comment.getTopiaId()); - Poll poll = getPollService().getPoll(pollId); + ErrorMap errorMap = checkComment(comment); + errorMap.failIfNotEmpty(); - checkCommentForm(comment); - + Poll poll = getPollService().getPoll(pollId); Comment result = saveComment(poll, comment); - - getCommentDao().update(comment); commit(); + getNotificationService().onCommentEdited(poll, result); + return result; } @@ -118,6 +116,8 @@ getCommentDao().delete(comment); commit(); + getNotificationService().onCommentDeleted(poll, comment); + } protected Comment getComment(Poll poll, String commentId) { @@ -134,10 +134,9 @@ } - protected void checkCommentForm(Comment comment) throws InvalidFormException { + protected ErrorMap checkComment(Comment comment) { - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); + ErrorMap errors = new ErrorMap(); checkNotBlank(errors, "text", comment.getText(), "textcan not be empty"); boolean authorNotNull = checkNotNull(errors, "author", comment.getAuthor(), "author can not be null"); @@ -147,12 +146,8 @@ } - if (!errors.isEmpty()) { + return errors; - throw new InvalidFormException(errors); - - } - } protected Comment saveComment(Poll poll, Comment comment) { @@ -167,7 +162,7 @@ } else { - toSave = getCommentDao().newInstance(); + toSave = getCommentDao().create(); toSave.setPostDate(serviceContext.getNow()); // -- author -- // Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ErrorMap.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ErrorMap.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ErrorMap.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.services.service; +/* + * #%L + * Pollen :: Service + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,13 +23,16 @@ * #L% */ -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; +import org.chorem.pollen.persistence.entity.FavoriteListMemberTopiaDao; +import org.chorem.pollen.persistence.entity.FavoriteListTopiaDao; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.services.PollenTechnicalException; import org.nuiton.util.StringUtil; @@ -46,7 +49,7 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.LinkedHashSet; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -68,7 +71,8 @@ PollenUser user = getConnectedUser(); List<FavoriteList> result = user.getFavoriteList(); - return result; + return ImmutableList.copyOf(result); + } public FavoriteList getFavoriteList(String favoriteListId) { @@ -80,6 +84,7 @@ FavoriteList result = getFavoriteList(user, favoriteListId); return result; + } public FavoriteList createFavoriteList(FavoriteList favoriteList) throws InvalidFormException { @@ -90,16 +95,17 @@ PollenUser user = getConnectedUser(); - checkFavoriteListForm(user, favoriteList); + List<FavoriteList> existingFavoriteLists = new ArrayList<>(user.getFavoriteList()); - FavoriteList toSave = getFavoriteListDao().newInstance(); - copyFavoriteList(favoriteList, toSave); + ErrorMap errorMap = checkFavoriteList(existingFavoriteLists, favoriteList); + errorMap.failIfNotEmpty(); - user.addFavoriteList(toSave); - getPollenUserDao().update(user); + FavoriteList result = saveFavoriteList(user, favoriteList); + commit(); - commit(); - return toSave; + getNotificationService().onFavoriteListAdded(user, favoriteList); + + return result; } public FavoriteList editFavoriteList(FavoriteList favoriteList) throws InvalidFormException { @@ -108,20 +114,19 @@ checkNotNull(favoriteList); checkIsPersisted(favoriteList); - // get user PollenUser user = getConnectedUser(); - // get list to save - FavoriteList toSave = getFavoriteList(user, favoriteList.getTopiaId()); + List<FavoriteList> existingFavoriteLists = new ArrayList<>(user.getFavoriteList()); - checkFavoriteListForm(user, favoriteList); + ErrorMap errorMap = checkFavoriteList(existingFavoriteLists, favoriteList); + errorMap.failIfNotEmpty(); + FavoriteList result = saveFavoriteList(user, favoriteList); + commit(); - copyFavoriteList(favoriteList, toSave); + getNotificationService().onFavoriteListEdited(user, favoriteList); - getFavoriteListDao().update(toSave); - commit(); - return toSave; + return result; } public void deleteFavoriteList(String favoriteListId) { @@ -131,15 +136,16 @@ PollenUser user = getConnectedUser(); - FavoriteList persisted = getFavoriteList(user, favoriteListId); + FavoriteList favoriteList = getFavoriteList(user, favoriteListId); - user.removeFavoriteList(persisted); + user.removeFavoriteList(favoriteList); + commit(); - getPollenUserDao().update(user); - commit(); + getNotificationService().onFavoriteListDeleted(user, favoriteList); + } - public LinkedHashSet<FavoriteListMember> getFavoriteListMembers(String favoriteListId) { + public Set<FavoriteListMember> getFavoriteListMembers(String favoriteListId) { checkIsConnected(); checkNotNull(favoriteListId); @@ -148,7 +154,9 @@ FavoriteList favoriteList = getFavoriteList(user, favoriteListId); - return favoriteList.getMember(); + Set<FavoriteListMember> member = favoriteList.getMember(); + return ImmutableSet.copyOf(member); + } public FavoriteListMember getFavoriteListMember(String favoriteListId, String memberId) { @@ -163,6 +171,7 @@ FavoriteListMember result = getFavoriteListMember(favoriteList, memberId); return result; + } public FavoriteListMember addFavoriteListMember(String favoriteListId, @@ -177,17 +186,16 @@ FavoriteList favoriteList = getFavoriteList(user, favoriteListId); - checkFavoriteListMemberForm(favoriteList, member); + List<FavoriteListMember> existingFavorliteListMembers = new ArrayList<>(); - FavoriteListMember newMember = - getFavoriteListMemberDao().newInstance(); - copyFavoriteListMember(member, newMember); - favoriteList.addMember(newMember); + ErrorMap errorMap = checkFavoriteListMember(existingFavorliteListMembers, member); + errorMap.failIfNotEmpty(); - getFavoriteListDao().update(favoriteList); + FavoriteListMember result = saveFavoriteListMember(favoriteList, member); + commit(); - commit(); - return newMember; + return result; + } public FavoriteListMember editFavoriteListMember(String favoriteListId, @@ -202,21 +210,19 @@ FavoriteList favoriteList = getFavoriteList(user, favoriteListId); - String memberId = member.getTopiaId(); + List<FavoriteListMember> existingFavorliteListMembers = new ArrayList<>(); - FavoriteListMember toSave = getFavoriteListMember(favoriteList, memberId); + ErrorMap errorMap = checkFavoriteListMember(existingFavorliteListMembers, member); + errorMap.failIfNotEmpty(); - checkFavoriteListMemberForm(favoriteList, member); + FavoriteListMember result = saveFavoriteListMember(favoriteList, member); + commit(); - copyFavoriteListMember(member, toSave); + return result; - getFavoriteListMemberDao().update(toSave); - - commit(); - return toSave; } - public void removeFavoriteListMember(String favoriteListId, + public void deleteFavoriteListMember(String favoriteListId, String memberId) { checkIsConnected(); @@ -233,6 +239,7 @@ getFavoriteListDao().update(favoriteList); commit(); + } public int importFavoriteListMembersFromCsv(String favoriteListId, @@ -449,104 +456,139 @@ } - protected void copyFavoriteList(FavoriteList source, - FavoriteList destination) { + protected FavoriteList saveFavoriteList(PollenUser user, FavoriteList favoriteList) { - destination.setName(source.getName()); + FavoriteListTopiaDao favoriteListDao = getFavoriteListDao(); + + boolean persisted = favoriteList.isPersisted(); + + FavoriteList toSave; + + if (persisted) { + + // get existing favorite list + toSave = getFavoriteList(user, favoriteList.getTopiaId()); + + } else { + + // create a new favorite list + toSave = favoriteListDao.create(); + + user.addFavoriteList(toSave); + + } + + toSave.setName(favoriteList.getName()); + + return toSave; + } - protected void copyFavoriteListMember(FavoriteListMember source, - FavoriteListMember destination) { + protected FavoriteListMember saveFavoriteListMember(FavoriteList favoriteList, FavoriteListMember favoriteListMember) { - destination.setName(source.getName()); - destination.setEmail(StringUtils.lowerCase(source.getEmail())); + FavoriteListMemberTopiaDao favoriteListDao = getFavoriteListMemberDao(); + + boolean persisted = favoriteListMember.isPersisted(); + + FavoriteListMember toSave; + + if (persisted) { + + // get existing favorite list + toSave = getFavoriteListMember(favoriteList, favoriteListMember.getTopiaId()); + + } else { + + // create a new favorite list + toSave = favoriteListDao.create(); + + favoriteList.addMember(toSave); + + } + + toSave.setName(favoriteListMember.getName()); + toSave.setEmail(StringUtils.lowerCase(favoriteListMember.getEmail())); + + return toSave; } - protected void checkFavoriteListForm(PollenUser user, FavoriteList favoriteList) throws InvalidFormException { + protected ErrorMap checkFavoriteList(List<FavoriteList> existingFavoriteLists, FavoriteList favoriteList) { - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); + ErrorMap errors = new ErrorMap(); String favoriteListName = favoriteList.getName(); - // can't accept favorite list without name checkNotBlank(errors, "name", favoriteListName, "name can not be empty"); + boolean favoriteListExists = favoriteList.isPersisted(); - // check there is not already a favorite list with same name - boolean nameFound = false; - if (!user.isFavoriteListEmpty()) { - for (FavoriteList list : user.getFavoriteList()) { - if (favoriteListName.equals(list.getName())) { - nameFound = true; - break; + Set<String> favoriteListNames = Sets.newHashSet(); + + if (CollectionUtils.isNotEmpty(existingFavoriteLists)) { + + // get all used names + + for (FavoriteList favoriteList1 : existingFavoriteLists) { + + if (favoriteListExists && + favoriteList1.getTopiaId().equals(favoriteList.getTopiaId())) { + + continue; + } + + favoriteListNames.add(favoriteList1.getName()); + } + } - check(errors, "name", !nameFound, "name already used by another favorite list"); + boolean nameAdded = favoriteListNames.add(favoriteListName); + check(errors, "name", nameAdded, "name already used by another favorite list"); - if (!favoriteList.isMemberEmpty()) { + if (CollectionUtils.isNotEmpty(favoriteList.getMember())) { int memberIndex = 0; - Set<String> memberNames = Sets.newHashSet(); - Set<String> memberEmails = Sets.newHashSet(); + List<FavoriteListMember> existingFavoriteListMembers = new ArrayList<>(favoriteList.getMember()); for (FavoriteListMember member : favoriteList.getMember()) { - String choiceField = "favoriteListMember[" + (memberIndex++) + "]."; + ErrorMap favoriteListMemberErrors = checkFavoriteListMember(existingFavoriteListMembers, member); + favoriteListMemberErrors.copyTo(errors, "favoriteListMember[" + (memberIndex++) + "]."); - boolean nameNotBlank = checkNotBlank(errors, choiceField + "name", member.getName(), "member name can not be empty"); - if (nameNotBlank) { - boolean added = memberNames.add(member.getName()); - - check(errors, choiceField + "name", added, "member name already used"); - } - - String memberEmail = getCleanMail(member.getEmail()); - - boolean emailNotBlank = checkNotBlank(errors, choiceField + "email", memberEmail, "member email can not be empty"); - - if (emailNotBlank) { - - checkValidEmail(errors, choiceField + "email", memberEmail, "member email is not valid"); - boolean emailAdded = memberEmails.add(memberEmail); - check(errors, choiceField + "email", emailAdded, "member email already used in this list"); - } } } - if (!errors.isEmpty()) { + return errors; - throw new InvalidFormException(errors); - } } + protected ErrorMap checkFavoriteListMember(List<FavoriteListMember> existingFavoriteListMember, FavoriteListMember favoriteListMember) { - protected void checkFavoriteListMemberForm(FavoriteList favoriteList, FavoriteListMember favoriteListMember) throws InvalidFormException { + ErrorMap errors = new ErrorMap(); - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); - boolean voterListMemberExists = favoriteListMember.isPersisted(); Set<String> memberNames = Sets.newHashSet(); Set<String> memberEmails = Sets.newHashSet(); - if (!favoriteList.isMemberEmpty()) { + if (CollectionUtils.isNotEmpty(existingFavoriteListMember)) { - // get all used names + // get all used names / emails - for (FavoriteListMember member : favoriteList.getMember()) { + for (FavoriteListMember favoriteListMember1 : existingFavoriteListMember) { - if (voterListMemberExists && member.getTopiaId().equals(member.getTopiaId())) { + if (voterListMemberExists && + favoriteListMember1.getTopiaId().equals(favoriteListMember1.getTopiaId())) { continue; } - memberNames.add(member.getName()); - memberEmails.add(member.getEmail()); + memberNames.add(favoriteListMember1.getName()); + memberEmails.add(favoriteListMember1.getEmail()); + } + } boolean nameNotBlank = checkNotBlank(errors, "name", favoriteListMember.getName(), "member name can not be empty"); @@ -562,15 +604,17 @@ if (emailNotBlank) { boolean emailValid = checkValidEmail(errors, "email", memberEmail, "member email is not valid"); + if (emailValid) { + boolean emailAdded = memberEmails.add(memberEmail); check(errors, "email", emailAdded, "member email already used in this list"); + } + } - if (!errors.isEmpty()) { + return errors; - throw new InvalidFormException(errors); - } } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.services.service; +/* + * #%L + * Pollen :: Service + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import org.chorem.pollen.services.PollenTechnicalException; import org.nuiton.topia.persistence.TopiaEntity; Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,6 +23,7 @@ import org.chorem.pollen.persistence.entity.Choice; import org.chorem.pollen.persistence.entity.Comment; +import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.Vote; @@ -35,38 +36,42 @@ */ public class NotificationService extends PollenServiceSupport { - public enum NotificationType { + public void onUserCreated(PollenUser user, boolean generatePassword) { + // TODO + } - // -- poll -- // - createPoll, - editPoll, - deletePoll, - closePoll, + public void onUserEdited(PollenUser user) { + // TODO + } - // -- choice -- // - addChoice, - editChoice, - deleteChoice, + public void onUserDeleted(PollenUser user) { + // TODO + } - // -- comment -- // - addComment, - editComment, - deleteComment, + public void onUserPasswordChanged(PollenUser user, String newPassword) { + // TODO + } - // -- vote -- // - addVote, - editVote, - deleteVote, + public void onUserEmailValidated(PollenUser user) { + // TODO } - public void onAccountCreated(PollenUser pollenUser) { + public void onUserLostPasswordAsked(PollenUser user, String newPassword) { } - public void onLostPasswordAsked(PollenUser pollenUser) { + public void onFavoriteListAdded(PollenUser user, FavoriteList favoriteList) { + // TODO + } + public void onFavoriteListEdited(PollenUser user, FavoriteList favoriteList) { + // TODO } + public void onFavoriteListDeleted(PollenUser user, FavoriteList favoriteList) { + // TODO + } + public void onPollCreated(Poll poll) { } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -53,7 +53,7 @@ // checkIsAdmin(); List<Poll> polls = getPollDao().findAll(); - return ImmutableSet.copyOf(polls); + return copyAsSet(polls); } @@ -64,7 +64,7 @@ PollenUser connectedUser = getConnectedUser(); Set<Poll> polls = getPollDao().findAllCreated(connectedUser); - return ImmutableSet.copyOf(polls); + return copyAsSet(polls); } @@ -75,7 +75,7 @@ PollenUser connectedUser = getConnectedUser(); Set<Poll> polls = getPollDao().findAllInvited(connectedUser); - return ImmutableSet.copyOf(polls); + return copyAsSet(polls); } @@ -86,7 +86,7 @@ PollenUser connectedUser = getConnectedUser(); Set<Poll> polls = getPollDao().findAllParticipated(connectedUser); - return ImmutableSet.copyOf(polls); + return copyAsSet(polls); } @@ -96,8 +96,15 @@ checkPermission(PermissionVerb.readPoll, pollId); Poll result = getPollDao().findByTopiaId(pollId); - return result; + if (isNotPermitted(PermissionVerb.editPoll, pollId)) { + + // remove creator informations + result.setCreator(null); + } + + return copy(result); + } public Poll getNewPoll() { @@ -123,6 +130,7 @@ creator.setName(connectedUser.getName()); creator.setEmail(connectedUser.getEmail()); + } return result; @@ -136,17 +144,15 @@ ErrorMap errorMap = checkPoll(poll); checkChoices(errorMap, choices); - checkvoterLists(errorMap, poll, voterLists); + checkVoterLists(errorMap, poll, voterLists); errorMap.failIfNotEmpty(); Poll savedPoll = savePoll(poll, choices, voterLists); - - getPollDao().create(savedPoll); commit(); getNotificationService().onPollCreated(poll); - return savedPoll; + return copy(savedPoll); } @@ -160,13 +166,11 @@ errorMap.failIfNotEmpty(); Poll savedPoll = savePoll(poll, null, null); - - getPollDao().update(savedPoll); commit(); getNotificationService().onPollEdited(poll); - return savedPoll; + return copy(savedPoll); } @@ -175,7 +179,7 @@ checkNotNull(pollId); checkPermission(PermissionVerb.deletePoll, pollId); - Poll poll = getPoll(pollId); + Poll poll = getPollDao().findByTopiaId(pollId); getPollDao().delete(poll); commit(); @@ -241,7 +245,7 @@ } else { - toSave = getPollDao().newInstance(); + toSave = getPollDao().create(); existingChoices = new ArrayList<>(); PollenPrincipal creatorToPersist = @@ -305,7 +309,7 @@ } } - // -- voting list -- // + // -- voter list -- // if (CollectionUtils.isNotEmpty(voterLists)) { @@ -322,151 +326,8 @@ } -// protected void checkPollForm(Poll poll, List<Choice> choices, List<VoterList> voterLists) throws InvalidFormException { -// -// //TODO use nuiton validator ? -// Multimap<String, String> errors = ArrayListMultimap.create(); -// -// checkNotNull(errors, Poll.PROPERTY_POLL_TYPE, poll.getPollType(), "pollType can not be null"); -// checkNotNull(errors, Poll.PROPERTY_COMMENT_VISIBILITY, poll.getCommentVisibility(), "commentVisibility can not be null"); -// checkNotNull(errors, Poll.PROPERTY_VOTE_VISIBILITY, poll.getVoteVisibility(), "voteVisibility can not be null"); -// checkNotNull(errors, Poll.PROPERTY_VOTE_COUNTING_TYPE, poll.getVoteCountingType(), "voteCountingType can not be null"); -// -// checkNotBlank(errors, Poll.PROPERTY_TITLE, poll.getTitle(), "title can not be empty"); -// -// if (!poll.isPersisted()) { -// -// // check choices -// checkNotEmpty(errors, "choice", choices, "need at least one choice"); -// -// if (CollectionUtils.isNotEmpty(choices)) { -// -// // validate choices -// -// Set<String> choiceNames = new HashSet<>(); -// int choiceIndex = 0; -// -// for (Choice choice : choices) { -// -// String choiceField = "choice" + "[" + (choiceIndex++) + "]."; -// -// checkNotNull(errors, -// choiceField + Choice.PROPERTY_CHOICE_TYPE, -// choice.getChoiceType(), -// "choiceType can not be null"); -// if (choice.getChoiceType() != null) { -// switch (choice.getChoiceType()) { -// -// case TEXT: -// -// boolean checkNotBlank = checkNotBlank(errors, -// choiceField + Choice.PROPERTY_NAME, -// choice.getName(), -// "choice name can not be empty"); -// -// if (checkNotBlank) { -// -// // check duplicated name -// -// check(errors, -// choiceField + Choice.PROPERTY_NAME, -// choiceNames.add(choice.getName()), -// "Duplicated choice name"); -// } -// break; -// case DATE: -// throw new IllegalStateException("Not implemented"); -// -// case IMAGE: -// throw new IllegalStateException("Not implemented"); -// } -// } -// } -// } -// -// -// // check voter lists -// -// if (Polls.isPollFree(poll)) { -// checkEmpty(errors, "voterList", voterLists, "can't have voterList with free poll"); -// } else if (Polls.isPollRestricted(poll)) { -// check(errors, "voterList", voterLists != null && 1 == voterLists.size(), "must have a unique voterList with a resitricted poll"); -// } else if (Polls.isPollGroup(poll)) { -// checkNotEmpty(errors, "voterList", voterLists, "must have at least one voterList with a group poll"); -// } -// -// -// if (CollectionUtils.isNotEmpty(voterLists)) { -// -// Set<String> voterListNames = Sets.newHashSet(); -// -// // validate voter lists -// -// int voterListIndex = 0; -// -// for (VoterList voterList : voterLists) { -// -// String voterListField = "voterList" + "[" + (voterListIndex++) + "]."; -// -// boolean notBlankName = checkNotBlank(errors, voterListField + VoterList.PROPERTY_NAME, voterList.getName(), "voterList name can not be empty"); -// -// if (notBlankName) { -// boolean added = voterListNames.add(voterList.getName()); -// -// check(errors, voterListField + VoterList.PROPERTY_NAME, added, "voterList name already used"); -// } -// check(errors, voterListField + VoterList.PROPERTY_WEIGHT, voterList.getWeight() > 0, "voterList weight must be greater than 0"); -// boolean withMember = checkNotEmpty(errors, voterListField + VoterList.PROPERTY_MEMBER, voterList.getMember(), "voterList must contains at least one member"); -// -// if (withMember) { -// Set<String> voterListMemberNames = Sets.newHashSet(); -// Set<String> voterListMemberEmails = Sets.newHashSet(); -// -// int voterListMemberIndex = 0; -// -// for (VoterListMember voterListMember : voterList.getMember()) { -// -// String voterListMemberField = voterListField + VoterList.PROPERTY_MEMBER + "[" + (voterListMemberIndex++) + "]."; -// -// String voterListMemberName = voterListMember.getName(); -// boolean nameNotNull = checkNotBlank(errors, voterListMemberField + VoterListMember.PROPERTY_NAME, voterListMemberName, "member name can not be empty"); -// -// if (nameNotNull) { -// boolean nameAdded = voterListMemberNames.add(voterListMemberName); -// check(errors, voterListMemberField + VoterListMember.PROPERTY_NAME, nameAdded, "member name already used in this list"); -// } -// -// String voterListMemberEmail = voterListMember.getEmail(); -// -// boolean emailNotNull = checkNotBlank(errors, voterListMemberField + VoterListMember.PROPERTY_EMAIL, voterListMemberEmail, "member email can not be empty"); -// -// if (emailNotNull) { -// -// voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail); -// -// checkValidEmail(errors, voterListMemberField + VoterListMember.PROPERTY_EMAIL, voterListMemberEmail, "member email is not valid"); -// boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail); -// check(errors, voterListMemberField + VoterListMember.PROPERTY_EMAIL, emailAdded, "member email already used in this list"); -// } -// -// check(errors, voterListMemberField + VoterListMember.PROPERTY_WEIGHT, voterListMember.getWeight() > 0, "member weight must be greater than 0"); -// } -// } -// } -// } -// } -// -// if (!errors.isEmpty()) { -// -// throw new InvalidFormException(errors); -// -// } -// -// } - protected ErrorMap checkPoll(Poll poll) { - //TODO use nuiton validator ? ErrorMap errors = new ErrorMap(); checkNotNull(errors, Poll.PROPERTY_POLL_TYPE, poll.getPollType(), "pollType can not be null"); @@ -480,7 +341,6 @@ } - protected void checkChoices(ErrorMap errorMap, List<Choice> choices) { boolean choicesNotEmpty = CollectionUtils.isNotEmpty(choices); @@ -505,7 +365,7 @@ } } - protected void checkvoterLists(ErrorMap errorMap, Poll poll, List<VoterList> voterLists) { + protected void checkVoterLists(ErrorMap errorMap, Poll poll, List<VoterList> voterLists) { boolean voterListsNotEmpty = CollectionUtils.isNotEmpty(voterLists); @@ -515,7 +375,7 @@ } else if (Polls.isPollRestricted(poll)) { - check(errorMap, "voterList", voterListsNotEmpty && 1 == voterLists.size(), "must have a unique voterList with a resitricted poll"); + check(errorMap, "voterList", voterListsNotEmpty && 1 == voterLists.size(), "must have a unique voterList with a restricted poll"); } else if (Polls.isPollGroup(poll)) { @@ -533,7 +393,7 @@ ErrorMap voterListErrors = getVoterListService().checkVoterList(existingVoterLists, voterList); - voterListErrors.copyTo(errorMap, "voterList[" + i + "]."); + voterListErrors.copyTo(errorMap, "voterList[" + (i++) + "]."); existingVoterLists.add(voterList); @@ -542,4 +402,5 @@ } } + } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenPrincipalRef.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenPrincipalRef.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenPrincipalRef.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.services.service; +/* + * #%L + * Pollen :: Service + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.PollenPrincipals; import org.nuiton.topia.persistence.TopiaEntity; Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -24,6 +24,8 @@ */ import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -43,6 +45,7 @@ import org.chorem.pollen.persistence.entity.VoterListTopiaDao; import org.chorem.pollen.services.PollenService; import org.chorem.pollen.services.PollenServiceContext; +import org.chorem.pollen.services.TopiaEntityCopyVisitor; import org.chorem.pollen.services.config.PollenServiceConfig; import org.chorem.pollen.services.service.mail.EmailService; import org.chorem.pollen.services.service.security.PermissionVerb; @@ -207,112 +210,197 @@ // -- check method -- // - protected PollenUser getConnectedUser() { - return serviceContext.getSecurityContext().getPollenUser(); - } - public void checkIsConnected() { - getSecurityService().checkIsConnected(); - } public void checkIsAdmin() { - getSecurityService().checkIsAdmin(); - } protected void checkPermission(PermissionVerb verb, String id) { + String permission = getSecurityService().createPermission(verb, id); getSecurityService().checkPermission(permission); + } + protected boolean isPermitted(PermissionVerb verb, String id) { + + String permission = getSecurityService().createPermission(verb, id); + boolean permitted = getSecurityService().isPermitted(permission); + return permitted; + + } + + protected boolean isNotPermitted(PermissionVerb verb, String id) { + + boolean notPermietted = !isPermitted(verb, id); + return notPermietted; + + } + protected void checkNotNull(Object object) { + Preconditions.checkNotNull(object); + } protected void checkIsPersisted(TopiaEntity entity) { + Preconditions.checkState(entity.isPersisted()); + } protected void checkIsNotPersisted(TopiaEntity entity) { + Preconditions.checkState(!entity.isPersisted()); + } protected boolean check(Multimap<String, String> errors, String field, boolean condition, String error) { + boolean valid = condition; if (!valid) { errors.put(field, error); } return valid; + } protected boolean checkNot(Multimap<String, String> errors, String field, boolean condition, String error) { + boolean valid = check(errors, field, !condition, error); return valid; + } protected boolean checkNotNull(Multimap<String, String> errors, String field, Object value, String error) { + boolean valid = check(errors, field, value != null, error); return valid; + } protected boolean checkEmpty(Multimap<String, String> errors, String field, Collection<?> value, String error) { + boolean valid = check(errors, field, CollectionUtils.isEmpty(value), error); return valid; + } protected boolean checkNotEmpty(Multimap<String, String> errors, String field, Collection<?> value, String error) { + boolean valid = check(errors, field, CollectionUtils.isNotEmpty(value), error); return valid; + } protected boolean checkNotBlank(Multimap<String, String> errors, String field, String value, String error) { + boolean valid = check(errors, field, StringUtils.isNotBlank(value), error); return valid; + } protected boolean checkValidEmail(Multimap<String, String> errors, String field, String value, String error) { + boolean valid = check(errors, field, StringUtil.isEmail(value), error); return valid; + } protected boolean checkNot(ErrorMap errors, String field, boolean condition, String error) { + boolean valid = check(errors, field, !condition, error); return valid; + } protected boolean checkNotNull(ErrorMap errors, String field, Object value, String error) { + boolean valid = check(errors, field, value != null, error); return valid; + } protected boolean checkEmpty(ErrorMap errors, String field, Collection<?> value, String error) { + boolean valid = check(errors, field, CollectionUtils.isEmpty(value), error); return valid; + } protected boolean checkNotEmpty(ErrorMap errors, String field, Collection<?> value, String error) { + boolean valid = check(errors, field, CollectionUtils.isNotEmpty(value), error); return valid; + } protected boolean checkNotBlank(ErrorMap errors, String field, String value, String error) { + boolean valid = check(errors, field, StringUtils.isNotBlank(value), error); return valid; + } protected boolean checkValidEmail(ErrorMap errors, String field, String value, String error) { + boolean valid = check(errors, field, StringUtil.isEmail(value), error); return valid; + } protected boolean check(ErrorMap errors, String field, boolean condition, String error) { + boolean valid = condition; if (!valid) { errors.addError(field, error); } return valid; + } + + protected PollenUser getConnectedUser() { + + PollenUser pollenUser = serviceContext.getSecurityContext().getPollenUser(); + return pollenUser; + + } + + protected <T extends TopiaEntity> T copy(T entity) { + + T copy = null; + + if (entity != null) { + + copy = TopiaEntityCopyVisitor.copy(serviceContext.getTopiaApplicationContext(), entity); + } + + return copy; + + } + + protected <T extends TopiaEntity> ImmutableList<T> copyAsList(Collection<T> entity) { + + Collection<T> copy = TopiaEntityCopyVisitor.copy(serviceContext.getTopiaApplicationContext(), entity); + + ImmutableList<T> result = ImmutableList.copyOf(copy); + + return result; + + } + + protected <T extends TopiaEntity> ImmutableSet<T> copyAsSet(Collection<T> entity) { + + Collection<T> copy = TopiaEntityCopyVisitor.copy(serviceContext.getTopiaApplicationContext(), entity); + + copy = ImmutableSet.copyOf(copy); + + ImmutableSet<T> result = ImmutableSet.copyOf(copy); + + return result; + + } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,8 +23,6 @@ * #L% */ -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; import org.apache.commons.lang3.ObjectUtils; import org.chorem.pollen.persistence.entity.PollenToken; import org.chorem.pollen.persistence.entity.PollenUser; @@ -50,7 +48,7 @@ // checkIsAdmin(); List<PollenUser> pollenUsers = getPollenUserDao().findAll(); - return pollenUsers; + return copyAsList(pollenUsers); } @@ -59,60 +57,55 @@ checkNotNull(userId); PollenUser result = getPollenUserDao().findByTopiaId(userId); - return result; + return copy(result); } - public PollenUser getUserByLogin(String login) { - - checkNotNull(login); - - PollenUser result = getPollenUserDao().forLoginEquals(login).findUnique(); - return result; - - } - public PollenUser createUser(PollenUser user, boolean generatePassword) throws InvalidFormException { checkNotNull(user); checkIsNotPersisted(user); - checkPollenUserForm(user); + ErrorMap errorMap = checkPollenUser(user); + errorMap.failIfNotEmpty(); + PollenUser result = savePollenUser(user, generatePassword); - - getPollenUserDao().create(result); commit(); - //TODO Notify user created - return result; + getNotificationService().onUserCreated(result, generatePassword); + return copy(result); + } public PollenUser editUser(PollenUser user) throws InvalidFormException { checkNotNull(user); checkIsPersisted(user); - checkPollenUserForm(user); + ErrorMap errorMap = checkPollenUser(user); + errorMap.failIfNotEmpty(); + PollenUser result = savePollenUser(user, false); - - getPollenUserDao().update(result); commit(); - //TODO Notify user edited - return result; + getNotificationService().onUserEdited(user); + return copy(result); + } public void deleteUser(String userId) { checkNotNull(userId); - PollenUser user = getUser(userId); + PollenUser user = getPollenUserDao().findByTopiaId(userId); getPollenUserDao().delete(user); commit(); + getNotificationService().onUserDeleted(user); + } public void changePassword(String userId, @@ -123,7 +116,7 @@ checkNotNull(oldPassword); checkNotNull(newPassword); - PollenUser user = getUser(userId); + PollenUser user = getPollenUserDao().findByTopiaId(userId); // check old password getSecurityService().checkUserPassword(user, oldPassword); @@ -131,10 +124,10 @@ // set new password getSecurityService().setUserPassword(user, newPassword); - getPollenUserDao().update(user); commit(); - //TODO Notify PasswordChanged + getNotificationService().onUserPasswordChanged(user, newPassword); + } public void validateUserEmail(String userId, @@ -143,7 +136,7 @@ checkNotNull(userId); checkNotNull(token); - PollenUser user = getUser(userId); + PollenUser user = getPollenUserDao().findByTopiaId(userId); getSecurityService().checkUserEmailValidation(user, token); @@ -152,6 +145,8 @@ commit(); + getNotificationService().onUserEmailValidated(user); + } public void createDefaultUsers() throws InvalidFormException { @@ -171,10 +166,9 @@ } - protected void checkPollenUserForm(PollenUser user) throws InvalidFormException { + protected ErrorMap checkPollenUser(PollenUser user) throws InvalidFormException { - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); + ErrorMap errors = new ErrorMap(); boolean userExists = user.isPersisted(); PollenUser persisted = userExists ? getUser(user.getTopiaId()) : null; @@ -186,12 +180,15 @@ boolean loginNotBlank = checkNotBlank(errors, "login", userLogin, "login can not be empty"); if (loginNotBlank && !userExists) { + check(errors, "login", !dao.loginExists(userLogin), "login already exists"); + } boolean emailNotblank = checkNotBlank(errors, "email", userEmail, "email can not be empty"); if (emailNotblank) { + checkValidEmail(errors, "email", userEmail, "email is not valid"); @@ -203,31 +200,37 @@ userEmail); if (emailChanged) { + check(errors, "email", !dao.emailExists(userEmail), "email already exists"); + } } else { + check(errors, "email", !dao.emailExists(userEmail), "email already exists"); + } + } if (userExists) { // check current password + try { + getSecurityService().checkUserPassword(persisted, user.getPassword()); + } catch (PollenInvalidPasswordException e) { + check(errors, "password", false, "invalid password"); + } } - if (!errors.isEmpty()) { + return errors; - throw new InvalidFormException(errors); - - } - } protected PollenUser savePollenUser(PollenUser user, boolean generatePassword) { @@ -240,7 +243,7 @@ if (userExists) { - toSave = getUser(user.getTopiaId()); + toSave = getPollenUserDao().findByTopiaId(user.getTopiaId()); boolean emailChanged = !Objects.equals(toSave.getEmail(), cleanMail); @@ -267,7 +270,7 @@ PollenToken emailActivation = getSecurityService().generateNewToken(); - toSave = getPollenUserDao().newInstance(); + toSave = getPollenUserDao().create(); toSave.setLogin(user.getLogin()); toSave.setEmailActivationToken(emailActivation); @@ -283,4 +286,5 @@ return toSave; } + } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,9 +23,7 @@ * #L% */ -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimap; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.Polls; import org.chorem.pollen.persistence.entity.Vote; @@ -74,14 +72,14 @@ Poll poll = getPollService().getPoll(pollId); - checkVoteForm(poll, vote); + ErrorMap errorMap = checkVote(poll, vote); + errorMap.failIfNotEmpty(); Vote result = saveVote(poll, vote); - - getPollDao().update(poll); commit(); - //TODO Notify vote added + getNotificationService().onVoteAdded(poll, result); + return result; } @@ -94,14 +92,14 @@ Poll poll = getPollService().getPoll(pollId); - checkVoteForm(poll, vote); + ErrorMap errorMap = checkVote(poll, vote); + errorMap.failIfNotEmpty(); Vote result = saveVote(poll, vote); - - getVoteDao().update(vote); commit(); - //TODO Notify vote edited + getNotificationService().onVoteEdited(poll, result); + return result; } @@ -115,17 +113,17 @@ Poll poll = getPollService().getPoll(pollId); Vote vote = getVote(poll, voteId); - + getVoteDao().delete(vote); commit(); - //TODO Notify vote deleted + getNotificationService().onVoteDeleted(poll, vote); + } - protected void checkVoteForm(Poll poll, Vote vote) throws InvalidFormException { + protected ErrorMap checkVote(Poll poll, Vote vote) { - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); + ErrorMap errors = new ErrorMap(); // poll can't be closed checkNot(errors, "poll", poll.isClosed(), "poll can not be closed"); @@ -139,12 +137,8 @@ //TODO Finish validation - if (!errors.isEmpty()) { + return errors; - throw new InvalidFormException(errors); - - } - } protected Vote saveVote(Poll poll, Vote vote) { @@ -157,9 +151,10 @@ if (voteExist) { toSave = getVote(poll, vote.getTopiaId()); + } else { - toSave = getVoteDao().newInstance(); + toSave = getVoteDao().create(); // toSave.setPostDate(serviceContext.getNow()); // -- author -- // @@ -195,4 +190,5 @@ return result; } + } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -23,9 +23,7 @@ * #L% */ -import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import org.apache.commons.collections4.CollectionUtils; import org.chorem.pollen.persistence.entity.FavoriteList; @@ -36,6 +34,7 @@ import org.chorem.pollen.persistence.entity.VoterListMemberTopiaDao; import org.chorem.pollen.persistence.entity.VoterListTopiaDao; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -59,7 +58,7 @@ FavoriteList favoriteList = getFavoriteListService().getFavoriteList(favoriteListId); VoterListTopiaDao dao = getVoterListDao(); - VoterList result = dao.newInstance(); + VoterList result = dao.create(); result.setName(favoriteList.getName()); result.setWeight(1d); @@ -76,7 +75,6 @@ } result.setPoll(poll); - getPollDao().update(poll); commit(); return result; @@ -113,11 +111,13 @@ Poll poll = getPollService().getPoll(pollId); - checkVoterListForm(poll, voterList); + List<VoterList> existingVoterLists = getVoterListDao().forPollEquals(poll).findAll(); - VoterList result = saveVoterList(poll, voterList); + ErrorMap errorMap = checkVoterList(existingVoterLists, voterList); + errorMap.failIfNotEmpty(); - getPollDao().update(poll); + + VoterList result = saveVoterList(poll, voterList); commit(); return result; @@ -132,11 +132,12 @@ Poll poll = getPollService().getPoll(pollId); - checkVoterListForm(poll, voterList); + List<VoterList> existingVoterLists = getVoterListDao().forPollEquals(poll).findAll(); - VoterList result = saveVoterList(poll, voterList); + ErrorMap errorMap = checkVoterList(existingVoterLists, voterList); + errorMap.failIfNotEmpty(); - getVoterListDao().update(voterList); + VoterList result = saveVoterList(poll, voterList); commit(); return result; @@ -151,7 +152,6 @@ Poll poll = getPollService().getPoll(pollId); VoterList voterList = getVoterList(poll, voterListId); - getVoterListDao().delete(voterList); commit(); @@ -192,11 +192,12 @@ VoterList voterList = getVoterList(pollId, voterListId); - checkVoterListMemberForm(voterList, member); + List<VoterListMember> existingVoterListMembers = new ArrayList<>(voterList.getMember()); - VoterListMember result = saveVoterListMember(voterList, member); + ErrorMap errorMap = checkVoterListMember(existingVoterListMembers, member); + errorMap.failIfNotEmpty(); - getVoterListDao().update(voterList); + VoterListMember result = saveVoterListMember(voterList, member); commit(); return result; @@ -213,11 +214,12 @@ VoterList voterList = getVoterList(pollId, voterListId); - checkVoterListMemberForm(voterList, member); + List<VoterListMember> existingVoterListMembers = new ArrayList<>(voterList.getMember()); - VoterListMember result = saveVoterListMember(voterList, member); + ErrorMap errorMap = checkVoterListMember(existingVoterListMembers, member); + errorMap.failIfNotEmpty(); - getVoterListMemberDao().update(member); + VoterListMember result = saveVoterListMember(voterList, member); commit(); return result; @@ -234,7 +236,6 @@ VoterListMember member = getVoterListMember(voterList, memberId); voterList.removeMember(member); - commit(); } @@ -310,8 +311,7 @@ } else { - toSave = getVoterListMemberDao().newInstance(); - + toSave = getVoterListMemberDao().create(); voterList.addMember(toSave); } @@ -324,30 +324,22 @@ } - protected void checkVoterListForm(Poll poll, VoterList voterList) throws InvalidFormException { + protected ErrorMap checkVoterList(List<VoterList> existingVoterLists, VoterList voterList) { - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); + ErrorMap errors = new ErrorMap(); boolean voterListExists = voterList.isPersisted(); Set<String> voterListNames = Sets.newHashSet(); - List<VoterList> existingVoterLists = null; - - if (poll.isPersisted()) { - - existingVoterLists = getVoterListDao().forPollEquals(poll).findAll(); - - } - if (CollectionUtils.isNotEmpty(existingVoterLists)) { // get all used names - for (VoterList lists : existingVoterLists) { + for (VoterList voterList1 : existingVoterLists) { - if (voterListExists && lists.getTopiaId().equals(voterList.getTopiaId())) { + if (voterListExists && + voterList1.getTopiaId().equals(voterList.getTopiaId())) { continue; } @@ -357,176 +349,95 @@ } - checkNotBlank(errors, "name", voterList.getName(), "voterList name can not be empty"); - check(errors, "weight", voterList.getWeight() > 0, "voterList weight must be greater than 0"); - checkNotEmpty(errors, "member", voterList.getMember(), "voterList must contains at least one member"); + checkNotBlank(errors, VoterList.PROPERTY_NAME, voterList.getName(), "voterList name can not be empty"); + check(errors, VoterList.PROPERTY_WEIGHT, voterList.getWeight() > 0, "voterList weight must be greater than 0"); + checkNotEmpty(errors, VoterList.PROPERTY_MEMBER, voterList.getMember(), "voterList must contains at least one member"); boolean added = voterListNames.add(voterList.getName()); - check(errors, "name", added, "voterList name already used"); + check(errors, VoterList.PROPERTY_NAME, added, "voterList name already used"); - Set<String> voterListMemberNames = Sets.newHashSet(); - Set<String> voterListMemberEmails = Sets.newHashSet(); - int voterListMemberIndex = 0; - for (VoterListMember voterListMember : voterList.getMember()) { + if (CollectionUtils.isNotEmpty(voterList.getMember())) { - String voterListMemberField = "member[" + (voterListMemberIndex++) + "]."; + List<VoterListMember> existingVoterListMembers; - String voterListMemberName = voterListMember.getName(); - boolean nameNotBlank = checkNotBlank(errors, voterListMemberField + "name", voterListMemberName, "member name can not be empty"); + if (voterListExists) { - if (nameNotBlank) { - boolean nameAdded = voterListMemberNames.add(voterListMemberName); - check(errors, voterListMemberField + "name", nameAdded, "member name already used in this list"); - } + existingVoterListMembers = new ArrayList<>(voterList.getMember()); - String voterListMemberEmail = getCleanMail(voterListMember.getEmail()); + } else { - boolean emailNotBlank = checkNotBlank(errors, voterListMemberField + "email", voterListMemberEmail, "member email can not be empty"); + existingVoterListMembers = new ArrayList<>(); - if (emailNotBlank) { - - checkValidEmail(errors, voterListMemberField + "email", voterListMemberEmail, "member email is not valid"); - boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail); - check(errors, voterListMemberField + "email", emailAdded, "member email already used in this list"); - } - } - if (!errors.isEmpty()) { + for (VoterListMember voterListMember : voterList.getMember()) { - throw new InvalidFormException(errors); + ErrorMap voterListMemberErrors = checkVoterListMember(existingVoterListMembers, voterListMember); + voterListMemberErrors.copyTo(errors, "member[" + (voterListMemberIndex++) + "]."); + existingVoterListMembers.add(voterListMember); + } } + return errors; + } - protected void checkVoterListMemberForm(VoterList voterList, VoterListMember voterListMember) throws InvalidFormException { + protected ErrorMap checkVoterListMember(List<VoterListMember> existingVoterListMembers, VoterListMember voterListMember) { - //TODO use nuiton validator ? - Multimap<String, String> errors = ArrayListMultimap.create(); + ErrorMap errors = new ErrorMap(); boolean voterListMemberExists = voterListMember.isPersisted(); Set<String> voterListMemberNames = Sets.newHashSet(); Set<String> voterListMemberEmails = Sets.newHashSet(); - if (!voterList.isMemberEmpty()) { + if (CollectionUtils.isNotEmpty(existingVoterListMembers)) { - // get all used names + // get all used names and email - for (VoterListMember member : voterList.getMember()) { + for (VoterListMember voterListMember1 : existingVoterListMembers) { if (voterListMemberExists && - member.getTopiaId().equals(voterListMember.getTopiaId())) { + voterListMember1.getTopiaId().equals(voterListMember.getTopiaId())) { continue; } - voterListMemberNames.add(voterListMember.getName()); - voterListMemberEmails.add(voterListMember.getEmail()); + voterListMemberNames.add(voterListMember1.getName()); + voterListMemberEmails.add(voterListMember1.getEmail()); } } + String voterListMemberName = voterListMember.getName(); - boolean nameNotblank = checkNotBlank(errors, "name", voterListMemberName, "member name can not be empty"); + boolean nameNotblank = checkNotBlank(errors, VoterListMember.PROPERTY_NAME, voterListMemberName, "member name can not be empty"); if (nameNotblank) { + boolean nameAdded = voterListMemberNames.add(voterListMemberName); - check(errors, "name", nameAdded, "member name already used in this list"); + check(errors, VoterListMember.PROPERTY_NAME, nameAdded, "member name already used in this list"); + } String voterListMemberEmail = getCleanMail(voterListMember.getEmail()); - boolean emailNotBlank = checkNotBlank(errors, "email", voterListMemberEmail, "member email can not be empty"); + boolean emailNotBlank = checkNotBlank(errors, VoterListMember.PROPERTY_EMAIL, voterListMemberEmail, "member email can not be empty"); if (emailNotBlank) { - checkValidEmail(errors, "email", voterListMemberEmail, "member email is not valid"); + checkValidEmail(errors, VoterListMember.PROPERTY_EMAIL, voterListMemberEmail, "member email is not valid"); boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail); - check(errors, "email", emailAdded, "member email already used in this list"); + check(errors, VoterListMember.PROPERTY_EMAIL, emailAdded, "member email already used in this list"); } - if (!errors.isEmpty()) { + check(errors, VoterListMember.PROPERTY_WEIGHT, voterListMember.getWeight() > 0, "member weight must be greater than 0"); - throw new InvalidFormException(errors); - - } - - } - - protected ErrorMap checkVoterList(List<VoterList> existingVoterLists, VoterList voterList) { - - ErrorMap errors = new ErrorMap(); - - boolean voterListExists = voterList.isPersisted(); - - Set<String> voterListNames = Sets.newHashSet(); - - if (CollectionUtils.isNotEmpty(existingVoterLists)) { - - // get all used names - - for (VoterList lists : existingVoterLists) { - - if (voterListExists && lists.getTopiaId().equals(voterList.getTopiaId())) { - continue; - } - - voterListNames.add(voterList.getName()); - - } - - } - - checkNotBlank(errors, VoterList.PROPERTY_NAME, voterList.getName(), "voterList name can not be empty"); - check(errors, VoterList.PROPERTY_WEIGHT, voterList.getWeight() > 0, "voterList weight must be greater than 0"); - checkNotEmpty(errors, VoterList.PROPERTY_MEMBER, voterList.getMember(), "voterList must contains at least one member"); - - boolean added = voterListNames.add(voterList.getName()); - - check(errors, VoterList.PROPERTY_NAME, added, "voterList name already used"); - - Set<String> voterListMemberNames = Sets.newHashSet(); - Set<String> voterListMemberEmails = Sets.newHashSet(); - - int voterListMemberIndex = 0; - - if (voterList.getMember() != null) { - for (VoterListMember voterListMember : voterList.getMember()) { - - String voterListMemberField = "member[" + (voterListMemberIndex++) + "]."; - - String voterListMemberName = voterListMember.getName(); - boolean nameNotBlank = checkNotBlank(errors, voterListMemberField + VoterListMember.PROPERTY_NAME, voterListMemberName, "member name can not be empty"); - - if (nameNotBlank) { - - boolean nameAdded = voterListMemberNames.add(voterListMemberName); - check(errors, voterListMemberField + VoterListMember.PROPERTY_NAME, nameAdded, "member name already used in this list"); - - } - - String voterListMemberEmail = getCleanMail(voterListMember.getEmail()); - - boolean emailNotBlank = checkNotBlank(errors, voterListMemberField + VoterListMember.PROPERTY_EMAIL, voterListMemberEmail, "member email can not be empty"); - - if (emailNotBlank) { - - checkValidEmail(errors, voterListMemberField + VoterListMember.PROPERTY_EMAIL, voterListMemberEmail, "member email is not valid"); - boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail); - check(errors, voterListMemberField + VoterListMember.PROPERTY_EMAIL, emailAdded, "member email already used in this list"); - - } - - check(errors, voterListMemberField + VoterListMember.PROPERTY_WEIGHT, voterListMember.getWeight() > 0, "member weight must be greater than 0"); - - } - } - return errors; } + } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -1,5 +1,26 @@ package org.chorem.pollen.services.service.security; +/* + * #%L + * Pollen :: Service + * %% + * Copyright (C) 2009 - 2014 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + /** * Created on 5/4/14. * Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -75,8 +75,8 @@ throw new PollenAuthenticationException(e); } - PollenUser user = getUserService().getUserByLogin(login); - return user; + PollenUser user = getPollenUserDao().forLoginEquals(login).findUnique(); + return copy(user); } @@ -89,7 +89,7 @@ subject.logout(); } - return sessionToken; + return copy(sessionToken); } @@ -98,16 +98,13 @@ PollenTokenTopiaDao dao = getPersistenceContext().getPollenTokenDao(); // Create instance - PollenToken pollenToken = dao.newInstance(); + PollenToken pollenToken = dao.create(); pollenToken.setCreationDate(serviceContext.getNow()); // Generate token String token = serviceContext.generateToken(); pollenToken.setToken(token); - // Persist - pollenToken = dao.create(pollenToken); - return pollenToken; } @@ -117,14 +114,12 @@ PollenPrincipalTopiaDao dao = getPersistenceContext().getPollenPrincipalDao(); // Create instance - PollenPrincipal principal = dao.newInstance(); + PollenPrincipal principal = dao.create(); // Generate token PollenToken token = generateNewToken(); principal.setPermission(token); - // Persist - dao.create(principal); return principal; } @@ -138,7 +133,7 @@ throw new PollenInvalidSessionTokenException(); } } - return sessionToken; + return copy(sessionToken); } @@ -148,7 +143,7 @@ if (principalId != null) { principal = getPollenPrincipalDao().findByPermissionToken(principalId); } - return principal; + return copy(principal); } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -45,6 +45,8 @@ import org.nuiton.util.DateUtil; import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -86,7 +88,11 @@ @Override protected void starting(Description description) { - currentPortNumber = portNumberCounter.getAndIncrement(); + // get an available port + currentPortNumber = getAvailablePort(); + if (log.isDebugEnabled()) { + log.debug("Using port: " + currentPortNumber); + } methodName = description.getMethodName(); @@ -233,4 +239,47 @@ } + protected int getAvailablePort() { + + int port = portNumberCounter.getAndIncrement(); + + boolean portTaken = false; + ServerSocket socket = null; + + try { + + socket = new ServerSocket(port); + + } catch (IOException e) { + + portTaken = true; + + } finally { + + if (socket != null) + + try { + + socket.close(); + + } catch (IOException e) { + + if (log.isDebugEnabled()) { + log.debug("Already used port: " + port); + } + + } + + } + + if (portTaken) { + + port = getAvailablePort(); + + } + + return port; + + } + } Modified: trunk/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties =================================================================== --- trunk/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties 2014-05-08 12:57:53 UTC (rev 3923) @@ -3,6 +3,7 @@ pollen.configuration.defaultPollType=Default Poll type used when creating a new poll pollen.configuration.defaultPollVoteVisibility=Default Poll vote visibility used when creating a new poll pollen.configuration.defaultVoteCountingType=Default vote counting type used when creating a new poll +pollen.configuration.pollChoiceType= pollen.error.favoriteList.import.csv.already.used.email= pollen.error.favoriteList.import.csv.already.used.name= pollen.error.favoriteList.import.csv.invalid.email= Modified: trunk/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties =================================================================== --- trunk/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties 2014-05-08 12:57:53 UTC (rev 3923) @@ -3,6 +3,7 @@ pollen.configuration.defaultPollType=Type de sondage par défaut lors de la création d'un nouveau sondage pollen.configuration.defaultPollVoteVisibility=Visibilité des votes par défaut lors de la création d'un nouveau sondage pollen.configuration.defaultVoteCountingType=Type de dépouillement par défaut lors de la création d'un nouveau sondage +pollen.configuration.pollChoiceType= pollen.error.favoriteList.import.csv.already.used.email= pollen.error.favoriteList.import.csv.already.used.name= pollen.error.favoriteList.import.csv.invalid.email= Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2014-05-08 07:34:51 UTC (rev 3922) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2014-05-08 12:57:53 UTC (rev 3923) @@ -73,6 +73,73 @@ } @Test + public void createSafeFreePoll() throws InvalidFormException { + + Poll poll = service.getNewPoll(); + + poll.setPollType(PollType.FREE); + poll.setTitle("poll1"); + + List<Choice> choices = new ArrayList<>(); + + Choice choice1 = getServiceContext().getPersistenceContext().getChoiceDao().newInstance(); + choices.add(choice1); + choice1.setChoiceType(ChoiceType.TEXT); + choice1.setName("A"); + choice1.setDescription("Choice A"); + + + Choice choice2 = getServiceContext().getPersistenceContext().getChoiceDao().newInstance(); + choice2.setChoiceType(ChoiceType.TEXT); + choice2.setName("B"); + choice2.setDescription("Choice B"); + choices.add(choice2); + + Poll createdPoll = service.createPoll(poll, choices, null); + Assert.assertNotNull(createdPoll); + Assert.assertNotNull(createdPoll.getTopiaId()); + + Poll reloadedPoll = service.getPoll(createdPoll.getTopiaId()); + Assert.assertEquals(createdPoll, reloadedPoll); + + Assert.assertEquals(getServiceContext().getNow(), createdPoll.getBeginDate()); + + Assert.assertNotNull(createdPoll.getCreator()); + Assert.assertNotNull(createdPoll.getCreator().getTopiaId()); + Assert.assertNull(createdPoll.getCreator().getName()); + Assert.assertNull(createdPoll.getCreator().getEmail()); + + List<Choice> createdChoices = choiceService.getChoices(createdPoll.getTopiaId()); + + Assert.assertNotNull(createdChoices); + Assert.assertEquals(2, createdChoices.size()); + + + Choice createdChoice1 = createdChoices.get(0); + Assert.assertNotNull(createdChoice1); + Assert.assertNotNull(createdChoice1.getTopiaId()); + + Choice reloadedChoice1 = choiceService.getChoice(createdPoll.getTopiaId(), createdChoice1.getTopiaId()); + Assert.assertEquals(createdChoice1, reloadedChoice1); + + Assert.assertEquals(choice1.getName(), createdChoice1.getName()); + Assert.assertEquals(choice1.getDescription(), createdChoice1.getDescription()); + Assert.assertEquals(createdPoll.getCreator(), createdChoice1.getCreator()); + + Choice createdChoice2 = createdChoices.get(1); + Assert.assertNotNull(createdChoice2); + Assert.assertNotNull(createdChoice2.getTopiaId()); + + Choice reloadedChoice2 = choiceService.getChoice(createdPoll.getTopiaId(), createdChoice2.getTopiaId()); + Assert.assertEquals(createdChoice2, reloadedChoice2); + + Assert.assertEquals(choice2.getName(), createdChoice2.getName()); + Assert.assertEquals(choice2.getDescription(), createdChoice2.getDescription()); + Assert.assertEquals(createdPoll.getCreator(), createdChoice2.getCreator()); + + } + + @Test public void testCreateFreePoll() throws InvalidFormException { Poll poll = service.getNewPoll(); @@ -179,7 +246,123 @@ } + @Test + public void createSafeRestrictedPoll() throws InvalidFormException { + + Poll poll = service.getNewPoll(); + + poll.setPollType(PollType.GROUP); + poll.setTitle("poll1"); + + List<Choice> choices = new ArrayList<>(); + + Choice choice1 = getServiceContext().getPersistenceContext().getChoiceDao().newInstance(); + choices.add(choice1); + choice1.setChoiceType(ChoiceType.TEXT); + choice1.setName("A"); + choice1.setDescription("Choice A"); + + + Choice choice2 = getServiceContext().getPersistenceContext().getChoiceDao().newInstance(); + choice2.setChoiceType(ChoiceType.TEXT); + choice2.setName("B"); + choice2.setDescription("Choice B"); + choices.add(choice2); + + List<VoterList> voterLists = new ArrayList<>(); + + // add voter list + VoterList voterList = getServiceContext().getPersistenceContext().getVoterListDao().newInstance(); + + voterLists.add(voterList); + voterList.setName("voterList1"); + voterList.setWeight(1); + + VoterListMember voterListMember1 = getServiceContext().getPersistenceContext().getVoterListMemberDao().newInstance(); + voterList.addMember(voterListMember1); + + voterListMember1.setName("voter1"); + voterListMember1.setWeight(0.3); + voterListMember1.setEmail("voter1@pollen.org"); + + VoterListMember voterListMember2 = getServiceContext().getPersistenceContext().getVoterListMemberDao().newInstance(); + voterList.addMember(voterListMember2); + voterListMember2.setName("voter2"); + voterListMember2.setEmail("voter2@pollen.org"); + voterListMember2.setWeight(0.7); + + Poll createdPoll = service.createPoll(poll, choices, voterLists); + Assert.assertNotNull(createdPoll); + Assert.assertNotNull(createdPoll.getTopiaId()); + + try { + service.getPoll(createdPoll.getTopiaId()); + Assert.fail(); + } catch (PollenInvalidPermissionException e) { + Assert.assertTrue(true); + } + + FakePollenSecurityContext securityContext = (FakePollenSecurityContext) serviceContext.getSecurityContext(); + securityContext.setMainPrincipal(createdPoll.getCreator()); + + Poll reloadedPoll = service.getPoll(createdPoll.getTopiaId()); + Assert.assertEquals(createdPoll, reloadedPoll); + + Assert.assertEquals(getServiceContext().getNow(), createdPoll.getBeginDate()); + + Assert.assertNotNull(createdPoll.getCreator()); + Assert.assertNotNull(createdPoll.getCreator().getTopiaId()); + Assert.assertNull(createdPoll.getCreator().getName()); + Assert.assertNull(createdPoll.getCreator().getEmail()); + + List<Choice> createdChoices = choiceService.getChoices(createdPoll.getTopiaId()); + + Assert.assertNotNull(createdChoices); + Assert.assertEquals(2, createdChoices.size()); + + Choice createdChoice1 = createdChoices.get(0); + Assert.assertNotNull(createdChoice1); + Assert.assertNotNull(createdChoice1.getTopiaId()); + + Choice reloadedChoice1 = choiceService.getChoice(createdPoll.getTopiaId(), createdChoice1.getTopiaId()); + Assert.assertEquals(createdChoice1, reloadedChoice1); + + Assert.assertEquals(choice1.getName(), createdChoice1.getName()); + Assert.assertEquals(choice1.getDescription(), createdChoice1.getDescription()); + Assert.assertEquals(createdPoll.getCreator(), createdChoice1.getCreator()); + + Choice createdChoice2 = createdChoices.get(1); + Assert.assertNotNull(createdChoice2); + Assert.assertNotNull(createdChoice2.getTopiaId()); + + Choice reloadedChoice2 = choiceService.getChoice(createdPoll.getTopiaId(), createdChoice2.getTopiaId()); + Assert.assertEquals(createdChoice2, reloadedChoice2); + + Assert.assertEquals(choice2.getName(), createdChoice2.getName()); + Assert.assertEquals(choice2.getDescription(), createdChoice2.getDescription()); + Assert.assertEquals(createdPoll.getCreator(), createdChoice2.getCreator()); + + List<VoterList> createdVoterLists = voterListService.getVoterLists(createdPoll.getTopiaId()); + + Assert.assertNotNull(createdVoterLists); + Assert.assertEquals(1, createdVoterLists.size()); + VoterList createdVoterList = createdVoterLists.get(0); + Assert.assertNotNull(createdVoterList); + Assert.assertNotNull(createdVoterList.getTopiaId()); + + VoterList reloadedVoterList = voterListService.getVoterList(createdPoll.getTopiaId(), createdVoterList.getTopiaId()); + Assert.assertEquals(createdVoterList, reloadedVoterList); + + Assert.assertEquals(voterList.getName(), createdVoterList.getName()); + Assert.assertEquals(voterList.getWeight(), createdVoterList.getWeight(), 0); + + Assert.assertNotNull(createdVoterList.getMember()); + Assert.assertEquals(2, createdVoterList.sizeMember()); + + } + + @Test public void testCreateRestrictedPoll() throws InvalidFormException { Poll poll = service.getNewPoll();