001// --------------------------------------------------------------------------------
002// Copyright 2002-2024 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.sequence.server.logic;
018
019import com.echothree.control.user.sequence.common.spec.SequenceUniversalSpec;
020import com.echothree.model.control.core.common.ComponentVendors;
021import com.echothree.model.control.core.common.EntityTypes;
022import com.echothree.model.control.core.common.exception.InvalidParameterCountException;
023import com.echothree.model.control.core.server.logic.EntityInstanceLogic;
024import com.echothree.model.control.sequence.common.SequenceTypes;
025import com.echothree.model.control.sequence.common.exception.DuplicateSequenceNameException;
026import com.echothree.model.control.sequence.common.exception.InvalidValueLengthException;
027import com.echothree.model.control.sequence.common.exception.UnknownDefaultSequenceException;
028import com.echothree.model.control.sequence.common.exception.UnknownDefaultSequenceTypeException;
029import com.echothree.model.control.sequence.common.exception.UnknownSequenceNameException;
030import com.echothree.model.control.sequence.server.control.SequenceControl;
031import com.echothree.model.data.core.server.entity.EntityInstance;
032import com.echothree.model.data.party.server.entity.Language;
033import com.echothree.model.data.sequence.server.entity.Sequence;
034import com.echothree.model.data.sequence.server.entity.SequenceType;
035import com.echothree.util.common.message.ExecutionErrors;
036import com.echothree.util.common.persistence.BasePK;
037import com.echothree.util.server.control.BaseLogic;
038import com.echothree.util.server.message.ExecutionErrorAccumulator;
039import com.echothree.util.server.persistence.EntityPermission;
040import com.echothree.util.server.persistence.Session;
041import com.echothree.util.server.validation.ParameterUtils;
042
043public class SequenceLogic
044        extends BaseLogic {
045    
046    private SequenceLogic() {
047        super();
048    }
049    
050    private static class SequenceLogicHolder {
051        static SequenceLogic instance = new SequenceLogic();
052    }
053    
054    public static SequenceLogic getInstance() {
055        return SequenceLogicHolder.instance;
056    }
057    
058    public Sequence createSequence(final ExecutionErrorAccumulator eea, final String sequenceTypeName, final String sequenceName,
059            final String value, final String mask, final Integer chunkSize, final Boolean isDefault, final Integer sortOrder,
060            final String description, final Language language, final BasePK createdBy) {
061        SequenceType sequenceType = SequenceTypeLogic.getInstance().getSequenceTypeByName(eea, sequenceTypeName);
062        Sequence sequence = null;
063        
064        if(eea == null || !eea.hasExecutionErrors()) {
065            sequence = createSequence(eea, sequenceType, sequenceName, value, mask, chunkSize, isDefault, sortOrder, description,
066                    language, createdBy);
067        }
068        
069        return sequence;
070    }    
071    
072    public Sequence createSequence(final ExecutionErrorAccumulator eea, final SequenceType sequenceType, String sequenceName,
073            String value, final String mask, final Integer chunkSize, final Boolean isDefault, final Integer sortOrder,
074            final String description, final Language language, final BasePK createdBy) {
075        Sequence sequence = null;
076        
077        if(sequenceName == null) {
078            sequenceName = SequenceGeneratorLogic.getInstance().getNextSequenceValue(eea, SequenceTypes.SEQUENCE.name());
079        }
080        
081        if(eea == null || !eea.hasExecutionErrors()) {
082            var sequenceControl = Session.getModelController(SequenceControl.class);
083
084            sequence = sequenceControl.getSequenceByName(sequenceType, sequenceName);
085    
086            if(sequence == null) {
087                if(value == null || value.length() == mask.length()) {
088                    sequence = sequenceControl.createSequence(sequenceType, sequenceName, mask, chunkSize, isDefault, sortOrder, createdBy);
089
090                    if(value == null) {
091                        char[] maskChars = mask.toCharArray();
092                        int maskLength = mask.length();
093                        StringBuilder valueBuilder = new StringBuilder(maskLength);
094
095                        for(int index = 0; index < maskLength; index++) {
096                            char maskChar = maskChars[index];
097
098                            switch(maskChar) {
099                                case '9':
100                                case 'Z':
101                                    valueBuilder.append('0');
102                                    break;
103                                case 'A':
104                                    valueBuilder.append('A');
105                                    break;
106                            }
107                        }
108
109                        value = valueBuilder.toString();
110                    }
111
112                    sequenceControl.createSequenceValue(sequence, value);
113
114                    if(description != null) {
115                        sequenceControl.createSequenceDescription(sequence, language, description, createdBy);
116                    }
117                } else {
118                    handleExecutionError(InvalidValueLengthException.class, eea, ExecutionErrors.InvalidValueLength.name());
119                }
120            } else {
121                handleExecutionError(DuplicateSequenceNameException.class, eea, ExecutionErrors.DuplicateSequenceName.name(),
122                        sequenceType.getLastDetail().getSequenceTypeName(), sequenceName);
123            }
124        }
125        
126        return sequence;
127    }
128
129    public Sequence getSequenceByName(final ExecutionErrorAccumulator eea, final SequenceType sequenceType, final String sequenceName,
130            final EntityPermission entityPermission) {
131        var sequenceControl = Session.getModelController(SequenceControl.class);
132        var sequence = sequenceControl.getSequenceByName(sequenceType, sequenceName, entityPermission);
133
134        if(sequence == null) {
135            handleExecutionError(UnknownSequenceNameException.class, eea, ExecutionErrors.UnknownSequenceName.name(),
136                    sequenceType.getLastDetail().getSequenceTypeName(), sequenceName);
137        }
138
139        return sequence;
140    }
141
142    public Sequence getSequenceByName(final ExecutionErrorAccumulator eea, final SequenceType sequenceType, final String sequenceName) {
143        return getSequenceByName(eea, sequenceType, sequenceName, EntityPermission.READ_ONLY);
144    }
145
146    public Sequence getSequenceByNameForUpdate(final ExecutionErrorAccumulator eea, final SequenceType sequenceType, final String sequenceName) {
147        return getSequenceByName(eea, sequenceType, sequenceName, EntityPermission.READ_WRITE);
148    }
149
150    public Sequence getSequenceByName(final ExecutionErrorAccumulator eea, final String sequenceTypeName, final String sequenceName,
151            final EntityPermission entityPermission) {
152        var sequenceType = SequenceTypeLogic.getInstance().getSequenceTypeByName(eea, sequenceTypeName);
153        Sequence sequence = null;
154
155        if(!eea.hasExecutionErrors()) {
156            sequence = getSequenceByName(eea, sequenceType, sequenceName, entityPermission);
157        }
158
159        return sequence;
160    }
161
162    public Sequence getSequenceByName(final ExecutionErrorAccumulator eea, final String sequenceTypeName, final String sequenceName) {
163        return getSequenceByName(eea, sequenceTypeName, sequenceName, EntityPermission.READ_ONLY);
164    }
165
166    public Sequence getSequenceByNameForUpdate(final ExecutionErrorAccumulator eea, final String sequenceTypeName, final String sequenceName) {
167        return getSequenceByName(eea, sequenceTypeName, sequenceName, EntityPermission.READ_WRITE);
168    }
169
170    public Sequence getSequenceByUniversalSpec(final ExecutionErrorAccumulator eea, final SequenceUniversalSpec universalSpec,
171            final boolean allowDefault, final EntityPermission entityPermission) {
172        var sequenceControl = Session.getModelController(SequenceControl.class);
173        var sequenceTypeName = universalSpec.getSequenceTypeName();
174        var sequenceName = universalSpec.getSequenceName();
175        var nameParameterCount= ParameterUtils.getInstance().countNonNullParameters(sequenceTypeName, sequenceName);
176        var possibleEntitySpecs= EntityInstanceLogic.getInstance().countPossibleEntitySpecs(universalSpec);
177        Sequence sequence = null;
178
179        if(nameParameterCount < 3 && possibleEntitySpecs == 0) {
180            SequenceType sequenceType = null;
181            
182            if(sequenceTypeName == null) {
183                if(allowDefault) {
184                    sequenceType = sequenceControl.getDefaultSequenceType();
185
186                    if(sequenceType == null) {
187                        handleExecutionError(UnknownDefaultSequenceTypeException.class, eea, ExecutionErrors.UnknownDefaultSequenceType.name());
188                    }
189                } else {
190                    handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
191                }
192            } else {
193                sequenceType = SequenceTypeLogic.getInstance().getSequenceTypeByName(eea, sequenceTypeName);
194            }
195
196            if(!eea.hasExecutionErrors()) {
197                if(sequenceName == null) {
198                    if(allowDefault) {
199                        sequence = sequenceControl.getDefaultSequence(sequenceType, entityPermission);
200
201                        if(sequence == null) {
202                            handleExecutionError(UnknownDefaultSequenceException.class, eea, ExecutionErrors.UnknownDefaultSequence.name());
203                        }
204                    } else {
205                        handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
206                    }
207                } else {
208                    sequence = getSequenceByName(eea, sequenceType, sequenceName, entityPermission);
209                }
210            }
211        } else if(nameParameterCount == 0 && possibleEntitySpecs == 1) {
212            var entityInstance = EntityInstanceLogic.getInstance().getEntityInstance(eea, universalSpec,
213                    ComponentVendors.ECHO_THREE.name(), EntityTypes.Sequence.name());
214
215            if(!eea.hasExecutionErrors()) {
216                sequence = sequenceControl.getSequenceByEntityInstance(entityInstance, entityPermission);
217            }
218        } else {
219            handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name());
220        }
221
222        return sequence;
223    }
224
225    public Sequence getSequenceByUniversalSpec(final ExecutionErrorAccumulator eea, final SequenceUniversalSpec universalSpec,
226            boolean allowDefault) {
227        return getSequenceByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_ONLY);
228    }
229
230    public Sequence getSequenceByUniversalSpecForUpdate(final ExecutionErrorAccumulator eea, final SequenceUniversalSpec universalSpec,
231            boolean allowDefault) {
232        return getSequenceByUniversalSpec(eea, universalSpec, allowDefault, EntityPermission.READ_WRITE);
233    }
234
235}