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 com.echothree.util.server.persistence.Session; 047import java.util.List; 048import javax.enterprise.context.Dependent; 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 /** Creates a new instance of EditCountryCommand */ 099 public EditCountryCommand() { 100 super(COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS); 101 } 102 103 @Override 104 public EditCountryResult getResult() { 105 return GeoResultFactory.getEditCountryResult(); 106 } 107 108 @Override 109 public CountryEdit getEdit() { 110 return GeoEditFactory.getCountryEdit(); 111 } 112 113 @Override 114 public GeoCode getEntity(EditCountryResult result) { 115 var geoControl = Session.getModelController(GeoControl.class); 116 GeoCode geoCode; 117 var geoCodeName = spec.getGeoCodeName(); 118 119 if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) { 120 geoCode = geoControl.getGeoCodeByName(geoCodeName); 121 } else { // EditMode.UPDATE 122 geoCode = geoControl.getGeoCodeByNameForUpdate(geoCodeName); 123 } 124 125 if(geoCode != null) { 126 var geoCodeTypeName = geoCode.getLastDetail().getGeoCodeType().getLastDetail().getGeoCodeTypeName(); 127 128 if(!geoCodeTypeName.equals(GeoCodeTypes.COUNTRY.name())) { 129 addExecutionError(ExecutionErrors.InvalidGeoCodeType.name(), geoCodeTypeName); 130 } 131 } else { 132 addExecutionError(ExecutionErrors.UnknownGeoCodeName.name(), geoCodeName); 133 } 134 135 return geoCode; 136 } 137 138 @Override 139 public GeoCode getLockEntity(GeoCode geoCode) { 140 return geoCode; 141 } 142 143 @Override 144 public void fillInResult(EditCountryResult result, GeoCode geoCode) { 145 var geoControl = Session.getModelController(GeoControl.class); 146 147 result.setCountry(geoControl.getCountryTransfer(getUserVisit(), geoCode)); 148 } 149 150 @Override 151 public void doLock(CountryEdit edit, GeoCode geoCode) { 152 var geoControl = Session.getModelController(GeoControl.class); 153 var geoCodeAliasLogic = GeoCodeAliasLogic.getInstance(); 154 var geoCodeDescription = geoControl.getGeoCodeDescription(geoCode, getPreferredLanguage()); 155 var geoCodeDetail = geoCode.getLastDetail(); 156 var geoCodeCountry = geoControl.getGeoCodeCountry(geoCode); 157 var postalCodeLength = geoCodeCountry.getPostalCodeGeoCodeLength(); 158 var postalCodeGeoCodeLength = geoCodeCountry.getPostalCodeGeoCodeLength(); 159 160 var geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.COUNTRY_NAME.name()); 161 edit.setCountryName(geoCodeAlias.getAlias()); 162 163 geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_NUMBER.name()); 164 edit.setIso3Number(geoCodeAlias.getAlias()); 165 166 geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_LETTER.name()); 167 edit.setIso3Letter(geoCodeAlias.getAlias()); 168 169 geoCodeAlias = geoCodeAliasLogic.getGeoCodeAliasUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_2_LETTER.name()); 170 edit.setIso2Letter(geoCodeAlias.getAlias()); 171 172 edit.setTelephoneCode(geoCodeCountry.getTelephoneCode()); 173 edit.setAreaCodePattern(geoCodeCountry.getAreaCodePattern()); 174 edit.setAreaCodeRequired(geoCodeCountry.getAreaCodeRequired().toString()); 175 edit.setAreaCodeExample(geoCodeCountry.getAreaCodeExample()); 176 edit.setTelephoneNumberPattern(geoCodeCountry.getTelephoneNumberPattern()); 177 edit.setTelephoneNumberExample(geoCodeCountry.getTelephoneNumberExample()); 178 edit.setPostalAddressFormatName(geoCodeCountry.getPostalAddressFormat().getLastDetail().getPostalAddressFormatName()); 179 edit.setCityRequired(geoCodeCountry.getCityRequired().toString()); 180 edit.setCityGeoCodeRequired(geoCodeCountry.getCityGeoCodeRequired().toString()); 181 edit.setStateRequired(geoCodeCountry.getStateRequired().toString()); 182 edit.setStateGeoCodeRequired(geoCodeCountry.getStateGeoCodeRequired().toString()); 183 edit.setPostalCodePattern(geoCodeCountry.getPostalCodePattern()); 184 edit.setPostalCodeRequired(geoCodeCountry.getPostalCodeRequired().toString()); 185 edit.setPostalCodeGeoCodeRequired(geoCodeCountry.getPostalCodeGeoCodeRequired().toString()); 186 edit.setPostalCodeLength(postalCodeLength == null ? null : postalCodeLength.toString()); 187 edit.setPostalCodeGeoCodeLength(postalCodeGeoCodeLength == null ? null : postalCodeGeoCodeLength.toString()); 188 edit.setPostalCodeExample(geoCodeCountry.getPostalCodeExample()); 189 edit.setIsDefault(geoCodeDetail.getIsDefault().toString()); 190 edit.setSortOrder(geoCodeDetail.getSortOrder().toString()); 191 192 if(geoCodeDescription != null) { 193 edit.setDescription(geoCodeDescription.getDescription()); 194 } 195 } 196 197 PostalAddressFormat postalAddressFormat; 198 199 @Override 200 public void canUpdate(GeoCode geoCode) { 201 var geoCodeTypeLogic = GeoCodeTypeLogic.getInstance(); 202 var geoCodeType = geoCodeTypeLogic.getGeoCodeTypeByName(this, GeoCodeTypes.COUNTRY.name()); 203 204 if(!hasExecutionErrors()) { 205 var geoCodeScopeLogic = GeoCodeScopeLogic.getInstance(); 206 var geoCodeScope = geoCodeScopeLogic.getGeoCodeScopeByName(this, GeoCodeScopes.COUNTRIES.name()); 207 208 if(!hasExecutionErrors()) { 209 var geoCodeLogic = GeoCodeLogic.getInstance(); 210 var iso3Number = edit.getIso3Number(); 211 var duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_NUMBER.name(), iso3Number); 212 213 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 214 var iso3Letter = edit.getIso3Letter(); 215 216 duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_3_LETTER.name(), iso3Letter); 217 218 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 219 var iso2Letter = edit.getIso2Letter(); 220 221 duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.ISO_2_LETTER.name(), iso2Letter); 222 223 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 224 var countryName = edit.getCountryName(); 225 226 duplicateGeoCode = geoCodeLogic.getGeoCodeByAlias(this, geoCodeType, geoCodeScope, GeoCodeAliasTypes.COUNTRY_NAME.name(), countryName); 227 228 if((duplicateGeoCode == null || duplicateGeoCode.equals(geoCode)) && !hasExecutionErrors()) { 229 var contactControl = Session.getModelController(ContactControl.class); 230 var postalAddressFormatName = edit.getPostalAddressFormatName(); 231 232 postalAddressFormat = contactControl.getPostalAddressFormatByName(postalAddressFormatName); 233 234 if(postalAddressFormat == null) { 235 addExecutionError(ExecutionErrors.UnknownPostalAddressFormatName.name(), postalAddressFormatName); 236 } 237 } else { 238 if(geoCode != null) { 239 addExecutionError(ExecutionErrors.DuplicateCountryName.name(), countryName); 240 } 241 } 242 } else { 243 if(geoCode != null) { 244 addExecutionError(ExecutionErrors.DuplicateIso2Letter.name(), iso2Letter); 245 } 246 } 247 } else { 248 if(geoCode != null) { 249 addExecutionError(ExecutionErrors.DuplicateIso3Letter.name(), iso3Letter); 250 } 251 } 252 } else { 253 if(geoCode != null) { 254 addExecutionError(ExecutionErrors.DuplicateIso3Number.name(), iso3Number); 255 } 256 } 257 } 258 } 259 } 260 261 @Override 262 public void doUpdate(GeoCode geoCode) { 263 var geoControl = Session.getModelController(GeoControl.class); 264 var geoCodeAliasLogic = GeoCodeAliasLogic.getInstance(); 265 var partyPK = getPartyPK(); 266 var geoCodeDetailValue = geoControl.getGeoCodeDetailValueForUpdate(geoCode); 267 var geoCodeDescription = geoControl.getGeoCodeDescriptionForUpdate(geoCode, getPreferredLanguage()); 268 var geoCodeCountryValue = geoControl.getGeoCodeCountryValueForUpdate(geoCode); 269 var strPostalCodeLength = edit.getPostalCodeLength(); 270 var postalCodeLength = strPostalCodeLength == null ? null : Integer.valueOf(strPostalCodeLength); 271 var strPostalCodeGeoCodeLength = edit.getPostalCodeGeoCodeLength(); 272 var postalCodeGeoCodeLength = strPostalCodeGeoCodeLength == null ? null : Integer.valueOf(strPostalCodeGeoCodeLength); 273 var description = edit.getDescription(); 274 275 var geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.COUNTRY_NAME.name()); 276 geoCodeAliasValue.setAlias(edit.getCountryName()); 277 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 278 279 geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_NUMBER.name()); 280 geoCodeAliasValue.setAlias(edit.getIso3Number()); 281 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 282 283 geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_3_LETTER.name()); 284 geoCodeAliasValue.setAlias(edit.getIso3Letter()); 285 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 286 287 geoCodeAliasValue = geoCodeAliasLogic.getGeoCodeAliasValueUsingNames(null, geoCode, GeoCodeAliasTypes.ISO_2_LETTER.name()); 288 geoCodeAliasValue.setAlias(edit.getIso2Letter()); 289 geoControl.updateGeoCodeAliasFromValue(geoCodeAliasValue, partyPK); 290 291 geoCodeCountryValue.setTelephoneCode(edit.getTelephoneCode()); 292 geoCodeCountryValue.setAreaCodePattern(edit.getAreaCodePattern()); 293 geoCodeCountryValue.setAreaCodeRequired(Boolean.valueOf(edit.getAreaCodeRequired())); 294 geoCodeCountryValue.setAreaCodeExample(edit.getAreaCodeExample()); 295 geoCodeCountryValue.setTelephoneNumberPattern(edit.getTelephoneNumberPattern()); 296 geoCodeCountryValue.setTelephoneNumberExample(edit.getTelephoneNumberExample()); 297 geoCodeCountryValue.setPostalAddressFormatPK(postalAddressFormat.getPrimaryKey()); 298 geoCodeCountryValue.setCityRequired(Boolean.valueOf(edit.getCityRequired())); 299 geoCodeCountryValue.setCityGeoCodeRequired(Boolean.valueOf(edit.getCityGeoCodeRequired())); 300 geoCodeCountryValue.setStateRequired(Boolean.valueOf(edit.getStateRequired())); 301 geoCodeCountryValue.setStateGeoCodeRequired(Boolean.valueOf(edit.getStateGeoCodeRequired())); 302 geoCodeCountryValue.setPostalCodePattern(edit.getPostalCodePattern()); 303 geoCodeCountryValue.setPostalCodeRequired(Boolean.valueOf(edit.getPostalCodeRequired())); 304 geoCodeCountryValue.setPostalCodeGeoCodeRequired(Boolean.valueOf(edit.getPostalCodeGeoCodeRequired())); 305 geoCodeCountryValue.setPostalCodeLength(postalCodeLength); 306 geoCodeCountryValue.setPostalCodeGeoCodeLength(postalCodeGeoCodeLength); 307 geoCodeCountryValue.setPostalCodeExample(edit.getPostalCodeExample()); 308 309 geoCodeDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault())); 310 geoCodeDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder())); 311 312 geoControl.updateGeoCodeFromValue(geoCodeDetailValue, partyPK); 313 geoControl.updateGeoCodeCountryFromValue(geoCodeCountryValue, partyPK); 314 315 if(geoCodeDescription == null && description != null) { 316 geoControl.createGeoCodeDescription(geoCode, getPreferredLanguage(), description, partyPK); 317 } else { 318 if(geoCodeDescription != null && description == null) { 319 geoControl.deleteGeoCodeDescription(geoCodeDescription, partyPK); 320 } else { 321 if(geoCodeDescription != null && description != null) { 322 var geoCodeDescriptionValue = geoControl.getGeoCodeDescriptionValue(geoCodeDescription); 323 324 geoCodeDescriptionValue.setDescription(description); 325 geoControl.updateGeoCodeDescriptionFromValue(geoCodeDescriptionValue, partyPK); 326 } 327 } 328 } 329 } 330 331}