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.chain.server.logic;
018
019import com.echothree.model.control.chain.common.exception.UnknownChainEntityRoleTypeNameException;
020import com.echothree.model.control.chain.common.exception.UnknownChainKindNameException;
021import com.echothree.model.control.chain.common.exception.UnknownChainTypeNameException;
022import com.echothree.model.control.chain.server.control.ChainControl;
023import com.echothree.model.control.customer.server.control.CustomerControl;
024import com.echothree.model.control.offer.server.control.OfferControl;
025import com.echothree.model.control.sequence.common.SequenceTypes;
026import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic;
027import com.echothree.model.data.chain.server.entity.Chain;
028import com.echothree.model.data.chain.server.entity.ChainEntityRoleType;
029import com.echothree.model.data.chain.server.entity.ChainInstance;
030import com.echothree.model.data.chain.server.entity.ChainKind;
031import com.echothree.model.data.chain.server.entity.ChainType;
032import com.echothree.model.data.core.server.entity.EntityInstance;
033import com.echothree.model.data.party.server.entity.Party;
034import com.echothree.util.common.message.ExecutionErrors;
035import com.echothree.util.common.persistence.BasePK;
036import com.echothree.util.server.control.BaseLogic;
037import com.echothree.util.server.message.ExecutionErrorAccumulator;
038import com.echothree.util.server.persistence.Session;
039import java.util.HashSet;
040import java.util.Set;
041
042public class BaseChainLogic
043        extends BaseLogic {
044    
045    protected BaseChainLogic() {
046        super();
047    }
048    
049    public ChainKind getChainKindByName(final ExecutionErrorAccumulator eea, final String chainKindName) {
050        var chainControl = Session.getModelController(ChainControl.class);
051        var chainKind = chainControl.getChainKindByName(chainKindName);
052
053        if(chainKind == null) {
054            handleExecutionError(UnknownChainKindNameException.class, eea, ExecutionErrors.UnknownChainKindName.name(), chainKindName);
055        }
056
057        return chainKind;
058    }
059
060    public ChainType getChainTypeByName(final ExecutionErrorAccumulator eea, final ChainKind chainKind, final String chainTypeName) {
061        var chainControl = Session.getModelController(ChainControl.class);
062        var chainType = chainControl.getChainTypeByName(chainKind, chainTypeName);
063
064        if(chainType == null) {
065            handleExecutionError(UnknownChainTypeNameException.class, eea, ExecutionErrors.UnknownChainTypeName.name(), chainKind.getLastDetail().getChainKindName(),
066                    chainTypeName);
067        }
068        
069        return chainType;
070    }
071    
072   public ChainType getChainTypeByName(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName) {
073       var chainKind = getChainKindByName(eea, chainKindName);
074        ChainType chainType = null;
075        
076        if(chainKind != null) {
077            chainType = getChainTypeByName(eea, chainKind, chainTypeName);
078        }
079        
080        return chainType;
081    }
082    
083    public ChainEntityRoleType getChainEntityRoleTypeByName(final ExecutionErrorAccumulator eea, final ChainType chainType, final String chainEntityRoleTypeName) {
084        var chainControl = Session.getModelController(ChainControl.class);
085        var chainEntityRoleType = chainControl.getChainEntityRoleTypeByName(chainType, chainEntityRoleTypeName);
086
087        if(chainEntityRoleType == null) {
088            handleExecutionError(UnknownChainEntityRoleTypeNameException.class, eea, ExecutionErrors.UnknownChainEntityRoleTypeName.name(),
089                    chainType.getLastDetail().getChainTypeName(), chainEntityRoleTypeName);
090        }
091        
092        return chainEntityRoleType;
093    }
094    
095    protected long countChainInstanceEntityRolesByChainEntityRoleType(final ChainEntityRoleType chainEntityRoleType) {
096        var chainControl = Session.getModelController(ChainControl.class);
097        
098        return chainControl.countChainInstanceEntityRolesByChainEntityRoleType(chainEntityRoleType);
099    }
100
101    protected long countChainInstanceEntityRolesByEntityInstance(final EntityInstance entityInstance) {
102        var chainControl = Session.getModelController(ChainControl.class);
103        
104        return chainControl.countChainInstanceEntityRolesByEntityInstance(entityInstance);
105    }
106
107    protected long countChainInstanceEntityRoles(final ChainEntityRoleType chainEntityRoleType, final EntityInstance entityInstance) {
108        var chainControl = Session.getModelController(ChainControl.class);
109        
110        return chainControl.countChainInstanceEntityRoles(chainEntityRoleType, entityInstance);
111    }
112
113    protected Long countChainInstanceEntityRoles(final ExecutionErrorAccumulator eea, final ChainType chainType, final String chainEntityRoleTypeName,
114            final EntityInstance entityInstance) {
115        var chainEntityRoleType = getChainEntityRoleTypeByName(eea, chainType, chainEntityRoleTypeName);
116        
117        return chainEntityRoleType == null ? null : countChainInstanceEntityRoles(chainEntityRoleType, entityInstance);
118    }
119    
120    protected Chain getChain(final ExecutionErrorAccumulator eea, final ChainType chainType, final Party party) {
121        var chainControl = Session.getModelController(ChainControl.class);
122        var offerControl = Session.getModelController(OfferControl.class);
123        var customerControl = Session.getModelController(CustomerControl.class);
124        var customer = customerControl.getCustomer(party);
125        var initialOfferUse = customer == null ? null : customer.getInitialOfferUse();
126        var offerChainType = initialOfferUse == null ? null : offerControl.getOfferChainType(initialOfferUse.getLastDetail().getOffer(), chainType);
127
128        return offerChainType == null ? chainControl.getDefaultChain(chainType) : offerChainType.getChain();
129    }
130
131    protected ChainInstance createChainInstance(final ExecutionErrorAccumulator eea, final Chain chain, final BasePK createdBy) {
132        var chainControl = Session.getModelController(ChainControl.class);
133        var defaultChainActionSet = chainControl.getDefaultChainActionSet(chain);
134        ChainInstance chainInstance = null;
135        
136        // The lack of a defaultChainActionSet is not a reportable error - it just silently avoids creating a Chain Instance.
137        if(defaultChainActionSet != null) {
138            var sequence = chain.getLastDetail().getChainInstanceSequence();
139
140            if(sequence == null) {
141                sequence = SequenceGeneratorLogic.getInstance().getDefaultSequence(eea, SequenceTypes.CHAIN_INSTANCE.name());
142            }
143
144            if(!hasExecutionErrors(eea)) {
145                chainInstance = chainControl.createChainInstance(SequenceGeneratorLogic.getInstance().getNextSequenceValue(sequence), defaultChainActionSet, createdBy);
146            }
147        }
148        
149        return chainInstance;
150    }
151    
152    protected ChainInstance createChainInstance(final ExecutionErrorAccumulator eea, final ChainType chainType, final Party party, final BasePK createdBy) {
153        var chain = getChain(eea, chainType, party);
154        ChainInstance chainInstance = null;
155
156        if(chain != null) {
157            chainInstance = createChainInstance(eea, chain, createdBy);
158        }
159
160        return chainInstance;
161    }
162    
163    protected ChainInstance createChainInstance(final ExecutionErrorAccumulator eea, final String chainKindName, final String chainTypeName, final Party party,
164            final BasePK createdBy) {
165        var chainType = getChainTypeByName(eea, chainKindName, chainTypeName);
166        ChainInstance chainInstance = null;
167
168        if(!hasExecutionErrors(eea)) {
169            chainInstance = createChainInstance(eea, chainType, party, createdBy);
170        }
171
172        return chainInstance;
173    }
174    
175    protected void deleteChainInstancedByChainEntityRoleTypeAndEntityInstance(final ChainEntityRoleType chainEntityRoleType, final EntityInstance entityInstance,
176            final BasePK deletedBy) {
177        var chainControl = Session.getModelController(ChainControl.class);
178        var chainInstanceEntityRoles = chainControl.getChainInstanceEntityRoles(chainEntityRoleType, entityInstance);
179        Set<ChainInstance> chainInstances = new HashSet<>();
180        
181        chainInstanceEntityRoles.forEach((chainInstanceEntityRole) -> {
182            chainInstances.add(chainInstanceEntityRole.getChainInstanceForUpdate());
183        });
184        
185        chainControl.deleteChainInstances(chainInstances, deletedBy);
186    }
187    
188}