LabelServicePlacementOptimizer.java

package org.wikidata.query.rdf.blazegraph.label;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.wikidata.query.rdf.blazegraph.WikidataServicePlacementOptimizer;
import org.wikidata.query.rdf.blazegraph.label.LabelService.Resolution;

import com.bigdata.bop.IVariable;
import com.bigdata.rdf.sparql.ast.StaticAnalysis;
import com.bigdata.rdf.sparql.ast.service.ServiceNode;

/**
 * Finds appropriate placement for SERVICE clause.
 * The placement depends on which variables are used and projected in the SERVICE clause.
 */
public class LabelServicePlacementOptimizer extends WikidataServicePlacementOptimizer {

    @Override
    protected void processProjection(StaticAnalysis sa, ServiceNode serviceNode) {
        if (serviceNode.getProjectedVars() == null) {
            List<Resolution> resolutions = LabelService.findResolutions(serviceNode);
            if (resolutions.size() > 0) {
                // If resolutions could be resolved, assume them as projected vars for the service node
                // this serves several purposes: we need these vars to check against variables used in
                // AssignmentNode(s) to properly place ServiceNode before these assignment nodes
                // and secondly, these projected vars become visible to subsequent optimizers so they
                // might use this information to apply further reordering properly.
                Set<IVariable<?>> inVars = new HashSet<>();
                Set<IVariable<?>> outVars = new HashSet<>();
                for (Resolution resolution: resolutions) {
                    if (resolution.subject() instanceof IVariable) {
                        inVars.add((IVariable<?>)resolution.subject());
                    }
                    outVars.add(resolution.target());
                }
                serviceNode.annotations().put(WIKIDATA_SERVICE_IN_VARS, inVars);
                serviceNode.annotations().put(WIKIDATA_SERVICE_OUT_VARS, outVars);
                HashSet<IVariable<?>> projectedVars = new HashSet<>(inVars);
                projectedVars.addAll(outVars);
                serviceNode.setProjectedVars(projectedVars);
            }
        }
    }

    @Override
    protected String getServiceKey() {
        return LabelService.SERVICE_KEY.stringValue();
    }
}