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