Package lupos.engine.operators.index.memoryindex

Source Code of lupos.engine.operators.index.memoryindex.MemoryIndexScan

/**
* 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.index.memoryindex;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import lupos.datastructures.bindings.Bindings;
import lupos.datastructures.items.Item;
import lupos.datastructures.items.Triple;
import lupos.datastructures.items.Variable;
import lupos.datastructures.items.literal.Literal;
import lupos.datastructures.queryresult.QueryResult;
import lupos.engine.operators.OperatorIDTuple;
import lupos.engine.operators.index.BasicIndexScan;
import lupos.engine.operators.index.Indices;
import lupos.engine.operators.index.Indices.MAP_PATTERN;
import lupos.engine.operators.index.Root;
import lupos.engine.operators.tripleoperator.TriplePattern;
import lupos.misc.util.ImmutableIterator;

/**
* Instances of this class are used to process queries by using a special index
* structure for enhancement.<br>
* The index structure has to be initialized previously. It is stored in a
* static way so new instantiations of this class to not yield a change in the
* original index structure.
*/
public class MemoryIndexScan extends BasicIndexScan {

  private static final long serialVersionUID = 4275399525492937163L;

  /**
   * Constructor
   */
  public MemoryIndexScan(final lupos.engine.operators.index.Root root) {
    super(root);
  }

  public MemoryIndexScan(final OperatorIDTuple succeedingOperator,
      final Collection<TriplePattern> triplePattern, final Item rdfGraph, final lupos.engine.operators.index.Root root) {
    super(succeedingOperator, triplePattern, rdfGraph, root);
  }

  public MemoryIndexScan(final List<OperatorIDTuple> succeedingOperators,
      final Collection<TriplePattern> triplePattern, final Item rdfGraph, final lupos.engine.operators.index.Root root) {
    super(succeedingOperators, triplePattern, rdfGraph, root);
  }

  public MemoryIndexScan(final Root root, final Collection<TriplePattern> triplePatterns) {
    super(root, triplePatterns);
  }

  @Override
  public MemoryIndexScan clone() {
    final MemoryIndexScan clone = new MemoryIndexScan(this.succeedingOperators, this.triplePatterns, this.rdfGraph, this.root);
    clone.bindingsFactory = this.bindingsFactory;
    return clone;
  }

  @Override
  public QueryResult join(final Collection<Indices> indicesC){
    try{
      QueryResult queryResult = QueryResult.createInstance();
      queryResult.add(this.bindingsFactory.createInstance());
      // move over the collection of the provided triple patterns
      for (final TriplePattern tp : this.triplePatterns) {

        final QueryResult zQueryResult = queryResult;

        final Iterator<Bindings> itb = new ImmutableIterator<Bindings>() {
          Iterator<Bindings> oldBindings = zQueryResult.oneTimeIterator();
          Bindings currentBindings = null;
          Iterator<Triple> newTriples = null;
          Bindings next = null;

          @Override
          public boolean hasNext() {
            if (this.next != null) {
              return true;
            }
            this.next = this.computeNext();
            return (this.next != null);
          }

          @Override
          public Bindings next() {
            if (this.next != null) {
              final Bindings znext = this.next;
              this.next = null;
              return znext;
            }
            return this.computeNext();
          }

          public Bindings computeNext() {
            while ((this.newTriples == null || !this.newTriples.hasNext()) && this.oldBindings.hasNext()) {
              this.retrieveNewTriples();
            }
            if (this.newTriples == null || !this.newTriples.hasNext()) {
              return null;
            }
            final Triple triple = this.newTriples.next();
            final Bindings cB = this.currentBindings.clone();
            for (int i = 0; i < 3; i++) {
              if (tp.getPos(i).isVariable()) {
                final Literal l = cB.get((Variable) tp.getPos(i));
                if (l != null) {
                  if (!triple.getPos(i).equals(l)) {
                    return this.computeNext();
                  }
                } else {
                  cB.add((Variable) tp.getPos(i), triple.getPos(i));
                }
              }
            }
            cB.addTriple(triple);
            return cB;
          }

          private void retrieveNewTriples() {
            this.currentBindings = this.oldBindings.next();

            final StringBuffer key = new StringBuffer();
            int mapPattern = MAP_PATTERN.NONE.ordinal();

            // compute a key which is as restrictive as possible
            // to cut down the amount of triple pattern which
            // have
            // to be processed to produce the result
            if (MemoryIndexScan.this.computeKey4Maps(this.currentBindings, key, tp.getPos(0))) {
              mapPattern += MAP_PATTERN.SMAP.ordinal();
            }
            if (MemoryIndexScan.this.computeKey4Maps(this.currentBindings, key, tp.getPos(1))) {
              mapPattern += MAP_PATTERN.PMAP.ordinal();
            }
            if (MemoryIndexScan.this.computeKey4Maps(this.currentBindings, key, tp.getPos(2))) {
              mapPattern += MAP_PATTERN.OMAP.ordinal();
            }
            this.newTriples = MemoryIndexScan.this.getFromMap(MAP_PATTERN.values()[mapPattern], key.toString(), indicesC);
          }
        };

        // use a "fresh" object to gather the result of the join
        // operation
        // when using the current triple pattern and the previous query
        // results
        final QueryResult qresult = QueryResult.createInstance(itb);

        // replace the previous query results with the new ones
        queryResult.release();
        queryResult = qresult;
      }
      return queryResult;
    } catch (final Exception e) {
      System.err.println("Error while joining triple patterns"+e);
      return null;
    }
  }

  private Iterator<Triple> getFromMap(final MAP_PATTERN mapPattern, final String keyString, final Collection<Indices> indicesG) {
    if(indicesG.size()==1){
      return this.getFromMap(mapPattern, keyString, indicesG.iterator().next());
    }
    final Iterator<Indices> it_indices = indicesG.iterator();
    return new ImmutableIterator<Triple>(){
      Iterator<Triple> it_triples = null;

      Triple triple = null;

      @Override
      public boolean hasNext() {
        if(this.triple!=null){
          return true;
        }
        this.triple = this.nextTriple();
        return (this.triple!=null);
      }

      @Override
      public Triple next() {
        if(this.triple!=null){
          final Triple inter_triple = this.triple;
          this.triple = null;
          return inter_triple;
        }
        return this.nextTriple();
      }

      public Triple nextTriple(){
        if(this.it_triples!=null && this.it_triples.hasNext()){
          // just do this here to be faster in the normal case...
          // (it would be enough to do this after the next while-loop)
          return this.it_triples.next();
        }
        while((this.it_triples==null || (this.it_triples!=null && !this.it_triples.hasNext())) && it_indices.hasNext()){
          final Indices indices = it_indices.next();
          final Collection<Triple> col_triples = ((SevenMemoryIndices) indices).getFromMap(mapPattern, keyString);
          this.it_triples = (col_triples==null) ? null : col_triples.iterator();
        }
        if(this.it_triples!=null && this.it_triples.hasNext()){
          return this.it_triples.next();
        } else {
          return null;
        }
      }
    };
  }


  @Override
  public QueryResult join(final Indices indices, final Bindings bindings) {
    final QueryResult queryResult = QueryResult.createInstance();
    queryResult.add(bindings); // empty since no bindings exist yet
    return this.join(indices, queryResult);
  }

  /**
   * Returns the result of a join operation using triple patterns and results
   * of previous queries
   *
   * @param tps
   *            a collection of triple patterns
   * @param queryResult
   *            the result of previous queries
   * @return the result of a join operation using triple patterns and results
   *         of previous queries
   */
  protected QueryResult join(final Indices indices, QueryResult queryResult) {
    try {

      // move over the collection of the provided triple patterns
      for (final TriplePattern tp : this.triplePatterns) {

        final QueryResult zQueryResult = queryResult;

        final Iterator<Bindings> itb = new ImmutableIterator<Bindings>() {
          Iterator<Bindings> oldBindings = zQueryResult.oneTimeIterator();
          Bindings currentBindings = null;
          Iterator<Triple> newTriples = null;
          Bindings next = null;

          @Override
          public boolean hasNext() {
            if (this.next != null) {
              return true;
            }
            this.next = this.computeNext();
            return (this.next != null);
          }

          @Override
          public Bindings next() {
            if (this.next != null) {
              final Bindings znext = this.next;
              this.next = null;
              return znext;
            }
            return this.computeNext();
          }

          public Bindings computeNext() {
            while ((this.newTriples == null || !this.newTriples.hasNext()) && this.oldBindings.hasNext()) {
              this.retrieveNewTriples();
            }
            if (this.newTriples == null || !this.newTriples.hasNext()) {
              return null;
            }
            final Triple triple = this.newTriples.next();
            final Bindings cB = this.currentBindings.clone();
            for (int i = 0; i < 3; i++) {
              if (tp.getPos(i).isVariable()) {
                final Literal l = cB.get((Variable) tp.getPos(i));
                if (l != null) {
                  if (!triple.getPos(i).equals(l)) {
                    return this.computeNext();
                  }
                } else {
                  cB.add((Variable) tp.getPos(i), triple.getPos(i));
                }
              }
            }
            cB.addTriple(triple);
            return cB;
          }

          private void retrieveNewTriples() {
            this.currentBindings = this.oldBindings.next();

            final StringBuffer key = new StringBuffer();
            int mapPattern = MAP_PATTERN.NONE.ordinal();

            // compute a key which is as restrictive as possible
            // to cut down the amount of triple pattern which
            // have
            // to be processed to produce the result
            if (MemoryIndexScan.this.computeKey4Maps(this.currentBindings, key, tp.getPos(0))) {
              mapPattern += MAP_PATTERN.SMAP.ordinal();
            }
            if (MemoryIndexScan.this.computeKey4Maps(this.currentBindings, key, tp.getPos(1))) {
              mapPattern += MAP_PATTERN.PMAP.ordinal();
            }
            if (MemoryIndexScan.this.computeKey4Maps(this.currentBindings, key, tp.getPos(2))) {
              mapPattern += MAP_PATTERN.OMAP.ordinal();
            }
            this.newTriples = MemoryIndexScan.this.getFromMap(MAP_PATTERN.values()[mapPattern], key.toString(), indices);
          }
        };

        // use a "fresh" object to gather the result of the join
        // operation
        // when using the current triple pattern and the previous query
        // results
        final QueryResult qresult = QueryResult.createInstance(itb);

        // replace the previous query results with the new ones
        queryResult.release();
        queryResult = qresult;
      }
      return queryResult;
    } catch (final Exception e) {
      System.err.println("Error while joining triple patterns"+e);
      return null;
    }
  }

  private Iterator<Triple> getFromMap(final MAP_PATTERN mapPattern,
      final String keyString, final Indices indicesG) {
    final Collection<Triple> tc = ((SevenMemoryIndices) indicesG).getFromMap(mapPattern, keyString);
    if(tc==null){
      return null;
    } else {
      return tc.iterator();
    }
  }

  /**
   * Computes and alters the key, respectively used to query the maps.<br>
   * To do this the information about the currently bound variables and the
   * information if the item is used.
   *
   * @param bindings
   *            - the currently available bindings
   * @param key
   *            the currently computed key which is to be extended
   * @param item
   *            the item used to extend the key
   * @return <code>true</code> if the key was extended.i
   */
  private boolean computeKey4Maps(final Bindings bindings,
      final StringBuffer key, final Item item) {

    // if the item is a variable, check if this variable
    // is bound
    if (item.isVariable()) {

      final Literal literal = bindings.get((Variable) item);

      // if the variable is bound, use the literal for the key used
      // later on to query the map
      if (literal != null) {
        key.append(literal.toString());
        return true;
      }

    }

    // otherwise if it is a literal which is no blank node
    // use the literal for the key used later on to query the map
    else if (!((Literal) item).isBlank()) {
      key.append(((Literal) item).toString());
      return true;
    }
    return false;
  }

  @Override
  public String toString() {
    return "Memory " + super.toString();
  }

  @Override
  public String toString(final lupos.rdf.Prefix prefixInstance) {
    return "Memory " + super.toString(prefixInstance);
  }
}
TOP

Related Classes of lupos.engine.operators.index.memoryindex.MemoryIndexScan

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.