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.model.control.user.server.logic; 018 019import com.echothree.model.control.order.server.control.OrderControl; 020import com.echothree.model.control.search.server.control.SearchControl; 021import com.echothree.model.control.user.server.control.UserControl; 022import com.echothree.model.control.workrequirement.server.logic.WorkRequirementLogic; 023import com.echothree.model.data.party.common.pk.PartyPK; 024import com.echothree.model.data.user.common.pk.UserVisitPK; 025import com.echothree.model.data.user.server.entity.UserKey; 026import com.echothree.model.data.user.server.entity.UserSession; 027import com.echothree.model.data.user.server.entity.UserVisit; 028import com.echothree.model.data.user.server.factory.UserVisitFactory; 029import com.echothree.model.data.user.server.value.UserKeyDetailValue; 030import com.echothree.util.server.control.BaseLogic; 031import com.echothree.util.server.persistence.EntityPermission; 032import com.echothree.util.server.persistence.Session; 033 034public class UserVisitLogic 035 extends BaseLogic { 036 037 private UserVisitLogic() { 038 super(); 039 } 040 041 private static class UserVisitLogicHolder { 042 static UserVisitLogic instance = new UserVisitLogic(); 043 } 044 045 public static UserVisitLogic getInstance() { 046 return UserVisitLogicHolder.instance; 047 } 048 049 private void cleanupUserVisitDependencies(final UserVisit userVisit, final Long endTime, final PartyPK cleanedUpBy) { 050 var orderControl = Session.getModelController(OrderControl.class); 051 var searchControl = Session.getModelController(SearchControl.class); 052 053 orderControl.deleteOrderUserVisitsByUserVisit(userVisit); 054 055 // Clear any searches since they may contain results that should not be accessible by another user. 056 searchControl.removeUserVisitSearchesByUserVisit(userVisit); 057 058 WorkRequirementLogic.getInstance().endWorkTimesByUserVisit(userVisit, endTime, cleanedUpBy); 059 } 060 061 public void invalidateUserVisit(UserVisit userVisit, PartyPK invalidatedBy) { 062 if(userVisit != null) { 063 var userControl = Session.getModelController(UserControl.class); 064 UserSession userSession = UserSessionLogic.getInstance().deleteUserSessionByUserVisit(userVisit); 065 066 cleanupUserVisitDependencies(userVisit, null, invalidatedBy); 067 068 if(userVisit.getRetainUntilTime() == null) { 069 if(userSession != null) { 070 userControl.removeUserSession(userSession); 071 } 072 073 userControl.removeUserVisit(userVisit); 074 } else { 075 userControl.deleteUserVisit(userVisit); 076 } 077 } 078 } 079 080 public void invalidateUserVisit(UserVisitPK userVisitPK, PartyPK invalidatedBy) { 081 var userControl = Session.getModelController(UserControl.class); 082 083 invalidateUserVisit(userControl.getUserVisitByPKForUpdate(userVisitPK), invalidatedBy); 084 } 085 086 public void invalidateAbandonedUserVisits(Long abandonedTime, PartyPK invalidatedBy) { 087 var userControl = Session.getModelController(UserControl.class); 088 089 for(UserVisit userVisit: userControl.getAbandonedUserVisits(abandonedTime)) { 090 userVisit = UserVisitFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, userVisit.getPrimaryKey()); 091 092 invalidateUserVisit(userVisit, invalidatedBy); 093 } 094 } 095 096 public void removeInvalidatedUserVisits() { 097 var userControl = Session.getModelController(UserControl.class); 098 099 for(UserVisit userVisit: userControl.getInvalidatedUserVisits()) { 100 userVisit = UserVisitFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, userVisit.getPrimaryKey()); 101 102 userControl.removeUserVisit(userVisit); 103 } 104 } 105 106 /** Disassociate any Party from the specified UserVisit by deleting the UserSession, keep all the Preferred* properties. 107 */ 108 public void disassociatePartyFromUserVisit(final UserVisit userVisit, final Long endTime, final PartyPK disassociatedBy) { 109 var userControl = Session.getModelController(UserControl.class); 110 UserSession userSession = userControl.getUserSessionByUserVisitForUpdate(userVisit); 111 112 if(userSession != null) { 113 // If there wasn't a specific UserSession and Party assocaited with the UserVisit, 114 // then we shouldn't need to perform this step. 115 cleanupUserVisitDependencies(userVisit, endTime, disassociatedBy); 116 117 userControl.deleteUserSession(userSession); 118 } 119 } 120 121 /** Remove any Party's specific connection to the UserVisit and its UserKey. Clearing the connection in the UserKey is one step beyond 122 * what's provided by disassociatePartyFromUserVisit(...). 123 */ 124 public void logout(final UserVisitPK userVisitPK, final Long endTime, final PartyPK loggedOutBy) { 125 var userControl = Session.getModelController(UserControl.class); 126 UserVisit userVisit = userControl.getUserVisitByPK(userVisitPK); 127 UserKey userKey = userVisit.getUserKey(); 128 UserKeyDetailValue userKeyDetailValue = userControl.getUserKeyDetailValueByPKForUpdate(userKey.getLastDetail().getPrimaryKey()); 129 130 if(userKeyDetailValue.getPartyPK() != null || userKeyDetailValue.getPartyRelationshipPK() != null) { 131 userKeyDetailValue.setPartyPK(null); 132 userKeyDetailValue.setPartyRelationshipPK(null); 133 userControl.updateUserKeyFromValue(userKeyDetailValue); 134 } 135 136 disassociatePartyFromUserVisit(userVisit, endTime, loggedOutBy); 137 138 // TODO: Create audit trail 139 } 140 141}