package jp.ac.do_johodai.j314.sw.je;

import java.util.ArrayList;

import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.reasoner.rulesys.builtins.BaseBuiltin;
import com.hp.hpl.jena.reasoner.rulesys.RuleContext;
import com.hp.hpl.jena.reasoner.rulesys.BindingEnvironment;
import com.hp.hpl.jena.util.iterator.ClosableIterator;

/**
 * 第1引数と第2引数のリストを結合して第3引数の
 * 変数に代入する。
 */
public class ListAppendBuiltin extends BaseBuiltin {
    public String getName() {
        return "list_append";
    }

    public int getArgLength() {
        return 3;
    }

    public boolean bodyCall(Node[] args, int length, RuleContext context) {
        if (length != 3)
            return false;
        listAppend(args,length,context);
        return true;
    }

    public void headAction(Node[] args, int length, RuleContext context) {
        listAppend(args,length,context);
    }

    void listAppend(Node[] args,int length,RuleContext context) {
        Node first = Node.create("http://www.w3.org/1999/02/22-rdf-syntax-ns#first");
        Node rest = Node.create("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest");
        Node nil = Node.create("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
        ArrayList<Node> al = new ArrayList<Node>();
        Node n = args[0];
        while (!n.equals(nil)) {
            ClosableIterator ci = context.find(n,first,null);
            Node e = ((Triple)ci.next()).getObject();
            al.add(e);
            ci = context.find(n,rest,null);
            n = ((Triple)ci.next()).getObject();
        }
        n = args[1];
        while (!n.equals(nil)) {
            ClosableIterator ci = context.find(n,first,null);
            Node e = ((Triple)ci.next()).getObject();
            al.add(e);
            ci = context.find(n,rest,null);
            n = ((Triple)ci.next()).getObject();
        }
        Node nn[] = al.toArray(new Node[0]);
        Node list = Node.create("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
        for (int i=nn.length-1;i>=0;i--) {
            Node tail = list;
            list = Node.createAnon();
            context.add(new Triple(list,first,nn[i]));
            context.add(new Triple(list,rest,tail));
        }
        BindingEnvironment env = context.getEnv();
        env.bind(args[2],list);
    }
}
