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.model.control.subscription.server.logic; 018 019import com.echothree.model.control.chain.common.ChainConstants; 020import com.echothree.model.control.chain.server.control.ChainControl; 021import com.echothree.model.control.chain.server.logic.BaseChainLogic; 022import com.echothree.model.control.subscription.server.control.SubscriptionControl; 023import com.echothree.model.data.chain.server.entity.Chain; 024import com.echothree.model.data.chain.server.entity.ChainInstance; 025import com.echothree.model.data.subscription.server.entity.Subscription; 026import com.echothree.util.common.persistence.BasePK; 027import com.echothree.util.server.message.ExecutionErrorAccumulator; 028import com.echothree.util.server.persistence.Session; 029import javax.enterprise.context.ApplicationScoped; 030import javax.enterprise.inject.spi.CDI; 031 032@ApplicationScoped 033public class SubscriptionChainLogic 034 extends BaseChainLogic { 035 036 protected SubscriptionChainLogic() { 037 super(); 038 } 039 040 public static SubscriptionChainLogic getInstance() { 041 return CDI.current().select(SubscriptionChainLogic.class).get(); 042 } 043 044 /** createChainInstance is different than the version in BaseChainLogic, it requires a Subscription parameter. Subscriptions 045 * are allowed to override the Chain being used in each SubscriptionType, so this takes that into account when choosing a 046 * Chain. If there is no SubscriptionTypeChain, then we fall back to the default for the ChainType, following the normal 047 * rules that take OfferChainTypes into account as well. If the chainTypeName == RENEWAL, then we immediately fall back to the 048 * default for the ChainType. 049 * 050 * TODO: RENEWAL should really be based on the amount of time remaining in the Subscription, and not just fall back to the 051 * default. getSubscriptionTypeChainsBySubscriptionTypeAndChainType(...) could order by the remaining time, and then search 052 * for the one that's the best fit. 053 */ 054 protected ChainInstance createChainInstance(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName, 055 final Subscription subscription, final BasePK createdBy) { 056 var subscriptionControl = Session.getModelController(SubscriptionControl.class); 057 var subscriptionType = subscription.getLastDetail().getSubscriptionType(); 058 var chainType = getChainTypeByName(eea, chainKindName, chainTypeName); 059 var party = subscription.getLastDetail().getParty(); 060 var subscriptionTypeChains = chainTypeName.equals(ChainConstants.ChainType_RENEWAL) ? null 061 : subscriptionControl.getSubscriptionTypeChainsBySubscriptionTypeAndChainType(subscriptionType, chainType); 062 Chain chain; 063 ChainInstance chainInstance = null; 064 065 if(subscriptionTypeChains == null || subscriptionTypeChains.isEmpty()) { 066 chain = getChain(eea, chainType, party); 067 } else { 068 chain = subscriptionTypeChains.iterator().next().getChain(); 069 } 070 071 if(chain != null) { 072 chainInstance = createChainInstance(eea, chainType, party, createdBy); 073 } 074 075 return chainInstance; 076 } 077 078 protected ChainInstance createSubscriptionChainInstance(final ExecutionErrorAccumulator eea, final String chainTypeName, final Subscription subscription, 079 final BasePK createdBy) { 080 var chainInstance = createChainInstance(eea, ChainConstants.ChainKind_SUBSCRIPTION, chainTypeName, subscription, createdBy); 081 082 if(chainInstance != null) { 083 var chainControl = Session.getModelController(ChainControl.class); 084 var chainType = chainInstance.getLastDetail().getChain().getLastDetail().getChainType(); 085 086 chainControl.createChainInstanceEntityRole(chainInstance, chainControl.getChainEntityRoleTypeByName(chainType, 087 ChainConstants.ChainEntityRoleType_SUBSCRIPTION), subscription.getPrimaryKey(), createdBy); 088 } 089 090 return chainInstance; 091 } 092 093 public ChainInstance createSubscriptionInitialChainInstance(final ExecutionErrorAccumulator eea, final Subscription subscription, 094 final BasePK createdBy) { 095 return createSubscriptionChainInstance(eea, ChainConstants.ChainType_INITIAL, subscription, createdBy); 096 } 097 098 public ChainInstance createSubscriptionExpirationWarningChainInstance(final ExecutionErrorAccumulator eea, final Subscription subscription, 099 final BasePK createdBy) { 100 return createSubscriptionChainInstance(eea, ChainConstants.ChainType_EXPIRATION_WARNING, subscription, createdBy); 101 } 102 103 /** TODO: Consider the RemainingTime in the SubscriptionDetail when choosing the Chain to use. 104 */ 105 public ChainInstance createSubscriptionRenewalChainInstance(final ExecutionErrorAccumulator eea, final Subscription subscription, 106 final BasePK createdBy) { 107 return createSubscriptionChainInstance(eea, ChainConstants.ChainType_RENEWAL, subscription, createdBy); 108 } 109 110 public ChainInstance createSubscriptionExpirationChainInstance(final ExecutionErrorAccumulator eea, final Subscription subscription, 111 final BasePK createdBy) { 112 return createSubscriptionChainInstance(eea, ChainConstants.ChainType_EXPIRATION, subscription, createdBy); 113 } 114 115}