diff --git a/graphwalker-cli/src/main/java/org/graphwalker/cli/CLI.java b/graphwalker-cli/src/main/java/org/graphwalker/cli/CLI.java index 3a7157e3c..8d9c72663 100644 --- a/graphwalker-cli/src/main/java/org/graphwalker/cli/CLI.java +++ b/graphwalker-cli/src/main/java/org/graphwalker/cli/CLI.java @@ -47,6 +47,7 @@ import org.graphwalker.core.model.Vertex; import org.graphwalker.dsl.antlr.DslException; import org.graphwalker.dsl.antlr.generator.GeneratorFactory; +import org.graphwalker.io.common.ResourceUtils; import org.graphwalker.io.factory.ContextFactory; import org.graphwalker.io.factory.ContextFactoryScanner; import org.graphwalker.java.test.TestExecutor; @@ -56,10 +57,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.file.Paths; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static org.graphwalker.core.model.Model.RuntimeModel; @@ -72,6 +77,7 @@ public class CLI { private Methods methods; private Requirements requirements; private Convert convert; + private Source source; enum Command { NONE, @@ -79,7 +85,8 @@ enum Command { ONLINE, METHODS, REQUIREMENTS, - CONVERT + CONVERT, + SOURCE } private Command command = Command.NONE; @@ -132,6 +139,9 @@ private void run(String[] args) { convert = new Convert(); jc.addCommand("convert", convert); + source = new Source(); + jc.addCommand("source", source); + jc.parse(args); jc.usage(); return; @@ -160,6 +170,9 @@ private void run(String[] args) { convert = new Convert(); jc.addCommand("convert", convert); + source = new Source(); + jc.addCommand("source", source); + jc.parse(args); // Parse for commands @@ -179,6 +192,9 @@ private void run(String[] args) { } else if (jc.getParsedCommand().equalsIgnoreCase("convert")) { command = Command.CONVERT; RunCommandConvert(); + } else if (jc.getParsedCommand().equalsIgnoreCase("source")) { + command = Command.SOURCE; + RunCommandSource(); } } @@ -295,8 +311,8 @@ private void RunCommandOnline() throws Exception { } private void RunCommandConvert() throws Exception { - String inputFileName = (String) convert.input.get(0); - String outputFileName = (String) convert.input.get(1); + String inputFileName = convert.input.get(0); + String outputFileName = convert.input.get(1); ContextFactory inputFactory = ContextFactoryScanner.get(Paths.get(inputFileName)); Context context; @@ -311,6 +327,55 @@ private void RunCommandConvert() throws Exception { outputFactory.write(context, Paths.get(outputFileName)); } + private void RunCommandSource() throws Exception { + String modelFileName = source.input.get(0); + String templateFileName = source.input.get(1); + + // Read the model + ContextFactory inputFactory = ContextFactoryScanner.get(Paths.get(modelFileName)); + Context context; + try { + context = inputFactory.create(Paths.get(modelFileName)); + } catch (DslException e) { + System.err.println("When parsing model: '" + modelFileName + "' " + e.getMessage() + System.lineSeparator()); + throw new Exception("Model syntax error"); + } + + // Read the template + BufferedReader reader = new BufferedReader(new InputStreamReader(ResourceUtils.getResourceAsStream(templateFileName))); + StringBuilder templateStrBuilder = new StringBuilder(); + String line; + try { + while ((line = reader.readLine()) != null) { + templateStrBuilder.append(line).append("\n"); + } + reader.close(); + } catch (IOException e) { + throw new RuntimeException("Could not read the file: " + templateFileName); + } + String templateStr = templateStrBuilder.toString(); + + // Apply the template and generate the source code to std out + String header = "", body = "", footer = ""; + Pattern p = Pattern.compile("HEADER<\\{\\{([.\\s\\S]+)\\}\\}>HEADER([.\\s\\S]+)FOOTER<\\{\\{([.\\s\\S]+)\\}\\}>FOOTER"); + Matcher m = p.matcher(templateStr); + if (m.find()) { + header = m.group(1); + body = m.group(2); + footer = m.group(3); + } + + System.out.println(header); + for (Element element : context.getModel().getElements()) { + if (element.hasName()) { + String edge_vertex = element instanceof Vertex.RuntimeVertex ? "vertex" : "edge"; + System.out.println(body.replaceAll("\\{LABEL\\}", element.getName()).replaceAll("\\{EDGE_VERTEX\\}", edge_vertex)); + } + } + System.out.println(footer); + + } + private void RunCommandOffline() throws Exception { TestExecutor executor = new TestExecutor(getContextsWithPathGenerators(offline.model.iterator())); executor.getMachine().addObserver(new Observer() { diff --git a/graphwalker-cli/src/main/java/org/graphwalker/cli/commands/Source.java b/graphwalker-cli/src/main/java/org/graphwalker/cli/commands/Source.java new file mode 100644 index 000000000..5bbc72797 --- /dev/null +++ b/graphwalker-cli/src/main/java/org/graphwalker/cli/commands/Source.java @@ -0,0 +1,42 @@ +package org.graphwalker.cli.commands; + +/* + * #%L + * GraphWalker Command Line Interface + * %% + * Copyright (C) 2005 - 2014 GraphWalker + * %% + * 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 com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; + +import java.util.ArrayList; +import java.util.List; + +@Parameters(commandDescription = "Will generate source code using the provided model and a template. See http://graphwalker.org/docs/command_line_syntax") +public class Source { + + @Parameter(names = {"--input", "-i"}, required = true, arity = 2, + description = "This command requires an input model file, and an input template file. " + + "See http://graphwalker.org/docs/command_line_syntax") + public List input = new ArrayList<>(); +} diff --git a/graphwalker-cli/src/test/java/org/graphwalker/cli/SourceTest.java b/graphwalker-cli/src/test/java/org/graphwalker/cli/SourceTest.java new file mode 100644 index 000000000..419026a50 --- /dev/null +++ b/graphwalker-cli/src/test/java/org/graphwalker/cli/SourceTest.java @@ -0,0 +1,46 @@ +/* + * #%L + * GraphWalker Command Line Interface + * %% + * Copyright (C) 2005 - 2014 GraphWalker + * %% + * 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% + */ + +package org.graphwalker.cli; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +import static org.hamcrest.core.Is.is; + + +public class SourceTest extends CLITestRoot { + + @Test + public void generatePerl() throws IOException { + String args[] = {"source", "--input", "json/example.json", "template/perl.template"}; + Result result = runCommand(args); + Assert.assertThat(result.getError(), is("")); + Assert.assertThat(result.getOutput().length(), is(1850)); + } +} diff --git a/graphwalker-cli/src/test/resources/template/perl.template b/graphwalker-cli/src/test/resources/template/perl.template new file mode 100644 index 000000000..401b77da0 --- /dev/null +++ b/graphwalker-cli/src/test/resources/template/perl.template @@ -0,0 +1,42 @@ +HEADER<{{ +use strict; +use warnings; + +use SOAP::Lite; + +# Connect to the MBT web-service +my $MBTService = SOAP::Lite->service($ARGV[0]); + +# Load MBT with a new xml +my $arg = SOAP::Data->new(name => 'arg0', value => $ARGV[1]); +my $res = $MBTService->Load($arg); + +if ($res eq "false") { + die "Unable to reload MBT, check path to .xml file!\nRemember that the path is relative where mbt is launched."; +} + +# Walk the model +while ( $MBTService->HasNextStep() eq "true"){ + # Get next step from MBT + my $step = $MBTService->GetNextStep(); + if ($step ne '') { + # Run the step + eval( $step ) or die; + } +} +print "MBT Statistics: \n" . $MBTService->GetStatistics() . "\n"; + +}}>HEADER + +# +# This sub routine implements the {EDGE_VERTEX} '{LABEL}' +# +sub {LABEL}() +{ + print "{EDGE_VERTEX}: {LABEL}\n"; + die "The {EDGE_VERTEX}: {LABEL} is not implemented yet!"; +} + +FOOTER<{{ +return 1; +}}>FOOTER