diff --git a/src/main/java/tech/ailef/dbadmin/external/controller/DataExportController.java b/src/main/java/tech/ailef/dbadmin/external/controller/DataExportController.java new file mode 100644 index 0000000..fdf4ad2 --- /dev/null +++ b/src/main/java/tech/ailef/dbadmin/external/controller/DataExportController.java @@ -0,0 +1,83 @@ +package tech.ailef.dbadmin.external.controller; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import tech.ailef.dbadmin.external.DbAdmin; +import tech.ailef.dbadmin.external.dbmapping.DbAdminRepository; +import tech.ailef.dbadmin.external.dbmapping.DbField; +import tech.ailef.dbadmin.external.dbmapping.DbObject; +import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema; +import tech.ailef.dbadmin.external.dto.QueryFilter; +import tech.ailef.dbadmin.external.exceptions.DbAdminException; +import tech.ailef.dbadmin.external.misc.Utils; + +@Controller +@RequestMapping(value= {"/${dbadmin.baseUrl}/export", "/${dbadmin.baseUrl}/export/"}) +public class DataExportController { + + @Autowired + private DbAdmin dbAdmin; + + @Autowired + private DbAdminRepository repository; + + @GetMapping("/{className}") + @ResponseBody + public ResponseEntity export(@PathVariable String className, + @RequestParam(required=false) String query, + @RequestParam MultiValueMap otherParams) { + + DbObjectSchema schema = dbAdmin.findSchemaByClassName(className); + + Set queryFilters = Utils.computeFilters(schema, otherParams); + + System.out.println("QF = " + queryFilters); + + List results = repository.search(schema, query, queryFilters); + + String result = toCsv(results, schema.getSortedFields()); + return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename=\"export_" + schema.getClass().getSimpleName() + ".csv\"") + .body(result.getBytes()); + } + + private String toCsv(List items, List fields) { + if (items.isEmpty()) return ""; + + StringWriter sw = new StringWriter(); + + CSVFormat csvFormat = CSVFormat.DEFAULT.builder() +// .setHeader(HEADERS) + .build(); + + try (final CSVPrinter printer = new CSVPrinter(sw, csvFormat)) { + for (DbObject item : items) { + printer.printRecord(fields.stream().map(f -> { + return item.get(f).getFormattedValue(); + })); + } + + return sw.toString(); + } catch (IOException e) { + throw new DbAdminException(e); + } + } + +} diff --git a/src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java b/src/main/java/tech/ailef/dbadmin/external/controller/FileDownloadController.java similarity index 99% rename from src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java rename to src/main/java/tech/ailef/dbadmin/external/controller/FileDownloadController.java index 2c43315..25448ed 100644 --- a/src/main/java/tech/ailef/dbadmin/external/controller/DownloadController.java +++ b/src/main/java/tech/ailef/dbadmin/external/controller/FileDownloadController.java @@ -48,7 +48,7 @@ import tech.ailef.dbadmin.external.exceptions.DbAdminException; */ @Controller @RequestMapping(value = {"/${dbadmin.baseUrl}/download", "/${dbadmin.baseUrl}/download/"}) -public class DownloadController { +public class FileDownloadController { @Autowired private DbAdminRepository repository; diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java index d81c139..e638e05 100644 --- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java +++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/CustomJpaRepository.java @@ -101,6 +101,12 @@ public class CustomJpaRepository extends SimpleJpaRepository { .setFirstResult((page - 1) * pageSize).getResultList(); } + + public List search(String query, Set filters) { + return search(query, 1, Integer.MAX_VALUE, null, null, filters); + } + + @SuppressWarnings("unchecked") public int update(DbObjectSchema schema, Map params, Map files) { diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java index 49f4aed..4ff85ab 100644 --- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java +++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbAdminRepository.java @@ -87,6 +87,17 @@ public class DbAdminRepository { public long count(DbObjectSchema schema, String query, Set queryFilters) { return schema.getJpaRepository().count(query, queryFilters); } + + public List search(DbObjectSchema schema, String query, Set queryFilters) { + CustomJpaRepository jpaRepository = schema.getJpaRepository(); + + long maxElement = count(schema, query, queryFilters); + + return jpaRepository.search(query, queryFilters).stream() + .map(o -> new DbObject(o, schema)) + .toList(); + + } /** diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java index de676ad..9b307cd 100644 --- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java +++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbField.java @@ -227,6 +227,16 @@ public class DbField { && getPrimitiveField().getAnnotation(ManyToMany.class) == null; } + /** + * Returns whether this field is exportable into a CSV file. + * + * @return + */ + public boolean isExportable() { + return !isBinary(); + } + + public boolean isGeneratedValue() { return getPrimitiveField().getAnnotation(GeneratedValue.class) != null; } diff --git a/src/main/resources/templates/model/list.html b/src/main/resources/templates/model/list.html index a813ccb..666f90b 100644 --- a/src/main/resources/templates/model/list.html +++ b/src/main/resources/templates/model/list.html @@ -3,6 +3,53 @@ + + + + +
@@ -59,6 +106,9 @@ [[ ${schema.getTableName()} ]] +