X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fscl%2Fontologymodule%2FOntologyModule.java;fp=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fscl%2FOntologyModule.java;h=ec698e670514984fa42128d3211238d503a93a35;hp=39cf2f76555387e85091512c0f4844e6cdecb38f;hb=6320ecb3f75e3a29ed620ca5425ca22ef88a5496;hpb=6d789e04560b01a1845d39f7e951230bb74d6470 diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModule.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java similarity index 58% rename from bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModule.java rename to bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java index 39cf2f765..ec698e670 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/OntologyModule.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/ontologymodule/OntologyModule.java @@ -1,8 +1,9 @@ -package org.simantics.modeling.scl; +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; import java.util.function.Consumer; @@ -16,29 +17,48 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.constants.StringConstant; +import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; +import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant; +import org.simantics.scl.compiler.elaboration.expressions.ELiteral; +import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda; +import org.simantics.scl.compiler.elaboration.expressions.EVariable; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.Variable; +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.filter.NamespaceFilter; +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.TCon; +import org.simantics.scl.compiler.types.TVar; 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.compiler.types.kinds.Kinds; import org.simantics.scl.runtime.SCLContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import gnu.trove.map.hash.THashMap; import gnu.trove.procedure.TObjectProcedure; public class OntologyModule extends LazyModule { - + private static final Logger LOGGER = LoggerFactory.getLogger(OntologyModule.class); + private static final String DB_MODULE = "Simantics/DB"; + private static final String VARIABLE_MODULE = "Simantics/Variable"; private static final Collection DEPENDENCIES = Arrays.asList( - new ImportDeclaration(DB_MODULE, null) + new ImportDeclaration(DB_MODULE, null), + new ImportDeclaration(VARIABLE_MODULE, null) ); private static final TCon RESOURCE = Types.con(DB_MODULE, "Resource"); + private static final TCon BROWSABLE = Types.con(DB_MODULE, "Browsable"); + private static final TCon VARIABLE = Types.con(VARIABLE_MODULE, "Variable"); Resource ontology; String defaultLocalName; @@ -69,26 +89,55 @@ public class OntologyModule extends LazyModule { return Collections.emptyList(); } - private Resource getResource(String name) { + private static interface ResourceSearchResult {} + private static class JustResource implements ResourceSearchResult { + public final Resource resource; + public JustResource(Resource resource) { + this.resource = resource; + } + } + private static class ResourceAndSuffix implements ResourceSearchResult { + public final Resource resource; + public final String suffix; + public ResourceAndSuffix(Resource resource, String suffix) { + this.resource = resource; + this.suffix = suffix; + } + } + + private ResourceSearchResult getResourceOrSuffixedResource(String name) { Map localMap = childMaps.get(ontology); if(localMap == null) return null; + Resource parent = ontology; while(true) { int p = name.indexOf('.'); if(p < 0) break; String localName = name.substring(0, p); - Resource newParent = localMap.get(localName); - if(newParent == null) + parent = localMap.get(localName); + if(parent == null) return null; name = name.substring(p+1); // Get new local map - localMap = getLocalMap(newParent); + localMap = getLocalMap(parent); if(localMap == null) return null; } - return localMap.get(name); + Resource child = localMap.get(name); + if(child != null) + return new JustResource(child); + else + return new ResourceAndSuffix(parent, name); + } + + private Resource getResource(String name) { + ResourceSearchResult searchResult = getResourceOrSuffixedResource(name); + if(searchResult instanceof JustResource) + return ((JustResource)searchResult).resource; + else + return null; } private Map getLocalMap(Resource parent) { @@ -129,16 +178,116 @@ public class OntologyModule extends LazyModule { } } + @FunctionalInterface + private static interface ResourceFunctionGenerator { + SCLValue createValue(Name name, Resource resource); + } + + private static class RelatedValueMacroRule implements MacroRule { + private final Resource relation; + private final SCLRelationInfo relationInfo; + private final boolean optionalValue; + + public RelatedValueMacroRule(Resource relation, SCLRelationInfo relationInfo, boolean optionalValue) { + this.relation = relation; + this.relationInfo = relationInfo; + this.optionalValue = optionalValue; + } + + private Expression applyWithSubject(SimplificationContext context, Type subjectType, Expression evidence, Expression subject) { + if(Types.equals(subjectType, RESOURCE)) + return new EApply( + Locations.NO_LOCATION, + Types.READ_GRAPH, + context.getConstant(Name.create(DB_MODULE, optionalValue ? "possibleRelatedValue2" : "relatedValue2"), relationInfo.rangeType), + subject, + new EExternalConstant(relation, RESOURCE)); + else if(Types.equals(subjectType, VARIABLE)) + return new EApply( + Locations.NO_LOCATION, + Types.READ_GRAPH, + context.getConstant(Name.create(DB_MODULE, optionalValue ? "untypedPossiblePropertyValue" : "untypedPropertyValue"), relationInfo.rangeType), + subject, + new ELiteral(new StringConstant(relationInfo.name))); + else + return new EApply( + Locations.NO_LOCATION, + Types.READ_GRAPH, + context.getConstant(Name.create(DB_MODULE, optionalValue ? "genericPossibleRelatedValue" : "genericRelatedValue"), subjectType, relationInfo.rangeType), + evidence, + subject, + new EExternalConstant(relation, RESOURCE)); + } + + @Override + public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) { + Type subjectType = typeParameters[0]; + if(apply.parameters.length == 1) { + Variable subject = new Variable("subject", subjectType); + return new ESimpleLambda(subject, applyWithSubject(context, subjectType, apply.parameters[0], new EVariable(subject))); + } + else if(apply.parameters.length >= 2) { + Expression valueReplacement = applyWithSubject(context, subjectType, apply.parameters[0], apply.parameters[1]); + if(apply.parameters.length == 2) + return valueReplacement; + else { + apply.set(valueReplacement, Arrays.copyOfRange(apply.parameters, 2, apply.parameters.length)); + return apply; + } + } + else { + LOGGER.error("Application of relation following functions should have at least one parameter (the evidence of Browsable)."); + return null; + } + } + } + + 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); + if(relationInfo == null) + return null; + + SCLValue value = new SCLValue(name); + value.setType(Types.forAll(A, Types.function(Types.pred(BROWSABLE, A), Types.functionE(A, Types.READ_GRAPH, relationInfo.rangeType)))); + value.setMacroRule(new RelatedValueMacroRule(resource, relationInfo, false)); + return value; + }); + VALUE_GENERATOR_MAP.put("possibleValue", (name, resource) -> { + SCLRelationInfo relationInfo = SCLRelationInfoRequest.getRelationInfo(resource); + if(relationInfo == null) + return null; + + SCLValue value = new SCLValue(name); + value.setType(Types.forAll(A, Types.function(Types.pred(BROWSABLE, A), Types.functionE(A, Types.READ_GRAPH, Types.apply(Types.MAYBE, relationInfo.rangeType))))); + value.setMacroRule(new RelatedValueMacroRule(resource, relationInfo, true)); + return value; + }); + } + @Override protected SCLValue createValue(String name) { - Resource resource = getResource(name); - if(resource == null) - return null; - SCLValue value = new SCLValue(Name.create(getName(), name)); - value.setType(RESOURCE); - value.setExpression(new EExternalConstant(resource, RESOURCE)); - value.setInlineInSimplification(true); - return value; + ResourceSearchResult searchResult = getResourceOrSuffixedResource(name); + if(searchResult instanceof JustResource) { + Resource resource = ((JustResource)searchResult).resource; + SCLValue value = new SCLValue(Name.create(getName(), name)); + value.setType(RESOURCE); + value.setExpression(new EExternalConstant(resource, RESOURCE)); + value.setInlineInSimplification(true); + return value; + } + else if(searchResult instanceof ResourceAndSuffix){ + ResourceAndSuffix resourceAndSuffix = (ResourceAndSuffix)searchResult; + ResourceFunctionGenerator generator = VALUE_GENERATOR_MAP.get(resourceAndSuffix.suffix); + if(generator == null) + return null; + else + return generator.createValue(Name.create(getName(), name), resourceAndSuffix.resource); + } + else + return null; } @Override