Java tutorial
/* Copyright 2014 Universidad Politcnica de Madrid - Center for Open Middleware (http://www.centeropenmiddleware.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.c4om.autoconf.ulysses.extra.svrlmultipathinterpreter; import static com.c4om.utils.xmlutils.JDOMUtils.loadJDOMDocumentFromFile; import static com.c4om.utils.xmlutils.XMLLibsShortcuts.performJAXENXPath; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.Namespace; import org.jdom2.Text; import org.jdom2.filter.Filters; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; import com.c4om.utils.xmlutils.constants.AutoconfXMLConstants; import com.c4om.utils.xmlutils.constants.CommonXMLConstants; /** * Main class of the application, which invokes all the process. * * @author Pablo Alonso Rodriguez (Center for Open Middleware) * */ public class SVRLMultipathInterpreterMain { /** * Default value for the settings property with the prefix for metamodel attributes */ private static final String DEFAULT_VALUE_METAMODEL_ATTRIBUTES_PREFIX = "mct"; /** * Key for the settings property with the prefix for metamodel attributes */ private static final String PROPERTY_KEY_METAMODEL_ATTRIBUTES_PREFIX = "metamodelAttributesPrefix"; /** * Key for the settings property with the XPath namespaces list */ private static final String PROPERTY_KEY_NAMESPACES_LIST = "namespacesList"; //TODO PartialNodeGenerator should access this cache. /** * A cache for documents */ private final Map<String, Document> documentCache = new HashMap<>(); /** * Path to the current runtime configuration */ private String pathToConfiguration; /** * Path to the metamodel folder */ private String pathToMetamodel; /** * Namespaces to be used at XPath queries */ private List<Namespace> xpathNamespaces; /** * Prefix for some attributes of the metamodel (typically, 'mct') */ private String metamodelAttributesPrefix; /** * Constructor * @param pathToConfiguration The path to the runtime configuration * @param pathToMetamodel The path to the metamodel * @param pathToSettings the path to the settings */ public SVRLMultipathInterpreterMain(String pathToConfiguration, String pathToMetamodel, String pathToSettings) { this.pathToMetamodel = pathToMetamodel; this.pathToConfiguration = pathToConfiguration; InputStream settingsIS = getClass().getClassLoader().getResourceAsStream(pathToSettings); if (settingsIS == null) { try { settingsIS = new FileInputStream(pathToSettings); } catch (IOException e) { throw new IllegalArgumentException("Settings file not found or not accessible", e); } } this.xpathNamespaces = new ArrayList<>(); Properties settings = new Properties(); try { settings.load(settingsIS); } catch (IOException e) { throw new IllegalArgumentException("Settings file not loadable"); } String metamodelAttributesPrefix = settings.getProperty(PROPERTY_KEY_METAMODEL_ATTRIBUTES_PREFIX, DEFAULT_VALUE_METAMODEL_ATTRIBUTES_PREFIX); this.metamodelAttributesPrefix = metamodelAttributesPrefix; String namespacesListSetting = settings.getProperty(PROPERTY_KEY_NAMESPACES_LIST); if (namespacesListSetting != null) { String[] namespacesListSettingSplit = namespacesListSetting.split(";"); Pattern pattern = Pattern.compile("^(?<prefix>[^:]+):(?<uri>.+)$"); for (String pair : namespacesListSettingSplit) { Matcher matcher = pattern.matcher(pair); if (!matcher.matches()) { throw new IllegalArgumentException("Pair '" + pair + "' does not follow the specified syntax."); } String prefix = matcher.group("prefix"); String uri = matcher.group("uri"); xpathNamespaces.add(Namespace.getNamespace(prefix, uri)); } } } /** * This method gets a list of all the paths occurring in <code>//svrl:failed-assert/svrl:text</code>, as expected by SVRLMultipathInterpreterMain. * @param svrlDocument The SVRL document, as a JDOM2 {@link Document} * @return a {@link List} of {@link String}, with the paths. */ private List<String> getPathsFromDocument(Document svrlDocument) { List<String> results = new ArrayList<>(); List<Namespace> namespaces = Arrays.asList(CommonXMLConstants.NAMESPACE_SVRL); List<Text> resultingTexts = performJAXENXPath("//svrl:failed-assert/svrl:text/text()", svrlDocument, Filters.text(), namespaces); for (Text resultingText : resultingTexts) { for (String untrimmedResult : resultingText.getText().split("[\r\n]+")) { String trimmedResult = untrimmedResult.trim(); if (!trimmedResult.equals("")) { results.add(trimmedResult); } } } return results; } /** * This method performs the actual svrl interpretation process (which constitutes the objective solving process). * @param svrlDocument the SVRL document (i.e. the objective description) * @return the svrl interpreter report (i.e. the objective solution) * @throws JDOMException if there are XML problems * @throws IOException if there are I/O problems. */ public Document interpret(Document svrlDocument) throws JDOMException, IOException { Element resultRootElement = new Element("report", AutoconfXMLConstants.NAMESPACE_SVRL_INTERPETER_REPORT); Document result = new Document(resultRootElement); List<String> pathsListRepeated = getPathsFromDocument(svrlDocument); PathGroupsGenerator pathGroupsGenerator = new PathGroupsGenerator(); List<PathGroup> pathGroups = pathGroupsGenerator.getPathGroups(pathsListRepeated); PartialNodeGenerator partialNodeGenerator = new PartialNodeGenerator(this.xpathNamespaces, this.pathToConfiguration, this.pathToMetamodel, this.metamodelAttributesPrefix); for (PathGroup pathGroup : pathGroups) { Element currentDiscrepancyElement = new Element("discrepancy", AutoconfXMLConstants.NAMESPACE_SVRL_INTERPETER_REPORT); Element currentInterestingPathsElement = new Element("interestingPaths", AutoconfXMLConstants.NAMESPACE_SVRL_INTERPETER_REPORT); // '/.[text()=something]' tokens should not be used to look for elements at the metamodel and/or search paths, as text DOES NOT identify elements according to our convention. String fixedBasePath = pathGroup.getBasePath().replaceAll("\\]/\\.\\[(?<bracketContent>[^\\]]+)\\]$", "]"); currentInterestingPathsElement.setAttribute("search-path", "doc('" + pathGroup.getDocumentPath() + "')" + fixedBasePath); currentDiscrepancyElement.addContent(currentInterestingPathsElement); Element suggestedPartialNodeElement = new Element("suggestedPartialNode", AutoconfXMLConstants.NAMESPACE_SVRL_INTERPETER_REPORT); currentDiscrepancyElement.addContent(suggestedPartialNodeElement); Element partialNode = partialNodeGenerator.generatePartialNode(pathGroup); suggestedPartialNodeElement.addContent(partialNode); File metamodelDocFile = new File(pathGroup.getDocumentPath()); if (!metamodelDocFile.isAbsolute()) { metamodelDocFile = new File(this.pathToMetamodel, pathGroup.getDocumentPath()); } List<Element> metamodelSuggestedNodeList; try { Document metamodelDoc = documentCache.get(metamodelDocFile.getAbsolutePath()); if (metamodelDoc == null) { metamodelDoc = loadJDOMDocumentFromFile(metamodelDocFile); documentCache.put(metamodelDocFile.getAbsolutePath(), metamodelDoc); } metamodelSuggestedNodeList = performJAXENXPath(fixedBasePath, metamodelDoc); } catch (IOException e) { metamodelSuggestedNodeList = Collections.emptyList(); } Element metamodelSuggestionsElement = new Element("metamodelSuggestions", AutoconfXMLConstants.NAMESPACE_SVRL_INTERPETER_REPORT); for (Element metamodelSuggestedNode : metamodelSuggestedNodeList) { metamodelSuggestionsElement.addContent(metamodelSuggestedNode.clone()); } currentDiscrepancyElement.addContent(metamodelSuggestionsElement); resultRootElement.addContent(currentDiscrepancyElement); } return result; } /** * Main method, invoked when the application starts * @param args command-line arguments. First is path to svrl document, second is the path to the configuration, third is the path to the metamodel */ public static void main(String[] args) throws Exception { SVRLMultipathInterpreterMain multipathInterpreter = new SVRLMultipathInterpreterMain(args[1], args[2], args[3]); Document svrlDocument = loadJDOMDocumentFromFile(new File(args[0])); Document result = multipathInterpreter.interpret(svrlDocument); XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); System.out.println(outputter.outputString(result)); } }