1 package org.simantics.graph.compiler;
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.DataInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.PrintStream;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Formatter;
13 import java.util.Locale;
15 import org.simantics.databoard.Bindings;
16 import org.simantics.databoard.Files;
17 import org.simantics.databoard.adapter.AdaptException;
18 import org.simantics.databoard.binding.Binding;
19 import org.simantics.databoard.binding.error.BindingException;
20 import org.simantics.databoard.binding.mutable.Variant;
21 import org.simantics.databoard.container.DataContainer;
22 import org.simantics.databoard.container.DataContainers;
23 import org.simantics.graph.compiler.internal.parsing.Parsing;
24 import org.simantics.graph.compiler.internal.procedures.AddConsistsOf;
25 import org.simantics.graph.compiler.internal.procedures.ApplyTemplates;
26 import org.simantics.graph.compiler.internal.procedures.Compactify;
27 import org.simantics.graph.compiler.internal.procedures.ConvertPreValues;
28 import org.simantics.graph.compiler.internal.procedures.CreateInverseRelations;
29 import org.simantics.graph.compiler.internal.procedures.CreateTemplates;
30 import org.simantics.graph.compiler.internal.procedures.DefaultValueTyping;
31 import org.simantics.graph.compiler.internal.procedures.MergeEqualResources;
32 import org.simantics.graph.compiler.internal.procedures.PropagateNewMarks;
33 import org.simantics.graph.compiler.internal.resourceFiles.ResourceFileGenerator;
34 import org.simantics.graph.compiler.internal.store.LocationStore;
35 import org.simantics.graph.compiler.internal.store.VariableStore;
36 import org.simantics.graph.compiler.internal.validation.ReportCollisions;
37 import org.simantics.graph.compiler.internal.validation.ValidateGraph;
38 import org.simantics.graph.query.CompositeGraph;
39 import org.simantics.graph.query.Paths;
40 import org.simantics.graph.query.TransferableGraphConversion;
41 import org.simantics.graph.representation.Extensions;
42 import org.simantics.graph.representation.TransferableGraph1;
43 import org.simantics.graph.store.GraphStore;
44 import org.simantics.ltk.FileSource;
45 import org.simantics.ltk.ISource;
46 import org.simantics.ltk.Location;
47 import org.simantics.ltk.Problem;
49 public class GraphCompiler {
51 public static PrintStream out = System.out;
53 public static TransferableGraph1 read(File file) throws Exception {
54 DataContainer container = DataContainers.readFile(file);
55 return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);
58 public static TransferableGraph1 read(InputStream stream) throws AdaptException, IOException {
59 DataContainer container = DataContainers.readFile(new DataInputStream(stream));
61 return (TransferableGraph1)container.content.getValue(TransferableGraph1.BINDING);
64 public static InputStream write(TransferableGraph1 tg) throws BindingException, IOException {
65 Binding binding = TransferableGraph1.BINDING;
66 int hashCode = binding.hashValue(tg);
67 tg.extensions.put(Extensions.CACHED_HASHCODE, new Variant(Bindings.INTEGER, hashCode));
69 byte[] buffer = DataContainers.writeFile(
70 new DataContainer("graph", 1, new Variant(TransferableGraph1.BINDING, tg))
72 return new ByteArrayInputStream(buffer);
74 tg.extensions.remove(Extensions.CACHED_HASHCODE);
78 public static CompilationResult compile(
80 Collection<ISource> sources,
81 Collection<TransferableGraph1> dependencies,
82 ExternalFileLoader fileLoader,
83 GraphCompilerPreferences preferences) {
84 out.println(preferences);
86 Collection<Problem> errors = new ArrayList<Problem>();
87 GraphStore store = new GraphStore();
89 CompilationResult compilationResult = new CompilationResult();
90 compilationResult.errors = errors;
91 compilationResult.warnings = new ArrayList<Problem>();
93 Paths paths = new Paths(Layer0Version);
96 run(new Parsing(paths, sources, errors, store));
99 return compilationResult;
101 // Create composite graph of the new statements and dependencies
102 CompositeGraph graph;
104 long beginTime = System.nanoTime();
105 graph = TransferableGraphConversion.convert(paths, dependencies);
106 graph.addFragment(store);
107 long endTime = System.nanoTime();
108 reportTime("Composition", beginTime, endTime);
112 run(new MergeEqualResources(paths, store));
114 int[] unfoundedIdentitities = store.identities.getUnfoundedIdentities();
115 if(unfoundedIdentitities.length > 0) {
116 LocationStore locations = store.getStore(LocationStore.class);
117 for(int id : unfoundedIdentitities) {
118 errors.add(new Problem(
119 locations.getLocation(id),
120 "URIless resource used as a parent."));
122 return compilationResult;
125 store.identities.createPathToId(paths.ConsistsOf);
126 run(new CreateTemplates(graph, store, errors));
127 run(new ApplyTemplates(graph, store, errors, fileLoader));
128 run(new DefaultValueTyping(paths, store));
129 run(new Compactify(store));
130 run(new PropagateNewMarks(store));
131 run(new CreateInverseRelations(graph, store));
132 run(new AddConsistsOf(paths, store));
133 run(new ConvertPreValues(graph, store, errors));
134 run(new ReportCollisions(preferences, errors, store));
135 if(preferences.validate)
136 run(new ValidateGraph(graph, errors, store, preferences));
140 long beginTime = System.nanoTime();
141 compilationResult.graph = TransferableGraphConversion.convert(graph, store);
142 long endTime = System.nanoTime();
143 reportTime("Generate TG", beginTime, endTime);
146 // Create resource files
148 long beginTime = System.nanoTime();
149 compilationResult.resourceFiles = ResourceFileGenerator.generate(paths, store);
150 long endTime = System.nanoTime();
151 reportTime("Generate resources", beginTime, endTime);
154 // Create source info
156 VariableStore variableStore = store.getStore(VariableStore.class);
157 compilationResult.sourceInfo = variableStore.getSourceInfo();
160 // Fix source location of problems whose location is null at this point
162 for(Problem problem : compilationResult.errors) {
163 if(problem.getLocation() == null)
164 for(ISource source : sources) {
165 problem.setLocation(new Location(source));
168 else if(problem.getLocation().getSource() == null)
169 for(ISource source : sources) {
170 problem.getLocation().setSource(source);
174 for(Problem problem : compilationResult.warnings) {
175 if(problem.getLocation() == null)
176 for(ISource source : sources) {
177 problem.setLocation(new Location(source));
180 else if(problem.getLocation().getSource() == null)
181 for(ISource source : sources) {
182 problem.getLocation().setSource(source);
187 } catch(Exception e) {
189 ByteArrayOutputStream stream = new ByteArrayOutputStream();
190 e.printStackTrace(new PrintStream(stream));
191 String description = "Internal error: " +
192 new String(stream.toByteArray());
193 for(ISource source : sources)
194 errors.add(new Problem(new Location(source), description));
197 return compilationResult;
200 private static void run(Runnable runnable) {
201 long beginTime = System.nanoTime();
203 long endTime = System.nanoTime();
205 reportTime(runnable.getClass().getSimpleName(), beginTime, endTime);
208 public static void reportTime(String taskName, long beginTime, long endTime) {
209 StringBuilder sb = new StringBuilder();
210 @SuppressWarnings("resource")
211 Formatter formatter = new Formatter(sb, Locale.US);
212 formatter.format("%-25s %8.4f ms", taskName, (endTime - beginTime)*1e-6);
214 out.println(sb.toString());
217 public static void reportTime(String taskName, long beginTime) {
218 reportTime(taskName, beginTime, System.nanoTime());
221 public static void main(String[] args) {
222 Collection<ISource> sources = new ArrayList<ISource>();
223 Collection<TransferableGraph1> dependencies = new ArrayList<TransferableGraph1>();
224 String outputFile = null;
226 for(int i=0;i<args.length;++i) {
227 String arg = args[i];
228 if(arg.equals("-o")) {
229 if(++i < args.length)
230 outputFile = args[i];
233 if(arg.endsWith(".tg")) {
235 dependencies.add(read(new File(arg)));
236 } catch (Exception e) {
241 else if(arg.endsWith(".graph") || arg.endsWith(".pgraph")) {
242 sources.add(new FileSource(arg));
245 System.err.println("Invalid input file extension " + arg);
251 if(sources.isEmpty()) {
252 System.err.println("No source files");
256 if(outputFile == null) {
257 System.err.println("Name of the output file is not given (use -o flag).");
261 CompilationResult result = compile("1.0", sources, dependencies, null, new GraphCompilerPreferences());
262 for(Problem problem : result.getErrors())
263 out.println(problem.getLocation() + ": " + problem.getDescription());
265 if(result.getGraph() != null)
267 Files.createFile(new File(outputFile), TransferableGraph1.BINDING, result.getGraph());
268 } catch (Exception e) {