00001 package com.declarativa.interprolog.gui;
00002 import com.declarativa.interprolog.*;
00003 import com.xsb.interprolog.*;
00004 import com.declarativa.interprolog.util.*;
00005 import java.util.*;
00006 import javax.swing.*;
00007 import javax.swing.tree.*;
00008 import javax.swing.event.*;
00009 import java.awt.event.*;
00010
00011 public class RelationTreeModel implements TreeModel{
00012 protected Vector listeners;
00013 PrologEngine engine;
00014 RelationTreeNode root;
00015 String relationFunctor;
00016
00017 public RelationTreeModel(PrologEngine engine,String relationFunctor,Object root){
00018 this.engine=engine;
00019 this.root=new RelationTreeNode(this,root);
00020 this.relationFunctor=relationFunctor;
00021 }
00022
00023 public static void browseRelation(PrologEngine engine,String relationFunctor,Object top){
00024 RelationTreeModel model = new RelationTreeModel(engine,relationFunctor,top);
00025 JTree tree = new JTree(model);
00026 JFrame w = new JFrame("Relation Tree Browser ("+top+")");
00027 w.getContentPane().add("Center",new JScrollPane(tree));
00028 w.setSize(300,300);
00029 w.setVisible(true);
00030 }
00031
00032 public static class BrowseAction extends AbstractAction{
00033 String relationFunctor; Object top; PrologEngine engine;
00034 public BrowseAction(PrologEngine engine,String relationFunctor,Object top){
00035 super(relationFunctor+"("+top+")");
00036 this.engine=engine;
00037 this.relationFunctor=relationFunctor;
00038 this.top=top;
00039 }
00040 public void actionPerformed(ActionEvent e){
00041 browseRelation(engine,relationFunctor,top);
00042 }
00043 }
00044
00045
00046
00047 public Object getRoot() {
00048 return root;
00049 }
00050 public Object getChild(Object parent,int index) {
00051 return ((RelationTreeNode)parent).getChild(index);
00052 }
00053 public int getChildCount(Object parent){
00054 return ((RelationTreeNode)parent).getChildCount();
00055 }
00056 public boolean isLeaf(Object node){
00057 return ((RelationTreeNode)node).isLeaf();
00058 }
00059 public void valueForPathChanged(TreePath path,Object newValue) {
00060 throw new RuntimeException("I can not handle term edition!");
00061 }
00062 public int getIndexOfChild(Object parent,Object child){
00063 return ((RelationTreeNode)parent).getIndexOfChild(child);
00064 }
00065 public void addTreeModelListener(TreeModelListener l){
00066 if (listeners==null) listeners = new Vector();
00067 listeners.addElement(l);
00068 }
00069 public void removeTreeModelListener(TreeModelListener l){
00070 if (!listeners.removeElement(l))
00071 throw new IPException("Bad removal of RelationTreeModel listener");
00072 }
00073
00074 public static class NodeDescriptionTriple implements java.io.Serializable{
00075 Object node,description;
00076 int childCount;
00077 }
00078 public static ObjectExamplePair example(){
00079 return new ObjectExamplePair(new NodeDescriptionTriple());
00080 }
00081 }
00082
00083
00084 class RelationTreeNode {
00085 static int dgcalls;
00086 RelationTreeModel myModel;
00087 private Object node;
00088 private Object[] nodeInArray;
00089 private int childCountCache;
00090 private String toStringCache;
00091 private Vector childrenCache;
00092
00093
00094 RelationTreeNode(RelationTreeModel model, Object node, String description, int childCount){
00095 myModel = model;
00096 if (!(node instanceof String) && !(node instanceof Number))
00097 throw new IPException("Bad value type for RelationTreeNode");
00098 this.node=node;
00099 nodeInArray = new Object[]{node};
00100 childCountCache = childCount;
00101 toStringCache = description;
00102 childrenCache = null;
00103 }
00104 RelationTreeNode(RelationTreeModel model, Object node){
00105 this(model,node,null,-1);
00106 }
00107 int getChildCount(){
00108 if (childCountCache!=-1) return childCountCache;
00109 System.err.println("getChildCount should be cached!!!");
00110
00111 String G = "NodeArray=[Node], countSolutions("+ getRelationFunctor()+ "(_,_,Node),N), ipObjectSpec('java.lang.Integer',Int,[N],_)";
00112 Integer N = (Integer)getEngine().deterministicGoal(G,"NodeArray",nodeInArray,"[Int]")[0];
00113 childCountCache = N.intValue();
00114
00115 dgcalls++;
00116 return childCountCache;
00117 }
00118 boolean isLeaf(){
00119 return getChildCount()==0;
00120 }
00121 Object getChild(int index){
00122 if (childrenCache==null) {
00123 childrenCache=new Vector();
00124 long start = System.currentTimeMillis();
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 String G = "NodeArray=[Node], ";
00137 G += "findall( Child, (";
00138 G += getRelationFunctor()+"(C,D,Node), countSolutions("+ getRelationFunctor()+ "(_,_,C),N), ";
00139 G += " ipObjectSpec('com.declarativa.interprolog.gui.RelationTreeModel$NodeDescriptionTriple',[node=C,description=D,childCount=N],Child)";
00140 G += "), L),";
00141 G += "ipObjectSpec('ArrayOfObject',L,Children)";
00142 Object[] children = (Object[])getEngine().deterministicGoal(G,"NodeArray",nodeInArray,"[Children]")[0];
00143 for (int i=0;i<children.length;i++) {
00144 RelationTreeModel.NodeDescriptionTriple c = (RelationTreeModel.NodeDescriptionTriple)children[i];
00145 childrenCache.addElement(new RelationTreeNode(myModel,c.node,c.description.toString(),c.childCount));
00146 }
00147 System.out.println("Exit getChild "+index+" of "+node+":"+ (System.currentTimeMillis()-start) + " mS, "+(dgcalls++)+ " dGcalls");
00148 }
00149 return childrenCache.elementAt(index);
00150 }
00151 int getIndexOfChild(Object child){
00152 System.out.println("getIndexOfChild");
00153
00154 RelationTreeNode childRTN = (RelationTreeNode)child;
00155
00156 String G = "Nodes=[Node,Child], get_solutionN("+ getRelationFunctor()+"(_,_,Node), N, "+getRelationFunctor()+"(Child,_,Node)), ";
00157 G += "ipObjectSpec('java.lang.Integer',Int,[N],_)";
00158 Integer N = (Integer)getEngine().deterministicGoal(G,"Nodes",new Object[]{node,childRTN.node},"[Int]")[0];
00159
00160 dgcalls++;
00161 return N.intValue();
00162 }
00163 public String toString(){
00164 if (toStringCache!=null) return toStringCache;
00165 System.err.println("toString should be cached!!!");
00166
00167
00168 String G = "NodeArray=[Node], "+getRelationFunctor()+"(Node,Description,_)";
00169 Object description = getEngine().deterministicGoal(G,"NodeArray",nodeInArray,"[Description]")[0];
00170
00171 dgcalls++;
00172 toStringCache = description.toString();
00173 return toStringCache;
00174 }
00175
00176 PrologEngine getEngine(){
00177 return myModel.engine;
00178 }
00179 String getRelationFunctor(){
00180 return myModel.relationFunctor;
00181 }
00182 }