From: Hannu Niemistö Date: Tue, 9 Oct 2018 07:35:43 +0000 (+0300) Subject: Use proper environment to resolve SCL types in ontology module X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=0010341b4736774d0f658d01e83657a102aa58b9;p=simantics%2Fplatform.git Use proper environment to resolve SCL types in ontology module gitlab #131 Change-Id: I9b16546633d8d566cb3d38d48d609878e794eae3 --- diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/EnvironmentRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/EnvironmentRequest.java new file mode 100644 index 000000000..2e37adee8 --- /dev/null +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/EnvironmentRequest.java @@ -0,0 +1,148 @@ +package org.simantics.db.layer0.util; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ParametrizedPrimitiveRead; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.internal.SimanticsInternal; +import org.simantics.db.procedure.Listener; +import org.simantics.db.request.Read; +import org.simantics.scl.compiler.environment.Environment; +import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification; +import org.simantics.scl.compiler.module.repository.ImportFailureException; +import org.simantics.scl.compiler.module.repository.UpdateListener; +import org.simantics.scl.osgi.SCLOsgi; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.utils.datastructures.Pair; + +/** + * Finds the environment of a model or other index root. + */ +public abstract class EnvironmentRequest extends UnaryRead> { + + public EnvironmentRequest(Resource parameter) { + super(parameter); + } + + protected abstract void fillEnvironmentSpecification(EnvironmentSpecification environmentSpecification); + protected abstract String getRootModuleName(); + + static class UpdateListenerImpl extends UpdateListener { + + final EnvironmentSpecification environmentSpecification; + final Listener callback; + + UpdateListenerImpl(EnvironmentSpecification environmentSpecification, Listener callback) { + this.environmentSpecification = environmentSpecification; + this.callback = callback; + } + + @Override + public void notifyAboutUpdate() { + if(callback.isDisposed()) { + stopListening(); + return; + } + getEnvironment(environmentSpecification, callback, this); + } + }; + + public static void getEnvironment(EnvironmentSpecification environmentSpecification, Listener callback, UpdateListenerImpl listener) { + + try { + + SCLContext context = SCLContext.getCurrent(); + + Environment env; + Object graph = context.get("graph"); + if(graph == null) + try { + env = SimanticsInternal.getSession().syncRequest(new Read() { + @Override + public Environment perform(ReadGraph graph) throws DatabaseException { + + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.get("graph"); + try { + sclContext.put("graph", graph); + return SCLOsgi.MODULE_REPOSITORY.createEnvironment( + environmentSpecification, listener); + } catch (ImportFailureException e) { + throw new DatabaseException(e); + } catch (Throwable t) { + throw new DatabaseException(t); + } finally { + sclContext.put("graph", oldGraph); + } + } + }); + } catch (DatabaseException e) { + callback.exception(e); + return; + } + else + env = SCLOsgi.MODULE_REPOSITORY.createEnvironment( + environmentSpecification, listener); + callback.execute(env); + } catch (ImportFailureException e) { + callback.exception(new DatabaseException(e)); + } + + } + + @Override + public Pair perform(ReadGraph graph) + throws DatabaseException { + final EnvironmentSpecification environmentSpecification = EnvironmentSpecification.of( + "Builtin", "", + "StandardLibrary", ""); + fillEnvironmentSpecification(environmentSpecification); + Resource mainModule = Layer0Utils.getPossibleChild(graph, parameter, getRootModuleName()); + String mainModuleUri; + if(mainModule != null) { + mainModuleUri = graph.getURI(mainModule); + environmentSpecification.importModule(mainModuleUri, ""); + } + else + mainModuleUri = graph.getURI(parameter) + "/#"; // Add something dummy to the model uri that cannot be in a real URI + + return Pair.make(environmentSpecification, graph.syncRequest(new ParametrizedPrimitiveRead(mainModuleUri) { + + UpdateListenerImpl sclListener; + + @Override + public void register(ReadGraph graph, Listener procedure) { + + SCLContext context = SCLContext.getCurrent(); + Object oldGraph = context.put("graph", graph); + try { + + if(procedure.isDisposed()) { + getEnvironment(environmentSpecification, procedure, null); + } else { + sclListener = new UpdateListenerImpl(environmentSpecification, procedure); + sclListener.notifyAboutUpdate(); + } + + } finally { + context.put("graph", oldGraph); + } + + } + + @Override + public void unregistered() { + if(sclListener != null) + sclListener.stopListening(); + } + + })); + } + + @Override + public int hashCode() { + return 31*getClass().hashCode() + super.hashCode(); + } + +} diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java index ec698e670..96ee42182 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java @@ -2,7 +2,6 @@ package org.simantics.modeling.scl.ontologymodule; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -12,8 +11,11 @@ import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.request.IndexRoot; import org.simantics.db.common.uri.UnescapedChildMapOfResource; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.util.EnvironmentRequest; +import org.simantics.db.layer0.util.RuntimeEnvironmentRequest; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.scl.compiler.common.names.Name; @@ -30,7 +32,9 @@ import org.simantics.scl.compiler.elaboration.macros.MacroRule; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.elaboration.relations.SCLRelation; +import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.environment.filter.NamespaceFilter; +import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.module.ImportDeclaration; import org.simantics.scl.compiler.module.LazyModule; @@ -41,6 +45,7 @@ import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException; import org.simantics.scl.compiler.types.kinds.Kinds; import org.simantics.scl.runtime.SCLContext; +import org.simantics.utils.datastructures.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,6 +55,7 @@ import gnu.trove.procedure.TObjectProcedure; public class OntologyModule extends LazyModule { private static final Logger LOGGER = LoggerFactory.getLogger(OntologyModule.class); + public static final String SCL_TYPES_NAME = "SCLTypes"; private static final String DB_MODULE = "Simantics/DB"; private static final String VARIABLE_MODULE = "Simantics/Variable"; private static final Collection DEPENDENCIES = Arrays.asList( @@ -60,15 +66,38 @@ public class OntologyModule extends LazyModule { private static final TCon BROWSABLE = Types.con(DB_MODULE, "Browsable"); private static final TCon VARIABLE = Types.con(VARIABLE_MODULE, "Variable"); - Resource ontology; - String defaultLocalName; - THashMap> childMaps = new THashMap>(); + private Resource ontology; + private String defaultLocalName; + private THashMap> childMaps = new THashMap>(); + private List importDeclarations; + private Environment environment; public OntologyModule(ReadGraph graph, String moduleName) throws DatabaseException { super(moduleName); ontology = graph.getResource(moduleName); readDefaultLocalName(graph); childMaps.put(ontology, createLocalMap(graph, ontology)); + Pair pair = graph.syncRequest(new Read>() { + @Override + public Pair perform(ReadGraph graph) throws DatabaseException { + Resource indexRoot = graph.syncRequest(new IndexRoot(ontology)); + return graph.syncRequest(new EnvironmentRequest(indexRoot) { + @Override + protected void fillEnvironmentSpecification(EnvironmentSpecification environmentSpecification) { + /*if(!moduleName.equals("http://www.simantics.org/Layer0-1.1")) { // Prevent cyclic dependencies + environmentSpecification.importModule(DB_MODULE, ""); + environmentSpecification.importModule(VARIABLE_MODULE, ""); + }*/ + } + @Override + protected String getRootModuleName() { + return SCL_TYPES_NAME; + } + }); + } + }); + this.importDeclarations = pair.first.imports; + this.environment = pair.second; } private void readDefaultLocalName(ReadGraph graph) throws DatabaseException { @@ -85,8 +114,7 @@ public class OntologyModule extends LazyModule { @Override public List getDependencies() { - //return DEPENDENCIES; - return Collections.emptyList(); + return importDeclarations; } private static interface ResourceSearchResult {} @@ -180,7 +208,7 @@ public class OntologyModule extends LazyModule { @FunctionalInterface private static interface ResourceFunctionGenerator { - SCLValue createValue(Name name, Resource resource); + SCLValue createValue(Name name, Resource resource, Environment environment); } private static class RelatedValueMacroRule implements MacroRule { @@ -245,8 +273,8 @@ public class OntologyModule extends LazyModule { private final static HashMap VALUE_GENERATOR_MAP = new HashMap<>(); static { TVar A = Types.var(Kinds.STAR); - VALUE_GENERATOR_MAP.put("value", (name, resource) -> { - SCLRelationInfo relationInfo = SCLRelationInfoRequest.getRelationInfo(resource); + VALUE_GENERATOR_MAP.put("value", (name, resource, environment) -> { + SCLRelationInfo relationInfo = SCLRelationInfoRequest.getRelationInfo(resource, environment); if(relationInfo == null) return null; @@ -255,8 +283,8 @@ public class OntologyModule extends LazyModule { value.setMacroRule(new RelatedValueMacroRule(resource, relationInfo, false)); return value; }); - VALUE_GENERATOR_MAP.put("possibleValue", (name, resource) -> { - SCLRelationInfo relationInfo = SCLRelationInfoRequest.getRelationInfo(resource); + VALUE_GENERATOR_MAP.put("possibleValue", (name, resource, environment) -> { + SCLRelationInfo relationInfo = SCLRelationInfoRequest.getRelationInfo(resource, environment); if(relationInfo == null) return null; @@ -284,7 +312,7 @@ public class OntologyModule extends LazyModule { if(generator == null) return null; else - return generator.createValue(Name.create(getName(), name), resourceAndSuffix.resource); + return generator.createValue(Name.create(getName(), name), resourceAndSuffix.resource, environment); } else return null; @@ -469,6 +497,7 @@ public class OntologyModule extends LazyModule { childMaps.clear(); childMaps = null; ontology = null; + environment = null; } @Override diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModuleSourceRepository.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModuleSourceRepository.java index 134b2b3d7..0b882efc3 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModuleSourceRepository.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModuleSourceRepository.java @@ -8,9 +8,14 @@ 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.errors.Failable; +import org.simantics.scl.compiler.errors.Failure; +import org.simantics.scl.compiler.errors.Success; +import org.simantics.scl.compiler.module.Module; +import org.simantics.scl.compiler.module.options.ModuleCompilationOptions; +import org.simantics.scl.compiler.module.repository.ModuleRepository; 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.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,15 +27,15 @@ public enum OntologyModuleSourceRepository implements ModuleSourceRepository { private static final Logger LOGGER = LoggerFactory.getLogger(OntologyModuleSourceRepository.class); - static class ModuleSourceRequest extends UnaryRead { + static class ModuleRequest extends UnaryRead { - public ModuleSourceRequest(String moduleName) { + public ModuleRequest(String moduleName) { super(moduleName); } @Override - public ModuleSource perform(ReadGraph graph) throws DatabaseException { - return new PrecompiledModuleSource(new OntologyModule(graph, parameter), -1.0); + public Module perform(ReadGraph graph) throws DatabaseException { + return new OntologyModule(graph, parameter); } }; @@ -41,12 +46,33 @@ public enum OntologyModuleSourceRepository implements ModuleSourceRepository { if(!moduleName.startsWith("http://")) return null; // Don't do a graph request if this cannot be a resource - try { - return Simantics.getAvailableRequestProcessor().syncRequest(new ModuleSourceRequest(moduleName)); - } catch(DatabaseException e) { - LOGGER.error("Failed to read ontology module " + moduleName + ".", e); - return null; - } + return new ModuleSource() { + + @Override + public double getPriority() { + return -1.0; + } + + @Override + public String getModuleName() { + return moduleName; + } + + @Override + public ClassLoader getClassLoader() { + return getClass().getClassLoader(); + } + + @Override + public Failable compileModule(ModuleRepository environment, UpdateListener listener, + ModuleCompilationOptions options) { + try { + return new Success(Simantics.getAvailableRequestProcessor().syncRequest(new ModuleRequest(moduleName))); + } catch(DatabaseException e) { + return new Failure(e); + } + } + }; } @Override diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/SCLRelationInfoRequest.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/SCLRelationInfoRequest.java index 6662463c5..e7ed5bd97 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/SCLRelationInfoRequest.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/SCLRelationInfoRequest.java @@ -6,21 +6,23 @@ import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.BinaryRead; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.layer0.Layer0; +import org.simantics.scl.compiler.environment.Environment; +import org.simantics.scl.compiler.environment.Environments; +import org.simantics.scl.compiler.top.SCLExpressionCompilationException; import org.simantics.scl.compiler.types.Type; -import org.simantics.scl.compiler.types.Types; -import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException; import org.simantics.scl.db.SCLCompilationRequestProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SCLRelationInfoRequest extends UnaryRead { +public class SCLRelationInfoRequest extends BinaryRead { private static final Logger LOGGER = LoggerFactory.getLogger(SCLRelationInfoRequest.class); - private SCLRelationInfoRequest(Resource resource) { - super(resource); + private SCLRelationInfoRequest(Resource resource, Environment environment) { + super(resource, environment); } @Override @@ -58,8 +60,8 @@ public class SCLRelationInfoRequest extends UnaryRead Type type; try { - type = Types.parseType(valueType); - } catch (SCLTypeParseException e) { + type = Environments.getType(parameter2, valueType); + } catch (SCLExpressionCompilationException e) { LOGGER.warn("Couldn't parse the value type of relation {}. Definition was '{}'.", graph.getURI(parameter), valueType); return null; } @@ -67,9 +69,9 @@ public class SCLRelationInfoRequest extends UnaryRead return new SCLRelationInfo(type, name); } - public static SCLRelationInfo getRelationInfo(Resource resource) { + public static SCLRelationInfo getRelationInfo(Resource resource, Environment environment) { try { - return SCLCompilationRequestProcessor.getRequestProcessor().syncRequest(new SCLRelationInfoRequest(resource), TransientCacheListener.instance()); + return SCLCompilationRequestProcessor.getRequestProcessor().syncRequest(new SCLRelationInfoRequest(resource, environment), TransientCacheListener.instance()); } catch(DatabaseException e) { LOGGER.error("SCLRelationInfoRequest failed.", e); return null;