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