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.model.control.core.server.transfer;
018
019import com.echothree.model.control.core.common.transfer.EntityLockTransfer;
020import com.echothree.model.control.core.server.CoreDebugFlags;
021import com.echothree.model.data.core.common.pk.EntityInstancePK;
022import com.echothree.model.data.core.server.entity.EntityInstance;
023import com.echothree.model.data.core.server.factory.EntityInstanceFactory;
024import com.echothree.model.data.user.server.entity.UserVisit;
025import com.echothree.util.common.exception.EntityLockException;
026import com.echothree.util.common.persistence.BasePK;
027import com.echothree.util.server.persistence.DslContextFactory;
028import com.echothree.util.server.persistence.EntityPermission;
029import com.echothree.util.server.persistence.PersistenceUtils;
030import com.echothree.util.server.persistence.Session;
031import java.sql.SQLException;
032import javax.enterprise.context.RequestScoped;
033
034@RequestScoped
035public class EntityLockTransferCache
036        extends BaseCoreTransferCache {
037
038
039    /** Creates a new instance of EntityLockTransferCache */
040    protected EntityLockTransferCache() {
041        super();
042    }
043    
044    @SuppressWarnings("Finally")
045    public EntityLockTransfer getEntityLockTransfer(final UserVisit userVisit, BasePK lockTarget) {
046        var entityLockTransfer = (EntityLockTransfer)get(lockTarget);
047        
048        if(entityLockTransfer == null) {
049            var lockTargetEntityInstance = entityInstanceControl.getEntityInstanceByBasePK(lockTarget);
050            
051            entityLockTransfer = getEntityLockTransferByEntityInstance(userVisit, lockTargetEntityInstance, true);
052        }
053        
054        return entityLockTransfer;
055    }
056    
057    public EntityLockTransfer getEntityLockTransferByEntityInstance(final UserVisit userVisit, EntityInstance lockTargetEntityInstance) {
058        return getEntityLockTransferByEntityInstance(userVisit, lockTargetEntityInstance, false);
059    }
060    
061    private EntityLockTransfer getEntityLockTransferByEntityInstance(final UserVisit userVisit, EntityInstance lockTargetEntityInstance, boolean putInCache) {
062        EntityLockTransfer entityLockTransfer = null;
063        
064        try (var conn = DslContextFactory.getInstance().getNTDslContext().parsingConnection()) {
065            long lockTargetEntityInstanceId = lockTargetEntityInstance.getPrimaryKey().getEntityId();
066            long lockedByEntityInstanceId = 0;
067            long lockedTime = 0;
068            long expirationTime = 0;
069
070            if(CoreDebugFlags.LogEntityLocks) {
071                getLog().info(">>> getEntityLockTransfer(lockTargetEntityInstance=" + lockTargetEntityInstance.getPrimaryKey() + ")");
072            }
073
074            if(CoreDebugFlags.LogEntityLocks) {
075                getLog().info("--- lockTargetEntityInstance=" + lockTargetEntityInstance);
076            }
077
078            try (var ps = conn.prepareStatement(
079                    "SELECT lcks_lockedbyentityinstanceid, lcks_lockedtime, lcks_lockexpirationtime "
080                    + "FROM entitylocks "
081                    + "WHERE lcks_locktargetentityinstanceid = ?")) {
082                ps.setLong(1, lockTargetEntityInstanceId);
083
084                try (var rs = ps.executeQuery()) {
085                    if (rs.next()) {
086                        lockedByEntityInstanceId = rs.getLong(1);
087                        lockedTime = rs.getLong(2);
088                        expirationTime = rs.getLong(3);
089                    }
090                } catch (SQLException se) {
091                    throw new EntityLockException(se);
092                }
093            } catch (SQLException se) {
094                throw new EntityLockException(se);
095            }
096
097            if(lockedByEntityInstanceId != 0) {
098                var lockedByEntityInstancePK = new EntityInstancePK(lockedByEntityInstanceId);
099                var lockedByEntityInstance = EntityInstanceFactory.getInstance().getEntityFromPK(EntityPermission.READ_ONLY, lockedByEntityInstancePK);
100                var lockTargetEntityInstanceTransfer = entityInstanceControl.getEntityInstanceTransfer(userVisit, lockTargetEntityInstance, false, false, false, false);
101                var lockedByEntityInstanceTransfer = entityInstanceControl.getEntityInstanceTransfer(userVisit, lockedByEntityInstance, false, false, false, false);
102
103                if(CoreDebugFlags.LogEntityLocks) {
104                    getLog().info("--- lockedByEntityInstancePK = " + lockedByEntityInstancePK);
105                    getLog().info("--- lockedByEntityInstance = " + lockedByEntityInstance);
106                    getLog().info("--- lockTargetEntityInstanceTransfer = " + lockTargetEntityInstanceTransfer.getEntityRef());
107                    getLog().info("--- lockTargetEntityInstanceTransfer = " + lockTargetEntityInstanceTransfer.getEntityRef());
108                }
109
110                var lockedTimeString = formatTypicalDateTime(userVisit, lockedTime);
111                var expirationTimeString = formatTypicalDateTime(userVisit, expirationTime);
112
113                entityLockTransfer = new EntityLockTransfer(lockTargetEntityInstanceTransfer, lockedByEntityInstanceTransfer, lockedTime, lockedTimeString, expirationTime, expirationTimeString);
114            }
115            
116            if(putInCache) {
117                transferCache.put(PersistenceUtils.getInstance().getBasePKFromEntityInstance(lockTargetEntityInstance), entityLockTransfer);
118            }
119        } catch (SQLException se) {
120            throw new EntityLockException(se);
121        }
122
123        if(CoreDebugFlags.LogEntityLocks) {
124            getLog().info("<<< entityLockTransfer=" + entityLockTransfer);
125        }
126
127        return entityLockTransfer;
128    }    
129    
130}