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.control.user.document.server.command;
018
019import com.echothree.control.user.document.common.edit.DocumentEditFactory;
020import com.echothree.control.user.document.common.edit.PartyDocumentEdit;
021import com.echothree.control.user.document.common.form.EditPartyDocumentForm;
022import com.echothree.control.user.document.common.result.DocumentResultFactory;
023import com.echothree.control.user.document.common.result.EditPartyDocumentResult;
024import com.echothree.control.user.document.common.spec.DocumentSpec;
025import com.echothree.model.control.core.common.EntityAttributeTypes;
026import com.echothree.model.control.core.server.control.MimeTypeControl;
027import com.echothree.model.control.document.server.control.DocumentControl;
028import com.echothree.model.control.document.server.logic.DocumentLogic;
029import com.echothree.model.control.party.common.PartyTypes;
030import com.echothree.model.control.security.common.SecurityRoleGroups;
031import com.echothree.model.control.security.common.SecurityRoles;
032import com.echothree.model.data.core.server.entity.MimeType;
033import com.echothree.model.data.document.server.entity.Document;
034import com.echothree.model.data.document.server.entity.DocumentBlob;
035import com.echothree.model.data.document.server.entity.DocumentClob;
036import com.echothree.model.data.document.server.entity.PartyDocument;
037import com.echothree.model.data.user.common.pk.UserVisitPK;
038import com.echothree.util.common.command.EditMode;
039import com.echothree.util.common.message.ExecutionErrors;
040import com.echothree.util.common.persistence.type.ByteArray;
041import com.echothree.util.common.validation.FieldDefinition;
042import com.echothree.util.common.validation.FieldType;
043import com.echothree.util.server.control.BaseAbstractEditCommand;
044import com.echothree.util.server.control.CommandSecurityDefinition;
045import com.echothree.util.server.control.PartyTypeDefinition;
046import com.echothree.util.server.control.SecurityRoleDefinition;
047import com.echothree.util.server.persistence.Session;
048import java.util.List;
049import javax.enterprise.context.Dependent;
050
051@Dependent
052public class EditPartyDocumentCommand
053        extends BaseAbstractEditCommand<DocumentSpec, PartyDocumentEdit, EditPartyDocumentResult, PartyDocument, Document> {
054    
055    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
056    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
057    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
058    
059    static {
060        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
061                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
062                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
063                    new SecurityRoleDefinition(SecurityRoleGroups.PartyDocument.name(), SecurityRoles.Edit.name())
064                    ))
065                ));
066        
067        SPEC_FIELD_DEFINITIONS = List.of(
068                new FieldDefinition("DocumentName", FieldType.ENTITY_NAME, true, null, null)
069                );
070        
071        EDIT_FIELD_DEFINITIONS = List.of(
072                new FieldDefinition("MimeTypeName", FieldType.MIME_TYPE, true, null, null),
073                new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null),
074                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
075                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L),
076                new FieldDefinition("Clob", FieldType.STRING, false, 1L, null)
077                );
078    }
079    
080    /** Creates a new instance of EditPartyDocumentCommand */
081    public EditPartyDocumentCommand() {
082        super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
083    }
084
085    @Override
086    public EditPartyDocumentResult getResult() {
087        return DocumentResultFactory.getEditPartyDocumentResult();
088    }
089
090    @Override
091    public PartyDocumentEdit getEdit() {
092        return DocumentEditFactory.getPartyDocumentEdit();
093    }
094
095    @Override
096    public PartyDocument getEntity(EditPartyDocumentResult result) {
097        var documentControl = Session.getModelController(DocumentControl.class);
098        PartyDocument partyDocument = null;
099        var documentName = spec.getDocumentName();
100        var document = documentControl.getDocumentByName(documentName);
101
102        if(document != null) {
103            if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
104                partyDocument = documentControl.getPartyDocument(document);
105            } else { // EditMode.UPDATE
106                partyDocument = documentControl.getPartyDocumentForUpdate(document);
107            }
108
109            if(partyDocument != null) {
110                result.setPartyDocument(documentControl.getPartyDocumentTransfer(getUserVisit(), partyDocument));
111            } else {
112                addExecutionError(ExecutionErrors.UnknownPartyDocument.name(), documentName);
113            }
114        } else {
115            addExecutionError(ExecutionErrors.UnknownDocumentName.name(), documentName);
116        }
117
118        return partyDocument;
119    }
120
121    @Override
122    public Document getLockEntity(PartyDocument partyDocument) {
123        return partyDocument.getDocument();
124    }
125
126    @Override
127    public void fillInResult(EditPartyDocumentResult result, PartyDocument partyDocument) {
128        var documentControl = Session.getModelController(DocumentControl.class);
129
130        result.setPartyDocument(documentControl.getPartyDocumentTransfer(getUserVisit(), partyDocument));
131    }
132
133    MimeType mimeType;
134
135    @Override
136    public void doLock(PartyDocumentEdit edit, PartyDocument partyDocument) {
137        var documentControl = Session.getModelController(DocumentControl.class);
138        var document = partyDocument.getDocument();
139        var documentDescription = documentControl.getDocumentDescription(document, getPreferredLanguage());
140
141        mimeType = document.getLastDetail().getMimeType();
142
143        edit.setMimeTypeName(mimeType.getLastDetail().getMimeTypeName());
144        edit.setIsDefault(partyDocument.getIsDefault().toString());
145        edit.setSortOrder(partyDocument.getSortOrder().toString());
146
147        if(mimeType.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName().equals(EntityAttributeTypes.CLOB.name())) {
148            var documentClob = documentControl.getDocumentClob(document);
149
150            edit.setClob(documentClob.getClob());
151        }
152
153        if(documentDescription != null) {
154            edit.setDescription(documentDescription.getDescription());
155        }
156    }
157
158    @Override
159    public void canUpdate(PartyDocument partyDocument) {
160        var mimeTypeControl = Session.getModelController(MimeTypeControl.class);
161        var mimeTypeName = edit.getMimeTypeName();
162
163        mimeType = mimeTypeControl.getMimeTypeByName(mimeTypeName);
164
165        if(mimeType != null) {
166            var mimeTypeUsageType = partyDocument.getDocument().getLastDetail().getDocumentType().getLastDetail().getMimeTypeUsageType();
167            var mimeTypeUsage = mimeTypeUsageType == null ? null : mimeTypeControl.getMimeTypeUsage(mimeType, mimeTypeUsageType);
168
169            if(mimeTypeUsageType == null || mimeTypeUsage != null) {
170                var entityAttributeTypeName = mimeType.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
171
172                if(entityAttributeTypeName.equals(EntityAttributeTypes.BLOB.name())) {
173                    var blob = edit.getBlob();
174
175                    if(blob == null) {
176                        addExecutionError(ExecutionErrors.MissingBlob.name());
177                    }
178                } else if(entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) {
179                    var clob = edit.getClob();
180
181                    if(clob == null) {
182                        addExecutionError(ExecutionErrors.MissingClob.name());
183                    }
184                } else {
185                    addExecutionError(ExecutionErrors.UnknownEntityAttributeTypeName.name(), entityAttributeTypeName);
186                }
187            } else {
188                addExecutionError(ExecutionErrors.UnknownMimeTypeUsage.name());
189            }
190        } else {
191            addExecutionError(ExecutionErrors.UnknownMimeTypeName.name(), mimeTypeName);
192        }
193    }
194
195    @Override
196    public void doUpdate(PartyDocument partyDocument) {
197        var documentControl = Session.getModelController(DocumentControl.class);
198        var partyDocumentValue = documentControl.getPartyDocumentValueForUpdate(partyDocument);
199        var document = partyDocument.getDocument();
200        var documentDetailValue = documentControl.getDocumentDetailValueForUpdate(document);
201        var blob = edit.getBlob();
202        var clob = edit.getClob();
203        var pages = DocumentLogic.getInstance().getPages(mimeType, blob, clob);
204        var partyPK = getPartyPK();
205
206        partyDocumentValue.setIsDefault(Boolean.valueOf(edit.getIsDefault()));
207        partyDocumentValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
208
209        documentControl.updatePartyDocumentFromValue(partyDocumentValue, partyPK);
210
211        documentDetailValue.setMimeTypePK(mimeType.getPrimaryKey());
212        documentDetailValue.setPages(pages);
213
214        documentControl.updateDocumentFromValue(documentDetailValue, partyPK);
215        
216        doLobUpdate(document, blob, clob);
217        doDescriptionUpdate(document);
218    }
219
220    private void doLobUpdate(Document document, ByteArray blob, String clob) {
221        var documentControl = Session.getModelController(DocumentControl.class);
222        DocumentBlob documentBlob = null;
223        DocumentClob documentClob = null;
224        var oldEntityAttributeTypeName = document.getLastDetail().getMimeType().getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
225        var entityAttributeTypeName = mimeType.getLastDetail().getEntityAttributeType().getEntityAttributeTypeName();
226        var partyPK = getPartyPK();
227
228        if(oldEntityAttributeTypeName.equals(EntityAttributeTypes.BLOB.name())) {
229            documentBlob = documentControl.getDocumentBlobForUpdate(document);
230        } else if(oldEntityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) {
231            documentClob = documentControl.getDocumentClobForUpdate(document);
232        }
233        
234        if(entityAttributeTypeName.equals(EntityAttributeTypes.BLOB.name())) {
235            if(documentClob != null) {
236                documentControl.deleteDocumentClob(documentClob, partyPK);
237                documentControl.createDocumentBlob(document, blob, partyPK);
238            } else {
239                var documentBlobValue = documentControl.getDocumentBlobValue(documentBlob);
240                documentBlobValue.setBlob(blob);
241                documentControl.updateDocumentBlobFromValue(documentBlobValue, partyPK);
242            }
243        } else if(entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name())) {
244            if(documentBlob != null) {
245                documentControl.deleteDocumentBlob(documentBlob, partyPK);
246                documentControl.createDocumentClob(document, clob, partyPK);
247            } else {
248                var documentClobValue = documentControl.getDocumentClobValue(documentClob);
249                documentClobValue.setClob(clob);
250                documentControl.updateDocumentClobFromValue(documentClobValue, partyPK);
251            }
252        }
253    }
254
255    private void doDescriptionUpdate(Document document) {
256        var documentControl = Session.getModelController(DocumentControl.class);
257        var documentDescription = documentControl.getDocumentDescriptionForUpdate(document, getPreferredLanguage());
258        var description = edit.getDescription();
259        var partyPK = getPartyPK();
260
261        if(documentDescription == null && description != null) {
262            documentControl.createDocumentDescription(document, getPreferredLanguage(), description, partyPK);
263        } else {
264            if(documentDescription != null && description == null) {
265                documentControl.deleteDocumentDescription(documentDescription, partyPK);
266            } else {
267                if(documentDescription != null && description != null) {
268                    var documentDescriptionValue = documentControl.getDocumentDescriptionValue(documentDescription);
269                    documentDescriptionValue.setDescription(description);
270                    documentControl.updateDocumentDescriptionFromValue(documentDescriptionValue, partyPK);
271                }
272            }
273        }
274    }
275
276}