--- /dev/null
+package org.simantics.graph.compiler;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.DataInputStream;\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.PrintStream;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Formatter;\r
+import java.util.Locale;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Files;\r
+import org.simantics.databoard.adapter.AdaptException;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.container.DataContainer;\r
+import org.simantics.databoard.container.DataContainers;\r
+import org.simantics.databoard.serialization.SerializationException;\r
+import org.simantics.graph.compiler.internal.parsing.Parsing;\r
+import org.simantics.graph.compiler.internal.procedures.AddConsistsOf;\r
+import org.simantics.graph.compiler.internal.procedures.ApplyTemplates;\r
+import org.simantics.graph.compiler.internal.procedures.Compactify;\r
+import org.simantics.graph.compiler.internal.procedures.ConvertPreValues;\r
+import org.simantics.graph.compiler.internal.procedures.CreateInverseRelations;\r
+import org.simantics.graph.compiler.internal.procedures.CreateTemplates;\r
+import org.simantics.graph.compiler.internal.procedures.DefaultValueTyping;\r
+import org.simantics.graph.compiler.internal.procedures.MergeEqualResources;\r
+import org.simantics.graph.compiler.internal.procedures.PropagateNewMarks;\r
+import org.simantics.graph.compiler.internal.resourceFiles.ResourceFileGenerator;\r
+import org.simantics.graph.compiler.internal.store.LocationStore;\r
+import org.simantics.graph.compiler.internal.store.VariableStore;\r
+import org.simantics.graph.compiler.internal.validation.ReportCollisions;\r
+import org.simantics.graph.compiler.internal.validation.ValidateGraph;\r
+import org.simantics.graph.query.CompositeGraph;\r
+import org.simantics.graph.query.Paths;\r
+import org.simantics.graph.query.TransferableGraphConversion;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.graph.store.GraphStore;\r
+import org.simantics.ltk.FileSource;\r
+import org.simantics.ltk.ISource;\r
+import org.simantics.ltk.Location;\r
+import org.simantics.ltk.Problem;\r
+\r
+public class GraphCompiler {\r
+ \r
+ public static PrintStream out = System.out;\r
+ \r
+ public static TransferableGraph1 read(File file) throws Exception {\r
+ DataContainer container = DataContainers.readFile(file);\r
+ return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);\r
+ }\r
+ \r
+ public static TransferableGraph1 read(InputStream stream) throws AdaptException, IOException {\r
+ DataContainer container = DataContainers.readFile(new DataInputStream(stream));\r
+ stream.close();\r
+ return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);\r
+ }\r
+ \r
+ public static InputStream write(TransferableGraph1 tg) throws BindingException, IOException {\r
+ byte[] buffer = DataContainers.writeFile(\r
+ new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, tg))\r
+ );\r
+ return new ByteArrayInputStream(buffer);\r
+ }\r
+ \r
+ public static CompilationResult compile(\r
+ String Layer0Version,\r
+ Collection<ISource> sources, \r
+ Collection<TransferableGraph1> dependencies,\r
+ ExternalFileLoader fileLoader,\r
+ GraphCompilerPreferences preferences) {\r
+ out.println(preferences);\r
+ \r
+ Collection<Problem> errors = new ArrayList<Problem>();\r
+ GraphStore store = new GraphStore(); \r
+ \r
+ CompilationResult compilationResult = new CompilationResult();\r
+ compilationResult.errors = errors;\r
+ compilationResult.warnings = new ArrayList<Problem>();\r
+ \r
+ Paths paths = new Paths(Layer0Version);\r
+ \r
+ try { \r
+ run(new Parsing(paths, sources, errors, store));\r
+ \r
+ if(!errors.isEmpty())\r
+ return compilationResult;\r
+ \r
+ // Create composite graph of the new statements and dependencies\r
+ CompositeGraph graph;\r
+ {\r
+ long beginTime = System.nanoTime();\r
+ graph = TransferableGraphConversion.convert(paths, dependencies);\r
+ graph.addFragment(store); \r
+ long endTime = System.nanoTime();\r
+ reportTime("Composition", beginTime, endTime);\r
+ }\r
+ \r
+ // Procedures\r
+ run(new MergeEqualResources(paths, store));\r
+ {\r
+ int[] unfoundedIdentitities = store.identities.getUnfoundedIdentities();\r
+ if(unfoundedIdentitities.length > 0) {\r
+ LocationStore locations = store.getStore(LocationStore.class);\r
+ for(int id : unfoundedIdentitities) {\r
+ errors.add(new Problem(\r
+ locations.getLocation(id), \r
+ "URIless resource used as a parent."));\r
+ }\r
+ return compilationResult;\r
+ }\r
+ } \r
+ store.identities.createPathToId(paths.ConsistsOf);\r
+ run(new CreateTemplates(graph, store, errors));\r
+ run(new ApplyTemplates(graph, store, errors, fileLoader));\r
+ run(new DefaultValueTyping(paths, store)); \r
+ run(new Compactify(store)); \r
+ run(new PropagateNewMarks(store)); \r
+ run(new CreateInverseRelations(graph, store));\r
+ run(new AddConsistsOf(paths, store));\r
+ run(new ConvertPreValues(graph, store, errors));\r
+ run(new ReportCollisions(errors, store));\r
+ if(preferences.validate)\r
+ run(new ValidateGraph(graph, errors, store, preferences));\r
+ \r
+ // Create the result\r
+ {\r
+ long beginTime = System.nanoTime();\r
+ compilationResult.graph = TransferableGraphConversion.convert(graph, store); \r
+ long endTime = System.nanoTime();\r
+ reportTime("Generate TG", beginTime, endTime);\r
+ }\r
+ \r
+ // Create resource files \r
+ {\r
+ long beginTime = System.nanoTime();\r
+ compilationResult.resourceFiles = ResourceFileGenerator.generate(paths, store); \r
+ long endTime = System.nanoTime();\r
+ reportTime("Generate resources", beginTime, endTime);\r
+ }\r
+ \r
+ // Create source info\r
+ {\r
+ VariableStore variableStore = store.getStore(VariableStore.class);\r
+ compilationResult.sourceInfo = variableStore.getSourceInfo();\r
+ }\r
+ \r
+ // Fix source location of problems whose location is null at this point\r
+\r
+ for(Problem problem : compilationResult.errors) {\r
+ if(problem.getLocation() == null)\r
+ for(ISource source : sources) {\r
+ problem.setLocation(new Location(source));\r
+ break;\r
+ }\r
+ else if(problem.getLocation().getSource() == null)\r
+ for(ISource source : sources) {\r
+ problem.getLocation().setSource(source);\r
+ break;\r
+ }\r
+ }\r
+ for(Problem problem : compilationResult.warnings) {\r
+ if(problem.getLocation() == null)\r
+ for(ISource source : sources) {\r
+ problem.setLocation(new Location(source));\r
+ break;\r
+ }\r
+ else if(problem.getLocation().getSource() == null)\r
+ for(ISource source : sources) {\r
+ problem.getLocation().setSource(source);\r
+ break;\r
+ }\r
+ }\r
+ \r
+ } catch(Exception e) {\r
+ e.printStackTrace();\r
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();\r
+ e.printStackTrace(new PrintStream(stream));\r
+ String description = "Internal error: " +\r
+ new String(stream.toByteArray());\r
+ for(ISource source : sources) \r
+ errors.add(new Problem(new Location(source), description));\r
+ }\r
+ \r
+ return compilationResult;\r
+ }\r
+ \r
+ private static void run(Runnable runnable) {\r
+ long beginTime = System.nanoTime();\r
+ runnable.run();\r
+ long endTime = System.nanoTime();\r
+ \r
+ reportTime(runnable.getClass().getSimpleName(), beginTime, endTime);\r
+ }\r
+ \r
+ public static void reportTime(String taskName, long beginTime, long endTime) {\r
+ StringBuilder sb = new StringBuilder();\r
+ Formatter formatter = new Formatter(sb, Locale.US);\r
+ formatter.format("%-25s %8.4f ms", taskName, (endTime - beginTime)*1e-6);\r
+ \r
+ out.println(sb.toString());\r
+ }\r
+ \r
+ public static void reportTime(String taskName, long beginTime) {\r
+ reportTime(taskName, beginTime, System.nanoTime());\r
+ }\r
+ \r
+ public static void main(String[] args) {\r
+ Collection<ISource> sources = new ArrayList<ISource>();\r
+ Collection<TransferableGraph1> dependencies = new ArrayList<TransferableGraph1>();\r
+ String outputFile = null;\r
+ \r
+ for(int i=0;i<args.length;++i) {\r
+ String arg = args[i];\r
+ if(arg.equals("-o")) {\r
+ if(++i < args.length)\r
+ outputFile = args[i];\r
+ }\r
+ else {\r
+ if(arg.endsWith(".tg")) {\r
+ try {\r
+ dependencies.add(read(new File(arg)));\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ return;\r
+ }\r
+ }\r
+ else if(arg.endsWith(".graph") || arg.endsWith(".pgraph")) {\r
+ sources.add(new FileSource(arg));\r
+ }\r
+ else {\r
+ System.err.println("Invalid input file extension " + arg);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if(sources.isEmpty()) {\r
+ System.err.println("No source files");\r
+ return;\r
+ }\r
+ \r
+ if(outputFile == null) {\r
+ System.err.println("Name of the output file is not given (use -o flag).");\r
+ return;\r
+ }\r
+ \r
+ CompilationResult result = compile("1.0", sources, dependencies, null, new GraphCompilerPreferences());\r
+ for(Problem problem : result.getErrors())\r
+ out.println(problem.getLocation() + ": " + problem.getDescription());\r
+ \r
+ if(result.getGraph() != null)\r
+ try {\r
+ Files.createFile(new File(outputFile), TransferableGraph1.BINDING, result.getGraph());\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ return;\r
+ }\r
+ }\r
+ \r
+}\r