1 package org.simantics.graph.compiler;
\r
3 import java.io.ByteArrayInputStream;
\r
4 import java.io.ByteArrayOutputStream;
\r
5 import java.io.DataInputStream;
\r
7 import java.io.IOException;
\r
8 import java.io.InputStream;
\r
9 import java.io.PrintStream;
\r
10 import java.util.ArrayList;
\r
11 import java.util.Collection;
\r
12 import java.util.Formatter;
\r
13 import java.util.Locale;
\r
15 import org.simantics.databoard.Bindings;
\r
16 import org.simantics.databoard.Files;
\r
17 import org.simantics.databoard.adapter.AdaptException;
\r
18 import org.simantics.databoard.binding.error.BindingException;
\r
19 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
\r
20 import org.simantics.databoard.binding.mutable.Variant;
\r
21 import org.simantics.databoard.container.DataContainer;
\r
22 import org.simantics.databoard.container.DataContainers;
\r
23 import org.simantics.databoard.serialization.SerializationException;
\r
24 import org.simantics.graph.compiler.internal.parsing.Parsing;
\r
25 import org.simantics.graph.compiler.internal.procedures.AddConsistsOf;
\r
26 import org.simantics.graph.compiler.internal.procedures.ApplyTemplates;
\r
27 import org.simantics.graph.compiler.internal.procedures.Compactify;
\r
28 import org.simantics.graph.compiler.internal.procedures.ConvertPreValues;
\r
29 import org.simantics.graph.compiler.internal.procedures.CreateInverseRelations;
\r
30 import org.simantics.graph.compiler.internal.procedures.CreateTemplates;
\r
31 import org.simantics.graph.compiler.internal.procedures.DefaultValueTyping;
\r
32 import org.simantics.graph.compiler.internal.procedures.MergeEqualResources;
\r
33 import org.simantics.graph.compiler.internal.procedures.PropagateNewMarks;
\r
34 import org.simantics.graph.compiler.internal.resourceFiles.ResourceFileGenerator;
\r
35 import org.simantics.graph.compiler.internal.store.LocationStore;
\r
36 import org.simantics.graph.compiler.internal.store.VariableStore;
\r
37 import org.simantics.graph.compiler.internal.validation.ReportCollisions;
\r
38 import org.simantics.graph.compiler.internal.validation.ValidateGraph;
\r
39 import org.simantics.graph.query.CompositeGraph;
\r
40 import org.simantics.graph.query.Paths;
\r
41 import org.simantics.graph.query.TransferableGraphConversion;
\r
42 import org.simantics.graph.representation.TransferableGraph1;
\r
43 import org.simantics.graph.store.GraphStore;
\r
44 import org.simantics.ltk.FileSource;
\r
45 import org.simantics.ltk.ISource;
\r
46 import org.simantics.ltk.Location;
\r
47 import org.simantics.ltk.Problem;
\r
49 public class GraphCompiler {
\r
51 public static PrintStream out = System.out;
\r
53 public static TransferableGraph1 read(File file) throws Exception {
\r
54 DataContainer container = DataContainers.readFile(file);
\r
55 return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);
\r
58 public static TransferableGraph1 read(InputStream stream) throws AdaptException, IOException {
\r
59 DataContainer container = DataContainers.readFile(new DataInputStream(stream));
\r
61 return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);
\r
64 public static InputStream write(TransferableGraph1 tg) throws BindingException, IOException {
\r
65 byte[] buffer = DataContainers.writeFile(
\r
66 new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, tg))
\r
68 return new ByteArrayInputStream(buffer);
\r
71 public static CompilationResult compile(
\r
72 String Layer0Version,
\r
73 Collection<ISource> sources,
\r
74 Collection<TransferableGraph1> dependencies,
\r
75 ExternalFileLoader fileLoader,
\r
76 GraphCompilerPreferences preferences) {
\r
77 out.println(preferences);
\r
79 Collection<Problem> errors = new ArrayList<Problem>();
\r
80 GraphStore store = new GraphStore();
\r
82 CompilationResult compilationResult = new CompilationResult();
\r
83 compilationResult.errors = errors;
\r
84 compilationResult.warnings = new ArrayList<Problem>();
\r
86 Paths paths = new Paths(Layer0Version);
\r
89 run(new Parsing(paths, sources, errors, store));
\r
91 if(!errors.isEmpty())
\r
92 return compilationResult;
\r
94 // Create composite graph of the new statements and dependencies
\r
95 CompositeGraph graph;
\r
97 long beginTime = System.nanoTime();
\r
98 graph = TransferableGraphConversion.convert(paths, dependencies);
\r
99 graph.addFragment(store);
\r
100 long endTime = System.nanoTime();
\r
101 reportTime("Composition", beginTime, endTime);
\r
105 run(new MergeEqualResources(paths, store));
\r
107 int[] unfoundedIdentitities = store.identities.getUnfoundedIdentities();
\r
108 if(unfoundedIdentitities.length > 0) {
\r
109 LocationStore locations = store.getStore(LocationStore.class);
\r
110 for(int id : unfoundedIdentitities) {
\r
111 errors.add(new Problem(
\r
112 locations.getLocation(id),
\r
113 "URIless resource used as a parent."));
\r
115 return compilationResult;
\r
118 store.identities.createPathToId(paths.ConsistsOf);
\r
119 run(new CreateTemplates(graph, store, errors));
\r
120 run(new ApplyTemplates(graph, store, errors, fileLoader));
\r
121 run(new DefaultValueTyping(paths, store));
\r
122 run(new Compactify(store));
\r
123 run(new PropagateNewMarks(store));
\r
124 run(new CreateInverseRelations(graph, store));
\r
125 run(new AddConsistsOf(paths, store));
\r
126 run(new ConvertPreValues(graph, store, errors));
\r
127 run(new ReportCollisions(preferences, errors, store));
\r
128 if(preferences.validate)
\r
129 run(new ValidateGraph(graph, errors, store, preferences));
\r
131 // Create the result
\r
133 long beginTime = System.nanoTime();
\r
134 compilationResult.graph = TransferableGraphConversion.convert(graph, store);
\r
135 long endTime = System.nanoTime();
\r
136 reportTime("Generate TG", beginTime, endTime);
\r
139 // Create resource files
\r
141 long beginTime = System.nanoTime();
\r
142 compilationResult.resourceFiles = ResourceFileGenerator.generate(paths, store);
\r
143 long endTime = System.nanoTime();
\r
144 reportTime("Generate resources", beginTime, endTime);
\r
147 // Create source info
\r
149 VariableStore variableStore = store.getStore(VariableStore.class);
\r
150 compilationResult.sourceInfo = variableStore.getSourceInfo();
\r
153 // Fix source location of problems whose location is null at this point
\r
155 for(Problem problem : compilationResult.errors) {
\r
156 if(problem.getLocation() == null)
\r
157 for(ISource source : sources) {
\r
158 problem.setLocation(new Location(source));
\r
161 else if(problem.getLocation().getSource() == null)
\r
162 for(ISource source : sources) {
\r
163 problem.getLocation().setSource(source);
\r
167 for(Problem problem : compilationResult.warnings) {
\r
168 if(problem.getLocation() == null)
\r
169 for(ISource source : sources) {
\r
170 problem.setLocation(new Location(source));
\r
173 else if(problem.getLocation().getSource() == null)
\r
174 for(ISource source : sources) {
\r
175 problem.getLocation().setSource(source);
\r
180 } catch(Exception e) {
\r
181 e.printStackTrace();
\r
182 ByteArrayOutputStream stream = new ByteArrayOutputStream();
\r
183 e.printStackTrace(new PrintStream(stream));
\r
184 String description = "Internal error: " +
\r
185 new String(stream.toByteArray());
\r
186 for(ISource source : sources)
\r
187 errors.add(new Problem(new Location(source), description));
\r
190 return compilationResult;
\r
193 private static void run(Runnable runnable) {
\r
194 long beginTime = System.nanoTime();
\r
196 long endTime = System.nanoTime();
\r
198 reportTime(runnable.getClass().getSimpleName(), beginTime, endTime);
\r
201 public static void reportTime(String taskName, long beginTime, long endTime) {
\r
202 StringBuilder sb = new StringBuilder();
\r
203 Formatter formatter = new Formatter(sb, Locale.US);
\r
204 formatter.format("%-25s %8.4f ms", taskName, (endTime - beginTime)*1e-6);
\r
206 out.println(sb.toString());
\r
209 public static void reportTime(String taskName, long beginTime) {
\r
210 reportTime(taskName, beginTime, System.nanoTime());
\r
213 public static void main(String[] args) {
\r
214 Collection<ISource> sources = new ArrayList<ISource>();
\r
215 Collection<TransferableGraph1> dependencies = new ArrayList<TransferableGraph1>();
\r
216 String outputFile = null;
\r
218 for(int i=0;i<args.length;++i) {
\r
219 String arg = args[i];
\r
220 if(arg.equals("-o")) {
\r
221 if(++i < args.length)
\r
222 outputFile = args[i];
\r
225 if(arg.endsWith(".tg")) {
\r
227 dependencies.add(read(new File(arg)));
\r
228 } catch (Exception e) {
\r
229 e.printStackTrace();
\r
233 else if(arg.endsWith(".graph") || arg.endsWith(".pgraph")) {
\r
234 sources.add(new FileSource(arg));
\r
237 System.err.println("Invalid input file extension " + arg);
\r
243 if(sources.isEmpty()) {
\r
244 System.err.println("No source files");
\r
248 if(outputFile == null) {
\r
249 System.err.println("Name of the output file is not given (use -o flag).");
\r
253 CompilationResult result = compile("1.0", sources, dependencies, null, new GraphCompilerPreferences());
\r
254 for(Problem problem : result.getErrors())
\r
255 out.println(problem.getLocation() + ": " + problem.getDescription());
\r
257 if(result.getGraph() != null)
\r
259 Files.createFile(new File(outputFile), TransferableGraph1.BINDING, result.getGraph());
\r
260 } catch (Exception e) {
\r
261 e.printStackTrace();
\r