--- /dev/null
+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<Resource, Pair<EnvironmentSpecification, Environment>> {
+
+ 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<Environment> callback;
+
+ UpdateListenerImpl(EnvironmentSpecification environmentSpecification, Listener<Environment> 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<Environment> 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<Environment>() {
+ @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<EnvironmentSpecification, Environment> 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<String, Environment>(mainModuleUri) {
+
+ UpdateListenerImpl sclListener;
+
+ @Override
+ public void register(ReadGraph graph, Listener<Environment> 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();
+ }
+
+}
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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;
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;
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;
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<ImportDeclaration> DEPENDENCIES = Arrays.asList(
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<Resource,Map<String,Resource>> childMaps = new THashMap<Resource,Map<String,Resource>>();
+ private Resource ontology;
+ private String defaultLocalName;
+ private THashMap<Resource,Map<String,Resource>> childMaps = new THashMap<Resource,Map<String,Resource>>();
+ private List<ImportDeclaration> 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<EnvironmentSpecification, Environment> pair = graph.syncRequest(new Read<Pair<EnvironmentSpecification, Environment>>() {
+ @Override
+ public Pair<EnvironmentSpecification, Environment> 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 {
@Override
public List<ImportDeclaration> getDependencies() {
- //return DEPENDENCIES;
- return Collections.emptyList();
+ return importDeclarations;
}
private static interface ResourceSearchResult {}
@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 {
private final static HashMap<String, ResourceFunctionGenerator> 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;
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;
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;
childMaps.clear();
childMaps = null;
ontology = null;
+ environment = null;
}
@Override
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;
private static final Logger LOGGER = LoggerFactory.getLogger(OntologyModuleSourceRepository.class);
- static class ModuleSourceRequest extends UnaryRead<String, ModuleSource> {
+ static class ModuleRequest extends UnaryRead<String, Module> {
- 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);
}
};
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<Module> compileModule(ModuleRepository environment, UpdateListener listener,
+ ModuleCompilationOptions options) {
+ try {
+ return new Success<Module>(Simantics.getAvailableRequestProcessor().syncRequest(new ModuleRequest(moduleName)));
+ } catch(DatabaseException e) {
+ return new Failure(e);
+ }
+ }
+ };
}
@Override
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<Resource,SCLRelationInfo> {
+public class SCLRelationInfoRequest extends BinaryRead<Resource, Environment, SCLRelationInfo> {
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
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;
}
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;