001// --------------------------------------------------------------------------------
002// Copyright 2002-2026 Echo Three, LLC
003//
004// Licensed under the Apache License, Version 2.0 (the "License");
005// you may not use this file except in compliance with the License.
006// You may obtain a copy of the License at
007//
008//     http://www.apache.org/licenses/LICENSE-2.0
009//
010// Unless required by applicable law or agreed to in writing, software
011// distributed under the License is distributed on an "AS IS" BASIS,
012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013// See the License for the specific language governing permissions and
014// limitations under the License.
015// --------------------------------------------------------------------------------
016
017package com.echothree.model.control.document.server.logic;
018
019import com.echothree.control.user.document.common.spec.DocumentUniversalSpec;
020import com.echothree.model.control.core.common.ComponentVendors;
021import com.echothree.model.control.core.common.EntityAttributeTypes;
022import com.echothree.model.control.core.common.EntityTypes;
023import com.echothree.model.control.core.common.MimeTypes;
024import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
025import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
026import com.echothree.model.control.document.common.exception.UnknownDocumentNameException;
027import com.echothree.model.control.document.server.control.DocumentControl;
028import com.echothree.model.data.core.server.entity.MimeType;
029import com.echothree.model.data.document.server.entity.Document;
030import com.echothree.model.data.document.server.entity.DocumentType;
031import com.echothree.model.data.document.server.entity.PartyDocument;
032import com.echothree.model.data.party.common.pk.PartyPK;
033import com.echothree.model.data.party.server.entity.Language;
034import com.echothree.model.data.party.server.entity.Party;
035import com.echothree.util.common.message.ExecutionErrors;
036import com.echothree.util.common.persistence.type.ByteArray;
037import com.echothree.util.server.control.BaseLogic;
038import com.echothree.util.server.message.ExecutionErrorAccumulator;
039import com.echothree.util.server.persistence.EntityPermission;
040import com.lowagie.text.pdf.PdfReader;
041import java.io.IOException;
042import javax.enterprise.context.ApplicationScoped;
043import javax.inject.Inject;
044
045@ApplicationScoped
046public class DocumentLogic
047        extends BaseLogic {
048
049    @Inject
050    DocumentControl documentControl;
051
052    @Inject
053    EntityInstanceLogic entityInstanceLogic;
054
055    protected DocumentLogic() {
056        super();
057    }
058
059    public Integer getPages(final MimeType mimeType, final ByteArray blob, final String clob) {
060        Integer pages = null;
061        var entityAttributeTypeName = mimeType.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
062
063        if(entityAttributeTypeName.equals(EntityAttributeTypes.BLOB.name())) {
064            var mimeTypeName = mimeType.getLastDetail().getMimeTypeName();
065
066            if(mimeTypeName.equals(MimeTypes.APPLICATION_PDF.mimeTypeName()) && blob != null) {
067                try {
068                    var pdfReader = new PdfReader(blob.getByteArrayInputStream());
069
070                    pages = pdfReader.getNumberOfPages();
071                } catch(IOException ioe) {
072                    // Nothing, pages stays null.
073                }
074            }
075        }
076
077        return pages;
078    }
079
080    public Document createDocument(final ExecutionErrorAccumulator ema, final DocumentType documentType, final MimeType mimeType,
081            final Language preferredLanguage, final String description, final ByteArray blob, final String clob, final PartyPK createdBy) {
082        var pages = getPages(mimeType, blob, clob);
083        Document document = null;
084        var hasErrors = false;
085
086        if(pages != null) {
087            var documentTypeDetail = documentType.getLastDetail();
088            var maximumPages = documentTypeDetail.getMaximumPages();
089
090            if(maximumPages != null) {
091                if(pages > maximumPages) {
092                    hasErrors = true;
093                    addExecutionError(ema, ExecutionErrors.DocumentExceedesMaximumPages.name());
094                }
095            }
096        }
097
098        if(!hasErrors) {
099            document = documentControl.createDocument(documentType, mimeType, pages, createdBy);
100
101            if(blob != null) {
102                documentControl.createDocumentBlob(document, blob, createdBy);
103            } else if(clob != null) {
104                documentControl.createDocumentClob(document, clob, createdBy);
105            }
106
107            if(description != null) {
108                documentControl.createDocumentDescription(document, preferredLanguage, description, createdBy);
109            }
110        }
111
112        return document;
113    }
114
115    public Document getDocumentByName(final ExecutionErrorAccumulator eea, final String documentName,
116            final EntityPermission entityPermission) {
117        var document = documentControl.getDocumentByName(documentName, entityPermission);
118
119        if(document == null) {
120            handleExecutionError(UnknownDocumentNameException.class, eea, ExecutionErrors.UnknownDocumentName.name(),
121                    documentName);
122        }
123
124        return document;
125    }
126
127    public Document getDocumentByName(final ExecutionErrorAccumulator eea, final String documentName) {
128        return getDocumentByName(eea, documentName, EntityPermission.READ_ONLY);
129    }
130
131    public Document getDocumentByNameForUpdate(final ExecutionErrorAccumulator eea, final String documentName) {
132        return getDocumentByName(eea, documentName, EntityPermission.READ_WRITE);
133    }
134
135    public Document getDocumentByUniversalSpec(final ExecutionErrorAccumulator eea,
136            final DocumentUniversalSpec universalSpec, final EntityPermission entityPermission) {
137        Document document = null;
138        var documentName = universalSpec.getDocumentName();
139        var possibleEntitySpecs = entityInstanceLogic.countPossibleEntitySpecs(universalSpec);
140        var parameterCount = (documentName == null ? 0 : 1) + possibleEntitySpecs;
141
142        switch(parameterCount) {
143            case 1 -> {
144                if(possibleEntitySpecs == 1) {
145                    var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec,
146                            ComponentVendors.ECHO_THREE.name(), EntityTypes.Document.name());
147
148                    if(eea == null || !eea.hasExecutionErrors()) {
149                        document = documentControl.getDocumentByEntityInstance(entityInstance, entityPermission);
150                    }
151                } else {
152                    document = getDocumentByName(eea, documentName, entityPermission);
153                }
154            }
155            default ->
156                    handleExecutionError(InvalidParameterCountException.class, eea,
157                            ExecutionErrors.InvalidParameterCount.name());
158        }
159
160        return document;
161    }
162
163    public Document getDocumentByUniversalSpec(final ExecutionErrorAccumulator eea,
164            final DocumentUniversalSpec universalSpec) {
165        return getDocumentByUniversalSpec(eea, universalSpec, EntityPermission.READ_ONLY);
166    }
167
168    public Document getDocumentByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea,
169            final DocumentUniversalSpec universalSpec) {
170        return getDocumentByUniversalSpec(eea, universalSpec, EntityPermission.READ_WRITE);
171    }
172
173    public PartyDocument createPartyDocument(final ExecutionErrorAccumulator ema, final Party party, final DocumentType documentType, final MimeType mimeType,
174            final Boolean isDefault, final Integer sortOrder,  final Language preferredLanguage, final String description, final ByteArray blob,
175            final String clob, final PartyPK createdBy) {
176        var document = createDocument(ema, documentType, mimeType, preferredLanguage, description, blob, clob, createdBy);
177
178        return document == null ? null : documentControl.createPartyDocument(party, document, isDefault, sortOrder, createdBy);
179    }
180
181}