--- /dev/null
+package org.simantics.modeling;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.Collections;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ResourceRead;\r
+import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.request.PropertyInfo;\r
+import org.simantics.db.layer0.request.PropertyInfoRequest;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+/**\r
+ * Contains necessary information about a component type to represent its\r
+ * variable space.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public class ComponentTypeSubstructure {\r
+ \r
+ public final THashMap<String, Type> properties;\r
+ public final Map<String, ComponentTypeSubstructure> children;\r
+ \r
+ private ComponentTypeSubstructure(THashMap<String, Type> properties,\r
+ Map<String, ComponentTypeSubstructure> children) {\r
+ this.properties = properties;\r
+ this.children = children;\r
+ }\r
+ \r
+ public Pair<String,Type> possibleTypedRVI(String name) {\r
+ StringBuilder b = new StringBuilder();\r
+ int namePos = 0;\r
+ ComponentTypeSubstructure substructure = this;\r
+ \r
+ // Find the children\r
+ int p;\r
+ while( (p = name.indexOf('.', namePos)) >= 0 ) {\r
+ String childName = name.substring(namePos, p);\r
+ ComponentTypeSubstructure childSubstructure = substructure.children.get(childName);\r
+ if(childSubstructure == null)\r
+ return null;\r
+ b.append('/').append(childName);\r
+ namePos = p+1;\r
+ substructure = childSubstructure;\r
+ }\r
+ \r
+ // Find the property\r
+ String propertyName = name.substring(namePos);\r
+ Type type = substructure.properties.get(propertyName);\r
+ if(type == null)\r
+ return null;\r
+ b.append('#').append(propertyName);\r
+ return Pair.make(b.toString(), type);\r
+ }\r
+\r
+ public static ComponentTypeSubstructure forType(RequestProcessor processor, Resource componentType) throws DatabaseException {\r
+ return processor.syncRequest(new ResourceRead<ComponentTypeSubstructure>(componentType) {\r
+ @Override\r
+ public ComponentTypeSubstructure perform(ReadGraph graph)\r
+ throws DatabaseException {\r
+ // Properties\r
+ THashMap<String, Type> properties = new THashMap<String, Type>();\r
+ collect(graph, resource, properties);\r
+ for(Resource t : graph.getSupertypes(resource)) collect(graph, t, properties);\r
+ \r
+ // Children\r
+ Map<String, ComponentTypeSubstructure> children;\r
+ \r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+ Resource composite = graph.getPossibleObject(resource, STR.IsDefinedBy);\r
+ if(composite == null)\r
+ children = Collections.<String, ComponentTypeSubstructure>emptyMap();\r
+ else {\r
+ Map<String, Resource> childMap = graph.syncRequest(new UnescapedChildMapOfResource(composite));\r
+ children = new THashMap<String, ComponentTypeSubstructure>(childMap.size());\r
+ for(Map.Entry<String,Resource> entry : childMap.entrySet()) {\r
+ Resource component = entry.getValue();\r
+ Resource type = graph.getPossibleType(component, STR.Component);\r
+ if(type != null)\r
+ children.put(entry.getKey(), forType(graph, type));\r
+ }\r
+ }\r
+ \r
+ // Return the result\r
+ return new ComponentTypeSubstructure(properties, children);\r
+ }\r
+ });\r
+ }\r
+ \r
+ private static void collect(ReadGraph graph, Resource t, THashMap<String, Type> result) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(Resource relation : graph.getObjects(t, L0.DomainOf)) {\r
+ if(graph.isSubrelationOf(relation, L0.HasProperty)) {\r
+ PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(relation));\r
+ result.put(propertyInfo.name, SCLTypeUtils.getType(propertyInfo));\r
+ }\r
+ }\r
+ }\r
+}\r