001// --------------------------------------------------------------------------------
002// Copyright 2002-2025 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.party.server.command;
018
019import com.echothree.control.user.party.common.edit.PartyEditFactory;
020import com.echothree.control.user.party.common.edit.ProfileEdit;
021import com.echothree.control.user.party.common.form.EditProfileForm;
022import com.echothree.control.user.party.common.result.EditProfileResult;
023import com.echothree.control.user.party.common.result.PartyResultFactory;
024import com.echothree.control.user.party.common.spec.PartySpec;
025import com.echothree.model.control.core.common.MimeTypeUsageTypes;
026import com.echothree.model.control.core.server.logic.MimeTypeLogic;
027import com.echothree.model.control.icon.common.IconConstants;
028import com.echothree.model.control.icon.server.control.IconControl;
029import com.echothree.model.control.party.common.PartyTypes;
030import com.echothree.model.control.party.server.control.PartyControl;
031import com.echothree.model.data.core.server.entity.MimeType;
032import com.echothree.model.data.icon.server.entity.Icon;
033import com.echothree.model.data.party.server.entity.BirthdayFormat;
034import com.echothree.model.data.party.server.entity.Gender;
035import com.echothree.model.data.party.server.entity.Party;
036import com.echothree.model.data.party.server.entity.Profile;
037import com.echothree.model.data.user.common.pk.UserVisitPK;
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.persistence.Session;
044import com.echothree.util.server.string.DateUtils;
045import java.util.Arrays;
046import java.util.Collections;
047import java.util.List;
048import javax.enterprise.context.RequestScoped;
049
050@RequestScoped
051public class EditProfileCommand
052        extends BaseAbstractEditCommand<PartySpec, ProfileEdit, EditProfileResult, Profile, Party> {
053    
054    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
055    private final static List<FieldDefinition> customerEditFieldDefinitions;
056    private final static List<FieldDefinition> otherEditFieldDefinitions;
057    
058    static {
059        SPEC_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
060                new FieldDefinition("PartyName", FieldType.ENTITY_NAME, false, null, null)
061                ));
062        
063        customerEditFieldDefinitions = Collections.unmodifiableList(Arrays.asList(
064                new FieldDefinition("Nickname", FieldType.STRING, true, 1L, 40L),
065                new FieldDefinition("IconName", FieldType.ENTITY_NAME, false, null, null),
066                new FieldDefinition("Pronunciation", FieldType.STRING, false, 1L, 200L),
067                new FieldDefinition("GenderName", FieldType.ENTITY_NAME, false, null, null),
068                new FieldDefinition("Pronouns", FieldType.STRING, false, 1L, 50L),
069                new FieldDefinition("Birthday", FieldType.DATE, false, null, null),
070                new FieldDefinition("BirthdayFormatName", FieldType.ENTITY_NAME, true, null, null),
071                new FieldDefinition("Occupation", FieldType.STRING, false, 1L, 200L),
072                new FieldDefinition("Hobbies", FieldType.STRING, false, 1L, 200L),
073                new FieldDefinition("Location", FieldType.STRING, false, 1L, 60L),
074                new FieldDefinition("BioMimeTypeName", FieldType.MIME_TYPE, false, null, null),
075                new FieldDefinition("Bio", FieldType.STRING, false, 1L, 512L),
076                new FieldDefinition("SignatureMimeTypeName", FieldType.MIME_TYPE, false, null, null),
077                new FieldDefinition("Signature", FieldType.STRING, false, 1L, 512L)
078                ));
079        
080        otherEditFieldDefinitions = Collections.unmodifiableList(Arrays.asList(
081                new FieldDefinition("Nickname", FieldType.STRING, false, 1L, 40L),
082                new FieldDefinition("IconName", FieldType.ENTITY_NAME, false, null, null),
083                new FieldDefinition("Pronunciation", FieldType.STRING, false, 1L, 200L),
084                new FieldDefinition("GenderName", FieldType.ENTITY_NAME, false, null, null),
085                new FieldDefinition("Pronouns", FieldType.STRING, false, 1L, 50L),
086                new FieldDefinition("Birthday", FieldType.DATE, false, null, null),
087                new FieldDefinition("BirthdayFormatName", FieldType.ENTITY_NAME, true, null, null),
088                new FieldDefinition("Occupation", FieldType.STRING, false, 1L, 200L),
089                new FieldDefinition("Hobbies", FieldType.STRING, false, 1L, 200L),
090                new FieldDefinition("Location", FieldType.STRING, false, 1L, 60L),
091                new FieldDefinition("BioMimeTypeName", FieldType.MIME_TYPE, false, null, null),
092                new FieldDefinition("Bio", FieldType.STRING, false, 1L, 512L),
093                new FieldDefinition("SignatureMimeTypeName", FieldType.MIME_TYPE, false, null, null),
094                new FieldDefinition("Signature", FieldType.STRING, false, 1L, 512L)
095                ));
096    }
097    
098    /** Creates a new instance of EditProfileCommand */
099    public EditProfileCommand() {
100        super(null, SPEC_FIELD_DEFINITIONS, null);
101    }
102    
103    @Override
104    protected List<FieldDefinition> getEditFieldDefinitions() {
105        var partyTypeName = getPartyTypeName();
106        
107        return partyTypeName == null || partyTypeName.equals(PartyTypes.CUSTOMER.name()) ? customerEditFieldDefinitions : otherEditFieldDefinitions;
108    }
109    
110    @Override
111    public EditProfileResult getResult() {
112        return PartyResultFactory.getEditProfileResult();
113    }
114
115    @Override
116    public ProfileEdit getEdit() {
117        return PartyEditFactory.getProfileEdit();
118    }
119
120    @Override
121    public Profile getEntity(EditProfileResult result) {
122        var partyControl = Session.getModelController(PartyControl.class);
123        Profile profile = null;
124        var partyTypeName = getPartyTypeName();
125        var partyName = partyTypeName.equals(PartyTypes.CUSTOMER.name()) ? null : spec.getPartyName();
126        var party = partyName == null ? null : partyControl.getPartyByName(partyName);
127
128        if(partyName == null || party != null) {
129            if(party == null) {
130                party = getParty();
131            }
132
133            if(party == null) {
134                addExecutionError(ExecutionErrors.PartyRequired.name());
135            } else {
136                if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
137                    profile = partyControl.getProfile(party);
138                } else { // EditMode.UPDATE
139                    profile = partyControl.getProfileForUpdate(party);
140                }
141
142                if(profile == null) {
143                    addExecutionError(ExecutionErrors.UnknownProfile.name(), partyName);
144                }
145            }
146        } else {
147            addExecutionError(ExecutionErrors.UnknownPartyName.name(), partyName);
148        }
149
150        return profile;
151    }
152
153    @Override
154    public Party getLockEntity(Profile profile) {
155        return profile.getParty();
156    }
157
158    @Override
159    public void fillInResult(EditProfileResult result, Profile profile) {
160        var partyControl = Session.getModelController(PartyControl.class);
161
162        result.setParty(partyControl.getPartyTransfer(getUserVisit(), profile.getParty()));
163    }
164
165    Icon icon;
166    Gender gender;
167    MimeType bioMimeType;
168    MimeType signatureMimeType;
169
170    @Override
171    public void doLock(ProfileEdit edit, Profile profile) {
172        icon = profile.getIcon();
173        gender = profile.getGender();
174
175        bioMimeType = profile.getBioMimeType();
176        signatureMimeType = profile.getSignatureMimeType();
177
178        edit.setNickname(profile.getNickname());
179        edit.setIconName(icon == null? null: icon.getLastDetail().getIconName());
180        edit.setPronunciation(profile.getPronunciation());
181        edit.setGenderName(gender == null? null: gender.getLastDetail().getGenderName());
182        edit.setPronouns(profile.getPronouns());
183        edit.setBirthday(DateUtils.getInstance().formatDate(getUserVisit(), profile.getBirthday()));
184        edit.setBirthdayFormatName(profile.getBirthdayFormat().getLastDetail().getBirthdayFormatName());
185        edit.setOccupation(profile.getOccupation());
186        edit.setHobbies(profile.getHobbies());
187        edit.setLocation(profile.getLocation());
188        edit.setBioMimeTypeName(bioMimeType == null ? null : bioMimeType.getLastDetail().getMimeTypeName());
189        edit.setBio(profile.getBio());
190        edit.setSignatureMimeTypeName(signatureMimeType == null ? null : signatureMimeType.getLastDetail().getMimeTypeName());
191        edit.setSignature(profile.getSignature());
192    }
193
194    BirthdayFormat birthdayFormat;
195
196    @Override
197    protected void canUpdate(Profile profile) {
198        var partyControl = Session.getModelController(PartyControl.class);
199        var mimeTypeLogic = MimeTypeLogic.getInstance();
200        var bioMimeTypeName = edit.getBioMimeTypeName();
201        var bio = edit.getBio();
202        var signatureMimeTypeName = edit.getSignatureMimeTypeName();
203        var signature = edit.getSignature();
204
205        bioMimeType = mimeTypeLogic.checkMimeType(this, bioMimeTypeName, bio, MimeTypeUsageTypes.TEXT.name(),
206                ExecutionErrors.MissingRequiredBioMimeTypeName.name(), ExecutionErrors.MissingRequiredBio.name(),
207                ExecutionErrors.UnknownBioMimeTypeName.name(), ExecutionErrors.UnknownBioMimeTypeUsage.name());
208
209        signatureMimeType = mimeTypeLogic.checkMimeType(this, signatureMimeTypeName, signature, MimeTypeUsageTypes.TEXT.name(),
210                ExecutionErrors.MissingRequiredSignatureMimeTypeName.name(), ExecutionErrors.MissingRequiredSignature.name(),
211                ExecutionErrors.UnknownSignatureMimeTypeName.name(), ExecutionErrors.UnknownSignatureMimeTypeUsage.name());
212
213        var nickname = edit.getNickname();
214        var duplicateProfile = nickname == null ? null : partyControl.getProfileByNickname(nickname);
215
216        if(duplicateProfile == null || duplicateProfile.getPrimaryKey().equals(profile.getPrimaryKey())) {
217            var iconControl = Session.getModelController(IconControl.class);
218            var iconName = edit.getIconName();
219
220            icon = iconName == null? null: iconControl.getIconByName(iconName);
221
222            if(iconName == null || icon != null) {
223                if(icon != null) {
224                    var iconUsageType = iconControl.getIconUsageTypeByName(IconConstants.IconUsageType_PROFILE);
225                    var iconUsage = iconControl.getIconUsage(iconUsageType, icon);
226
227                    if(iconUsage == null) {
228                        addExecutionError(ExecutionErrors.UnknownIconUsage.name());
229                    }
230                }
231
232                if(!hasExecutionErrors()) {
233                    var genderName = edit.getGenderName();
234
235                    gender = genderName == null? null: partyControl.getGenderByName(genderName);
236
237                    if(genderName == null || gender != null) {
238                        var birthdayFormatName = edit.getBirthdayFormatName();
239
240                        birthdayFormat = birthdayFormatName == null ? null : partyControl.getBirthdayFormatByName(birthdayFormatName);
241
242                        if(birthdayFormat == null) {
243                            addExecutionError(ExecutionErrors.UnknownBirthdayFormatName.name(), birthdayFormatName);
244                        }
245                    } else {
246                        addExecutionError(ExecutionErrors.UnknownGenderName.name(), genderName);
247                    }
248                }
249            } else {
250                addExecutionError(ExecutionErrors.UnknownIconName.name(), iconName);
251            }
252        } else {
253            addExecutionError(ExecutionErrors.DuplicateNickname.name(), nickname);
254        }
255    }
256
257    @Override
258    public void doUpdate(Profile profile) {
259        var partyControl = Session.getModelController(PartyControl.class);
260        var profileValue = partyControl.getProfileValue(profile);
261        var nickname = edit.getNickname();
262        var pronunciation = edit.getPronunciation();
263        var pronouns = edit.getPronouns();
264        var birthday = edit.getBirthday();
265
266        profileValue.setNickname(nickname);
267        profileValue.setIconPK(icon == null ? null : icon.getPrimaryKey());
268        profileValue.setPronunciation(pronunciation);
269        profileValue.setGenderPK(gender == null ? null : gender.getPrimaryKey());
270        profileValue.setPronouns(pronouns);
271        profileValue.setBirthday(birthday == null ? null : Integer.valueOf(birthday));
272        profileValue.setBirthdayFormatPK(birthdayFormat.getPrimaryKey());
273        profileValue.setOccupation(edit.getOccupation());
274        profileValue.setHobbies(edit.getHobbies());
275        profileValue.setLocation(edit.getLocation());
276        profileValue.setBioMimeTypePK(bioMimeType == null ? null : bioMimeType.getPrimaryKey());
277        profileValue.setBio(edit.getBio());
278        profileValue.setSignatureMimeTypePK(signatureMimeType == null ? null : signatureMimeType.getPrimaryKey());
279        profileValue.setSignature(edit.getSignature());
280
281        partyControl.updateProfileFromValue(profileValue, getPartyPK());
282    }
283    
284}