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