Java tutorial
package org.gw4e.eclipse.facade; /*- * #%L * gw4e * $Id:$ * $HeadURL:$ * %% * Copyright (C) 2017 gw4e-project * %% * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * #L% */ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.SortedSet; import java.util.Timer; import java.util.TimerTask; import java.util.TreeSet; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.io.FilenameUtils; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchWindow; import org.graphwalker.core.condition.StopCondition; import org.graphwalker.core.condition.VertexCoverage; import org.graphwalker.core.event.EventType; import org.graphwalker.core.event.Observer; import org.graphwalker.core.generator.PathGenerator; import org.graphwalker.core.machine.Context; import org.graphwalker.core.machine.ExecutionContext; import org.graphwalker.core.machine.Machine; import org.graphwalker.core.model.Action; import org.graphwalker.core.model.Builder; import org.graphwalker.core.model.Edge; import org.graphwalker.core.model.Edge.RuntimeEdge; import org.graphwalker.core.model.Element; import org.graphwalker.core.model.Model; import org.graphwalker.core.model.Model.RuntimeModel; import org.graphwalker.core.model.Requirement; import org.graphwalker.core.model.Vertex; import org.graphwalker.core.model.Vertex.RuntimeVertex; import org.graphwalker.dsl.antlr.DslException; import org.graphwalker.dsl.antlr.generator.GeneratorFactory; import org.graphwalker.io.factory.ContextFactory; import org.graphwalker.io.factory.ContextFactoryException; import org.graphwalker.io.factory.dot.DotContextFactory; import org.graphwalker.io.factory.java.JavaContextFactory; import org.graphwalker.io.factory.json.JsonContextFactory; import org.graphwalker.io.factory.yed.YEdContextFactory; import org.graphwalker.java.source.CodeGenerator; import org.graphwalker.java.source.SourceFile; import org.graphwalker.java.source.cache.CacheEntry; import org.graphwalker.java.source.cache.SimpleCache; import org.graphwalker.java.test.IsolatedClassLoader; import org.graphwalker.java.test.Result; import org.graphwalker.java.test.TestExecutionException; import org.graphwalker.java.test.TestExecutor; import org.graphwalker.modelchecker.ContextsChecker; import org.gw4e.eclipse.builder.BuildPolicy; import org.gw4e.eclipse.constant.Constant; import org.gw4e.eclipse.message.MessageUtil; import org.gw4e.eclipse.preferences.PreferenceManager; import org.gw4e.eclipse.wizard.convert.OfflineContext; import com.google.gson.JsonSyntaxException; /** * A facade to GraphWalker apis * */ public class GraphWalkerFacade { /** * Retrieve the graph models contained in the container * * @param container * @param models * @throws CoreException */ public static void getGraphModels(IContainer container, List<IFile> models) throws CoreException { if (!container.exists()) return; IResource[] members = container.members(); for (IResource member : members) { if (member instanceof IContainer) getGraphModels((IContainer) member, models); else if (member instanceof IFile) { IFile file = (IFile) member; if (PreferenceManager.isGraphModelFile(file)) models.add(file); if (PreferenceManager.isGW3ModelFile(file)) models.add(file); if (PreferenceManager.isJSONModelFile(file)) models.add(file); } } } public static final String REQUIREMENT = "Requirement"; public static Set<String> getPropertiesValue(RuntimeModel rmodel, String property) { if (REQUIREMENT.equalsIgnoreCase(property)) { Set<String> modelReq = rmodel.getRequirements().stream().map(req -> req.getKey()) .collect(Collectors.toSet()); Set<String> edgesReq = rmodel.getEdges().stream().map(edge -> { return edge.getRequirements(); }).flatMap(x -> x.stream()).map(req -> req.getKey()).collect(Collectors.toSet()); Set<String> vertexReq = rmodel.getVertices().stream().map(vertex -> { return vertex.getRequirements(); }).flatMap(x -> x.stream()).map(req -> req.getKey()).collect(Collectors.toSet()); modelReq.addAll(edgesReq); modelReq.addAll(vertexReq); return modelReq.stream().distinct().collect(Collectors.toSet()); } Optional<Map.Entry<String, Object>> graphProperty = rmodel.getProperties().entrySet().stream() .filter(entry -> entry.getKey().equalsIgnoreCase(property)).findFirst(); if (graphProperty.isPresent()) return Arrays.asList(String.valueOf(graphProperty.get().getValue())).stream() .collect(Collectors.toSet()); Optional<Map.Entry<String, Object>> edgePropertValue = rmodel.getEdges().stream().map(edge -> { return edge.getProperties(); }).map(p -> { return p.entrySet(); }).flatMap(p -> p.stream()).filter(entry -> entry.getKey().equals(property)).findFirst(); if (edgePropertValue.isPresent()) return Arrays.asList(String.valueOf(edgePropertValue.get().getValue())).stream() .collect(Collectors.toSet()); Optional<Map.Entry<String, Object>> vertextPropertValue = rmodel.getVertices().stream().map(vertex -> { return vertex.getProperties(); }).map(p -> { return p.entrySet(); }).flatMap(p -> p.stream()).filter(entry -> entry.getKey().equals(property)).findFirst(); if (vertextPropertValue.isPresent()) return Arrays.asList(String.valueOf(vertextPropertValue.get().getValue())).stream() .collect(Collectors.toSet()); return null; } /** * Retrieve the graph models contained in a projects list * * @param container * @param models * @throws CoreException * @throws IOException * @throws FileNotFoundException */ public static List<String> getPropertiesForGraphModels(List<IProject> projects) throws CoreException, FileNotFoundException, IOException { List<String> ret = null; List<IFile> files = new ArrayList<IFile>(); for (IProject project : projects) { getGraphModels(project, files); } List<String> all = new ArrayList<String>(); for (IFile model : files) { RuntimeModel rmodel = GraphWalkerFacade.getModel(ResourceManager.toFile(model.getFullPath())); Set set = rmodel.getProperties().keySet(); List<String> edgeProperties = rmodel.getEdges().stream().map(edge -> { return edge.getProperties(); }).map(p -> { return p.keySet(); }).flatMap(x -> x.stream()).distinct().collect(Collectors.toList()); List<String> vertexProperties = rmodel.getVertices().stream().map(vertex -> { return vertex.getProperties(); }).map(p -> { return p.keySet(); }).flatMap(x -> x.stream()).distinct().collect(Collectors.toList()); all.addAll(set); all.addAll(edgeProperties); all.addAll(vertexProperties); ret = all.stream().distinct().filter(x -> !isPrivateProperties(x)).collect(Collectors.toList()); } return ret; } private static List getPrivateProperties() { List<String> all = new ArrayList<String>(); all.add("x"); all.add("y"); all.add("width"); all.add("height"); all.add("gw.vertex.init.script"); return all; } private static boolean isPrivateProperties(String property) { return property == null || property.startsWith("gw.edge.bendpoint.") || property.startsWith("gw4e.elk.") || getPrivateProperties().contains(property); } /** * @param sharedName * @param container * @return * @throws JsonSyntaxException * @throws ContextFactoryException * @throws IOException * @throws CoreException */ public static List<IFile> getSharedGraphModels(String sharedName, IContainer container) throws JsonSyntaxException, ContextFactoryException, IOException, CoreException { List<IFile> ret = new ArrayList<IFile>(); List<IFile> files = new ArrayList<IFile>(); getGraphModels(container, files); for (IFile iFile : files) { File f = ResourceManager.toFile(iFile.getFullPath()); Context c = GraphWalkerFacade.getContext(f.getAbsolutePath()); Set<String> names = c.getModel().getSharedStates(); if (names.contains(sharedName)) ret.add(iFile); } return ret; } /** * Paths are similar of they have the same PathGenerator class and the same * StopCondition class * * @param pg1 * @param pathGenerator2 * @return */ public static boolean similarPathGenerator(PathGenerator<StopCondition> pg1, String pathGenerator2) { PathGenerator<StopCondition> pg2; try { pg2 = GeneratorFactory.parse(pathGenerator2); } catch (Exception e) { ResourceManager.logException(e); return false; } String clazz1 = pg1.getClass().getName(); String clazz2 = pg2.getClass().getName(); if (!clazz1.equals(clazz2)) return false; StopCondition sc1 = pg1.getStopCondition(); StopCondition sc2 = pg2.getStopCondition(); if (!sc1.getClass().getName().equals(sc2.getClass().getName())) return false; return true; } /** * @param pathgenerator1 * @param pathGenerator2 * @return */ public static boolean equalsPathGenerator(PathGenerator<StopCondition> pg1, String pathGenerator2) { if (!similarPathGenerator(pg1, pathGenerator2)) return false; PathGenerator<StopCondition> pg2; try { pg2 = GeneratorFactory.parse(pathGenerator2); } catch (Exception e) { ResourceManager.logException(e); return false; } return pg1.getStopCondition().getValue().equals(pg2.getStopCondition().getValue()); } /** * @param cache * @param file * @return * @throws IOException */ private static boolean isModified(SimpleCache cache, Path file) throws IOException { return !Files.getLastModifiedTime(file).equals(cache.get(file).getLastModifiedTime()); } /** * @param cache * @param file * @return * @throws IOException */ private static boolean isNotGenerated(SimpleCache cache, Path file) throws IOException { return !cache.contains(file) || (!cache.get(file).isGenerated()); } public static String getStartElement(File file) throws IOException { ContextFactory factory = getContextFactory(file.toPath()); List<Context> readContexts = factory.create(file.toPath()); // RuntimeModel model = readContexts.get(0).getModel(); Element startElement = readContexts.get(0).getNextElement(); if (startElement == null) return null; return startElement.getName(); } public static List<Element> getElements(File file) throws IOException { List<Element> elements = getModel(file).getElements(); return elements; } public static RuntimeModel getModel(File file) throws IOException { ContextFactory factory = getContextFactory(file.toPath()); List<Context> readContexts = factory.create(file.toPath()); RuntimeModel model = readContexts.get(0).getModel(); return model; } public static List<String> getVertices(File file) throws IOException { List<RuntimeVertex> vertices = getModel(file).getVertices(); List<String> ret = vertices.stream().map(vertex -> vertex.getName()).collect(Collectors.toList()); return ret; } public static List<String> getEdges(File file) throws IOException { List<RuntimeEdge> edges = getModel(file).getEdges(); List<String> ret = edges.stream().map(edge -> edge.getName()).collect(Collectors.toList()); return ret; } public static boolean isValidEdge(File file, String edge) throws IOException { return getModel(file).findEdges(edge) != null; } public static boolean isValidVertex(File file, String vertex) throws IOException { return getModel(file).findVertices(vertex) != null; } /** * Filter a model. It keeps only the passed element in the source model * (removing the others) * * @param sourceFileModel * @param elements * @return a string representation of the reduced model on json format * @throws IOException */ public static String reduceModel(File sourceFileModel, String name, Element[] elements) throws IOException { Map<RuntimeVertex, Vertex> mapping = new HashMap<RuntimeVertex, Vertex>(); Builder<? extends Element> startElement = null; RuntimeModel sourceModel = GraphWalkerFacade.getModel(sourceFileModel); Model model = new Model(); model.setName(name); model.setProperties(sourceModel.getProperties()); model.setId(UUID.randomUUID().toString()); List<Vertex.RuntimeVertex> vertices = sourceModel.getVertices(); for (RuntimeVertex v : vertices) { boolean found = false; for (int i = 0; i < elements.length; i++) { Element element = elements[i]; if (element.getId().equals(v.getId())) { found = true; break; } } if (!found) continue; org.graphwalker.core.model.Vertex vertex = new org.graphwalker.core.model.Vertex().setName(v.getName()) .setId(v.getId()); if (elements[0].equals(v)) { startElement = vertex; } vertex.setId(UUID.randomUUID().toString()); vertex.setProperties(v.getProperties()); vertex.setSharedState(v.getSharedState()); vertex.setRequirements(v.getRequirements()); List<Action> actions = v.getActions(); for (Action action : actions) { model.addAction(action); } model.addVertex(vertex); mapping.put(v, vertex); } List<Edge.RuntimeEdge> edges = sourceModel.getEdges(); for (RuntimeEdge runtimeEdge : edges) { boolean found = false; for (int i = 0; i < elements.length; i++) { Element element = elements[i]; if (element.getId().equals(runtimeEdge.getId())) { found = true; break; } } if (!found) continue; org.graphwalker.core.model.Vertex sourceVertex = mapping.get(runtimeEdge.getSourceVertex()); org.graphwalker.core.model.Vertex targetVertex = mapping.get(runtimeEdge.getTargetVertex()); Edge edge = new Edge().setSourceVertex(sourceVertex).setTargetVertex(targetVertex) .setName(runtimeEdge.getName()).setId(UUID.randomUUID().toString()); if (elements[0].getId().equals(runtimeEdge.getId())) { startElement = edge; } edge.setProperties(runtimeEdge.getProperties()); edge.setGuard(runtimeEdge.getGuard()); edge.setActions(runtimeEdge.getActions()); edge.setDependency(runtimeEdge.getDependency()); edge.setRequirements(runtimeEdge.getRequirements()); edge.setWeight(runtimeEdge.getWeight()); model.addEdge(edge); } Context writeContext = new ExecutionContext() { }; writeContext.setModel(model.build()); if (startElement != null) { writeContext.setNextElement(startElement); } List<Context> writeContexts = new ArrayList<>(); writeContexts.add(writeContext); ContextFactory factory = new JsonContextFactory(); String content = factory.getAsString(writeContexts); return content; } private static void addContexts(List<Context> executionContexts, Path modelFileName, String generator, String startElement) throws IOException { ContextFactory factory = getContextFactory(modelFileName); List<Context> contexts = factory.create(modelFileName); contexts.get(0).setPathGenerator(GeneratorFactory.parse(generator)); Element element = contexts.get(0).getModel().findElements(startElement).get(0); contexts.get(0).setNextElement(element); executionContexts.addAll(contexts); } public static List<IFile> generateOffLineFromFile(IWorkbenchWindow ww, TestResourceGeneration dcp, BuildPolicy[] generators, int timeout, IProgressMonitor monitor) throws IOException, CoreException, InterruptedException { IFile graphModel = dcp.getGraphIFile(); String startElement = getStartElement(dcp.getGraphFile()); List<IFile> ret = new ArrayList<IFile>(); try { for (BuildPolicy policy : generators) { OfflineContext oc = new OfflineContext(policy); dcp.addOfflineContext(oc); File shellFile = ProcessFacade.buildOfflineShellFile(dcp.getJavaProject(), graphModel, policy.getPathGenerator(), startElement); ProcessFacade.execute(shellFile, (long) timeout).forEach(oc::addMethodName); } } catch (Exception e) { ResourceManager.logException(e); if (!ErrorDialog.AUTOMATED_MODE) { // Avoid displaying a window while running automated mode DialogManager.asyncDisplayErrorMessage(MessageUtil.getString("error"), MessageUtil.getString("an_error_occured_while_running_offline_tool"), e); } } dcp.updateWithOfflines(); generateFromFile(ww, dcp, monitor); return ret; } public static List<IFile> generateOffLineFromFile1(IWorkbenchWindow ww, TestResourceGeneration dcp, BuildPolicy[] generators, int timeout, IProgressMonitor monitor) throws IOException, CoreException, InterruptedException { IFile graphModel = dcp.getGraphIFile(); List<IFile> ret = new ArrayList<IFile>(); List<Context> executionContexts = new ArrayList<Context>(); for (BuildPolicy policy : generators) { String startElement = getStartElement(dcp.getGraphFile()); Path path = dcp.getInputPath(); String generator = policy.getPathGenerator(); String msg = "Offline arguments: " + path + " " + generator + " " + startElement; ResourceManager.logInfo(graphModel.getProject().getName(), msg); addContexts(executionContexts, path, generator, startElement); } int index = 0; for (Context context : executionContexts) { OfflineContext oc = new OfflineContext(generators[index]); index++; dcp.addOfflineContext(oc); TestExecutor executor = new TestExecutor(context); executor.getMachine().addObserver(new Observer() { @Override public void update(Machine machine, Element element, EventType type) { if (EventType.BEFORE_ELEMENT.equals(type)) { oc.addMethodName(element.getName()); if (monitor.isCanceled()) { throw new RuntimeException( new InterruptedException(MessageUtil.getString("timeoutofflineorcancelled"))); } } } }); Timer canceller = new Timer(); canceller.schedule(new TimerTask() { @Override public void run() { try { monitor.setCanceled(true); } catch (Throwable e) { } } }, timeout * 1000); try { Result result = executor.execute(); canceller.cancel(); } catch (TestExecutionException e) { String reason = e.getResult().getResultsAsString(); canceller.cancel(); ResourceManager.logException(e, reason); if (!ErrorDialog.AUTOMATED_MODE) { // Avoid displaying a window while running automated mode DialogManager.asyncDisplayErrorMessage(MessageUtil.getString("error"), reason, e); } } catch (Throwable e) { canceller.cancel(); ResourceManager.logException(e); if (!ErrorDialog.AUTOMATED_MODE) { // Avoid displaying a window while running automated mode DialogManager.asyncDisplayErrorMessage(MessageUtil.getString("error"), MessageUtil.getString("an_error_occured_while_running_offline_tool"), e); } return ret; } } dcp.updateWithOfflines(); generateFromFile(ww, dcp, monitor); return ret; } /** * Generate code * * @param input * @param output * @throws IOException * @throws CoreException * @throws InterruptedException */ public static List<IFile> generateFromFile(IWorkbenchWindow ww, TestResourceGeneration dcp, IProgressMonitor monitor) throws IOException, CoreException, InterruptedException { List<IFile> ret = new ArrayList<IFile>(); List<IFile> additionals = dcp.getClassExtension().getAdditionalContexts(); int max = additionals.size() + 1; SubMonitor subMonitor = SubMonitor.convert(monitor, max); if (additionals != null) { for (IFile iFile : additionals) { subMonitor.setTaskName("Processing " + iFile); try { try { GraphWalkerContextManager.generateDefaultGraphConversion(ww, iFile, monitor); } catch (InvocationTargetException e) { ResourceManager.logException(e); } } finally { subMonitor.split(1); } } } final SimpleCache cache = new SimpleCache(dcp.getOutputPath()); if (!PreferenceManager.isCacheEnabled() || isNotGenerated(cache, dcp.getInputPath()) || isModified(cache, dcp.getInputPath()) || dcp.isOffline()) { try { subMonitor.setTaskName("Processing " + dcp.getInputPath().getFileName()); // write interface SourceFile sourceFile = new SourceFile(dcp.getInputPath(), dcp.getBasePath(), dcp.getOutputPath()); ContextFactory factory = getContextFactory(sourceFile.getInputPath()); List<IPath> interfaces = write(factory, sourceFile, true, monitor); if (dcp.isGenerateOnlyInterface()) return ret; // write implementation IFile type = null; if (dcp.isAppendSource()) { type = dcp.toIFile(); } else { type = JDTManager.generateTestImplementation(dcp, monitor); ResourceManager.updateBuildPolicyFileFor(type); } ret.add(type); type = ret.get(ret.size() - 1); JDTManager.enrichClass(type, dcp, monitor); JDTManager.formatUnitSourceCode(type, monitor); JDTManager.openEditor(type, ww); ICompilationUnit cu = JavaCore.createCompilationUnitFrom(type); int count = 0; CompilationUnit ast = null; while (ast == null && count < 10) { Thread.sleep(200); ast = JDTManager.parse(cu); count++; } type = ret.get(ret.size() - 1); JDTManager.reorganizeImport(JavaCore.createCompilationUnitFrom(type)); cache.add(dcp.getInputPath(), new CacheEntry(dcp.getInputPath().toFile().lastModified(), true)); IFile iFileCache = ResourceManager.toIFile(dcp.getOutputPath().toFile()); ResourceManager.resfresh(iFileCache.getParent()); } catch (Exception e) { ResourceManager.logException(e); cache.add(dcp.getInputPath(), new CacheEntry(dcp.getInputPath().toFile().lastModified(), false)); } finally { subMonitor.split(1); } } return ret; } public static List<IFile> generateFromFile1(IWorkbenchWindow ww, TestResourceGeneration dcp, IProgressMonitor monitor) throws IOException, CoreException, InterruptedException { List<IFile> ret = new ArrayList<IFile>(); List<IFile> additionals = dcp.getClassExtension().getAdditionalContexts(); int max = additionals.size() + 1; SubMonitor subMonitor = SubMonitor.convert(monitor, max); if (additionals != null) { for (IFile iFile : additionals) { subMonitor.setTaskName("Processing " + iFile); try { try { GraphWalkerContextManager.generateDefaultGraphConversion(ww, iFile, monitor); } catch (InvocationTargetException e) { ResourceManager.logException(e); } } finally { subMonitor.split(1); } } } final SimpleCache cache = new SimpleCache(dcp.getOutputPath()); if (!PreferenceManager.isCacheEnabled() || isNotGenerated(cache, dcp.getInputPath()) || isModified(cache, dcp.getInputPath()) || dcp.isOffline()) { try { subMonitor.setTaskName("Processing " + dcp.getInputPath().getFileName()); // write interface SourceFile sourceFile = new SourceFile(dcp.getInputPath(), dcp.getBasePath(), dcp.getOutputPath()); ContextFactory factory = getContextFactory(sourceFile.getInputPath()); List<IPath> interfaces = write(factory, sourceFile, true, monitor); if (dcp.isGenerateOnlyInterface()) return ret; // write implementation IFile type = null; if (dcp.isAppendSource()) { type = dcp.toIFile(); } else { type = JDTManager.generateTestImplementation(dcp, monitor); ResourceManager.updateBuildPolicyFileFor(type); } ret.add(type); Display.getDefault().syncExec(new Runnable() { public void run() { try { IFile type = ret.get(ret.size() - 1); JDTManager.enrichClass(type, dcp, monitor); JDTManager.formatUnitSourceCode(type, monitor); JDTManager.openEditor(type, ww); } catch (Exception e) { ResourceManager.logException(e); } } }); ICompilationUnit cu = JavaCore.createCompilationUnitFrom(type); int count = 0; CompilationUnit ast = null; while (ast == null && count < 10) { Thread.sleep(1000); ast = JDTManager.parse(cu); count++; } Display.getDefault().syncExec(new Runnable() { public void run() { try { IFile type = ret.get(ret.size() - 1); JDTManager.reorganizeImport(JavaCore.createCompilationUnitFrom(type)); } catch (Exception e) { ResourceManager.logException(e); } } }); cache.add(dcp.getInputPath(), new CacheEntry(dcp.getInputPath().toFile().lastModified(), true)); IFile iFileCache = ResourceManager.toIFile(dcp.getOutputPath().toFile()); ResourceManager.resfresh(iFileCache.getParent()); } catch (Exception e) { ResourceManager.logException(e); cache.add(dcp.getInputPath(), new CacheEntry(dcp.getInputPath().toFile().lastModified(), false)); } finally { subMonitor.split(1); } } return ret; } /** * @param factory * @param file * @throws IOException */ private static List<IPath> write(ContextFactory factory, SourceFile file, boolean erase, IProgressMonitor monitor) throws IOException { List<IPath> ret = new ArrayList<IPath>(); List<Context> contexts = factory.create(file.getInputPath()); for (Context context : contexts) { try { RuntimeModel model = context.getModel(); File outfile = file.getOutputPath().toFile(); if (erase) { IFile ifileTodelete = ResourceManager.toIFile(outfile); if (ifileTodelete.exists()) { ifileTodelete.delete(true, monitor); } } String source = new CodeGenerator().generate(file, model); File f = file.getOutputPath().getParent().toFile(); IFolder ifolder = ResourceManager.toIFolder(f); ResourceManager.ensureFolder((IFolder) ifolder); IFile ifile = ResourceManager.createFileDeleteIfExists(file.getOutputPath().toFile(), source, monitor); ret.add(ifile.getFullPath()); } catch (Throwable t) { ResourceManager.logException(t); } } return ret; } /** * Generate code * * @param input * @param output */ public static void generateFromFolder(final Path input, final Path output) { CodeGenerator.generate(input, output); } /** * @param modelFileName * @return * @throws IOException */ public static String getNextElement(String modelFileName) throws IOException { Context c = getContext(modelFileName); if (c.getNextElement() != null) { return c.getNextElement().getName(); } return null; } /** * Return the Context built after having read and parsed the passed graph model * GraphWalker lookup factory fails in OSGI env. * * @param modelFileName * @return * @throws IOException */ static Map<String, ContextFactory> cache = new HashMap<String, ContextFactory>(); static { cache.put("json", new JsonContextFactory()); cache.put("graphml", new YEdContextFactory()); cache.put("dot", new DotContextFactory()); cache.put("java", new JavaContextFactory()); } public static ContextFactory getContextFactory(Path path) { String extension = FilenameUtils.getExtension(path.toString()); ContextFactory factory = cache.get(extension); if (factory == null) { throw new NullPointerException(" No factory found for : " + path); } return factory; } /** * @param modelFileName * @return * @throws IOException * @throws JsonSyntaxException * @throws ContextFactoryException */ public static Context getContext(String modelFileName) throws IOException, JsonSyntaxException, ContextFactoryException { Path path = Paths.get(modelFileName); ContextFactory factory = getContextFactory(path); List<Context> contexts = factory.create(Paths.get(modelFileName)); if (contexts != null && contexts.size() > 0) { return contexts.get(0); } return null; } /** * @param main * @param candidatesGraphFiles * @return * @throws IOException * @throws JavaModelException * @throws InterruptedException */ public static List<IFile> findSharedContexts(IFile main, List<IFile> candidatesGraphFiles) throws IOException, JavaModelException, InterruptedException { IPath path = main.getFullPath(); File file = ResourceManager.toFile(path); Context mainContext = GraphWalkerFacade.getContext(file.getAbsolutePath()); List<Context> candidates = new ArrayList<Context>(); Map<Context, IFile> mapping = new HashMap<Context, IFile>(); for (IFile graphFile : candidatesGraphFiles) { try { File gfile = ResourceManager.toFile(graphFile.getFullPath()); Context candidatContext = GraphWalkerFacade.getContext(gfile.getAbsolutePath()); mapping.put(candidatContext, graphFile); candidates.add(candidatContext); } catch (Exception e) { ResourceManager.logException(e); } } List<Context> contexts = new ArrayList<Context>(); findSharedContexts(contexts, mainContext, candidates); List<IFile> ret = new ArrayList<IFile>(); for (Context context : contexts) { IFile t = mapping.get(context); ret.add(t); } return ret; } /** * @param filtered * @param main * @param candidates * @throws IOException * @throws JavaModelException */ private static void findSharedContexts(List<Context> filtered, Context main, List<Context> candidates) throws IOException, JavaModelException { List<Context> newCandidates = new ArrayList<Context>(); Set<String> sharedStates = main.getModel().getSharedStates(); for (String shared : sharedStates) { for (Context context : candidates) { if (context.equals(main)) continue; List<RuntimeVertex> states = context.getModel().getSharedStates(shared); if (states != null) { if (!filtered.contains(context)) { newCandidates.add(context); filtered.add(context); } } } } for (Context c : newCandidates) { findSharedContexts(filtered, c, candidates); } } /** * @param project * @param type * @param others * @return * @throws IOException * @throws JavaModelException */ public static List<IType> getSharedContexts(IProject project, IType type, List<IType> others) throws IOException, JavaModelException { Map<Context, IType> mapping = new HashMap<Context, IType>(); IPath path = JDTManager.getGraphModelPath(project, type); if (path == null) return new ArrayList<IType>(); File file = ResourceManager.toFile(path); Context main = GraphWalkerFacade.getContext(file.getAbsolutePath()); mapping.put(main, type); List<Context> candidates = new ArrayList<Context>(); for (IType t : others) { path = JDTManager.getGraphModelPath(project, t); file = ResourceManager.toFile(path); Context c = GraphWalkerFacade.getContext(file.getAbsolutePath()); candidates.add(c); mapping.put(c, t); } List<Context> contexts = new ArrayList<Context>(); findSharedContexts(contexts, main, candidates); List<IType> ret = new ArrayList<IType>(); for (Context context : contexts) { IType t = mapping.get(context); ret.add(t); } return ret; } /** * Parse a graph model file with its directives held by the buildPolicy * parameter * * @param context * @param pathgenerator * @return */ public static List<String> parse(Context context, String pathgenerator) { List<Context> contexts = new ArrayList<Context>(); contexts.add(context); try { context.setPathGenerator(GeneratorFactory.parse(pathgenerator)); } catch (Throwable e) { List<String> issues = new ArrayList<String>(); issues.add(e.getMessage()); return issues; } List<String> issues = ContextsChecker.hasIssues(contexts); // assess whether we have 100% coverage on vertex while having a start vertex // and start element which is not the Start vertex List<RuntimeVertex> vertices = context.getModel().getVertices(); RuntimeVertex[] filteredVertex = vertices.stream() .filter(item -> item.getName().equalsIgnoreCase(Constant.START_VERTEX_NAME)) .toArray(RuntimeVertex[]::new); if (filteredVertex != null && filteredVertex.length > 0 && context != null && context.getNextElement() != null && !context.getNextElement().getName().equalsIgnoreCase(Constant.START_VERTEX_NAME)) { PathGenerator<StopCondition> pg = GeneratorFactory.parse(pathgenerator); StopCondition condition = pg.getStopCondition(); if (condition instanceof VertexCoverage && condition.getValue().trim().equals("100")) { issues.add(MessageUtil.getString("cannot_reach_one_hundred_vertex_coverage_with_start_vertex")); } } return issues; } /** * @param pathgenerator * @return */ public static boolean parsePathGenerator(String pathgenerator) { try { GeneratorFactory.parse(pathgenerator); return true; } catch (Exception e) { return false; } } /** * @param pathgenerator * @return */ public static PathGenerator createPathGenerator(String pathgenerator) { return GeneratorFactory.parse(pathgenerator); } /** * A listViewer of context for the passed model iterator * * @param itr * @return * @throws Exception */ private static List<Context> getContexts(Iterator<String> itr) throws Exception { List<Context> executionContexts = new ArrayList<>(); while (itr.hasNext()) { String modelFileName = itr.next(); ContextFactory factory = getContextFactory(Paths.get(modelFileName)); List<Context> contexts; try { contexts = factory.create(Paths.get(modelFileName)); } catch (DslException e) { ResourceManager.logException(e); throw new Exception("Model syntax error : " + "When parsing model: '" + modelFileName + "' "); } executionContexts.addAll(contexts); } return executionContexts; } /** * Get the requirement located in the graphml file * * @param file * @return * @throws Exception */ public static Set<String> getRequirement(String filepath) throws Exception { List<String> input = new ArrayList<String>(); input.add(filepath); SortedSet<String> reqs = new TreeSet<>(); for (Context context : getContexts(input.iterator())) { for (Requirement req : context.getRequirements()) { reqs.add(req.getKey()); } } return reqs; } /** * Get the requirement located in the graphml file * * @param file * @return * @throws Exception */ public static Set<String> getRequirement(IFile file) throws Exception { return getRequirement(file.getRawLocation().makeAbsolute().toString()); } /** * Get the "methods" for the graphml file * * @param file * @return * @throws Exception */ public static Set<String> getMethods(String filepath) throws Exception { List<String> input = new ArrayList<String>(); input.add(filepath); SortedSet<String> names = new TreeSet<>(); for (Context context : getContexts(input.iterator())) { for (Vertex.RuntimeVertex vertex : context.getModel().getVertices()) { if (null != vertex.getName()) { names.add(vertex.getName()); } } for (Edge.RuntimeEdge edge : context.getModel().getEdges()) { if (edge.getName() != null) { names.add(edge.getName()); } } } return names; } /** * Get the "methods" for the graphml file * * @param file * @return * @throws Exception */ public static Set<String> getMethods(IFile file) throws Exception { return getMethods(file.getRawLocation().makeAbsolute().toString()); } /** * Convert a graph model file into another format * * @param inputFileName * @param outputFileName * @throws IOException */ public static String convert(String inputFileName, String outputFileName) throws IOException { ContextFactory inputFactory = getContextFactory(Paths.get(inputFileName)); List<Context> contexts = inputFactory.create(Paths.get(inputFileName)); ContextFactory outputFactory = getContextFactory(Paths.get(outputFileName)); return outputFactory.getAsString(contexts); } public static class GW4EExecutor { List<String> classpathElements; List<String> classnames; File reportDir; boolean displayDetail; boolean removedBlockedElements; public GW4EExecutor(List<String> classpathElements, List<String> classnames, File reportDir, boolean displayDetail, boolean removedBlockedElements) { super(); this.classpathElements = classpathElements; this.removedBlockedElements = removedBlockedElements; this.reportDir = reportDir; this.displayDetail = displayDetail; this.classnames = new ArrayList<String>(); for (String clazz : classnames) { if (this.classnames.contains(clazz)) continue; this.classnames.add(clazz); } System.out.println("---------------------------------------------------------------------------"); System.out.println("---------------------------------------------------------------------------"); System.out.println("reportDir : " + reportDir); System.out.println("displayDetail : " + displayDetail); System.out.println("removedBlockedElements : " + removedBlockedElements); System.out.println("classnames : " + classnames); System.out.println("classpathElements : " + classpathElements); System.out.println("---------------------------------------------------------------------------"); System.out.println("---------------------------------------------------------------------------"); } private void installEntryPointExecutionContext(Class[] contextClasses, List<Context> contextInstances) { for (Context context : contextInstances) { if (contextClasses[0].equals(context.getClass())) { continue; } context.setCurrentElement(null); context.setNextElement((Element) null); } } private void displayConfiguration(List<Context> contexts) { if (!displayDetail) return; System.out.println("------------------------------------------------------------------------"); for (Context context : contexts) { System.out.println( " " + context.getClass().getName() + "(" + context.getPathGenerator().toString() + " )"); } System.out.println("------------------------------------------------------------------------"); } private void displayResult(boolean displayDetail, String classname, Result result) throws IOException { if (!displayDetail) return; if (result.hasErrors()) { System.err.println("------------------------------------------------------------------------"); for (String error : result.getErrors()) { System.err.println(error); } } System.out.println("------------------------------------------------------------------------"); System.out.println("Result :"); String temp = result.getResultsAsString(); System.out.println(temp); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); String timestamp = formatter.format(new Date()); Files.write(Paths.get("graphwalker-model-summary-" + classname + "-" + timestamp + ".json"), temp.getBytes()); } private ClassLoader switchClassLoader(ClassLoader classLoader) { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(classLoader); return contextClassLoader; } private Class[] loadTests(ClassLoader classLoader, List<String> classnames) throws ClassNotFoundException { List<Class> ret = new ArrayList<Class>(); for (String test : classnames) { Class clazz = classLoader.loadClass(test); ret.add(clazz); } Class[] classes = new Class[ret.size()]; ret.toArray(classes); return classes; } public void execute() throws IOException, ClassNotFoundException { Date starttime = new Date(); ClassLoader classLoader = new IsolatedClassLoader(classpathElements); ClassLoader contextClassLoader = switchClassLoader(classLoader); Class[] contexts = loadTests(contextClassLoader, classnames); TestExecutor executor; switchClassLoader(contextClassLoader); executor = new TestExecutor(contexts); List<Context> all = executor.getMachine().getContexts(); if (removedBlockedElements) { org.graphwalker.io.common.Util.filterBlockedElements(all); } installEntryPointExecutionContext(contexts, executor.getMachine().getContexts()); displayConfiguration(executor.getMachine().getContexts()); Result result = null; try { executor.execute(); } catch (Throwable e) { e.printStackTrace(); } result = executor.getResult(); displayResult(displayDetail, classnames.get(0), result); executor.reportResults(reportDir, starttime, System.getProperties()); } } }