/*
 *  Copyright (C) 2011-2012 The Animo Project
 *  http://animotron.org
 *  	
 *  This file is part of Animotron.
 *  
 *  Animotron is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as 
 *  published by the Free Software Foundation, either version 3 of 
 *  the License, or (at your option) any later version.
 *  
 *  Animotron 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 Affero General Public License for more details.
 *  
 *  You should have received a copy of 
 *  the GNU Affero General Public License along with Animotron.  
 *  If not, see <http://www.gnu.org/licenses/>.
 */
package org.animotron.statement.animo;

import javolution.util.FastSet;

import org.animotron.graph.index.Order;
import org.animotron.io.Pipe;
import org.animotron.manipulator.Evaluator;
import org.animotron.manipulator.OnQuestion;
import org.animotron.manipulator.PFlow;
import org.animotron.manipulator.QCAVector;
import org.animotron.statement.instruction.Instruction;
import org.animotron.statement.operator.AN;
import org.animotron.statement.operator.Evaluable;
import org.animotron.statement.operator.REF;
import org.animotron.statement.operator.Utils;
import org.animotron.statement.query.AbstractQuery;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.index.IndexHits;

/**
 * Return IS relations of object.
 * 
 * @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
 *
 */
public class WHATIS extends Instruction implements Evaluable {
	
	public static final WHATIS _ = new WHATIS();
	
	private WHATIS() { super("what-is", "whatis"); }

	@Override
	public OnQuestion onCalcQuestion() {
		return new Calc();
	}

    class Calc extends OnQuestion {
        @Override
        public void act(final PFlow pf) {
        	
        	Pipe pipe = Evaluator._.execute(pf.getController(), pf.getVector(), pf.getOP().getStartNode());
    		QCAVector v;
    		while ((v = pipe.take()) != null) {
            	IndexHits<Relationship> hits = Order.queryDown(v.getClosest().getEndNode());
            	try {
                	for (Relationship rr : hits) {
	        			if (!isLeaf(rr.getStartNode())) {
	        				pf.sendAnswer( rr );
	        			}
                	}
            	} finally {
            		hits.close();
            	}
    		}
        }
    }
    
    protected boolean isLeaf(Node node) {
		for (Relationship r : node.getRelationships(Direction.INCOMING, REF._))
			if (r.getStartNode().hasRelationship(Direction.INCOMING, AN._))
				return false;
		
		return true;
	};

}

@@ -915,82 +915,8 @@
 er;%0A
-import org.animotron.io.Pipe;%0Aimport org.animotron.manipulator.Evaluator;%0A
 impo
@@ -1021,225 +1021,36 @@
 ron.
-manipulator.QCAVector;%0Aimport org.animotron.statement.instruction.Instruction;%0Aimport org.animotron.statement.operator.AN;%0Aimport org.animotron.statement.operator.Evaluable;%0Aimport org.animotron.statement.operator.REF
+statement.operator.Reference
 ;%0Aim
@@ -1150,75 +1150,8 @@
 ry;%0A
-import org.neo4j.graphdb.Direction;%0Aimport org.neo4j.graphdb.Node;%0A
 impo
@@ -1378,19 +1378,21 @@
 nds 
-Instruction
+AbstractQuery
  imp
@@ -1403,16 +1403,16 @@
 nts 
-Evaluabl
+Referenc
 e %7B%0A
@@ -1696,186 +1696,270 @@
   %09%0A
-        %09Pipe pipe = Evaluator._.execute(pf.getController(), pf.getVector(), pf.getOP().getStartNode());%0A    %09%09QCAVector v;%0A    %09%09while ((v = pipe.take()) != null) %7B%0A      
+%09%09%09FastSet%3CRelationship%3E thes = FastSet.newInstance();%0A%09%09%09try %7B%0A%09%09%09%09Utils.getTHELikeBag(pf, pf.getVector(), thes);%0A%09%09%09%09%0A%09%09%09%09for (FastSet.Record rc = thes.head(), end = thes.tail(); (rc = rc.getNext()) != end;) %7B%0A%09%09%09%09%09Relationship the = thes.valueOf(rc);%0A%0A%09
     
-  
+%09%09
 %09Ind
@@ -2006,22 +2006,11 @@
 own(
-v.getClosest()
+the
 .get
@@ -2021,16 +2021,17 @@
 ode());%0A
+%09
         
@@ -2037,24 +2037,25 @@
      %09try %7B%0A
+%09
             
@@ -2086,24 +2086,25 @@
 r : hits) %7B%0A
+%09
 %09        %09%09%09
@@ -2112,26 +2112,35 @@
 f (!
-isLeaf
+Utils.haveContext
 (rr.get
-Start
+End
 Node
@@ -2146,16 +2146,17 @@
 e())) %7B%0A
+%09
 %09       
@@ -2181,16 +2181,17 @@
 ( rr );%0A
+%09
 %09       
@@ -2192,24 +2192,25 @@
        %09%09%09%7D%0A
+%09
             
@@ -2212,24 +2212,25 @@
          %09%7D%0A
+%09
             
@@ -2242,16 +2242,17 @@
 nally %7B%0A
+%09
         
@@ -2271,16 +2271,17 @@
 lose();%0A
+%09
         
@@ -2291,259 +2291,78 @@
  %09%7D%0A
-    %09%09%7D%0A        %7D%0A    %7D%0A    %0A    protected boolean isLeaf(Node node) %7B%0A%09%09for (Relationship r : node.getRelationships(Direction.INCOMING, REF._))%0A%09%09%09if (r.getStartNode().hasRelationship(Direction.INCOMING, AN._))%0A%09%09%09%09return false;%0A%09%09%0A%09%09return true;%0A%09%7D;%0A
+%09%09%09%09%7D%0A%09%09%09%7D finally %7B%0A%09%09%09%09FastSet.recycle(thes);%0A    %09%09%7D%0A        %7D%0A    %7D
 %0A%7D%0A

make WHAT-IS operator