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.model.control.chain.server.logic; 018 019import com.echothree.control.user.chain.common.spec.ChainUniversalSpec; 020import com.echothree.model.control.chain.common.exception.CannotDeleteChainInUseException; 021import com.echothree.model.control.chain.common.exception.DuplicateChainNameException; 022import com.echothree.model.control.chain.common.exception.UnknownChainNameException; 023import com.echothree.model.control.chain.common.exception.UnknownDefaultChainException; 024import com.echothree.model.control.chain.common.exception.UnknownDefaultChainKindException; 025import com.echothree.model.control.chain.common.exception.UnknownDefaultChainTypeException; 026import com.echothree.model.control.chain.server.control.ChainControl; 027import com.echothree.model.control.core.common.ComponentVendors; 028import com.echothree.model.control.core.common.EntityTypes; 029import com.echothree.model.control.core.common.exception.InvalidParameterCountException; 030import com.echothree.model.control.core.server.logic.EntityInstanceLogic; 031import com.echothree.model.control.customer.server.control.CustomerControl; 032import com.echothree.model.control.offer.server.control.OfferControl; 033import com.echothree.model.control.sequence.common.SequenceTypes; 034import com.echothree.model.control.sequence.server.logic.SequenceLogic; 035import com.echothree.model.data.chain.server.entity.Chain; 036import com.echothree.model.data.chain.server.entity.ChainKind; 037import com.echothree.model.data.chain.server.entity.ChainType; 038import com.echothree.model.data.party.server.entity.Language; 039import com.echothree.model.data.party.server.entity.Party; 040import com.echothree.model.data.sequence.server.entity.Sequence; 041import com.echothree.util.common.message.ExecutionErrors; 042import com.echothree.util.common.persistence.BasePK; 043import com.echothree.util.server.control.BaseLogic; 044import com.echothree.util.server.message.ExecutionErrorAccumulator; 045import com.echothree.util.server.persistence.EntityPermission; 046import com.echothree.util.server.validation.ParameterUtils; 047import javax.enterprise.context.ApplicationScoped; 048import javax.inject.Inject; 049 050@ApplicationScoped 051public class ChainLogic 052 extends BaseLogic { 053 054 @Inject 055 ChainControl chainControl; 056 057 @Inject 058 CustomerControl customerControl; 059 060 @Inject 061 OfferControl offerControl; 062 063 @Inject 064 ChainKindLogic chainKindLogic; 065 066 @Inject 067 ChainTypeLogic chainTypeLogic; 068 069 @Inject 070 EntityInstanceLogic entityInstanceLogic; 071 072 @Inject 073 SequenceLogic sequenceLogic; 074 075 protected ChainLogic() { 076 super(); 077 } 078 079 public Chain createChain(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName, 080 final String chainName, final String initialChainAdjustmentName, final String chainItemSelectorName, 081 final Boolean isDefault, final Integer sortOrder, final Language language, final String description, 082 final BasePK createdBy) { 083 var chainType = chainTypeLogic.getChainTypeByName(eea, chainKindName, chainTypeName); 084 Chain chain = null; 085 086 if(eea == null || !eea.hasExecutionErrors()) { 087 var chainInstanceSequence = initialChainAdjustmentName == null ? null : 088 sequenceLogic.getSequenceByName(eea, SequenceTypes.CHAIN_INSTANCE.name(), initialChainAdjustmentName); 089 090 if(eea == null || !eea.hasExecutionErrors()) { 091 chain = createChain(eea, chainType, chainName, chainInstanceSequence, 092 isDefault, sortOrder, language, description, createdBy); 093 } 094 } 095 096 return chain; 097 } 098 099 public Chain createChain(final ExecutionErrorAccumulator eea, final ChainType chainType, final String chainName, 100 final Sequence chainInstanceSequence, final Boolean isDefault, final Integer sortOrder, final Language language, 101 final String description, final BasePK createdBy) { 102 var chain = chainControl.getChainByName(chainType, chainName); 103 104 if(chain == null) { 105 chain = chainControl.createChain(chainType, chainName, chainInstanceSequence, isDefault, sortOrder, createdBy); 106 107 if(description != null) { 108 chainControl.createChainDescription(chain, language, description, createdBy); 109 } 110 } else { 111 handleExecutionError(DuplicateChainNameException.class, eea, ExecutionErrors.DuplicateChainName.name(), chainName); 112 } 113 return chain; 114 } 115 116 public Chain getChainByName(final ExecutionErrorAccumulator eea, final ChainType chainType, final String chainName, 117 final EntityPermission entityPermission) { 118 var chain = chainControl.getChainByName(chainType, chainName, entityPermission); 119 120 if(chain == null) { 121 handleExecutionError(UnknownChainNameException.class, eea, ExecutionErrors.UnknownChainName.name(), 122 chainType.getLastDetail().getChainKind().getLastDetail().getChainKindName(), 123 chainType.getLastDetail().getChainTypeName(), chainName); 124 } 125 126 return chain; 127 } 128 129 public Chain getChainByName(final ExecutionErrorAccumulator eea, final ChainType chainType, final String chainName) { 130 return getChainByName(eea, chainType, chainName, EntityPermission.READ_ONLY); 131 } 132 133 public Chain getChainByNameForUpdate(final ExecutionErrorAccumulator eea, final ChainType chainType, final String chainName) { 134 return getChainByName(eea, chainType, chainName, EntityPermission.READ_WRITE); 135 } 136 137 public Chain getChainByName(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName, 138 final String chainName, final EntityPermission entityPermission) { 139 var chainType = chainTypeLogic.getChainTypeByName(eea, chainKindName, chainTypeName); 140 Chain chain = null; 141 142 if(eea == null || !eea.hasExecutionErrors()) { 143 chain = getChainByName(eea, chainType, chainName, entityPermission); 144 } 145 146 return chain; 147 } 148 149 public Chain getChainByName(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName, final String chainName) { 150 return getChainByName(eea, chainKindName, chainTypeName, chainName, EntityPermission.READ_ONLY); 151 } 152 153 public Chain getChainByNameForUpdate(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName, final String chainName) { 154 return getChainByName(eea, chainKindName, chainTypeName, chainName, EntityPermission.READ_WRITE); 155 } 156 157 public Chain getChainByUniversalSpec(final ExecutionErrorAccumulator eea, final ChainUniversalSpec universalSpec, 158 final boolean allowDefault, final EntityPermission entityPermission) { 159 var chainKindName = universalSpec.getChainKindName(); 160 var chainTypeName = universalSpec.getChainTypeName(); 161 var chainName = universalSpec.getChainName(); 162 var nameParameterCount = ParameterUtils.getInstance().countNonNullParameters(chainKindName, chainTypeName, chainName); 163 var possibleEntitySpecs = entityInstanceLogic.countPossibleEntitySpecs(universalSpec); 164 Chain chain = null; 165 166 if(nameParameterCount < 4 && possibleEntitySpecs == 0) { 167 ChainKind chainKind = null; 168 ChainType chainType = null; 169 170 if(chainKindName == null) { 171 if(allowDefault) { 172 chainKind = chainControl.getDefaultChainKind(); 173 174 if(chainKind == null) { 175 handleExecutionError(UnknownDefaultChainKindException.class, eea, ExecutionErrors.UnknownDefaultChainKind.name()); 176 } 177 } else { 178 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 179 } 180 } else { 181 chainKind = chainKindLogic.getChainKindByName(eea, chainKindName); 182 } 183 184 if(eea == null || !eea.hasExecutionErrors()) { 185 if(chainTypeName == null) { 186 if(allowDefault) { 187 chainType = chainControl.getDefaultChainType(chainKind); 188 189 if(chainType == null) { 190 handleExecutionError(UnknownDefaultChainTypeException.class, eea, ExecutionErrors.UnknownDefaultChainType.name(), 191 chainKind.getLastDetail().getChainKindName()); 192 } 193 } else { 194 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 195 } 196 } else { 197 chainType = chainTypeLogic.getChainTypeByName(eea, chainKind, chainTypeName); 198 } 199 } 200 201 if(eea == null || !eea.hasExecutionErrors()) { 202 if(chainName == null) { 203 if(allowDefault) { 204 chain = chainControl.getDefaultChain(chainType, entityPermission); 205 206 if(chain == null) { 207 handleExecutionError(UnknownDefaultChainException.class, eea, ExecutionErrors.UnknownDefaultChain.name(), 208 chainKind.getLastDetail().getChainKindName(), 209 chainType.getLastDetail().getChainTypeName()); 210 } 211 } else { 212 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 213 } 214 } else { 215 chain = getChainByName(eea, chainType, chainName, entityPermission); 216 } 217 } 218 } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) { 219 var entityInstance = entityInstanceLogic.getEntityInstance(eea, universalSpec, 220 ComponentVendors.ECHO_THREE.name(), EntityTypes.Chain.name()); 221 222 if(eea == null || !eea.hasExecutionErrors()) { 223 chain = chainControl.getChainByEntityInstance(entityInstance, entityPermission); 224 } 225 } else { 226 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 227 } 228 229 return chain; 230 } 231 232 public Chain getChainByUniversalSpec(final ExecutionErrorAccumulator eea, final ChainUniversalSpec universalSpec, 233 boolean allowDefault) { 234 return getChainByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY); 235 } 236 237 public Chain getChainByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final ChainUniversalSpec universalSpec, 238 boolean allowDefault) { 239 return getChainByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE); 240 } 241 242 public void deleteChain(final ExecutionErrorAccumulator eea, final Chain chain, final BasePK deletedBy) { 243 if(chainControl.countChainActionSetsByChain(chain) == 0) { 244 chainControl.deleteChain(chain, deletedBy); 245 } else { 246 var chainDetail = chain.getLastDetail(); 247 248 handleExecutionError(CannotDeleteChainInUseException.class, eea, ExecutionErrors.CannotDeleteChainInUse.name(), 249 chainDetail.getChainType().getLastDetail().getChainKind().getLastDetail().getChainKindName(), 250 chainDetail.getChainType().getLastDetail().getChainTypeName(), 251 chainDetail.getChainName()); 252 } 253 } 254 255 public Chain getChain(final ExecutionErrorAccumulator eea, final ChainType chainType, final Party party) { 256 var customer = customerControl.getCustomer(party); 257 var initialOfferUse = customer == null ? null : customer.getInitialOfferUse(); 258 var offerChainType = initialOfferUse == null ? null : offerControl.getOfferChainType(initialOfferUse.getLastDetail().getOffer(), chainType); 259 260 return offerChainType == null ? chainControl.getDefaultChain(chainType) : offerChainType.getChain(); 261 } 262 263}