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