geoportal-data-mapper/src/main/java/org/gcube/application/geoportaldatamapper/exporter/Geoportal_PDF_Exporter.java

1164 lines
38 KiB
Java

package org.gcube.application.geoportaldatamapper.exporter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.rest.TempFile;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.gcube.application.geoportal.common.utils.StorageUtils;
import org.gcube.application.geoportalcommon.ConvertToDataValueObjectModel;
import org.gcube.application.geoportalcommon.ProjectDVBuilder;
import org.gcube.application.geoportalcommon.geoportal.GeoportalClientCaller;
import org.gcube.application.geoportalcommon.geoportal.ProjectsCaller;
import org.gcube.application.geoportalcommon.shared.geoportal.geojson.GeoJSON;
import org.gcube.application.geoportalcommon.shared.geoportal.materialization.GCubeSDIViewerLayerDV;
import org.gcube.application.geoportalcommon.shared.geoportal.materialization.innerobject.FilesetDV;
import org.gcube.application.geoportalcommon.shared.geoportal.materialization.innerobject.PayloadDV;
import org.gcube.application.geoportalcommon.shared.geoportal.project.ProjectDV;
import org.gcube.application.geoportalcommon.shared.geoportal.view.ProjectView;
import org.gcube.application.geoportalcommon.shared.geoportal.view.SectionView;
import org.gcube.application.geoportalcommon.shared.geoportal.view.SubDocumentView;
import org.gcube.application.geoportaldatamapper.Geoportal_JSON_Mapper;
import org.gcube.application.geoportaldatamapper.URLParserUtil;
import org.gcube.application.geoportaldatamapper.exporter.beans.Credits;
import org.gcube.application.geoportaldatamapper.exporter.beans.PDFExporterConfig;
import org.gcube.application.geoportaldatamapper.exporter.beans.PageNumber;
import org.gcube.application.geoportaldatamapper.exporter.beans.Watermarker;
import org.gcube.application.geoportaldatamapper.exporter.gis.BBOXConverter;
import org.gcube.application.geoportaldatamapper.exporter.gis.Recalculate_WGS84_Offset;
import org.gcube.application.geoportaldatamapper.reader.MapBoxEndpointReader;
import org.gcube.application.geoportaldatamapper.reader.ServiceAccessPoint;
import org.gcube.application.geoportaldatamapper.shared.ExporterProjectSource;
import org.gcube.application.geoportaldatamapper.shared.FileReference;
import org.gcube.spatial.data.geoutility.bean.WmsParameters;
import org.gcube.spatial.data.geoutility.shared.wfs.WFSParameter;
import org.gcube.spatial.data.geoutility.wfs.WFSQueryBuilder;
//import org.imgscalr.Scalr;
//import org.imgscalr.Scalr.Method;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfAnnotationBorder;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.IElement;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Link;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.properties.HorizontalAlignment;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.VerticalAlignment;
import com.itextpdf.layout.renderer.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
/**
* The Class Geoportal_PDF_Exporter.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Nov 21, 2023
*/
public class Geoportal_PDF_Exporter {
private static final int PARAGRAPH_MARGIN_TOP = 20;
private static final int FONT_SIZE_SECTION_TITLE = 14;
private static final float PARAGRAPH_FONT_SIZE = 9;
public static final String mapSizeWithCentroid = "550x350";
private static Logger LOG = LoggerFactory.getLogger(Geoportal_PDF_Exporter.class);
/**
* Read PDF exporter configs from GR.
*
* @return the PDF exporter config
*/
private PDFExporterConfig readPDFExporterConfigsFromGR() {
PDFExporterConfigProvider exporterProvider = new PDFExporterConfigProvider();
PDFExporterConfig exporterConfig = null;
try {
exporterConfig = exporterProvider.readConfigsFromGR();
} catch (Exception ex) {
LOG.warn("no pdf credits found");
}
return exporterConfig;
}
/**
* Check config.
*
* @return true, if the PDFExporterConfig (means the proper GR see
* {@link PDFExporterConfigProvider}) exists, false otherwise.
*/
public boolean checkConfig() {
PDFExporterConfig exporterConfig = readPDFExporterConfigsFromGR();
return exporterConfig != null;
}
/**
* Creates the PDF file.
*
* @param exportSource the export source. // set ExporterProjectSource.username
* = null to test PUBLIC ACCESS
* @return the string
* @throws Exception the exception
*/
public FileReference createPDFFile(ExporterProjectSource exportSource) throws Exception {
FileReference fileRef = new FileReference();
PDFExporterConfig pdfExporterConfigs = readPDFExporterConfigsFromGR();
PageNumber pagenumber = null;
Watermarker watermarker = null;
Boolean isAddTimpestampCreatedAt = false;
if (pdfExporterConfigs != null) {
pagenumber = pdfExporterConfigs.getPagenumber();
watermarker = pdfExporterConfigs.getWatermarker();
isAddTimpestampCreatedAt = pdfExporterConfigs.getTimestampCreatedAt();
}
List<ServiceAccessPoint> listSAP = MapBoxEndpointReader.getMapBoxEndpoint();
PdfDocument pdfDocument = null;
ByteArrayOutputStream out = null;
try {
ProjectsCaller clientProjects = GeoportalClientCaller.projects();
Project theProject = clientProjects.getProjectByID(exportSource.getProfileID(),
exportSource.getProjectID());
if (exportSource.getProfileTitle() == null || exportSource.getProfileTitle().isEmpty()) {
UseCaseDescriptor usecasedesc = GeoportalClientCaller.useCaseDescriptors()
.getUCDForId(exportSource.getProfileID());
exportSource.setProfileTitle(usecasedesc.getName());
}
ProjectDVBuilder projectBuilder = ProjectDVBuilder.newBuilder().fullDocumentMap(true);
projectBuilder.relationships(false);
ProjectDV theProjectDV = ConvertToDataValueObjectModel.toProjectDV(theProject, projectBuilder);
ProjectView projectView = Geoportal_JSON_Mapper.loadProjectView(theProjectDV, exportSource.getScope(),
exportSource.getAccountname());
// CREATING NEW PDF
// Initialize PDF document
out = new ByteArrayOutputStream();
pdfDocument = new PdfDocument(new PdfWriter(out));
String projectTitle = theProjectDV.getId();
try {
projectTitle = (String) theProjectDV.getTheDocument().getFirstEntryOfMap().getValue();
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
boolean addPageNumber = false;
try {
addPageNumber = Boolean.parseBoolean(pagenumber.getValue());
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
if (addPageNumber) {
// Creates a header for every page in the document. The PageNumberHandler
// implements
// add page numbers.
pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new PageNumberHandler(pagenumber));
}
String addWatermarker = null;
try {
addWatermarker = watermarker.getValue();
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
if (addWatermarker != null) {
pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new WaterMarkerHandler(watermarker));
}
// Initialize document
Document document = new Document(pdfDocument);
// Adding header (i.e. Logo D4GNA)
if (pdfExporterConfigs != null && pdfExporterConfigs.getCredits() != null) {
Image image = toImageFromLink(pdfExporterConfigs.getCredits().getHeader(), 80);
if (image != null) {
image.setFixedPosition(document.getLeftMargin(),
(pdfDocument.getDefaultPageSize().getHeight() - image.getImageHeight()) + 80);
//image.setPaddingTop(20);
document.add(image);
}
}
// Project Title (i.e. project name)
PdfFont bold = PdfFontFactory.createFont(StandardFonts.TIMES_BOLD);
Text title = new Text(projectTitle).setFont(bold);
Style style = new Style();
style.setPaddingTop(30);
style.setTextAlignment(TextAlignment.LEFT);
Paragraph p = new Paragraph().add(title).addStyle(style).setFontSize(17);
document.add(p);
// Project Type
if (exportSource.getProfileTitle() != null) {
Text projectType = new Text(exportSource.getProfileTitle()).setFontColor(ColorConstants.WHITE)
.setTextAlignment(TextAlignment.CENTER).setFontSize(8);
Style marginLeft = new Style().setMarginLeft(10);
projectType.addStyle(marginLeft);
// Adding type
Paragraph preface = new Paragraph();
preface.setHorizontalAlignment(HorizontalAlignment.CENTER);
DeviceRgb rgbColor = new DeviceRgb(0, 60, 136);
preface.setBackgroundColor(rgbColor);
preface.add(projectType);
document.add(preface);
}
// GIS LINK
if (exportSource.getGisLink() != null && !exportSource.getGisLink().isEmpty()) {
Link theLink = getLinkFromURL(exportSource.getGisLink(), exportSource.getGisLink(), 5);
theLink.setFontSize(7);
Paragraph p2 = new Paragraph().add(theLink);
document.add(p2);
}
// Adding centroid MAP
if (theProjectDV.getSpatialReference() != null) {
String geoJSON = theProjectDV.getSpatialReference().getGeoJSON();
if (geoJSON != null && !geoJSON.isEmpty()) {
String downMapBoxImg = linkToMarkerURLViaMapBoxStaticMap(geoJSON, 7, mapSizeWithCentroid,
listSAP.get(0));
if (downMapBoxImg != null) {
Image backgroundImage = toImageFromLink(downMapBoxImg, 250);
if (backgroundImage != null) {
Table tableI = new Table(1);
tableI.setTextAlignment(TextAlignment.CENTER);
tableI.addCell(backgroundImage);
Paragraph pCentroid = new Paragraph();
pCentroid.setTextAlignment(TextAlignment.CENTER);
pCentroid.add(tableI);
document.add(pCentroid);
}
}
}
}
// Getting API MapBox Access Point
ServiceAccessPoint sap = listSAP.size() > 1 ? listSAP.get(1) : listSAP.get(0);
for (SectionView section : projectView.getListSections()) {
document = appendSubDocumentToPDF(document, section, section.getListSubDocuments(),
exportSource.getGisLink(), sap, pdfExporterConfigs);
}
// Add timestamp Created at...
if (isAddTimpestampCreatedAt) {
// TimeStamp - Created at
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER_OBLIQUE);
Style style2 = new Style().setFont(font).setFontSize(8);
Paragraph pt = new Paragraph().add("Created at " + now.format(dtf)).addStyle(style2);
pt.setMarginTop(50);
document.add(pt);
}
// Add Footer Credits
if (pdfExporterConfigs != null) {
Table tableCredits = addFooterCredits(document, pdfExporterConfigs.getCredits());
document.add(tableCredits);
}
document.close();
// Copying OutputStream into Temp File on Storage
InputStream in = new ByteArrayInputStream(out.toByteArray());
String projectTitleSanitized = projectTitle.replaceAll("[^a-zA-Z0-9]", "_");
// Save PDF on storage VOLATILE
StorageUtils storage = new StorageUtils();
TempFile tempFile = storage.putOntoStorage(in, projectTitleSanitized + ".pdf");
String storageURL = storage.getURL(tempFile.getId());
LOG.trace("mongo pdf ID: " + tempFile.getId());
LOG.trace("mongo pdf filename: " + tempFile.getFilename());
String contentType = "application/pdf";
String pdfFileURL = String.format("%s?contentType=%s&fileName=%s&content-disposition=%s", storageURL,
contentType, tempFile.getFilename(), "inline");
LOG.info("returning pdf URL: " + pdfFileURL);
fileRef.setStorageVolatileURL(new URL(pdfFileURL));
fileRef.setFileName(tempFile.getFilename());
fileRef.setContentType(contentType);
// TEST save file locally
// File targetFile = new File(projectTitleSanitized + ".pdf");
// java.nio.file.Files.copy(in, targetFile.toPath(),
// StandardCopyOption.REPLACE_EXISTING); LOG.info("targetFile at: " +
// targetFile.getAbsolutePath());
IOUtils.closeQuietly(in);
} catch (Exception e) {
LOG.error("Error on generating the pdf file: ", e);
throw new Exception("Error on generating the pdf file", e);
} finally {
if (pdfDocument != null) {
try {
pdfDocument.close();
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
}
}
return fileRef;
}
/**
* The Class PageNumberHandler.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Nov 21, 2023
*/
public class PageNumberHandler implements IEventHandler {
private PageNumber pagenumber;
/**
* Instantiates a new page number handler.
*
* @param pagenumber the pagenumber
*/
public PageNumberHandler(PageNumber pagenumber) {
this.pagenumber = pagenumber;
}
/**
* Handle event.
*
* @param event the event
*/
@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdf = docEvent.getDocument();
PdfPage page = docEvent.getPage();
int pageNumber = pdf.getPageNumber(page);
Rectangle pageSize = page.getPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdf);
Canvas canvas = new Canvas(pdfCanvas, pageSize);
Paragraph p = new Paragraph().add("pg. ").add(String.valueOf(pageNumber));
try {
int fontSize = pagenumber.getFontSize() != null ? pagenumber.getFontSize() : 8;
p.setFontSize(fontSize);
p.setFont(PdfFontFactory.createFont(StandardFonts.TIMES_ITALIC));
p.setFontColor(ColorConstants.DARK_GRAY);
} catch (IOException e1) {
LOG.warn("PageNumberHandler error: " + e1.getMessage());
}
// int x = 565;
// int y = 25;
float xR = pageSize.getRight() - 30;
float yB = pageSize.getBottom() + 30;
canvas.showTextAligned(p, xR, yB, TextAlignment.RIGHT);
pdfCanvas.release();
}
}
/**
* The Class WaterMarkerHandler.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Nov 21, 2023
*/
public class WaterMarkerHandler implements IEventHandler {
private Watermarker watermarker;
/**
* Instantiates a new water marker handler.
*
* @param watermarker the watermarker
*/
public WaterMarkerHandler(Watermarker watermarker) {
this.watermarker = watermarker;
}
/**
* Handle event.
*
* @param event the event
*/
@Override
public void handleEvent(Event event) {
if (watermarker.getValue() == null || watermarker.getValue().isEmpty())
return;
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdf = docEvent.getDocument();
PdfPage page = docEvent.getPage();
Rectangle pageSize = page.getPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdf);
int pageNumber = pdf.getPageNumber(page);
page.setIgnorePageRotationForContent(true);
PdfFont font;
try {
font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN);
int fontSize = watermarker.getFontSize() != null ? watermarker.getFontSize() : 100;
Paragraph paragraph = new Paragraph(watermarker.getValue()).setFont(font).setFontSize(fontSize)
.setFontColor(ColorConstants.RED).setOpacity(new Float(0.2));
Canvas canvas = new Canvas(pdfCanvas, pageSize);
float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
float y = (pageSize.getTop() + pageSize.getBottom()) / 2;
canvas.showTextAligned(paragraph, x, y, pageNumber, TextAlignment.CENTER, VerticalAlignment.TOP, 45);
} catch (IOException e) {
LOG.warn("WaterMarkerHandler error: " + e.getMessage());
}
}
}
/**
* Link to marker URL via map box static map.
*
* @param geoJSON the geo JSON
* @param zoom the zoom
* @param widthXheight the width xheight
* @param serviceAP the service AP
* @return the string
*/
private static String linkToMarkerURLViaMapBoxStaticMap(String geoJSON, int zoom, String widthXheight,
ServiceAccessPoint serviceAP) {
LOG.debug("called linkToMarker via MAP BOX with geoJSON: " + geoJSON);
try {
JSONObject theGeoJSONObj = new JSONObject(geoJSON);
String pointCoordinates = null;
try {
pointCoordinates = theGeoJSONObj.getString(GeoJSON.COORDINATES);
} catch (Exception e) {
LOG.debug(GeoJSON.COORDINATES + " error: " + e.getMessage());
try {
JSONArray array = theGeoJSONObj.getJSONArray(GeoJSON.COORDINATES);
pointCoordinates = array.toString();
} catch (Exception e1) {
LOG.debug(GeoJSON.COORDINATES + " error: " + e1.getMessage());
}
}
LOG.debug(GeoJSON.COORDINATES + " are: " + pointCoordinates);
String geojson = String.format("geojson({\"type\":\"Point\",\"coordinates\":%s})", pointCoordinates);
JSONArray jsonArray = new JSONArray(pointCoordinates);
if (zoom < 0)
zoom = 7;
jsonArray.put(jsonArray.length() - 1, zoom);
pointCoordinates = jsonArray.toString();
String downMapBoxImg = String.format("%s/%s/%s/%s?%s=%s", serviceAP.getUrl(), geojson,
pointCoordinates.replaceAll("\\[", "").replaceAll("\\]", ""), widthXheight,
serviceAP.getApiTokenName(), serviceAP.getApiTokenPwd());
LOG.debug("linkToMarkerURLViaMapBoxStaticMap url: " + downMapBoxImg);
return downMapBoxImg;
} catch (JSONException e) {
LOG.warn("JSONException: " + e);
} catch (Exception e) {
LOG.warn("Error: " + e);
}
return null;
}
/**
* Link to map box static map.
*
* @param bbox the bbox
* @param widthXheight the width xheight
* @param serviceAP the service AP
* @return the string
*/
private static String linkToMapBoxStaticMap(String bbox, String widthXheight, ServiceAccessPoint serviceAP) {
try {
String downMapBoxImg = String.format("%s/[%s]/%s?%s=%s", serviceAP.getUrl(), bbox, widthXheight,
serviceAP.getApiTokenName(), serviceAP.getApiTokenPwd());
LOG.trace("linkToMapBoxStaticMap IMAGE: " + downMapBoxImg);
return downMapBoxImg;
} catch (Exception e) {
LOG.warn("Error: " + e);
}
return null;
}
/**
* Removes the border.
*
* @param table the table
*/
private static void removeBorder(Table table) {
for (IElement iElement : table.getChildren()) {
((Cell) iElement).setBorder(Border.NO_BORDER);
}
}
/**
* Builds the credits.
*
* @param document the document
* @param credits the credits
* @return the table
*/
private Table addFooterCredits(Document document, Credits credits) {
if (credits == null)
return null;
Table tableCredits = new Table(1);
tableCredits.setTextAlignment(TextAlignment.CENTER);
float pageWidthSize = document.getPdfDocument().getDefaultPageSize().getWidth() - 85;
tableCredits.setFixedPosition(document.getLeftMargin(), 20, pageWidthSize);
Image img = null;
try {
ImageData data = null;
data = ImageDataFactory.create(new URL(credits.getFooter()));
img = new Image(data);
img.setTextAlignment(TextAlignment.CENTER);
img.setHorizontalAlignment(HorizontalAlignment.CENTER);
img.setMaxHeight(22);
img.setMaxWidth(pageWidthSize);
// img.setBorder(new SolidBorder(1F));
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
//
if (img != null) {
Cell cell = new Cell();
cell.setTextAlignment(TextAlignment.CENTER);
cell.add(img);
tableCredits.addCell(cell);
}
removeBorder(tableCredits);
return tableCredits;
}
/**
* Append sub document to PDF.
*
* @param document the document
* @param sectionView the section view
* @param subDocuments the sub documents
* @param gisLink the gis link
* @param sap the sap
* @param pdfExporterConfigs the pdf exporter configs
* @return the document
*/
private static Document appendSubDocumentToPDF(Document document, SectionView sectionView,
List<SubDocumentView> subDocuments, String gisLink, ServiceAccessPoint sap,
PDFExporterConfig pdfExporterConfigs) {
try {
boolean displayAsGallery = false;
for (SubDocumentView subDocumentView : subDocuments) {
if (subDocumentView.getListImages() != null && subDocumentView.getListImages().size() > 0) {
LOG.debug("Section with images: " + subDocumentView.getListImages());
displayAsGallery = true;
break;
}
}
boolean displayAsMapOfLayers = false;
for (SubDocumentView subDocumentView : subDocuments) {
if (subDocumentView.getListLayers() != null && subDocumentView.getListLayers().size() > 0) {
LOG.debug("Section with layers: " + subDocumentView.getListLayers());
displayAsMapOfLayers = true;
break;
}
}
// Displaying the whole section as a Gallery
if (displayAsGallery) {
try {
PdfFont bold = PdfFontFactory.createFont(StandardFonts.TIMES_BOLD);
Paragraph paragraph = new Paragraph().add(sectionView.getSectionTitle()).setFont(bold)
.setFontSize(FONT_SIZE_SECTION_TITLE);
paragraph.setMarginTop(PARAGRAPH_MARGIN_TOP);
document.add(new AreaBreak());
document.add(paragraph);
LOG.debug("displayAsGallery the: " + sectionView);
for (SubDocumentView subDocumentView : subDocuments) {
JsonObject jsonObject = new JsonParser().parse(subDocumentView.getMetadataAsJSON())
.getAsJsonObject();
Table tableContainer = toTableFixedLayout(document, 2, true);
// tableContainer.setBorder(Border.NO_BORDER);
Table tableMeta = new Table(2);
tableMeta = jsonToTable(tableMeta, 1, "", jsonObject);
// tableMeta.setBorder(Border.NO_BORDER);
List<FilesetDV> files = subDocumentView.getListImages();
Table tableI = new Table(1);
// tableI.setTextAlignment(TextAlignment.CENTER);
// tableI.setBorder(Border.NO_BORDER);
if (files != null) {
for (FilesetDV fileset : files) {
// Paragraph paragraphInt = new Paragraph(fileset.getGcubeProfileFieldName());
List<Image> listLinks = toImages(fileset.getListPayload(), 250);
for (Image image : listLinks) {
image.setBorder(Border.NO_BORDER);
tableI.addCell(image);
}
}
}
tableContainer.addCell(tableMeta);
removeBorder(tableMeta);
tableContainer.addCell(tableI);
removeBorder(tableI);
document.add(tableContainer);
}
} catch (Exception e) {
LOG.warn("Error on rendering the gallery section: " + sectionView);
}
// Displaying the whole section as a Map of Layers
} else if (displayAsMapOfLayers) {
try {
PdfFont bold = PdfFontFactory.createFont(StandardFonts.TIMES_BOLD);
Paragraph paragraph = new Paragraph().add(sectionView.getSectionTitle()).setFont(bold)
.setFontSize(FONT_SIZE_SECTION_TITLE);
paragraph.setMarginTop(PARAGRAPH_MARGIN_TOP);
document.add(new AreaBreak());
document.add(paragraph);
LOG.trace("displayAsMapOfLayers the: " + sectionView);
for (SubDocumentView subDocumentView : subDocuments) {
JsonObject jsonObject = new JsonParser().parse(subDocumentView.getMetadataAsJSON())
.getAsJsonObject();
Table tableContainerL = toTableFixedLayout(document, 1, true);
List<GCubeSDIViewerLayerDV> layers = subDocumentView.getListLayers();
if (layers != null) {
for (GCubeSDIViewerLayerDV gCubeLayer : layers) {
Paragraph pLayer = new Paragraph();
pLayer.setTextAlignment(TextAlignment.CENTER);
Table tableLayer = new Table(1);
tableLayer.setTextAlignment(TextAlignment.CENTER);
Table tableMeta = new Table(2);
tableMeta = jsonToTable(tableMeta, 1, "", jsonObject);
String wmsLink = gCubeLayer.getWMSLink();
LOG.trace("wmsLink(1): " + wmsLink);
wmsLink = URLParserUtil.setValueOfParameter("format", wmsLink, "image/png", true);
String source_bbox = URLParserUtil.extractValueOfParameterFromURL("bbox", wmsLink);
String wmsVersion = URLParserUtil.extractValueOfParameterFromURL("version", wmsLink);
double bboxOffset = 0.0;
LOG.trace("source_bbox: " + source_bbox);
Recalculate_WGS84_Offset source_Projection = new Recalculate_WGS84_Offset(wmsVersion,
source_bbox, bboxOffset);
LOG.trace("source width: " + source_Projection.getAspectratioWidth());
LOG.trace("source heigth: " + source_Projection.getAspectratioHeight());
LOG.trace("source ratio: " + source_Projection.getRatio_Width_Height());
LOG.trace("source bbox: " + source_Projection.getBboxWithOffset());
// Calculate best BBOX offset
bboxOffset = BBOXConverter.bestBBOXOffset(wmsVersion, source_bbox);
// bboxOffset = 0.0001;
LOG.debug("applying offset: " + bboxOffset);
Recalculate_WGS84_Offset recalculate_Projection = new Recalculate_WGS84_Offset(
wmsVersion, source_bbox, bboxOffset);
LOG.trace("offset width: " + recalculate_Projection.getAspectratioWidth());
LOG.trace("offset heigth: " + recalculate_Projection.getAspectratioHeight());
LOG.trace("ratio: " + recalculate_Projection.getRatio_Width_Height());
LOG.trace("bbox with offset: " + recalculate_Projection.getBboxWithOffset());
int aspectratioWidth = recalculate_Projection.getAspectratioWidth();
int aspectratioHeight = recalculate_Projection.getAspectratioHeight();
String recaulculateBBOX = recalculate_Projection.getBboxWithOffset();
// Layer with aspect ratio on width/height according to bbox width/height
wmsLink = URLParserUtil.setValueOfParameter("width", wmsLink, aspectratioWidth + "",
true);
wmsLink = URLParserUtil.setValueOfParameter("height", wmsLink, aspectratioHeight + "",
true);
String wmsLinkTol = URLParserUtil.setValueOfParameter("bbox", wmsLink, recaulculateBBOX,
false);
wmsLinkTol += "&TRANSPARENT=TRUE";
LOG.trace("wmsLink aspect ratio link: " + wmsLink);
int maxWidthOfMapWithLayer = 250;
Image image2 = toImageFromLink(wmsLinkTol, maxWidthOfMapWithLayer);
// MapBox static as background
String linkToMapBox = linkToMapBoxStaticMap(recaulculateBBOX,
aspectratioWidth + "x" + aspectratioHeight, sap);
LOG.trace("linkToMapBox: " + linkToMapBox);
Image backImg = toImageFromLink(linkToMapBox, maxWidthOfMapWithLayer);
Cell mapCell = new Cell();
mapCell.setMaxWidth(maxWidthOfMapWithLayer);
mapCell.setNextRenderer(new ImageBackgroundCellRenderer(mapCell, backImg));
mapCell.add(image2);
mapCell.setTextAlignment(TextAlignment.CENTER);
tableLayer.addCell(mapCell);
removeBorder(tableLayer);
pLayer.add(tableLayer);
// adding tables with layer and meta to table container
// Row with layers
tableContainerL.addCell(pLayer);
// Row with layer metadata
tableContainerL.addCell(tableMeta);
}
}
// Row with alert message - No more required
// tableContainerL.addCell(paragraph1);
document.add(tableContainerL);
}
} catch (Exception e) {
LOG.warn("Error on rendering the layer section: " + sectionView);
}
} else {
try {
PdfFont bold = PdfFontFactory.createFont(StandardFonts.TIMES_BOLD);
Paragraph paragraph = new Paragraph().add(sectionView.getSectionTitle()).setFont(bold)
.setFontSize(FONT_SIZE_SECTION_TITLE);
paragraph.setMarginTop(PARAGRAPH_MARGIN_TOP);
document.add(paragraph);
LOG.debug("displaying default the: " + sectionView);
for (SubDocumentView subDocumentView : subDocuments) {
JsonObject jsonObject = new JsonParser().parse(subDocumentView.getMetadataAsJSON())
.getAsJsonObject();
Table table = toTableFixedLayout(document, 2, false);
table = jsonToTable(table, 1, "", jsonObject);
int rows = table.getNumberOfRows();
for (int i = 1; i < rows; i++) {
Cell cell1 = table.getCell(i, 0);
cell1.setMinWidth(80);
}
document.add(table);
List<FilesetDV> files = subDocumentView.getListFiles();
if (files != null) {
for (FilesetDV fileset : files) {
Paragraph paragraphInt = new Paragraph(fileset.getGcubeProfileFieldName());
paragraphInt.setFontSize(PARAGRAPH_FONT_SIZE);
List<Link> listLinks = toPDFLinks(fileset.getListPayload(), 5);
for (Link anchor : listLinks) {
paragraphInt.add(anchor);
}
document.add(paragraphInt);
}
}
}
} catch (Exception e) {
LOG.warn("Error on rendering the default section: " + sectionView);
}
}
} catch (Exception e) {
LOG.warn("Error on rendering the whole section: " + sectionView);
}
return document;
}
/**
* The Class ImageBackgroundCellRenderer.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Nov 15, 2023
*/
private static class ImageBackgroundCellRenderer extends CellRenderer {
protected Image img;
/**
* Instantiates a new image background cell renderer.
*
* @param modelElement the model element
* @param img the img
*/
public ImageBackgroundCellRenderer(Cell modelElement, Image img) {
super(modelElement);
this.img = img;
}
// If a renderer overflows on the next area, iText uses #getNextRenderer()
// method to create a new renderer for the overflow part.
// If #getNextRenderer() isn't overridden, the default method will be used and
// thus the default rather than the custom
/**
* Gets the next renderer.
*
* @return the next renderer
*/
// renderer will be created
@Override
public IRenderer getNextRenderer() {
return new ImageBackgroundCellRenderer((Cell) modelElement, img);
}
/**
* Draw.
*
* @param drawContext the draw context
*/
@Override
public void draw(DrawContext drawContext) {
img.scaleToFit(getOccupiedAreaBBox().getWidth(), getOccupiedAreaBBox().getHeight());
drawContext.getCanvas().addXObjectFittedIntoRectangle(img.getXObject(), getOccupiedAreaBBox());
super.draw(drawContext);
}
}
/**
* Wms link to WFS request.
*
* @param wmsLink the wms link
* @return the string
*/
private static String wmsLinkToWFSRequest(String wmsLink) {
String endpoint = wmsLink.substring(0, wmsLink.indexOf("?"));
WFSQueryBuilder builder = new WFSQueryBuilder();
HashMap<WFSParameter, String> defaultR = builder.getDefaultWFSGetFeatureRequest();
wmsLink = URLParserUtil.setValueOfParameter("format", wmsLink, "application/json", true);
defaultR.put(WFSParameter.TYPENAME,
URLParserUtil.extractValueOfParameterFromURL(WmsParameters.LAYERS.getParameter(), wmsLink));
String crs = URLParserUtil.extractValueOfParameterFromURL(WmsParameters.CRS.getParameter(), wmsLink);
if (crs != null && !crs.isEmpty())
defaultR.put(WFSParameter.CRS, crs);
String srs = URLParserUtil.extractValueOfParameterFromURL(WmsParameters.SRS.getParameter(), wmsLink);
if (srs != null && !srs.isEmpty())
defaultR.put(WFSParameter.SRSNAME, srs);
String version = URLParserUtil.extractValueOfParameterFromURL(WmsParameters.VERSION.getParameter(), wmsLink);
if (version != null && !version.isEmpty())
defaultR.put(WFSParameter.VERSION, version);
// String bbox = URLParserUtil.extractValueOfParameterFromURL(WmsParameters.BBOX.getParameter(), wmsLink);
// if(bbox!=null && !bbox.isEmpty())
defaultR.put(WFSParameter.BBOX, null); // all features of the layers
String cqlFilter = URLParserUtil.extractValueOfParameterFromURL(WmsParameters.CQL_FILTER.getParameter(),
wmsLink);
if (cqlFilter != null && !cqlFilter.isEmpty())
defaultR.put(WFSParameter.CQL_FILTER, cqlFilter);
defaultR.put(WFSParameter.OUTPUTFORMAT, "application/json");
String wfsURL = builder.buildWFSFeatureQuery(endpoint, defaultR);
LOG.debug("wfsLink:" + wfsURL);
return wfsURL;
}
/**
* To table fixed layout.
*
* @param document the document
* @param column the column
* @param maxWidthToPageSize the max width to page size
* @return the table
*/
private static Table toTableFixedLayout(Document document, int column, boolean maxWidthToPageSize) {
Table table = new Table(column);
table.setFixedLayout();
if (maxWidthToPageSize)
table.setWidth(document.getPdfDocument().getDefaultPageSize().getWidth() - 75);
return table;
}
/**
* To images.
*
* @param payloads the payloads
* @param maxWidth the max width
* @return the list
* @throws IOException Signals that an I/O exception has occurred.
*/
private static List<Image> toImages(List<PayloadDV> payloads, Integer maxWidth) throws IOException {
List<Image> listImages = new ArrayList<Image>(payloads.size());
for (PayloadDV payloadDV : payloads) {
Image img = toImageFromLink(payloadDV.getLink(), maxWidth);
if (img != null)
listImages.add(img);
}
return listImages;
}
/**
* To image from link.
*
* @param link the link
* @param maxWidth the max width
* @return the image
*/
private static Image toImageFromLink(String link, Integer maxWidth) {
Image img = null;
try {
ImageData data = null;
data = ImageDataFactory.create(new URL(link));
img = new Image(data);
if (maxWidth != null)
img.setMaxWidth(maxWidth);
else
img.setAutoScaleWidth(true);
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
return img;
}
/**
* To image from link.
*
* @param link the link
* @param width the width
* @param height the height
* @return the image
*/
private static Image toImageFromLink(String link, Integer width, Integer height) {
Image img = null;
try {
ImageData data = null;
data = ImageDataFactory.create(new URL(link));
img = new Image(data);
if (width != null && height != null) {
img.setWidth(width);
img.setHeight(height);
} else {
img.setAutoScaleWidth(true);
// img.setAutoScaleHeight(true);
}
} catch (Exception e) {
// silent
LOG.trace("Error: ", e);
}
return img;
}
/**
* To PDF links.
*
* @param payloads the payloads
* @param marginLeft the margin left
* @return the list
* @throws IOException Signals that an I/O exception has occurred.
*/
private static List<Link> toPDFLinks(List<PayloadDV> payloads, Integer marginLeft) throws IOException {
List<Link> listLinks = new ArrayList<Link>(payloads.size());
for (PayloadDV payloadDV : payloads) {
Link theLink = getLinkFromURL(payloadDV.getName(), payloadDV.getLink(), 5);
listLinks.add(theLink);
}
return listLinks;
}
/**
* Gets the link from URL.
*
* @param linkTxt the link txt
* @param url the url
* @param marginLeft the margin left
* @return the link from URL
*/
private static Link getLinkFromURL(String linkTxt, String url, Integer marginLeft) {
Link theLink = new Link(linkTxt, PdfAction.createURI(url));
theLink.setFontSize(PARAGRAPH_FONT_SIZE);
theLink.setFontColor(ColorConstants.BLUE);
theLink.getLinkAnnotation().setBorder(new PdfAnnotationBorder(0, 0, 0));
Style style = new Style();
if (marginLeft != null)
style.setMarginLeft(marginLeft);
theLink.addStyle(style);
return theLink;
}
/**
* convert json Data to structured Html text.
*
* @param table the table
* @param deep the deep
* @param key the key
* @param obj the obj
* @return string
*/
private static Table jsonToTable(Table table, int deep, String key, Object obj) {
try {
if (obj instanceof JsonObject) {
JsonObject jsonObject = (JsonObject) obj;
// String[] keys = JSONObject.getNames(jsonObject);
Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
if (entrySet.size() > 0) {
for (Map.Entry<String, JsonElement> entry : entrySet) {
// System.out.println("Adding entry: " + entry);
table = jsonToTable(table, deep++, entry.getKey(), entry.getValue());
}
}
} else if (obj instanceof JsonArray) {
JsonArray array = (JsonArray) obj;
for (int i = 0; i < array.size(); i++) {
// recursive call
String arrayKey = key;
if (i > 0)
arrayKey = "";
table = jsonToTable(table, deep++, arrayKey, array.get(i));
}
} else {
Cell cell1 = createContentCell(2);
cell1.setFontColor(ColorConstants.GRAY);
cell1.add(new Paragraph(key));
table.addCell(cell1);
// row.add(key);
Cell cell2 = createContentCell(2);
JsonElement value = (JsonElement) obj;
Paragraph content = new Paragraph(value.getAsString());
content.setTextAlignment(TextAlignment.JUSTIFIED);
cell2.add(content);
table.addCell(cell2);
}
} catch (Exception e) {
e.printStackTrace();
}
return table;
}
/**
* Creates the content cell.
*
* @param paddingTop the padding top
* @return the cell
*/
private static Cell createContentCell(Integer paddingTop) {
Cell cell = new Cell();
cell.setBorder(Border.NO_BORDER);
cell.setTextAlignment(TextAlignment.LEFT);
if (paddingTop != null)
cell.setPaddingTop(paddingTop);
cell.setFontSize(PARAGRAPH_FONT_SIZE);
return cell;
}
}