private void JoinTuples (Tuple tuple1 ,Tuple tuple2)
	{
		//increase count outcome tuples because this join produces a tuple
		this.countOutcomeTuples++ ;
		//Constructing a new bitmap for new integrated tuple
		//==========================NEW READY BITS=======================================
		int newReadyBits  ;
		int xorT1T2ReadyBits = tuple1.getReadyBits() ^ tuple2.getReadyBits() ;
		int andT1T2ReadyBits =tuple1.getReadyBits() & tuple2.getReadyBits() ;
		//Integration of 2 tuple ready bits
		newReadyBits =xorT1T2ReadyBits | andT1T2ReadyBits;
		//This tuple maybe ready for new operators
		int newAvailableReadyBits =0 ;
		ArrayList<Byte> joinsOnSameVar = Eddy.getInstance().getJoinVarTojoinMapper().get(this.joinVariable) ;
		int joinReadyBitSetter = 0;
		for (Byte joinId: joinsOnSameVar)
		{
			joinReadyBitSetter = (1 << joinId) ;
			newAvailableReadyBits = newAvailableReadyBits | joinReadyBitSetter ;
		}
		int xorAvailableAndIntegration = newReadyBits ^ newAvailableReadyBits ;
		int andAvailableAndIntegration = newReadyBits & newAvailableReadyBits ;
		newReadyBits = xorAvailableAndIntegration | andAvailableAndIntegration ;
		//Don't Forget this again //Set ready bit for the current join to 0
		//newBitMap.put(this.joinId, JoinStatus.Done);
		int readyBitMasker = 1 << this.joinId ;
		readyBitMasker = ~readyBitMasker;
		//Final Operation for Ready Bits 
		newReadyBits = newReadyBits & readyBitMasker;
		//====================================END NEW READY BITS=========================================
		//====================================NEW DONE BITS============================================
		int newDoneBits  ;
		int xorT1T2DoneBits = tuple1.getDoneBits() ^ tuple2.getDoneBits() ;
		int andT1T2DoneBits =tuple1.getDoneBits() & tuple2.getDoneBits() ;
		//Integration of 2 tuple Done bits
		newDoneBits =xorT1T2DoneBits | andT1T2DoneBits;
		
		//Setting done bit 1 for this join id 
		int doneBitSetter = 0 ;
		doneBitSetter = 1<< this.joinId ;
		//Final operation for done bits
		newDoneBits =newDoneBits | doneBitSetter ;
		//==================================END NEW DONE BITS=========================================
//		for (Byte joinId:tuple1.getBitMap().keySet())
//		{
//			JoinStatus newBitMapStatus =newBitMap.get(joinId) ;
//			if (newBitMapStatus==null)
//				newBitMapStatus=JoinStatus.NotReady ;
//			JoinStatus MaximumStatus =Maximum (tuple1.getBitMap().get(joinId),tuple2.getBitMap().get(joinId),newBitMapStatus) ;
//			newBitMap.put(joinId, MaximumStatus);
//		}
		
		//Constructing a new subquerynamelist for new integrated tuple
		//badan check kon ke duplicate insert nashe dar subquery list yek tuple .
		ArrayList<String> newSubQueryNameList =new ArrayList<String>();
		for (String subQueryNameItem :tuple1.getSubQueryList())
		{
			newSubQueryNameList.add(subQueryNameItem);
		}
		for (String subQueryNameItem :tuple2.getSubQueryList())
		{
			newSubQueryNameList.add(subQueryNameItem);
		}
		
		//Constructing a new binding set for new integrated tuple 
		QueryBindingSet newqbSet =new QueryBindingSet();
		newqbSet.addAll(tuple1.getBindingSet()) ;
		newqbSet.addAll(tuple2.getBindingSet()) ;

		//new tuple priority= randomCeiling+1 or +2,+3,....
		int newPriority =1 ;
		if (tuple1.getPriority()>=tuple2.getPriority())
			newPriority=tuple1.getPriority() ;
		else
			newPriority=tuple2.getPriority() ;
		if (newPriority>this.randomCeiling)
			newPriority++ ;
		else
			newPriority=this.randomCeiling+1; 
		//and finaly create a new tuple from tuple1 , tuple2
		
		Tuple finalNewTuple =new Tuple(newqbSet,newReadyBits,newDoneBits,newSubQueryNameList,newPriority);
		//DEBUG
		//putTupleToFile2(finalNewTuple) ;
		//=====================HoooraY one Result Tuple ==========================//
		if (finalNewTuple.getDoneBits() == (Math.pow(2, numberOfJoinOperators)-1))
		{
			try 
			{
				this.resultTuples.put(finalNewTuple);
			} 
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
			this.coutResultTuples++ ;
//			System.out.println("Join "+joinId+" Count Results Tuples= "+coutResultTuples);
			//System.out.println(finalNewTuple.getBindingSet().toString());
			//System.out.println("There is "+workQueue.size()+" tuples in working quee of join "+joinId);
			//DEBUG
			//putTupleToFile(finalNewTuple) ;
		}

		else
		{
			try 
			{
				tupleHeap.put(finalNewTuple) ;
				//Because this is not a final tuple
				this.countIntermeidateTuplesGenerated++ ;
				
			} catch (InterruptedException e) 
			{
				throw new OptimizerException(e) ;
			}
			
		}
			
	}