package org.aksw.jena_sparql_api.mapper.impl.engine; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.function.Function; import org.aksw.jena_sparql_api.concepts.Relation; import org.aksw.jena_sparql_api.mapper.impl.type.PathFragment; import org.aksw.jena_sparql_api.mapper.impl.type.PathResolver; import org.aksw.jena_sparql_api.mapper.model.RdfType; import org.aksw.jena_sparql_api.utils.ElementUtils; import org.aksw.jena_sparql_api.utils.Generator; import org.aksw.jena_sparql_api.utils.NodeTransformRenameMap; import org.aksw.jena_sparql_api.utils.VarGeneratorBlacklist; import org.aksw.jena_sparql_api.utils.VarUtils; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.syntax.Element; abstract class PathResolverBase implements PathResolver { protected String alias; @Override public String getAlias() { return alias; } @Override public PathResolver setAlias(String alias) { this.alias = alias; return this; } } /** * @author raven * */ public class PathResolverImpl extends PathResolverBase { protected PathResolverImpl parent; /** * The current pathFragment - null for the root path resolver */ protected PathFragment pathFragment; /** * TODO: Instead of referring to the engine, it would be more modular if * we referred to some RdfMappingMetamodel / RdfMappingModule object. * Similar to JPA's metamodel. * */ protected RdfMapperEngine mapperEngine; //protected Function<String, PathResolver> protected String reachingPropertyName; //protected RdfType current; @Override public PathResolverImpl getParent() { return parent; } //@Override public PathFragment getPathFragment() { return pathFragment; } public PathResolverImpl(PathFragment pathFragment, RdfMapperEngine mapperEngine, String reachingPropertyName, PathResolverImpl parent) { super(); this.pathFragment = pathFragment; this.mapperEngine = mapperEngine; this.reachingPropertyName = reachingPropertyName; this.parent = parent; } public PathResolver resolve(Function<Class<?>, RdfType> rdfTypeFactory, Class<?> javaClass, String propertyName) { RdfType rdfType = rdfTypeFactory.apply(javaClass);//mapperEngine.getRdfTypeFactory().forJavaType(javaClass); PathResolver result = resolve(rdfType, propertyName); return result; } public PathResolver resolve(RdfType rdfType, String propertyName) { PathFragment pathFragment = rdfType.resolve(propertyName); PathResolver result = new PathResolverImpl(pathFragment, mapperEngine, propertyName, this); return result; } public PathResolver resolve(RdfMapperEngine mapperEngine, PathFragment pathFragment, String propertyName) { PathResolver result; PathResolver tmp = pathFragment.getNextResolver(); if(tmp != null) { result = tmp.resolve(propertyName); } else { RdfType rdfType = pathFragment.getRdfType(); if(rdfType != null) { result = resolve(rdfType, propertyName); } else { Class<?> javaClass = pathFragment.getJavaClass(); if(javaClass != null) { result = resolve(mapperEngine.getRdfTypeFactory()::forJavaType, javaClass, propertyName); } else { throw new RuntimeException("Could not resolve pathFragment: " + pathFragment); } } } return result; } @Override public PathResolver resolve(String propertyName) { PathResolver result = resolve(mapperEngine, pathFragment, propertyName); return result; } // Note: the varGen is assumed to be configured to avoid yielding fixed vars public Relation getOverallRelation(Generator<Var> varGen) { //PathResolver parent = getParent(); //PathResolver grandParent = parent != null ? parent.getParent() : null; Relation result; if(pathFragment == null) { result = null; } else { Relation contribRel = getPathFragment().getRelation(); Var srcVar; Var tgtVar; Element e; String aliasName = this.getAlias(); if(aliasName != null) { tgtVar = Var.alloc(aliasName); } else { // Conservative approach: always obtain a new var from the generator tgtVar = varGen.next(); //tgtVar = fixedVars.contains(tgtVar) ? varGen.next() : tgtVar; //tgtVar = varGen.prefer(tgtVar); } if(parent != null) { Relation parentRel = parent.getOverallRelation(varGen); Collection<Var> parentVars = parentRel.getVarsMentioned(); Collection<Var> contribInnerVars = contribRel.getInnerVars(); // - Make any intermediary var of the contribRel distinct from union(fixedVars, vars(parentRel)) // - If there is an alias, map contribRel.tgtVar -> alias; otherwise allocate a fresh name Map<Var, Var> varMap = VarUtils.createDistinctVarMap(parentVars, contribInnerVars, true, varGen); varMap.put(contribRel.getSourceVar(), parentRel.getSourceVar()); varMap.put(contribRel.getTargetVar(), tgtVar); contribRel = contribRel.applyNodeTransform(new NodeTransformRenameMap(varMap)); srcVar = parentRel.getSourceVar(); e = ElementUtils.groupIfNeeded(parentRel.getElement(), contribRel.getElement()); } else { srcVar = contribRel.getSourceVar(); //varGen.next(); e = contribRel.getElement(); } result = new Relation(e, srcVar, tgtVar); // if there is an alias, replace the target with it } return result; } // @Override // public Relation getOverallRelation() { // Set<Var> fixedVars = VarUtils.toSet(getAliases()); // Generator<Var> varGen = VarGeneratorBlacklist.create(fixedVars); // // Relation result = getOverallRelation(varGen); // // return result; // } }