刘光辉
8 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package jnpf.bizcommon.onlyoffice.service.impl;
 
import jnpf.base.UserInfo;
import jnpf.bizcommon.onlyoffice.entity.DmsPrintRenderItem;
import jnpf.bizcommon.onlyoffice.entity.DmsPrintRenderRequest;
import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeProperties;
import jnpf.dmsEntity.preview.model.DmsFilePreviewTicket;
import jnpf.exception.DataException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
 
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
 
@Service
@RequiredArgsConstructor
public class DmsOnlyOfficePrintService {
    private final DmsOnlyOfficePrintTicketValidator validator;
    private final OnlyOfficeDmsPrintRenderer renderer;
    private final DmsOnlyOfficePrintPdfComposer composer;
    private final OnlyOfficeProperties properties;
 
    public byte[] render(DmsPrintRenderRequest request, UserInfo user) {
        List<DmsPrintRenderItem> items = items(request);
        UUID fileVersionId = items.get(0).getFileVersionId();
        String fileName = items.get(0).getFileName();
        Set<String> accessTickets = new HashSet<>();
        List<DmsFilePreviewTicket> tickets = new ArrayList<>(items.size());
        for (DmsPrintRenderItem item : items) {
            if (!fileVersionId.equals(item.getFileVersionId())
                    || !fileName.equals(item.getFileName())
                    || !accessTickets.add(item.getAccessTicket())) {
                throw new DataException("批量打印必须使用同一文件且每份使用独立票据");
            }
            DmsFilePreviewTicket ticket = validator.validate(item, user);
            applyPageSubset(ticket, item.getPrintPages());
            tickets.add(ticket);
        }
        DmsPrintRenderItem sourceItem = request.sourceItem();
        DmsFilePreviewTicket sourceTicket;
        if (sameItem(sourceItem, items.get(0))) {
            sourceTicket = tickets.get(0);
        } else {
            sourceTicket = validator.validate(sourceItem, user);
            if (!fileVersionId.equals(sourceItem.getFileVersionId())
                    || !fileName.equals(sourceItem.getFileName())) {
                throw new DataException("基础打印文件与批次文件不一致");
            }
        }
        byte[] basePdf = renderer.renderBase(sourceTicket, sourceItem.getAccessTicket());
        return composer.compose(basePdf, tickets);
    }
 
    private List<DmsPrintRenderItem> items(DmsPrintRenderRequest request) {
        if (request == null) {
            throw new DataException("缺少 DMS 打印转换参数");
        }
        boolean hasItems = request.getItems() != null;
        boolean hasLegacy = request.getFileVersionId() != null
                || !ObjectUtils.isEmpty(request.getFileName())
                || !ObjectUtils.isEmpty(request.getAccessTicket());
        if (hasItems == hasLegacy) {
            throw new DataException("单份打印参数和批量打印 items 必须且只能使用一种");
        }
        List<DmsPrintRenderItem> items = hasItems
                ? request.getItems() : List.of(request.legacyItem());
        if (items.isEmpty() || items.size() > properties.getDmsPrint().getMaxBatchItems()) {
            throw new DataException("批量打印份数超过系统限制");
        }
        for (DmsPrintRenderItem item : items) {
            if (item == null || item.getFileVersionId() == null
                    || ObjectUtils.isEmpty(item.getFileName())
                    || ObjectUtils.isEmpty(item.getAccessTicket())) {
                throw new DataException("DMS 打印转换参数不完整");
            }
        }
        return items;
    }
 
    private boolean sameItem(DmsPrintRenderItem left, DmsPrintRenderItem right) {
        return left != null && right != null
                && java.util.Objects.equals(left.getFileVersionId(), right.getFileVersionId())
                && java.util.Objects.equals(left.getFileName(), right.getFileName())
                && java.util.Objects.equals(left.getAccessTicket(), right.getAccessTicket());
    }
 
    private void applyPageSubset(DmsFilePreviewTicket ticket, String requestedPages) {
        if (ObjectUtils.isEmpty(requestedPages)) return;
        Set<Integer> requested = parsePages(requestedPages);
        if (!ObjectUtils.isEmpty(ticket.getPrintPages())
                && !parsePages(ticket.getPrintPages()).containsAll(requested)) {
            throw new DataException("批次打印页码超出票据授权范围");
        }
        ticket.setPrintPages(requestedPages.trim());
    }
 
    private Set<Integer> parsePages(String value) {
        Set<Integer> pages = new LinkedHashSet<>();
        for (String raw : value.split(",", -1)) {
            String token = raw.trim();
            if (!token.matches("\\d+(?:\\s*-\\s*\\d+)?")) {
                throw new DataException("批次打印页码格式无效");
            }
            String[] bounds = token.split("\\s*-\\s*");
            int start;
            int end;
            try {
                start = Integer.parseInt(bounds[0]);
                end = bounds.length == 1 ? start : Integer.parseInt(bounds[1]);
            } catch (NumberFormatException exception) {
                throw new DataException("批次打印页码格式无效");
            }
            if (start < 1 || end < start || end - start + 1L + pages.size()
                    > properties.getDmsPrint().getMaxPages()) {
                throw new DataException("批次打印页码超过系统限制");
            }
            for (int page = start; page <= end; page++) pages.add(page);
        }
        return pages;
    }
 
}