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.edit.CountryEdit; 020import com.echothree.control.user.geo.common.edit.GeoEditFactory; 021import com.echothree.control.user.geo.common.result.EditCountryResult; 022import com.echothree.control.user.geo.common.result.GeoResultFactory; 023import com.echothree.control.user.geo.common.spec.GeoCodeSpec; 024import com.echothree.model.control.contact.server.control.ContactControl; 025import com.echothree.model.control.geo.common.GeoCodeAliasTypes; 026import com.echothree.model.control.geo.common.GeoCodeScopes; 027import com.echothree.model.control.geo.common.GeoCodeTypes; 028import com.echothree.model.control.geo.server.control.GeoControl; 029import com.echothree.model.control.geo.server.logic.GeoCodeAliasLogic; 030import com.echothree.model.control.geo.server.logic.GeoCodeLogic; 031import com.echothree.model.control.geo.server.logic.GeoCodeScopeLogic; 032import com.echothree.model.control.geo.server.logic.GeoCodeTypeLogic; 033import com.echothree.model.control.party.common.PartyTypes; 034import com.echothree.model.control.security.common.SecurityRoleGroups; 035import com.echothree.model.control.security.common.SecurityRoles; 036import com.echothree.model.data.contact.server.entity.PostalAddressFormat; 037import com.echothree.model.data.geo.server.entity.GeoCode; 038import com.echothree.util.common.command.EditMode; 039import com.echothree.util.common.message.ExecutionErrors; 040import com.echothree.util.common.validation.FieldDefinition; 041import com.echothree.util.common.validation.FieldType; 042import com.echothree.util.server.control.BaseAbstractEditCommand; 043import com.echothree.util.server.control.CommandSecurityDefinition; 044import com.echothree.util.server.control.PartyTypeDefinition; 045import com.echothree.util.server.control.SecurityRoleDefinition; 046import java.util.List; 047import javax.enterprise.context.Dependent; 048import javax.inject.Inject; 049 050@Dependent 051public class EditCountryCommand 052 extends BaseAbstractEditCommand<GeoCodeSpec, CountryEdit, EditCountryResult, GeoCode, GeoCode> { 053 054 private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION; 055 private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS; 056 private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS; 057 058 static { 059 COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(List.of( 060 new PartyTypeDefinition(PartyTypes.UTILITY.name(), null), 061 new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), List.of( 062 new SecurityRoleDefinition(SecurityRoleGroups.Country.name(), SecurityRoles.Edit.name()) 063 )) 064 )); 065 066 SPEC_FIELD_DEFINITIONS = List.of( 067 new FieldDefinition("GeoCodeName", FieldType.ENTITY_NAME, true, null, null) 068 ); 069 070 EDIT_FIELD_DEFINITIONS = List.of( 071 new FieldDefinition("CountryName", FieldType.ENTITY_NAME, true, null, null), 072 new FieldDefinition("Iso3Number", FieldType.NUMBER_3, true, null, null), 073 new FieldDefinition("Iso3Letter", FieldType.UPPER_LETTER_3, true, null, null), 074 new FieldDefinition("Iso2Letter", FieldType.UPPER_LETTER_2, true, null, null), 075 new FieldDefinition("TelephoneCode", FieldType.STRING, false, 1L, 5L), 076 new FieldDefinition("AreaCodePattern", FieldType.REGULAR_EXPRESSION, false, null, null), 077 new FieldDefinition("AreaCodeRequired", FieldType.BOOLEAN, true, null, null), 078 new FieldDefinition("AreaCodeExample", FieldType.STRING, false, 1L, 5L), 079 new FieldDefinition("TelephoneNumberPattern", FieldType.REGULAR_EXPRESSION, false, null, null), 080 new FieldDefinition("TelephoneNumberExample", FieldType.STRING, false, 1L, 25L), 081 new FieldDefinition("PostalAddressFormatName", FieldType.ENTITY_NAME, true, null, null), 082 new FieldDefinition("CityRequired", FieldType.BOOLEAN, true, null, null), 083 new FieldDefinition("CityGeoCodeRequired", FieldType.BOOLEAN, true, null, null), 084 new FieldDefinition("StateRequired", FieldType.BOOLEAN, true, null, null), 085 new FieldDefinition("StateGeoCodeRequired", FieldType.BOOLEAN, true, null, null), 086 new FieldDefinition("PostalCodePattern", FieldType.REGULAR_EXPRESSION, false, null, null), 087 new FieldDefinition("PostalCodeRequired", FieldType.BOOLEAN, true, null, null), 088 new FieldDefinition("PostalCodeGeoCodeRequired", FieldType.BOOLEAN, true, null, null), 089 new FieldDefinition("PostalCodeLength", FieldType.UNSIGNED_INTEGER, false, null, null), 090 new FieldDefinition("PostalCodeGeoCodeLength", FieldType.UNSIGNED_INTEGER, false, null, null), 091 new FieldDefinition("PostalCodeExample", FieldType.STRING, false, 1L, 15L), 092 new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null), 093 new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null), 094 new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L) 095 ); 096 } 097 098 @Inject 099 ContactControl contactControl; 100 101 @Inject 102 GeoControl geoControl; 103 104 @Inject 105 GeoCodeAliasLogic geoCodeAliasLogic; 106 107 @Inject 108 GeoCodeLogic geoCodeLogic; 109 110 @Inject 111 GeoCodeScopeLogic geoCodeScopeLogic; 112 113 @Inject 114 GeoCodeTypeLogic geoCodeTypeLogic; 115 116 /** Creates a new instance of EditCountryCommand */ 117 public EditCountryCommand() { 118 super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS); 119 } 120 121 @Override 122 public EditCountryResult getResult() { 123 return GeoResultFactory.getEditCountryResult(); 124 } 125 126 @Override 127 public CountryEdit getEdit() { 128 return GeoEditFactory.getCountryEdit(); 129 } 130 131 @Override 132 public GeoCode getEntity(EditCountryResult result) { 133 GeoCode geoCode; 134 var geoCodeName = spec.getGeoCodeName(); 135 136 if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) { 137 geoCode = geoControl.getGeoCodeByName(geoCodeName); 138 } else { // EditMode.UPDATE 139 geoCode = geoControl.getGeoCodeByNameForUpdate(geoCodeName); 140 } 141 142 if(geoCode != null) { 143 var geoCodeTypeName = geoCode.getLastDetail().getGeoCodeType().getLastDetail().getGeoCodeTypeName(); 144 145 if(!geoCodeTypeName.equals(GeoCodeTypes.COUNTRY.name())) { 146 addExecutionError(ExecutionErrors.InvalidGeoCodeType.name(), geoCodeTypeName); 147 } 148 } else { 149 addExecutionError(ExecutionErrors.UnknownGeoCodeName.name(), geoCodeName); 150 } 151 152 return geoCode; 153 } 154 155 @Override 156 public GeoCode getLockEntity(GeoCode geoCode) { 157 return geoCode; 158 } 159 160 @Override 161 public void fillInResult(EditCountryResult result, GeoCode geoCode) { 162 result.setCountry(geoControl.getCountryTransfer(getUserVisit(), geoCode)); 163 } 164 165 @Override 166 public void doLock(CountryEdit edit, GeoCode geoCode) { 167 var geoCodeDescription = geoControl.getGeoCodeDescription(geoCode, getPreferredLanguage()); 168 var geoCodeDetail = geoCode.getLastDetail(); 169 var geoCodeCountry = geoControl.getGeoCodeCountry(geoCode); 170 var postalCodeLength = geoCodeCountry.getPostalCodeGeoCodeLength(); 171 var postalCodeGeoCodeLength = geoCodeCountry.getPostalCodeGeoCodeLength(); 172 173 var geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.COUNTRY_NAME.name()); 174 edit.setCountryName(geoCodeAlias.getAlias()); 175 176 geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_NUMBER.name()); 177 edit.setIso3Number(geoCodeAlias.getAlias()); 178 179 geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_LETTER.name()); 180 edit.setIso3Letter(geoCodeAlias.getAlias()); 181 182 geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_2_LETTER.name()); 183 edit.setIso2Letter(geoCodeAlias.getAlias()); 184 185 edit.setTelephoneCode(geoCodeCountry.getTelephoneCode()); 186 edit.setAreaCodePattern(geoCodeCountry.getAreaCodePattern()); 187 edit.setAreaCodeRequired(geoCodeCountry.getAreaCodeRequired().toString()); 188 edit.setAreaCodeExample(geoCodeCountry.getAreaCodeExample()); 189 edit.setTelephoneNumberPattern(geoCodeCountry.getTelephoneNumberPattern()); 190 edit.setTelephoneNumberExample(geoCodeCountry.getTelephoneNumberExample()); 191 edit.setPostalAddressFormatName(geoCodeCountry.getPostalAddressFormat().getLastDetail().getPostalAddressFormatName()); 192 edit.setCityRequired(geoCodeCountry.getCityRequired().toString()); 193 edit.setCityGeoCodeRequired(geoCodeCountry.getCityGeoCodeRequired().toString()); 194 edit.setStateRequired(geoCodeCountry.getStateRequired().toString()); 195 edit.setStateGeoCodeRequired(geoCodeCountry.getStateGeoCodeRequired().toString()); 196 edit.setPostalCodePattern(geoCodeCountry.getPostalCodePattern()); 197 edit.setPostalCodeRequired(geoCodeCountry.getPostalCodeRequired().toString()); 198 edit.setPostalCodeGeoCodeRequired(geoCodeCountry.getPostalCodeGeoCodeRequired().toString()); 199 edit.setPostalCodeLength(postalCodeLength == null ? null : postalCodeLength.toString()); 200 edit.setPostalCodeGeoCodeLength(postalCodeGeoCodeLength == null ? null : postalCodeGeoCodeLength.toString()); 201 edit.setPostalCodeExample(geoCodeCountry.getPostalCodeExample()); 202 edit.setIsDefault(geoCodeDetail.getIsDefault().toString()); 203 edit.setSortOrder(geoCodeDetail.getSortOrder().toString()); 204 205 if(geoCodeDescription != null) { 206 edit.setDescription(geoCodeDescription.getDescription()); 207 } 208 } 209 210 PostalAddressFormat postalAddressFormat; 211 212 @Override 213 public void canUpdate(GeoCode geoCode) { 214 var geoCodeType = geoCodeTypeLogic.getGeoCodeTypeByName(this, GeoCodeTypes.COUNTRY.name()); 215 216 if(!hasExecutionErrors()) { 217 var geoCodeScope = geoCodeScopeLogic.getGeoCodeScopeByName(this, GeoCodeScopes.COUNTRIES.name()); 218 219 if(!hasExecutionErrors()) { 220 var iso3Number = edit.getIso3Number(); 221 var duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_NUMBER.name(), iso3Number); 222 223 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 224 var iso3Letter = edit.getIso3Letter(); 225 226 duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_LETTER.name(), iso3Letter); 227 228 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 229 var iso2Letter = edit.getIso2Letter(); 230 231 duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_2_LETTER.name(), iso2Letter); 232 233 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 234 var countryName = edit.getCountryName(); 235 236 duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.COUNTRY_NAME.name(), countryName); 237 238 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 239 var postalAddressFormatName = edit.getPostalAddressFormatName(); 240 241 postalAddressFormat = contactControl.getPostalAddressFormatByName(postalAddressFormatName); 242 243 if(postalAddressFormat == null) { 244 addExecutionError(ExecutionErrors.UnknownPostalAddressFormatName.name(), postalAddressFormatName); 245 } 246 } else { 247 if(geoCode != null) { 248 addExecutionError(ExecutionErrors.DuplicateCountryName.name(), countryName); 249 } 250 } 251 } else { 252 if(geoCode != null) { 253 addExecutionError(ExecutionErrors.DuplicateIso2Letter.name(), iso2Letter); 254 } 255 } 256 } else { 257 if(geoCode != null) { 258 addExecutionError(ExecutionErrors.DuplicateIso3Letter.name(), iso3Letter); 259 } 260 } 261 } else { 262 if(geoCode != null) { 263 addExecutionError(ExecutionErrors.DuplicateIso3Number.name(), iso3Number); 264 } 265 } 266 } 267 } 268 } 269 270 @Override 271 public void doUpdate(GeoCode geoCode) { 272 var partyPK = getPartyPK(); 273 var geoCodeDetailValue = geoControl.getGeoCodeDetailValueForUpdate(geoCode); 274 var geoCodeDescription = geoControl.getGeoCodeDescriptionForUpdate(geoCode, getPreferredLanguage()); 275 var geoCodeCountryValue = geoControl.getGeoCodeCountryValueForUpdate(geoCode); 276 var strPostalCodeLength = edit.getPostalCodeLength(); 277 var postalCodeLength = strPostalCodeLength == null ? null : Integer.valueOf(strPostalCodeLength); 278 var strPostalCodeGeoCodeLength = edit.getPostalCodeGeoCodeLength(); 279 var postalCodeGeoCodeLength = strPostalCodeGeoCodeLength == null ? null : Integer.valueOf(strPostalCodeGeoCodeLength); 280 var description = edit.getDescription(); 281 282 var geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.COUNTRY_NAME.name()); 283 geoCodeAliasValue.setAlias(edit.getCountryName()); 284 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 285 286 geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_NUMBER.name()); 287 geoCodeAliasValue.setAlias(edit.getIso3Number()); 288 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 289 290 geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_LETTER.name()); 291 geoCodeAliasValue.setAlias(edit.getIso3Letter()); 292 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 293 294 geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_2_LETTER.name()); 295 geoCodeAliasValue.setAlias(edit.getIso2Letter()); 296 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 297 298 geoCodeCountryValue.setTelephoneCode(edit.getTelephoneCode()); 299 geoCodeCountryValue.setAreaCodePattern(edit.getAreaCodePattern()); 300 geoCodeCountryValue.setAreaCodeRequired(Boolean.valueOf(edit.getAreaCodeRequired())); 301 geoCodeCountryValue.setAreaCodeExample(edit.getAreaCodeExample()); 302 geoCodeCountryValue.setTelephoneNumberPattern(edit.getTelephoneNumberPattern()); 303 geoCodeCountryValue.setTelephoneNumberExample(edit.getTelephoneNumberExample()); 304 geoCodeCountryValue.setPostalAddressFormatPK(postalAddressFormat.getPrimaryKey()); 305 geoCodeCountryValue.setCityRequired(Boolean.valueOf(edit.getCityRequired())); 306 geoCodeCountryValue.setCityGeoCodeRequired(Boolean.valueOf(edit.getCityGeoCodeRequired())); 307 geoCodeCountryValue.setStateRequired(Boolean.valueOf(edit.getStateRequired())); 308 geoCodeCountryValue.setStateGeoCodeRequired(Boolean.valueOf(edit.getStateGeoCodeRequired())); 309 geoCodeCountryValue.setPostalCodePattern(edit.getPostalCodePattern()); 310 geoCodeCountryValue.setPostalCodeRequired(Boolean.valueOf(edit.getPostalCodeRequired())); 311 geoCodeCountryValue.setPostalCodeGeoCodeRequired(Boolean.valueOf(edit.getPostalCodeGeoCodeRequired())); 312 geoCodeCountryValue.setPostalCodeLength(postalCodeLength); 313 geoCodeCountryValue.setPostalCodeGeoCodeLength(postalCodeGeoCodeLength); 314 geoCodeCountryValue.setPostalCodeExample(edit.getPostalCodeExample()); 315 316 geoCodeDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault())); 317 geoCodeDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder())); 318 319 geoControl.updateGeoCodeFromValue(geoCodeDetailValue, partyPK); 320 geoControl.updateGeoCodeCountryFromValue(geoCodeCountryValue, partyPK); 321 322 if(geoCodeDescription == null && description != null) { 323 geoControl.createGeoCodeDescription(geoCode, getPreferredLanguage(), description, partyPK); 324 } else { 325 if(geoCodeDescription != null && description == null) { 326 geoControl.deleteGeoCodeDescription(geoCodeDescription, partyPK); 327 } else { 328 if(geoCodeDescription != null && description != null) { 329 var geoCodeDescriptionValue = geoControl.getGeoCodeDescriptionValue(geoCodeDescription); 330 331 geoCodeDescriptionValue.setDescription(description); 332 geoControl.updateGeoCodeDescriptionFromValue(geoCodeDescriptionValue, partyPK); 333 } 334 } 335 } 336 } 337 338}