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