/*
 *  Copyright (C) 2011 The Animo Project
 *  http://animotron.org
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 3
 *  of the License, or (at your option) any later version.
 *
 *  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 Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.animotron.graph.traverser;

import org.animotron.graph.handler.GraphHandler;
import org.animotron.graph.serializer.CachedSerializer;
import org.animotron.manipulator.PFlow;
import org.animotron.manipulator.QCAVector;
import org.animotron.statement.Prefix;
import org.animotron.statement.Statement;
import org.animotron.statement.Statements;
import org.animotron.statement.ml.ELEMENT;
import org.animotron.statement.ml.MLOperator;
import org.animotron.statement.ml.NS;
import org.animotron.statement.ml.QNAME;
import org.animotron.statement.operator.Evaluable;
import org.animotron.statement.operator.REF;
import org.animotron.statement.operator.Shift;
import org.animotron.statement.relation.USE;
import org.animotron.statement.value.VALUE;
import org.neo4j.graphdb.Relationship;

import java.io.IOException;

/**
 * @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
 * @author <a href="mailto:gazdovskyd@gmail.com">Evgeny Gazdovsky</a>
 * 
 */
public class MLResultTraverser extends ResultTraverser {

    public static MLResultTraverser _ = new MLResultTraverser();

    protected MLResultTraverser() {}

    @Override
    protected void process(GraphHandler handler, PFlow pf, Statement s, Statement parent, QCAVector rr, int level, boolean isOne, int pos, boolean isLast) throws IOException {

        if (s != null) {
            if (s instanceof MLOperator || s instanceof VALUE) {
                if (s instanceof Prefix) {
                    node = rr.getClosest().getEndNode();
                    It it = new It(node);
                    String[] param = {null, null};
                    try {
                        if (it.hasNext()) {
                            Object p = it.next();
                            param[0] = param(pf, p);
                            if (!(s instanceof ELEMENT)) {
                                param[1] = param(pf, it);
                                if (param[1] == null) {
                                    if (s instanceof NS) {
                                        if (QNAME._.name().equals(p instanceof String ? p : ((Relationship) p).getType().name())) {
                                            param[1] = "";
                                        } else {
                                            param[1] = param[0];
                                            param[0] = "";
                                        }
                                    }
                                }
                            }
                            handler.start(s, parent, param, level++, isOne, pos, isLast);
                            iterate(handler, pf, rr, s, it, level);
                            handler.end(s, parent, param, --level, isOne, pos, isLast);
                        }
                    } finally {
                        it.remove();
                    }
                } else if (!(s instanceof VALUE) || (s instanceof VALUE && level > 0)) {
                    String param = CachedSerializer.STRING.serialize(pf, rr);
                    handler.start(s, parent, param, level++, isOne, pos, isLast);
                    handler.end(s, parent, param, --level, isOne, pos, isLast);
                }
            } else {
            	//XXX: send to super method?
            	Statement qS = Statements.relationshipType(rr.getQuestion());
            	if ((qS instanceof Shift && rr.getUnrelaxedAnswer() == null)
            			|| (s instanceof Evaluable && !(qS instanceof Shift))
        			) {

            		result(handler, pf, rr, level, isOne);
            		//workaround IS and USE
            	} else if (!(s instanceof USE || s instanceof REF)) {
            		node = rr.getClosest().getEndNode();
            		iterate(handler, pf, rr, s, new It(node), level);
            	}
            }
        }
    }

    private String param(PFlow pf, It it) throws IOException {
        if (it.hasNext()) {
            return param(pf, it.next());
        }
        return null;
    }

    private String param(PFlow pf, Object o) throws IOException {
        return
            o instanceof Relationship
                ? CachedSerializer.STRING.serialize(pf, (Relationship) o)
                : (String) node.getProperty((String) o);
    }

}

@@ -1112,51 +1112,8 @@
 nt;%0A
-import org.animotron.statement.Statements;%0A
 impo
@@ -1280,196 +1280,8 @@
 ME;%0A
-import org.animotron.statement.operator.Evaluable;%0Aimport org.animotron.statement.operator.REF;%0Aimport org.animotron.statement.operator.Shift;%0Aimport org.animotron.statement.relation.USE;%0A
 impo
@@ -3836,559 +3836,79 @@
     
-%09//XXX: send to super method?%0A            %09Statement qS = Statements.relationshipType(rr.getQuestion());%0A            %09if ((qS instanceof Shift && rr.getUnrelaxedAnswer() == null)%0A            %09%09%09%7C%7C (s instanceof Evaluable && !(qS instanceof Shift))%0A        %09%09%09) %7B%0A%0A            %09%09result(handler, pf, rr, level, isOne);%0A            %09%09//workaround IS and USE%0A            %09%7D else if (!(s instanceof USE %7C%7C s instanceof REF)) %7B%0A            %09%09node = rr.getClosest().getEndNode();%0A            %09%09iterate(handler, pf, rr, s, new It(node), level);%0A            %09%7D
+    super.process(handler, pf, s, null, rr, level, isOne, pos, isLast);
 %0A   

fix ML traverser