Fixing a deadlock. Some improvements to ModuleSourceRepository API 26/226/2
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Fri, 23 Dec 2016 14:09:58 +0000 (16:09 +0200)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Tue, 27 Dec 2016 11:41:09 +0000 (13:41 +0200)
refs #6851

Change-Id: I4328ab825ae1bb9f9ab529c947f6b02a8d90be83

12 files changed:
.gitattributes [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/GraphModuleSourceRepository.java
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModuleSourceRepository.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java [deleted file]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ClassModuleSourceRepository.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/CompositeModuleSourceRepository.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/FileModuleSourceRepository.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/MapModuleSourceRepository.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/ModuleSourceRepository.java
bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/BundleModuleSourceRepository.java
bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/FileSystemModuleSourceRepository.java
bundles/org.simantics.scl.osgi/src/org/simantics/scl/osgi/internal/ServiceBasedModuleSourceRepository.java

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..146504c
--- /dev/null
@@ -0,0 +1,10 @@
+*.java      text\r
+*.pgraph    text\r
+*.scl       text\r
+*.xml       text\r
+*.svg       text\r
+MANIFEST.MF text\r
+\r
+*.tg        binary\r
+*.png       binary\r
+*.gif       binary
\ No newline at end of file
index 3edc7bfeae28dd2a696dc9c3bd1d9d984c00de5d..10a217b9da073918575c19bacf98f2925619688e 100644 (file)
-package org.simantics.modeling.scl;\r
-\r
-import java.util.Collection;\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.RequestProcessorSpecific;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.procedure.SyncListener;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.ModelingUtils;\r
-import org.simantics.scl.compiler.module.repository.UpdateListener;\r
-import org.simantics.scl.compiler.source.ModuleSource;\r
-import org.simantics.scl.compiler.source.StringModuleSource;\r
-import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;\r
-import org.simantics.scl.runtime.SCLContext;\r
-import org.simantics.structural2.utils.StructuralUtils;\r
-import org.simantics.scl.runtime.tuple.Tuple0;\r
-\r
-import gnu.trove.procedure.TObjectProcedure;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-public enum GraphModuleSourceRepository implements ModuleSourceRepository {\r
-    INSTANCE;\r
-\r
-    @Override\r
-    public ModuleSource getModuleSource(final String moduleName, UpdateListener listener) {\r
-        if(!moduleName.startsWith("http://"))\r
-            return null;\r
-\r
-        Object graph = SCLContext.getCurrent().get("graph");\r
-        RequestProcessorSpecific requestProcessor;\r
-        if(graph instanceof ReadGraph)\r
-            requestProcessor = (ReadGraph)graph;\r
-        else\r
-            requestProcessor = Simantics.getSession();\r
-\r
-        Read<ModuleSource> request = new ReadModuleSource(moduleName);\r
-\r
-        try {\r
-            if(listener != null)\r
-                return requestProcessor.syncRequest(request, new ModuleListener(listener, moduleName));\r
-            else\r
-                return requestProcessor.syncRequest(request);\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-            return null;\r
-        }\r
-    }\r
-\r
-    static class ModuleListener implements SyncListener<ModuleSource> {\r
-        UpdateListener listener;\r
-        boolean alreadyExecutedOnce;\r
-        final String moduleName;\r
-        public ModuleListener(UpdateListener listener, String moduleName) {\r
-            this.listener = listener;\r
-            this.moduleName = moduleName;\r
-        }\r
-        @Override\r
-        public boolean isDisposed() {\r
-            return listener == null;\r
-        }\r
-        private void fireUpdate(ReadGraph graph) {\r
-            if(listener != null) {\r
-                SCLContext context = SCLContext.getCurrent();\r
-                Object oldGraph = context.put("graph", graph);\r
-                try {\r
-                    listener.notifyAboutUpdate();\r
-                } finally {\r
-                    listener = null;\r
-                    context.put("graph", oldGraph);\r
-                }\r
-            }\r
-        }\r
-        @Override\r
-        public void execute(ReadGraph graph, ModuleSource result)\r
-                throws DatabaseException {\r
-            if(alreadyExecutedOnce)\r
-                fireUpdate(graph);\r
-            else\r
-                alreadyExecutedOnce = true;\r
-        }\r
-        @Override\r
-        public void exception(ReadGraph graph, Throwable t)\r
-                throws DatabaseException {\r
-            t.printStackTrace();\r
-            if(alreadyExecutedOnce && listener != null)\r
-                fireUpdate(graph);\r
-        }\r
-    };\r
-    \r
-    public static class GraphModuleSource extends StringModuleSource {\r
-\r
-        private final boolean immutable;\r
-\r
-        public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) {\r
-            super(moduleName, classLoader, moduleText);\r
-            this.immutable = immutable;\r
-        }\r
-        \r
-        @Override\r
-        public boolean isUpdateable() {\r
-            return !immutable;\r
-        }\r
-        \r
-        @Override\r
-        public void update(String newSourceText) {\r
-            try {\r
-                Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText));\r
-            } catch (DatabaseException e) {\r
-                e.printStackTrace();\r
-            }\r
-        }\r
-    }\r
-\r
-    static class ReadModuleSource extends UnaryRead<String, ModuleSource> {\r
-        public ReadModuleSource(String moduleName) {\r
-            super(moduleName);\r
-        }\r
-\r
-        @Override\r
-        public ModuleSource perform(ReadGraph graph) throws DatabaseException {\r
-            Resource moduleResource = graph.getPossibleResource(parameter);\r
-            if(moduleResource == null)\r
-                return null;\r
-            Layer0 L0 = Layer0.getInstance(graph);\r
-            if(!graph.isInstanceOf(moduleResource, L0.SCLModule))\r
-                return null;\r
-            String text = graph.getRelatedValue(moduleResource, L0.SCLModule_definition);\r
-            boolean immutable = StructuralUtils.isImmutable(graph, moduleResource);\r
-            return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable);\r
-        }\r
-    }\r
-    \r
-    static class WriteModuleSource extends WriteRequest {\r
-        private final String moduleURI;\r
-        private final String sourceText;\r
-        \r
-        public WriteModuleSource(String moduleURI, String sourceText) {\r
-            this.moduleURI = moduleURI;\r
-            this.sourceText = sourceText;\r
-        }\r
-\r
-        @Override\r
-        public void perform(WriteGraph graph) throws DatabaseException {\r
-            Resource moduleResource = graph.getPossibleResource(moduleURI);\r
-            if(moduleResource == null)\r
-                return;\r
-            Layer0 L0 = Layer0.getInstance(graph);\r
-            if(!graph.isInstanceOf(moduleResource, L0.SCLModule))\r
-                return;\r
-            graph.claimLiteral(moduleResource, L0.SCLModule_definition, sourceText);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void forAllModules(TObjectProcedure<String> procedure) {\r
-        THashSet<String> moduleURIs;\r
-        try {\r
-            moduleURIs = Simantics.getSession().syncRequest(new Read<THashSet<String>>() {\r
-                @Override\r
-                public THashSet<String> perform(ReadGraph graph)\r
-                        throws DatabaseException {\r
-                    THashSet<String> result = new THashSet<String>(); \r
-                    Resource projectResource = Simantics.getProjectResource();\r
-                    Layer0 L0 = Layer0.getInstance(graph);\r
-                    for(Resource model : graph.getObjects(projectResource, L0.ConsistsOf)) {\r
-                        if(graph.isInstanceOf(model, L0.IndexRoot)) {\r
-                            for(Resource module : ModelingUtils.searchByType(graph, model, L0.SCLModule))\r
-                                result.add(graph.getURI(module));\r
-                        }\r
-                    }\r
-                    \r
-                    Collection<Resource> ontologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE);\r
-                    for (Resource ontology : ontologies) {\r
-                        for(Resource module : ModelingUtils.searchByType(graph, ontology, L0.SCLModule))\r
-                            result.add(graph.getURI(module));\r
-                    }\r
-                    \r
-                    return result;\r
-                }\r
-            });\r
-            moduleURIs.forEach(procedure);\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void checkUpdates() {\r
-    }\r
-\r
-    @Override\r
-    public String getDocumentation(String documentationName) {\r
-        return null;\r
-    }\r
-\r
-    @Override\r
-    public void forAllDocumentations(TObjectProcedure<String> procedure) {\r
-    }\r
-\r
-    @Override\r
-    public void clear() {\r
-    }\r
-}\r
+package org.simantics.modeling.scl;
+
+import java.util.ArrayList;
+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.structural2.utils.StructuralUtils;
+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<ModuleSource> 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<ModuleSource> {
+        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 {
+
+        private final boolean immutable;
+
+        public GraphModuleSource(String moduleName, ClassLoader classLoader, String moduleText, boolean immutable) {
+            super(moduleName, classLoader, moduleText);
+            this.immutable = immutable;
+        }
+        
+        @Override
+        public boolean isUpdateable() {
+            return !immutable;
+        }
+        
+        @Override
+        public void update(String newSourceText) {
+            try {
+                Simantics.getSession().syncRequest(new WriteModuleSource(getModuleName(), newSourceText));
+            } catch (DatabaseException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    static class ReadModuleSource extends UnaryRead<String, ModuleSource> {
+        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);
+            boolean immutable = StructuralUtils.isImmutable(graph, moduleResource);
+            return new GraphModuleSource(parameter, getClass().getClassLoader(), text, immutable);
+        }
+    }
+    
+    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<String> procedure) {
+        THashSet<String> moduleURIs;
+        try {
+            moduleURIs = Simantics.getSession().syncRequest(new Read<THashSet<String>>() {
+                @Override
+                public THashSet<String> perform(ReadGraph graph)
+                        throws DatabaseException {
+                    THashSet<String> result = new THashSet<String>(); 
+                    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<Resource> 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 Collection<String> getModuleNames() {
+        ArrayList<String> result = new ArrayList<>();
+        forAllModules((String name) -> {
+            result.add(name);
+            return true;
+        });
+        return result;
+    }
+}
index a8cefb1fa7e899d5df782cecd3dce03a6eefb237..6fbcfd8e973f50597bbf975d3c2b2461e21052a8 100644 (file)
@@ -1,73 +1,64 @@
-package org.simantics.modeling.scl;\r
-\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.scl.compiler.module.repository.UpdateListener;\r
-import org.simantics.scl.compiler.source.ModuleSource;\r
-import org.simantics.scl.compiler.source.PrecompiledModuleSource;\r
-import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;\r
-import org.simantics.scl.runtime.SCLContext;\r
-\r
-import gnu.trove.procedure.TObjectProcedure;\r
-\r
-public enum OntologyModuleSourceRepository implements ModuleSourceRepository {\r
-    INSTANCE;\r
-\r
-       static class ModuleSourceRequest extends UnaryRead<String, ModuleSource> {\r
-\r
-        public ModuleSourceRequest(String moduleName) {\r
-                       super(moduleName);\r
-               }\r
-\r
-               @Override\r
-        public ModuleSource perform(ReadGraph graph) throws DatabaseException {\r
-            return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0);\r
-        }\r
-\r
-    };\r
-       \r
-    @Override\r
-    public ModuleSource getModuleSource(final String moduleName,\r
-            UpdateListener listener) {\r
-        if(!moduleName.startsWith("http://"))\r
-            return null; // Don't do a graph request if this cannot be a resource\r
-        \r
-        ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph");\r
-        \r
-        try {\r
-            if(graph != null) {\r
-                return new PrecompiledModuleSource(new OntologyModule(graph, moduleName), -1.0);\r
-            }\r
-\r
-            return Simantics.getSession().syncRequest(new ModuleSourceRequest(moduleName));\r
-        } catch(DatabaseException e) {\r
-            e.printStackTrace();\r
-            return null;\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void forAllModules(TObjectProcedure<String> procedure) {\r
-    }\r
-    \r
-    @Override\r
-    public void checkUpdates() {\r
-    }\r
-\r
-    @Override\r
-    public String getDocumentation(String documentationName) {\r
-        return null;\r
-    }\r
-\r
-    @Override\r
-    public void forAllDocumentations(TObjectProcedure<String> procedure) {\r
-    }\r
-\r
-    @Override\r
-    public void clear() {\r
-    }\r
-\r
-}\r
+package org.simantics.modeling.scl;
+
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.scl.compiler.module.repository.UpdateListener;
+import org.simantics.scl.compiler.source.ModuleSource;
+import org.simantics.scl.compiler.source.PrecompiledModuleSource;
+import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
+import org.simantics.scl.runtime.SCLContext;
+
+import gnu.trove.procedure.TObjectProcedure;
+
+public enum OntologyModuleSourceRepository implements ModuleSourceRepository {
+    INSTANCE;
+
+       static class ModuleSourceRequest extends UnaryRead<String, ModuleSource> {
+
+        public ModuleSourceRequest(String moduleName) {
+                       super(moduleName);
+               }
+
+               @Override
+        public ModuleSource perform(ReadGraph graph) throws DatabaseException {
+            return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0);
+        }
+
+    };
+       
+    @Override
+    public ModuleSource getModuleSource(final String moduleName,
+            UpdateListener listener) {
+        if(!moduleName.startsWith("http://"))
+            return null; // Don't do a graph request if this cannot be a resource
+        
+        ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph");
+        
+        try {
+            if(graph != null) {
+                return new PrecompiledModuleSource(new OntologyModule(graph, moduleName), -1.0);
+            }
+
+            return Simantics.getSession().syncRequest(new ModuleSourceRequest(moduleName));
+        } catch(DatabaseException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public void forAllModules(TObjectProcedure<String> procedure) {
+    }
+    
+    @Override
+    public Collection<String> getModuleNames() {
+        return Collections.emptyList();
+    }
+
+}
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/repository/AbstractModuleSourceRepository.java
deleted file mode 100644 (file)
index 1436310..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.simantics.scl.compiler.source.repository;
-
-import gnu.trove.procedure.TObjectProcedure;
-
-
-public abstract class AbstractModuleSourceRepository implements ModuleSourceRepository {
-    @Override
-    public String getDocumentation(String documentationName) {
-        return null;
-    }
-    
-    @Override
-    public void forAllDocumentations(TObjectProcedure<String> procedure) {
-    }
-    
-    @Override
-    public void checkUpdates() {
-    }
-}
index 873859a2de6a65c5a2eec24e853523bafae09913..581f1db8a617e3f6063f40f775ed6c3f9d31bcda 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.source.repository;
 
 import java.io.IOException;
 import java.net.URL;
+import java.util.Collection;
 
 import org.simantics.scl.compiler.module.ImportDeclaration;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
@@ -11,7 +12,7 @@ import org.simantics.scl.compiler.source.ModuleSource;
 import gnu.trove.procedure.TObjectProcedure;
 import gnu.trove.set.hash.THashSet;
 
-public class ClassModuleSourceRepository extends AbstractModuleSourceRepository {
+public class ClassModuleSourceRepository implements ModuleSourceRepository {
     
     private final Class<?> clazz;
     private final String path;
@@ -36,6 +37,11 @@ public class ClassModuleSourceRepository extends AbstractModuleSourceRepository
         return new ClassModuleSource(moduleName, clazz, classLoader, path + "/" + moduleName + ".scl", getBuiltinImports());
     }
 
+    @Override
+    public Collection<String> getModuleNames() {
+        return modules;
+    }
+    
     @Override
     public void forAllModules(TObjectProcedure<String> procedure) {
         modules.forEach(procedure);
@@ -44,9 +50,4 @@ public class ClassModuleSourceRepository extends AbstractModuleSourceRepository
     protected ImportDeclaration[] getBuiltinImports() {
         return ClassModuleSource.DEFAULT_IMPORTS;
     }
-
-    @Override
-    public void clear() {
-        
-    }
 }
index 82bb0bcf94368296ccc083adb5f3e6e196777878..b55e3d285f19b31abba33ffcdf1c1a99b461f2f1 100644 (file)
@@ -1,5 +1,8 @@
 package org.simantics.scl.compiler.source.repository;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.ModuleSource;
 
@@ -50,14 +53,36 @@ public class CompositeModuleSourceRepository implements ModuleSourceRepository {
             sourceRepository.forAllModules(procedure);
     }
     
+    @Override
+    public Collection<String> getModuleNames() {
+        ArrayList<String> result = new ArrayList<>();
+        forAllModules((String name) -> {
+            result.add(name);
+            return true;
+        });
+        return result;
+    }
+    
     @Override
     public void forAllDocumentations(TObjectProcedure<String> procedure) {
         for(ModuleSourceRepository sourceRepository : children)
             sourceRepository.forAllDocumentations(procedure);
     }
+    
+    @Override
+    public Collection<String> getDocumentationNames() {
+        ArrayList<String> result = new ArrayList<>();
+        forAllDocumentations((String name) -> {
+            result.add(name);
+            return true;
+        });
+        return result;
+    }
 
     @Override
     public void checkUpdates() {
+        for (ModuleSourceRepository child : children)
+            child.checkUpdates();
     }
 
     @Override
index 805dd77f465b90b999ecc27aec7f3a3643842139..d2caa38835e3601fa5c47cebd9fb0ab8681bd29b 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.source.repository;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collection;
 
 import org.simantics.scl.compiler.module.ImportDeclaration;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
@@ -12,7 +13,7 @@ import org.simantics.scl.compiler.source.ModuleSource;
 import gnu.trove.procedure.TObjectProcedure;
 import gnu.trove.set.hash.THashSet;
 
-public class FileModuleSourceRepository extends AbstractModuleSourceRepository {
+public class FileModuleSourceRepository implements ModuleSourceRepository {
     
     private final File path;
     private final ClassLoader classLoader;
@@ -37,12 +38,12 @@ public class FileModuleSourceRepository extends AbstractModuleSourceRepository {
         modules.forEach(procedure);
     }
     
+    @Override
+    public Collection<String> getModuleNames() {
+        return modules;
+    }
+    
     protected ImportDeclaration[] getBuiltinImports() {
         return ClassModuleSource.DEFAULT_IMPORTS;
     }
-
-    @Override
-    public void clear() {
-        
-    }
 }
index 9872451c311e904cb72aec9bd34bad833184a240..939010d40bc9392db981081bfbdb52496344fcf2 100644 (file)
@@ -1,5 +1,7 @@
 package org.simantics.scl.compiler.source.repository;
 
+import java.util.Collection;
+
 import org.simantics.scl.compiler.module.Module;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.ModuleSource;
@@ -50,6 +52,11 @@ public class MapModuleSourceRepository implements ModuleSourceRepository {
         return modules.get(moduleName);
     }
 
+    @Override
+    public Collection<String> getModuleNames() {
+        return modules.keySet();
+    }
+    
     @Override
     public void forAllModules(TObjectProcedure<String> procedure) {
         modules.forEachKey(procedure);
@@ -61,16 +68,7 @@ public class MapModuleSourceRepository implements ModuleSourceRepository {
     }
     
     @Override
-    public void forAllDocumentations(TObjectProcedure<String> procedure) {
-        for(String documentationName : documentations.keySet())
-            procedure.execute(documentationName);
-    }
-    
-    @Override
-    public void checkUpdates() {
-    }
-
-    @Override
-    public void clear() {
+    public Collection<String> getDocumentationNames() {
+        return documentations.keySet();
     }
 }
index 76698f5be6a44d9cea0db368d933b2e2d3251deb..c335a8aa1349d8bc4cf42c1c6ada90fd2961568e 100644 (file)
@@ -1,5 +1,8 @@
 package org.simantics.scl.compiler.source.repository;
 
+import java.util.Collection;
+import java.util.Collections;
+
 import org.simantics.scl.compiler.module.repository.ModuleRepository;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.ModuleSource;
@@ -13,10 +16,64 @@ import gnu.trove.procedure.TObjectProcedure;
  * @author Hannu Niemist&ouml;
  */
 public interface ModuleSourceRepository {
+    /**
+     * Returns all module names governed by this repository. Some implementations
+     * may return empty collection, even if the contain modules, if it is hard
+     * to discover all modules (for example file system based module repository 
+     * works like this).
+     */
+    Collection<String> getModuleNames();
+    
+    /**
+     * Calls the given procedure with all module names returned by {@link #getModuleNames}
+     */
+    default void forAllModules(TObjectProcedure<String> procedure) {
+        for(String module : getModuleNames())
+            if(!procedure.execute(module))
+                return;
+    }
+    
+    /**
+     * Returns the module source of the given module name or null, if the module does not exists.
+     * If {@code listener} is not null, it is called when the module contents change.
+     */
     ModuleSource getModuleSource(String moduleName, UpdateListener listener);
-    void forAllModules(TObjectProcedure<String> procedure);
-    String getDocumentation(String documentationName);
-    void forAllDocumentations(TObjectProcedure<String> procedure);
-    void checkUpdates();
-    void clear();
+    
+    /**
+     * Returns all documentation names governed by this repository. Some implementations
+     * may return empty collection, even if the contain documentation.
+     */
+    default Collection<String> getDocumentationNames() {
+        return Collections.emptyList();
+    }
+    
+    /**
+     * Calls the given procedure with all documentation names eturned by {@link #getDocumentationNames}
+     */
+    default void forAllDocumentations(TObjectProcedure<String> procedure) {
+        for(String module : getDocumentationNames())
+            if(!procedure.execute(module))
+                return;
+    }
+
+    /**
+     * Returns original markdown text for the given documentation name or null
+     * if the documentation does not exist.
+     */
+    default String getDocumentation(String documentationName) {
+        return null;
+    }
+    
+    /**
+     * Triggers repository to check if module contents have been changed. Some repositories listen
+     * changes and report them to update listeners even without manual triggering.
+     */
+    default void checkUpdates() {
+    }
+
+    /**
+     * Resets the repository and removes listeners. This is only used during regression testing and shouldn't be called during normal operation.
+     */
+    default void clear() {
+    }
 }
index 31d06b72619399ffbb9d8f9b4666c2c468303bdd..b3f5ac319122941c621ae89420558ba9ef3e3b2d 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.osgi.internal;
 
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Enumeration;
 
 import org.osgi.framework.Bundle;
@@ -14,16 +15,14 @@ import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.util.tracker.BundleTracker;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.ModuleSource;
-import org.simantics.scl.compiler.source.repository.AbstractModuleSourceRepository;
 import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
 
 import gnu.trove.map.hash.THashMap;
 import gnu.trove.procedure.TObjectObjectProcedure;
-import gnu.trove.procedure.TObjectProcedure;
 import gnu.trove.set.hash.THashSet;
 
 @Component
-public class BundleModuleSourceRepository extends AbstractModuleSourceRepository implements ModuleSourceRepository {
+public class BundleModuleSourceRepository implements ModuleSourceRepository {
     
     Tracker tracker;
     THashMap<String, BundleModuleSource> modules = new THashMap<String, BundleModuleSource>();
@@ -107,8 +106,13 @@ public class BundleModuleSourceRepository extends AbstractModuleSourceRepository
     }
 
     @Override
-    synchronized public void forAllModules(TObjectProcedure<String> procedure) {
-        modules.forEachKey(procedure);
+    public synchronized Collection<String> getModuleNames() {
+        return new ArrayList<String>(modules.keySet());
+    }
+    
+    @Override
+    public synchronized Collection<String> getDocumentationNames() {
+        return new ArrayList<String>(documentations.keySet());
     }
     
     @Override
@@ -119,12 +123,7 @@ public class BundleModuleSourceRepository extends AbstractModuleSourceRepository
         else
             return source.getText();
     }
-
-    @Override
-    synchronized public void forAllDocumentations(TObjectProcedure<String> procedure) {
-        documentations.forEachKey(procedure);
-    }
-
+    
     @Override
     public void checkUpdates() {
         synchronized(this) {
index 0e26c1d273acc71cbe385f7a90dea810cf4ddbde..68e6ac0502db9342680b57a9014f8a5ef1a3f5c1 100644 (file)
@@ -1,6 +1,8 @@
 package org.simantics.scl.osgi.internal;
 
 import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
 
 import org.osgi.service.component.annotations.Component;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
@@ -23,23 +25,12 @@ public class FileSystemModuleSourceRepository implements ModuleSourceRepository
     }
 
     @Override
-    synchronized public void forAllModules(TObjectProcedure<String> procedure) {
+    public Collection<String> getModuleNames() {
+        return Collections.emptyList();
     }
     
     @Override
-    public String getDocumentation(String documentationName) {
-        return null;
+    public void forAllModules(TObjectProcedure<String> procedure) {
     }
     
-    @Override
-    public void forAllDocumentations(TObjectProcedure<String> procedure) {
-    }
-
-    @Override
-    public void checkUpdates() {
-    }
-
-    @Override
-    public void clear() {
-    }
 }
index 9b173e48d7c1c3f6d8ecccb9cdda762afae9d935..ac8384c242bf54e834148f6cfa8b7c31d2220024 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.scl.osgi.internal;
 
-import gnu.trove.procedure.TObjectProcedure;
+import java.util.ArrayList;
+import java.util.Collection;
 
 import org.osgi.framework.BundleContext;
 import org.osgi.util.tracker.ServiceTracker;
@@ -8,6 +9,8 @@ import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.ModuleSource;
 import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
 
+import gnu.trove.procedure.TObjectProcedure;
+
 public class ServiceBasedModuleSourceRepository implements ModuleSourceRepository {
 
     ServiceTracker<ModuleSourceRepository, ModuleSourceRepository> sourceRepositories;
@@ -45,6 +48,7 @@ public class ServiceBasedModuleSourceRepository implements ModuleSourceRepositor
     
     @Override
     public String getDocumentation(String documentationName) {
+        // getServices is internally synchronized, so no need to synchronize here
         Object[] services = sourceRepositories.getServices();
         if(services != null)
             for(Object sourceRepository_ : services) {
@@ -58,18 +62,43 @@ public class ServiceBasedModuleSourceRepository implements ModuleSourceRepositor
 
     @Override
     public void forAllModules(TObjectProcedure<String> procedure) {
-        for(Object sourceRepository_ : sourceRepositories.getServices()) {
-            ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_;
-            sourceLoader.forAllModules(procedure);
-        }
+        // getServices is internally synchronized, so no need to synchronize here
+        Object[] services = sourceRepositories.getServices();
+        if(services != null)
+            for(Object sourceRepository_ : services) {
+                ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_;
+                sourceLoader.forAllModules(procedure);
+            }
+    }
+    
+    @Override
+    public Collection<String> getModuleNames() {
+        ArrayList<String> result = new ArrayList<>();
+        forAllModules((String name) -> {
+            result.add(name);
+            return true;
+        });
+        return result;
     }
     
     @Override
     public void forAllDocumentations(TObjectProcedure<String> procedure) {
-        for(Object sourceRepository_ : sourceRepositories.getServices()) {
-            ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_;
-            sourceLoader.forAllDocumentations(procedure);
-        }
+        Object[] services = sourceRepositories.getServices();
+        if(services != null)
+            for(Object sourceRepository_ : services) {
+                ModuleSourceRepository sourceLoader = (ModuleSourceRepository)sourceRepository_;
+                sourceLoader.forAllDocumentations(procedure);
+            }
+    }
+    
+    @Override
+    public Collection<String> getDocumentationNames() {
+        ArrayList<String> result = new ArrayList<>();
+        forAllDocumentations((String name) -> {
+            result.add(name);
+            return true;
+        });
+        return result;
     }
 
     @Override
@@ -80,8 +109,4 @@ public class ServiceBasedModuleSourceRepository implements ModuleSourceRepositor
         }
     }
 
-    @Override
-    public void clear() {
-    }
-
 }