Author: tchemit Date: 2011-11-23 18:51:57 +0100 (Wed, 23 Nov 2011) New Revision: 110 Url: http://forge.codelutin.com/repositories/revision/echobase/110 Log: using csv model for all dbeditor commands Added: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvImportResult.java trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvModelUtil.java trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorCsvModel.java Modified: trunk/echobase-services/pom.xml trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/AbstractEchoBaseService.java trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorService.java trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/ExportSqlService.java Modified: trunk/echobase-services/pom.xml =================================================================== --- trunk/echobase-services/pom.xml 2011-11-23 17:50:27 UTC (rev 109) +++ trunk/echobase-services/pom.xml 2011-11-23 17:51:57 UTC (rev 110) @@ -38,6 +38,11 @@ <artifactId>nuiton-utils</artifactId> </dependency> + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-csv</artifactId> + </dependency> + <!--dependency> <groupId>org.nuiton.i18n</groupId> <artifactId>nuiton-i18n</artifactId> @@ -55,10 +60,10 @@ <artifactId>xwork-core</artifactId> </dependency--> - <dependency> + <!--dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> - </dependency> + </dependency--> <dependency> <groupId>commons-logging</groupId> Modified: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/AbstractEchoBaseService.java =================================================================== --- trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/AbstractEchoBaseService.java 2011-11-23 17:50:27 UTC (rev 109) +++ trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/AbstractEchoBaseService.java 2011-11-23 17:51:57 UTC (rev 110) @@ -24,9 +24,17 @@ package fr.ifremer.echobase.services; import fr.ifremer.echobase.EchoBaseConfiguration; +import fr.ifremer.echobase.EchoBaseTechnicalException; +import fr.ifremer.echobase.entities.EchoBaseDAOHelper; +import fr.ifremer.echobase.entities.EchoBaseEntityEnum; import fr.ifremer.echobase.entities.meta.DbMeta; +import org.apache.commons.lang3.time.DateUtils; import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.TopiaException; +import org.nuiton.topia.persistence.TopiaDAO; +import org.nuiton.topia.persistence.TopiaEntity; +import java.util.Date; import java.util.Locale; /** @@ -63,5 +71,31 @@ return e; } + protected <E extends TopiaEntity> TopiaDAO<E> getDAO(EchoBaseEntityEnum entityEnum) throws TopiaException { + TopiaDAO<E> dao = getDAO((Class<E>) entityEnum.getContract()); + return dao; + } + protected <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityType) throws TopiaException { + TopiaDAO<E> dao = EchoBaseDAOHelper.<E, TopiaDAO<E>>getDAO( + getTransaction(), + entityType); + + return dao; + } + + protected void commitTransaction(String errorMessage) { + try { + getTransaction().commitTransaction(); + } catch (TopiaException eee) { + throw new EchoBaseTechnicalException(errorMessage, eee); + } + } + + protected Date newDate() { + Date result = new Date(); + DateUtils.setMilliseconds(result,0); + return result; + } + } Added: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvImportResult.java =================================================================== --- trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvImportResult.java (rev 0) +++ trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvImportResult.java 2011-11-23 17:51:57 UTC (rev 110) @@ -0,0 +1,98 @@ +/* + * #%L + * EchoBase :: Services + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 Ifremer, 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% + */ +package fr.ifremer.echobase.services; + +import fr.ifremer.echobase.entities.EchoBaseEntityEnum; + +import java.io.Serializable; + +/** + * A simple csv result bean just to keep the number of created or + * updated entities. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class CsvImportResult implements Serializable { + + private static final long serialVersionUID = 1L; + + /** type of entity to import csv datas. */ + protected EchoBaseEntityEnum entityType; + + /** Name of the csv file to import. */ + protected String importFileName; + + /** Count of created entities. */ + + protected int numberCreated; + + /** Count of updated entities. */ + protected int numberUpdated; + + /** Flag to authorize to create entities not found in db. */ + protected boolean createIfNotFound; + + + public EchoBaseEntityEnum getEntityType() { + return entityType; + } + + + public String getImportFileName() { + return importFileName; + } + + public int getNumberCreated() { + return numberCreated; + } + + public int getNumberUpdated() { + return numberUpdated; + } + + public boolean isCreateIfNotFound() { + return createIfNotFound; + } + + public void incrementsNumberCreated() { + numberCreated++; + } + + public void incrementsNumberUpdated() { + numberUpdated++; + } + + public void setEntityType(EchoBaseEntityEnum entityType) { + this.entityType = entityType; + } + + public void setImportFileName(String importFileName) { + this.importFileName = importFileName; + } + + public void setCreateIfNotFound(boolean createIfNotFound) { + this.createIfNotFound = createIfNotFound; + } +} Property changes on: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvImportResult.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvModelUtil.java =================================================================== --- trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvModelUtil.java (rev 0) +++ trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvModelUtil.java 2011-11-23 17:51:57 UTC (rev 110) @@ -0,0 +1,134 @@ +/* + * #%L + * EchoBase :: Services + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 Ifremer, 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% + */ +package fr.ifremer.echobase.services; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import fr.ifremer.echobase.EchoBaseTechnicalException; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.util.csv.Common; +import org.nuiton.util.csv.ValueFormatter; +import org.nuiton.util.csv.ValueParserFormatter; + +import java.text.ParseException; +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +/** + * Usefull class to build csv import-export models. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class CsvModelUtil extends Common { + + public static <E extends TopiaEntity> ForeignKeyValue<E> newForeignKeyValue(Class<E> type) { + return new ForeignKeyValue<E>(type); + } + + public static <E extends TopiaEntity> ForeignKeyValue<E> newForeignKeyValue(Class<E> type, Collection<E> entitites) { + return new ForeignKeyValue<E>(type, entitites); + } + + public static <E extends TopiaEntity> ForeignKeyDecoratedValue<E> newForeignKeyDecoratedValue(Class<E> entityType, DecoratorService decoratorService, Locale locale) { + return new ForeignKeyDecoratedValue<E>(entityType, decoratorService, locale); + } + + public static class ForeignKeyValue<E extends TopiaEntity> implements ValueParserFormatter<E> { + + protected final Class<E> entityType; + + protected final Map<String, E> universe; + + public ForeignKeyValue(Class<E> entityType, Collection<E> entitites) { + this.entityType = entityType; + universe = Maps.uniqueIndex(entitites, new Function<E, String>() { + @Override + public String apply(E input) { + return input.getTopiaId(); + } + }); + } + + public ForeignKeyValue(Class<E> entityType) { + this.entityType = entityType; + universe = Maps.newHashMap(); + } + + @Override + public E parse(String value) throws ParseException { + E result = null; + if (StringUtils.isNotBlank(value)) { + + // get entity from universe + result = universe.get(value); + + if (result == null) { + + // can not find entity this is a big problem for us... + throw new EchoBaseTechnicalException( + "Could not find entity with name " + value); + } + } + return result; + } + + @Override + public String format(E e) { + String value = ""; + if (e != null) { + value = e.getTopiaId(); + } + return value; + } + } + + public static class ForeignKeyDecoratedValue<E extends TopiaEntity> implements ValueFormatter<E> { + + protected final Class<E> entityType; + + protected final DecoratorService decoratorService; + + protected final Locale locale; + + public ForeignKeyDecoratedValue(Class<E> entityType, DecoratorService decoratorService, Locale locale) { + this.entityType = entityType; + this.decoratorService = decoratorService; + this.locale = locale; + + } + + @Override + public String format(E e) { + String value = ""; + if (e != null) { + + value = decoratorService.decorate(locale, e, null); + } + return value; + } + } +} Property changes on: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/CsvModelUtil.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorCsvModel.java =================================================================== --- trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorCsvModel.java (rev 0) +++ trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorCsvModel.java 2011-11-23 17:51:57 UTC (rev 110) @@ -0,0 +1,159 @@ +/* + * #%L + * EchoBase :: Services + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2011 Ifremer, 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% + */ +package fr.ifremer.echobase.services; + +import fr.ifremer.echobase.entities.meta.TableMeta; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.util.csv.ExportableColumn; +import org.nuiton.util.csv.ImportExportModel; +import org.nuiton.util.csv.ImportableColumn; +import org.nuiton.util.csv.ModelBuilder; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * Import/Export csv model. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class DbEditorCsvModel<E extends TopiaEntity> implements ImportExportModel<E> { + + protected final char separator; + + protected final TableMeta tableMeta; + + protected ModelBuilder<E> modelBuilder; + + public DbEditorCsvModel(char separator, TableMeta tableMeta) { + this.separator = separator; + this.tableMeta = tableMeta; + modelBuilder = new ModelBuilder<E>(); + } + + @Override + public char getSeparator() { + return separator; + } + + @Override + public Collection<ExportableColumn<E, Object>> getColumnsForExport() { + return (Collection) + modelBuilder.getColumnsForExport(); + } + + @Override + public Collection<ImportableColumn<E, Object>> getColumnsForImport() { + return (Collection) + modelBuilder.getColumnsForImport(); + } + + @Override + public void pushCsvHeaderNames(List<String> headerNames) { + } + + @Override + public E newEmptyInstance() { + return (E) tableMeta.newEntity(); + } + + public void addForeignKeyForExport(String propertyName, + Class<TopiaEntity> entityType) { + + modelBuilder.newColumnForExport( + propertyName, + propertyName, + CsvModelUtil.newForeignKeyValue(entityType) + ); + } + + public void addForeignKeyForImport(String propertyName, + Class<TopiaEntity> entityType, + Collection<TopiaEntity> universe) { + + modelBuilder.newMandatoryColumn( + propertyName, + propertyName, + CsvModelUtil.newForeignKeyValue(entityType, universe) + ); + } + + public <E extends TopiaEntity> void addDefaultColumn(String propertyName, + Class<?> type) { + + if (Date.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.DAY_TIME_SECOND + ); + } else if (float.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.PRIMITIVE_FLOAT + ); + } else if (Float.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.FLOAT + ); + } else if (int.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.PRIMITIVE_INTEGER + ); + } else if (Integer.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.INTEGER + ); + } else if (boolean.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.PRIMITIVE_BOOLEAN + ); + } else if (Boolean.class.equals(type)) { + modelBuilder.newColumnForImportExport( + propertyName, + propertyName, + CsvModelUtil.BOOLEAN + ); + } else { + + // string + modelBuilder.newColumnForImportExport( + propertyName, + propertyName + ); + } + } + +} Property changes on: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorCsvModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorService.java =================================================================== --- trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorService.java 2011-11-23 17:50:27 UTC (rev 109) +++ trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/DbEditorService.java 2011-11-23 17:51:57 UTC (rev 110) @@ -24,19 +24,15 @@ package fr.ifremer.echobase.services; import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import fr.ifremer.echobase.EchoBaseTechnicalException; -import fr.ifremer.echobase.entities.EchoBaseDAOHelper; import fr.ifremer.echobase.entities.EchoBaseEntityEnum; import fr.ifremer.echobase.entities.EchoBaseUser; import fr.ifremer.echobase.entities.EntityModificationLog; -import fr.ifremer.echobase.entities.EntityModificationLogDAO; import fr.ifremer.echobase.entities.meta.ColumnMeta; import fr.ifremer.echobase.entities.meta.DbMeta; import fr.ifremer.echobase.entities.meta.TableMeta; -import org.apache.commons.beanutils.BeanUtils; -import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -44,18 +40,19 @@ import org.nuiton.topia.framework.TopiaQuery; import org.nuiton.topia.persistence.TopiaDAO; import org.nuiton.topia.persistence.TopiaEntity; -import org.nuiton.topia.persistence.util.EntityOperator; -import org.nuiton.util.StringUtil; import org.nuiton.util.beans.BeanMonitor; import org.nuiton.util.beans.PropertyDiff; +import org.nuiton.util.csv.Export; +import org.nuiton.util.csv.ExportableColumn; +import org.nuiton.util.csv.Import; +import org.nuiton.util.csv.ImportableColumn; +import org.nuiton.util.csv.ModelBuilder; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -70,14 +67,9 @@ /** Logger. */ private static final Log log = LogFactory.getLog(DbEditorService.class); - public static final String EXPORT_FILE_PREFIX = "modifExport-"; - public static final String SCV_EXT = ".csv"; - public static final String EXPORT_FILE_FORMAT_DATE = "yyyyMMddHHmmss"; - public static final String BASE_EDITOR_FORMAT_DATE = "dd/MM/yyyy HH:mm:ss"; - public static final String CSV_SEPARATOR = ";"; + public static final char CSV_CHAR_SEPARATOR = ';'; protected DecoratorService decoratorService; - protected SimpleDateFormat dateFormat; protected DecoratorService getDecoratorService() { if (decoratorService == null) { @@ -86,67 +78,50 @@ return decoratorService; } - public SimpleDateFormat getDateFormat() { - if (dateFormat == null) { - dateFormat = new SimpleDateFormat(BASE_EDITOR_FORMAT_DATE); - } - return dateFormat; - } - - public List<TopiaEntity> getForeignDatas(String entityType) { + public <E extends TopiaEntity> List<E> getForeignDatas(Class<E> entityType) { Preconditions.checkNotNull(entityType); - EchoBaseEntityEnum entityEnum = EchoBaseEntityEnum.valueOf(entityType); - Preconditions.checkNotNull(entityEnum); - Class<? extends TopiaEntity> contract = entityEnum.getContract(); try { - TopiaDAO dao = EchoBaseDAOHelper.getDAO(getTransaction(), contract); + TopiaDAO<E> dao = getDAO(entityType); - List result = dao.findAll(); + List<E> result = dao.findAll(); return result; } catch (TopiaException eee) { throw new EchoBaseTechnicalException("Could not obtain data", eee); } } - public TableMeta getTableMetas(String tableName) { + public TableMeta getTableMetas(EchoBaseEntityEnum tableName) { DbMeta dbMeta = getDbMeta(); TableMeta result = dbMeta.getTable(tableName); return result; } - public Map<?, ?>[] getAllDatas(String tableName, boolean addDecorated) { - return getDatas(tableName, null, null, null, addDecorated); - } - //TODO Use an object to filter datas - public Map<?, ?>[] getDatas(String tableName, + public Map<?, ?>[] getDatas(EchoBaseEntityEnum entityType, Pager pager, String sidx, Boolean ascendantOrder) { - return getDatas(tableName, pager, sidx, ascendantOrder, true); + return getDatas(entityType, pager, sidx, ascendantOrder, true); } - public Map<?, ?>[] getDatas(String tableName, - Pager pager, - String sidx, - Boolean ascendantOrder, - boolean addDecorated) { - DbMeta dbMeta = getDbMeta(); - TableMeta tableMeta = dbMeta.getTable(tableName); + public <E extends TopiaEntity> List<E> getEntities(TableMeta tableMeta, + Pager pager, + String sidx, + Boolean ascendantOrder) { + + List<E> result; EchoBaseEntityEnum entityEnum = tableMeta.getEntityEnum(); Class<? extends TopiaEntity> contract = entityEnum.getContract(); try { - TopiaDAO dao = EchoBaseDAOHelper.getDAO(getTransaction(), contract); + TopiaDAO dao = getDAO(contract); // first query to count datas TopiaQuery countQuery = dao.createQuery("e"); countQuery.addSelect("count(*)"); int count = dao.countByQuery(countQuery); - List<?> all; - int resultSize; if (pager != null) { pager.setRecords(count); pager.computeIndexesAndPageCount(); @@ -154,8 +129,6 @@ int from = pager.getStartIndex(); int to = pager.getEndIndex(); - resultSize = to - from; - if (log.isDebugEnabled()) { log.debug("Count = " + count); log.debug("page = " + pager.getPageNumber()); @@ -174,319 +147,445 @@ } } query.setLimit(from, to - 1); - all = dao.findAllByQuery(query); + result = dao.findAllByQuery(query); } else { // Get all - all = dao.findAll(); - resultSize = count; + result = dao.findAll(); } - Map<?, ?>[] rows = new Map[resultSize]; - - int i = 0; - for (Object o : all) { - TopiaEntity entity = (TopiaEntity) o; - Map<String, Object> row = loadRow(tableMeta, entity, addDecorated); - rows[i++] = row; - } - return rows; + return result; } catch (TopiaException eee) { throw new EchoBaseTechnicalException("Could not obtain data", eee); } } - public Map<?, ?> getData(String tableName, - String topiaId) { + public Map<?, ?>[] getDatas(EchoBaseEntityEnum entityType, + Pager pager, + String sidx, + Boolean ascendantOrder, + boolean addDecorated) { - DbMeta dbMeta = getDbMeta(); - TableMeta tableMeta = dbMeta.getTable(tableName); + TableMeta tableMeta = getTableMetas(entityType); + + List<TopiaEntity> entities = getEntities(tableMeta, + pager, + sidx, + ascendantOrder + ); + + Map<?, ?>[] rows = new Map[entities.size()]; + + DbEditorCsvModel<TopiaEntity> model = + buildForLoad(tableMeta, addDecorated); + + int i = 0; + for (Object o : entities) { + TopiaEntity entity = (TopiaEntity) o; + Map<String, Object> row = loadRow(entity, model); + rows[i++] = row; + } + return rows; + } + + public Map<?, ?> getData(TableMeta tableMeta, String topiaId) { + EchoBaseEntityEnum entityEnum = tableMeta.getEntityEnum(); - Class<? extends TopiaEntity> contract = entityEnum.getContract(); try { - TopiaDAO dao = EchoBaseDAOHelper.getDAO(getTransaction(), contract); + TopiaDAO<?> dao = getDAO(entityEnum.getContract()); TopiaEntity entity = dao.findByTopiaId(topiaId); - return loadRow(tableMeta, entity, true); + DbEditorCsvModel<TopiaEntity> model = buildForLoad(tableMeta, true); + return loadRow(entity, model); } catch (TopiaException eee) { throw new EchoBaseTechnicalException("Could not obtain data", eee); } } - public PropertyDiff[] saveEntity(TableMeta tableMeta, - String id, - Map<String, String> properties, - EchoBaseUser user) { + public void saveEntity(TableMeta tableMeta, + String id, + Map<String, String> properties, + EchoBaseUser user) { - return saveEntity(tableMeta, id, properties, user, true); + // transform properties entity + DbEditorCsvModel<TopiaEntity> model = buildForSave(tableMeta); + + TopiaEntity entity = model.newEmptyInstance(); + entity.setTopiaId(id); + + for (ImportableColumn<TopiaEntity, Object> column : model.getColumnsForImport()) { + String propertyName = column.getHeaderName(); + String stringValue = properties.get(propertyName); + Object o; + try { + o = column.parseValue(stringValue); + } catch (Exception e) { + throw new EchoBaseTechnicalException("Could not parse property [" + propertyName + "] with value " + stringValue); + } + try { + column.setValue(entity, o); + } catch (Exception e) { + throw new EchoBaseTechnicalException("Could not set property [" + propertyName + "] with value " + stringValue + " to entity " + entity); + } + } + + saveEntity( + tableMeta, + "Modification utilisateur", + entity, + user, + false, + null + ); + commitTransaction("Could not commit transaction"); } - public PropertyDiff[] saveEntity(TableMeta tableMeta, - String id, - Map<String, String> properties, - EchoBaseUser user, - boolean commit) { + public CsvImportResult importDatas(EchoBaseEntityEnum entityType, + String importFileName, + File importFile, + boolean createIfNotFound, + EchoBaseUser user) { + TableMeta tableMeta = getTableMetas(entityType); + DbEditorCsvModel<TopiaEntity> csvModel = buildForImport(tableMeta); + String messagePrefix = "Import du fichier " + importFileName; - Class<? extends TopiaEntity> entityType = tableMeta.getEntityType(); + CsvImportResult result = new CsvImportResult(); + result.setImportFileName(importFileName); + result.setEntityType(entityType); + BufferedReader bf = null; + try { + + bf = new BufferedReader(new FileReader(importFile)); + + Import<TopiaEntity> importer = Import.newImport(csvModel, bf); + + Iterator<TopiaEntity> iterator = importer.startImport(); + + try { + while (iterator.hasNext()) { + TopiaEntity entity = iterator.next(); + saveEntity(tableMeta, + messagePrefix, + entity, + user, + createIfNotFound, + result + ); + } + } finally { + + importer.stopImport(); + } + + commitTransaction("Could not commit transaction"); + } catch (EchoBaseTechnicalException eee) { + throw eee; + } catch (Exception eee) { + log.error("Failed to read import file " + importFile.getName(), eee); + throw new EchoBaseTechnicalException(eee); + } finally { + IOUtils.closeQuietly(bf); + } + + return result; + } + + public String exportDatas(EchoBaseEntityEnum entityType) { + + TableMeta tableMeta = getTableMetas(entityType); + + List<TopiaEntity> datas = getEntities(tableMeta, null, null, null); + + DbEditorCsvModel<TopiaEntity> model = buildForExport(tableMeta); + + Export<TopiaEntity> export = Export.newExport(model, datas); + + try { + return export.startExportAsString(); + } catch (Exception eee) { + throw new EchoBaseTechnicalException("Can not export datas", eee); + } + } + + protected void saveEntity(TableMeta tableMeta, + String messagePrefix, + TopiaEntity entity, + EchoBaseUser user, + boolean createIfNotFound, + CsvImportResult result) { + String[] columnNames = tableMeta.getColumnNamesAsArray(); - BeanMonitor monitor = new BeanMonitor(columnNames); + BeanMonitor monitor = null; + String id = entity.getTopiaId(); + try { - TopiaDAO dao = EchoBaseDAOHelper.getDAO( - getTransaction(), - entityType); + TopiaDAO<TopiaEntity> dao = getDAO(tableMeta.getEntityEnum()); TopiaEntity entityToSave; // Find or create entity if no id boolean create = StringUtils.isEmpty(id); if (create) { + entityToSave = dao.create(); + result.incrementsNumberCreated(); } else { + entityToSave = dao.findByTopiaId(id); - } - monitor.setBean(entityToSave); - for (Map.Entry<String, String> entry : properties.entrySet()) { - String propertyName = entry.getKey(); - String propertyValue = entry.getValue(); - Object value; - ColumnMeta columnMeta = tableMeta.getColumns(propertyName); - if (columnMeta.isFK()) { + if (entityToSave == null) { - // let's find the entity - TopiaDAO daoFK = EchoBaseDAOHelper.getDAO( - getTransaction(), - (Class<? extends TopiaEntity>) columnMeta.getType()); - value = daoFK.findByTopiaId(propertyValue); + if (!createIfNotFound) { - } else if (Date.class.equals(columnMeta.getType())) { - value = getDateFormat().parse(propertyValue); - } else { - value = propertyValue; + // this is an error + throw new EchoBaseTechnicalException("Could not found entity with id " + id); + } else { + entityToSave = dao.create(TopiaEntity.TOPIA_ID, id); + + } } - BeanUtils.setProperty(entityToSave, - propertyName, - value); + // monitor the existing bean + monitor = new BeanMonitor(columnNames); + monitor.setBean(entityToSave); + + result.incrementsNumberUpdated(); } - PropertyDiff[] propertyDiffs = monitor.getPropertyDiffs(); + tableMeta.copy(entity, entityToSave); - int length = propertyDiffs.length; + PropertyDiff[] propertyDiffs = monitor == null ? null : + monitor.getPropertyDiffs(); - if (length > 0) { + createEntityModificationLog( + tableMeta, + messagePrefix, + entityToSave, + user, + propertyDiffs + ); + } catch (Exception eee) { + throw new EchoBaseTechnicalException("Could not update entity", eee); + } finally { + if (monitor != null) { + monitor.setBean(null); + } + } + } - // something was modified on the entity + protected void createEntityModificationLog( + TableMeta tableMeta, + String messagePrefix, + TopiaEntity entity, + EchoBaseUser user, + PropertyDiff[] propertyDiffs) throws TopiaException { - EntityModificationLogDAO dao1 = - EchoBaseDAOHelper.getEntityModificationLogDAO( - getTransaction() - ); + StringBuilder buffer; - StringBuilder buffer; + String topiaId = entity.getTopiaId(); - if (create) { - buffer = new StringBuilder("Une entité à été crée :"); - } else { - if (length == 1) { - buffer = new StringBuilder("Une propriété a été modifiée :"); - } else { - buffer = new StringBuilder(length + " propriétés ont été modifiées :"); - } - } - for (int i = 0; i < length; i++) { - PropertyDiff diff = propertyDiffs[i]; + boolean create = propertyDiffs == null; - Object sourceValue = diff.getSourceValue(); - Object targetValue = diff.getTargetValue(); + buffer = new StringBuilder(messagePrefix + "\n"); + if (create) { + buffer.append("Une entité à été crée d'identifiant ").append(topiaId); + } else { - String propertyName = diff.getSourceProperty(); + int length = propertyDiffs.length; - if (tableMeta.getColumns(propertyName).isFK()) { + if (length == 1) { + buffer.append("Une propriété a été modifiée :"); + } else { + buffer.append(length).append(" propriétés ont été modifiées :"); + } + for (int i = 0; i < length; i++) { + PropertyDiff diff = propertyDiffs[i]; - // replace by the decorate value - if (sourceValue != null) { - sourceValue = getDecoratorService().decorate( - getLocale(), sourceValue, null); - } - if (targetValue != null) { - targetValue = getDecoratorService().decorate( - getLocale(), targetValue, null); - } + Object sourceValue = diff.getSourceValue(); + Object targetValue = diff.getTargetValue(); - } + String propertyName = diff.getSourceProperty(); - if (create) { - buffer.append(String.format("\n Propriété '%s', valeur : %s", - propertyName, - targetValue - )); - } else { - buffer.append(String.format("\n Propriété '%s', ancienne valeur : %s, nouvelle valeur : %s", - propertyName, - sourceValue, - targetValue - )); + if (tableMeta.getColumns(propertyName).isFK()) { + + // replace by the decorate value + if (sourceValue != null) { + sourceValue = getDecoratorService().decorate( + getLocale(), sourceValue, null); } + if (targetValue != null) { + targetValue = getDecoratorService().decorate( + getLocale(), targetValue, null); + } + buffer.append(String.format("\n Propriété '%s', ancienne valeur : %s, nouvelle valeur : %s", + propertyName, + sourceValue, + targetValue + )); } - dao1.create( - EntityModificationLog.PROPERTY_ENTITY_TYPE, entityType.getSimpleName(), - EntityModificationLog.PROPERTY_ENTITY_ID, id, - EntityModificationLog.PROPERTY_USER, user, - EntityModificationLog.PROPERTY_MODIFICATION_DATE, new Date(), - EntityModificationLog.PROPERTY_MODIFICATION_TEXT, buffer.toString() - ); - - if (commit) { - getTransaction().commitTransaction(); - } } - return propertyDiffs; - } catch (Exception eee) { - throw new EchoBaseTechnicalException("Could not update entity", eee); - } finally { - monitor.setBean(null); } + + TopiaDAO<EntityModificationLog> dao = + getDAO(EntityModificationLog.class); + + dao.create( + EntityModificationLog.PROPERTY_ENTITY_TYPE, tableMeta.getEntityEnum().name(), + EntityModificationLog.PROPERTY_ENTITY_ID, topiaId, + EntityModificationLog.PROPERTY_USER, user, + EntityModificationLog.PROPERTY_MODIFICATION_DATE, newDate(), + EntityModificationLog.PROPERTY_MODIFICATION_TEXT, buffer.toString() + ); } - protected Map<String, Object> loadRow(TableMeta tableMeta, - TopiaEntity entity, - boolean addDecorated) { + protected <E extends TopiaEntity> Map<String, Object> loadRow( + E entity, + DbEditorCsvModel<E> loadModel) { + Map<String, Object> row = Maps.newLinkedHashMap(); - EntityOperator<TopiaEntity> operator = - (EntityOperator<TopiaEntity>) tableMeta.getOperator(); - row.put("id", entity.getTopiaId()); - for (ColumnMeta columnMeta : tableMeta) { - String propertyName = columnMeta.getName(); - // get property value - Object property = operator.get(propertyName, entity); - if (columnMeta.isFK() && property != null) { + Collection<ExportableColumn<E, Object>> columns = + loadModel.getColumnsForExport(); - // this is a foreign key, just keep the topiaid - String topiaId = ((TopiaEntity) property).getTopiaId(); + for (ExportableColumn<E, Object> column : columns) { + String propertyName = column.getHeaderName(); + Object value; + try { + value = column.getValue(entity); + } catch (Exception eee) { + throw new EchoBaseTechnicalException( + "Could not obtain property [" + propertyName + + "] value ", eee); + } + String formatedValue = column.formatValue(value); + row.put(propertyName, formatedValue); - if (addDecorated) { - // decorate the entity - String decorate = getDecoratorService().decorate( - getLocale(), property, null); + } + return row; + } - // keep the decorate value - row.put(propertyName + "_lib", decorate); - } + protected <E extends TopiaEntity> DbEditorCsvModel<E> buildForImport(TableMeta tableMetas) { - // use as the property his topiaid - property = topiaId; - } + DbEditorCsvModel<E> model = new DbEditorCsvModel<E>(CSV_CHAR_SEPARATOR, + tableMetas); - // Format date - if (columnMeta.isDate() && property != null) { - Date date = (Date) property; - property = getDateFormat().format(date); + ModelBuilder<E> modelBuilder = model.modelBuilder; + + modelBuilder.newColumnForImportExport( + TopiaEntity.TOPIA_ID, + TopiaEntity.TOPIA_ID + ); + + for (ColumnMeta columnMeta : model.tableMeta) { + String propertyName = columnMeta.getName(); + Class<?> type = columnMeta.getType(); + if (columnMeta.isFK()) { + + Class<TopiaEntity> entityType = (Class<TopiaEntity>) type; + Collection<TopiaEntity> universe = getForeignDatas(entityType); + model.addForeignKeyForImport(propertyName, entityType, universe); + } else { + model.addDefaultColumn(propertyName, type); } - row.put(propertyName, property); } - return row; + return model; } - public List<PropertyDiff[]> importDatas(String tableName, - File importFile, - EchoBaseUser user) { - TableMeta tableMetas = getTableMetas(tableName); - BufferedReader bf = null; - List<PropertyDiff[]> result = Lists.newArrayList(); - try { - bf = new BufferedReader(new FileReader(importFile)); - String csvHeader = bf.readLine(); - String[] properties = csvHeader.split(CSV_SEPARATOR); + protected <E extends TopiaEntity> DbEditorCsvModel<E> buildForSave(TableMeta tableMetas) { - String line = bf.readLine(); - while (line != null) { + DbEditorCsvModel<E> model = new DbEditorCsvModel<E>(CSV_CHAR_SEPARATOR, + tableMetas); - Map<String, String> valuesMap = Maps.newLinkedHashMap(); + ModelBuilder<E> modelBuilder = model.modelBuilder; - String[] values = line.split(CSV_SEPARATOR); + modelBuilder.newColumnForExport( + TopiaEntity.TOPIA_ID, + TopiaEntity.TOPIA_ID + ); - String id = values[0]; - for (int i=1;i<values.length;i++) { - valuesMap.put(properties[i], values[i]); - } + for (ColumnMeta columnMeta : model.tableMeta) { + String propertyName = columnMeta.getName(); + Class<?> type = columnMeta.getType(); + if (columnMeta.isFK()) { - // Save entity - PropertyDiff[] propertyDiffs = saveEntity(tableMetas, id, valuesMap, user, false); - result.add(propertyDiffs); + Class<TopiaEntity> entityType = (Class<TopiaEntity>) type; - line = bf.readLine(); - } + Collection<TopiaEntity> universe = getForeignDatas(entityType); - // Commit - getTransaction().commitTransaction(); - } catch (Exception eee) { - log.error("Failed to read import file " + importFile.getName(), eee); - throw new EchoBaseTechnicalException(eee); - } finally { - if (bf != null) { - try { - bf.close(); - } catch (IOException eee) { - log.error("Failed to close import file " + importFile.getName(), eee); - throw new EchoBaseTechnicalException(eee); - } + // translate foreign key to his id + model.addForeignKeyForImport(propertyName, entityType, universe); + + } else { + model.addDefaultColumn(propertyName, type); } } - return result; + return model; } - public File exportDatas(String tableName) { + protected <E extends TopiaEntity> DbEditorCsvModel<E> buildForExport(TableMeta tableMetas) { - Map<?, ?>[] datas = getAllDatas(tableName, false); + DbEditorCsvModel<E> model = new DbEditorCsvModel<E>(CSV_CHAR_SEPARATOR, + tableMetas); - StringBuilder csvContent = new StringBuilder(); + ModelBuilder<E> modelBuilder = model.modelBuilder; - // Build csv - boolean headerCompleted = false; + modelBuilder.newColumnForImportExport( + TopiaEntity.TOPIA_ID, + TopiaEntity.TOPIA_ID + ); - // To escape value if csv special char is found - StringUtil.ToString csvConvertor = new StringUtil.ToCSV(CSV_SEPARATOR); - for (Map<?, ?> data : datas) { + for (ColumnMeta columnMeta : model.tableMeta) { + String propertyName = columnMeta.getName(); + Class<?> type = columnMeta.getType(); + if (columnMeta.isFK()) { - // Write header - if (!headerCompleted) { - String keys = StringUtil.join(data.keySet(), csvConvertor, CSV_SEPARATOR, false); - csvContent.append(keys); - csvContent.append("\n"); - headerCompleted = true; + Class<TopiaEntity> entityType = (Class<TopiaEntity>) type; + model.addForeignKeyForExport(propertyName, entityType); + } else { + model.addDefaultColumn(propertyName, type); } - - // Write content - String values = StringUtil.join(data.values(), csvConvertor, CSV_SEPARATOR, false); - csvContent.append(values); - csvContent.append("\n"); } + return model; + } - // Write export file - SimpleDateFormat format = new SimpleDateFormat(EXPORT_FILE_FORMAT_DATE); - String now = format.format(new Date()); + protected <E extends TopiaEntity> DbEditorCsvModel<E> buildForLoad(TableMeta tableMetas, + boolean addDecorated) { - // Write in tmp dir - File tempDirectory = FileUtils.getTempDirectory(); - File file = new File(tempDirectory, EXPORT_FILE_PREFIX + now + SCV_EXT); - file.deleteOnExit(); + DbEditorCsvModel<E> model = new DbEditorCsvModel<E>(CSV_CHAR_SEPARATOR, + tableMetas); - FileWriter writer = null; - try { - writer = new FileWriter(file, true); - writer.write(csvContent.toString()); - } catch (IOException eee) { - log.error("Failed to write modif export file", eee); - throw new EchoBaseTechnicalException(eee); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException eee) { - log.error("Failed to close modif export file", eee); - throw new EchoBaseTechnicalException(eee); + ModelBuilder<E> modelBuilder = model.modelBuilder; + + modelBuilder.newColumnForImportExport( + "id", + TopiaEntity.TOPIA_ID + ); + + for (ColumnMeta columnMeta : model.tableMeta) { + String propertyName = columnMeta.getName(); + Class<?> type = columnMeta.getType(); + if (columnMeta.isFK()) { + + Class<TopiaEntity> entityType = (Class<TopiaEntity>) type; + + // translate foreign key to his id + model.addForeignKeyForExport(propertyName, entityType); + + if (addDecorated) { + + // translate foreign key to his decorated value + modelBuilder.newColumnForExport( + propertyName + "_lib", + propertyName, + CsvModelUtil.newForeignKeyDecoratedValue( + entityType, + getDecoratorService(), + getLocale()) + ); } + + } else { + model.addDefaultColumn(propertyName, type); } } - return file; + return model; } + } Modified: trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/ExportSqlService.java =================================================================== --- trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/ExportSqlService.java 2011-11-23 17:50:27 UTC (rev 109) +++ trunk/echobase-services/src/main/java/fr/ifremer/echobase/services/ExportSqlService.java 2011-11-23 17:51:57 UTC (rev 110) @@ -40,7 +40,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Date; import java.util.List; import java.util.Map; @@ -90,7 +89,7 @@ entityToSave.setName(exportQuery.getName()); entityToSave.setDescription(exportQuery.getDescription()); entityToSave.setSqlQuery(exportQuery.getSqlQuery()); - entityToSave.setLastModifiedDate(new Date()); + entityToSave.setLastModifiedDate(newDate()); entityToSave.setLastModifiedUser(user); dao.update(entityToSave); @@ -156,8 +155,7 @@ } StringBuilder buffer = new StringBuilder(); int rowCount = rows.length; - buffer.append("#Created at ").append(new Date()).append(" by user ").append(echoBaseUser.getEmail()); - buffer.append("\n#").append(StringUtils.join(columnNames, ";")); + buffer.append(StringUtils.join(columnNames, ";")); for (int i = 0; i < rowCount; i++) { Map<String, Object> row = rows[i]; buffer.append('\n').append(StringUtils.join(row.values(), ";"));