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 0fb4207abb..273dce5e92 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 @@ -2439,9 +2439,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.getActiveVersionByIdentifier(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 78f640b705..a1b8e7b8db 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.getActiveVersionByIdentifier(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.getActiveVersionByIdentifier(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 651bf31abb..ed89eeb78f 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.getActiveVersionByIdentifier(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.getActiveVersionByIdentifier(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 8050c7ac37..ad32548f84 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 active versions of Petri nets. */ - private String petriNetNewest = "petriNetNewest"; + private String petriNetActive = "petriNetActive"; + + /** + * 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, petriNetActive, + 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 c0a5627de0..aeba0a4e6c 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,7 @@ 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.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 +63,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.getActiveVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER); + if (petriNet == null) { + throw new IllegalStateException("Dashboard item process not found or not active"); + } + 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 95a426e88e..4326840671 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 @@ -9,6 +9,7 @@ import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; 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 +65,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.getActiveVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER); + if (petriNet == null) { + throw new IllegalStateException("Dashboard management process not found or not active"); + } + 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 a8dd005b20..41d53b6f0c 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,15 @@ public interface PetriNetRepository extends MongoRepository, Q */ PetriNet findByIdentifierAndVersion(String identifier, Version version); + /** + * Finds a {@link PetriNet} entity by its identifier and versionActive attribute + * + * @param identifier the unique identifier of the PetriNet. + * @param versionActive if true, the active version will be found, otherwise the inactive version + * @return the {@link PetriNet} entity matching the given identifier and versionActive attribute, or {@code null} if none found. + */ + PetriNet findByIdentifierAndVersionActive(String identifier, boolean versionActive); + /** * 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 a468461636..c3eabbfcf1 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 @@ -7,12 +7,10 @@ import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.ArcImportReference; -import com.netgrif.application.engine.objects.auth.domain.Group; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; 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; @@ -141,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.getPetriNetActive()), cacheProperties.getPetriNetActive()).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.getPetriNetActive()), cacheProperties.getPetriNetActive()).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()); } @@ -179,63 +178,85 @@ 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 newProcess = importedProcess.get(); + PetriNet inactivatedProcess = null; - 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 (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()); + 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())) { + throw new IllegalArgumentException("Only higher versions of process [%s] are allowed to import. The requested version [%s] cannot be imported because the higher version [%s] already exists." + .formatted(newProcess.getIdentifier(), newProcess.getVersion(), existingLatestProcess.getVersion())); } - if (net.getVersion() == null) { - net.setVersion(existingNet.getVersion()); - net.incrementVersion(releaseType); + if (existingLatestProcess != null && existingLatestProcess.isVersionActive()) { + existingLatestProcess.makeInactive(); + inactivatedProcess = existingLatestProcess; + } else { + PetriNet existingActiveProcess = self.getActiveVersionByIdentifier(newProcess.getIdentifier()); + if (existingActiveProcess != null) { + existingActiveProcess.makeInactive(); + inactivatedProcess = existingActiveProcess; + } } - } else if (net.getVersion() == null) { - net.setVersion(new Version()); } + newProcess.makeActive(); - 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()); - publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.POST)); - return outcome; - } - protected void evaluateRules(Event event) { - publisher.publishEvent(event); + if (inactivatedProcess != null) { + doSaveInternal(inactivatedProcess); + } + doSaveInternal(newProcess); + outcome.setOutcomes(eventService.runActions(newProcess.getPostUploadActions(), null, Optional.empty(), params)); + outcome.setNet(importedProcess.get()); + publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.POST)); + return outcome; } @Override public Optional save(PetriNet petriNet) { + return doSaveInternal(petriNet); + } + + protected final Optional doSaveInternal(PetriNet petriNet) { petriNet.initializeArcs(); this.evictCache(petriNet); petriNet = repository.save(petriNet); @@ -243,7 +264,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); @@ -263,6 +284,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; @@ -284,13 +308,26 @@ 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 = "petriNetActive", unless = "#result == null") + public PetriNet getActiveVersionByIdentifier(String identifier) { + if (identifier == null) { return null; } - return nets.getFirst(); + return repository.findByIdentifierAndVersionActive(identifier, true); + } + + @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(); } /** @@ -422,7 +459,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 ? getActiveVersionByIdentifier(identifier) : getPetriNet(identifier, version); return net != null ? transformToReference(net, locale) : new PetriNetReference(); } @@ -554,6 +591,15 @@ public void deletePetriNet(String processId, LoggedUser loggedUser, boolean forc repository.deleteBy_id(petriNet.getObjectId()); evictCache(petriNet); functionCacheService.reloadCachedFunctions(petriNet); + if (petriNet.isVersionActive()) { + PetriNet toBeActivated = self.getLatestVersionByIdentifier(petriNet.getIdentifier()); + if (toBeActivated != null) { + log.debug("The active version was removed. Activating the latest version of the process [{}] with id [{}]...", + toBeActivated.getIdentifier(), toBeActivated.getStringId()); + toBeActivated.makeActive(); + save(toBeActivated); + } + } 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 c6fd966cb5..a1c066b143 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 active 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 active version of the {@link PetriNet} matching the provided identifier or null if not found */ - PetriNet getNewestVersionByIdentifier(String identifier); + PetriNet getActiveVersionByIdentifier(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 93a2618d03..64453b2c15 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 @@ -424,7 +424,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.getActiveVersionByIdentifier("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 44522a2556..6407d1e001 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.getActiveVersionByIdentifier(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 923d17bfa5..c4769d6565 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.getActiveVersionByIdentifier(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 1b996bc60d..5ae423c476 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.getActiveVersionByIdentifier(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 9dd6cea3f5..cfc56b6468 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 @@ -266,7 +266,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.getActiveVersionByIdentifier(FILTER_NET_IDENTIFIER); + if (filterNet == null) { + throw new IllegalStateException("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 1eb921882b..4766834b65 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.getActiveVersionByIdentifier(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.getActiveVersionByIdentifier("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 9fdb0e83f1..c4e9bae29a 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.getActiveVersionByIdentifier(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.getActiveVersionByIdentifier(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.getActiveVersionByIdentifier(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 dab63cbf0f..578ba26f42 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.getActiveVersionByIdentifier("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.getActiveVersionByIdentifier("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 b6b97f5352..7eeebba6a5 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.getActiveVersionByIdentifier(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 15e6138b78..33645198c1 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.getActiveVersionByIdentifier("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.getActiveVersionByIdentifier("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 19b9b76ec8..f0e5464685 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 1c4a7d430a..a222b227b0 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.getPetriNetActive()).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.getPetriNetActive()).get(testNet.getIdentifier()) == null + PetriNet test = petriNetService.getActiveVersionByIdentifier(testNet.getIdentifier()) + assert cacheManager.getCache(cacheProperties.getPetriNetActive()).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 84ce8b5ee0..6c1e17f130 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,6 +34,8 @@ import org.springframework.data.domain.PageRequest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension +import static org.junit.jupiter.api.Assertions.assertThrows + @Disabled @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @@ -46,6 +43,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension 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" @@ -106,7 +104,7 @@ class PetriNetServiceTest { 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() @@ -149,15 +147,107 @@ class PetriNetServiceTest { assert exceptionThrown } + @Test + void testVersionsOnImport() { + ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + PetriNet petriNetV2 = outcome.getNet() + assert petriNetV2 != null + assert petriNetV2.versionActive + Version version = new Version() + version.setMajor(2) + assert petriNetV2.getVersion() == version + Thread.sleep(5000) + Optional elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assert elasticPetriNetV2Optional.isPresent() + assert elasticPetriNetV2Optional.get().isVersionActive() + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("4"), superCreator.loggedSuper) + PetriNet petriNetV4 = outcome.getNet() + assert petriNetV4 != null + assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() + assert petriNetV4.isVersionActive() + version = new Version() + version.setMajor(4) + assert petriNetV4.getVersion() == version + Thread.sleep(5000) + elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assert !elasticPetriNetV2Optional.get().isVersionActive() + Optional elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) + assert elasticPetriNetV4Optional.isPresent() + assert elasticPetriNetV4Optional.get().isVersionActive() + + assertThrows(IllegalArgumentException.class, { + // cannot import with lower version number than the highest + importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper) + }) + assertThrows(IllegalArgumentException.class, { + // cannot import already existing version + importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + }) + + petriNetV2.makeActive() + petriNetV2 = petriNetService.save(petriNetV2).get() + assert petriNetV2.versionActive + petriNetV4.makeInactive() + petriNetV4 = petriNetService.save(petriNetV4).get() + assert !petriNetV4.versionActive + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("5"), superCreator.loggedSuper) + PetriNet petriNetV5 = outcome.getNet() + assert petriNetV5 != null + assert !petriNetService.get(petriNetV2.getObjectId()).versionActive + assert !petriNetService.get(petriNetV4.getObjectId()).versionActive + assert petriNetV5.versionActive + version = new Version() + version.setMajor(5) + assert petriNetV5.getVersion() == version + Thread.sleep(5000) + elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assert !elasticPetriNetV2Optional.get().versionActive + elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) + assert !elasticPetriNetV4Optional.get().versionActive + Optional elasticPetriNetV5Optional = elasticPetriNetRepository.findById(petriNetV5.stringId) + assert elasticPetriNetV5Optional.isPresent() + assert elasticPetriNetV5Optional.get().versionActive + } + + @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() + + assert !petriNetService.get(processV1.getObjectId()).versionActive + assert !petriNetService.get(processV2.getObjectId()).versionActive + assert petriNetService.get(processV3.getObjectId()).versionActive + + petriNetService.deletePetriNet(processV2.getStringId(), superCreator.loggedSuper) + + assert petriNetRepository.findById(processV2.getStringId()).isEmpty() + assert !petriNetService.get(processV1.getObjectId()).versionActive + assert petriNetService.get(processV3.getObjectId()).versionActive + + petriNetService.deletePetriNet(processV3.getStringId(), superCreator.loggedSuper) + + assert petriNetRepository.findById(processV3.getStringId()).isEmpty() + assert petriNetService.get(processV1.getObjectId()).versionActive + + petriNetService.deletePetriNet(processV1.getStringId(), superCreator.loggedSuper) + + assert petriNetRepository.findById(processV1.getStringId()).isEmpty() + } + @Test 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 +299,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 3e7f28bd4d..84d2de4bdc 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.getActiveVersionByIdentifier("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 cf908b29fe..ebaf019330 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.getActiveVersionByIdentifier("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.getActiveVersionByIdentifier("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 3379437305..c019e50ab2 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.getActiveVersionByIdentifier("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 0000000000..6359404689 --- /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 0000000000..f095c407ae --- /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 0000000000..fdf75f4294 --- /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 0000000000..58e472c139 --- /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 0000000000..21b309f9be --- /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/elastic/domain/ElasticPetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java index bdec2b24c7..5f86772a42 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 versionActive; + 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.versionActive = net.isVersionActive(); 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.versionActive = net.isVersionActive(); 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 a8b2fa447c..a2d5627ac5 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 @@ -1,5 +1,6 @@ package com.netgrif.application.engine.objects.petrinet.domain; +import com.netgrif.application.engine.objects.annotations.Indexed; import com.netgrif.application.engine.objects.auth.domain.ActorRef; import com.netgrif.application.engine.objects.petrinet.domain.arcs.Arc; import com.netgrif.application.engine.objects.petrinet.domain.arcs.reference.Referencable; @@ -30,7 +31,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 @@ -72,6 +73,11 @@ public abstract class PetriNet extends PetriNetObject { @Setter private Version version; + @Getter + @Setter + @Indexed + private boolean versionActive; + @Getter @Setter private ActorRef author; @@ -141,22 +147,23 @@ 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<>(); + 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.makeInactive(); } public PetriNet(PetriNet petriNet) { @@ -167,6 +174,7 @@ public PetriNet(PetriNet petriNet) { this.title = petriNet.getTitle(); this.importId = petriNet.getImportId(); this.version = petriNet.getVersion(); + this.versionActive = petriNet.isVersionActive(); this.defaultCaseName = petriNet.getDefaultCaseName(); this.defaultCaseNameExpression = petriNet.getDefaultCaseNameExpression(); this.initials = petriNet.getInitials(); @@ -430,6 +438,14 @@ public boolean hasDynamicCaseName() { return defaultCaseNameExpression != null; } + public void makeActive() { + this.setVersionActive(true); + } + + public void makeInactive() { + this.setVersionActive(false); + } + @Override public String getStringId() { return _id.toString(); 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 3c5c2d84be..50dd1f5481 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 7e91f07c13..4076351e98 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();