All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.bop.paths.ZeroLengthPathOp Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
 * Created on Aug 25, 2010
 */

package com.bigdata.bop.paths;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpContext;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IConstant;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.IVariableOrConstant;
import com.bigdata.bop.NV;
import com.bigdata.bop.PipelineOp;
import com.bigdata.relation.accesspath.IBlockingBuffer;

import cutthecrap.utils.striterators.ICloseableIterator;

/**
 * An attempt to solve the zero length path problem with its own operator.
 * 
 * @deprecated Does not work. Leads to cardinality problems and can be removed.
 *             Zero Length Paths are integrated into the ALP node /
 *             ArbitraryLengthPathOp now.
 */
public class ZeroLengthPathOp extends PipelineOp {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public interface Annotations extends PipelineOp.Annotations {

    	/**
    	 * The left side of the zero-length path.
    	 */
        String LEFT_TERM = Annotations.class.getName() + ".leftTerm";

    	/**
    	 * The right side of the zero-length path.
    	 */
        String RIGHT_TERM = Annotations.class.getName() + ".rightTerm";
        
    }

    /**
     * Deep copy constructor.
     * 
     * @param op
     */
    public ZeroLengthPathOp(ZeroLengthPathOp op) {
        super(op);
    }

    /**
     * Shallow copy constructor.
     * 
     * @param args
     * @param annotations
     */
    public ZeroLengthPathOp(BOp[] args, Map annotations) {
        super(args, annotations);
    }

    public ZeroLengthPathOp(final BOp[] args, NV... annotations) {

        this(args, NV.asMap(annotations));
        
    }

    public FutureTask eval(final BOpContext context) {

        return new FutureTask(new ZeroLengthPathTask(this, context));

    }

    static private class ZeroLengthPathTask implements Callable {

        private final BOpContext context;
        
        private final IVariable leftVar, rightVar;
        
        private final IConstant leftConst, rightConst;
        
        ZeroLengthPathTask(final ZeroLengthPathOp op,
                final BOpContext context) {

            this.context = context;

            final IVariableOrConstant leftTerm = (IVariableOrConstant) op
                    .getProperty(Annotations.LEFT_TERM);
            
        	this.leftVar = leftTerm.isVar() ? (IVariable) leftTerm : null;
        	
        	this.leftConst = leftTerm.isConstant() ? (IConstant) leftTerm : null;

            final IVariableOrConstant rightTerm = (IVariableOrConstant) op
                    .getProperty(Annotations.RIGHT_TERM);
            
            this.rightVar = rightTerm.isVar() ? (IVariable) rightTerm : null;
            
            this.rightConst = rightTerm.isConstant() ? (IConstant) rightTerm : null;
            
        	if (leftConst != null && rightConst != null) {
        		
        		throw new IllegalArgumentException("must be a variable on at least one side");
        		
        	}
        	
        }

        public Void call() throws Exception {

            // source.
            final ICloseableIterator source = context
                    .getSource();

            // default sink
            final IBlockingBuffer sink = context.getSink();
            
            try {

            	while (source.hasNext()) {
            		
            		final IBindingSet[] chunk = source.next();
            		
            		final IBindingSet[] chunkOut = processChunk(chunk);
            		
        			sink.add(chunkOut);
            		
            	}
            	
                // flush the sink.
                sink.flush();

                // Done.
                return null;
                
            } finally {
                
                sink.close();
                
                source.close();
                
            }

        }
        
        @SuppressWarnings("unchecked")
		private IBindingSet[] processChunk(final IBindingSet[] chunk) {
        	
    		final IBindingSet[] chunkOut = new IBindingSet[chunk.length];
    		
    		int j = 0;
    		for (int i = 0; i < chunk.length; i++) {
    			
    			final IBindingSet bs = chunk[i].clone();
    			
    			final Gearing gearing = getGearing(bs);
    			
    			if (gearing == null) {
    				
    				// neither side of the zero-length path is bound
    				return new IBindingSet[0];
    				
    			}
    			
    			// first check to see if the variable side is already bound
    			if (bs.isBound(gearing.var)) {
    				
    				/*
    				 * If it has a value that is not equals to the constant 
    				 * side then we filter out the solution (by not adding it
    				 * to chunkOut).
    				 */
    				
    				if (!bs.get(gearing.var).equals(gearing.constant)) {
    					
    					continue;
    					
    				}
    				
    			} else {
    				
    				// create a zero length path
    				bs.set(gearing.var, gearing.constant);
    				
    			}
    			
    			chunkOut[j++] = bs;
    			
    		}
    		
    		if (j != chunk.length) {
    			
    			final IBindingSet[] tmp = new IBindingSet[j];
    			
    			System.arraycopy(chunkOut, 0, tmp, 0, j);
    			
    			return tmp;
    			
    		} else {
    			
    			return chunkOut;
    			
    		}
    			
        }
        
        private Gearing getGearing(final IBindingSet bs) {
        	
        	if (leftConst != null) {
        		
        		return new Gearing(rightVar, leftConst);
        		
        	} else if (rightConst != null) {
        		
        		return new Gearing(leftVar, rightConst);
        		
        	} else { // both left and right are vars

        		if (bs.isBound(this.leftVar)) {
        			
        			return new Gearing(this.rightVar, bs.get(this.leftVar));
        			
        		} else if (bs.isBound(this.rightVar)) {
        			
        			return new Gearing(this.leftVar, bs.get(this.rightVar));
        			
        		} else {
        			
        			return null;
        			
        		}
        		
        	}
        	
        }
        
        private class Gearing {
        	
        	final public IVariable var;
        	
        	final public IConstant constant;
        	
        	public Gearing(final IVariable var, final IConstant constant) {
        		
        		this.var = var;
        		this.constant = constant;
        		
        	}
        	
        }

    } // class ZeroLengthPathTask

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy