package org.simantics.modeling.scl; import java.util.Collection; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessorSpecific; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.SyncListener; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingUtils; import org.simantics.scl.compiler.module.repository.UpdateListener; import org.simantics.scl.compiler.source.ModuleSource; import org.simantics.scl.compiler.source.StringModuleSource; import org.simantics.scl.compiler.source.repository.ModuleSourceRepository; import org.simantics.scl.runtime.SCLContext; import org.simantics.scl.runtime.tuple.Tuple0; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; public enum GraphModuleSourceRepository implements ModuleSourceRepository { INSTANCE; @Override public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) { if(!moduleName.startsWith("http://")) return null; Object graph = SCLContext.getCurrent().get("graph"); RequestProcessorSpecific requestProcessor; if(graph instanceof ReadGraph) requestProcessor = (ReadGraph)graph; else requestProcessor = Simantics.getSession(); Read request = new ReadModuleSource(moduleName); try { if(listener != null) return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName)); else return requestProcessor.syncRequest(request); } catch (DatabaseException e) { e.printStackTrace(); return null; } } static class ModuleListener implements SyncListener { UpdateListener listener; boolean alreadyExecutedOnce; final String moduleName; public ModuleListener(UpdateListener listener, String moduleName) { this.listener = listener; this.moduleName = moduleName; } @Override public boolean isDisposed() { return listener == null; } private void fireUpdate(ReadGraph graph) { if(listener != null) { SCLContext context = SCLContext.getCurrent(); Object oldGraph = context.put("graph", graph); try { listener.notifyAboutUpdate(); } finally { listener = null; context.put("graph", oldGraph); } } } @Override public void execute(ReadGraph graph, ModuleSource result) throws DatabaseException { if(alreadyExecutedOnce) fireUpdate(graph); else alreadyExecutedOnce = true; } @Override public void exception(ReadGraph graph, Throwable t) throws DatabaseException { t.printStackTrace(); if(alreadyExecutedOnce && listener != null) fireUpdate(graph); } }; public static class GraphModuleSource extends StringModuleSource { public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText) { super(moduleName, classLoader, moduleText); } @Override public boolean isUpdateable() { return true; } @Override public void update(String newSourceText) { try { Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText)); } catch (DatabaseException e) { e.printStackTrace(); } } } static class ReadModuleSource extends UnaryRead { public ReadModuleSource(String moduleName) { super(moduleName); } @Override public ModuleSource perform(ReadGraph graph) throws DatabaseException { Resource moduleResource = graph.getPossibleResource(parameter); if(moduleResource == null) return null; Layer0 L0 = Layer0.getInstance(graph); if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) return null; String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition); return new GraphModuleSource(parameter, getClass().getClassLoader(), text); } } static class WriteModuleSource extends WriteRequest { private final String moduleURI; private final String sourceText; public WriteModuleSource(String moduleURI, String sourceText) { this.moduleURI = moduleURI; this.sourceText = sourceText; } @Override public void perform(WriteGraph graph) throws DatabaseException { Resource moduleResource = graph.getPossibleResource(moduleURI); if(moduleResource == null) return; Layer0 L0 = Layer0.getInstance(graph); if(!graph.isInstanceOf(moduleResource, L0.SCLModule)) return; graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText); } } @Override public void forAllModules(TObjectProcedure procedure) { THashSet moduleURIs; try { moduleURIs = Simantics.getSession().syncRequest(new Read>() { @Override public THashSet perform(ReadGraph graph) throws DatabaseException { THashSet result = new THashSet(); Resource projectResource = Simantics.getProjectResource(); Layer0 L0 = Layer0.getInstance(graph); for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) { if(graph.isInstanceOf(model, L0.IndexRoot)) { for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule)) result.add(graph.getURI(module)); } } Collection ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE); for (Resource ontology : ontologies) { for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule)) result.add(graph.getURI(module)); } return result; } }); moduleURIs.forEach(procedure); } catch (DatabaseException e) { e.printStackTrace(); } } @Override public void checkUpdates() { } @Override public String getDocumentation(String documentationName) { return null; } @Override public void forAllDocumentations(TObjectProcedure procedure) { } @Override public void clear() { } }