Package lupos.engine.operators.multiinput.join

Source Code of lupos.engine.operators.multiinput.join.IndexOnLeftOperandJoin$JoinIterator

/**
* Copyright (c) 2013, Institute of Information Systems (Sven Groppe and contributors of LUPOSDATE), University of Luebeck
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*     disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*     following disclaimer in the documentation and/or other materials provided with the distribution.
*   - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*     products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lupos.engine.operators.multiinput.join;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import lupos.datastructures.bindings.Bindings;
import lupos.datastructures.items.Variable;
import lupos.datastructures.items.literal.Literal;
import lupos.datastructures.queryresult.ParallelIterator;
import lupos.datastructures.queryresult.ParallelIteratorMultipleQueryResults;
import lupos.datastructures.queryresult.QueryResult;
import lupos.datastructures.queryresult.QueryResultDebug;
import lupos.engine.operators.BasicOperator;
import lupos.engine.operators.OperatorIDTuple;
import lupos.engine.operators.messages.EndOfEvaluationMessage;
import lupos.engine.operators.messages.Message;
import lupos.misc.debug.DebugStep;
import lupos.misc.util.ImmutableIterator;

/**
* This join operator creates an index on the left operand and
* iterates one time through the results of the right operand
* using the previously created index to find join partners.
*
* Thus, the operand with less intermediate results should be the left operand.
*
* This operator is not suitable for recursive queries and rule processing, where cycles in the operatorgraph can occur.
*/
public abstract class IndexOnLeftOperandJoin extends Join {
  protected ParallelIteratorMultipleQueryResults[] operands = new ParallelIteratorMultipleQueryResults(),
                                  new ParallelIteratorMultipleQueryResults()};

  public IndexOnLeftOperandJoin() {
    super();
  }

  @Override
  public void cloneFrom(final BasicOperator op) {
    super.cloneFrom(op);
  }

  public abstract Map<String, QueryResult> createDatastructure();

  @Override
  public synchronized QueryResult process(final QueryResult bindings, final int operandID) {
    //bindings.materialize(); // I do not know why this is necessary, but if there are several IndexOnLeftOperandJoin operators after each other this seems to be necessary...
    this.operands[operandID].addQueryResult(bindings); // just store the queryresult!
    return null; // wait for EndOfStreamMessage...
  }

  @Override
  public Message preProcessMessage(final EndOfEvaluationMessage msg) {
    if(!this.operands[0].isEmpty() && ! this.operands[1].isEmpty()){
      final Map<String, QueryResult> leftOperandsData = this.createDatastructure();
      final QueryResult cartesianProduct = QueryResult.createInstance();

      IndexOnLeftOperandJoin.indexQueryResult(this.operands[0].getQueryResult(), this.intersectionVariables, leftOperandsData, cartesianProduct);

      final QueryResult result = QueryResult.createInstance(new JoinIterator(this.intersectionVariables, this.operands[1].getQueryResult(), leftOperandsData, cartesianProduct));

      if(this.succeedingOperators.size()>1){
        result.materialize();
      }

      for (final OperatorIDTuple opId : this.succeedingOperators) {
        opId.processAll(result);
      }
    }
    return msg;
  }

  @Override
  public Message preProcessMessageDebug(final EndOfEvaluationMessage msg, final DebugStep debugstep) {
    if(!this.operands[0].isEmpty() && ! this.operands[1].isEmpty()){
      final Map<String, QueryResult> leftOperandsData = this.createDatastructure();
      final QueryResult cartesianProduct = QueryResult.createInstance();

      IndexOnLeftOperandJoin.indexQueryResult(this.operands[0].getQueryResult(), this.intersectionVariables, leftOperandsData, cartesianProduct);

      final QueryResult result = QueryResult.createInstance(new JoinIterator(this.intersectionVariables, this.operands[1].getQueryResult(), leftOperandsData, cartesianProduct));

      if(this.succeedingOperators.size()>1){
        result.materialize();
      }

      for (final OperatorIDTuple opId : this.succeedingOperators) {
        opId.processAllDebug(new QueryResultDebug(result, debugstep, this, opId.getOperator(), true), debugstep);
      }
    }
    return msg;
  }


  public static void indexQueryResult(final QueryResult toIndex, final Collection<Variable> joinVariables, final Map<String, QueryResult> index, final QueryResult cartesianProduct){
    final Iterator<Bindings> itbindings = toIndex.oneTimeIterator();
    while (itbindings.hasNext()) {

      final Bindings bindings = itbindings.next();

      final String keyJoin = IndexOnLeftOperandJoin.getKey(bindings, joinVariables);

      if (keyJoin == null){
        cartesianProduct.add(bindings);
        continue;
      }

      QueryResult lb = index.get(keyJoin);
      if (lb == null){
        lb = QueryResult.createInstance();
      }
      lb.add(bindings);
      index.put(keyJoin, lb);
    }
    if(itbindings instanceof ParallelIterator){
      ((ParallelIterator<Bindings>)itbindings).close();
    }
  }

  public static String getKey(final Bindings bindings, final Collection<Variable> joinVariables){
    String keyJoin = "";
    final Iterator<Variable> it = joinVariables.iterator();
    while (it.hasNext()) {
      final Literal literal = bindings.get(it.next());
      if (literal == null) {
        keyJoin = null;
        break;
      }
      keyJoin += "|" + literal.getKey();
    }
    return keyJoin;
  }

  public static class DebugIterator implements Iterator<Bindings>{

    private final Iterator<Bindings> innerIterator;
    private final String id;

    public DebugIterator(final String id, final Iterator<Bindings> innerIterator){
      this.innerIterator = innerIterator;
      this.id = id;
    }

    @Override
    public boolean hasNext() {
      final boolean result = this.innerIterator.hasNext();
      System.out.println(this.id+".hasNext():"+result);
      return result;
    }

    @Override
    public Bindings next() {
      final Bindings result = this.innerIterator.next();
      System.out.println(this.id+".next():"+result);
      return result;
    }

    @Override
    public void remove() {
      this.innerIterator.remove();
    }
  }

  public static class JoinIterator implements ParallelIterator<Bindings>{

    protected final Map<String, QueryResult> leftOperandsData;
    protected final QueryResult cartesianProduct;
    protected final Iterator<Bindings> rightOperandIt;
    protected Iterator<Bindings> currentBindingsOfRightOperandIt;
    protected final Collection<Variable> joinVariables;

    public JoinIterator(final Collection<Variable> joinVariables, final QueryResult rightOperand, final Map<String, QueryResult> leftOperandsData, final QueryResult cartesianProduct){
      this(joinVariables, rightOperand.oneTimeIterator(), leftOperandsData, cartesianProduct);
    }

    public JoinIterator(final Collection<Variable> joinVariables, final Iterator<Bindings> rightOperandIt, final Map<String, QueryResult> leftOperandsData, final QueryResult cartesianProduct){
      this.joinVariables = joinVariables;
      this.rightOperandIt = rightOperandIt;
      this.leftOperandsData = leftOperandsData;
      this.cartesianProduct = cartesianProduct;
    }

    @Override
    public boolean hasNext() {
      if(this.currentBindingsOfRightOperandIt!=null && this.currentBindingsOfRightOperandIt.hasNext()){
        return true;
      } else {
        this.currentBindingsOfRightOperandIt = this.nextIterator();
        if(this.currentBindingsOfRightOperandIt!=null){
          return true;
        }
      }
      return false;
    }

    private Iterator<Bindings> nextIterator() {
      while(this.rightOperandIt.hasNext()){
        Iterator<Bindings> result = null;
        final Bindings bindings = this.rightOperandIt.next();
        final String keyJoin = IndexOnLeftOperandJoin.getKey(bindings, this.joinVariables);
        final QueryResult fromLeft;
        if(keyJoin != null){
          fromLeft = this.leftOperandsData.get(keyJoin);
        } else {
          if(this.cartesianProduct!=null && this.cartesianProduct.size()>0){
            fromLeft = this.cartesianProduct;
          } else {
            fromLeft = null;
          }
        }
        if(fromLeft!=null){
          result = new ImmutableIterator<Bindings>(){
            final Iterator<Bindings> it = fromLeft.oneTimeIterator();
            Bindings next = null;
            @Override
            public boolean hasNext() {
              if(this.next!=null){
                return true;
              }
              this.next = this.next();
              return (this.next!=null);
            }

            @Override
            public Bindings next() {
              if(this.next!=null){
                final Bindings zBindings = this.next;
                this.next = null;
                return zBindings;
              }
              if(!this.it.hasNext()){
                return null;
              }
              Bindings bnew;
              do {
                bnew = bindings.clone();
                final Bindings bindings2 = this.it.next();
                bnew = Join.joinBindingsAndReturnBindings(bnew, bindings2);
              } while(bnew==null && this.it.hasNext());
              return bnew;
            }
          };
        }
        if(result!=null && result.hasNext()){
          return result;
        }
      }
      return null;
    }

    @Override
    public Bindings next() {
      if(this.hasNext()){
        return this.currentBindingsOfRightOperandIt.next();
      } else {
        return null;
      }
    }

    @Override
    public void remove() {
      throw new UnsupportedOperationException();
    }

    @Override
    public void close() {
      if(this.rightOperandIt instanceof ParallelIterator){
        ((ParallelIterator<Bindings>)this.rightOperandIt).close();
      }
    }
  }
}
TOP

Related Classes of lupos.engine.operators.multiinput.join.IndexOnLeftOperandJoin$JoinIterator

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.