--- /dev/null
+package org.simantics.modeling.scl;\r
+\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.function.Consumer;\r
+\r
+import org.simantics.Simantics;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.environment.filter.NamespaceFilter;\r
+import org.simantics.scl.compiler.module.ImportDeclaration;\r
+import org.simantics.scl.compiler.module.LazyModule;\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException;\r
+import org.simantics.scl.runtime.SCLContext;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectProcedure;\r
+\r
+public class OntologyModule extends LazyModule {\r
+\r
+ private static final String DB_MODULE = "Simantics/DB";\r
+ private static final Collection<ImportDeclaration> DEPENDENCIES = Arrays.asList(\r
+ new ImportDeclaration(DB_MODULE, null)\r
+ );\r
+ private static final TCon RESOURCE = Types.con(DB_MODULE, "Resource");\r
+ \r
+ Resource ontology;\r
+ THashMap<Resource,Map<String,Resource>> childMaps = new THashMap<Resource,Map<String,Resource>>();\r
+ \r
+ public OntologyModule(ReadGraph graph, String moduleName) throws DatabaseException {\r
+ super(moduleName);\r
+ ontology = graph.getResource(moduleName);\r
+ childMaps.put(ontology, createLocalMap(graph, ontology));\r
+ }\r
+\r
+ @Override\r
+ public List<ImportDeclaration> getDependencies() {\r
+ //return DEPENDENCIES;\r
+ return Collections.emptyList();\r
+ }\r
+ \r
+ private Resource getResource(String name) {\r
+ Map<String,Resource> localMap = childMaps.get(ontology); \r
+ if(localMap == null)\r
+ return null;\r
+ while(true) {\r
+ int p = name.indexOf('.');\r
+ if(p < 0)\r
+ break;\r
+ String localName = name.substring(0, p);\r
+ Resource newParent = localMap.get(localName);\r
+ if(newParent == null)\r
+ return null;\r
+ name = name.substring(p+1);\r
+ \r
+ // Get new local map\r
+ localMap = getLocalMap(newParent);\r
+ if(localMap == null)\r
+ return null;\r
+ }\r
+ return localMap.get(name);\r
+ }\r
+ \r
+ private Map<String, Resource> getLocalMap(Resource parent) {\r
+ Map<String, Resource> localMap = childMaps.get(parent);\r
+ if(localMap == null) {\r
+ if(childMaps.contains(parent))\r
+ return null;\r
+ localMap = createLocalMap(parent);\r
+ childMaps.put(parent, localMap);\r
+ }\r
+ return localMap;\r
+ }\r
+\r
+ private static Map<String, Resource> createLocalMap(final Resource parent) {\r
+ ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph");\r
+ if(graph != null)\r
+ return createLocalMap(graph, parent);\r
+ else\r
+ try {\r
+ return Simantics.getSession().syncRequest(new Read<Map<String, Resource>>() {\r
+ @Override\r
+ public Map<String, Resource> perform(ReadGraph graph) throws DatabaseException {\r
+ return createLocalMap(graph, parent);\r
+ }\r
+ });\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ } \r
+ }\r
+\r
+ private static Map<String, Resource> createLocalMap(ReadGraph graph, Resource parent) {\r
+ try {\r
+ return graph.syncRequest(new UnescapedChildMapOfResource(parent));\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ protected SCLValue createValue(String name) {\r
+ Resource resource = getResource(name);\r
+ if(resource == null)\r
+ return null; \r
+ SCLValue value = new SCLValue(Name.create(getName(), name));\r
+ value.setType(RESOURCE);\r
+ value.setExpression(new EExternalConstant(resource, RESOURCE));\r
+ value.setInlineInSimplification(true);\r
+ return value;\r
+ }\r
+ \r
+ @Override\r
+ protected SCLRelation createRelation(String name) {\r
+ final Resource resource = getResource(name);\r
+ if(resource == null)\r
+ return null;\r
+ ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph");\r
+ if(graph != null)\r
+ return createRelation(graph, resource);\r
+ else\r
+ try {\r
+ return Simantics.getSession().syncRequest(new Read<SCLRelation>() {\r
+ @Override\r
+ public SCLRelation perform(ReadGraph graph) throws DatabaseException {\r
+ return createRelation(graph, resource);\r
+ }\r
+ });\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ } \r
+ }\r
+ \r
+ public static SCLRelation createRelation(ReadGraph graph, Resource relation) {\r
+ try {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ if(!graph.isInstanceOf(relation, L0.Relation))\r
+ return null;\r
+ if(graph.isInstanceOf(relation, L0.PropertyRelation) && graph.isInstanceOf(relation, L0.FunctionalRelation)) {\r
+ Type valueType = getValueType(graph, relation);\r
+ if(valueType != null)\r
+ return new GraphPropertyRelation(relation, valueType);\r
+ }\r
+ \r
+ Resource inverseRelation = graph.getPossibleInverse(relation);\r
+ return new GraphRelation(relation, getSelectivity(graph, relation),\r
+ inverseRelation, getSelectivity(graph, inverseRelation));\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ protected SCLEntityType createEntityType(String name) {\r
+ final Resource resource = getResource(name);\r
+ if(resource == null)\r
+ return null;\r
+ ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph");\r
+ if(graph != null)\r
+ return createEntityType(graph, resource);\r
+ else\r
+ try {\r
+ return Simantics.getSession().syncRequest(new Read<SCLEntityType>() {\r
+ @Override\r
+ public SCLEntityType perform(ReadGraph graph) throws DatabaseException {\r
+ return createEntityType(graph, resource);\r
+ }\r
+ });\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ } \r
+ }\r
+ \r
+ private SCLEntityType createEntityType(ReadGraph graph, Resource type) {\r
+ try {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ if(!graph.isInstanceOf(type, L0.Type))\r
+ return null;\r
+ return new GraphEntityType(graph, type);\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private static double getSelectivity(ReadGraph graph, Resource relation) throws DatabaseException {\r
+ if(relation == null)\r
+ return Double.POSITIVE_INFINITY;\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ if(graph.isInstanceOf(relation, L0.FunctionalRelation))\r
+ return 1.0;\r
+ else\r
+ return 10.0;\r
+ }\r
+\r
+ private static Type getValueType(ReadGraph graph, Resource relation) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ Type valueType = parseValueType((String)graph.getPossibleRelatedValue(relation, L0.RequiresValueType, Bindings.STRING));\r
+ if(valueType != null)\r
+ return valueType;\r
+ Resource range = graph.getPossibleObject(relation, L0.HasRange);\r
+ if(range != null) {\r
+ for(Resource valueTypeLiteral : graph.getAssertedObjects(range, L0.HasValueType)) {\r
+ valueType = parseValueType((String)graph.getValue(valueTypeLiteral, Bindings.STRING));\r
+ if(valueType != null)\r
+ return valueType;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private static Type parseValueType(String valueTypeString) {\r
+ if(valueTypeString == null)\r
+ return null;\r
+ try {\r
+ return Types.parseType(valueTypeString);\r
+ } catch (SCLTypeParseException e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void findValuesForPrefix(String prefix,\r
+ NamespaceFilter filter,\r
+ TObjectProcedure<SCLValue> proc) {\r
+ Map<String,Resource> localMap = childMaps.get(ontology); \r
+ if(localMap == null)\r
+ return;\r
+ String namePrefix = "";\r
+ while(true) {\r
+ int p = prefix.indexOf('.');\r
+ if(p < 0)\r
+ break;\r
+ String localName = prefix.substring(0, p);\r
+ Resource newParent = localMap.get(localName);\r
+ if(newParent == null)\r
+ return;\r
+ prefix = prefix.substring(p+1);\r
+ namePrefix = namePrefix + localName + ".";\r
+ \r
+ // Get new local map\r
+ localMap = getLocalMap(newParent);\r
+ if(localMap == null)\r
+ return;\r
+ }\r
+ for(String name : localMap.keySet())\r
+ if(name.startsWith(prefix) && filter.isValueIncluded(name))\r
+ proc.execute(getValue(namePrefix+name));\r
+ }\r
+ \r
+ @Override\r
+ public void findValuesForPrefix(String prefix, NamespaceFilter filter, Consumer<SCLValue> consumer) {\r
+ Map<String,Resource> localMap = childMaps.get(ontology); \r
+ if(localMap == null)\r
+ return;\r
+ String namePrefix = "";\r
+ while(true) {\r
+ int p = prefix.indexOf('.');\r
+ if(p < 0)\r
+ break;\r
+ String localName = prefix.substring(0, p);\r
+ Resource newParent = localMap.get(localName);\r
+ if(newParent == null)\r
+ return;\r
+ prefix = prefix.substring(p+1);\r
+ namePrefix = namePrefix + localName + ".";\r
+ \r
+ // Get new local map\r
+ localMap = getLocalMap(newParent);\r
+ if(localMap == null)\r
+ return;\r
+ }\r
+ for(String name : localMap.keySet())\r
+ if(name.startsWith(prefix) && filter.isValueIncluded(name))\r
+ consumer.accept(getValue(namePrefix+name));\r
+ }\r
+\r
+ @Override\r
+ public void findTypesForPrefix(String prefix, NamespaceFilter instance, Consumer<TCon> consumer) {\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ childMaps.clear();\r
+ childMaps = null;\r
+ ontology = null;\r
+ }\r
+}\r