package org.aksw.sparqlify.core.algorithms; import java.util.Collection; import java.util.Map.Entry; import org.aksw.jena_sparql_api.exprs_ext.E_StrConcatPermissive; import org.aksw.jena_sparql_api.restriction.RestrictionImpl; import org.aksw.jena_sparql_api.restriction.RestrictionManagerImpl; import org.aksw.jena_sparql_api.restriction.RestrictionSetImpl; import org.aksw.jena_sparql_api.views.E_RdfTerm; import org.aksw.jena_sparql_api.views.PrefixSet; import org.aksw.jena_sparql_api.views.RdfTermType; import org.aksw.jena_sparql_api.views.RestrictedExpr; import org.aksw.jena_sparql_api.views.SqlTranslationUtils; import org.aksw.jena_sparql_api.views.VarDefinition; import org.aksw.sparqlify.core.domain.input.Mapping; import org.aksw.sparqlify.core.domain.input.ViewDefinition; import org.aksw.sparqlify.expr.util.NodeValueUtilsSparqlify; import org.apache.jena.graph.Node; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.expr.E_StrConcat; import org.apache.jena.sparql.expr.Expr; import org.apache.jena.sparql.expr.ExprFunction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; public class ViewDefinitionNormalizerImpl implements ViewDefinitionNormalizer<ViewDefinition> { private static final Logger logger = LoggerFactory.getLogger(ViewDefinitionNormalizer.class); public RestrictedExpr normalize(RestrictedExpr restExpr) { RestrictionSetImpl rs = restExpr.getRestrictions(); if(rs == null) { rs = new RestrictionSetImpl(); } else { rs = restExpr.getRestrictions().clone(); } Expr expr = restExpr.getExpr(); RdfTermType type = deriveType(expr); if(type != null) { rs.stateType(type); } String prefix = derivePrefix(expr); if(RdfTermType.URI.equals(type) && prefix != null) { PrefixSet ps = new PrefixSet(prefix); rs.stateUriPrefixes(ps); } if(rs.isUnsatisfiable()) { System.err.println("Unsatisfiable restriction detected: " + restExpr); throw new RuntimeException("Unsatisfiable restriction detected: " + restExpr); } RestrictedExpr result = new RestrictedExpr(expr, rs); return result; } public VarDefinition normalize(VarDefinition varDef) { Multimap<Var, RestrictedExpr> resultMap = HashMultimap.create(); for(Entry<Var, RestrictedExpr> entry : varDef.getMap().entries()) { Var var = entry.getKey(); RestrictedExpr old = entry.getValue(); RestrictedExpr newRestExpr = normalize(old); resultMap.put(var, newRestExpr); } VarDefinition result = new VarDefinition(resultMap); return result; } /** * Combines all of a variables restrictions. * * @param varDef * @return */ public RestrictionManagerImpl createVarRestrictions(VarDefinition varDef) { RestrictionManagerImpl result = new RestrictionManagerImpl(); for(Entry<Var, Collection<RestrictedExpr>> entry : varDef.getMap().asMap().entrySet()) { Var var = entry.getKey(); Collection<RestrictedExpr> restExprs = entry.getValue(); int m = restExprs.size(); if(m == 1) { RestrictedExpr restExpr = restExprs.iterator().next(); RestrictionSetImpl rs = restExpr.getRestrictions(); int n = rs.getRestrictions().size(); if(n == 1) { RestrictionImpl r = rs.getRestrictions().iterator().next(); result.stateRestriction(var, r); } else if(n > 1) { logger.warn("More than 1 restriction found; having to ignore all for now: " + rs); } } else if(m > 1) { logger.warn("More than 1 definition found; can't derive restrictions because of that: " + restExprs); } } return result; } public ViewDefinition normalize(ViewDefinition viewDefinition) { VarDefinition normVarDef = normalize(viewDefinition.getMapping().getVarDefinition()); RestrictionManagerImpl restrictionManager = createVarRestrictions(normVarDef); Mapping newMapping = new Mapping(normVarDef, viewDefinition.getMapping().getSqlOp()); ViewDefinition result = new ViewDefinition(viewDefinition.getName(), viewDefinition.getTemplate(), viewDefinition.getViewReferences(), newMapping, restrictionManager, viewDefinition); return result; } public static String derivePrefixConcat(ExprFunction concat) { // TODO If all arguments are constant, we could infer a constant constraint String prefix = ""; for(Expr arg : concat.getArgs()) { if(arg.isConstant()) { prefix += arg.getConstant().asUnquotedString(); } else { break; } } return prefix; } public static String derivePrefix(E_RdfTerm termCtor) { String result; Expr expr = termCtor.getArgs().get(1); if(expr instanceof E_StrConcat || expr instanceof E_StrConcatPermissive) { result = derivePrefixConcat(expr.getFunction()); } else { result = null; } return result; } public static String derivePrefix(ExprFunction fn) { E_RdfTerm termCtor = SqlTranslationUtils.expandRdfTerm(fn); String result; if(termCtor != null) { result = derivePrefix(termCtor); } else { result = null; } return result; } public static String derivePrefix(Node node) { String result; if(node.isURI()) { result = node.getURI(); } else { result = null; } return result; } public static String derivePrefix(Expr expr) { String result; if(expr.isFunction()) { result = derivePrefix(expr.getFunction()); } else if(expr.isConstant()) { result = derivePrefix(expr.getConstant().getNode()); } else { result = null; } return result; } public static RdfTermType deriveType(Node node) { if(node.isURI()) { return RdfTermType.URI; } else if(node.isLiteral()) { return RdfTermType.LITERAL; } else if(node.isBlank()) { throw new RuntimeException("Decide on what to return here."); //return Type.URI; } else { return RdfTermType.UNKNOWN; } } public static RdfTermType deriveType(E_RdfTerm termCtor) { Expr arg = termCtor.getArg(1); if(arg.isConstant()) { Object o = NodeValueUtilsSparqlify.getValue(arg.getConstant()); Number number = (Number)o; switch(number.intValue()) { case 1: return RdfTermType.URI; case 2: case 3: return RdfTermType.LITERAL; } } return RdfTermType.UNKNOWN; } public static RdfTermType deriveType(ExprFunction fn) { E_RdfTerm termCtor = SqlTranslationUtils.expandRdfTerm(fn); RdfTermType result; if(termCtor != null) { result = deriveType(termCtor); } else { result = RdfTermType.UNKNOWN; } return result; } public static RdfTermType deriveType(Expr expr) { RdfTermType result = null; if(expr.isConstant()) { result = deriveType(expr.getConstant().asNode()); } else if(expr.isFunction()) { result = deriveType(expr.getFunction()); } return result; } }