Package org.openrdf.query.parser.serql

Source Code of org.openrdf.query.parser.serql.ProjectionProcessor$VariableCollector

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2008.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.query.parser.serql;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.parser.serql.ast.ASTProjectionElem;
import org.openrdf.query.parser.serql.ast.ASTQueryContainer;
import org.openrdf.query.parser.serql.ast.ASTSelect;
import org.openrdf.query.parser.serql.ast.ASTSelectQuery;
import org.openrdf.query.parser.serql.ast.ASTVar;
import org.openrdf.query.parser.serql.ast.ASTWhere;
import org.openrdf.query.parser.serql.ast.Node;
import org.openrdf.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants;
import org.openrdf.query.parser.serql.ast.VisitorException;

/**
* Processes projections. 'Wildcard' projections are made explicit by adding
* projection elements with the appropriate variable nodes to them. Explicit
* projections are checked to see if they don't contain any unbound variables.
*
* @author Arjohn Kampman
*/
class ProjectionProcessor extends ASTVisitorBase {

  public static void process(ASTQueryContainer qc)
    throws MalformedQueryException
  {
    try {
      qc.jjtAccept(new ProjectionProcessor(), null);
    }
    catch (VisitorException e) {
      throw new MalformedQueryException(e.getMessage(), e);
    }
  }

  @Override
  public Object visit(ASTSelect selectNode, Object data)
    throws VisitorException
  {
    // Collect all variables used in the body of the select query
    Set<String> bodyVars = VariableCollector.process(selectNode.jjtGetParent());

    if (selectNode.isWildcard()) {
      // Make wildcard projection explicit
      for (String varName : bodyVars) {
        ASTProjectionElem projElemNode = new ASTProjectionElem(
            SyntaxTreeBuilderTreeConstants.JJTPROJECTIONELEM);
        selectNode.jjtAppendChild(projElemNode);
        projElemNode.jjtSetParent(selectNode);

        ASTVar varNode = new ASTVar(SyntaxTreeBuilderTreeConstants.JJTVAR);
        varNode.setName(varName);
        projElemNode.jjtAppendChild(varNode);
        varNode.jjtSetParent(projElemNode);
      }

      selectNode.setWildcard(false);
    }
    else {
      // Verify that all projection vars are bound
      Set<String> projVars = new LinkedHashSet<String>();

      for (ASTProjectionElem projElem : selectNode.getProjectionElemList()) {
        projVars.addAll(VariableCollector.process(projElem.getValueExpr()));
      }

      projVars.removeAll(bodyVars);

      if (!projVars.isEmpty()) {
        StringBuilder errMsg = new StringBuilder(64);
        errMsg.append("Unbound variable(s) in projection: ");

        Iterator<String> iter = projVars.iterator();
        while (iter.hasNext()) {
          errMsg.append(iter.next());
          if (iter.hasNext()) {
            errMsg.append(", ");
          }
        }

        throw new VisitorException(errMsg.toString());
      }
    }

    return data;
  }

  /*-------------------------------*
   * Inner class VariableCollector *
   *-------------------------------*/

  /**
   * Collects variable names for 'wildcard' projections. An instance of this
   * class should be supplied to a {@link ASTSelectQuery} node. When done, the
   * collected variable names can be acquired by calling
   * {@link #getVariableNames}.
   */
  private static class VariableCollector extends ASTVisitorBase {

    public static Set<String> process(Node node)
      throws VisitorException
    {
      VariableCollector visitor = new VariableCollector();
      node.jjtAccept(visitor, null);
      return visitor.getVariableNames();
    }

    private Set<String> variableNames = new LinkedHashSet<String>();

    public Set<String> getVariableNames() {
      return variableNames;
    }

    @Override
    public Object visit(ASTSelect node, Object data)
      throws VisitorException
    {
      // Do not visit select clauses
      return data;
    }

    @Override
    public Object visit(ASTWhere node, Object data)
      throws VisitorException
    {
      // Do not visit where clauses
      return data;
    }

    @Override
    public Object visit(ASTVar node, Object data)
      throws VisitorException
    {
      variableNames.add(node.getName());
      return super.visit(node, data);
    }
  }
}
TOP

Related Classes of org.openrdf.query.parser.serql.ProjectionProcessor$VariableCollector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.