Package org.openrdf.result.util

Source Code of org.openrdf.result.util.QueryResultUtil

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.result.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openrdf.model.BNode;
import org.openrdf.model.Statement;
import org.openrdf.model.Value;
import org.openrdf.model.util.ModelUtil;
import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.TupleQueryResultHandler;
import org.openrdf.query.TupleQueryResultHandlerException;
import org.openrdf.result.GraphResult;
import org.openrdf.result.TupleResult;
import org.openrdf.rio.RDFHandler;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.store.StoreException;

/**
* Class offering utility methods related to query results.
*
* @author Arjohn Kampman
*/
public class QueryResultUtil {

  /**
   * Reports a tuple query result to a {@link TupleQueryResultHandler}.
   *
   * @param tqr
   *        The query result to report.
   * @param handler
   *        The handler to report the query result to.
   * @throws TupleQueryResultHandlerException
   *         If such an exception is thrown by the used query result writer.
   */
  public static void report(TupleResult tqr, TupleQueryResultHandler handler)
    throws TupleQueryResultHandlerException, StoreException
  {
    handler.startQueryResult(tqr.getBindingNames());
    try {
      while (tqr.hasNext()) {
        BindingSet bindingSet = tqr.next();
        handler.handleSolution(bindingSet);
      }
    }
    finally {
      tqr.close();
    }
    handler.endQueryResult();
  }

  /**
   * Reports a graph query result to an {@link RDFHandler}.
   *
   * @param gqr
   *        The query result to report.
   * @param rdfHandler
   *        The handler to report the query result to.
   * @throws RDFHandlerException
   *         If such an exception is thrown by the used RDF writer.
   * @throws StoreException
   */
  public static void report(GraphResult gqr, RDFHandler rdfHandler)
    throws RDFHandlerException, StoreException
  {
    try {
      rdfHandler.startRDF();

      for (Map.Entry<String, String> entry : gqr.getNamespaces().entrySet()) {
        String prefix = entry.getKey();
        String namespace = entry.getValue();
        rdfHandler.handleNamespace(prefix, namespace);
      }

      while (gqr.hasNext()) {
        Statement st = gqr.next();
        rdfHandler.handleStatement(st);
      }

      rdfHandler.endRDF();
    }
    finally {
      gqr.close();
    }
  }

  /**
   * Compares the two query results by converting them to graphs and returns
   * true if they are equal. QueryResults are equal if they contain the same
   * set of BindingSet and have the headers. Blank nodes identifiers are not
   * relevant for equality, they are mapped from one model to the other by
   * using the attached properties. Note that the method consumes both query
   * results fully.
   *
   * @throws StoreException
   */
  public static boolean equals(TupleResult tqr1, TupleResult tqr2)
    throws StoreException
  {
    List<BindingSet> list1 = tqr1.asList();
    List<BindingSet> list2 = tqr2.asList();

    // Compare the number of statements in both sets
    if (list1.size() != list2.size()) {
      return false;
    }

    return matchBindingSets(list1, list2);
  }

  public static boolean isSubset(TupleResult tqr1, TupleResult tqr2)
    throws StoreException
  {
    List<BindingSet> list1 = tqr1.asList();
    List<BindingSet> list2 = tqr2.asList();

    // Compare the number of statements in both sets
    if (list1.size() > list2.size()) {
      return false;
    }

    return matchBindingSets(list1, list2);
  }

  public static boolean equals(GraphResult result1, GraphResult result2)
    throws StoreException
  {
    Set<? extends Statement> graph1 = result1.asSet();
    Set<? extends Statement> graph2 = result1.asSet();

    return ModelUtil.equals(graph1, graph2);
  }

  private static boolean matchBindingSets(List<? extends BindingSet> queryResult1,
      Iterable<? extends BindingSet> queryResult2)
  {
    return matchBindingSets(queryResult1, queryResult2, new HashMap<BNode, BNode>(), 0);
  }

  /**
   * A recursive method for finding a complete mapping between blank nodes in
   * queryResult1 and blank nodes in queryResult2. The algorithm does a
   * depth-first search trying to establish a mapping for each blank node
   * occurring in queryResult1.
   *
   * @return true if a complete mapping has been found, false otherwise.
   */
  private static boolean matchBindingSets(List<? extends BindingSet> queryResult1,
      Iterable<? extends BindingSet> queryResult2, Map<BNode, BNode> bNodeMapping, int idx)
  {
    boolean result = false;

    if (idx < queryResult1.size()) {
      BindingSet bs1 = queryResult1.get(idx);

      List<BindingSet> matchingBindingSets = findMatchingBindingSets(bs1, queryResult2, bNodeMapping);

      for (BindingSet bs2 : matchingBindingSets) {
        // Map bNodes in bs1 to bNodes in bs2
        Map<BNode, BNode> newBNodeMapping = new HashMap<BNode, BNode>(bNodeMapping);

        for (Binding binding : bs1) {
          if (binding.getValue() instanceof BNode) {
            newBNodeMapping.put((BNode)binding.getValue(), (BNode)bs2.getValue(binding.getName()));
          }
        }

        // FIXME: this recursive implementation has a high risk of
        // triggering a stack overflow

        // Enter recursion
        result = matchBindingSets(queryResult1, queryResult2, newBNodeMapping, idx + 1);

        if (result == true) {
          // models match, look no further
          break;
        }
      }
    }
    else {
      // All statements have been mapped successfully
      result = true;
    }

    return result;
  }

  private static List<BindingSet> findMatchingBindingSets(BindingSet st,
      Iterable<? extends BindingSet> model, Map<BNode, BNode> bNodeMapping)
  {
    List<BindingSet> result = new ArrayList<BindingSet>();

    for (BindingSet modelSt : model) {
      if (bindingSetsMatch(st, modelSt, bNodeMapping)) {
        // All components possibly match
        result.add(modelSt);
      }
    }

    return result;
  }

  private static boolean bindingSetsMatch(BindingSet bs1, BindingSet bs2, Map<BNode, BNode> bNodeMapping) {
    for (Binding binding1 : bs1) {
      Value value1 = binding1.getValue();
      Value value2 = bs2.getValue(binding1.getName());

      if (value1 instanceof BNode && value2 instanceof BNode) {
        BNode mappedBNode = bNodeMapping.get(value1);

        if (mappedBNode != null) {
          // bNode 'value1' was already mapped to some other bNode
          if (!value2.equals(mappedBNode)) {
            // 'value1' and 'value2' do not match
            return false;
          }
        }
        else {
          // 'value1' was not yet mapped, we need to check if 'value2' is a
          // possible mapping candidate
          if (bNodeMapping.containsValue(value2)) {
            // 'value2' is already mapped to some other value.
            return false;
          }
        }
      }
      else {
        // values are not (both) bNodes
        if (!value1.equals(value2)) {
          return false;
        }
      }
    }

    return true;
  }

  /**
   * Check whether two {@link BindingSet}s are compatible. Two binding sets are
   * compatible if they have equal values for each binding name that occurs in
   * both binding sets.
   */
  public static boolean bindingSetsCompatible(BindingSet bs1, BindingSet bs2) {
    Set<String> sharedBindings = new HashSet<String>(bs1.getBindingNames());
    sharedBindings.retainAll(bs2.getBindingNames());

    for (String bindingName : sharedBindings) {
      Value value1 = bs1.getValue(bindingName);
      Value value2 = bs2.getValue(bindingName);

      if (!value1.equals(value2)) {
        return false;
      }
    }

    return true;
  }
}
TOP

Related Classes of org.openrdf.result.util.QueryResultUtil

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.