Author: tchemit Date: 2012-08-16 18:19:17 +0200 (Thu, 16 Aug 2012) New Revision: 2621 Url: http://nuiton.org/repositories/revision/topia/2621 Log: refs #2266: Add some api about import / export in csv format Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/EntityCsvModel.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/TopiaCsvCommons.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/AbstractImportModel.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvFileImportResult.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvImportResult.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/EntityAssociationImportModel.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/ImportModelFactory.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/TopiaCsvImports.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/package-info.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/AbstractExportEntityVisitor.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/Entity2.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/EntityAssociationExportModel.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/ExportModelFactory.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/TopiaCsvExports.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/package-info.java branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/package-info.java Modified: branches/topia-2.6.x/topia-persistence/pom.xml Modified: branches/topia-2.6.x/topia-persistence/pom.xml =================================================================== --- branches/topia-2.6.x/topia-persistence/pom.xml 2012-08-16 16:18:14 UTC (rev 2620) +++ branches/topia-2.6.x/topia-persistence/pom.xml 2012-08-16 16:19:17 UTC (rev 2621) @@ -24,7 +24,9 @@ #L% --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> @@ -49,6 +51,11 @@ </dependency> <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-csv</artifactId> + </dependency> + + <dependency> <groupId>org.nuiton.i18n</groupId> <artifactId>nuiton-i18n</artifactId> </dependency> @@ -59,6 +66,11 @@ </dependency> <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> </dependency> @@ -323,7 +335,9 @@ <plugin> <artifactId>maven-invoker-plugin</artifactId> <configuration> - <localRepositoryPath>${basedir}/target/local-repo</localRepositoryPath> + <localRepositoryPath> + ${basedir}/target/local-repo + </localRepositoryPath> <settingsFile>src/it/settings.xml</settingsFile> <cloneProjectsTo>${project.build.directory}/its</cloneProjectsTo> <debug>${maven.verbose}</debug> @@ -342,7 +356,7 @@ </plugins> </build> </profile> - + <!-- reporting at release time --> <profile> <id>reporting</id> @@ -360,6 +374,10 @@ <artifactId>plexus-maven-plugin</artifactId> <version>1.3.8</version> </plugin> + + <plugin> + <artifactId>maven-invoker-plugin</artifactId> + </plugin> </plugins> </reporting> Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/EntityCsvModel.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/EntityCsvModel.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/EntityCsvModel.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,233 @@ +package org.nuiton.topia.persistence.csv; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.TopiaId; +import org.nuiton.topia.persistence.metadata.TableMeta; +import org.nuiton.util.csv.ext.AbstractImportExportModel; +import org.nuiton.util.decorator.Decorator; + +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.Map; + +/** + * A model to import / export entities into csv files. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.2 + */ +public class EntityCsvModel<T extends TopiaEntityEnum, E extends TopiaEntity> extends AbstractImportExportModel<E> { + + protected final TableMeta<T> tableMeta; + + public static <T extends TopiaEntityEnum, E extends TopiaEntity> EntityCsvModel<T, E> newModel( + char separator, + TableMeta<T> tableMeta) { + return new EntityCsvModel<T, E>(separator, tableMeta); + } + + public static <T extends TopiaEntityEnum, E extends TopiaEntity> EntityCsvModel<T, E> newModel( + char separator, + TableMeta<T> tableMeta, + String idHeader) { + return new EntityCsvModel<T, E>(separator, tableMeta, idHeader); + } + + @Override + public E newEmptyInstance() { + return (E) tableMeta.newEntity(); + } + + public void addForeignKeyForExport(String propertyName, + Class<TopiaEntity> entityType) { + + Map<String, TopiaEntity> universe = Collections.emptyMap(); + + newColumnForExport( + propertyName, + TopiaCsvCommons.newForeignKeyValue(entityType, + propertyName, + universe) + ); + } + + public <T> void addDecoratedForeignKeyForExport(String headerName, + String propertyName, + Decorator<T> decorator) { + modelBuilder.newColumnForExport( + headerName, + propertyName, + TopiaCsvCommons.newForeignKeyDecoratedValue(decorator)); + } + + public <E extends TopiaEntity> void addForeignKeyForImport(String headerName, + String propertyName, + Class<E> entityType, + Collection<E> entities, + Function<E, String> transform) { + + Map<String, E> universe = Maps.uniqueIndex(entities, transform); + + newMandatoryColumn( + headerName, + propertyName, + TopiaCsvCommons.newForeignKeyValue(entityType, + propertyName, + universe) + ); + } + + public <E extends TopiaEntity> void addForeignKeyForAssociationForImport(String headerName, + String propertyName, + Class<E> entityType, + Collection<E> entities, + Function<E, String> transform) { + + Map<String, E> universe = Maps.uniqueIndex(entities, transform); + + newMandatoryColumn( + headerName, + propertyName, + TopiaCsvCommons.newForeignKeyValueAssociation(entityType, + propertyName, + universe) + ); + } + + public <E extends TopiaEntity> void addForeignKeyForImport(String propertyName, + Class<E> entityType, + Collection<E> entities) { + + Map<String, E> universe = Maps.uniqueIndex(entities, + TopiaId.GET_TOPIA_ID); + + newMandatoryColumn( + propertyName, + TopiaCsvCommons.newForeignKeyValue(entityType, + propertyName, + universe) + ); + } + + public void addDefaultColumn(String propertyName, Class<?> type) { + addDefaultColumn(propertyName, propertyName, type); + } + + public void addDefaultColumn(String headerName, + String propertyName, + Class<?> type) { + + if (Date.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.DAY_TIME_SECOND_WITH_TIMESTAMP + ); + } else if (double.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.DOUBLE_PRIMITIVE + ); + } else if (Double.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.DOUBLE + ); + } else if (long.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.PRIMITIVE_LONG + ); + } else if (Long.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.LONG + ); + } else if (float.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.PRIMITIVE_FLOAT + ); + } else if (Float.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.FLOAT + ); + } else if (int.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.PRIMITIVE_INTEGER + ); + } else if (Integer.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.INTEGER + ); + } else if (boolean.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.PRIMITIVE_BOOLEAN + ); + } else if (Boolean.class.equals(type)) { + newColumnForImportExport( + headerName, + propertyName, + TopiaCsvCommons.BOOLEAN + ); + } else { + + // string + newColumnForImportExport( + headerName, + propertyName + ); + } + } + + protected EntityCsvModel(char separator, TableMeta<T> tableMeta) { + super(separator); + this.tableMeta = tableMeta; + } + + protected EntityCsvModel(char separator, TableMeta<T> tableMeta, + String idHeader) { + this(separator, tableMeta); + newColumnForImportExport(idHeader, TopiaEntity.TOPIA_ID); + } +} \ No newline at end of file Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/EntityCsvModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/TopiaCsvCommons.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/TopiaCsvCommons.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/TopiaCsvCommons.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,262 @@ +package org.nuiton.topia.persistence.csv; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Lists; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.topia.TopiaRuntimeException; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.util.StringUtil; +import org.nuiton.util.csv.Common; +import org.nuiton.util.csv.ValueFormatter; +import org.nuiton.util.csv.ValueParser; +import org.nuiton.util.csv.ValueParserFormatter; +import org.nuiton.util.decorator.Decorator; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +/** + * More useful method added to {@link Common}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public class TopiaCsvCommons extends Common { + + protected TopiaCsvCommons() { + // no instance of this helper + } + + public static final ValueParserFormatter<Date> DAY_TIME_SECOND_WITH_TIMESTAMP = + new DateValue("dd/MM/yyyy HH:mm:ss") { + + @Override + public Date parse(String value) throws ParseException { + + Date parse = super.parse(value); + if (parse != null) { + parse = new Timestamp(parse.getTime()); + } + return parse; + } + }; + + public static final AssociationValueParser ASSOCIATION_VALUE_PARSER = new AssociationValueParser(); + + public static <E extends TopiaEntity> ForeignKeyValue<E> newForeignKeyValue(Class<E> type, String propertyName, Map<String, E> universe) { + return new ForeignKeyValue<E>(type, propertyName, universe); + } + + public static <E extends TopiaEntity> ForeignKeyValueForAssociation<E> newForeignKeyValueAssociation(Class<E> type, String propertyName, Map<String, E> universe) { + return new ForeignKeyValueForAssociation<E>(type, propertyName, universe); + } + + public static <E extends TopiaEntity> ValueFormatter<Collection<E>> newAssociationValueFormatter() { + return new AssociationValueParserFormatter<E>(null, null); + } + + public static <E> ForeignKeyDecoratedValue<E> newForeignKeyDecoratedValue(Decorator<E> decorator) { + return new ForeignKeyDecoratedValue<E>(decorator); + } + + /** + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ + public static class AssociationValueParser implements ValueParser<String[]> { + + @Override + public String[] parse(String value) throws ParseException { + String[] ids = value.split("\\|"); + return ids; + } + } + + /** + * @param <E> + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ + public static class AssociationValueParserFormatter<E extends TopiaEntity> implements ValueParserFormatter<Collection<E>> { + + protected final Class<E> entityType; + + protected final Map<String, E> universe; + + public AssociationValueParserFormatter( + Class<E> entityType, + Map<String, E> universe) { + this.entityType = entityType; + this.universe = universe; + } + + @Override + public Collection<E> parse(String value) throws ParseException { + Collection<E> result = Lists.newArrayList(); + if (StringUtils.isNotBlank(value)) { + + String[] ids = value.split("\\|"); + for (String id : ids) { + E association = universe.get(id); + association.setTopiaId(id); + result.add(association); + } + } + return result; + } + + @Override + public String format(Collection<E> e) { + + String value; + if (CollectionUtils.isEmpty(e)) { + value = ""; + } else { + Collection<String> ids = Lists.newArrayList(); + for (E e1 : e) { + ids.add(e1.getTopiaId()); + } + value = StringUtil.join(ids, "|", true); + } + return value; + } + } + + /** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ + public static class ForeignKeyDecoratedValue<E> implements ValueFormatter<E> { + + protected final Decorator<E> decorator; + + public ForeignKeyDecoratedValue(Decorator<E> decorator) { + this.decorator = decorator; + } + + @Override + public String format(E e) { + String value = ""; + if (e != null) { + value = decorator.toString(e); + } + return value; + } + } + + /** + * @param <E> + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ + public static class ForeignKeyValue<E extends TopiaEntity> implements ValueParserFormatter<E> { + + protected final String propertyName; + + protected final Class<E> entityType; + + protected final Map<String, E> universe; + + public ForeignKeyValue(Class<E> entityType, + String propertyName, + Map<String, E> universe) { + this.entityType = entityType; + this.propertyName = propertyName; + this.universe = universe; + } + + + @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 TopiaRuntimeException( + "Could not find entity of type " + + entityType.getSimpleName() + " with '" + + propertyName + "' = " + value); + } + } + return result; + } + + @Override + public String format(E e) { + String value = ""; + if (e != null) { + value = e.getTopiaId(); + } + return value; + } + } + + public static class ForeignKeyValueForAssociation<E extends TopiaEntity> implements ValueParser<Collection<E>> { + + protected final String propertyName; + + protected final Class<E> entityType; + + protected final Map<String, E> universe; + + public ForeignKeyValueForAssociation(Class<E> entityType, + String propertyName, + Map<String, E> universe) { + this.entityType = entityType; + this.propertyName = propertyName; + this.universe = universe; + } + + @Override + public Collection<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 TopiaRuntimeException( + "Could not find entity with '" + propertyName + "' = " + value); + } + } + return Arrays.asList(result); + } + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/TopiaCsvCommons.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/AbstractImportModel.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/AbstractImportModel.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/AbstractImportModel.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,50 @@ +/* + * #%L + * EchoBase :: Entities + * + * $Id$ + * $HeadURL: http://svn.forge.codelutin.com/svn/echobase/trunk/echobase-entities/src/main... $ + * %% + * Copyright (C) 2011 - 2012 Ifremer, Codelutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.topia.persistence.csv.in; + +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.csv.TopiaCsvCommons; + +import java.util.List; +import java.util.Map; + +public abstract class AbstractImportModel<E> extends org.nuiton.util.csv.ext.AbstractImportModel<E> { + + public AbstractImportModel(char separator) { + super(separator); + } + + @Override + public void pushCsvHeaderNames(List<String> headerNames) { + } + + public <E extends TopiaEntity> void newForeignKeyColumn(String headerName, String propertyName, Class<E> entityType, String foreignKeyName, Map<String, E> universe) { + newMandatoryColumn(headerName, propertyName, TopiaCsvCommons.newForeignKeyValue(entityType, foreignKeyName, universe)); + } + + public <E extends TopiaEntity> void newForeignKeyColumn(String propertyName, Class<E> entityType, String foreignKeyName, Map<String, E> universe) { + newMandatoryColumn(propertyName, propertyName, TopiaCsvCommons.newForeignKeyValue(entityType, foreignKeyName, universe)); + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/AbstractImportModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvFileImportResult.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvFileImportResult.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvFileImportResult.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,113 @@ +package org.nuiton.topia.persistence.csv.in; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.nuiton.topia.persistence.TopiaEntityEnum; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +/** + * To keep result of the import of a file. + * + * @since 2.6.12 + * @author tchemit <chemit@codelutin.com> + */ +public class CsvFileImportResult<T extends TopiaEntityEnum> implements Serializable { + + private static final long serialVersionUID = 1L; + + /** Name of the csv file to import. */ + protected final String importFileName; + + /** type of entity to import csv datas. */ + protected final Set<T> entityTypes; + + /** Count of created entities. */ + protected final Map<T, Integer> numberCreated; + + /** Count of updated entities. */ + protected final Map<T, Integer> numberUpdated; + + public static <T extends TopiaEntityEnum> CsvFileImportResult<T> newResult(String importFileName, T... universe) { + CsvFileImportResult<T> result = new CsvFileImportResult<T>( + importFileName, universe + ); + return result; + } + + public CsvFileImportResult(String importFileName, T... universe) { + this.importFileName = importFileName; + entityTypes = Sets.newHashSet(); + numberCreated = Maps.newHashMap(); + numberUpdated = Maps.newHashMap(); + for (T t : universe) { + numberCreated.put(t, 0); + numberUpdated.put(t, 0); + } + } + + public Set<T> getEntityTypes() { + return ImmutableSet.copyOf(entityTypes); + } + + public int getNumberCreated(T entityType) { + return getInteger(numberCreated, entityType); + } + + public int getNumberUpdated(T entityType) { + return getInteger(numberUpdated, entityType); + } + + public String getImportFileName() { + return importFileName; + } + + public void incrementsNumberCreated(T entityType) { + increments(numberCreated, entityType); + } + + public void incrementsNumberUpdated(T entityType) { + increments(numberUpdated, entityType); + } + + protected int getInteger(Map<T, Integer> map, T entityType) { + Integer result = map.get(entityType); + return result == null ? 0 : result; + } + + protected void increments(Map<T, Integer> map, T entityType) { + Integer result = map.get(entityType); + if (result == null) { + + entityTypes.add(entityType); + result = 0; + } + map.put(entityType, ++result); + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvFileImportResult.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvImportResult.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvImportResult.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvImportResult.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,101 @@ +package org.nuiton.topia.persistence.csv.in; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.topia.persistence.TopiaEntityEnum; + +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<T extends TopiaEntityEnum> implements Serializable { + + private static final long serialVersionUID = 1L; + + /** type of entity to import csv datas. */ + protected final T entityType; + + /** Name of the csv file to import. */ + protected final String importFileName; + + /** Flag to authorize to create entities not found in db. */ + protected final boolean createIfNotFound; + + /** Count of created entities. */ + protected int numberCreated; + + /** Count of updated entities. */ + protected int numberUpdated; + + public static <T extends TopiaEntityEnum> CsvImportResult<T> newResult(T entityType, + String importFileName, + boolean createIfNotFound) { + CsvImportResult<T> result = new CsvImportResult<T>(entityType, importFileName, + createIfNotFound); + return result; + } + + protected CsvImportResult(T entityType, + String importFileName, + boolean createIfNotFound) { + this.entityType = entityType; + this.importFileName = importFileName; + this.createIfNotFound = createIfNotFound; + } + + public T 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++; + } + +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/CsvImportResult.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/EntityAssociationImportModel.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/EntityAssociationImportModel.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/EntityAssociationImportModel.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,75 @@ +package org.nuiton.topia.persistence.csv.in; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.metadata.AssociationMeta; +import org.nuiton.topia.persistence.csv.TopiaCsvCommons; +import org.nuiton.util.csv.ImportModel; + +import java.util.Map; + +/** + * A model to import associations of entities into csv files. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public class EntityAssociationImportModel extends AbstractImportModel<Map<String, Object>> { + + protected final AssociationMeta meta; + + public static ImportModel<Map<String, Object>> newImportModel(char separator, + AssociationMeta meta + ) { + EntityAssociationImportModel model = new EntityAssociationImportModel( + separator, meta); + + // topiaId <-> topiaId + model.newMandatoryColumn( + TopiaEntity.TOPIA_ID, + TopiaCsvCommons.<Map<String, Object>, String>newMapProperty(TopiaEntity.TOPIA_ID) + ); + + // add association -> target + model.newMandatoryColumn( + meta.getName(), + TopiaCsvCommons.ASSOCIATION_VALUE_PARSER, + TopiaCsvCommons.<Map<String, Object>, String[]>newMapProperty("target") + ); + + return model; + } + + @Override + public Map<String, Object> newEmptyInstance() { + return null; + } + + public EntityAssociationImportModel(char separator, AssociationMeta meta) { + super(separator); + this.meta = meta; + } + +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/EntityAssociationImportModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/ImportModelFactory.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/ImportModelFactory.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/ImportModelFactory.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,47 @@ +package org.nuiton.topia.persistence.csv.in; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.metadata.AssociationMeta; +import org.nuiton.topia.persistence.metadata.TableMeta; +import org.nuiton.util.csv.ImportModel; + +import java.util.Map; + +/** + * To produce import model. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public interface ImportModelFactory<T extends TopiaEntityEnum> { + + <E extends TopiaEntity> ImportModel<E> buildForImport(TableMeta<T> meta); + + ImportModel<Map<String, Object>> buildForImport(AssociationMeta<T> meta); + + boolean isNMAssociationMeta(AssociationMeta<T> meta); +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/ImportModelFactory.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/TopiaCsvImports.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/TopiaCsvImports.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/TopiaCsvImports.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,231 @@ +package org.nuiton.topia.persistence.csv.in; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.TopiaContext; +import org.nuiton.topia.TopiaException; +import org.nuiton.topia.framework.TopiaContextImplementor; +import org.nuiton.topia.persistence.TopiaDAO; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.metadata.AssociationMeta; +import org.nuiton.topia.persistence.metadata.MetaFilenameAware; +import org.nuiton.topia.persistence.metadata.TableMeta; +import org.nuiton.topia.persistence.util.TopiaEntityHelper; +import org.nuiton.util.csv.Import; +import org.nuiton.util.csv.ImportModel; +import org.nuiton.util.csv.ImportToMap; + +import java.io.IOException; +import java.io.Reader; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Helper for csv imports. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public class TopiaCsvImports { + + /** Logger. */ + private static final Log log = LogFactory.getLog(TopiaCsvImports.class); + + protected TopiaCsvImports() { + // no instance of this helper + } + + public static <T extends TopiaEntityEnum> void importFile(TopiaContextImplementor tx, + ImportModelFactory<T> modelFactory, + MetaFilenameAware<T> entry, + Reader reader, + CsvImportResult<T> csvResult) throws IOException, TopiaException { + + if (entry instanceof AssociationMeta) { + + // load a association input + AssociationMeta<T> meta = (AssociationMeta<T>) entry; + ImportModel<Map<String, Object>> model = + modelFactory.buildForImport(meta); + ImportToMap importer = ImportToMap.newImportToMap(model, reader, false); + + try { + if (modelFactory.isNMAssociationMeta(meta)) { + importNMAssociationFile(tx, meta, importer, csvResult, 1000); + } else { + importAssociationFile(tx, meta, importer, csvResult, 1000); + } + } finally { + importer.close(); + } + + } else { + + // normal entity table import + TableMeta<T> meta = (TableMeta<T>) entry; + ImportModel<TopiaEntity> model = modelFactory.buildForImport(meta); + Import<TopiaEntity> importer = Import.newImport(model, reader); + + try { + TopiaDAO<TopiaEntity> dao = (TopiaDAO<TopiaEntity>) tx.getDAO(meta.getSource().getContract()); + importEntityFile(dao, meta, importer, csvResult); + } finally { + importer.close(); + } + } + + } + + public static <T extends TopiaEntityEnum> Map<MetaFilenameAware<T>, ZipEntry> discoverEntries( + String entryPrefix, + MetaFilenameAware<T>[] entries, + ZipFile zipFile, + List<String> missingEntries) { + + Map<MetaFilenameAware<T>, ZipEntry> result = Maps.newLinkedHashMap(); + + // check that all mandatories + for (MetaFilenameAware<T> entry : entries) { + String filename = entry.getFilename(); + ZipEntry zipEntry = zipFile.getEntry(entryPrefix + filename); + + if (zipEntry == null) { + missingEntries.add(filename); + } else { + result.put(entry, zipEntry); + } + } + return result; + } + + public static <T extends TopiaEntityEnum, E extends TopiaEntity> void importEntityFile(TopiaDAO<E> dao, + TableMeta<T> meta, + Import<E> importer, + CsvImportResult<T> csvResult) throws TopiaException { + + for (TopiaEntity entity : importer) { + + Map<String, Object> properties = meta.prepareCreate( + entity, entity.getTopiaId()); + E entityToSave = dao.create(properties); + + meta.copy(entity, entityToSave); + + csvResult.incrementsNumberUpdated(); + } + } + + public static <T extends TopiaEntityEnum> void importAssociationFile(TopiaContext tx, AssociationMeta<T> meta, + ImportToMap importer, + CsvImportResult<T> csvResult, + int nbRowBuffer) throws TopiaException { + + T source = meta.getSource(); + T target = meta.getTarget(); + + StringBuilder builder = new StringBuilder(); + + String targetTableName = target.getContract().getSimpleName(); + String sourceTableName = source.getContract().getSimpleName(); + String table = targetTableName; + + String updateString = String.format("UPDATE %s SET %s = '%%s' WHERE topiaId ='%%s';", table, sourceTableName); + + if (log.isDebugEnabled()) { + log.debug("Will apply " + updateString); + } + int compt = 0; + for (Map<String, Object> row : importer) { + String topiaId = (String) row.get(TopiaEntity.TOPIA_ID); + String[] associations = (String[]) row.get("target"); + for (String association : associations) { + if (StringUtils.isNotEmpty(association)) { + builder.append(String.format(updateString, topiaId, association)).append('\n'); + compt++; + if (compt % nbRowBuffer == 0) { + // flush it + tx.executeSQL(builder.toString()); + builder = new StringBuilder(); + } + } + } + csvResult.incrementsNumberUpdated(); + } + if (builder.length() > 0) { + tx.executeSQL(builder.toString()); + } + } + + public static <T extends TopiaEntityEnum> void importNMAssociationFile(TopiaContext tx, AssociationMeta<T> meta, + ImportToMap importer, + CsvImportResult<T> csvResult, + int nbRowBuffer) throws TopiaException { + + T source = meta.getSource(); + T target = meta.getTarget(); + + StringBuilder builder = new StringBuilder(); + + + String targetTableName = target.getContract().getSimpleName(); + String sourceTableName = source.getContract().getSimpleName(); + + // relation *-* + String table = TopiaEntityHelper.getNormalizedAssociationTableName( + sourceTableName, targetTableName); + + String updateString = String.format("INSERT INTO %s (%s,%s) VALUES('%%s','%%s');", table, sourceTableName, targetTableName); + + if (log.isDebugEnabled()) { + log.debug("Will apply " + updateString); + } + int compt = 0; + for (Map<String, Object> row : importer) { + String topiaId = (String) row.get(TopiaEntity.TOPIA_ID); + String[] associations = (String[]) row.get("target"); + for (String association : associations) { + if (StringUtils.isNotEmpty(association)) { + builder.append(String.format(updateString, topiaId, association)).append('\n'); + compt++; + if (compt % nbRowBuffer == 0) { + // flush it + tx.executeSQL(builder.toString()); + builder = new StringBuilder(); + } + } + } + csvResult.incrementsNumberUpdated(); + } + if (builder.length() > 0) { + tx.executeSQL(builder.toString()); + } + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/TopiaCsvImports.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/package-info.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/package-info.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/package-info.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,7 @@ +/** + * Package for csv import of entities. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +package org.nuiton.topia.persistence.csv.in; \ No newline at end of file Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/in/package-info.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/AbstractExportEntityVisitor.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/AbstractExportEntityVisitor.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/AbstractExportEntityVisitor.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,181 @@ +package org.nuiton.topia.persistence.csv.out; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.TopiaException; +import org.nuiton.topia.TopiaRuntimeException; +import org.nuiton.topia.persistence.EntityVisitor; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.util.TimeLog; + +import java.util.Collection; +import java.util.Map; + +/** + * entity visitor to export data to csv files. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.3 + */ +public abstract class AbstractExportEntityVisitor<T extends TopiaEntityEnum> implements EntityVisitor { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(AbstractExportEntityVisitor.class); + + public static final TimeLog TIME_LOG = + new TimeLog(AbstractExportEntityVisitor.class); + + + protected abstract boolean isNoChildVisit(String propertyName, TopiaEntity entity); + + + /** Export for simple entity. */ + protected final Map<Class<?>, TopiaCsvExports.EntityExportContext> entityExporters; + + public AbstractExportEntityVisitor(Map<Class<?>, TopiaCsvExports.EntityExportContext> entityExporters) { + this.entityExporters = entityExporters; + } + + public void export(TopiaEntity entity) { + Preconditions.checkNotNull(entity); + long s1 = TimeLog.getTime(); + try { + entity.accept(this); + } catch (TopiaException e) { + throw new TopiaRuntimeException( + "Could not export entity " + entity.getTopiaId(), e); + } finally { + TIME_LOG.log(s1, "export::" + entity.getTopiaId()); + } + } + + @Override + public void start(TopiaEntity entity) { + String topiaId = entity.getTopiaId(); + try { + if (log.isDebugEnabled()) { + log.debug("Starts export of entity " + topiaId); + } + TopiaCsvExports.EntityExportContext entityExporter = + entityExporters.get(entity.getClass()); + entityExporter.write(entity); + } catch (Exception e) { + throw new TopiaRuntimeException( + "Could not export entity " + entity, e); + } finally { + if (log.isDebugEnabled()) { + log.debug("Ends export of entity " + topiaId); + } + } + } + + @Override + public void end(TopiaEntity entity) { + try { + if (log.isDebugEnabled()) { + log.debug("Starts export of association of entity " + + entity.getTopiaId()); + } + TopiaCsvExports.EntityExportContext entityExporter = + entityExporters.get(entity.getClass()); + entityExporter.writeAssociations(entity); + } catch (Exception e) { + throw new TopiaRuntimeException( + "Could not export associations of entity " + entity, e); + } finally { + if (log.isDebugEnabled()) { + log.debug("Ends export of association of entity " + + entity.getTopiaId()); + } + } + } + + @Override + public void visit(TopiaEntity entity, String propertyName, + Class<?> type, Object value) { + } + + @Override + public void visit(TopiaEntity entity, + String propertyName, + Class<?> collectionType, + Class<?> type, + Object value) { + + if (TopiaEntity.class.isAssignableFrom(type) && + entityExporters.containsKey(type)) { + Collection<?> cValue = (Collection<?>) value; + + if (CollectionUtils.isNotEmpty(cValue)) { + + if (isNoChildVisit(propertyName, entity) && + Entity2.class.isAssignableFrom(type)) { + + // special case, when visiting a entity with no child + // visisting at this time... + for (Object currentValue : cValue) { + ((Entity2) currentValue).accept2(this); + } + } else { + for (Object currentValue : cValue) { + try { + ((TopiaEntity) currentValue).accept(this); + } catch (TopiaException e) { + if (log.isErrorEnabled()) { + log.error("Can not visit entity " + value, e); + } + } + } + } + } + } + } + + @Override + public void visit(TopiaEntity entity, + String propertyName, + Class<?> collectionType, Class<?> type, + int index, + Object value) { + + // nothing to do + } + + @Override + public void clear() { + + // use at the end of visit (or later) + + for (TopiaCsvExports.EntityExportContext exportContext : entityExporters.values()) { + IOUtils.closeQuietly(exportContext); + } + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/AbstractExportEntityVisitor.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/Entity2.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/Entity2.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/Entity2.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,40 @@ +package org.nuiton.topia.persistence.csv.out; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.topia.persistence.EntityVisitor; +import org.nuiton.topia.persistence.TopiaEntity; + +/** + * To mark some entites visitable but not by generatl + * {@link TopiaEntity#accept(EntityVisitor)} method. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public interface Entity2 { + + void accept2(EntityVisitor visitor); + +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/Entity2.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/EntityAssociationExportModel.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/EntityAssociationExportModel.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/EntityAssociationExportModel.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,64 @@ +package org.nuiton.topia.persistence.csv.out; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.metadata.AssociationMeta; +import org.nuiton.topia.persistence.csv.TopiaCsvCommons; +import org.nuiton.util.csv.ExportModel; +import org.nuiton.util.csv.ext.AbstractExportModel; + +/** + * A model to export associations of entities into csv files. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public class EntityAssociationExportModel<T extends TopiaEntityEnum, E extends TopiaEntity> extends AbstractExportModel<E> { + + protected final AssociationMeta meta; + + public static <T extends TopiaEntityEnum, E extends TopiaEntity> ExportModel<E> newExportModel(char separator, + AssociationMeta<T> meta + ) { + EntityAssociationExportModel<T, E> model = new EntityAssociationExportModel<T, E>( + separator, + meta); + + // topiaId <-> topiaId + model.newColumnForExport(TopiaEntity.TOPIA_ID); + + model.newColumnForExport( + meta.getName(), + TopiaCsvCommons.newAssociationValueFormatter() + ); + return model; + } + + EntityAssociationExportModel(char separator, AssociationMeta<T> meta) { + super(separator); + this.meta = meta; + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/EntityAssociationExportModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/ExportModelFactory.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/ExportModelFactory.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/ExportModelFactory.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,43 @@ +package org.nuiton.topia.persistence.csv.out; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.metadata.AssociationMeta; +import org.nuiton.topia.persistence.metadata.TableMeta; +import org.nuiton.util.csv.ExportModel; + +/** +* To produce export model. +* +* @author tchemit <chemit@codelutin.com> +* @since 2.6.12 +*/ +public interface ExportModelFactory<T extends TopiaEntityEnum> { + + <E extends TopiaEntity> ExportModel<E> buildForExport(TableMeta<T> meta, boolean asSeen); + + <E extends TopiaEntity> ExportModel<E> buildForExport(AssociationMeta<T> associationMeta); +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/ExportModelFactory.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/TopiaCsvExports.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/TopiaCsvExports.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/TopiaCsvExports.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,283 @@ +package org.nuiton.topia.persistence.csv.out; +/* + * #%L + * ToPIA :: Persistence + * $Id$ + * $HeadURL:$ + * %% + * Copyright (C) 2004 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityEnum; +import org.nuiton.topia.persistence.metadata.AssociationMeta; +import org.nuiton.topia.persistence.metadata.MetaFilenameAware; +import org.nuiton.topia.persistence.metadata.TableMeta; +import org.nuiton.util.csv.ExportModel; +import org.nuiton.util.csv.ext.RepeatableExport; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * Helper for csv exports. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +public class TopiaCsvExports { + + /** Logger. */ + private static final Log log = LogFactory.getLog(TopiaCsvExports.class); + + protected TopiaCsvExports() { + // no instance of this helper + } + + public static <T extends TopiaEntityEnum> Map<Class<?>, EntityExportContext> createReplicateEntityVisitorContexts(ExportModelFactory<T> modelFactory, + MetaFilenameAware<T>[] entityMetas, + Multimap<T, MetaFilenameAware<T>> associations, + File container) { + + Preconditions.checkNotNull(modelFactory); + Preconditions.checkNotNull(entityMetas); + Preconditions.checkNotNull(associations); + Preconditions.checkNotNull(container); + + Map<Class<?>, EntityExportContext> contexts = Maps.newHashMap(); + + for (MetaFilenameAware<T> entityMeta : entityMetas) { + TableMeta<T> meta = (TableMeta<T>) entityMeta; + T source = meta.getSource(); + + Collection<MetaFilenameAware<T>> metaFilenameAwares = associations.get(source); + + ExportModel<TopiaEntity> model = modelFactory.buildForExport(meta, false); + + EntityExportContext<T> exportContext = EntityExportContext.newExportContext( + model, + meta, + container); + + // save both for contract and implementation with same context + contexts.put(source.getContract(), exportContext); + contexts.put(source.getImplementation(), exportContext); + + for (MetaFilenameAware<T> metaFilenameAware : metaFilenameAwares) { + AssociationMeta<T> associationMeta = (AssociationMeta<T>) metaFilenameAware; + + ExportModel<TopiaEntity> associationModel = + modelFactory.buildForExport(associationMeta); + exportContext.addAssociationExportContext(associationMeta, + associationModel, + container); + } + } + return contexts; + } + + + /** + * to export entity as csv files. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ + public static class EntityExportContext<T extends TopiaEntityEnum> implements Closeable { + + /** meta to export. */ + protected final TableMeta<T> meta; + + /** Exporter object. */ + protected final RepeatableExport export; + + /** Where to export datas. */ + protected final Writer writer; + + /** + * Unique list to store data to export. (will be shared with + * association export contexts.) + */ + private final List<TopiaEntity> data; + + /** Association export context for this type of entity. */ + protected final Collection<AssociationExportContext<T>> associationExportContexts; + + protected final File entryFile; + + public static <T extends TopiaEntityEnum> EntityExportContext<T> newExportContext( + ExportModel<TopiaEntity> model, + TableMeta<T> meta, + File container + ) { + return new EntityExportContext<T>(model, meta, container); + } + + protected EntityExportContext(ExportModel<TopiaEntity> model, + TableMeta<T> meta, + File container) { + Preconditions.checkNotNull(model); + Preconditions.checkNotNull(meta); + Preconditions.checkNotNull(container); + + this.meta = meta; + data = Lists.newArrayList(); + export = RepeatableExport.newExport(model, data, true); + entryFile = meta.newFile(container); + if (log.isDebugEnabled()) { + log.debug("Creates EntityExportContext::" + meta + " - " + + entryFile.getName()); + } + writer = meta.newWriter(container); + associationExportContexts = Lists.newArrayList(); + } + + public void addAssociationExportContext(AssociationMeta<T> meta, + ExportModel<TopiaEntity> model, + File container) { + associationExportContexts.add( + new AssociationExportContext<T>(model, + meta, + container, + data) + ); + } + + @Override + public void close() throws IOException { + + try { + if (export.isHeaderWritten()) { + + if (log.isInfoEnabled()) { + log.info("Export table " + meta + " to " + entryFile); + } + writer.flush(); + } else { + // this file was not used, delete it + FileUtils.deleteQuietly(entryFile); + } + } finally { + IOUtils.closeQuietly(writer); + for (AssociationExportContext<T> c : associationExportContexts) { + c.close(); + } + } + } + + public void write(TopiaEntity data) throws Exception { + this.data.add(data); + try { + export.write(writer); + } finally { + this.data.clear(); + } + } + + public void writeAssociations(TopiaEntity data) throws Exception { + this.data.add(data); + try { + for (AssociationExportContext<T> c : associationExportContexts) { + AssociationMeta<T> cMeta = c.meta; + boolean emptyChild = cMeta.isChildEmpty(data); + if (!emptyChild) { + c.write(); + } + } + } finally { + this.data.clear(); + } + } + } + + /** + * To export associations as csv files. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ + public static class AssociationExportContext<T extends TopiaEntityEnum> implements Closeable { + + /** association meta to export. */ + protected final AssociationMeta<T> meta; + + /** Exporter object. */ + protected final RepeatableExport export; + + /** Where to export datas. */ + protected final Writer writer; + + protected final File entryFile; + + protected AssociationExportContext(ExportModel<TopiaEntity> model, + AssociationMeta<T> meta, + File container, + List<TopiaEntity> data) { + Preconditions.checkNotNull(model); + Preconditions.checkNotNull(meta); + Preconditions.checkNotNull(container); + Preconditions.checkNotNull(data); + this.meta = meta; + + export = RepeatableExport.newExport(model, data, true); + + entryFile = meta.newFile(container); + if (log.isDebugEnabled()) { + log.debug("Creates AssociationExportContext::" + meta + + " - " + entryFile.getName()); + } + writer = meta.newWriter(container); + } + + @Override + public void close() throws IOException { + try { + if (export.isHeaderWritten()) { + + if (log.isInfoEnabled()) { + log.info("Export association " + meta + " to " + entryFile); + } + writer.flush(); + } else { + + // this file was not used, delete it + FileUtils.deleteQuietly(entryFile); + } + } finally { + IOUtils.closeQuietly(writer); + } + } + + public void write() throws Exception { + export.write(writer); + } + } +} Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/TopiaCsvExports.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/package-info.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/package-info.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/package-info.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,7 @@ +/** + * Package for csv export of entities. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +package org.nuiton.topia.persistence.csv.out; \ No newline at end of file Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/out/package-info.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/package-info.java =================================================================== --- branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/package-info.java (rev 0) +++ branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/package-info.java 2012-08-16 16:19:17 UTC (rev 2621) @@ -0,0 +1,7 @@ +/** + * Base package for csv import and export of entities. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.6.12 + */ +package org.nuiton.topia.persistence.csv; \ No newline at end of file Property changes on: branches/topia-2.6.x/topia-persistence/src/main/java/org/nuiton/topia/persistence/csv/package-info.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native