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.util.server.control;
018
019import com.echothree.model.control.core.common.transfer.EntityLockTransfer;
020import com.echothree.model.control.core.server.control.EntityLockControl;
021import com.echothree.model.data.user.common.pk.UserVisitPK;
022import com.echothree.util.common.command.BaseResult;
023import com.echothree.util.common.command.CommandResult;
024import com.echothree.util.common.exception.EntityLockException;
025import com.echothree.util.common.validation.FieldDefinition;
026import com.echothree.util.common.command.EditMode;
027import com.echothree.util.common.form.BaseEdit;
028import com.echothree.util.common.form.BaseEditForm;
029import com.echothree.util.common.form.BaseForm;
030import com.echothree.util.common.form.BaseSpec;
031import com.echothree.util.common.form.ValidationResult;
032import com.echothree.util.common.persistence.BasePK;
033import com.echothree.util.server.persistence.BaseEntity;
034import com.echothree.util.server.persistence.BaseValue;
035import com.echothree.util.server.persistence.Session;
036import com.echothree.util.server.validation.Validator;
037import java.util.List;
038import java.util.concurrent.Future;
039import javax.inject.Inject;
040
041public abstract class BaseEditCommand<S extends BaseSpec, E extends BaseEdit>
042        extends BaseCommand {
043
044    @Inject
045    EntityLockControl entityLockControl;
046
047    private List<FieldDefinition> specFieldDefinitions;
048    private List<FieldDefinition> editFieldDefinitions;
049    protected EditMode editMode = null;
050    protected S spec = null;
051    protected E edit = null;
052    
053    protected BaseEditCommand(CommandSecurityDefinition commandSecurityDefinition,
054            List<FieldDefinition> specFieldDefinitions, List<FieldDefinition> editFieldDefinitions) {
055        super(commandSecurityDefinition);
056        
057        this.specFieldDefinitions = specFieldDefinitions;
058        this.editFieldDefinitions = editFieldDefinitions;
059    }
060
061    private void initForRun(BaseEditForm<S, E> editForm) {
062        if(editForm != null) {
063            editMode = editForm.getEditMode();
064            spec = editForm.getSpec();
065            edit = editForm.getEdit();
066        }
067    }
068
069    public <R extends BaseResult> Future<CommandResult<R>> runAsync(UserVisitPK userVisitPK, BaseEditForm<S, E> editForm) {
070        initForRun(editForm);
071
072        return super.runAsync(userVisitPK);
073    }
074
075    public <R extends BaseResult> CommandResult<R> run(UserVisitPK userVisitPK, BaseEditForm<S, E> editForm) {
076        initForRun(editForm);
077
078        return super.run(userVisitPK);
079    }
080
081    protected void setupValidatorForSpec(Validator validator) {
082        // Nothing.
083    }
084    
085    protected void setupValidatorForEdit(Validator validator, BaseForm specForm) {
086        // Nothing.
087    }
088    
089    protected ValidationResult validateSpec(Validator validator) {
090        return validator.validate(spec, getSpecFieldDefinitions());
091    }
092    
093    protected ValidationResult validateEdit(Validator validator) {
094        return validator.validate(edit, getEditFieldDefinitions());
095    }
096    
097    protected ValidationResult validateLock() {
098        var validator = new Validator(this);
099        
100        setupValidatorForSpec(validator);
101        
102        return validateSpec(validator);
103    }
104    
105    protected void saveResultAfterEditValidatorErrors() {
106        // Nothing.
107    }
108    
109    protected ValidationResult validateUpdate() {
110        var validator = new Validator(this);
111        ValidationResult validationResult;
112        BaseForm specForm = spec;
113        
114        setupValidatorForSpec(validator);
115        validationResult = validateSpec(validator);
116        
117        if(!validationResult.getHasErrors()) {
118            setupValidatorForEdit(validator, specForm);
119            validationResult = validateEdit(validator);
120            
121            if(validationResult.getHasErrors()) {
122                saveResultAfterEditValidatorErrors();
123            }
124        }
125        
126        return validationResult;
127    }
128    
129    @Override
130    protected ValidationResult validate() {
131        ValidationResult validationResult = null;
132        
133        if(editMode.equals(EditMode.LOCK)) {
134            validationResult = validateLock();
135        } else if(editMode.equals(EditMode.UPDATE)) {
136            validationResult = validateUpdate();
137        }
138        
139        return validationResult;
140    }
141    
142    protected List<FieldDefinition> getSpecFieldDefinitions() {
143        return specFieldDefinitions;
144    }
145    
146    protected void setSpecFieldDefinitions(List<FieldDefinition> specFieldDefinitions) {
147        this.specFieldDefinitions = specFieldDefinitions;
148    }
149    
150    protected List<FieldDefinition> getEditFieldDefinitions() {
151        return editFieldDefinitions;
152    }
153    
154    protected void setEditFieldDefinitions(List<FieldDefinition> editFieldDefinitions) {
155        this.editFieldDefinitions = editFieldDefinitions;
156    }
157    
158    public EntityLockTransfer getEntityLockTransfer(BaseEntity lockTarget)
159            throws EntityLockException {
160        return entityLockControl.getEntityLockTransfer(getUserVisit(), lockTarget);
161    }
162
163    public EntityLockTransfer getEntityLockTransfer(BasePK lockTarget)
164            throws EntityLockException {
165        return entityLockControl.getEntityLockTransfer(getUserVisit(), lockTarget);
166    }
167
168    public EntityLockTransfer getEntityLockTransfer(BaseValue lockTarget)
169            throws EntityLockException {
170        return entityLockControl.getEntityLockTransfer(getUserVisit(), lockTarget);
171    }
172
173    public boolean lockEntity(BaseEntity lockTarget)
174            throws EntityLockException {
175        return entityLockControl.lockEntity(lockTarget, getPartyPK()) != 0;
176    }
177
178    public boolean lockEntity(BasePK lockTarget)
179            throws EntityLockException {
180        return entityLockControl.lockEntity(lockTarget, getPartyPK()) != 0;
181    }
182
183    public boolean lockEntity(BaseValue lockTarget)
184            throws EntityLockException {
185        return entityLockControl.lockEntity(lockTarget, getPartyPK()) != 0;
186    }
187
188    public boolean lockEntityForUpdate(BaseEntity lockTarget)
189            throws EntityLockException {
190        return entityLockControl.lockEntityForUpdate(lockTarget, getPartyPK());
191    }
192
193    public boolean lockEntityForUpdate(BasePK lockTarget)
194            throws EntityLockException {
195        return entityLockControl.lockEntityForUpdate(lockTarget, getPartyPK());
196    }
197
198    public boolean lockEntityForUpdate(BaseValue lockTarget)
199            throws EntityLockException {
200        return entityLockControl.lockEntityForUpdate(lockTarget, getPartyPK());
201    }
202
203    public boolean unlockEntity(BaseEntity lockTarget)
204            throws EntityLockException {
205        return entityLockControl.unlockEntity(lockTarget, getPartyPK());
206    }
207
208    public boolean unlockEntity(BasePK lockTarget)
209            throws EntityLockException {
210        return entityLockControl.unlockEntity(lockTarget, getPartyPK());
211    }
212
213    public boolean unlockEntity(BaseValue lockTarget)
214            throws EntityLockException {
215        return entityLockControl.unlockEntity(lockTarget, getPartyPK());
216    }
217
218    public boolean isEntityLocked(BaseEntity lockTarget)
219            throws EntityLockException {
220        return entityLockControl.isEntityLocked(lockTarget, getPartyPK());
221    }
222
223    public boolean isEntityLocked(BasePK lockTarget)
224            throws EntityLockException {
225        return entityLockControl.isEntityLocked(lockTarget, getPartyPK());
226    }
227
228    public boolean isEntityLocked(BaseValue lockTarget)
229            throws EntityLockException {
230        return entityLockControl.isEntityLocked(lockTarget, getPartyPK());
231    }
232    
233}