de.viadee.bpm.vPAV.AbstractRunner Maven / Gradle / Ivy
/**
* Copyright © 2017, viadee Unternehmensberatung GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the viadee Unternehmensberatung GmbH.
* 4. Neither the name of the viadee Unternehmensberatung GmbH nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.viadee.bpm.vPAV;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import de.viadee.bpm.vPAV.config.model.Rule;
import de.viadee.bpm.vPAV.config.reader.ConfigReaderException;
import de.viadee.bpm.vPAV.config.reader.XmlConfigReader;
import de.viadee.bpm.vPAV.output.IssueOutputWriter;
import de.viadee.bpm.vPAV.output.JsOutputWriter;
import de.viadee.bpm.vPAV.output.JsonOutputWriter;
import de.viadee.bpm.vPAV.output.OutputWriterException;
import de.viadee.bpm.vPAV.output.RuleSetOutputWriter;
import de.viadee.bpm.vPAV.output.XmlOutputWriter;
import de.viadee.bpm.vPAV.processing.BpmnModelDispatcher;
import de.viadee.bpm.vPAV.processing.ConfigItemNotFoundException;
import de.viadee.bpm.vPAV.processing.model.data.CheckerIssue;
public abstract class AbstractRunner {
private static Logger logger = Logger.getLogger(AbstractRunner.class.getName());
private static FileScanner fileScanner;
private static OuterProcessVariablesScanner variableScanner;
private static Collection issues;
private static Collection filteredIssues;
private static Map fileMapping = createFileFolderMapping();
private static ArrayList allOutputFilesArray = createAllOutputFilesArray();
private static boolean isExecuted = false;
/**
* Main method which represents lifecycle of the validation process Calls main functions
*/
public static void viadeeProcessApplicationValidator() {
// 1
final Map rules = readConfig();
// 2
scanClassPath(rules);
// 3
getProcessVariables();
// 4
createIssues(rules);
// 5
removeIgnoredIssues();
// 6
writeOutput(filteredIssues);
// 7
copyFiles();
logger.info("BPMN validation successful completed");
}
/**
* 1) If local_ruleSet doesn't exist, then load default_RuleSet 2) If local_ruleSet exist and parent is deactivated
* then override deactivatedRules with local_ruleSet 3) If local_ruleSet exist and parent is activated then override
* deactivatedRules with parent_ruleSet and then override with local_ruleSet
*
* write effectiveRuleSet to vPAV folder
*
* @return Map(String, Rule) ruleSet
*/
private static Map readConfig() {
createBaseFolder();
Map rules = new XmlConfigReader().getDeactivatedRuleSet();
final RuleSetOutputWriter ruleSetOutputWriter = new RuleSetOutputWriter();
try {
if (new File(ConstantsConfig.TEST_BASEPATH + ConstantsConfig.RULESET).exists()) {
Map localRule = new XmlConfigReader().read(ConstantsConfig.RULESET);
if (localRule.containsKey(ConstantsConfig.HASPARENTRULESET)
&& localRule.get(ConstantsConfig.HASPARENTRULESET).isActive()) {
rules = mergeRuleSet(rules, new XmlConfigReader().read(ConstantsConfig.RULESETPARENT));
rules = mergeRuleSet(rules, localRule);
} else {
rules = mergeRuleSet(rules, localRule);
}
} else {
rules = new XmlConfigReader().read(ConstantsConfig.RULESETDEFAULT);
}
ruleSetOutputWriter.write(rules);
RuntimeConfig.getInstance().addActiveRules(rules);
} catch (final ConfigReaderException | OutputWriterException e) {
throw new RuntimeException("Config file could not be read or written");
}
rules.remove(ConstantsConfig.HASPARENTRULESET);
return rules;
}
/**
* merges ruleSets according to inheritance hierarchy (Deactivated < global < default < local)
*
* @param parentRules
* Basis RuleSet which will be overwritten
* @param childRules
* New RuleSet
* @return Map(String, Rule) finalRules merged ruleSet
*/
private static Map mergeRuleSet(final Map parentRules,
final Map childRules) {
final Map finalRules = new HashMap<>();
finalRules.putAll(parentRules);
finalRules.putAll(childRules);
return finalRules;
}
/**
* Initializes the fileScanner with the current set of rules
*
* @param rules
* Map of rules
*/
private static void scanClassPath(Map rules) {
fileScanner = new FileScanner(rules);
}
/**
* Initializes the variableScanner to scan and read outer process variables with the current javaResources
*/
private static void getProcessVariables() {
variableScanner = new OuterProcessVariablesScanner(fileScanner.getJavaResourcesFileInputStream());
readOuterProcessVariables(variableScanner);
}
/**
* Creates the list of issues found for a given model and ruleSet Throws a RuntimeException if errors are found, so
* automated builds in a CI/CD pipeline will fail
*
* @param rules
* Map of rules
* @throws RuntimeException
* Config item couldn't be read
*/
private static void createIssues(Map rules) throws RuntimeException {
issues = checkModels(rules, fileScanner, variableScanner);
}
/**
* Removes whitelisted issues from the list of issues found
*
* @throws RuntimeException
* Ignored issues couldn't be read successfully
*/
private static void removeIgnoredIssues() throws RuntimeException {
filteredIssues = filterIssues(issues);
}
/**
* Write output files (xml / json / js)
*
* @param filteredIssues
* List of filteredIssues
* @throws RuntimeException
* Abort if writer can not be instantiated
*/
private static void writeOutput(final Collection filteredIssues) throws RuntimeException {
if (filteredIssues.size() > 0) {
final IssueOutputWriter xmlOutputWriter = new XmlOutputWriter();
final IssueOutputWriter jsonOutputWriter = new JsonOutputWriter();
final IssueOutputWriter jsOutputWriter = new JsOutputWriter();
try {
xmlOutputWriter.write(filteredIssues);
jsonOutputWriter.write(filteredIssues);
jsOutputWriter.write(filteredIssues);
} catch (final OutputWriterException e) {
throw new RuntimeException("Output couldn't be written");
}
} else {
// 6a if no issues, then delete files if exists
ArrayList validationFiles = new ArrayList();
validationFiles.add(Paths.get(ConstantsConfig.VALIDATION_JS_OUTPUT));
validationFiles.add(Paths.get(ConstantsConfig.VALIDATION_JSON_OUTPUT));
validationFiles.add(Paths.get(ConstantsConfig.VALIDATION_XML_OUTPUT));
deleteFiles(validationFiles);
final IssueOutputWriter jsOutputWriter = new JsOutputWriter();
try {
jsOutputWriter.write(filteredIssues);
} catch (OutputWriterException e) {
throw new RuntimeException("JavaScript File couldn't be written");
}
}
}
/**
* Create Base folders
*
* @throws RuntimeException
* Folders couldn't be created
*/
private static void createBaseFolder() throws RuntimeException {
createvPAVFolder();
createImgFolder();
createCssFolder();
createJsFolder();
}
/**
* Create vPAV folder
*
*/
private static void createvPAVFolder() {
File vPavDir = new File(ConstantsConfig.VALIDATION_FOLDER);
if (!vPavDir.exists()) {
boolean success = vPavDir.mkdirs();
if (!success) {
throw new RuntimeException("vPav directory does not exist and could not be created");
}
}
}
/**
* Make img folder
*/
private static void createImgFolder() {
File imgDir = new File(ConstantsConfig.IMG_FOLDER);
if (!imgDir.exists()) {
boolean success = imgDir.mkdirs();
if (!success) {
throw new RuntimeException("vPav/img directory does not exist and could not be created");
}
}
}
/**
* Make css folder
*/
private static void createJsFolder() {
File jsDir = new File(ConstantsConfig.JS_FOLDER);
if (!jsDir.exists()) {
boolean success = jsDir.mkdirs();
if (!success)
throw new RuntimeException("vPav/js directory does not exist and could not be created");
}
}
/**
* Make css folder
*/
private static void createCssFolder() {
File cssDir = new File(ConstantsConfig.CSS_FOLDER);
if (!cssDir.exists()) {
boolean success = cssDir.mkdirs();
if (!success)
throw new RuntimeException("vPav/css directory does not exist and could not be created");
}
}
/**
* Delete files from destinations
*
* @param destinations
* List of destinations who will be deleted
*/
private static void deleteFiles(ArrayList destinations) {
for (Path destination : destinations) {
if (destination.toFile().exists())
destination.toFile().delete();
}
}
/**
* Copies all necessary files and deletes outputFiles
*
* @throws RuntimeException
* Files couldn't be copied
*/
private static void copyFiles() throws RuntimeException {
// 7a delete files before copy
ArrayList outputFiles = new ArrayList();
for (String file : allOutputFilesArray)
outputFiles.add(Paths.get(fileMapping.get(file), file));
deleteFiles(outputFiles);
for (String file : allOutputFilesArray)
copyFileToVPAVFolder(file);
}
/**
* Creates ArrayList to hold output files
*
* @return ArrayList allFiles
*/
private static ArrayList createAllOutputFilesArray() {
ArrayList allFiles = new ArrayList();
allFiles.add("bootstrap.min.js");
allFiles.add("bpmn-navigated-viewer.js");
allFiles.add("bpmn.io.viewer.app.js");
allFiles.add("jquery-3.2.1.min.js");
allFiles.add("popper.min.js");
allFiles.add("infoPOM.js");
allFiles.add("bootstrap.min.css");
allFiles.add("viadee.css");
allFiles.add("MarkerStyle.css");
allFiles.add("vPAV.png");
allFiles.add("viadee_Logo.png");
allFiles.add("GitHub.png");
allFiles.add("error.png");
allFiles.add("warning.png");
allFiles.add("info.png");
allFiles.add("success.png");
allFiles.add("validationResult.html");
return allFiles;
}
/**
* Creates Map for files and corresponding folders
*
* @return Map fMap
*/
private static Map createFileFolderMapping() {
Map fMap = new HashMap();
fMap.put("bootstrap.min.js", ConstantsConfig.JS_FOLDER);
fMap.put("bpmn-navigated-viewer.js", ConstantsConfig.JS_FOLDER);
fMap.put("bpmn.io.viewer.app.js", ConstantsConfig.JS_FOLDER);
fMap.put("jquery-3.2.1.min.js", ConstantsConfig.JS_FOLDER);
fMap.put("popper.min.js", ConstantsConfig.JS_FOLDER);
fMap.put("infoPOM.js", ConstantsConfig.JS_FOLDER);
fMap.put("bootstrap.min.css", ConstantsConfig.CSS_FOLDER);
fMap.put("viadee.css", ConstantsConfig.CSS_FOLDER);
fMap.put("MarkerStyle.css", ConstantsConfig.CSS_FOLDER);
fMap.put("vPAV.png", ConstantsConfig.IMG_FOLDER);
fMap.put("viadee_Logo.png", ConstantsConfig.IMG_FOLDER);
fMap.put("GitHub.png", ConstantsConfig.IMG_FOLDER);
fMap.put("error.png", ConstantsConfig.IMG_FOLDER);
fMap.put("warning.png", ConstantsConfig.IMG_FOLDER);
fMap.put("info.png", ConstantsConfig.IMG_FOLDER);
fMap.put("success.png", ConstantsConfig.IMG_FOLDER);
fMap.put("validationResult.html", ConstantsConfig.VALIDATION_FOLDER);
return fMap;
}
/**
* Copies files to vPAV folder
*
* @param file
* File who will be copied to vPAV folder
* @throws RuntimeException
* Files couldn't be written
*/
private static void copyFileToVPAVFolder(String file) throws RuntimeException {
InputStream source = AbstractRunner.class.getClassLoader().getResourceAsStream(file);
Path destination = Paths.get(fileMapping.get(file) + file);
try {
Files.copy(source, destination);
} catch (IOException e) {
throw new RuntimeException("Files couldn't be written");
}
}
/**
* filter issues based on black list
*
* @param issues
* all found issues
* @return filtered issues
* @throws IOException
* Ignored issues couldn't be read successfully
*/
private static Collection filterIssues(final Collection issues)
throws RuntimeException {
Collection filteredIssues;
try {
filteredIssues = getFilteredIssues(issues);
} catch (final IOException e) {
throw new RuntimeException("Ignored issues couldn't be read successfully", e);
}
Collections.sort((List) filteredIssues);
return filteredIssues;
}
/**
* remove false positives from issue collection
*
* @param issues
* collection of issues
* @return filteredIssues
* @throws IOException
* ignoreIssues file doesn't exist
*/
private static Collection getFilteredIssues(Collection issues)
throws IOException {
final Collection filteredIssues = new ArrayList();
filteredIssues.addAll(issues);
final Collection ignoredIssues = collectIgnoredIssues(ConstantsConfig.IGNORE_FILE);
for (final CheckerIssue issue : issues) {
if (ignoredIssues.contains(issue.getId())) {
filteredIssues.remove(issue);
}
}
return filteredIssues;
}
/**
* Read issue ids, that should be ignored
*
* Assumption: Each row is an issue id
*
* @param filePath
* Path of ignoredIssues-file
* @return issue ids
* @throws IOException
* ignoreIssues file doesn't exist
*/
private static Collection collectIgnoredIssues(final String filePath) throws IOException {
final Collection ignoredIssues = new ArrayList();
FileReader fileReader = null;
try {
fileReader = new FileReader(filePath);
} catch (final FileNotFoundException ex) {
logger.info(".ignoreIssues file doesn't exist");
}
if (fileReader != null) {
final BufferedReader bufferedReader = new BufferedReader(fileReader);
String zeile = bufferedReader.readLine();
addIgnoredIssue(ignoredIssues, zeile);
while (zeile != null) {
zeile = bufferedReader.readLine();
addIgnoredIssue(ignoredIssues, zeile);
}
bufferedReader.close();
}
return ignoredIssues;
}
/**
* Check consistency of all models
*
* @param rules
* all rules of ruleSet.xml
* @param beanMapping
* beanMapping if spring context is available
* @param fileScanner
* fileScanner
* @param variableScanner
* variablenScanner
* @return foundIssues
* @throws ConfigItemNotFoundException
* ConfigItem not found
*/
private static Collection checkModels(final Map rules, final FileScanner fileScanner,
final OuterProcessVariablesScanner variableScanner) throws RuntimeException {
final Collection issues = new ArrayList();
for (final String pathToModel : fileScanner.getProcessdefinitions()) {
issues.addAll(checkModel(rules, pathToModel, fileScanner,
variableScanner));
}
JsOutputWriter.finish();
return issues;
}
/**
* Check consistency of a model
*
* @param rules
* all rules of ruleSet.xml
* @param beanMapping
* beanMapping if spring context is available
* @param processdef
* processdefintion
* @param fileScanner
* fileScanner
* @param variableScanner
* variableScanner
* @return modelIssues
* @throws ConfigItemNotFoundException
*/
private static Collection checkModel(final Map rules, final String processdef,
final FileScanner fileScanner,
final OuterProcessVariablesScanner variableScanner) throws RuntimeException {
Collection modelIssues;
try {
modelIssues = BpmnModelDispatcher.dispatch(new File(ConstantsConfig.BASEPATH + processdef),
fileScanner.getDecisionRefToPathMap(), fileScanner.getProcessIdToPathMap(),
variableScanner.getMessageIdToVariableMap(), variableScanner.getProcessIdToVariableMap(),
fileScanner.getResourcesNewestVersions(), rules);
} catch (final ConfigItemNotFoundException e) {
throw new RuntimeException("Config item couldn't be read");
}
return modelIssues;
}
/**
* Scan process variables in external classes, which are not referenced from model
*
* @param scanner
* OuterProcessVariablesScanner
* @throws IOException
* Outer process variables couldn't be read
*/
private static void readOuterProcessVariables(final OuterProcessVariablesScanner scanner)
throws RuntimeException {
try {
scanner.scanProcessVariables();
} catch (final IOException e) {
throw new RuntimeException("Outer process variables couldn't be read: " + e.getMessage());
}
}
/**
* Add ignored issue
*
* @param issues
* Collection of issues
* @param row
* row of file
*/
private static void addIgnoredIssue(final Collection issues, final String row) {
if (row != null && !row.isEmpty() && !row.trim().startsWith("#"))
issues.add(row);
}
public static Set getModelPath() {
return fileScanner.getProcessdefinitions();
}
public static Collection getfilteredIssues() {
return filteredIssues;
}
public static boolean isExecuted() {
return isExecuted;
}
public static void setExecuted(boolean isExecuted) {
AbstractRunner.isExecuted = isExecuted;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy