From f57405f4c6e56792fb9f0a1b83ee04133b8d4a71 Mon Sep 17 00:00:00 2001 From: CHIARAMELLO Marco Date: Thu, 28 May 2020 16:37:41 +0200 Subject: [PATCH 1/2] See #24: new class is introduced to treat cases for which the xmi is impossible, e.g. the ones breaking the xml/rdf consistency. If the case, the json containg the broken rules are written immediately in the cache directory, without any further validation. These cases are then treated as any other when writing the excel reports. --- src/main/java/ocl/OCLEvaluator.java | 14 +- src/main/java/ocl/Profile.java | 18 +- src/main/java/ocl/XMITransformation.java | 20 +- .../java/ocl/util/CheckXMLConsistency.java | 176 ++++++++++++++++++ 4 files changed, 209 insertions(+), 19 deletions(-) create mode 100644 src/main/java/ocl/util/CheckXMLConsistency.java diff --git a/src/main/java/ocl/OCLEvaluator.java b/src/main/java/ocl/OCLEvaluator.java index 16f83c7..6959aef 100644 --- a/src/main/java/ocl/OCLEvaluator.java +++ b/src/main/java/ocl/OCLEvaluator.java @@ -80,7 +80,7 @@ private Map> assessRules(File where) throws IOExc XMITransformation my_transf = new XMITransformation(); HashMap xmi_list = new HashMap<>(); - + cacheDir.mkdirs(); try { my_prep.readZip(where); LOGGER.info("Reordering done!"); @@ -101,7 +101,7 @@ private Map> assessRules(File where) throws IOExc List files = new ArrayList<>(); - cacheDir.mkdirs(); + LOGGER.info("Validator ready"); @@ -313,7 +313,7 @@ private static void write(Document doc, OutputStream out) { * @return * @throws IOException */ - static HashMap getConfig() throws IOException, URISyntaxException { + public static HashMap getConfig() throws IOException, URISyntaxException { HashMap configs = new HashMap<>(); InputStream config = new FileInputStream(System.getenv("VALIDATOR_CONFIG")+File.separator+"config.properties"); Properties properties = new Properties(); @@ -350,9 +350,10 @@ static HashMap getConfig() throws IOException, URISyntaxException if(cacheDir_!=null ){ try{ + configs.put("cacheDir", IOUtils.resolveEnvVars(cacheDir_)+File.separator+"cache"); cacheDir = new File(IOUtils.resolveEnvVars(cacheDir_)+File.separator+"cache"); }catch (Exception e){ - + configs.put("cacheDir",where.getAbsolutePath()+File.separator+"/cache" ); cacheDir= new File(where.getAbsolutePath()+File.separator+"/cache"); } @@ -418,8 +419,9 @@ public static void main(String[] args) { // Read rule details RuleDescriptionParser parser = new RuleDescriptionParser(); HashMap rules = parser.parseRules("config/UMLRestrictionRules.xml"); - + getConfig(); OCLEvaluator evaluator = new OCLEvaluator(); + if(debugMode) LOGGER.info("Validator running in debug mode"); Map> synthesis = evaluator.assessRules(where); @@ -432,7 +434,7 @@ public static void main(String[] args) { evaluator.cleanCache(); - } catch (ParserConfigurationException | IOException | SAXException e){ + } catch (ParserConfigurationException | IOException | SAXException | URISyntaxException e){ e.printStackTrace(); System.exit(-1); } diff --git a/src/main/java/ocl/Profile.java b/src/main/java/ocl/Profile.java index 473c022..b886997 100644 --- a/src/main/java/ocl/Profile.java +++ b/src/main/java/ocl/Profile.java @@ -4,18 +4,18 @@ import java.util.ArrayList; import java.util.List; -class Profile{ - enum Type{ +public class Profile{ + public enum Type{ EQ, TP, SSH, SV, other } - Type type; - String id; - List depOn= new ArrayList<>(); - File file; - String xml_name; - List DepToBeReplaced= new ArrayList<>(); - List modelProfile = new ArrayList<>(); + public Type type; + public String id; + public List depOn= new ArrayList<>(); + public File file; + public String xml_name; + public List DepToBeReplaced= new ArrayList<>(); + public List modelProfile = new ArrayList<>(); Profile(Type type, String id, List deps, File file, String xmlName, List modelProfile){ this.type = type; diff --git a/src/main/java/ocl/XMITransformation.java b/src/main/java/ocl/XMITransformation.java index e55d8c7..541b39c 100644 --- a/src/main/java/ocl/XMITransformation.java +++ b/src/main/java/ocl/XMITransformation.java @@ -14,6 +14,7 @@ **/ package ocl; +import ocl.util.CheckXMLConsistency; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.*; @@ -150,11 +151,20 @@ HashMap convertData(HashMap> IGM_CGM, L break; } } - Document merged_xml = createMerge(EQBD,TPBD, getBusinessProcess(key.xml_name), key, EQ, SSH, TP,defaultBDIds); - resulting_xmi = createXmi(merged_xml); - LOGGER.info("Transformed:"+key.xml_name); + CheckXMLConsistency xmlConsistency = new CheckXMLConsistency(EQ,TP,SSH,key, sv_sn.get(0)); + + if(!xmlConsistency.isExcluded()){ + Document merged_xml = createMerge(EQBD,TPBD, getBusinessProcess(key.xml_name), key, EQ, SSH, TP,defaultBDIds); + resulting_xmi = createXmi(merged_xml); + LOGGER.info("Transformed:"+key.xml_name); + + xmi_map.put(sv_sn.get(0),resulting_xmi); + } + else{ + LOGGER.info("Xmi not created for "+key.xml_name+". Probably basic xml/rdf consistency is broken."); + } + - xmi_map.put(sv_sn.get(0),resulting_xmi); } catch (Exception e){ @@ -221,6 +231,8 @@ private NodeList getNodeList(File file) throws ParserConfigurationException, IOE return nodeList; } + + /** * * @param eqbd diff --git a/src/main/java/ocl/util/CheckXMLConsistency.java b/src/main/java/ocl/util/CheckXMLConsistency.java new file mode 100644 index 0000000..bc7aa29 --- /dev/null +++ b/src/main/java/ocl/util/CheckXMLConsistency.java @@ -0,0 +1,176 @@ +package ocl.util; + +import com.google.gson.Gson; +import ocl.OCLEvaluator; +import ocl.Profile; + +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +public class CheckXMLConsistency { + + RuleDescriptionParser parser = new RuleDescriptionParser(); + HashMap rules = parser.parseRules("config/UMLRestrictionRules.xml"); + + private boolean isExcluded = false; + private String caseName; + + public boolean isExcluded() { + return isExcluded; + } + + class IDUniqueness{ + Profile.Type type ; + String Object; + String id; + IDUniqueness(Profile.Type type, String Object, String id){ + this.type = type; + this.Object = Object; + this.id=id; + } + } + + List idUniquenessList = new ArrayList<>(); + + /** + * @param EQ + * @param TP + * @param SSH + * @param SV + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + public CheckXMLConsistency(Profile EQ, Profile TP, Profile SSH, Profile SV, String caseName) throws IOException, SAXException, ParserConfigurationException, URISyntaxException { + this.caseName = caseName; + IDUniqueness(EQ,TP, SSH, SV); + } + + /** + * @param EQ + * @param TP + * @param SSH + * @param SV + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + public void IDUniqueness(Profile EQ, Profile TP, Profile SSH, Profile SV) throws IOException, SAXException, ParserConfigurationException, URISyntaxException { + checkIDUniqueness(EQ); + checkIDUniqueness(TP); + checkIDUniqueness(SSH); + checkIDUniqueness(SV); + List results = new ArrayList<>(); + String ruleName = "IDuniqueness"; + String severity = rules.get(ruleName) == null ? "UNKOWN" : rules.get(ruleName).getSeverity(); + int level = rules.get(ruleName) == null ? 0 : rules.get(ruleName).getLevel(); + String specificMessage= rules.get(ruleName) == null? "mRID (rdf:ID or rdf:about) not unique within model":null; + for(IDUniqueness idUniqueness:idUniquenessList){ + EvaluationResult evaluationResult = new EvaluationResult(severity, + ruleName, + level, + idUniqueness.id, + idUniqueness.type.toString()+"."+idUniqueness.Object, + null, specificMessage + ); + results.add(evaluationResult); + } + writeJsonResults(results); + } + + /** + * @param profile + * @throws ParserConfigurationException + * @throws SAXException + * @throws IOException + */ + public void checkIDUniqueness(Profile profile) throws ParserConfigurationException, SAXException, IOException { + Set ids = new HashSet(); + for (Node node : convertToArray(getNodeList(profile))) { + if(!StringUtils.isEmpty(node.getLocalName())){ + String id = node.getAttributes().item(0).getNodeValue().replace("#",""); + if (ids.contains(id)){ + idUniquenessList.add(new IDUniqueness(profile.type,node.getNodeName(), id )); + isExcluded = true; + } + ids.add(id); + } + } + ids = null; + } + + + public void writeJsonResults(List results) throws IOException, URISyntaxException { + + File cachedir = new File(OCLEvaluator.getConfig().get("cacheDir")); + OutputStream zipout = Files.newOutputStream(Paths.get(cachedir.getAbsolutePath()+File.separator+caseName+".json.zip")); + ZipOutputStream zipOutputStream = new ZipOutputStream(zipout); + String json = new Gson().toJson(results); + ZipEntry entry_ = new ZipEntry(caseName + ".xmi.json"); // The name + zipOutputStream.putNextEntry(entry_); + zipOutputStream.write(json.getBytes()); + zipOutputStream.closeEntry(); + zipOutputStream.close(); + } + + /** + * + * @param profile + * @return + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + private NodeList getNodeList(Profile profile) throws IOException, SAXException, ParserConfigurationException { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + builderFactory.setNamespaceAware(true); + DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder(); + Document document = null; + ZipFile zip = new ZipFile(new File(profile.file.getAbsolutePath())); + Enumeration entries = zip.entries(); + while (entries.hasMoreElements()){ + ZipEntry entry = entries.nextElement(); + InputStream xmlStream = zip.getInputStream(entry); + document = documentBuilder.parse(xmlStream); + xmlStream.close(); + } + NodeList nodeList = document.getDocumentElement().getChildNodes(); + return nodeList; + + } + + /** + * + * @param list + * @return + */ + private Node[] convertToArray(NodeList list) + { + int length = list.getLength(); + Node[] copy = new Node[length]; + + for (int n = 0; n < length; ++n) + copy[n] = list.item(n); + + return copy; + } + +} From 51f30c7af53e91a8f88822f670898997c2be2ef5 Mon Sep 17 00:00:00 2001 From: CHIARAMELLO Marco Date: Fri, 29 May 2020 11:55:38 +0200 Subject: [PATCH 2/2] See #24: minor bug fix --- src/main/java/ocl/util/CheckXMLConsistency.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/ocl/util/CheckXMLConsistency.java b/src/main/java/ocl/util/CheckXMLConsistency.java index bc7aa29..bd77f2b 100644 --- a/src/main/java/ocl/util/CheckXMLConsistency.java +++ b/src/main/java/ocl/util/CheckXMLConsistency.java @@ -93,7 +93,8 @@ public void IDUniqueness(Profile EQ, Profile TP, Profile SSH, Profile SV) throws ); results.add(evaluationResult); } - writeJsonResults(results); + if(results.size()!=0) + writeJsonResults(results); } /**