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.control.user.geo.server.command;
018
019import com.echothree.control.user.geo.common.form.CreateCountryForm;
020import com.echothree.control.user.geo.common.result.GeoResultFactory;
021import com.echothree.model.control.contact.server.control.ContactControl;
022import com.echothree.model.control.geo.common.GeoCodeAliasTypes;
023import com.echothree.model.control.geo.common.GeoCodeScopes;
024import com.echothree.model.control.geo.common.GeoCodeTypes;
025import com.echothree.model.control.geo.server.control.GeoControl;
026import com.echothree.model.control.geo.server.logic.GeoCodeLogic;
027import com.echothree.model.control.geo.server.logic.GeoCodeScopeLogic;
028import com.echothree.model.control.geo.server.logic.GeoCodeTypeLogic;
029import com.echothree.model.control.party.common.PartyTypes;
030import com.echothree.model.control.security.common.SecurityRoleGroups;
031import com.echothree.model.control.security.common.SecurityRoles;
032import com.echothree.model.control.sequence.common.SequenceTypes;
033import com.echothree.model.control.sequence.server.logic.SequenceGeneratorLogic;
034import com.echothree.model.data.geo.server.entity.GeoCode;
035import com.echothree.util.common.command.BaseResult;
036import com.echothree.util.common.message.ExecutionErrors;
037import com.echothree.util.common.persistence.BasePK;
038import com.echothree.util.common.validation.FieldDefinition;
039import com.echothree.util.common.validation.FieldType;
040import com.echothree.util.server.control.BaseSimpleCommand;
041import com.echothree.util.server.control.CommandSecurityDefinition;
042import com.echothree.util.server.control.PartyTypeDefinition;
043import com.echothree.util.server.control.SecurityRoleDefinition;
044import com.echothree.util.server.persistence.Session;
045import java.util.List;
046import javax.enterprise.context.Dependent;
047
048@Dependent
049public class CreateCountryCommand
050        extends BaseSimpleCommand<CreateCountryForm> {
051    
052    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
053    private final static List<FieldDefinition> FORM_FIELD_DEFINITIONS;
054    
055    static {
056        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of(
057                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
058                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of(
059                        new SecurityRoleDefinition(SecurityRoleGroups.Country.name(), SecurityRoles.Create.name())
060                        ))
061                ));
062        
063        FORM_FIELD_DEFINITIONS = List.of(
064                new FieldDefinition("CountryName", FieldType.ENTITY_NAME, true, null, null),
065                new FieldDefinition("Iso3Number", FieldType.NUMBER_3, true, null, null),
066                new FieldDefinition("Iso3Letter", FieldType.UPPER_LETTER_3, true, null, null),
067                new FieldDefinition("Iso2Letter", FieldType.UPPER_LETTER_2, true, null, null),
068                new FieldDefinition("TelephoneCode", FieldType.STRING, false, 1L, 5L),
069                new FieldDefinition("AreaCodePattern", FieldType.REGULAR_EXPRESSION, false, null, null),
070                new FieldDefinition("AreaCodeRequired", FieldType.BOOLEAN, true, null, null),
071                new FieldDefinition("AreaCodeExample", FieldType.STRING, false, 1L, 5L),
072                new FieldDefinition("TelephoneNumberPattern", FieldType.REGULAR_EXPRESSION, false, null, null),
073                new FieldDefinition("TelephoneNumberExample", FieldType.STRING, false, 1L, 25L),
074                new FieldDefinition("PostalAddressFormatName", FieldType.ENTITY_NAME, true, null, null),
075                new FieldDefinition("CityRequired", FieldType.BOOLEAN, true, null, null),
076                new FieldDefinition("CityGeoCodeRequired", FieldType.BOOLEAN, true, null, null),
077                new FieldDefinition("StateRequired", FieldType.BOOLEAN, true, null, null),
078                new FieldDefinition("StateGeoCodeRequired", FieldType.BOOLEAN, true, null, null),
079                new FieldDefinition("PostalCodePattern", FieldType.REGULAR_EXPRESSION, false, null, null),
080                new FieldDefinition("PostalCodeRequired", FieldType.BOOLEAN, true, null, null),
081                new FieldDefinition("PostalCodeGeoCodeRequired", FieldType.BOOLEAN, true, null, null),
082                new FieldDefinition("PostalCodeLength", FieldType.UNSIGNED_INTEGER, false, null, null),
083                new FieldDefinition("PostalCodeGeoCodeLength", FieldType.UNSIGNED_INTEGER, false, null, null),
084                new FieldDefinition("PostalCodeExample", FieldType.STRING, false, 1L, 15L),
085                new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null),
086                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
087                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
088                );
089    }
090    
091    /** Creates a new instance of CreateCountryCommand */
092    public CreateCountryCommand() {
093        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
094    }
095
096    @Override
097    protected BaseResult execute() {
098        var geoCodeTypeLogic = GeoCodeTypeLogic.getInstance();
099        var result = GeoResultFactory.getCreateCountryResult();
100        var geoControl = Session.getModelController(GeoControl.class);
101        GeoCode geoCode = null;
102        var geoCodeType = geoCodeTypeLogic.getGeoCodeTypeByName(this, GeoCodeTypes.COUNTRY.name());
103
104        if(!hasExecutionErrors()) {
105            var geoCodeScopeLogic = GeoCodeScopeLogic.getInstance();
106            var geoCodeScope = geoCodeScopeLogic.getGeoCodeScopeByName(this, GeoCodeScopes.COUNTRIES.name());
107
108            if(!hasExecutionErrors()) {
109                var geoCodeLogic = GeoCodeLogic.getInstance();
110                var iso3Number = form.getIso3Number();
111
112                geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_NUMBER.name(), iso3Number);
113
114                if(geoCode == null && !hasExecutionErrors()) {
115                    var iso3Letter = form.getIso3Letter();
116
117                    geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_LETTER.name(), iso3Letter);
118
119                    if(geoCode == null && !hasExecutionErrors()) {
120                        var iso2Letter = form.getIso2Letter();
121
122                        geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_2_LETTER.name(), iso2Letter);
123
124                        if(geoCode == null && !hasExecutionErrors()) {
125                            var countryName = form.getCountryName();
126
127                            geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.COUNTRY_NAME.name(), countryName);
128
129                            if(geoCode == null && !hasExecutionErrors()) {
130                                var contactControl = Session.getModelController(ContactControl.class);
131                                var postalAddressFormatName = form.getPostalAddressFormatName();
132                                var postalAddressFormat = contactControl.getPostalAddressFormatByName(postalAddressFormatName);
133
134                                if(postalAddressFormat != null) {
135                                    BasePK createdBy = getPartyPK();
136                                    var geoCodeName = SequenceGeneratorLogic.getInstance().getNextSequenceValue(null, SequenceTypes.GEO_CODE.name());
137                                    var telephoneCode = form.getTelephoneCode();
138                                    var areaCodePattern = form.getAreaCodePattern();
139                                    var areaCodeRequired = Boolean.valueOf(form.getAreaCodeRequired());
140                                    var areaCodeExample = form.getAreaCodeExample();
141                                    var telephoneNumberPattern = form.getTelephoneNumberPattern();
142                                    var telephoneNumberExample = form.getTelephoneNumberExample();
143                                    var cityRequired = Boolean.valueOf(form.getCityRequired());
144                                    var cityGeoCodeRequired = Boolean.valueOf(form.getCityGeoCodeRequired());
145                                    var stateRequired = Boolean.valueOf(form.getStateRequired());
146                                    var stateGeoCodeRequired = Boolean.valueOf(form.getStateGeoCodeRequired());
147                                    var postalCodePattern = form.getPostalCodePattern();
148                                    var postalCodeRequired = Boolean.valueOf(form.getPostalCodeRequired());
149                                    var postalCodeGeoCodeRequired = Boolean.valueOf(form.getPostalCodeGeoCodeRequired());
150                                    var strPostalCodeLength = form.getPostalCodeLength();
151                                    var postalCodeLength = strPostalCodeLength == null ? null : Integer.valueOf(strPostalCodeLength);
152                                    var strPostalCodeGeoCodeLength = form.getPostalCodeGeoCodeLength();
153                                    var postalCodeGeoCodeLength = strPostalCodeGeoCodeLength == null ? null : Integer.valueOf(strPostalCodeGeoCodeLength);
154                                    var postalCodeExample = form.getPostalCodeExample();
155                                    var isDefault = Boolean.valueOf(form.getIsDefault());
156                                    var sortOrder = Integer.valueOf(form.getSortOrder());
157                                    var description = form.getDescription();
158
159                                    geoCode = geoControl.createGeoCode(geoCodeName, geoCodeType, geoCodeScope, isDefault, sortOrder, createdBy);
160                                    geoControl.createGeoCodeCountry(geoCode, telephoneCode, areaCodePattern, areaCodeRequired, areaCodeExample,
161                                            telephoneNumberPattern, telephoneNumberExample, postalAddressFormat, cityRequired, cityGeoCodeRequired,
162                                            stateRequired, stateGeoCodeRequired, postalCodePattern, postalCodeRequired, postalCodeGeoCodeRequired,
163                                            postalCodeLength, postalCodeGeoCodeLength, postalCodeExample, createdBy);
164
165                                    var geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.ISO_3_NUMBER.name());
166                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, iso3Number, createdBy);
167                                    geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.ISO_3_LETTER.name());
168                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, iso3Letter, createdBy);
169                                    geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.ISO_2_LETTER.name());
170                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, iso2Letter, createdBy);
171                                    geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.COUNTRY_NAME.name());
172                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, countryName, createdBy);
173
174                                    if(description != null) {
175                                        var language = getPreferredLanguage();
176
177                                        geoControl.createGeoCodeDescription(geoCode, language, description, createdBy);
178                                    }
179                                } else {
180                                    addExecutionError(ExecutionErrors.UnknownPostalAddressFormatName.name(), postalAddressFormatName);
181                                }
182                            } else {
183                                if(geoCode != null) {
184                                    addExecutionError(ExecutionErrors.DuplicateCountryName.name(), countryName);
185                                }
186                            }
187                        } else {
188                            if(geoCode != null) {
189                                addExecutionError(ExecutionErrors.DuplicateIso2Letter.name(), iso2Letter);
190                            }
191                        }
192                    } else {
193                        if(geoCode != null) {
194                            addExecutionError(ExecutionErrors.DuplicateIso3Letter.name(), iso3Letter);
195                        }
196                    }
197                } else {
198                    if(geoCode != null) {
199                        addExecutionError(ExecutionErrors.DuplicateIso3Number.name(), iso3Number);
200                    }
201                }
202            }
203        }
204
205        if(geoCode != null) {
206            result.setEntityRef(geoCode.getPrimaryKey().getEntityRef());
207            result.setGeoCodeName(geoCode.getLastDetail().getGeoCodeName());
208        }
209        
210        return result;
211    }
212    
213}