com.netgrif.application.engine.petrinet.service.PetriNetService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of application-engine Show documentation
Show all versions of application-engine Show documentation
System provides workflow management functions including user, role and data management.
package com.netgrif.application.engine.petrinet.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.netgrif.application.engine.auth.domain.LoggedUser;
import com.netgrif.application.engine.auth.service.interfaces.IUserService;
import com.netgrif.application.engine.configuration.properties.CacheProperties;
import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService;
import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService;
import com.netgrif.application.engine.history.domain.petrinetevents.DeletePetriNetEventLog;
import com.netgrif.application.engine.history.domain.petrinetevents.ImportPetriNetEventLog;
import com.netgrif.application.engine.history.domain.taskevents.TaskEventLog;
import com.netgrif.application.engine.history.service.IHistoryService;
import com.netgrif.application.engine.importer.service.Importer;
import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException;
import com.netgrif.application.engine.ldap.service.interfaces.ILdapGroupRefService;
import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService;
import com.netgrif.application.engine.petrinet.domain.PetriNet;
import com.netgrif.application.engine.petrinet.domain.PetriNetSearch;
import com.netgrif.application.engine.petrinet.domain.Transition;
import com.netgrif.application.engine.petrinet.domain.VersionType;
import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.Action;
import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.FieldActionsRunner;
import com.netgrif.application.engine.petrinet.domain.events.EventPhase;
import com.netgrif.application.engine.petrinet.domain.events.ProcessEventType;
import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository;
import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException;
import com.netgrif.application.engine.petrinet.domain.version.Version;
import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService;
import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService;
import com.netgrif.application.engine.petrinet.service.interfaces.IUriService;
import com.netgrif.application.engine.petrinet.web.responsebodies.*;
import com.netgrif.application.engine.rules.domain.facts.NetImportedFact;
import com.netgrif.application.engine.rules.service.interfaces.IRuleEngine;
import com.netgrif.application.engine.workflow.domain.Case;
import com.netgrif.application.engine.workflow.domain.FileStorageConfiguration;
import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome;
import com.netgrif.application.engine.workflow.service.interfaces.IEventService;
import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService;
import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.FileSystemResource;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.inject.Provider;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService.transformToReference;
@Slf4j
@Service
public class PetriNetService implements IPetriNetService {
@Autowired
private IProcessRoleService processRoleService;
@Autowired
private PetriNetRepository repository;
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private FileStorageConfiguration fileStorageConfiguration;
@Autowired
private IRuleEngine ruleEngine;
@Autowired
private IWorkflowService workflowService;
@Autowired
private INextGroupService groupService;
@Autowired
private Provider importerProvider;
@Autowired
private FieldActionsRunner actionsRunner;
@Autowired(required = false)
private ILdapGroupRefService ldapGroupService;
@Autowired
private IFieldActionsCacheService functionCacheService;
@Autowired
private IUserService userService;
@Autowired
private IEventService eventService;
@Autowired
private IHistoryService historyService;
@Autowired
private CacheManager cacheManager;
@Autowired
private CacheProperties cacheProperties;
@Resource
private IPetriNetService self;
@Autowired
private IElasticPetriNetMappingService petriNetMappingService;
@Autowired
private IUriService uriService;
private IElasticPetriNetService elasticPetriNetService;
@Autowired
public void setElasticPetriNetService(IElasticPetriNetService elasticPetriNetService) {
this.elasticPetriNetService = elasticPetriNetService;
}
protected Importer getImporter() {
return importerProvider.get();
}
@Override
public void evictAllCaches() {
requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetById()), cacheProperties.getPetriNetById()).clear();
requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetNewest()), cacheProperties.getPetriNetNewest()).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.getPetriNetCache()), cacheProperties.getPetriNetCache()).evict(net.getObjectId());
requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetByIdentifier()), cacheProperties.getPetriNetByIdentifier()).evict(net.getIdentifier() + net.getVersion().toString());
}
/**
* Get read only Petri net.
*/
@Override
@Cacheable(value = "petriNetCache")
public PetriNet get(ObjectId petriNetId) {
Optional optional = repository.findById(petriNetId.toString());
if (optional.isEmpty()) {
throw new IllegalArgumentException("Petri net with id [" + petriNetId + "] not found");
}
return optional.get();
}
@Override
public List get(Collection petriNetIds) {
return petriNetIds.stream().map(id -> self.get(id)).collect(Collectors.toList());
}
@Override
public List get(List petriNetIds) {
return self.get(petriNetIds.stream().map(ObjectId::new).collect(Collectors.toList()));
}
@Override
public PetriNet clone(ObjectId petriNetId) {
return self.get(petriNetId).clone();
}
@Override
@Deprecated
public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException {
return importPetriNet(xmlFile, VersionType.valueOf(releaseType.trim().toUpperCase()), author, uriService.getRoot().getStringId());
}
@Override
@Deprecated
public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser author, String uriNodeId) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException {
return importPetriNet(xmlFile, VersionType.valueOf(releaseType.trim().toUpperCase()), author, uriNodeId);
}
@Override
public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException {
return importPetriNet(xmlFile, releaseType, author, uriService.getRoot().getStringId());
}
@Override
public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, Map params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException {
return importPetriNet(xmlFile, releaseType, author, uriService.getRoot().getStringId(), params);
}
@Override
public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, String uriNodeId) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException {
return importPetriNet(xmlFile, releaseType, author, uriNodeId, new HashMap<>());
}
@Override
public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, String uriNodeId, 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()) {
return outcome;
}
PetriNet net = imported.get();
net.setUriNodeId(uriNodeId);
PetriNet existingNet = getNewestVersionByIdentifier(net.getIdentifier());
if (existingNet != null) {
net.setVersion(existingNet.getVersion());
net.incrementVersion(releaseType);
}
processRoleService.saveAll(net.getRoles().values());
net.setAuthor(author.transformToAuthor());
functionCacheService.cachePetriNetFunctions(net);
Path savedPath = getImporter().saveNetFile(net, 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());
outcome.setOutcomes(eventService.runActions(net.getPreUploadActions(), null, Optional.empty(), params));
evaluateRules(net, EventPhase.PRE);
historyService.save(new ImportPetriNetEventLog(null, EventPhase.PRE, net.getObjectId()));
save(net);
outcome.setOutcomes(eventService.runActions(net.getPostUploadActions(), null, Optional.empty(), params));
evaluateRules(net, EventPhase.POST);
historyService.save(new ImportPetriNetEventLog(null, EventPhase.POST, net.getObjectId()));
addMessageToOutcome(net, ProcessEventType.UPLOAD, outcome);
outcome.setNet(imported.get());
return outcome;
}
private ImportPetriNetEventOutcome addMessageToOutcome(PetriNet net, ProcessEventType type, ImportPetriNetEventOutcome outcome) {
if (net.getProcessEvents().containsKey(type)) {
outcome.setMessage(net.getProcessEvents().get(type).getMessage());
}
return outcome;
}
protected void evaluateRules(PetriNet net, EventPhase phase) {
int rulesExecuted = ruleEngine.evaluateRules(net, new NetImportedFact(net.getStringId(), phase));
if (rulesExecuted > 0) {
save(net);
}
}
@Override
public Optional save(PetriNet petriNet) {
petriNet.initializeArcs();
this.evictCache(petriNet);
petriNet = repository.save(petriNet);
try {
elasticPetriNetService.indexNow(this.petriNetMappingService.transform(petriNet));
} catch (Exception e) {
log.error("Indexing failed [" + petriNet.getStringId() + "]", e);
}
return Optional.of(petriNet);
}
@Override
@Cacheable(value = "petriNetById")
public PetriNet getPetriNet(String id) {
Optional net = repository.findById(id);
if (net.isEmpty()) {
throw new IllegalArgumentException("No Petri net with id: " + id + " was found.");
}
net.get().initializeArcs();
return net.get();
}
@Override
@Cacheable(value = "petriNetByIdentifier", key = "#identifier+#version.toString()", unless = "#result == null")
public PetriNet getPetriNet(String identifier, Version version) {
PetriNet net = repository.findByIdentifierAndVersion(identifier, version);
if (net == null) {
return null;
}
net.initializeArcs();
return net;
}
@Override
public List getByIdentifier(String identifier) {
List nets = repository.findAllByIdentifier(identifier);
nets.forEach(PetriNet::initializeArcs);
return nets;
}
@Override
public List findAllByUriNodeId(String uriNodeId) {
List nets = elasticPetriNetService.findAllByUriNodeId(uriNodeId);
nets.forEach(PetriNet::initializeArcs);
return nets;
}
@Override
public List findAllById(List ids) {
return StreamSupport.stream(repository.findAllById(ids).spliterator(), false).collect(Collectors.toList());
}
@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()) {
return null;
}
return nets.get(0);
}
/**
* Determines which of the provided Strings are identifiers of {@link PetriNet}s uploaded in the system.
*
* @param identifiers a list of Strings that represent potential PetriNet identifiers
* @return a list containing a subset of the input strings that correspond to identifiers of PetriNets that are present in the system
*/
@Override
public List getExistingPetriNetIdentifiersFromIdentifiersList(List identifiers) {
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(Criteria.where("identifier").in(identifiers)),
Aggregation.group("identifier"),
Aggregation.project("identifier").and("identifier").previousOperation()
);
AggregationResults> groupResults = mongoTemplate.aggregate(
agg,
PetriNet.class,
TypeFactory.defaultInstance().constructType(new TypeReference
© 2015 - 2025 Weber Informatics LLC | Privacy Policy