diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index df4371b62e6..2dd1827222b 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2444,9 +2444,13 @@ class ActionDelegate { return [(role.importId + ":" + GLOBAL_ROLE), ("$role.name (🌍 Global role)" as String)] } else { if (!temp.containsKey(entry.value)) { - temp.put(entry.value, petriNetService.getNewestVersionByIdentifier(entry.value)) + temp.put(entry.value, petriNetService.getDefaultVersionByIdentifier(entry.value)) } PetriNet net = temp[entry.value] + if (net == null) { + throw new IllegalArgumentException("The process with identifier [%s] could not be found when collecting roles." + .formatted(entry.value)) + } ProcessRole role = net.roles.find { it.value.importId == entry.key }.value return [(role.importId + ":" + net.identifier), ("$role.name ($net.title)" as String)] } diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy index 78f640b7052..550e5a89513 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy @@ -51,7 +51,10 @@ class RoleActionDelegate extends AbstractActionDelegate { } AbstractUser assignRole(String roleImportId, String petriNetIdentifier, AbstractUser user = affectedUser) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(petriNetIdentifier) + PetriNet petriNet = petriNetService.getDefaultVersionByIdentifier(petriNetIdentifier) + if (petriNet == null) { + throw new IllegalArgumentException("The process with identifier [%s] could not be found".formatted(petriNetIdentifier)) + } assignRole(roleImportId, user, petriNet) } @@ -75,7 +78,10 @@ class RoleActionDelegate extends AbstractActionDelegate { } AbstractUser removeRole(String roleImportId, String petriNetIdentifier, AbstractUser user = affectedUser) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(petriNetIdentifier) + PetriNet petriNet = petriNetService.getDefaultVersionByIdentifier(petriNetIdentifier) + if (petriNet == null) { + throw new IllegalArgumentException("The process with identifier [%s] could not be found".formatted(petriNetIdentifier)) + } removeRole(roleImportId, user, petriNet) } diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy index a71f624e5b3..a3fe4d0f822 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy @@ -128,7 +128,7 @@ class ImportHelper { } Optional upsertNet(String filename, String identifier, VersionType release = VersionType.MAJOR, LoggedUser author = ActorTransformer.toLoggedUser(userService.getSystem())) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(identifier) + PetriNet petriNet = petriNetService.getDefaultVersionByIdentifier(identifier) if (!petriNet) { return createNet(filename, release, author) } @@ -249,7 +249,7 @@ class ImportHelper { } Optional importProcessOnce(String message, String netIdentifier, String netFileName) { - PetriNet filter = petriNetService.getNewestVersionByIdentifier(netIdentifier) + PetriNet filter = petriNetService.getDefaultVersionByIdentifier(netIdentifier) if (filter != null) { log.info("${message} has already been imported.") return Optional.of(filter) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java index 8050c7ac379..738fc560553 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java @@ -27,9 +27,14 @@ public class CacheConfigurationProperties { private String petriNetByIdentifier = "petriNetByIdentifier"; /** - * Default cache name for caching the newest versions of Petri nets. + * Default cache name for caching the default versions of Petri nets. */ - private String petriNetNewest = "petriNetNewest"; + private String petriNetDefault = "petriNetDefault"; + + /** + * Default cache name for caching the latest versions of Petri nets. + */ + private String petriNetLatest = "petriNetLatest"; /** * Default cache name for general Petri net caching. @@ -54,7 +59,8 @@ public class CacheConfigurationProperties { * @return a {@link Set} of all cache names. */ public Set getAllCaches() { - Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache, loadedModules)); + Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetDefault, + petriNetLatest, petriNetCache, loadedModules)); caches.addAll(additional); return caches; } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java index c0a5627de03..8d20ed2dd55 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java @@ -8,6 +8,9 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.common.ResourceNotFoundException; +import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; +import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.objects.utils.MenuItemUtils; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -62,7 +65,11 @@ public Case getOrCreate(DashboardItemBody body) throws TransitionNotExecutableEx } LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); - itemCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); + PetriNet petriNet = petriNetService.getDefaultVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER); + if (petriNet == null) { + throw new ResourceNotFoundException(ResourceNotFoundExceptionCode.DEFAULT_PROCESS_NOT_FOUND, "Dashboard item process not found"); + } + itemCase = workflowService.createCase(petriNet.getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); ToDataSetOutcome outcome = body.toDataSet(); itemCase = setDataWithExecute(itemCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet()); return itemCase; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java index 95a426e88eb..73e6ab67a61 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java @@ -8,7 +8,10 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.common.ResourceNotFoundException; +import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; +import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.objects.utils.MenuItemUtils; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -64,7 +67,11 @@ public Case createDashboardManagement(DashboardManagementBody body) throws Trans } addReferencedMenuItems(body); LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); - managementCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); + PetriNet petriNet = petriNetService.getDefaultVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER); + if (petriNet == null) { + throw new ResourceNotFoundException(ResourceNotFoundExceptionCode.DEFAULT_PROCESS_NOT_FOUND, "Dashboard management process not found"); + } + managementCase = workflowService.createCase(petriNet.getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); ToDataSetOutcome outcome = body.toDataSet(); managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet()); return managementCase; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java index a8dd005b207..dcdf836e12c 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java @@ -33,6 +33,16 @@ public interface PetriNetRepository extends MongoRepository, Q */ PetriNet findByIdentifierAndVersion(String identifier, Version version); + /** + * Finds a page of {@link PetriNet} entities by its identifier and defaultVersion attribute + * + * @param identifier the unique identifier of the PetriNet. + * @param defaultVersion if true, the default version will be found, otherwise the non-default version will be found + * @param pageable the pagination details. + * @return the page of {@link PetriNet} entities matching the given identifier and defaultVersion attribute + */ + Page findByIdentifierAndDefaultVersion(String identifier, boolean defaultVersion, Pageable pageable); + /** * Finds a paginated list of {@link PetriNet} entities by their identifier. * diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index c5867b0ddf7..6f5aef7d064 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -11,7 +11,6 @@ import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; -import com.netgrif.application.engine.objects.event.events.Event; import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeleteEvent; import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeployEvent; import com.netgrif.application.engine.importer.service.Importer; @@ -140,15 +139,16 @@ protected Importer getImporter() { @Override public void evictAllCaches() { requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetById()), cacheProperties.getPetriNetById()).clear(); - requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetNewest()), cacheProperties.getPetriNetNewest()).clear(); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetDefault()), cacheProperties.getPetriNetDefault()).clear(); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetLatest()), cacheProperties.getPetriNetLatest()).clear(); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetCache()), cacheProperties.getPetriNetCache()).clear(); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetByIdentifier()), cacheProperties.getPetriNetByIdentifier()).clear(); - } public void evictCache(PetriNet net) { requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetById()), cacheProperties.getPetriNetById()).evict(net.getStringId()); - requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetNewest()), cacheProperties.getPetriNetNewest()).evict(net.getIdentifier()); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetDefault()), cacheProperties.getPetriNetDefault()).evict(net.getIdentifier()); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetLatest()), cacheProperties.getPetriNetLatest()).evict(net.getIdentifier()); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetCache()), cacheProperties.getPetriNetCache()).evict(net.getObjectId()); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetByIdentifier()), cacheProperties.getPetriNetByIdentifier()).evict(net.getIdentifier() + net.getVersion().toString()); } @@ -178,63 +178,113 @@ public List get(List petriNetIds) { @Override @Deprecated + @Transactional public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { return importPetriNet(xmlFile, VersionType.valueOf(releaseType.trim().toUpperCase()), author); } @Override + @Transactional public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { return importPetriNet(xmlFile, releaseType, author, new HashMap<>()); } @Override + @Transactional public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, Map params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { ImportPetriNetEventOutcome outcome = new ImportPetriNetEventOutcome(); ByteArrayOutputStream xmlCopy = new ByteArrayOutputStream(); IOUtils.copy(xmlFile, xmlCopy); - Optional imported = getImporter().importPetriNet(new ByteArrayInputStream(xmlCopy.toByteArray())); - if (imported.isEmpty()) { + Optional importedProcess = getImporter().importPetriNet(new ByteArrayInputStream(xmlCopy.toByteArray())); + if (importedProcess.isEmpty()) { return outcome; } - PetriNet net = imported.get(); - - PetriNet existingNet = getNewestVersionByIdentifier(net.getIdentifier()); - - if (existingNet != null) { - if (existingNet.getVersion().equals(net.getVersion())) { - throw new IllegalArgumentException("Provided Petri net version is already present in the system"); - } - if (net.getVersion() == null) { - net.setVersion(existingNet.getVersion()); - net.incrementVersion(releaseType); - } - } else if (net.getVersion() == null) { - net.setVersion(new Version()); - } + PetriNet newProcess = importedProcess.get(); + PetriNet processToMakeNonDefault = checkAndHandleProcessVersion(newProcess, releaseType); - processRoleService.saveAll(net.getRoles().values()); - net.setAuthor(ActorTransformer.toActorRef(author)); - functionCacheService.cachePetriNetFunctions(net); - Path savedPath = getImporter().saveNetFile(net, new ByteArrayInputStream(xmlCopy.toByteArray())); + processRoleService.saveAll(newProcess.getRoles().values()); + newProcess.setAuthor(ActorTransformer.toActorRef(author)); + functionCacheService.cachePetriNetFunctions(newProcess); + Path savedPath = getImporter().saveNetFile(newProcess, new ByteArrayInputStream(xmlCopy.toByteArray())); xmlCopy.close(); - log.info("Petri net " + net.getTitle() + " (" + net.getInitials() + " v" + net.getVersion() + ") imported successfully and saved in a folder: " + savedPath.toString()); + log.info("Petri net " + newProcess.getTitle() + " (" + newProcess.getInitials() + " v" + newProcess.getVersion() + ") imported successfully and saved in a folder: " + savedPath.toString()); - outcome.setOutcomes(eventService.runActions(net.getPreUploadActions(), null, Optional.empty(), params)); + outcome.setOutcomes(eventService.runActions(newProcess.getPreUploadActions(), null, Optional.empty(), params)); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.PRE)); - save(net); - outcome.setOutcomes(eventService.runActions(net.getPostUploadActions(), null, Optional.empty(), params)); - outcome.setNet(imported.get()); + + if (processToMakeNonDefault != null) { + doSaveInternal(processToMakeNonDefault); + } + Optional saveProcessOpt = doSaveInternal(newProcess); + + outcome.setOutcomes(eventService.runActions(newProcess.getPostUploadActions(), null, Optional.empty(), params)); + outcome.setNet(saveProcessOpt.orElseThrow()); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.POST)); return outcome; } - protected void evaluateRules(Event event) { - publisher.publishEvent(event); + /** + * Validates the version of an importing process. This method can update 'newProces': initialize version, + * initialize default version attribute. This method can also update the current default version of the process if needed. + * + *

Version initialization logic

+ *
    + *
  • Uploaded process becomes default only if its version is the highest
  • + *
  • Only one process can be default. If the importing process is about to get default, the currently default + * process becomes non-default
  • + *
  • If no version is provided, it's initialized to 1.0.0 or by the existing highest version incremented + * by 'releaseType' input parameter
  • + *
+ * + * @param newProcess A process to be checked and updated + * @param releaseType requested release type level. It's used for version initialization + * + * @return The process, which has been made non-default or null if no process updated + * + * @throws IllegalArgumentException if the version already exists + * */ + private PetriNet checkAndHandleProcessVersion(PetriNet newProcess, VersionType releaseType) { + PetriNet processToMakeNonDefault = null; + + if (newProcess.getVersion() != null && self.getPetriNet(newProcess.getIdentifier(), newProcess.getVersion()) != null) { + throw new IllegalArgumentException("A process [%s] with such version [%s] already exists" + .formatted(newProcess.getIdentifier(), newProcess.getVersion())); + } + PetriNet existingLatestProcess = self.getLatestVersionByIdentifier(newProcess.getIdentifier()); + boolean makeNonDefaultCurrentVersion = true; + if (existingLatestProcess == null && newProcess.getVersion() == null) { + newProcess.setVersion(new Version()); + } else { + if (newProcess.getVersion() == null) { + newProcess.setVersion(existingLatestProcess.getVersion().clone()); + newProcess.incrementVersion(releaseType); + } else if (existingLatestProcess != null && newProcess.getVersion().isLowerThan(existingLatestProcess.getVersion())) { + makeNonDefaultCurrentVersion = false; + } + if (makeNonDefaultCurrentVersion && existingLatestProcess != null && existingLatestProcess.isDefaultVersion()) { + existingLatestProcess.makeNonDefault(); + processToMakeNonDefault = existingLatestProcess; + } else if (makeNonDefaultCurrentVersion) { + PetriNet existingActiveProcess = self.getDefaultVersionByIdentifier(newProcess.getIdentifier()); + if (existingActiveProcess != null) { + existingActiveProcess.makeNonDefault(); + processToMakeNonDefault = existingActiveProcess; + } + } + } + if (makeNonDefaultCurrentVersion) { + newProcess.makeDefault(); + } + return processToMakeNonDefault; } @Override public Optional save(PetriNet petriNet) { + return doSaveInternal(petriNet); + } + + protected final Optional doSaveInternal(PetriNet petriNet) { petriNet.initializeArcs(); this.evictCache(petriNet); petriNet = repository.save(petriNet); @@ -242,7 +292,7 @@ public Optional save(PetriNet petriNet) { try { elasticPetriNetService.indexNow(this.petriNetMappingService.transform(petriNet)); } catch (Exception e) { - log.error("Indexing failed [" + petriNet.getStringId() + "]", e); + log.error("Indexing failed [{}]", petriNet.getStringId(), e); } return Optional.of(petriNet); @@ -262,6 +312,9 @@ public PetriNet getPetriNet(String id) { @Override @Cacheable(value = "petriNetByIdentifier", key = "#identifier+#version.toString()", unless = "#result == null") public PetriNet getPetriNet(String identifier, Version version) { + if (identifier == null || version == null) { + return null; + } PetriNet net = repository.findByIdentifierAndVersion(identifier, version); if (net == null) { return null; @@ -283,13 +336,32 @@ public List findAllById(List ids) { } @Override - @Cacheable(value = "petriNetNewest", unless = "#result == null") - public PetriNet getNewestVersionByIdentifier(String identifier) { - List nets = repository.findByIdentifier(identifier, PageRequest.of(0, 1, Sort.Direction.DESC, "version.major", "version.minor", "version.patch")).getContent(); - if (nets.isEmpty()) { + @Cacheable(value = "petriNetDefault", unless = "#result == null") + public PetriNet getDefaultVersionByIdentifier(String identifier) { + if (identifier == null) { return null; } - return nets.getFirst(); + + List result = repository.findByIdentifierAndDefaultVersion(identifier, true, PageRequest.of(0, 1)).getContent(); + if (!result.isEmpty()) { + return result.getFirst(); + } + + return null; + } + + @Override + @Cacheable(value = "petriNetLatest", unless = "#result == null") + public PetriNet getLatestVersionByIdentifier(String identifier) { + if (identifier == null) { + return null; + } + List processes = repository.findByIdentifier(identifier, PageRequest.of(0, 1, + Sort.Direction.DESC, "version.major", "version.minor", "version.patch")).getContent(); + if (processes.isEmpty()) { + return null; + } + return processes.getFirst(); } /** @@ -421,7 +493,7 @@ public List getReferencesByUsersProcessRoles(LoggedUser user, @Override public PetriNetReference getReference(String identifier, Version version, LoggedUser user, Locale locale) { - PetriNet net = version == null ? getNewestVersionByIdentifier(identifier) : getPetriNet(identifier, version); + PetriNet net = version == null ? getDefaultVersionByIdentifier(identifier) : getPetriNet(identifier, version); return net != null ? transformToReference(net, locale) : new PetriNetReference(); } @@ -555,6 +627,15 @@ protected void deletePetriNet(String processId, LoggedUser loggedUser, boolean f repository.deleteBy_id(petriNet.getObjectId()); evictCache(petriNet); functionCacheService.reloadCachedFunctions(petriNet); + if (petriNet.isDefaultVersion()) { + PetriNet processToMakeDefault = self.getLatestVersionByIdentifier(petriNet.getIdentifier()); + if (processToMakeDefault != null) { + log.debug("The default version was removed. Making the latest version of the process [{}] with id [{}] as default...", + processToMakeDefault.getIdentifier(), processToMakeDefault.getStringId()); + processToMakeDefault.makeDefault(); + save(processToMakeDefault); + } + } publisher.publishEvent(new ProcessDeleteEvent(petriNet, EventPhase.POST)); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index fd16261e0a4..276e00815c0 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -153,12 +153,20 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti List findAllById(List ids); /** - * Retrieves the newest version of a {@link PetriNet} by its identifier. + * Retrieves the default version of a {@link PetriNet} by its identifier. * * @param identifier the unique identifier of the PetriNet - * @return the newest version of the {@link PetriNet} matching the provided identifier + * @return the default version of the {@link PetriNet} matching the provided identifier or null if not found */ - PetriNet getNewestVersionByIdentifier(String identifier); + PetriNet getDefaultVersionByIdentifier(String identifier); + + /** + * Retrieves the latest version of a {@link PetriNet} by its identifier. + * + * @param identifier the unique identifier of the PetriNet + * @return the latest version of the {@link PetriNet} matching the provided identifier or null if not found + */ + PetriNet getLatestVersionByIdentifier(String identifier); /** * Retrieves a paginated list of all {@link PetriNet} objects. diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java index 93a2618d03a..65a80c0610b 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java @@ -17,10 +17,8 @@ import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @@ -424,7 +422,7 @@ public Optional createFilter(String title, String icon, String filterType, } private Optional createFilterCase(String title, String icon, String filterType, String filterVisibility, String filterQuery, List allowedNets, Map filterMetadata, Map titleTranslations, String originId, boolean viewOrigin, boolean isImported) { - PetriNet filterNet = this.petriNetService.getNewestVersionByIdentifier("filter"); + PetriNet filterNet = this.petriNetService.getDefaultVersionByIdentifier("filter"); if (filterNet == null) { return Optional.empty(); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java index 44522a25567..4244f1e6079 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java @@ -39,7 +39,7 @@ public void createConfigNets() { } public Optional importProcess(final String message, String netIdentifier, String netFileName) { - PetriNet foundNet = petriNetService.getNewestVersionByIdentifier(netIdentifier); + PetriNet foundNet = petriNetService.getDefaultVersionByIdentifier(netIdentifier); if (foundNet != null) { log.info("{} has already been imported.", message); return Optional.of(foundNet); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java index 923d17bfa54..7d4850a1692 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java @@ -280,7 +280,7 @@ public Predicate fullText(Object petriNetQuery, String searchPhrase) { // TODO JOFO: unpaged necessary? petriNets = petriNetService.getAll(Pageable.unpaged()).getContent(); } else { - petriNets = processes.stream().map(process -> petriNetService.getNewestVersionByIdentifier(process)).collect(Collectors.toList()); + petriNets = processes.stream().map(process -> petriNetService.getDefaultVersionByIdentifier(process)).collect(Collectors.toList()); } if (petriNets.isEmpty()) return null; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java index 1b996bc60da..3cf6bf9edb1 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java @@ -71,7 +71,7 @@ public void cachePetriNetFunctions(PetriNet petriNet) { @Override public void reloadCachedFunctions(PetriNet petriNet) { namespaceFunctionsCache.remove(petriNet.getIdentifier()); - cachePetriNetFunctions(petriNetService.getNewestVersionByIdentifier(petriNet.getIdentifier())); + cachePetriNetFunctions(petriNetService.getDefaultVersionByIdentifier(petriNet.getIdentifier())); } @Override diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java index 9dd6cea3f5c..5cb67c54798 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java @@ -9,6 +9,8 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; +import com.netgrif.application.engine.objects.common.ResourceNotFoundException; +import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; import com.netgrif.application.engine.workflow.domain.FilterDeserializer; import com.netgrif.application.engine.objects.workflow.domain.IllegalFilterFileException; import com.netgrif.application.engine.auth.service.UserService; @@ -266,7 +268,10 @@ public void changeFilterField(Collection filterFields) { filterFields.forEach(f -> { Task importedFilterTask = taskService.findOne(f); Case filterCase = workflowService.findOne(importedFilterTask.getCaseId()); - PetriNet filterNet = petriNetService.getNewestVersionByIdentifier(FILTER_NET_IDENTIFIER); + PetriNet filterNet = petriNetService.getDefaultVersionByIdentifier(FILTER_NET_IDENTIFIER); + if (filterNet == null) { + throw new ResourceNotFoundException(ResourceNotFoundExceptionCode.DEFAULT_PROCESS_NOT_FOUND, "No filter process found or active"); + } List requiredNets = filterCase.getDataSet().get(FIELD_FILTER).getAllowedNets(); List currentNets = petriNetService.getExistingPetriNetIdentifiersFromIdentifiersList(requiredNets); if (currentNets.size() < requiredNets.size()) { diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java index 1eb921882b7..5e1030344c9 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java @@ -237,7 +237,7 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St String roleImportId = menuEntryRole.getRoleImportId(); String netImportId = menuEntryRole.getNetImportId(); if (netImportId != null) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(netImportId); + PetriNet net = petriNetService.getDefaultVersionByIdentifier(netImportId); if (net == null) { resultMessage.append("\n- Missing net with import ID: \"").append(netImportId).append("\"").append("for role ").append(roleImportId).append("\n"); netCheck.set(false); @@ -261,7 +261,7 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St } //Creating new Case of preference_filter_item net and setting its data... Case menuItemCase = workflowService.createCase( - petriNetService.getNewestVersionByIdentifier("preference_filter_item").getStringId(), + petriNetService.getDefaultVersionByIdentifier("preference_filter_item").getStringId(), item.getEntryName() + "_" + menuIdentifier, "", ActorTransformer.toLoggedUser(userService.getSystem()) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java index 9fdb0e83f11..162c76b0447 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java @@ -285,7 +285,7 @@ public CreateCaseEventOutcome createCase(String netId, String title, String colo @Override public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Locale locale, Map params) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); + PetriNet net = petriNetService.getDefaultVersionByIdentifier(identifier); if (net == null) { throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); } @@ -299,7 +299,7 @@ public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String t @Override public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Map params) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); + PetriNet net = petriNetService.getDefaultVersionByIdentifier(identifier); if (net == null) { throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); } @@ -308,7 +308,7 @@ public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String t @Override public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); + PetriNet net = petriNetService.getDefaultVersionByIdentifier(identifier); if (net == null) { throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy index dab63cbf0f5..a726f2572db 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy @@ -128,7 +128,7 @@ class ExportServiceTest { taskService.assignTask(ActorTransformer.toLoggedUser(userService.findByEmail(UserConstants.ADMIN_USER_EMAIL, null)), exportTask) Thread.sleep(20000) //Elastic wait - def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId + def processId = petriNetService.getDefaultVersionByIdentifier("export_test").stringId def taskRequest = new ElasticTaskSearchRequest() taskRequest.process = [new com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet(processId)] as List taskRequest.transitionId = ["t4"] as List @@ -146,7 +146,7 @@ class ExportServiceTest { @Test void buildDefaultCsvTaskHeaderTest(){ - def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId + def processId = petriNetService.getDefaultVersionByIdentifier("export_test").stringId String exportTask = mainCase.tasks.find { it.transition == "t4" }.task taskService.assignTask(ActorTransformer.toLoggedUser(userService.findByEmail(UserConstants.ADMIN_USER_EMAIL, null)), exportTask) List task = taskRepository.findAll(QTask.task.processId.eq(processId).and(QTask.task.transitionId.eq("t4"))) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy index b6b97f53520..5fef3a0e8e3 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy @@ -311,7 +311,7 @@ class ImpersonationServiceTest { } def createConfigCase(AbstractUser user, String impersonator, List roles = null, List auths = null) { - def caze = helper.createCase("config", petriNetService.getNewestVersionByIdentifier(ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)) + def caze = helper.createCase("config", petriNetService.getDefaultVersionByIdentifier(ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)) def owner = new UserFieldValue(user) caze.dataSet["impersonated"].value = owner caze.dataSet["impersonated_email"].value = owner.username diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy index 15e6138b78c..09d870976cb 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy @@ -130,7 +130,7 @@ class ImporterTest { assert net.places.size() == 0 // ASSERT IMPORTED NET FROM REPO - net = petriNetService.getNewestVersionByIdentifier("new_model") + net = petriNetService.getDefaultVersionByIdentifier("new_model") assert net != null assert net.importId == "new_model" assert net.version.major == 1 @@ -204,7 +204,7 @@ class ImporterTest { assert net2.places.size() == 0 // ASSERT NEW NET FROM REPO - net2 = petriNetService.getNewestVersionByIdentifier("new_model") + net2 = petriNetService.getDefaultVersionByIdentifier("new_model") assert net2 != null assert net2.importId == "new_model" assert net2.version.major == 2 diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy index 7efdd6ca99a..cb6630d5c94 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy @@ -136,7 +136,7 @@ class PetriNetTest { try { petriNetService.importPetriNet(netResource3.inputStream, VersionType.MAJOR, superCreator.loggedSuper) } catch (Exception e) { - assert e.getMessage() == "Provided Petri net version is already present in the system" + assert e.getMessage() == "A process [test] with such version [0.0.1] already exists" } } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index 1c4a7d430ab..bda05fbec7e 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -67,13 +67,13 @@ class CachePetriNetServiceTest { @Test void cacheTest() { - assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get("processDeleteTest") == null + assert cacheManager.getCache(cacheProperties.getPetriNetDefault()).get("processDeleteTest") == null ImportPetriNetEventOutcome testNetOptional = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) assert testNetOptional.getNet() != null PetriNet testNet = testNetOptional.getNet() - assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()) == null - PetriNet test = petriNetService.getNewestVersionByIdentifier(testNet.getIdentifier()) - assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()).get().equals(test) + assert cacheManager.getCache(cacheProperties.getPetriNetDefault()).get(testNet.getIdentifier()) == null + PetriNet test = petriNetService.getDefaultVersionByIdentifier(testNet.getIdentifier()) + assert cacheManager.getCache(cacheProperties.getPetriNetDefault()).get(testNet.getIdentifier()).get().equals(test) } } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 84ce8b5ee0c..f6a9d6ee00e 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -1,29 +1,24 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.objects.auth.domain.ActorRef -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer -import com.netgrif.application.engine.objects.auth.domain.Authority -import com.netgrif.application.engine.objects.auth.domain.User -import com.netgrif.application.engine.objects.auth.domain.enums.UserState +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService import com.netgrif.application.engine.auth.service.UserService -import com.netgrif.application.engine.objects.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.elastic.domain.ElasticPetriNetRepository import com.netgrif.application.engine.ipc.TaskApiTest +import com.netgrif.application.engine.objects.auth.domain.* +import com.netgrif.application.engine.objects.auth.domain.enums.UserState +import com.netgrif.application.engine.objects.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch -import com.netgrif.application.engine.objects.petrinet.domain.UriContentType -import com.netgrif.application.engine.objects.petrinet.domain.UriNode import com.netgrif.application.engine.objects.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository import com.netgrif.application.engine.objects.petrinet.domain.version.Version +import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository +import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.runner.SuperCreatorRunner -import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -39,13 +34,18 @@ import org.springframework.data.domain.PageRequest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension -@Disabled +import static org.junit.jupiter.api.Assertions.assertFalse +import static org.junit.jupiter.api.Assertions.assertNotNull +import static org.junit.jupiter.api.Assertions.assertThrows +import static org.junit.jupiter.api.Assertions.assertTrue + @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest class PetriNetServiceTest { public static final String NET_FILE = "process_delete_test.xml" + public static final String VERSION_PROCESS_FILE_FORMAT = "petriNets/process_version_%s_0_0.xml" public static final String NET_SEARCH_FILE = "process_search_test.xml" public static final String CUSTOMER_USER_MAIL = "customer@netgrif.com" @@ -100,13 +100,14 @@ class PetriNetServiceTest { } @Test + @Disabled void processImportAndDelete() { long processRoleCount = processRoleRepository.count() long processCount = petriNetRepository.count() long taskCount = taskRepository.count() - ImportPetriNetEventOutcome testNetOptional = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + ImportPetriNetEventOutcome testNetOptional = importProcess(NET_FILE, superCreator.getLoggedSuper()) assert testNetOptional.getNet() != null assert petriNetRepository.count() == processCount + 1 PetriNet testNet = testNetOptional.getNet() @@ -150,14 +151,112 @@ class PetriNetServiceTest { } @Test + void testVersionsOnImport() { + ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + PetriNet petriNetV2 = outcome.getNet() + assertNotNull(petriNetV2) + assertTrue(petriNetV2.defaultVersion) + Version version = new Version() + version.setMajor(2) + assertTrue(petriNetV2.getVersion() == version) + Thread.sleep(5000) + Optional elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assertTrue(elasticPetriNetV2Optional.isPresent()) + assertTrue(elasticPetriNetV2Optional.get().isDefaultVersion()) + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("4"), superCreator.loggedSuper) + PetriNet petriNetV4 = outcome.getNet() + assertNotNull(petriNetV4) + assertFalse(petriNetService.get(petriNetV2.getObjectId()).isDefaultVersion()) + assertTrue(petriNetV4.isDefaultVersion()) + version = new Version() + version.setMajor(4) + assertTrue(petriNetV4.getVersion() == version) + Thread.sleep(5000) + elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assertFalse(elasticPetriNetV2Optional.get().isDefaultVersion()) + Optional elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) + assertTrue(elasticPetriNetV4Optional.isPresent()) + assertTrue(elasticPetriNetV4Optional.get().isDefaultVersion()) + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper) + PetriNet petriNetV1 = outcome.getNet() + assertNotNull(petriNetV1) + assertTrue(petriNetService.get(petriNetV4.getObjectId()).isDefaultVersion()) + assertFalse(petriNetV1.isDefaultVersion()) + version = new Version() + version.setMajor(1) + assertTrue(petriNetV1.getVersion() == version) + + assertThrows(IllegalArgumentException.class, { + // cannot import already existing version + importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + }) + + petriNetV2.makeDefault() + petriNetV2 = petriNetService.save(petriNetV2).get() + assertTrue(petriNetV2.defaultVersion) + petriNetV4.makeNonDefault() + petriNetV4 = petriNetService.save(petriNetV4).get() + assertFalse(petriNetV4.defaultVersion) + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("5"), superCreator.loggedSuper) + PetriNet petriNetV5 = outcome.getNet() + assertNotNull(petriNetV5) + assertFalse(petriNetService.get(petriNetV2.getObjectId()).defaultVersion) + assertFalse(petriNetService.get(petriNetV4.getObjectId()).defaultVersion) + assertTrue(petriNetV5.defaultVersion) + version = new Version() + version.setMajor(5) + assertTrue(petriNetV5.getVersion() == version) + Thread.sleep(5000) + elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assertFalse(elasticPetriNetV2Optional.get().defaultVersion) + elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) + assertFalse(elasticPetriNetV4Optional.get().defaultVersion) + Optional elasticPetriNetV5Optional = elasticPetriNetRepository.findById(petriNetV5.stringId) + assertTrue(elasticPetriNetV5Optional.isPresent()) + assertTrue(elasticPetriNetV5Optional.get().defaultVersion) + } + + @Test + void testVersionActiveOnDelete() { + ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper) + PetriNet processV1 = outcome.getNet() + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + PetriNet processV2 = outcome.getNet() + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("3"), superCreator.loggedSuper) + PetriNet processV3 = outcome.getNet() + + assertFalse(petriNetService.get(processV1.getObjectId()).defaultVersion) + assertFalse(petriNetService.get(processV2.getObjectId()).defaultVersion) + assertTrue(petriNetService.get(processV3.getObjectId()).defaultVersion) + + petriNetService.deletePetriNet(processV2.getStringId(), superCreator.loggedSuper) + + assertTrue(petriNetRepository.findById(processV2.getStringId()).isEmpty()) + assertFalse(petriNetService.get(processV1.getObjectId()).defaultVersion) + assertTrue(petriNetService.get(processV3.getObjectId()).defaultVersion) + + petriNetService.deletePetriNet(processV3.getStringId(), superCreator.loggedSuper) + + assertTrue(petriNetRepository.findById(processV3.getStringId()).isEmpty()) + assertTrue(petriNetService.get(processV1.getObjectId()).defaultVersion) + + petriNetService.deletePetriNet(processV1.getStringId(), superCreator.loggedSuper) + + assertTrue(petriNetRepository.findById(processV1.getStringId()).isEmpty()) + } + + @Test + @Disabled void processSearch() { long processCount = petriNetRepository.count() - def user = userService.findUserByUsername(CUSTOMER_USER_MAIL, null) assert user != null && user.isPresent() - petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - petriNetService.importPetriNet(stream(NET_SEARCH_FILE), VersionType.MAJOR, ActorTransformer.toLoggedUser(user.get())) + importProcess(NET_FILE, superCreator.getLoggedSuper()) + importProcess(NET_SEARCH_FILE, ActorTransformer.toLoggedUser(user.get())) assert petriNetRepository.count() == processCount + 2 @@ -209,4 +308,8 @@ class PetriNetServiceTest { search8.setAuthor(author); assert petriNetService.search(search8, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1; } + + private ImportPetriNetEventOutcome importProcess(String filePath, LoggedUser author) { + return petriNetService.importPetriNet(stream(filePath), VersionType.MAJOR, author) + } } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy index 3e7f28bd4d8..c8d55017a17 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy @@ -45,7 +45,7 @@ class NewInitTest { @Test void newInitTest() throws IOException, MissingIconKeyException, MissingPetriNetMetaDataException { petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/nae_1276_Init_value_as_choice.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - Case initTestCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier("new_init_test").stringId, "New init test", "", superCreator.getLoggedSuper()).getCase() + Case initTestCase = workflowService.createCase(petriNetService.getDefaultVersionByIdentifier("new_init_test").stringId, "New init test", "", superCreator.getLoggedSuper()).getCase() assert (initTestCase.dataSet["new_init_multichoice"].value as List).stream().any { it.defaultValue == "Bob" } assert (initTestCase.dataSet["new_init_multichoice"].value as List).stream().any { it.defaultValue == "Alice" } assert (initTestCase.dataSet["old_init_multichoice"].value as List).stream().any { it.defaultValue == "Bob" } diff --git a/application-engine/src/test/resources/change_caseref_value_action_test.xml b/application-engine/src/test/resources/change_caseref_value_action_test.xml index cf908b29fe9..9d600ef99e1 100644 --- a/application-engine/src/test/resources/change_caseref_value_action_test.xml +++ b/application-engine/src/test/resources/change_caseref_value_action_test.xml @@ -29,7 +29,7 @@ caseref: f.caseref; - def net = petriNetService.getNewestVersionByIdentifier("change_value"); + def net = petriNetService.getDefaultVersionByIdentifier("change_value"); def newCase = workflowService.createCase(net.stringId, "", "", userService.transformToLoggedUser(userService.getLoggedOrSystem())).getACase() def newValue = new ArrayList(caseref.value) newValue.add(newCase) @@ -43,7 +43,7 @@ caseref: f.caseref; - def net = petriNetService.getNewestVersionByIdentifier("test"); + def net = petriNetService.getDefaultVersionByIdentifier("test"); def newCase = workflowService.createCase(net.stringId, "", "", userService.transformToLoggedUser(userService.getLoggedOrSystem())).getACase() def newValue = new ArrayList(caseref.value) newValue.add(newCase) diff --git a/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml b/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml index 33794373055..08fe3fd77ea 100644 --- a/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml +++ b/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml @@ -217,7 +217,7 @@ export - def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId + def processId = petriNetService.getDefaultVersionByIdentifier("export_test").stringId def config = new com.netgrif.application.engine.export.domain.ExportDataConfig() config.setDataToExport(["immediate_multichoice","immediate_number", "text"] as LinkedHashSet) exportTasksToFile({it.processId.eq(processId) & it.transitionId.eq("t3")},"src/test/resources/csv/task_mongo_export.csv", config) diff --git a/application-engine/src/test/resources/petriNets/process_version_1_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_1_0_0.xml new file mode 100644 index 00000000000..63594046899 --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_1_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 1.0.0 + PVT + Process Version 1.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_2_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_2_0_0.xml new file mode 100644 index 00000000000..f095c407ae6 --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_2_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 2.0.0 + PVT + Process Version 2.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_3_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_3_0_0.xml new file mode 100644 index 00000000000..fdf75f42944 --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_3_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 3.0.0 + PVT + Process Version 3.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_4_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_4_0_0.xml new file mode 100644 index 00000000000..58e472c139b --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_4_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 4.0.0 + PVT + Process Version 4.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_5_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_5_0_0.xml new file mode 100644 index 00000000000..21b309f9bed --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_5_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 5.0.0 + PVT + Process Version 5.0.0 test + false + diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/common/ResourceNotFoundExceptionCode.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/common/ResourceNotFoundExceptionCode.java index 797b7999d59..a158a4f392b 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/common/ResourceNotFoundExceptionCode.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/common/ResourceNotFoundExceptionCode.java @@ -6,7 +6,8 @@ public enum ResourceNotFoundExceptionCode { DEFAULT_SYSTEM_GROUP_NOT_FOUND("defaultSystemGroupNotFound"), - DEFAULT_USER_GROUP_NOT_FOUND("defaultUserGroupNotFound"); + DEFAULT_USER_GROUP_NOT_FOUND("defaultUserGroupNotFound"), + DEFAULT_PROCESS_NOT_FOUND("defaultProcessNotFound"); private final String key; diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java index bdec2b24c71..1a6fae31bcf 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java @@ -24,6 +24,8 @@ public abstract class ElasticPetriNet { private Version version; + private boolean defaultVersion; + private String uriNodeId; private I18nField title; @@ -38,6 +40,7 @@ public ElasticPetriNet(PetriNet net) { this.id = net.getStringId(); this.identifier = net.getIdentifier(); this.version = net.getVersion(); + this.defaultVersion = net.isDefaultVersion(); this.uriNodeId = net.getUriNodeId(); this.title = this.transformToField(net.getTitle()); this.initials = net.getInitials(); @@ -46,6 +49,7 @@ public ElasticPetriNet(PetriNet net) { public void update(ElasticPetriNet net) { this.version = net.getVersion(); + this.defaultVersion = net.isDefaultVersion(); if (net.getUriNodeId() != null) { this.uriNodeId = net.getUriNodeId(); } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java index 6a0518862d7..565f52c1317 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java @@ -33,7 +33,7 @@ public abstract class PetriNet extends PetriNetObject { @Getter @Setter - private String identifier; //combination of identifier and version must be unique ... maybe use @CompoundIndex? + private String identifier; // todo: combination of identifier and version must be unique ... maybe use @CompoundIndex? @Getter @Setter @@ -76,6 +76,11 @@ public abstract class PetriNet extends PetriNetObject { @Setter private Version version; + @Getter + @Setter + @Indexed + private boolean defaultVersion; + @Getter @Setter private ActorRef author; @@ -149,23 +154,24 @@ public PetriNet() { this.title = new I18nString(""); this.importId = ""; this.version = new Version(); - defaultCaseName = new I18nString(""); - initialized = false; - creationDate = LocalDateTime.now(); - places = new LinkedHashMap<>(); - transitions = new LinkedHashMap<>(); - arcs = new LinkedHashMap<>(); - dataSet = new LinkedHashMap<>(); - roles = new LinkedHashMap<>(); - negativeViewRoles = new LinkedList<>(); - transactions = new LinkedHashMap<>(); - processEvents = new LinkedHashMap<>(); - caseEvents = new LinkedHashMap<>(); - permissions = new HashMap<>(); - userRefs = new HashMap<>(); - functions = new LinkedList<>(); - tags = new HashMap<>(); - pluginDependencies = new HashSet<>(); + this.defaultCaseName = new I18nString(""); + this.initialized = false; + this.creationDate = LocalDateTime.now(); + this.places = new LinkedHashMap<>(); + this.transitions = new LinkedHashMap<>(); + this.arcs = new LinkedHashMap<>(); + this.dataSet = new LinkedHashMap<>(); + this.roles = new LinkedHashMap<>(); + this.negativeViewRoles = new LinkedList<>(); + this.transactions = new LinkedHashMap<>(); + this.processEvents = new LinkedHashMap<>(); + this.caseEvents = new LinkedHashMap<>(); + this.permissions = new HashMap<>(); + this.userRefs = new HashMap<>(); + this.functions = new LinkedList<>(); + this.tags = new HashMap<>(); + this.pluginDependencies = new HashSet<>(); + this.makeNonDefault(); } public PetriNet(PetriNet petriNet) { @@ -176,6 +182,7 @@ public PetriNet(PetriNet petriNet) { this.title = petriNet.getTitle(); this.importId = petriNet.getImportId(); this.version = petriNet.getVersion(); + this.defaultVersion = petriNet.isDefaultVersion(); this.defaultCaseName = petriNet.getDefaultCaseName(); this.defaultCaseNameExpression = petriNet.getDefaultCaseNameExpression(); this.initials = petriNet.getInitials(); @@ -443,6 +450,14 @@ public boolean hasDynamicCaseName() { return defaultCaseNameExpression != null; } + public void makeDefault() { + this.setDefaultVersion(true); + } + + public void makeNonDefault() { + this.setDefaultVersion(false); + } + @Override public String getStringId() { return _id.toString(); diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNetSearch.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNetSearch.java index 3db8891f7c4..72c70199fd0 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNetSearch.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNetSearch.java @@ -20,6 +20,8 @@ public class PetriNetSearch { private String defaultCaseName; + private Boolean defaultVersion; + private String initials; private List group; diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java index 3c5c2d84be6..50dd1f5481d 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java @@ -52,6 +52,12 @@ public void increment(VersionType type) { } } + /** + * Compares this version to the other version + * + * @param other other version to be compared with + * @return 0 if the versions equal, <0 if this is lower than other, >0 if this is higher than other + */ public int compareTo(Version other) { if (this.major != other.major) { return Long.compare(this.major, other.major); @@ -62,6 +68,24 @@ public int compareTo(Version other) { return Long.compare(this.patch, other.patch); } + /** + * Checks if this version is higher than the other + * @param other other version to be compared with + * @return true if this version is higher than the other + */ + public boolean isHigherThan(Version other) { + return compareTo(other) > 0; + } + + /** + * Checks if this version is lower than the other + * @param other other version to be compared with + * @return true if this version is lower than the other + */ + public boolean isLowerThan(Version other) { + return compareTo(other) < 0; + } + @Override public Version clone() { diff --git a/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java b/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java index 7e91f07c13f..4076351e98f 100644 --- a/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java +++ b/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java @@ -60,6 +60,7 @@ public LinkedHashMap getRoles() { return super.getRoles(); } + // todo: delete clone method if not needed // @Override // public PetriNet clone() { // PetriNet clone = new PetriNet();