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.EntityAttributeTypes; 020import com.echothree.model.control.core.common.MimeTypes; 021import com.echothree.model.control.core.server.control.MimeTypeControl; 022import com.echothree.model.data.user.common.pk.UserVisitPK; 023import com.echothree.util.common.command.BaseResult; 024import com.echothree.util.common.command.CommandResult; 025import com.echothree.util.common.form.BaseForm; 026import com.echothree.util.common.form.ValidationResult; 027import com.echothree.util.common.message.ExecutionErrors; 028import com.echothree.util.common.validation.FieldDefinition; 029import com.echothree.util.server.validation.Validator; 030import java.util.List; 031import java.util.concurrent.Future; 032import javax.inject.Inject; 033 034public abstract class BaseSimpleCommand<F extends BaseForm> 035 extends BaseCommand { 036 037 protected F form; 038 private List<FieldDefinition> formFieldDefinitions; 039 boolean allowLimits; 040 041 @Inject 042 protected MimeTypeControl mimeTypeControl; 043 044 private void init(F form, List<FieldDefinition> formFieldDefinitions, boolean allowLimits) { 045 this.form = form; 046 this.formFieldDefinitions = formFieldDefinitions; 047 this.allowLimits = allowLimits; 048 } 049 050 protected BaseSimpleCommand(CommandSecurityDefinition commandSecurityDefinition, 051 List<FieldDefinition> formFieldDefinitions, boolean allowLimits) { 052 super(commandSecurityDefinition); 053 054 init(form, formFieldDefinitions, allowLimits); 055 } 056 057 protected BaseSimpleCommand(CommandSecurityDefinition commandSecurityDefinition, boolean allowLimits) { 058 super(commandSecurityDefinition); 059 060 init(null, null, allowLimits); 061 } 062 063 @Override 064 protected void setupSession() { 065 super.setupSession(); 066 067 if(form != null) { 068 session.setOptions(form.getOptions()); 069 session.setTransferProperties(form.getTransferProperties()); 070 071 if(allowLimits) { 072 session.setLimits(form.getLimits()); 073 } 074 } 075 } 076 077 protected F getForm() { 078 return form; 079 } 080 081 protected List<FieldDefinition> getFormFieldDefinitions() { 082 return formFieldDefinitions; 083 } 084 085 protected void setupValidator(Validator validator) { 086 // Nothing. 087 } 088 089 protected ValidationResult validate(Validator validator) { 090 return validator.validate(form, getFormFieldDefinitions()); 091 } 092 093 @Override 094 protected ValidationResult validate() { 095 ValidationResult validationResult = null; 096 097 if(getFormFieldDefinitions() != null) { 098 var validator = new Validator(this); 099 100 setupValidator(validator); 101 validationResult = validate(validator); 102 } 103 104 return validationResult; 105 } 106 107 protected void setupPreferredClobMimeType() { 108 var preferredClobMimeTypeName = form.getPreferredClobMimeTypeName(); 109 110 if(preferredClobMimeTypeName != null) { 111 var preferredClobMimeType = mimeTypeControl.getMimeTypeByName(preferredClobMimeTypeName); 112 113 if(preferredClobMimeType == null) { 114 addExecutionError(ExecutionErrors.UnknownPreferredClobMimeTypeName.name(), preferredClobMimeTypeName); 115 } else { 116 var preferredClobMimeTypeDetail = preferredClobMimeType.getLastDetail(); 117 var entityAttributeTypeName = preferredClobMimeTypeDetail.getEntityAttributeType().getEntityAttributeTypeName(); 118 119 // Must be a CLOB and for now the preferred MIME type must be HTML. 120 if(!entityAttributeTypeName.equals(EntityAttributeTypes.CLOB.name()) 121 || !preferredClobMimeTypeDetail.getMimeTypeName().equals(MimeTypes.TEXT_HTML.mimeTypeName())) { 122 addExecutionError(ExecutionErrors.InvalidPreferredClobMimeType.name(), preferredClobMimeTypeName, entityAttributeTypeName); 123 } else { 124 session.setPreferredClobMimeType(preferredClobMimeType); 125 } 126 } 127 } 128 } 129 130 private void initForRun(F form) { 131 this.form = form; 132 } 133 134 public <R extends BaseResult> Future<CommandResult<R>> runAsync(UserVisitPK userVisitPK, F form) { 135 initForRun(form); 136 137 return super.runAsync(userVisitPK); 138 } 139 140 public <R extends BaseResult> CommandResult<R> run(UserVisitPK userVisitPK, F form) { 141 initForRun(form); 142 143 return super.run(userVisitPK); 144 } 145 146 // Perform security and validation for GraphQL queries. 147 public boolean canQueryByGraphQl(UserVisitPK userVisitPK, F form) { 148 initForRun(form); 149 setUserVisitPK(userVisitPK); 150 151 initSession(); 152 153 var securityResult = security(); 154 var canQuery = false; 155 156 if(securityResult == null || !securityResult.getHasMessages()) { 157 var validationResult = validate(); 158 159 if((validationResult == null || !validationResult.getHasErrors())) { 160 canQuery = true; 161 } 162 } 163 164 return canQuery; 165 } 166}