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 java.util.List;
045import javax.enterprise.context.Dependent;
046import javax.inject.Inject;
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    @Inject
092    ContactControl contactControl;
093
094    @Inject
095    GeoControl geoControl;
096
097    @Inject
098    GeoCodeLogic geoCodeLogic;
099
100    @Inject
101    GeoCodeScopeLogic geoCodeScopeLogic;
102
103    @Inject
104    GeoCodeTypeLogic geoCodeTypeLogic;
105
106    @Inject
107    SequenceGeneratorLogic sequenceGeneratorLogic;
108
109    
110    /** Creates a new instance of CreateCountryCommand */
111    public CreateCountryCommand() {
112        super(COMMAND_SECURITY_DEFINITION, FORM_FIELD_DEFINITIONS, false);
113    }
114
115    @Override
116    protected BaseResult execute() {
117        var result = GeoResultFactory.getCreateCountryResult();
118        GeoCode geoCode = null;
119        var geoCodeType = geoCodeTypeLogic.getGeoCodeTypeByName(this, GeoCodeTypes.COUNTRY.name());
120
121        if(!hasExecutionErrors()) {
122            var geoCodeScope = geoCodeScopeLogic.getGeoCodeScopeByName(this, GeoCodeScopes.COUNTRIES.name());
123
124            if(!hasExecutionErrors()) {
125                var iso3Number = form.getIso3Number();
126
127                geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_NUMBER.name(), iso3Number);
128
129                if(geoCode == null && !hasExecutionErrors()) {
130                    var iso3Letter = form.getIso3Letter();
131
132                    geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_LETTER.name(), iso3Letter);
133
134                    if(geoCode == null && !hasExecutionErrors()) {
135                        var iso2Letter = form.getIso2Letter();
136
137                        geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_2_LETTER.name(), iso2Letter);
138
139                        if(geoCode == null && !hasExecutionErrors()) {
140                            var countryName = form.getCountryName();
141
142                            geoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.COUNTRY_NAME.name(), countryName);
143
144                            if(geoCode == null && !hasExecutionErrors()) {
145                                var postalAddressFormatName = form.getPostalAddressFormatName();
146                                var postalAddressFormat = contactControl.getPostalAddressFormatByName(postalAddressFormatName);
147
148                                if(postalAddressFormat != null) {
149                                    BasePK createdBy = getPartyPK();
150                                    var geoCodeName = sequenceGeneratorLogic.getNextSequenceValue(null, SequenceTypes.GEO_CODE.name());
151                                    var telephoneCode = form.getTelephoneCode();
152                                    var areaCodePattern = form.getAreaCodePattern();
153                                    var areaCodeRequired = Boolean.valueOf(form.getAreaCodeRequired());
154                                    var areaCodeExample = form.getAreaCodeExample();
155                                    var telephoneNumberPattern = form.getTelephoneNumberPattern();
156                                    var telephoneNumberExample = form.getTelephoneNumberExample();
157                                    var cityRequired = Boolean.valueOf(form.getCityRequired());
158                                    var cityGeoCodeRequired = Boolean.valueOf(form.getCityGeoCodeRequired());
159                                    var stateRequired = Boolean.valueOf(form.getStateRequired());
160                                    var stateGeoCodeRequired = Boolean.valueOf(form.getStateGeoCodeRequired());
161                                    var postalCodePattern = form.getPostalCodePattern();
162                                    var postalCodeRequired = Boolean.valueOf(form.getPostalCodeRequired());
163                                    var postalCodeGeoCodeRequired = Boolean.valueOf(form.getPostalCodeGeoCodeRequired());
164                                    var strPostalCodeLength = form.getPostalCodeLength();
165                                    var postalCodeLength = strPostalCodeLength == null ? null : Integer.valueOf(strPostalCodeLength);
166                                    var strPostalCodeGeoCodeLength = form.getPostalCodeGeoCodeLength();
167                                    var postalCodeGeoCodeLength = strPostalCodeGeoCodeLength == null ? null : Integer.valueOf(strPostalCodeGeoCodeLength);
168                                    var postalCodeExample = form.getPostalCodeExample();
169                                    var isDefault = Boolean.valueOf(form.getIsDefault());
170                                    var sortOrder = Integer.valueOf(form.getSortOrder());
171                                    var description = form.getDescription();
172
173                                    geoCode = geoControl.createGeoCode(geoCodeName, geoCodeType, geoCodeScope, isDefault, sortOrder, createdBy);
174                                    geoControl.createGeoCodeCountry(geoCode, telephoneCode, areaCodePattern, areaCodeRequired, areaCodeExample,
175                                            telephoneNumberPattern, telephoneNumberExample, postalAddressFormat, cityRequired, cityGeoCodeRequired,
176                                            stateRequired, stateGeoCodeRequired, postalCodePattern, postalCodeRequired, postalCodeGeoCodeRequired,
177                                            postalCodeLength, postalCodeGeoCodeLength, postalCodeExample, createdBy);
178
179                                    var geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.ISO_3_NUMBER.name());
180                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, iso3Number, createdBy);
181                                    geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.ISO_3_LETTER.name());
182                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, iso3Letter, createdBy);
183                                    geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.ISO_2_LETTER.name());
184                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, iso2Letter, createdBy);
185                                    geoCodeAliasType = geoControl.getGeoCodeAliasTypeByName(geoCodeType, GeoCodeAliasTypes.COUNTRY_NAME.name());
186                                    geoControl.createGeoCodeAlias(geoCode, geoCodeAliasType, countryName, createdBy);
187
188                                    if(description != null) {
189                                        var language = getPreferredLanguage();
190
191                                        geoControl.createGeoCodeDescription(geoCode, language, description, createdBy);
192                                    }
193                                } else {
194                                    addExecutionError(ExecutionErrors.UnknownPostalAddressFormatName.name(), postalAddressFormatName);
195                                }
196                            } else {
197                                if(geoCode != null) {
198                                    addExecutionError(ExecutionErrors.DuplicateCountryName.name(), countryName);
199                                }
200                            }
201                        } else {
202                            if(geoCode != null) {
203                                addExecutionError(ExecutionErrors.DuplicateIso2Letter.name(), iso2Letter);
204                            }
205                        }
206                    } else {
207                        if(geoCode != null) {
208                            addExecutionError(ExecutionErrors.DuplicateIso3Letter.name(), iso3Letter);
209                        }
210                    }
211                } else {
212                    if(geoCode != null) {
213                        addExecutionError(ExecutionErrors.DuplicateIso3Number.name(), iso3Number);
214                    }
215                }
216            }
217        }
218
219        if(geoCode != null) {
220            result.setEntityRef(geoCode.getPrimaryKey().getEntityRef());
221            result.setGeoCodeName(geoCode.getLastDetail().getGeoCodeName());
222        }
223        
224        return result;
225    }
226    
227}