package de.uniba.dsg.bpmnspector.schematron; import api.*; import de.uniba.dsg.bpmnspector.common.importer.BPMNProcess; import de.uniba.dsg.bpmnspector.common.util.ConstantHelper; import de.uniba.dsg.bpmnspector.common.util.ResourceUtils; import org.jdom2.Attribute; import org.jdom2.Namespace; import org.jdom2.filter.Filters; import org.jdom2.located.LocatedElement; import org.jdom2.xpath.XPathFactory; import org.jdom2.xpath.XPathHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * This class is resposible for the check of the EXT.002 constraint * * @author Philipp Neugebauer * @author Matthias Geiger * @version 1.0 * */ class Ext002Checker { private final static Logger LOGGER = LoggerFactory.getLogger(Ext002Checker.class.getSimpleName()); private static final String CONSTRAINTNUMBER = "EXT.002"; private final XPathFactory xPathFactory = XPathFactory.instance(); /** * checks, if there are violations of the EXT.002 constraint * * @param process * the process to be checked * @param validationResult * the current validation result of validating process for adding * found violations */ public void checkConstraint002(BPMNProcess process, ValidationResult validationResult) { Map<String, Map<String, Attribute>> nspIdMap = new HashMap<>(); ArrayList<BPMNProcess> allChildren = new ArrayList<>(); process.getAllProcessesRecursively(allChildren); // Add IDs of all processes for(BPMNProcess child : allChildren) { Map<String, Attribute> idsOfChild = getAllIdAttributesInProcess(child); if(nspIdMap.containsKey(child.getNamespace())) { // duplicate found create Violation: idsOfChild.keySet().stream() .filter(key -> nspIdMap.get(child.getNamespace()).containsKey(key)) .forEach(key -> createViolation(nspIdMap.get(child.getNamespace()) .get(key), idsOfChild.get(key), validationResult)); } else { nspIdMap.put(child.getNamespace(),idsOfChild); } } } private void createViolation(Attribute firstAttrib, Attribute secondAttrib, ValidationResult validationResult) { try { Resource firstResource = ResourceUtils .determineAndCreateResourceFromString(firstAttrib.getDocument().getBaseURI(), null); int file1Line = ((LocatedElement) firstAttrib.getParent()).getLine(); int file1Column = ((LocatedElement) secondAttrib.getParent()).getColumn(); String file1XPath = XPathHelper.getAbsolutePath(firstAttrib); Resource secondResource = ResourceUtils .determineAndCreateResourceFromString(secondAttrib.getDocument().getBaseURI(), null); int file2Line = ((LocatedElement) secondAttrib.getParent()).getLine(); int file2Column = ((LocatedElement) secondAttrib.getParent()).getColumn(); String file2XPath = XPathHelper.getAbsolutePath(secondAttrib); Location location = new Location(firstResource, new LocationCoordinate(file1Line, file1Column), file1XPath); Violation violation = new Violation(location, "Resources have id duplicates", CONSTRAINTNUMBER); validationResult.addViolation(violation); Location location2 = new Location(secondResource, new LocationCoordinate(file2Line, file2Column), file2XPath); Violation violation2 = new Violation(location2, "Resources have id duplicates", CONSTRAINTNUMBER); validationResult.addViolation(violation2); LOGGER.info("violation of constraint {} found.", CONSTRAINTNUMBER); } catch (ValidationException e) { throw new IllegalArgumentException("Invalid baseURI detected.", e); } } private Map<String, Attribute> getAllIdAttributesInProcess(BPMNProcess process) { Map<String, Attribute> map = new HashMap<>(); String expStr = "//bpmn:*/@id"; org.jdom2.xpath.XPathExpression<Attribute> exp = xPathFactory.compile(expStr, Filters.attribute(), null, Namespace.getNamespace("bpmn", ConstantHelper.BPMNNAMESPACE)); List<Attribute> attributes = exp.evaluate(process.getProcessAsDoc()); attributes.forEach(x -> map.put(x.getValue(), x)); return map; } }