mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-03-13 02:18:16 +01:00
propietary move
This commit is contained in:
@@ -1,516 +0,0 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class EndpointConfiguration {
|
||||
|
||||
private static final String REMOVE_BLANKS = "remove-blanks";
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
||||
private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
|
||||
private Set<String> disabledGroups = new HashSet<>();
|
||||
private Map<String, Set<String>> endpointAlternatives = new ConcurrentHashMap<>();
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
public EndpointConfiguration(
|
||||
ApplicationProperties applicationProperties,
|
||||
@Qualifier("runningProOrHigher") boolean runningProOrHigher) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
init();
|
||||
processEnvironmentConfigs();
|
||||
}
|
||||
|
||||
public void enableEndpoint(String endpoint) {
|
||||
endpointStatuses.put(endpoint, true);
|
||||
log.debug("Enabled endpoint: {}", endpoint);
|
||||
}
|
||||
|
||||
public void disableEndpoint(String endpoint) {
|
||||
if (!Boolean.FALSE.equals(endpointStatuses.get(endpoint))) {
|
||||
log.debug("Disabling endpoint: {}", endpoint);
|
||||
}
|
||||
endpointStatuses.put(endpoint, false);
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getEndpointStatuses() {
|
||||
return endpointStatuses;
|
||||
}
|
||||
|
||||
public boolean isEndpointEnabled(String endpoint) {
|
||||
String original = endpoint;
|
||||
if (endpoint.startsWith("/")) {
|
||||
endpoint = endpoint.substring(1);
|
||||
}
|
||||
|
||||
// Rule 1: Explicit flag wins - if disabled via disableEndpoint(), stay disabled
|
||||
Boolean explicitStatus = endpointStatuses.get(endpoint);
|
||||
if (Boolean.FALSE.equals(explicitStatus)) {
|
||||
log.debug("isEndpointEnabled('{}') -> false (explicitly disabled)", original);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rule 2: Functional-group override - check if endpoint belongs to any disabled functional
|
||||
// group
|
||||
for (String group : endpointGroups.keySet()) {
|
||||
if (disabledGroups.contains(group) && endpointGroups.get(group).contains(endpoint)) {
|
||||
// Skip tool groups (qpdf, OCRmyPDF, Ghostscript, LibreOffice, etc.)
|
||||
if (!isToolGroup(group)) {
|
||||
log.debug(
|
||||
"isEndpointEnabled('{}') -> false (functional group '{}' disabled)",
|
||||
original,
|
||||
group);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rule 3: Tool-group fallback - check if at least one alternative tool group is enabled
|
||||
Set<String> alternatives = endpointAlternatives.get(endpoint);
|
||||
if (alternatives != null && !alternatives.isEmpty()) {
|
||||
boolean hasEnabledToolGroup =
|
||||
alternatives.stream()
|
||||
.anyMatch(toolGroup -> !disabledGroups.contains(toolGroup));
|
||||
log.debug(
|
||||
"isEndpointEnabled('{}') -> {} (tool groups check)",
|
||||
original,
|
||||
hasEnabledToolGroup);
|
||||
return hasEnabledToolGroup;
|
||||
}
|
||||
|
||||
// Rule 4: Single-dependency check - if no alternatives defined, check if endpoint belongs
|
||||
// to any disabled tool groups
|
||||
for (String group : endpointGroups.keySet()) {
|
||||
if (isToolGroup(group)
|
||||
&& disabledGroups.contains(group)
|
||||
&& endpointGroups.get(group).contains(endpoint)) {
|
||||
log.debug(
|
||||
"isEndpointEnabled('{}') -> false (single tool group '{}' disabled, no alternatives)",
|
||||
original,
|
||||
group);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Default: enabled if not explicitly disabled
|
||||
boolean enabled = !Boolean.FALSE.equals(explicitStatus);
|
||||
log.debug("isEndpointEnabled('{}') -> {} (default)", original, enabled);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public boolean isGroupEnabled(String group) {
|
||||
// Rule 1: If group is explicitly disabled, it stays disabled
|
||||
if (disabledGroups.contains(group)) {
|
||||
log.debug("isGroupEnabled('{}') -> false (explicitly disabled)", group);
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<String> endpoints = endpointGroups.get(group);
|
||||
if (endpoints == null || endpoints.isEmpty()) {
|
||||
log.debug("isGroupEnabled('{}') -> false (no endpoints)", group);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rule 2: For functional groups, check if all endpoints are enabled
|
||||
// Rule 3: For tool groups, they're enabled unless explicitly disabled (handled above)
|
||||
if (isToolGroup(group)) {
|
||||
log.debug("isGroupEnabled('{}') -> true (tool group not disabled)", group);
|
||||
return true;
|
||||
}
|
||||
|
||||
// For functional groups, check each endpoint individually
|
||||
for (String endpoint : endpoints) {
|
||||
if (!isEndpointEnabledDirectly(endpoint)) {
|
||||
log.debug(
|
||||
"isGroupEnabled('{}') -> false (endpoint '{}' disabled)", group, endpoint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("isGroupEnabled('{}') -> true (all endpoints enabled)", group);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addEndpointToGroup(String group, String endpoint) {
|
||||
endpointGroups.computeIfAbsent(group, k -> new HashSet<>()).add(endpoint);
|
||||
}
|
||||
|
||||
public void addEndpointAlternative(String endpoint, String toolGroup) {
|
||||
endpointAlternatives.computeIfAbsent(endpoint, k -> new HashSet<>()).add(toolGroup);
|
||||
}
|
||||
|
||||
public void disableGroup(String group) {
|
||||
if (disabledGroups.add(group)) {
|
||||
if (isToolGroup(group)) {
|
||||
log.debug(
|
||||
"Disabling tool group: {} (endpoints with alternatives remain available)",
|
||||
group);
|
||||
} else {
|
||||
log.debug(
|
||||
"Disabling functional group: {} (will disable all endpoints in group)",
|
||||
group);
|
||||
}
|
||||
}
|
||||
// Only cascade to endpoints for *functional* groups
|
||||
if (!isToolGroup(group)) {
|
||||
Set<String> endpoints = endpointGroups.get(group);
|
||||
if (endpoints != null) {
|
||||
endpoints.forEach(this::disableEndpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void enableGroup(String group) {
|
||||
if (disabledGroups.remove(group)) {
|
||||
log.debug("Enabling group: {}", group);
|
||||
}
|
||||
Set<String> endpoints = endpointGroups.get(group);
|
||||
if (endpoints != null) {
|
||||
endpoints.forEach(this::enableEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getDisabledGroups() {
|
||||
return new HashSet<>(disabledGroups);
|
||||
}
|
||||
|
||||
public void logDisabledEndpointsSummary() {
|
||||
// Get all unique endpoints across all groups
|
||||
Set<String> allEndpoints =
|
||||
endpointGroups.values().stream()
|
||||
.flatMap(Set::stream)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
|
||||
// Check which endpoints are actually disabled (functionally unavailable)
|
||||
List<String> functionallyDisabledEndpoints =
|
||||
allEndpoints.stream()
|
||||
.filter(endpoint -> !isEndpointEnabled(endpoint))
|
||||
.sorted()
|
||||
.toList();
|
||||
|
||||
// Separate tool groups from functional groups
|
||||
List<String> disabledToolGroups =
|
||||
disabledGroups.stream().filter(this::isToolGroup).sorted().toList();
|
||||
|
||||
List<String> disabledFunctionalGroups =
|
||||
disabledGroups.stream().filter(group -> !isToolGroup(group)).sorted().toList();
|
||||
|
||||
if (!disabledToolGroups.isEmpty()) {
|
||||
log.info(
|
||||
"Disabled tool groups: {} (endpoints may have alternative implementations)",
|
||||
String.join(", ", disabledToolGroups));
|
||||
}
|
||||
|
||||
if (!disabledFunctionalGroups.isEmpty()) {
|
||||
log.info("Disabled functional groups: {}", String.join(", ", disabledFunctionalGroups));
|
||||
}
|
||||
|
||||
if (!functionallyDisabledEndpoints.isEmpty()) {
|
||||
log.info(
|
||||
"Total disabled endpoints: {}. Disabled endpoints: {}",
|
||||
functionallyDisabledEndpoints.size(),
|
||||
String.join(", ", functionallyDisabledEndpoints));
|
||||
} else if (!disabledToolGroups.isEmpty()) {
|
||||
log.info(
|
||||
"No endpoints disabled despite missing tools - fallback implementations available");
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
// Adding endpoints to "PageOps" group
|
||||
addEndpointToGroup("PageOps", "remove-pages");
|
||||
addEndpointToGroup("PageOps", "merge-pdfs");
|
||||
addEndpointToGroup("PageOps", "split-pdfs");
|
||||
addEndpointToGroup("PageOps", "pdf-organizer");
|
||||
addEndpointToGroup("PageOps", "rotate-pdf");
|
||||
addEndpointToGroup("PageOps", "multi-page-layout");
|
||||
addEndpointToGroup("PageOps", "booklet-imposition");
|
||||
addEndpointToGroup("PageOps", "scale-pages");
|
||||
addEndpointToGroup("PageOps", "crop");
|
||||
addEndpointToGroup("PageOps", "extract-page");
|
||||
addEndpointToGroup("PageOps", "pdf-to-single-page");
|
||||
addEndpointToGroup("PageOps", "auto-split-pdf");
|
||||
addEndpointToGroup("PageOps", "split-by-size-or-count");
|
||||
addEndpointToGroup("PageOps", "overlay-pdf");
|
||||
addEndpointToGroup("PageOps", "split-pdf-by-sections");
|
||||
addEndpointToGroup("PageOps", "split-pdf-by-chapters");
|
||||
|
||||
// Adding endpoints to "Convert" group
|
||||
addEndpointToGroup("Convert", "pdf-to-img");
|
||||
addEndpointToGroup("Convert", "img-to-pdf");
|
||||
addEndpointToGroup("Convert", "pdf-to-pdfa");
|
||||
addEndpointToGroup("Convert", "file-to-pdf");
|
||||
addEndpointToGroup("Convert", "pdf-to-word");
|
||||
addEndpointToGroup("Convert", "pdf-to-presentation");
|
||||
addEndpointToGroup("Convert", "pdf-to-text");
|
||||
addEndpointToGroup("Convert", "pdf-to-html");
|
||||
addEndpointToGroup("Convert", "pdf-to-xml");
|
||||
addEndpointToGroup("Convert", "html-to-pdf");
|
||||
addEndpointToGroup("Convert", "url-to-pdf");
|
||||
addEndpointToGroup("Convert", "markdown-to-pdf");
|
||||
addEndpointToGroup("Convert", "pdf-to-csv");
|
||||
addEndpointToGroup("Convert", "pdf-to-markdown");
|
||||
addEndpointToGroup("Convert", "eml-to-pdf");
|
||||
|
||||
// Adding endpoints to "Security" group
|
||||
addEndpointToGroup("Security", "add-password");
|
||||
addEndpointToGroup("Security", "remove-password");
|
||||
addEndpointToGroup("Security", "change-permissions");
|
||||
addEndpointToGroup("Security", "add-watermark");
|
||||
addEndpointToGroup("Security", "cert-sign");
|
||||
addEndpointToGroup("Security", "remove-cert-sign");
|
||||
addEndpointToGroup("Security", "sanitize-pdf");
|
||||
addEndpointToGroup("Security", "auto-redact");
|
||||
addEndpointToGroup("Security", "redact");
|
||||
addEndpointToGroup("Security", "validate-signature");
|
||||
addEndpointToGroup("Security", "stamp");
|
||||
addEndpointToGroup("Security", "sign");
|
||||
|
||||
// Adding endpoints to "Other" group
|
||||
addEndpointToGroup("Other", "ocr-pdf");
|
||||
addEndpointToGroup("Other", "add-image");
|
||||
addEndpointToGroup("Other", "extract-images");
|
||||
addEndpointToGroup("Other", "change-metadata");
|
||||
addEndpointToGroup("Other", "flatten");
|
||||
addEndpointToGroup("Other", "unlock-pdf-forms");
|
||||
addEndpointToGroup("Other", REMOVE_BLANKS);
|
||||
addEndpointToGroup("Other", "remove-annotations");
|
||||
addEndpointToGroup("Other", "compare");
|
||||
addEndpointToGroup("Other", "add-page-numbers");
|
||||
addEndpointToGroup("Other", "get-info-on-pdf");
|
||||
addEndpointToGroup("Other", "remove-image-pdf");
|
||||
addEndpointToGroup("Other", "add-attachments");
|
||||
addEndpointToGroup("Other", "view-pdf");
|
||||
addEndpointToGroup("Other", "replace-and-invert-color-pdf");
|
||||
addEndpointToGroup("Other", "multi-tool");
|
||||
|
||||
// Adding endpoints to "Advance" group
|
||||
addEndpointToGroup("Advance", "adjust-contrast");
|
||||
addEndpointToGroup("Advance", "compress-pdf");
|
||||
addEndpointToGroup("Advance", "extract-image-scans");
|
||||
addEndpointToGroup("Advance", "repair");
|
||||
addEndpointToGroup("Advance", "auto-rename");
|
||||
addEndpointToGroup("Advance", "pipeline");
|
||||
addEndpointToGroup("Advance", "scanner-effect");
|
||||
addEndpointToGroup("Advance", "auto-split-pdf");
|
||||
addEndpointToGroup("Advance", "show-javascript");
|
||||
addEndpointToGroup("Advance", "split-by-size-or-count");
|
||||
addEndpointToGroup("Advance", "overlay-pdf");
|
||||
addEndpointToGroup("Advance", "split-pdf-by-sections");
|
||||
addEndpointToGroup("Advance", "edit-table-of-contents");
|
||||
addEndpointToGroup("Advance", "split-pdf-by-chapters");
|
||||
|
||||
// CLI
|
||||
addEndpointToGroup("CLI", "compress-pdf");
|
||||
addEndpointToGroup("CLI", "extract-image-scans");
|
||||
addEndpointToGroup("CLI", "repair");
|
||||
addEndpointToGroup("CLI", "pdf-to-pdfa");
|
||||
addEndpointToGroup("CLI", "file-to-pdf");
|
||||
addEndpointToGroup("CLI", "pdf-to-word");
|
||||
addEndpointToGroup("CLI", "pdf-to-presentation");
|
||||
addEndpointToGroup("CLI", "pdf-to-html");
|
||||
addEndpointToGroup("CLI", "pdf-to-xml");
|
||||
addEndpointToGroup("CLI", "ocr-pdf");
|
||||
addEndpointToGroup("CLI", "html-to-pdf");
|
||||
addEndpointToGroup("CLI", "url-to-pdf");
|
||||
addEndpointToGroup("CLI", "pdf-to-rtf");
|
||||
|
||||
// python
|
||||
addEndpointToGroup("Python", "extract-image-scans");
|
||||
addEndpointToGroup("Python", "html-to-pdf");
|
||||
addEndpointToGroup("Python", "url-to-pdf");
|
||||
addEndpointToGroup("Python", "file-to-pdf");
|
||||
|
||||
// openCV
|
||||
addEndpointToGroup("OpenCV", "extract-image-scans");
|
||||
|
||||
// LibreOffice
|
||||
addEndpointToGroup("LibreOffice", "file-to-pdf");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-word");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-presentation");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-rtf");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-html");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-xml");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-pdfa");
|
||||
|
||||
// Unoconvert
|
||||
addEndpointToGroup("Unoconvert", "file-to-pdf");
|
||||
|
||||
// Java
|
||||
addEndpointToGroup("Java", "merge-pdfs");
|
||||
addEndpointToGroup("Java", "remove-pages");
|
||||
addEndpointToGroup("Java", "split-pdfs");
|
||||
addEndpointToGroup("Java", "pdf-organizer");
|
||||
addEndpointToGroup("Java", "rotate-pdf");
|
||||
addEndpointToGroup("Java", "pdf-to-img");
|
||||
addEndpointToGroup("Java", "img-to-pdf");
|
||||
addEndpointToGroup("Java", "add-password");
|
||||
addEndpointToGroup("Java", "remove-password");
|
||||
addEndpointToGroup("Java", "change-permissions");
|
||||
addEndpointToGroup("Java", "add-watermark");
|
||||
addEndpointToGroup("Java", "add-image");
|
||||
addEndpointToGroup("Java", "extract-images");
|
||||
addEndpointToGroup("Java", "change-metadata");
|
||||
addEndpointToGroup("Java", "cert-sign");
|
||||
addEndpointToGroup("Java", "remove-cert-sign");
|
||||
addEndpointToGroup("Java", "multi-page-layout");
|
||||
addEndpointToGroup("Java", "booklet-imposition");
|
||||
addEndpointToGroup("Java", "scale-pages");
|
||||
addEndpointToGroup("Java", "add-page-numbers");
|
||||
addEndpointToGroup("Java", "auto-rename");
|
||||
addEndpointToGroup("Java", "auto-split-pdf");
|
||||
addEndpointToGroup("Java", "sanitize-pdf");
|
||||
addEndpointToGroup("Java", "crop");
|
||||
addEndpointToGroup("Java", "get-info-on-pdf");
|
||||
addEndpointToGroup("Java", "extract-page");
|
||||
addEndpointToGroup("Java", "pdf-to-single-page");
|
||||
addEndpointToGroup("Java", "markdown-to-pdf");
|
||||
addEndpointToGroup("Java", "show-javascript");
|
||||
addEndpointToGroup("Java", "auto-redact");
|
||||
addEndpointToGroup("Java", "redact");
|
||||
addEndpointToGroup("Java", "pdf-to-csv");
|
||||
addEndpointToGroup("Java", "split-by-size-or-count");
|
||||
addEndpointToGroup("Java", "overlay-pdf");
|
||||
addEndpointToGroup("Java", "split-pdf-by-sections");
|
||||
addEndpointToGroup("Java", REMOVE_BLANKS);
|
||||
addEndpointToGroup("Java", "pdf-to-text");
|
||||
addEndpointToGroup("Java", "remove-image-pdf");
|
||||
addEndpointToGroup("Java", "pdf-to-markdown");
|
||||
addEndpointToGroup("Java", "add-attachments");
|
||||
addEndpointToGroup("Java", "compress-pdf");
|
||||
|
||||
// Javascript
|
||||
addEndpointToGroup("Javascript", "pdf-organizer");
|
||||
addEndpointToGroup("Javascript", "sign");
|
||||
addEndpointToGroup("Javascript", "compare");
|
||||
addEndpointToGroup("Javascript", "adjust-contrast");
|
||||
|
||||
/* qpdf */
|
||||
addEndpointToGroup("qpdf", "repair");
|
||||
addEndpointToGroup("qpdf", "compress-pdf");
|
||||
|
||||
/* Ghostscript */
|
||||
addEndpointToGroup("Ghostscript", "repair");
|
||||
addEndpointToGroup("Ghostscript", "compress-pdf");
|
||||
|
||||
/* tesseract */
|
||||
addEndpointToGroup("tesseract", "ocr-pdf");
|
||||
|
||||
/* OCRmyPDF */
|
||||
addEndpointToGroup("OCRmyPDF", "ocr-pdf");
|
||||
|
||||
// Multi-tool endpoints - endpoints that can be handled by multiple tools
|
||||
addEndpointAlternative("repair", "qpdf");
|
||||
addEndpointAlternative("repair", "Ghostscript");
|
||||
addEndpointAlternative("compress-pdf", "qpdf");
|
||||
addEndpointAlternative("compress-pdf", "Ghostscript");
|
||||
addEndpointAlternative("compress-pdf", "Java");
|
||||
addEndpointAlternative("ocr-pdf", "tesseract");
|
||||
addEndpointAlternative("ocr-pdf", "OCRmyPDF");
|
||||
|
||||
// file-to-pdf has multiple implementations
|
||||
addEndpointAlternative("file-to-pdf", "LibreOffice");
|
||||
addEndpointAlternative("file-to-pdf", "Unoconvert");
|
||||
|
||||
// pdf-to-html and pdf-to-markdown can use either LibreOffice or Pdftohtml
|
||||
addEndpointAlternative("pdf-to-html", "LibreOffice");
|
||||
addEndpointAlternative("pdf-to-html", "Pdftohtml");
|
||||
addEndpointAlternative("pdf-to-markdown", "Pdftohtml");
|
||||
|
||||
// markdown-to-pdf can use either Weasyprint or Java
|
||||
addEndpointAlternative("markdown-to-pdf", "Weasyprint");
|
||||
addEndpointAlternative("markdown-to-pdf", "Java");
|
||||
|
||||
// Weasyprint dependent endpoints
|
||||
addEndpointToGroup("Weasyprint", "html-to-pdf");
|
||||
addEndpointToGroup("Weasyprint", "url-to-pdf");
|
||||
addEndpointToGroup("Weasyprint", "markdown-to-pdf");
|
||||
addEndpointToGroup("Weasyprint", "eml-to-pdf");
|
||||
|
||||
// Pdftohtml dependent endpoints
|
||||
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
||||
addEndpointToGroup("Pdftohtml", "pdf-to-markdown");
|
||||
}
|
||||
|
||||
private void processEnvironmentConfigs() {
|
||||
if (applicationProperties != null && applicationProperties.getEndpoints() != null) {
|
||||
List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove();
|
||||
List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove();
|
||||
|
||||
if (endpointsToRemove != null) {
|
||||
for (String endpoint : endpointsToRemove) {
|
||||
disableEndpoint(endpoint.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (groupsToRemove != null) {
|
||||
for (String group : groupsToRemove) {
|
||||
disableGroup(group.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!runningProOrHigher) {
|
||||
disableGroup("enterprise");
|
||||
}
|
||||
|
||||
if (!applicationProperties.getSystem().getEnableUrlToPDF()) {
|
||||
disableEndpoint("url-to-pdf");
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getEndpointsForGroup(String group) {
|
||||
return endpointGroups.getOrDefault(group, new HashSet<>());
|
||||
}
|
||||
|
||||
private boolean isToolGroup(String group) {
|
||||
return "qpdf".equals(group)
|
||||
|| "OCRmyPDF".equals(group)
|
||||
|| "Ghostscript".equals(group)
|
||||
|| "LibreOffice".equals(group)
|
||||
|| "tesseract".equals(group)
|
||||
|| "CLI".equals(group)
|
||||
|| "Python".equals(group)
|
||||
|| "OpenCV".equals(group)
|
||||
|| "Unoconvert".equals(group)
|
||||
|| "Java".equals(group)
|
||||
|| "Javascript".equals(group)
|
||||
|| "Weasyprint".equals(group)
|
||||
|| "Pdftohtml".equals(group);
|
||||
}
|
||||
|
||||
private boolean isEndpointEnabledDirectly(String endpoint) {
|
||||
if (endpoint.startsWith("/")) {
|
||||
endpoint = endpoint.substring(1);
|
||||
}
|
||||
|
||||
// Check explicit disable flag
|
||||
Boolean explicitStatus = endpointStatuses.get(endpoint);
|
||||
if (Boolean.FALSE.equals(explicitStatus)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if endpoint belongs to any disabled functional group
|
||||
for (String group : endpointGroups.keySet()) {
|
||||
if (disabledGroups.contains(group) && endpointGroups.get(group).contains(endpoint)) {
|
||||
if (!isToolGroup(group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package stirling.software.SPDF.config.swagger;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "Standard error response")
|
||||
public class ErrorResponse {
|
||||
|
||||
@Schema(description = "HTTP status code", example = "400")
|
||||
private int status;
|
||||
|
||||
@Schema(
|
||||
description = "Error message describing what went wrong",
|
||||
example = "Invalid PDF file or corrupted data")
|
||||
private String message;
|
||||
|
||||
@Schema(description = "Timestamp when the error occurred", example = "2024-01-15T10:30:00Z")
|
||||
private String timestamp;
|
||||
|
||||
@Schema(
|
||||
description = "Request path where the error occurred",
|
||||
example = "/api/v1/{endpoint-path}")
|
||||
private String path;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package stirling.software.SPDF.config.swagger;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
|
||||
/**
|
||||
* Standard API response annotation for PDF operations that take PDF input and return PDF output.
|
||||
* Use for single PDF input → single PDF output (SISO) operations like rotate, compress, etc.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "PDF processed successfully",
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/pdf",
|
||||
schema =
|
||||
@Schema(
|
||||
type = "string",
|
||||
format = "binary",
|
||||
description = "The processed PDF file"))),
|
||||
@ApiResponse(
|
||||
responseCode = "400",
|
||||
description = "Invalid PDF file or request parameters",
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorResponse.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "500",
|
||||
description = "Internal server error during processing",
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorResponse.class)))
|
||||
})
|
||||
public @interface StandardPdfResponse {}
|
||||
@@ -1,74 +0,0 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import stirling.software.SPDF.config.swagger.StandardPdfResponse;
|
||||
import stirling.software.SPDF.service.PdfJsonConversionService;
|
||||
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||
import stirling.software.common.annotations.api.ConvertApi;
|
||||
import stirling.software.common.model.api.GeneralFile;
|
||||
import stirling.software.common.model.api.PDFFile;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@ConvertApi
|
||||
@RequiredArgsConstructor
|
||||
public class ConvertPdfJsonController {
|
||||
|
||||
private final PdfJsonConversionService pdfJsonConversionService;
|
||||
|
||||
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/pdf/json")
|
||||
@Operation(
|
||||
summary = "Convert PDF to JSON",
|
||||
description =
|
||||
"Extracts PDF text, fonts, and metadata into an editable JSON structure that can be"
|
||||
+ " transformed back into a PDF. Input:PDF Output:JSON Type:SISO")
|
||||
public ResponseEntity<byte[]> convertPdfToJson(@ModelAttribute PDFFile request)
|
||||
throws Exception {
|
||||
MultipartFile inputFile = request.getFileInput();
|
||||
if (inputFile == null) {
|
||||
throw ExceptionUtils.createNullArgumentException("fileInput");
|
||||
}
|
||||
|
||||
byte[] jsonBytes = pdfJsonConversionService.convertPdfToJson(inputFile);
|
||||
String originalName = inputFile.getOriginalFilename();
|
||||
String baseName =
|
||||
(originalName != null && !originalName.isBlank())
|
||||
? Filenames.toSimpleFileName(originalName).replaceFirst("[.][^.]+$", "")
|
||||
: "document";
|
||||
String docName = baseName + ".json";
|
||||
return WebResponseUtils.bytesToWebResponse(jsonBytes, docName, MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
@AutoJobPostMapping(consumes = "multipart/form-data", value = "/json/pdf")
|
||||
@StandardPdfResponse
|
||||
@Operation(
|
||||
summary = "Convert JSON to PDF",
|
||||
description =
|
||||
"Rebuilds a PDF from the editable JSON structure generated by the PDF to JSON"
|
||||
+ " endpoint. Input:JSON Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> convertJsonToPdf(@ModelAttribute GeneralFile request)
|
||||
throws Exception {
|
||||
MultipartFile jsonFile = request.getFileInput();
|
||||
if (jsonFile == null) {
|
||||
throw ExceptionUtils.createNullArgumentException("fileInput");
|
||||
}
|
||||
|
||||
byte[] pdfBytes = pdfJsonConversionService.convertJsonToPdf(jsonFile);
|
||||
String originalName = jsonFile.getOriginalFilename();
|
||||
String baseName =
|
||||
(originalName != null && !originalName.isBlank())
|
||||
? Filenames.toSimpleFileName(originalName).replaceFirst("[.][^.]+$", "")
|
||||
: "document";
|
||||
String docName = baseName.endsWith(".pdf") ? baseName : baseName + ".pdf";
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, docName);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Represents a PDF annotation (comments, highlights, stamps, etc.). Annotations often contain OCR
|
||||
* text layers or other metadata not visible in content streams.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonAnnotation {
|
||||
|
||||
/** Annotation subtype (Text, Highlight, Link, Stamp, Widget, etc.) */
|
||||
private String subtype;
|
||||
|
||||
/** Human-readable text content of the annotation */
|
||||
private String contents;
|
||||
|
||||
/** Annotation rectangle [x1, y1, x2, y2] */
|
||||
private List<Float> rect;
|
||||
|
||||
/** Annotation appearance characteristics */
|
||||
private String appearanceState;
|
||||
|
||||
/** Color components (e.g., [r, g, b] for RGB) */
|
||||
private List<Float> color;
|
||||
|
||||
/** Annotation flags (print, hidden, etc.) */
|
||||
private Integer flags;
|
||||
|
||||
/** For link annotations: destination or action */
|
||||
private String destination;
|
||||
|
||||
/** For text annotations: icon name */
|
||||
private String iconName;
|
||||
|
||||
/** Subject/title of the annotation */
|
||||
private String subject;
|
||||
|
||||
/** Author of the annotation */
|
||||
private String author;
|
||||
|
||||
/** Creation date (ISO 8601 format) */
|
||||
private String creationDate;
|
||||
|
||||
/** Modification date (ISO 8601 format) */
|
||||
private String modificationDate;
|
||||
|
||||
/** Full annotation dictionary for lossless round-tripping */
|
||||
private PdfJsonCosValue rawData;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonCosValue {
|
||||
|
||||
public enum Type {
|
||||
NULL,
|
||||
BOOLEAN,
|
||||
INTEGER,
|
||||
FLOAT,
|
||||
NAME,
|
||||
STRING,
|
||||
ARRAY,
|
||||
DICTIONARY,
|
||||
STREAM
|
||||
}
|
||||
|
||||
private Type type;
|
||||
|
||||
/**
|
||||
* Holds the decoded value for primitives (boolean, integer, float, name, string). For name
|
||||
* values the stored value is the PDF name literal. For string values the content is Base64
|
||||
* encoded to safely transport arbitrary binaries.
|
||||
*/
|
||||
private Object value;
|
||||
|
||||
/** Reference to nested values for arrays. */
|
||||
private List<PdfJsonCosValue> items;
|
||||
|
||||
/** Reference to nested values for dictionaries. */
|
||||
private Map<String, PdfJsonCosValue> entries;
|
||||
|
||||
/** Stream payload when {@code type == STREAM}. */
|
||||
private PdfJsonStream stream;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonDocument {
|
||||
|
||||
private PdfJsonMetadata metadata;
|
||||
|
||||
/** Optional XMP metadata packet stored as Base64. */
|
||||
private String xmpMetadata;
|
||||
|
||||
@Builder.Default private List<PdfJsonFont> fonts = new ArrayList<>();
|
||||
|
||||
@Builder.Default private List<PdfJsonPage> pages = new ArrayList<>();
|
||||
|
||||
/** Form fields (AcroForm) at document level */
|
||||
@Builder.Default private List<PdfJsonFormField> formFields = new ArrayList<>();
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonFont {
|
||||
|
||||
/** PDF resource name (e.g. F1) used as the primary identifier. */
|
||||
private String id;
|
||||
|
||||
/** Logical page number that owns this font resource. */
|
||||
private Integer pageNumber;
|
||||
|
||||
/** Stable UID combining page number and resource for diagnostics. */
|
||||
private String uid;
|
||||
|
||||
/** Reported PostScript/Base font name. */
|
||||
private String baseName;
|
||||
|
||||
/** Declared subtype in the COS dictionary. */
|
||||
private String subtype;
|
||||
|
||||
/** Encoding dictionary or name. */
|
||||
private String encoding;
|
||||
|
||||
/** CID system info for Type0 fonts. */
|
||||
private PdfJsonFontCidSystemInfo cidSystemInfo;
|
||||
|
||||
/** True when the original PDF embedded the font program. */
|
||||
private Boolean embedded;
|
||||
|
||||
/** Font program bytes (TTF/OTF/CFF/PFB) encoded as Base64. */
|
||||
private String program;
|
||||
|
||||
/** Hint describing the font program type (ttf, otf, cff, pfb, etc.). */
|
||||
private String programFormat;
|
||||
|
||||
/** Web-optimized font program (e.g. converted TrueType) encoded as Base64. */
|
||||
private String webProgram;
|
||||
|
||||
/** Format hint for the webProgram payload. */
|
||||
private String webProgramFormat;
|
||||
|
||||
/** ToUnicode stream encoded as Base64 when present. */
|
||||
private String toUnicode;
|
||||
|
||||
/** Mapped Standard 14 font name when available. */
|
||||
private String standard14Name;
|
||||
|
||||
/** Font descriptor flags copied from the source document. */
|
||||
private Integer fontDescriptorFlags;
|
||||
|
||||
/** Font ascent in glyph units (typically 1/1000). */
|
||||
private Float ascent;
|
||||
|
||||
/** Font descent in glyph units (typically negative). */
|
||||
private Float descent;
|
||||
|
||||
/** Capital height when available. */
|
||||
private Float capHeight;
|
||||
|
||||
/** x-height when available. */
|
||||
private Float xHeight;
|
||||
|
||||
/** Italic angle reported by the font descriptor. */
|
||||
private Float italicAngle;
|
||||
|
||||
/** Units per em extracted from the font matrix. */
|
||||
private Integer unitsPerEm;
|
||||
|
||||
/** Serialized COS dictionary describing the original font resource. */
|
||||
private PdfJsonCosValue cosDictionary;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonFontCidSystemInfo {
|
||||
|
||||
private String registry;
|
||||
private String ordering;
|
||||
private Integer supplement;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/** Represents a PDF form field (AcroForm). */
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonFormField {
|
||||
|
||||
/** Fully qualified field name (e.g., "form1.textfield1") */
|
||||
private String name;
|
||||
|
||||
/** Partial field name (last component) */
|
||||
private String partialName;
|
||||
|
||||
/** Field type (Tx=text, Btn=button, Ch=choice, Sig=signature) */
|
||||
private String fieldType;
|
||||
|
||||
/** Field value as string */
|
||||
private String value;
|
||||
|
||||
/** Default value */
|
||||
private String defaultValue;
|
||||
|
||||
/** Field flags (readonly, required, multiline, etc.) */
|
||||
private Integer flags;
|
||||
|
||||
/** Alternative field name (for accessibility) */
|
||||
private String alternateFieldName;
|
||||
|
||||
/** Mapping name (for export) */
|
||||
private String mappingName;
|
||||
|
||||
/** Page number where field appears (1-indexed) */
|
||||
private Integer pageNumber;
|
||||
|
||||
/** Field rectangle [x1, y1, x2, y2] on the page */
|
||||
private List<Float> rect;
|
||||
|
||||
/** For choice fields: list of options */
|
||||
private List<String> options;
|
||||
|
||||
/** For choice fields: selected indices */
|
||||
private List<Integer> selectedIndices;
|
||||
|
||||
/** For button fields: whether it's checked */
|
||||
private Boolean checked;
|
||||
|
||||
/** Font information for text fields */
|
||||
private String fontName;
|
||||
|
||||
private Float fontSize;
|
||||
|
||||
/** Full field dictionary for lossless round-tripping */
|
||||
private PdfJsonCosValue rawData;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonImageElement {
|
||||
|
||||
private String id;
|
||||
private String objectName;
|
||||
private Boolean inlineImage;
|
||||
private Integer nativeWidth;
|
||||
private Integer nativeHeight;
|
||||
private Float x;
|
||||
private Float y;
|
||||
private Float width;
|
||||
private Float height;
|
||||
private Float left;
|
||||
private Float right;
|
||||
private Float top;
|
||||
private Float bottom;
|
||||
@Builder.Default private List<Float> transform = new ArrayList<>();
|
||||
private Integer zOrder;
|
||||
private String imageData;
|
||||
private String imageFormat;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonMetadata {
|
||||
|
||||
private String title;
|
||||
private String author;
|
||||
private String subject;
|
||||
private String keywords;
|
||||
private String creator;
|
||||
private String producer;
|
||||
private String creationDate;
|
||||
private String modificationDate;
|
||||
private String trapped;
|
||||
private Integer numberOfPages;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonPage {
|
||||
|
||||
private Integer pageNumber;
|
||||
private Float width;
|
||||
private Float height;
|
||||
private Integer rotation;
|
||||
|
||||
@Builder.Default private List<PdfJsonTextElement> textElements = new ArrayList<>();
|
||||
@Builder.Default private List<PdfJsonImageElement> imageElements = new ArrayList<>();
|
||||
@Builder.Default private List<PdfJsonAnnotation> annotations = new ArrayList<>();
|
||||
|
||||
/** Serialized representation of the page resources dictionary. */
|
||||
private PdfJsonCosValue resources;
|
||||
|
||||
/** Raw content streams associated with the page, preserved for lossless round-tripping. */
|
||||
@Builder.Default private List<PdfJsonStream> contentStreams = new ArrayList<>();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonStream {
|
||||
|
||||
/**
|
||||
* A dictionary of entries that describe the stream metadata (Filter, DecodeParms, etc). Each
|
||||
* entry is represented using {@link PdfJsonCosValue} so nested structures are supported.
|
||||
*/
|
||||
private Map<String, PdfJsonCosValue> dictionary;
|
||||
|
||||
/** Raw stream bytes in Base64 form. Data is stored exactly as it appeared in the source PDF. */
|
||||
private String rawData;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonTextColor {
|
||||
|
||||
private String colorSpace;
|
||||
private List<Float> components;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package stirling.software.SPDF.model.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PdfJsonTextElement {
|
||||
|
||||
private String text;
|
||||
private String fontId;
|
||||
private Float fontSize;
|
||||
private Float fontMatrixSize;
|
||||
private Float fontSizeInPt;
|
||||
private Float characterSpacing;
|
||||
private Float wordSpacing;
|
||||
private Float spaceWidth;
|
||||
private Integer zOrder;
|
||||
private Float horizontalScaling;
|
||||
private Float leading;
|
||||
private Float rise;
|
||||
private Float x;
|
||||
private Float y;
|
||||
private Float width;
|
||||
private Float height;
|
||||
@Builder.Default private List<Float> textMatrix = new ArrayList<>();
|
||||
private PdfJsonTextColor fillColor;
|
||||
private PdfJsonTextColor strokeColor;
|
||||
private Integer renderingMode;
|
||||
private Boolean fallbackUsed;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user