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