diff --git a/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java b/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java index 211b8a310..170e65b61 100644 --- a/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java +++ b/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java @@ -59,7 +59,7 @@ import com.databasepreservation.common.api.utils.ViewerStreamingOutput; import com.databasepreservation.common.api.v1.utils.IterableIndexResultsCSVOutputStream; import com.databasepreservation.common.api.v1.utils.ResultsCSVOutputStream; -import com.databasepreservation.common.api.v1.utils.ZipOutputStream; +import com.databasepreservation.common.api.v1.utils.ZipOutputStreamMultiRow; import com.databasepreservation.common.api.v1.utils.ZipOutputStreamSingleRow; import com.databasepreservation.common.client.ViewerConstants; import com.databasepreservation.common.client.common.search.SavedSearch; @@ -81,6 +81,7 @@ import com.databasepreservation.common.client.models.structure.ViewerDatabaseStatus; import com.databasepreservation.common.client.models.structure.ViewerRow; import com.databasepreservation.common.client.models.structure.ViewerTable; +import com.databasepreservation.common.client.models.structure.ViewerType; import com.databasepreservation.common.client.models.user.User; import com.databasepreservation.common.client.services.CollectionService; import com.databasepreservation.common.client.tools.ViewerStringUtils; @@ -493,6 +494,10 @@ public Response exportLOB(@PathParam(ViewerConstants.API_PATH_PARAM_DATABASE_UUI .getConfigurationCollection(databaseUUID, databaseUUID); final TableStatus configTable = configurationCollection.getTableStatusByTableId(row.getTableId()); + if (ViewerType.dbTypes.CLOB.equals(configTable.getColumnByIndex(columnIndex).getType())) { + return handleClobDownload(configTable, row, columnIndex); + } + if (configurationCollection.getConsolidateProperty().equals(LargeObjectConsolidateProperty.CONSOLIDATED)) { return handleConsolidatedLobDownload(databaseUUID, configTable, columnIndex, row, rowIndex); } else { @@ -529,6 +534,20 @@ private Response handleConsolidatedLobDownload(String databaseUUID, TableStatus databaseUUID, row.getTableId(), columnIndex, rowIndex))))); } + private Response handleClobDownload(TableStatus tableConfiguration, ViewerRow row, int columnIndex) { + String handlebarsFilename = HandlebarsUtils.applyExportTemplate(row, tableConfiguration, columnIndex); + + if (ViewerStringUtils.isBlank(handlebarsFilename)) { + handlebarsFilename = "file_" + columnIndex; + } + + ByteArrayInputStream inputStream = new ByteArrayInputStream( + row.getCells().get(tableConfiguration.getColumnByIndex(columnIndex).getId()).getValue().getBytes()); + + return ApiUtils.okResponse(new StreamResponse(handlebarsFilename, + tableConfiguration.getColumnByIndex(columnIndex).getApplicationType(), DownloadUtils.stream(inputStream))); + } + private Response handleExternalLobDownload(TableStatus tableConfiguration, ViewerRow row, int columnIndex) throws FileNotFoundException { final String lobLocation = row.getCells().get(tableConfiguration.getColumnByIndex(columnIndex).getId()).getValue(); @@ -743,8 +762,8 @@ private Response handleCSVExportWithLobs(DatabaseRowsSolrManager solrManager, final IterableIndexResult clone = solrManager.findAllRows(databaseUUID, findRequest.filter, findRequest.sorter, fields, findRequest.extraParameters); return ApiUtils.okResponse(new StreamResponse( - new ZipOutputStream(configurationCollection, databaseUUID, database, configTable, allRows, clone, zipFilename, - filename, findRequest.fieldsToReturn, findRequest.sublist, exportDescription, fieldsToHeader))); + new ZipOutputStreamMultiRow(configurationCollection, database, configTable, allRows, clone, zipFilename, + filename, findRequest.sublist, exportDescription, fieldsToHeader))); } private Object[] appendValue(Object[] obj, Object newObj) { diff --git a/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStream.java b/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStream.java index 48df8dee8..28f3627ce 100644 --- a/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStream.java +++ b/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStream.java @@ -2,123 +2,94 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; import java.util.zip.ZipFile; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.compress.archivers.zip.Zip64Mode; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; -import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.io.IOUtils; -import org.roda.core.data.v2.index.sublist.Sublist; - import com.databasepreservation.common.api.utils.ExtraMediaType; import com.databasepreservation.common.api.utils.HandlebarsUtils; import com.databasepreservation.common.client.ViewerConstants; -import com.databasepreservation.common.client.models.status.collection.CollectionStatus; import com.databasepreservation.common.client.models.status.collection.ColumnStatus; import com.databasepreservation.common.client.models.status.collection.LargeObjectConsolidateProperty; -import com.databasepreservation.common.client.models.status.collection.TableStatus; import com.databasepreservation.common.client.models.structure.ViewerCell; -import com.databasepreservation.common.client.models.structure.ViewerDatabase; import com.databasepreservation.common.client.models.structure.ViewerRow; +import com.databasepreservation.common.client.models.structure.ViewerType; +import com.databasepreservation.common.client.tools.ViewerStringUtils; import com.databasepreservation.common.server.ViewerFactory; -import com.databasepreservation.common.server.index.utils.IterableIndexResult; import com.databasepreservation.common.utils.FilenameUtils; import com.databasepreservation.common.utils.LobManagerUtils; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.io.IOUtils; +import org.roda.core.data.v2.index.sublist.Sublist; + +import com.databasepreservation.common.client.models.status.collection.CollectionStatus; +import com.databasepreservation.common.client.models.status.collection.TableStatus; +import com.databasepreservation.common.client.models.structure.ViewerDatabase; /** * @author Miguel Guimarães */ -public class ZipOutputStream extends CSVOutputStream { +public abstract class ZipOutputStream extends CSVOutputStream { + private final CollectionStatus configurationCollection; - private final String databaseUUID; private final ViewerDatabase database; private final TableStatus configTable; private final String zipFilename; private final String csvFilename; - private final IterableIndexResult viewerRows; - private final IterableIndexResult viewerRowsClone; private final List fieldsToReturn; - private Sublist sublist; private final boolean exportDescriptions; - public ZipOutputStream(final CollectionStatus configurationCollection, final String databaseUUID, - final ViewerDatabase database, final TableStatus configTable, final IterableIndexResult viewerRows, - final IterableIndexResult viewerRowsClone, final String zipFilename, final String csvFilename, - List fieldsToReturn, Sublist sublist, boolean exportDescriptions, String fieldsToHeader) { + public ZipOutputStream(CollectionStatus configurationCollection, ViewerDatabase database, TableStatus configTable, + String zipFilename, String csvFilename, List fieldsToReturn, boolean exportDescriptions) { super(zipFilename, ','); this.configurationCollection = configurationCollection; - this.databaseUUID = databaseUUID; this.database = database; this.configTable = configTable; this.zipFilename = zipFilename; this.csvFilename = csvFilename; - this.viewerRows = viewerRows; - this.fieldsToReturn = Stream.of(fieldsToHeader.split(",")).collect(Collectors.toList()); - this.viewerRowsClone = viewerRowsClone; - this.sublist = sublist; + this.fieldsToReturn = fieldsToReturn; this.exportDescriptions = exportDescriptions; } - @Override - public void consumeOutputStream(OutputStream out) throws IOException { - ZipFile siardArchive = new ZipFile(database.getPath()); + public CollectionStatus getConfigurationCollection() { + return configurationCollection; + } - boolean all = false; - if (sublist == null) { - sublist = Sublist.NONE; - all = true; - } - Iterator iterator = viewerRows.iterator(); - int nIndex = 0; + public ViewerDatabase getDatabase() { + return database; + } - int maxIndex = sublist.getFirstElementIndex() + sublist.getMaximumElementCount(); + public TableStatus getConfigTable() { + return configTable; + } - try (ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(out)) { - zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded); - zipArchiveOutputStream.setMethod(ZipArchiveOutputStream.DEFLATED); + public String getZipFilename() { + return zipFilename; + } - final List binaryColumns = configTable.getBinaryColumns(); - while (iterator.hasNext() && (nIndex < maxIndex || all)) { - ViewerRow row = iterator.next(); - if (nIndex < (sublist.getFirstElementIndex())) { - nIndex++; - continue; - } else { - writeToZipFile(siardArchive, zipArchiveOutputStream, row, binaryColumns); - } - nIndex++; - } + public String getCsvFilename() { + return csvFilename; + } - nIndex = 0; - final ByteArrayOutputStream byteArrayOutputStream = writeCSVFile(nIndex, all); - zipArchiveOutputStream.putArchiveEntry(new ZipArchiveEntry(csvFilename)); - zipArchiveOutputStream.write(byteArrayOutputStream.toByteArray()); - byteArrayOutputStream.close(); - zipArchiveOutputStream.closeArchiveEntry(); + public List getFieldsToReturn() { + return fieldsToReturn; + } - zipArchiveOutputStream.finish(); - zipArchiveOutputStream.flush(); - } + public boolean isExportDescriptions() { + return exportDescriptions; } @Override public String getFileName() { - return this.zipFilename; + return getZipFilename(); } @Override @@ -126,7 +97,10 @@ public String getMediaType() { return ExtraMediaType.APPLICATION_ZIP; } - private ColumnStatus findBinaryColumn(final List columns, final String cell) { + @Override + public abstract void consumeOutputStream(OutputStream out) throws IOException; + + protected ColumnStatus findLobColumn(final List columns, final String cell) { for (ColumnStatus column : columns) { if (column.getId().equals(cell)) { return column; @@ -135,14 +109,16 @@ private ColumnStatus findBinaryColumn(final List columns, final St return null; } - private void writeToZipFile(ZipFile siardArchive, ZipArchiveOutputStream out, ViewerRow row, - List binaryColumns) throws IOException { + protected void writeToZipFile(ZipFile siardArchive, ZipArchiveOutputStream out, ViewerRow row, + List binaryColumns) throws IOException { for (Map.Entry cellEntry : row.getCells().entrySet()) { - final ColumnStatus binaryColumn = findBinaryColumn(binaryColumns, cellEntry.getKey()); + final ColumnStatus binaryColumn = findLobColumn(binaryColumns, cellEntry.getKey()); if (binaryColumn != null) { - if (configurationCollection.getConsolidateProperty().equals(LargeObjectConsolidateProperty.CONSOLIDATED)) { + if (ViewerType.dbTypes.CLOB.equals(binaryColumn.getType())) { + handleWriteClob(out, binaryColumn, row); + } else if (configurationCollection.getConsolidateProperty().equals(LargeObjectConsolidateProperty.CONSOLIDATED)) { handleWriteConsolidateLobs(out, binaryColumn, row); } else { if (configTable.getColumnByIndex(binaryColumn.getColumnIndex()).isExternalLob()) { @@ -155,50 +131,19 @@ private void writeToZipFile(ZipFile siardArchive, ZipArchiveOutputStream out, Vi } } - private ByteArrayOutputStream writeCSVFile(int nIndex, boolean all) throws IOException { - ByteArrayOutputStream listBytes = new ByteArrayOutputStream(); - try (final OutputStreamWriter writer = new OutputStreamWriter(listBytes)) { - CSVPrinter printer = null; - boolean isFirst = true; - - int maxIndex = sublist.getFirstElementIndex() + sublist.getMaximumElementCount(); - - Iterator iterator = viewerRowsClone.iterator(); - while (iterator.hasNext() && (nIndex < maxIndex || all)) { - ViewerRow row = iterator.next(); - if (nIndex < sublist.getFirstElementIndex()) { - nIndex++; - continue; - } else { - if (isFirst) { - printer = new CSVPrinter(writer, getFormat() - .withHeader(configTable.getCSVHeaders(fieldsToReturn, exportDescriptions).toArray(new String[0]))); - isFirst = false; - } - - printer.printRecord(HandlebarsUtils.getCellValues(row, configTable, fieldsToReturn)); - } - nIndex++; - } - viewerRowsClone.close(); - } - - return listBytes; - } - private void handleWriteConsolidateLobs(ZipArchiveOutputStream out, ColumnStatus binaryColumn, ViewerRow row) - throws IOException { + throws IOException { final Path consolidatedPath = LobManagerUtils.getConsolidatedPath(ViewerFactory.getViewerConfiguration(), - databaseUUID, configTable.getId(), binaryColumn.getColumnIndex(), row.getUuid()); + database.getUuid(), configTable.getId(), binaryColumn.getColumnIndex(), row.getUuid()); InputStream in = new FileInputStream(consolidatedPath.toFile()); final String templateFilename = FilenameUtils.getTemplateFilename(row, configTable, binaryColumn, - consolidatedPath.getFileName().toString()); + consolidatedPath.getFileName().toString()); addEntryToZip(out, in, templateFilename); } private void handleWriteInternalLobs(ZipArchiveOutputStream out, ZipFile siardArchive, ColumnStatus binaryColumn, - ViewerRow row) throws IOException { + ViewerRow row) throws IOException { final String templateFilename = FilenameUtils.getTemplateFilename(row, configTable, binaryColumn); if (LobManagerUtils.isLobEmbedded(configTable, row, binaryColumn.getColumnIndex())) { @@ -209,23 +154,45 @@ private void handleWriteInternalLobs(ZipArchiveOutputStream out, ZipFile siardAr addEntryToZip(out, new BufferedInputStream(new ByteArrayInputStream(decodedString.getBytes())), templateFilename); } else { final InputStream in = siardArchive.getInputStream( - siardArchive.getEntry(LobManagerUtils.getZipFilePath(configTable, binaryColumn.getColumnIndex(), row))); + siardArchive.getEntry(LobManagerUtils.getZipFilePath(configTable, binaryColumn.getColumnIndex(), row))); addEntryToZip(out, in, templateFilename); } } private void handleWriteExternalLobs(ZipArchiveOutputStream out, ColumnStatus binaryColumn, ViewerRow row, - ViewerCell cell) throws IOException { + ViewerCell cell) throws IOException { final String lobLocation = cell.getValue(); final Path lobPath = Paths.get(lobLocation); final Path completeLobPath = ViewerFactory.getViewerConfiguration().getSIARDFilesPath().resolve(lobPath); final String templateFilename = FilenameUtils.getTemplateFilename(row, configTable, binaryColumn, - completeLobPath.getFileName().toString()); + completeLobPath.getFileName().toString()); InputStream inputStream = new FileInputStream(lobPath.toFile()); addEntryToZip(out, inputStream, templateFilename); } + private void handleWriteClob(ZipArchiveOutputStream out, ColumnStatus binaryColumn, ViewerRow row) + throws IOException { + + String handlebarsFilename = HandlebarsUtils.applyExportTemplate(row, configTable, binaryColumn.getColumnIndex()); + + if (ViewerStringUtils.isBlank(handlebarsFilename)) { + handlebarsFilename = "file_" + binaryColumn.getColumnIndex(); + } + + ByteArrayInputStream in = new ByteArrayInputStream( + row.getCells().get(binaryColumn.getId()).getValue().getBytes()); + + addClobEntryToZip(out, in, handlebarsFilename); + } + + private void addClobEntryToZip(ZipArchiveOutputStream out, InputStream in, String templateFilename) throws IOException { + out.putArchiveEntry(new ZipArchiveEntry(ViewerConstants.INTERNAL_ZIP_CLOB_FOLDER + templateFilename)); + IOUtils.copy(in, out); + in.close(); + out.closeArchiveEntry(); + } + private void addEntryToZip(ZipArchiveOutputStream out, InputStream in, String templateFilename) throws IOException { out.putArchiveEntry(new ZipArchiveEntry(ViewerConstants.INTERNAL_ZIP_LOB_FOLDER + templateFilename)); IOUtils.copy(in, out); diff --git a/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamMultiRow.java b/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamMultiRow.java new file mode 100644 index 000000000..df6a3e166 --- /dev/null +++ b/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamMultiRow.java @@ -0,0 +1,118 @@ +package com.databasepreservation.common.api.v1.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipFile; + +import org.apache.commons.compress.archivers.zip.Zip64Mode; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.csv.CSVPrinter; +import org.roda.core.data.v2.index.sublist.Sublist; + +import com.databasepreservation.common.api.utils.HandlebarsUtils; +import com.databasepreservation.common.client.models.status.collection.CollectionStatus; +import com.databasepreservation.common.client.models.status.collection.ColumnStatus; +import com.databasepreservation.common.client.models.status.collection.TableStatus; +import com.databasepreservation.common.client.models.structure.ViewerDatabase; +import com.databasepreservation.common.client.models.structure.ViewerRow; +import com.databasepreservation.common.server.index.utils.IterableIndexResult; + +/** + * @author Miguel Guimarães + */ +public class ZipOutputStreamMultiRow extends ZipOutputStream { + private final IterableIndexResult viewerRows; + private final IterableIndexResult viewerRowsClone; + private Sublist sublist; + + public ZipOutputStreamMultiRow(final CollectionStatus configurationCollection, final ViewerDatabase database, + final TableStatus configTable, final IterableIndexResult viewerRows, final IterableIndexResult viewerRowsClone, + final String zipFilename, final String csvFilename, Sublist sublist, boolean exportDescriptions, + String fieldsToHeader) { + super(configurationCollection, database, configTable, zipFilename, csvFilename, + Stream.of(fieldsToHeader.split(",")).collect(Collectors.toList()), exportDescriptions); + this.viewerRows = viewerRows; + this.sublist = sublist; + this.viewerRowsClone = viewerRowsClone; + } + + @Override + public void consumeOutputStream(OutputStream out) throws IOException { + ZipFile siardArchive = new ZipFile(getDatabase().getPath()); + + boolean all = false; + if (sublist == null) { + sublist = Sublist.NONE; + all = true; + } + Iterator iterator = viewerRows.iterator(); + int nIndex = 0; + + int maxIndex = sublist.getFirstElementIndex() + sublist.getMaximumElementCount(); + + try (ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(out)) { + zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded); + zipArchiveOutputStream.setMethod(ZipArchiveOutputStream.DEFLATED); + + final List lobColumns = getConfigTable().getLobColumns(); + while (iterator.hasNext() && (nIndex < maxIndex || all)) { + ViewerRow row = iterator.next(); + if (nIndex < (sublist.getFirstElementIndex())) { + nIndex++; + continue; + } else { + writeToZipFile(siardArchive, zipArchiveOutputStream, row, lobColumns); + } + nIndex++; + } + + nIndex = 0; + final ByteArrayOutputStream byteArrayOutputStream = writeCSVFile(nIndex, all); + zipArchiveOutputStream.putArchiveEntry(new ZipArchiveEntry(getCsvFilename())); + zipArchiveOutputStream.write(byteArrayOutputStream.toByteArray()); + byteArrayOutputStream.close(); + zipArchiveOutputStream.closeArchiveEntry(); + + zipArchiveOutputStream.finish(); + zipArchiveOutputStream.flush(); + } + } + + private ByteArrayOutputStream writeCSVFile(int nIndex, boolean all) throws IOException { + ByteArrayOutputStream listBytes = new ByteArrayOutputStream(); + try (final OutputStreamWriter writer = new OutputStreamWriter(listBytes)) { + CSVPrinter printer = null; + boolean isFirst = true; + + int maxIndex = sublist.getFirstElementIndex() + sublist.getMaximumElementCount(); + + Iterator iterator = viewerRowsClone.iterator(); + while (iterator.hasNext() && (nIndex < maxIndex || all)) { + ViewerRow row = iterator.next(); + if (nIndex < sublist.getFirstElementIndex()) { + nIndex++; + continue; + } else { + if (isFirst) { + printer = new CSVPrinter(writer, getFormat().withHeader( + getConfigTable().getCSVHeaders(getFieldsToReturn(), isExportDescriptions()).toArray(new String[0]))); + isFirst = false; + } + + printer.printRecord(HandlebarsUtils.getCellValues(row, getConfigTable(), getFieldsToReturn())); + } + nIndex++; + } + viewerRowsClone.close(); + } + + return listBytes; + } +} diff --git a/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamSingleRow.java b/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamSingleRow.java index 4156d3e4d..332419a9a 100644 --- a/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamSingleRow.java +++ b/src/main/java/com/databasepreservation/common/api/v1/utils/ZipOutputStreamSingleRow.java @@ -1,65 +1,35 @@ package com.databasepreservation.common.api.v1.utils; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; -import java.util.Map; import java.util.zip.ZipFile; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.compress.archivers.zip.Zip64Mode; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.io.IOUtils; -import com.databasepreservation.common.api.utils.ExtraMediaType; import com.databasepreservation.common.api.utils.HandlebarsUtils; -import com.databasepreservation.common.client.ViewerConstants; import com.databasepreservation.common.client.models.status.collection.CollectionStatus; import com.databasepreservation.common.client.models.status.collection.ColumnStatus; -import com.databasepreservation.common.client.models.status.collection.LargeObjectConsolidateProperty; import com.databasepreservation.common.client.models.status.collection.TableStatus; -import com.databasepreservation.common.client.models.structure.ViewerCell; import com.databasepreservation.common.client.models.structure.ViewerDatabase; import com.databasepreservation.common.client.models.structure.ViewerRow; -import com.databasepreservation.common.server.ViewerFactory; -import com.databasepreservation.common.utils.FilenameUtils; -import com.databasepreservation.common.utils.LobManagerUtils; /** * @author Miguel Guimarães */ -public class ZipOutputStreamSingleRow extends CSVOutputStream { - private final CollectionStatus configurationCollection; - private final ViewerDatabase database; - private final TableStatus configTable; - private final String zipFilename; - private final String csvFilename; +public class ZipOutputStreamSingleRow extends ZipOutputStream { private final ViewerRow row; - private final List fieldsToReturn; - private final boolean exportDescriptions; public ZipOutputStreamSingleRow(CollectionStatus configurationCollection, ViewerDatabase database, TableStatus configTable, ViewerRow row, String zipFilename, String csvFilename, List fieldsToReturn, boolean exportDescriptions) { - super(zipFilename, ','); - this.configurationCollection = configurationCollection; - this.database = database; - this.configTable = configTable; + super(configurationCollection, database, configTable, zipFilename, csvFilename, fieldsToReturn, exportDescriptions); this.row = row; - this.zipFilename = zipFilename; - this.csvFilename = csvFilename; - this.fieldsToReturn = fieldsToReturn; - this.exportDescriptions = exportDescriptions; } @Override @@ -68,11 +38,11 @@ public void consumeOutputStream(OutputStream out) throws IOException { zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded); zipArchiveOutputStream.setMethod(ZipArchiveOutputStream.DEFLATED); - final List binaryColumns = configTable.getBinaryColumns(); - writeToZipFile(new ZipFile(database.getPath()), zipArchiveOutputStream, row, binaryColumns); + final List binaryColumns = getConfigTable().getLobColumns(); + writeToZipFile(new ZipFile(getDatabase().getPath()), zipArchiveOutputStream, row, binaryColumns); final ByteArrayOutputStream byteArrayOutputStream = writeCSVFile(); - zipArchiveOutputStream.putArchiveEntry(new ZipArchiveEntry(csvFilename)); + zipArchiveOutputStream.putArchiveEntry(new ZipArchiveEntry(getCsvFilename())); zipArchiveOutputStream.write(byteArrayOutputStream.toByteArray()); byteArrayOutputStream.close(); zipArchiveOutputStream.closeArchiveEntry(); @@ -82,98 +52,13 @@ public void consumeOutputStream(OutputStream out) throws IOException { } } - @Override - public String getFileName() { - return this.zipFilename; - } - - @Override - public String getMediaType() { - return ExtraMediaType.APPLICATION_ZIP; - } - - private ColumnStatus findBinaryColumn(final List columns, final String cell) { - for (ColumnStatus column : columns) { - if (column.getId().equals(cell)) { - return column; - } - } - return null; - } - - private void writeToZipFile(ZipFile siardArchive, ZipArchiveOutputStream out, ViewerRow row, - List binaryColumns) throws IOException { - for (Map.Entry cellEntry : row.getCells().entrySet()) { - final ColumnStatus binaryColumn = findBinaryColumn(binaryColumns, cellEntry.getKey()); - - if (binaryColumn != null) { - if (configurationCollection.getConsolidateProperty().equals(LargeObjectConsolidateProperty.CONSOLIDATED)) { - handleWriteConsolidateLobs(out, binaryColumn, row); - } else { - if (configTable.getColumnByIndex(binaryColumn.getColumnIndex()).isExternalLob()) { - handleWriteExternalLobs(out, binaryColumn, row, cellEntry.getValue()); - } else { - handleWriteInternalLobs(out, siardArchive, binaryColumn, row); - } - } - } - } - } - private ByteArrayOutputStream writeCSVFile() throws IOException { ByteArrayOutputStream listBytes = new ByteArrayOutputStream(); try (final OutputStreamWriter writer = new OutputStreamWriter(listBytes)) { - CSVPrinter printer = new CSVPrinter(writer, - getFormat().withHeader(configTable.getCSVHeaders(fieldsToReturn, exportDescriptions).toArray(new String[0]))); - printer.printRecord(HandlebarsUtils.getCellValues(row, configTable, fieldsToReturn)); + CSVPrinter printer = new CSVPrinter(writer, getFormat().withHeader( + getConfigTable().getCSVHeaders(getFieldsToReturn(), isExportDescriptions()).toArray(new String[0]))); + printer.printRecord(HandlebarsUtils.getCellValues(row, getConfigTable(), getFieldsToReturn())); } return listBytes; } - - private void handleWriteConsolidateLobs(ZipArchiveOutputStream out, ColumnStatus binaryColumn, ViewerRow row) - throws IOException { - final Path consolidatedPath = LobManagerUtils.getConsolidatedPath(ViewerFactory.getViewerConfiguration(), - database.getUuid(), configTable.getId(), binaryColumn.getColumnIndex(), row.getUuid()); - - InputStream in = new FileInputStream(consolidatedPath.toFile()); - final String templateFilename = FilenameUtils.getTemplateFilename(row, configTable, binaryColumn, - consolidatedPath.getFileName().toString()); - addEntryToZip(out, in, templateFilename); - } - - private void handleWriteInternalLobs(ZipArchiveOutputStream out, ZipFile siardArchive, ColumnStatus binaryColumn, - ViewerRow row) throws IOException { - final String templateFilename = FilenameUtils.getTemplateFilename(row, configTable, binaryColumn); - - if (LobManagerUtils.isLobEmbedded(configTable, row, binaryColumn.getColumnIndex())) { - String lobCellValue = LobManagerUtils.getLobCellValue(configTable, row, binaryColumn.getColumnIndex()); - lobCellValue = lobCellValue.replace(ViewerConstants.SIARD_EMBEDDED_LOB_PREFIX, ""); - String decodedString = new String(Base64.decodeBase64(lobCellValue.getBytes())); - - addEntryToZip(out, new BufferedInputStream(new ByteArrayInputStream(decodedString.getBytes())), templateFilename); - } else { - final InputStream in = siardArchive.getInputStream( - siardArchive.getEntry(LobManagerUtils.getZipFilePath(configTable, binaryColumn.getColumnIndex(), row))); - addEntryToZip(out, in, templateFilename); - } - } - - private void handleWriteExternalLobs(ZipArchiveOutputStream out, ColumnStatus binaryColumn, ViewerRow row, - ViewerCell cell) throws IOException { - final String lobLocation = cell.getValue(); - final Path lobPath = Paths.get(lobLocation); - final Path completeLobPath = ViewerFactory.getViewerConfiguration().getSIARDFilesPath().resolve(lobPath); - - final String templateFilename = FilenameUtils.getTemplateFilename(row, configTable, binaryColumn, - completeLobPath.getFileName().toString()); - InputStream inputStream = new FileInputStream(lobPath.toFile()); - addEntryToZip(out, inputStream, templateFilename); - } - - private void addEntryToZip(ZipArchiveOutputStream out, InputStream in, String templateFilename) throws IOException { - out.putArchiveEntry(new ZipArchiveEntry(ViewerConstants.INTERNAL_ZIP_LOB_FOLDER + templateFilename)); - IOUtils.copy(in, out); - in.close(); - out.closeArchiveEntry(); - } } diff --git a/src/main/java/com/databasepreservation/common/client/ViewerConstants.java b/src/main/java/com/databasepreservation/common/client/ViewerConstants.java index 572fca254..12f660be0 100644 --- a/src/main/java/com/databasepreservation/common/client/ViewerConstants.java +++ b/src/main/java/com/databasepreservation/common/client/ViewerConstants.java @@ -82,6 +82,7 @@ public class ViewerConstants { public static final String DENORMALIZATION_STATUS_PREFIX = "denormalization-"; public static final String INTERNAL_ZIP_LOB_FOLDER = "lobs/"; + public static final String INTERNAL_ZIP_CLOB_FOLDER = "clobs/"; /* * SOLR CONFIGSETS diff --git a/src/main/java/com/databasepreservation/common/client/common/lists/TableRowList.java b/src/main/java/com/databasepreservation/common/client/common/lists/TableRowList.java index 167fbf43d..e8c5c69bb 100644 --- a/src/main/java/com/databasepreservation/common/client/common/lists/TableRowList.java +++ b/src/main/java/com/databasepreservation/common/client/common/lists/TableRowList.java @@ -1,8 +1,8 @@ package com.databasepreservation.common.client.common.lists; import static com.databasepreservation.common.client.models.structure.ViewerType.dbTypes.BINARY; -import static com.databasepreservation.common.client.models.structure.ViewerType.dbTypes.NESTED; import static com.databasepreservation.common.client.models.structure.ViewerType.dbTypes.CLOB; +import static com.databasepreservation.common.client.models.structure.ViewerType.dbTypes.NESTED; import java.math.BigDecimal; import java.util.ArrayList; @@ -13,10 +13,10 @@ import java.util.List; import java.util.Map; -import com.databasepreservation.common.client.ClientConfigurationManager; import org.fusesource.restygwt.client.MethodCallback; import org.roda.core.data.v2.index.sublist.Sublist; +import com.databasepreservation.common.client.ClientConfigurationManager; import com.databasepreservation.common.client.ClientLogger; import com.databasepreservation.common.client.ViewerConstants; import com.databasepreservation.common.client.common.DefaultAsyncCallback; @@ -116,7 +116,7 @@ private Map getColumnWithBinary(TableStatus table) { Map binaryColumns = new HashMap<>(); int index = 0; for (ColumnStatus configColumn : table.getVisibleColumnsList()) { - if (configColumn.getType().equals(BINARY)) { + if (configColumn.getType().equals(BINARY) || configColumn.getType().equals(CLOB)) { binaryColumns.put(configColumn.getId(), index); } index++; @@ -148,7 +148,7 @@ protected void configureDisplay(CellTable display) { // Treat as non nested if (configColumn.getType().equals(BINARY) || configColumn.getType().equals(CLOB)) { Column binaryColumn = buildDownloadColumn(configColumn, database, table, - configColumn.getColumnIndex()); + configColumn.getColumnIndex()); binaryColumn.setSortable(true); // add to configuration file sortable options addColumn(configColumn, binaryColumn); configColumns.put(configColumn, binaryColumn); @@ -326,13 +326,11 @@ public SafeHtml getValue(ViewerRow row) { private SafeHtml getLobDownload(ViewerDatabase database, ColumnStatus configColumn, ViewerTable table, ViewerRow row, int columnIndex) { - final String value = row.getCells().get(configColumn.getId()).getValue(); - String template = configColumn.getSearchStatus().getList().getTemplate().getTemplate(); if (template != null && !template.isEmpty()) { String json = JSOUtils.cellsToJson(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL, messages.row_downloadLOB(), ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK, RestUtils.createExportLobUri(database.getUuid(), - table.getSchemaName(), table.getName(), row.getUuid(), columnIndex, value)); + table.getSchemaName(), table.getName(), row.getUuid(), columnIndex)); return SafeHtmlUtils.fromSafeConstant(JavascriptUtils.compileTemplate(template, json)); } @@ -378,10 +376,6 @@ protected void getData(Sublist sublist, ColumnSortList columnSortList, currentSorter = createSorter(columnSortList, columnSortingKeyMap); - GWT.log("sorter: " + currentSorter); - GWT.log("Filter: " + filter); - GWT.log("isNested: " + wrapper.isNested()); - FindRequest findRequest = new FindRequest(ViewerDatabase.class.getName(), filter, currentSorter, sublist, getFacets(), false, fieldsToReturn, extraParameters); @@ -513,8 +507,6 @@ private String getExportURL(String zipFilename, String filename, boolean exportA sublist = null; } - GWT.log("s: " + sublist); - FindRequest findRequest = new FindRequest(ViewerRow.class.getName(), getFilter(), currentSorter, sublist, Facets.NONE, false, fieldsToSolr, extraParameters); diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/RowPanel.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/RowPanel.java index 79970cc0d..76e2eb36f 100644 --- a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/RowPanel.java +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/RowPanel.java @@ -302,7 +302,7 @@ private void getCellHTML(ViewerColumn column, Set relatedTo, Set refer } else if (value == null) { rowField = RowField.createInstance(label, new HTML("NULL")); } else { - if (column.getType().getDbType().equals(ViewerType.dbTypes.BINARY)) { + if (ViewerType.dbTypes.BINARY.equals(column.getType().getDbType())) { if ((database.getPath() == null || database.getPath().isEmpty()) && !status.getConsolidateProperty().equals(LargeObjectConsolidateProperty.CONSOLIDATED)) { rowField = RowField.createInstance(label, new HTML(messages.rowPanelTextForLobUnavailable())); @@ -312,12 +312,28 @@ private void getCellHTML(ViewerColumn column, Set relatedTo, Set refer if (template != null && !template.isEmpty()) { String json = JSOUtils.cellsToJson(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL, messages.row_downloadLOB(), ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK, RestUtils.createExportLobUri(database.getUuid(), - table.getSchemaName(), table.getName(), row.getUuid(), columnStatus.getColumnIndex(), value)); + table.getSchemaName(), table.getName(), row.getUuid(), columnStatus.getColumnIndex())); safeHtml = SafeHtmlUtils.fromSafeConstant(JavascriptUtils.compileTemplate(template, json)); } rowField = RowField.createInstance(label, new HTML(safeHtml)); } + } else if (ViewerType.dbTypes.CLOB.equals(column.getType().getDbType())) { + if (columnStatus.getDetailsStatus().isShowContent()) { + rowField = RowField.createInstance(label, new HTML(SafeHtmlUtils.fromString(value))); + } else { + SafeHtml safeHtml = SafeHtmlUtils.EMPTY_SAFE_HTML; + String template = columnStatus.getDetailsStatus().getTemplateStatus().getTemplate(); + if (template != null && !template.isEmpty()) { + String json = JSOUtils.cellsToJson(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL, messages.row_downloadLOB(), + ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK, RestUtils.createExportLobUri(database.getUuid(), + table.getSchemaName(), table.getName(), row.getUuid(), columnStatus.getColumnIndex())); + safeHtml = SafeHtmlUtils.fromSafeConstant(JavascriptUtils.compileTemplate(template, json)); + rowField = RowField.createInstance(label, new HTML(safeHtml)); + } else { + rowField = RowField.createInstance(label, new HTML(SafeHtmlUtils.fromString(value))); + } + } } else { if (ViewerType.dbTypes.NUMERIC_FLOATING_POINT.equals(column.getType().getDbType())) { SafeHtml safeHtml = SafeHtmlUtils.fromString(new BigDecimal(value).toPlainString()); diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/ColumnsManagementPanel.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/ColumnsManagementPanel.java index 5c358cba5..51dc1d4b8 100644 --- a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/ColumnsManagementPanel.java +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/ColumnsManagementPanel.java @@ -26,6 +26,7 @@ import com.databasepreservation.common.client.common.sidebar.Sidebar; import com.databasepreservation.common.client.common.utils.CommonClientUtils; import com.databasepreservation.common.client.common.visualization.browse.configuration.columns.helpers.BinaryColumnOptionsPanel; +import com.databasepreservation.common.client.common.visualization.browse.configuration.columns.helpers.ClobColumnOptionsPanel; import com.databasepreservation.common.client.common.visualization.browse.configuration.columns.helpers.ColumnOptionsPanel; import com.databasepreservation.common.client.common.visualization.browse.configuration.columns.helpers.NestedColumnOptionsPanel; import com.databasepreservation.common.client.configuration.observer.ICollectionStatusObserver; @@ -499,11 +500,16 @@ public String getValue(ColumnStatus column) { return description; } + private boolean isAnOptionColumn(ViewerType.dbTypes type) { + return ViewerType.dbTypes.BINARY.equals(type) || ViewerType.dbTypes.NESTED.equals(type) + || ViewerType.dbTypes.CLOB.equals(type); + } + private Column getOptionsColumn() { Column options = new ButtonColumn() { @Override public void render(Cell.Context context, ColumnStatus object, SafeHtmlBuilder sb) { - if (object.getType().equals(ViewerType.dbTypes.BINARY) || object.getType().equals(ViewerType.dbTypes.NESTED)) { + if (isAnOptionColumn(object.getType())) { sb.appendHtmlConstant( "
"); } else { @@ -519,7 +525,7 @@ public String getValue(ColumnStatus object) { }; options.setFieldUpdater((index, columnStatus, value) -> { - if (columnStatus.getType().equals(ViewerType.dbTypes.NESTED)) { + if (ViewerType.dbTypes.NESTED.equals(columnStatus.getType())) { final ColumnOptionsPanel nestedColumnOptionPanel = NestedColumnOptionsPanel.createInstance(columnStatus); Dialogs.showDialogColumnConfiguration(messages.basicTableHeaderOptions(), messages.basicActionSave(), messages.basicActionCancel(), nestedColumnOptionPanel, new DefaultAsyncCallback() { @@ -539,7 +545,31 @@ public void onSuccess(Boolean value) { } } }); - } else if (columnStatus.getType().equals(ViewerType.dbTypes.BINARY)) { + } else if (ViewerType.dbTypes.CLOB.equals(columnStatus.getType())) { + ColumnOptionsPanel clobColumnOptionPanel = ClobColumnOptionsPanel.createInstance( + collectionStatus.getTableStatusByTableId(tableId), + collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId())); + + Dialogs.showDialogColumnConfiguration(messages.basicTableHeaderOptions(), messages.basicActionSave(), + messages.basicActionCancel(), clobColumnOptionPanel, new DefaultAsyncCallback() { + @Override + public void onSuccess(Boolean value) { + if (value) { + collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId()) + .updateExportTemplate(clobColumnOptionPanel.getExportTemplate()); + collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId()) + .updateSearchListTemplate(clobColumnOptionPanel.getSearchTemplate()); + collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId()) + .updateDetailsTemplate(clobColumnOptionPanel.getDetailsTemplate()); + collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId()) + .updateDetailsShowContent(((ClobColumnOptionsPanel) clobColumnOptionPanel).showContent()); + collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId()) + .setApplicationType(((ClobColumnOptionsPanel) clobColumnOptionPanel).getApplicationType()); + saveChanges(true); + } + } + }); + } else if (ViewerType.dbTypes.BINARY.equals(columnStatus.getType())) { ColumnOptionsPanel binaryColumnOptionPanel = BinaryColumnOptionsPanel.createInstance( collectionStatus.getTableStatusByTableId(tableId), collectionStatus.getTableStatusByTableId(tableId).getColumnById(columnStatus.getId())); diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/BinaryColumnOptionsPanel.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/BinaryColumnOptionsPanel.java index 2a337946a..8c3a25726 100644 --- a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/BinaryColumnOptionsPanel.java +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/BinaryColumnOptionsPanel.java @@ -101,68 +101,14 @@ private BinaryColumnOptionsPanel(TableStatus tableConfiguration, ColumnStatus co templateEngineLabel.setHTML(messages.columnManagementTextForTemplateHint(ViewerConstants.TEMPLATE_ENGINE_LINK)); templateList.setText(columnConfiguration.getExportStatus().getTemplateStatus().getTemplate()); - templateListHint.add(buildHintWithButtons(tableConfiguration, templateList)); + templateListHint.add(ColumnOptionUtils.buildHintWithButtons(tableConfiguration, templateList, messages.columnManagementTextForPossibleFields())); - displayList.setText(getDefaultTextOrValue(columnConfiguration.getSearchStatus().getList().getTemplate())); - displayListHint.add(buildHintForLabel(displayList)); + displayList.setText(ColumnOptionUtils.getDefaultTextOrValue(columnConfiguration.getSearchStatus().getList().getTemplate())); + displayListHint.add(ColumnOptionUtils.buildHintForLabel(displayList, messages.columnManagementTextForPossibleFields())); - detailsList.setText(getDefaultTextOrValue(columnConfiguration.getDetailsStatus().getTemplateStatus())); - detailsListHint.add(buildHintForLabel(detailsList)); + detailsList.setText(ColumnOptionUtils.getDefaultTextOrValue(columnConfiguration.getDetailsStatus().getTemplateStatus())); + detailsListHint.add(ColumnOptionUtils.buildHintForLabel(detailsList, messages.columnManagementTextForPossibleFields())); applicationType.setText(columnConfiguration.getApplicationType()); } - - private String getDefaultTextOrValue(TemplateStatus templateConfig) { - String template = templateConfig.getTemplate(); - - if (ViewerStringUtils.isBlank(template)) { - template = DEFAULT_DOWNLOAD_LABEL_TEMPLATE; - } - - return template; - } - - private FlowPanel buildHintForLabel(TextBox target) { - FlowPanel hintPanel = new FlowPanel(); - hintPanel.setStyleName("data-transformation-title"); - hintPanel.add(new Label(messages.columnManagementTextForPossibleFields())); - - Button btnDownloadLink = new Button(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK); - btnDownloadLink.setStyleName("btn btn-primary btn-small"); - btnDownloadLink.addClickHandler(event -> { - target.setText(target.getText() + ViewerConstants.OPEN_TEMPLATE_ENGINE - + ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK + ViewerConstants.CLOSE_TEMPLATE_ENGINE); - }); - Button btnDownloadLabel = new Button(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL); - btnDownloadLabel.setStyleName("btn btn-primary btn-small"); - btnDownloadLabel.addClickHandler(event -> { - target.setText(target.getText() + ViewerConstants.OPEN_TEMPLATE_ENGINE - + ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL + ViewerConstants.CLOSE_TEMPLATE_ENGINE); - }); - - hintPanel.add(btnDownloadLink); - hintPanel.add(btnDownloadLabel); - - return hintPanel; - } - - private FlowPanel buildHintWithButtons(TableStatus tableConfiguration, TextBox target) { - FlowPanel hintPanel = new FlowPanel(); - hintPanel.setStyleName("data-transformation-title"); - hintPanel.add(new Label(messages.columnManagementTextForPossibleFields())); - - for (ColumnStatus column : tableConfiguration.getColumns()) { - Button btnField = new Button(column.getCustomName()); - btnField.setStyleName("btn btn-primary btn-small"); - btnField.addClickHandler(handler -> { - target.setText(target.getText() + ViewerConstants.OPEN_TEMPLATE_ENGINE - + ViewerStringUtils.replaceAllFor(btnField.getText(), "\\s", "_") + ViewerConstants.CLOSE_TEMPLATE_ENGINE); - }); - - hintPanel.add(btnField); - } - - return hintPanel; - } - } \ No newline at end of file diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ClobColumnOptionsPanel.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ClobColumnOptionsPanel.java new file mode 100644 index 000000000..58360fdfd --- /dev/null +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ClobColumnOptionsPanel.java @@ -0,0 +1,109 @@ +package com.databasepreservation.common.client.common.visualization.browse.configuration.columns.helpers; + +import com.databasepreservation.common.client.ViewerConstants; +import com.databasepreservation.common.client.models.status.collection.ColumnStatus; +import com.databasepreservation.common.client.models.status.collection.TableStatus; +import com.databasepreservation.common.client.models.status.collection.TemplateStatus; +import com.databasepreservation.common.client.tools.ViewerStringUtils; +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.CheckBox; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import config.i18n.client.ClientMessages; + +import static com.databasepreservation.common.client.ViewerConstants.DEFAULT_DOWNLOAD_LABEL_TEMPLATE; + +/** + * @author Miguel Guimarães + */ +public class ClobColumnOptionsPanel extends ColumnOptionsPanel { + interface ColumnsOptionsPanelUiBinder extends UiBinder { + } + + private static ColumnsOptionsPanelUiBinder binder = GWT.create(ColumnsOptionsPanelUiBinder.class); + + @UiField + ClientMessages messages = GWT.create(ClientMessages.class); + + @UiField + FlowPanel templateListHint; + + @UiField + HTML templateEngineLabel; + + @UiField + TextBox templateList; + + @UiField + TextBox applicationType; + + @UiField + TextBox displayList; + + @UiField + FlowPanel displayListHint; + + @UiField + FlowPanel content; + + @UiField + CheckBox showContent; + + public static ColumnOptionsPanel createInstance(TableStatus tableConfiguration, ColumnStatus columnConfiguration) { + return new ClobColumnOptionsPanel(tableConfiguration, columnConfiguration); + } + + private ClobColumnOptionsPanel(TableStatus tableConfiguration, ColumnStatus columnConfiguration) { + initWidget(binder.createAndBindUi(this)); + + templateEngineLabel.setHTML(messages.columnManagementTextForTemplateHint(ViewerConstants.TEMPLATE_ENGINE_LINK)); + templateList.setText(columnConfiguration.getExportStatus().getTemplateStatus().getTemplate()); + templateListHint.add(ColumnOptionUtils.buildHintWithButtons(tableConfiguration, templateList, messages.columnManagementTextForPossibleFields())); + + displayList.setText(ColumnOptionUtils.getDefaultTextOrValue(columnConfiguration.getSearchStatus().getList().getTemplate())); + displayListHint.add(ColumnOptionUtils.buildHintForLabel(displayList, messages.columnManagementTextForPossibleFields())); + + applicationType.setText(columnConfiguration.getApplicationType()); + + showContent.setValue(columnConfiguration.getDetailsStatus().isShowContent()); + } + + @Override + public TemplateStatus getSearchTemplate() { + TemplateStatus templateStatus = new TemplateStatus(); + if (ViewerStringUtils.isBlank(this.displayList.getText())) { + templateStatus.setTemplate(DEFAULT_DOWNLOAD_LABEL_TEMPLATE); + } else { + templateStatus.setTemplate(this.displayList.getText()); + } + + return templateStatus; + } + + @Override + public TemplateStatus getDetailsTemplate() { + TemplateStatus templateStatus = new TemplateStatus(); + templateStatus.setTemplate(DEFAULT_DOWNLOAD_LABEL_TEMPLATE); + return templateStatus; + } + + @Override + public TemplateStatus getExportTemplate() { + TemplateStatus templateStatus = new TemplateStatus(); + templateStatus.setTemplate(this.templateList.getText()); + return templateStatus; + } + + public boolean showContent() { + return this.showContent.getValue(); + } + + public String getApplicationType() { + return this.applicationType.getText(); + } + +} diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ClobColumnOptionsPanel.ui.xml b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ClobColumnOptionsPanel.ui.xml new file mode 100644 index 000000000..adffbc047 --- /dev/null +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ClobColumnOptionsPanel.ui.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ColumnOptionUtils.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ColumnOptionUtils.java new file mode 100644 index 000000000..f1e54d6c0 --- /dev/null +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/columns/helpers/ColumnOptionUtils.java @@ -0,0 +1,76 @@ +package com.databasepreservation.common.client.common.visualization.browse.configuration.columns.helpers; + +import com.databasepreservation.common.client.ViewerConstants; +import com.databasepreservation.common.client.models.status.collection.ColumnStatus; +import com.databasepreservation.common.client.models.status.collection.TableStatus; +import com.databasepreservation.common.client.models.status.collection.TemplateStatus; +import com.databasepreservation.common.client.tools.ViewerStringUtils; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextBox; + +import static com.databasepreservation.common.client.ViewerConstants.DEFAULT_DOWNLOAD_LABEL_TEMPLATE; + +/** + * @author Miguel Guimarães + */ +public class ColumnOptionUtils { + + private ColumnOptionUtils() { + super(); + } + + public static FlowPanel buildHintForLabel(TextBox target, String label) { + FlowPanel hintPanel = new FlowPanel(); + hintPanel.setStyleName("data-transformation-title"); + hintPanel.add(new Label(label)); + + Button btnDownloadLink = new Button(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK); + btnDownloadLink.setStyleName("btn btn-primary btn-small"); + btnDownloadLink.addClickHandler(event -> { + target.setText(target.getText() + ViewerConstants.OPEN_TEMPLATE_ENGINE + + ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LINK + ViewerConstants.CLOSE_TEMPLATE_ENGINE); + }); + Button btnDownloadLabel = new Button(ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL); + btnDownloadLabel.setStyleName("btn btn-primary btn-small"); + btnDownloadLabel.addClickHandler(event -> { + target.setText(target.getText() + ViewerConstants.OPEN_TEMPLATE_ENGINE + + ViewerConstants.TEMPLATE_LOB_DOWNLOAD_LABEL + ViewerConstants.CLOSE_TEMPLATE_ENGINE); + }); + + hintPanel.add(btnDownloadLink); + hintPanel.add(btnDownloadLabel); + + return hintPanel; + } + + public static String getDefaultTextOrValue(TemplateStatus templateConfig) { + String template = templateConfig.getTemplate(); + + if (ViewerStringUtils.isBlank(template)) { + template = DEFAULT_DOWNLOAD_LABEL_TEMPLATE; + } + + return template; + } + + public static FlowPanel buildHintWithButtons(TableStatus tableConfiguration, TextBox target, String label) { + FlowPanel hintPanel = new FlowPanel(); + hintPanel.setStyleName("data-transformation-title"); + hintPanel.add(new Label(label)); + + for (ColumnStatus column : tableConfiguration.getColumns()) { + Button btnField = new Button(column.getCustomName()); + btnField.setStyleName("btn btn-primary btn-small"); + btnField.addClickHandler(handler -> { + target.setText(target.getText() + ViewerConstants.OPEN_TEMPLATE_ENGINE + + ViewerStringUtils.replaceAllFor(btnField.getText(), "\\s", "_") + ViewerConstants.CLOSE_TEMPLATE_ENGINE); + }); + + hintPanel.add(btnField); + } + + return hintPanel; + } +} diff --git a/src/main/java/com/databasepreservation/common/client/models/status/collection/ColumnStatus.java b/src/main/java/com/databasepreservation/common/client/models/status/collection/ColumnStatus.java index ecfa425fb..33427dc29 100644 --- a/src/main/java/com/databasepreservation/common/client/models/status/collection/ColumnStatus.java +++ b/src/main/java/com/databasepreservation/common/client/models/status/collection/ColumnStatus.java @@ -187,6 +187,10 @@ public void updateDetailsShowValue(boolean value) { this.getDetailsStatus().setShow(value); } + public void updateDetailsShowContent(boolean value) { + this.getDetailsStatus().setShowContent(value); + } + public void updateAdvancedSearchShowValue(boolean value) { this.getSearchStatus().getAdvanced().setFixed(value); } diff --git a/src/main/java/com/databasepreservation/common/client/models/status/collection/DetailsStatus.java b/src/main/java/com/databasepreservation/common/client/models/status/collection/DetailsStatus.java index 936e05177..91144d008 100644 --- a/src/main/java/com/databasepreservation/common/client/models/status/collection/DetailsStatus.java +++ b/src/main/java/com/databasepreservation/common/client/models/status/collection/DetailsStatus.java @@ -2,19 +2,22 @@ import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; /** * @author Miguel Guimarães */ -@JsonPropertyOrder({"show", "template"}) +@JsonPropertyOrder({"show", "showContent", "template"}) public class DetailsStatus implements Serializable { private boolean show; private TemplateStatus templateStatus; + private boolean showContent; public DetailsStatus() { + this.showContent = true; } public boolean isShow() { @@ -33,4 +36,12 @@ public TemplateStatus getTemplateStatus() { public void setTemplateStatus(TemplateStatus templateStatus) { this.templateStatus = templateStatus; } + + public boolean isShowContent() { + return showContent; + } + + public void setShowContent(boolean showContent) { + this.showContent = showContent; + } } diff --git a/src/main/java/com/databasepreservation/common/client/models/status/collection/TableStatus.java b/src/main/java/com/databasepreservation/common/client/models/status/collection/TableStatus.java index 1cd237e54..a6472cca5 100644 --- a/src/main/java/com/databasepreservation/common/client/models/status/collection/TableStatus.java +++ b/src/main/java/com/databasepreservation/common/client/models/status/collection/TableStatus.java @@ -2,11 +2,9 @@ import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import com.databasepreservation.common.client.models.structure.ViewerColumn; import com.databasepreservation.common.client.models.structure.ViewerType; import com.databasepreservation.common.client.tools.ViewerStringUtils; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -16,7 +14,8 @@ /** * @author Miguel Guimarães */ -@JsonPropertyOrder({"uuid", "id", "schemaFolder", "tableFolder", "name", "customName", "description", "customDescription", "show", "columns"}) +@JsonPropertyOrder({"uuid", "id", "schemaFolder", "tableFolder", "name", "customName", "description", + "customDescription", "show", "columns"}) public class TableStatus implements Serializable { private String uuid; @@ -119,19 +118,20 @@ public void addColumnStatus(ColumnStatus status) { } @JsonIgnore - public int getLastColumnOrder(){ + public int getLastColumnOrder() { int lastIndex = 0; for (ColumnStatus column : columns) { - if(column.getOrder() > lastIndex) lastIndex = column.getOrder(); + if (column.getOrder() > lastIndex) + lastIndex = column.getOrder(); } return lastIndex; } - public void reorderColumns(){ + public void reorderColumns() { for (int i = 0; i < columns.size(); i++) { ColumnStatus column = columns.get(i); int currentIndex = i + 1; - if(column.getOrder() != currentIndex){ + if (column.getOrder() != currentIndex) { column.setOrder(currentIndex); } } @@ -139,17 +139,18 @@ public void reorderColumns(){ @JsonIgnore public List getVisibleColumnsList() { - return columns.stream().filter(c -> c.getSearchStatus().getList().isShow()).sorted() - .collect(Collectors.toList()); - } + return columns.stream().filter(c -> c.getSearchStatus().getList().isShow()).sorted().collect(Collectors.toList()); + } - public boolean showAdvancedSearchOption() { + public boolean showAdvancedSearchOption() { return columns.stream().anyMatch(c -> c.getSearchStatus().getAdvanced().isFixed()); } - @JsonIgnore - public List getBinaryColumns() { - return getVisibleColumnsList().stream().filter(c -> c.getType().equals(ViewerType.dbTypes.BINARY)).collect(Collectors.toList()); + @JsonIgnore + public List getLobColumns() { + return getVisibleColumnsList().stream() + .filter(c -> c.getType().equals(ViewerType.dbTypes.BINARY) || c.getType().equals(ViewerType.dbTypes.CLOB)) + .collect(Collectors.toList()); } @JsonIgnore @@ -159,7 +160,7 @@ public ColumnStatus getColumnById(String id) { @JsonIgnore public ColumnStatus getColumnByIndex(int index) { - return columns.stream().filter(c -> c.getColumnIndex() == index).findFirst().orElse(null); + return columns.stream().filter(c -> c.getColumnIndex() == index).findFirst().orElse(null); } @JsonIgnore diff --git a/src/main/java/com/databasepreservation/common/client/models/structure/ViewerType.java b/src/main/java/com/databasepreservation/common/client/models/structure/ViewerType.java index 4c1843fe9..291db6e44 100644 --- a/src/main/java/com/databasepreservation/common/client/models/structure/ViewerType.java +++ b/src/main/java/com/databasepreservation/common/client/models/structure/ViewerType.java @@ -8,7 +8,7 @@ */ public class ViewerType implements Serializable { public enum dbTypes { - BINARY, BOOLEAN, DATETIME, DATETIME_JUST_DATE, DATETIME_JUST_TIME, ENUMERATION, TIME_INTERVAL, + BINARY, CLOB, BOOLEAN, DATETIME, DATETIME_JUST_DATE, DATETIME_JUST_TIME, ENUMERATION, TIME_INTERVAL, NUMERIC_FLOATING_POINT, NUMERIC_INTEGER, STRING, COMPOSED_STRUCTURE, COMPOSED_ARRAY, NESTED } diff --git a/src/main/java/com/databasepreservation/common/client/tools/RestUtils.java b/src/main/java/com/databasepreservation/common/client/tools/RestUtils.java index 3fa7ebca6..04290e44f 100644 --- a/src/main/java/com/databasepreservation/common/client/tools/RestUtils.java +++ b/src/main/java/com/databasepreservation/common/client/tools/RestUtils.java @@ -50,7 +50,7 @@ public static SafeUri createFileResourceDownloadValidationReportUri(String datab } public static String createExportLobUri(String databaseUUID, String schemaName, String tableName, String rowIndex, - int columnIndex, String filename) { + int columnIndex) { // api/v1/database/{databaseUUID}/collection/{collectionUUID}/data/{schema}/{table}/{row // index}/{col index} diff --git a/src/main/java/com/databasepreservation/common/transformers/ToolkitStructure2ViewerStructure.java b/src/main/java/com/databasepreservation/common/transformers/ToolkitStructure2ViewerStructure.java index e7bab1ddd..c1e7ab439 100644 --- a/src/main/java/com/databasepreservation/common/transformers/ToolkitStructure2ViewerStructure.java +++ b/src/main/java/com/databasepreservation/common/transformers/ToolkitStructure2ViewerStructure.java @@ -622,7 +622,11 @@ private static ViewerType getType(Type type) throws ViewerException { result.setDbType(ViewerType.dbTypes.NUMERIC_FLOATING_POINT); } } else if (type instanceof SimpleTypeString) { - result.setDbType(ViewerType.dbTypes.STRING); + if ("CHARACTER LARGE OBJECT".equalsIgnoreCase(type.getSql2008TypeName())) { + result.setDbType(ViewerType.dbTypes.CLOB); + } else { + result.setDbType(ViewerType.dbTypes.STRING); + } } else if (type instanceof ComposedTypeArray) { result = new ViewerTypeArray(); result.setDbType(ViewerType.dbTypes.COMPOSED_ARRAY); diff --git a/src/main/java/config/i18n/client/ClientMessages.java b/src/main/java/config/i18n/client/ClientMessages.java index 3f1c70b08..1e6338da9 100644 --- a/src/main/java/config/i18n/client/ClientMessages.java +++ b/src/main/java/config/i18n/client/ClientMessages.java @@ -1507,6 +1507,11 @@ public interface ClientMessages extends Messages { String binaryColumnMIMEType(); + /******************************************** + * Column Management Panel - Clob Column + *******************************************/ + String clobColumnDisplayContent(); + /******************************************** * Resources *******************************************/ diff --git a/src/main/resources/config/i18n/client/ClientMessages.properties b/src/main/resources/config/i18n/client/ClientMessages.properties index d241a8a80..7a1381b6c 100644 --- a/src/main/resources/config/i18n/client/ClientMessages.properties +++ b/src/main/resources/config/i18n/client/ClientMessages.properties @@ -1123,6 +1123,10 @@ columnManagementLabelForQuantityList=Quantity of records that will show in the t binaryColumnTemplateForFilename=Template to render the LOB file name binaryColumnMIMEType=MIME Type ############################################################################# +# Column Management Panel - Clob # +############################################################################# +clobColumnDisplayContent=Display CLOB content on detailed view panel +############################################################################# # Resources # ############################################################################# resourceNotAvailableTitle=Resource not found