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.core.server.logic; 018 019import com.echothree.control.user.core.common.spec.EntityRefSpec; 020import com.echothree.control.user.core.common.spec.GuidSpec; 021import com.echothree.control.user.core.common.spec.KeySpec; 022import com.echothree.control.user.core.common.spec.UlidSpec; 023import com.echothree.control.user.core.common.spec.UniversalEntitySpec; 024import com.echothree.model.control.core.common.ComponentVendors; 025import com.echothree.model.control.core.common.EventTypes; 026import com.echothree.model.control.core.common.exception.InvalidComponentVendorException; 027import com.echothree.model.control.core.common.exception.InvalidEntityTypeException; 028import com.echothree.model.control.core.common.exception.InvalidParameterCountException; 029import com.echothree.model.control.core.common.exception.UnknownEntityRefException; 030import com.echothree.model.control.core.common.exception.UnknownGuidException; 031import com.echothree.model.control.core.common.exception.UnknownKeyException; 032import com.echothree.model.control.core.common.exception.UnknownUlidException; 033import com.echothree.model.control.core.server.control.CoreControl; 034import com.echothree.model.control.core.server.database.EntityInstancesByEntityTypeWithNullDeletedTimeQuery; 035import com.echothree.model.data.core.server.entity.EntityInstance; 036import com.echothree.model.data.core.server.entity.EntityTime; 037import com.echothree.model.data.core.server.entity.EntityType; 038import com.echothree.model.data.core.server.entity.EntityTypeDetail; 039import com.echothree.model.data.core.server.factory.EntityInstanceFactory; 040import com.echothree.util.common.message.ExecutionErrors; 041import com.echothree.util.common.persistence.BasePK; 042import com.echothree.util.server.control.BaseLogic; 043import com.echothree.util.server.message.ExecutionErrorAccumulator; 044import com.echothree.util.server.persistence.EntityIdGenerator; 045import com.echothree.util.server.persistence.EntityPermission; 046import com.echothree.util.server.persistence.Session; 047 048public class EntityInstanceLogic 049 extends BaseLogic { 050 051 private EntityInstanceLogic() { 052 super(); 053 } 054 055 private static class EntityInstanceLogicHolder { 056 static EntityInstanceLogic instance = new EntityInstanceLogic(); 057 } 058 059 public static EntityInstanceLogic getInstance() { 060 return EntityInstanceLogicHolder.instance; 061 } 062 063 public EntityInstance createEntityInstance(final ExecutionErrorAccumulator eea, final EntityType entityType, 064 final BasePK createdBy) { 065 var entityTypeDetail = entityType.getLastDetail(); 066 var componentVendorName = entityTypeDetail.getComponentVendor().getLastDetail().getComponentVendorName(); 067 EntityInstance entityInstance = null; 068 069 if(!ComponentVendors.ECHO_THREE.name().equals(componentVendorName)) { 070 var coreControl = Session.getModelController(CoreControl.class); 071 var entityTypeName = entityTypeDetail.getEntityTypeName(); 072 var entityIdGenerator = new EntityIdGenerator(componentVendorName, entityTypeName, 1); // TODO 073 var entityId = entityIdGenerator.getNextEntityId(); 074 var basePK = new BasePK(componentVendorName, entityTypeName, entityId); 075 var event = coreControl.sendEvent(basePK, EventTypes.CREATE, null, null, createdBy); 076 077 entityInstance = event.getEntityInstance(); 078 } else { 079 handleExecutionError(InvalidComponentVendorException.class, eea, ExecutionErrors.InvalidComponentVendor.name(), componentVendorName); 080 } 081 082 return entityInstance; 083 } 084 085 private EntityInstance checkEntityTimeForDeletion(CoreControl coreControl, EntityInstance entityInstance) { 086 // If the EntityInstance is null, then it is already going to indicate it has been deleted, otherwise... 087 if(entityInstance != null) { 088 EntityTime entityTime = coreControl.getEntityTime(entityInstance); 089 090 // If the EntityTime is null, then we're not going to find a DeletedTime, which means it must exist... 091 if(entityTime != null) { 092 // Check the DeletedTime... 093 if(entityTime.getDeletedTime() != null) { 094 // It's been deleted. 095 entityInstance = null; 096 } 097 } 098 } 099 100 return entityInstance; 101 } 102 103 public EntityInstance getEntityInstanceByEntityRef(final ExecutionErrorAccumulator eea, final String entityRef) { 104 var coreControl = Session.getModelController(CoreControl.class); 105 EntityInstance entityInstance = checkEntityTimeForDeletion(coreControl, coreControl.getEntityInstanceByEntityRef(entityRef)); 106 107 if(entityInstance == null) { 108 handleExecutionError(UnknownEntityRefException.class, eea, ExecutionErrors.UnknownEntityRef.name(), entityRef); 109 } 110 111 return entityInstance; 112 } 113 114 public EntityInstance getEntityInstanceByEntityRef(final ExecutionErrorAccumulator eea, final EntityRefSpec spec) { 115 return getEntityInstanceByEntityRef(eea, spec.getEntityRef()); 116 } 117 118 public EntityInstance getEntityInstanceByKey(final ExecutionErrorAccumulator eea, final String key) { 119 var coreControl = Session.getModelController(CoreControl.class); 120 EntityInstance entityInstance = checkEntityTimeForDeletion(coreControl, coreControl.getEntityInstanceByKey(key)); 121 122 if(entityInstance == null) { 123 handleExecutionError(UnknownKeyException.class, eea, ExecutionErrors.UnknownKey.name(), key); 124 } 125 126 return entityInstance; 127 } 128 129 public EntityInstance getEntityInstanceByKey(final ExecutionErrorAccumulator eea, final KeySpec spec) { 130 return getEntityInstanceByKey(eea, spec.getKey()); 131 } 132 133 public EntityInstance getEntityInstanceByGuid(final ExecutionErrorAccumulator eea, final String guid) { 134 var coreControl = Session.getModelController(CoreControl.class); 135 EntityInstance entityInstance = checkEntityTimeForDeletion(coreControl, coreControl.getEntityInstanceByGuid(guid)); 136 137 if(entityInstance == null) { 138 handleExecutionError(UnknownGuidException.class, eea, ExecutionErrors.UnknownGuid.name(), guid); 139 } 140 141 return entityInstance; 142 } 143 144 public EntityInstance getEntityInstanceByUlid(final ExecutionErrorAccumulator eea, final String ulid) { 145 var coreControl = Session.getModelController(CoreControl.class); 146 EntityInstance entityInstance = checkEntityTimeForDeletion(coreControl, coreControl.getEntityInstanceByUlid(ulid)); 147 148 if(entityInstance == null) { 149 handleExecutionError(UnknownUlidException.class, eea, ExecutionErrors.UnknownUlid.name(), ulid); 150 } 151 152 return entityInstance; 153 } 154 155 public EntityInstance getEntityInstanceByGuid(final ExecutionErrorAccumulator eea, final GuidSpec spec) { 156 return getEntityInstanceByGuid(eea, spec.getGuid()); 157 } 158 159 public EntityInstance getEntityInstanceByUlid(final ExecutionErrorAccumulator eea, final UlidSpec spec) { 160 return getEntityInstanceByUlid(eea, spec.getUlid()); 161 } 162 163 public EntityInstance getEntityInstance(final ExecutionErrorAccumulator eea, final String entityRef, final String key, 164 final String guid, final String ulid, final String componentVendorName, final String... entityTypeNames) { 165 var parameterCount = countPossibleEntitySpecs(entityRef, key, guid, ulid); 166 EntityInstance entityInstance = null; 167 168 if(parameterCount == 1) { 169 if(entityRef != null) { 170 entityInstance = getEntityInstanceByEntityRef(eea, entityRef); 171 } else if(key != null) { 172 entityInstance = getEntityInstanceByKey(eea, key); 173 } else if(guid != null) { 174 entityInstance = getEntityInstanceByGuid(eea, guid); 175 } else if(ulid != null) { 176 entityInstance = getEntityInstanceByUlid(eea, ulid); 177 } 178 } else { 179 handleExecutionError(InvalidParameterCountException.class, eea, ExecutionErrors.InvalidParameterCount.name()); 180 } 181 182 if((eea == null || !eea.hasExecutionErrors()) && componentVendorName != null && entityTypeNames.length > 0) { 183 EntityTypeDetail entityTypeDetail = entityInstance.getEntityType().getLastDetail(); 184 String foundComponentVendorName = entityTypeDetail.getComponentVendor().getLastDetail().getComponentVendorName(); 185 String foundEntityTypeName = entityTypeDetail.getEntityTypeName(); 186 boolean found = false; 187 188 if(foundComponentVendorName.equals(componentVendorName)) { 189 for(var entityTypeName : entityTypeNames) { 190 if(entityTypeName.equals(foundEntityTypeName)) { 191 found = true; 192 break; 193 } 194 } 195 } 196 197 if(!found) { 198 handleExecutionError(InvalidEntityTypeException.class, eea, ExecutionErrors.InvalidEntityType.name(), foundComponentVendorName, foundEntityTypeName); 199 entityInstance = null; 200 } 201 } 202 203 return entityInstance; 204 } 205 206 public EntityInstance getEntityInstance(final ExecutionErrorAccumulator eea, final EntityRefSpec entityRefSpec, final KeySpec keySpec, 207 final GuidSpec guidSpec, final UlidSpec ulidSpec, final String componentVendorName, final String... entityTypeNames) { 208 return getEntityInstance(eea, entityRefSpec.getEntityRef(), keySpec.getKey(), guidSpec.getGuid(), ulidSpec.getUlid(), 209 componentVendorName, entityTypeNames); 210 } 211 212 public EntityInstance getEntityInstance(final ExecutionErrorAccumulator eea, final UniversalEntitySpec universalEntitySpec) { 213 return getEntityInstance(eea, universalEntitySpec.getEntityRef(), universalEntitySpec.getKey(), 214 universalEntitySpec.getGuid(), universalEntitySpec.getUlid(), null); 215 } 216 217 public EntityInstance getEntityInstance(final ExecutionErrorAccumulator eea, final UniversalEntitySpec universalEntitySpec, 218 final String componentVendorName, final String... entityTypeNames) { 219 return getEntityInstance(eea, universalEntitySpec.getEntityRef(), universalEntitySpec.getKey(), 220 universalEntitySpec.getGuid(), universalEntitySpec.getUlid(), componentVendorName, entityTypeNames); 221 } 222 223 public int countPossibleEntitySpecs(final String entityRef, final String key, final String guid, final String ulid) { 224 return (entityRef == null ? 0 : 1) + (key == null ? 0 : 1) + (guid == null ? 0 : 1) + (ulid == null ? 0 : 1); 225 } 226 227 public int countPossibleEntitySpecs(final EntityRefSpec entityRefSpec, final KeySpec keySpec, final GuidSpec guidSpec, 228 final UlidSpec ulidSpec) { 229 return countPossibleEntitySpecs(entityRefSpec == null ? null : entityRefSpec.getEntityRef(), 230 keySpec == null ? null : keySpec.getKey(), guidSpec == null ? null : guidSpec.getGuid(), 231 ulidSpec == null ? null : ulidSpec.getUlid()); 232 } 233 234 public int countPossibleEntitySpecs(final UniversalEntitySpec universalEntitySpec) { 235 return universalEntitySpec == null ? 0 : countPossibleEntitySpecs(universalEntitySpec.getEntityRef(), 236 universalEntitySpec.getKey(), universalEntitySpec.getGuid(), universalEntitySpec.getUlid()); 237 } 238 239 public String getEntityRefFromEntityInstance(EntityInstance entityInstance) { 240 var entityTypeDetail = entityInstance.getEntityType().getLastDetail(); 241 var componentVendorDetail = entityTypeDetail.getComponentVendor().getLastDetail(); 242 243 return new StringBuilder(componentVendorDetail.getComponentVendorName()).append('.') 244 .append(entityTypeDetail.getEntityTypeName()).append('.') 245 .append(entityInstance.getEntityUniqueId()).toString(); 246 } 247 248 public void deleteEntityInstance(final ExecutionErrorAccumulator eea, final EntityInstance entityInstance, final BasePK deletedBy) { 249 var componentVendorName = entityInstance.getEntityType().getLastDetail().getComponentVendor().getLastDetail().getComponentVendorName(); 250 251 if(!ComponentVendors.ECHO_THREE.name().equals(componentVendorName)) { 252 var coreControl = Session.getModelController(CoreControl.class); 253 254 coreControl.deleteEntityInstance(entityInstance, deletedBy); 255 } else { 256 handleExecutionError(InvalidComponentVendorException.class, eea, ExecutionErrors.InvalidComponentVendor.name(), componentVendorName); 257 } 258 } 259 260 public void removeEntityInstance(final ExecutionErrorAccumulator eea, final EntityInstance entityInstance) { 261 var componentVendorName = entityInstance.getEntityType().getLastDetail().getComponentVendor().getLastDetail().getComponentVendorName(); 262 263 if(!ComponentVendors.ECHO_THREE.name().equals(componentVendorName)) { 264 var coreControl = Session.getModelController(CoreControl.class); 265 266 coreControl.removeEntityInstance(entityInstance); 267 } else { 268 handleExecutionError(InvalidComponentVendorException.class, eea, ExecutionErrors.InvalidComponentVendor.name(), componentVendorName); 269 } 270 } 271 272}