/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.sparql.engine.join;
import java.util.Collection ;
import java.util.Iterator ;
import java.util.List ;

import org.apache.jena.atlas.lib.DS ;

import org.apache.jena.sparql.core.Var ;

/** JoinKey for hash joins */
public final class JoinKey implements Iterable<Var>
{
    private static final JoinKey emptyKey = new JoinKey(DS.listOfNone()) ;

    // Common way to make a JoinKey
    /** Make a JoinKey from the intersection of two sets **/  
    public static JoinKey create(Collection<Var> vars1, Collection<Var> vars2) {
        // JoinKeys are generally small so short loops are best.
        // vars2 may be smallest e.g. from triple and running accumulator (vars1) 
        List<Var> intersection = DS.list() ;
        for ( Var v : vars1 ) {
            if ( vars2.contains(v) )
                intersection.add(v) ;  
        }
        return new JoinKey(intersection) ;
    }
    
    /** Make a JoinKey of single variable from the intersection of two sets **/  
    public static JoinKey createVarKey(Collection<Var> vars1, Collection<Var> vars2) {
        // JoinKeys are generally small so short loops are best.
        // vars2 may be smallest e.g. from triple and running accumulator (vars1) 
        List<Var> intersection = DS.list() ;
        for ( Var v : vars1 ) {
            if ( vars2.contains(v) )
                // First and single key.
                return create(v) ;
                // Compound keys needs validation : what if they are partial
                // i.e. some rows only have part of the join key?
                //intersection.add(v) ;  
        }
        return emptyKey ;
    }
    
    public static JoinKey create(Var var) {
        return new JoinKey(var) ;
    }
    
    /** The builder can emit a key every time build() is caller
     * and it can be continued to be used.
     */
    public static final class Builder {
        private List<Var> keys = DS.list() ;
        
        public Builder() { }
        
        public boolean contains(Var var) {
            return keys.contains(var) ;
        }
        
        public Builder add(Var var) {
            // We expect the keys list to be short - a Set is overkill(??)
            if ( ! contains(var) )
                keys.add(var) ;
            return this ;
        }
        
        public Builder remove(Var var) {
            keys.remove(var) ;
            return this ;
        }

        public Builder clear()      { keys.clear() ; return this ; }

        public JoinKey build() {
            JoinKey joinKey = new JoinKey(DS.list(keys)) ; 
            return joinKey ;
        }
    }
    
    // Consider using an array.
    private final List<Var> keys ;
    
    private JoinKey(List<Var> _keys) { keys = _keys ; }
    
    private JoinKey(Var var)        { keys = DS.listOfOne(var) ; }
    
    public boolean isEmpty()        { return keys.isEmpty() ; }
    
    public int length()             { return keys.size() ; }

    /** Get a single variable for this key. 
     *  For any one key, it always returns the same var */ 
    public Var getVarKey() { 
        if ( keys.isEmpty() )
            return null ;
        return keys.get(0) ;
    }
    
    @Override
    public Iterator<Var> iterator() { return keys.iterator() ; }
    
    @Override
    public String toString() {
        return keys.toString() ;
    }
}

@@ -1093,16 +1093,47 @@
 %3CVar%3E%0A%7B%0A
+    /** Key of no variables */%0A
     priv
@@ -1204,44 +1204,8 @@
  ;%0A%0A
-    // Common way to make a JoinKey%0A
     
@@ -1356,32 +1356,53 @@
     // JoinKeys 
+and choices for keys 
 are generally sm
@@ -1434,91 +1434,8 @@
 st.%0A
-        // vars2 may be smallest e.g. from triple and running accumulator (vars1) %0A
     
@@ -1829,522 +1829,103 @@
     
-// JoinKeys are generally small so short loops are best.%0A        // vars2 may be smallest e.g. from triple and running accumulator (vars1) %0A        List%3CVar%3E intersection = DS.list() ;%0A        for ( Var v : vars1 ) %7B%0A            if ( vars2.contains(v) )%0A                // First and single key.%0A                return create(v) ;%0A                // Compound keys needs validation : what if they are partial%0A                // i.e. some rows only have part of the join key?%0A                //intersection.add(v) ;  
+for ( Var v : vars1 ) %7B%0A            if ( vars2.contains(v) )%0A                return create(v) ;
 %0A   

Remove repeated comments