RelationTreeModel.java

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         // Swing TreeModel methods:
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         // node is just a reference, not the node 'description', for that cf. toString()
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; // -1; // nothing in cache
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                 //long start = System.currentTimeMillis();
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                 //System.out.println("Exit getChildCount "+node+", result "+childCountCache+":"+ (System.currentTimeMillis()-start) + " mS, "+(dgcalls++)+ " dGcalls");
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                         // Assuming constant ordering of solutions, e.g. no tabling
00126                         /* Get description; to be totally cacheless we might not get the desciption
00127                         index = index+1;
00128                         String G = "NodeArray=[Node], get_solutionN("+ getRelationFunctor()+"(_,_,Node), "+index+",S), arg(1,S,Child), arg(2,S,Description)";
00129                         Object[] bindings = getEngine().deterministicGoal(G,"NodeArray",nodeInArray,"[Child,Description]");
00130                         Object child = bindings[0];
00131                         Object description = bindings[1];
00132                         return new RelationTreeNode(myModel,child,description.toString());
00133                         */
00134                         //System.out.println("Exit getChild "+index+" of "+node+":"+ (System.currentTimeMillis()-start) + " mS, "+(dgcalls++)+ " dGcalls");
00135                         // Get all offspring together:
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); // hopefully consistent with getChildCount()'s separate Prolog computation...
00150         }
00151         int getIndexOfChild(Object child){
00152                 System.out.println("getIndexOfChild");
00153                 //long start = System.currentTimeMillis();
00154                 RelationTreeNode childRTN = (RelationTreeNode)child;
00155                 // Assuming constant ordering of solutions, e.g. no tabling
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                 //System.out.println("Exit getIndexOfChild "+childRTN.node+" in "+node+":"+ (System.currentTimeMillis()-start) + " mS, "+(dgcalls++)+ " dGcalls");
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                 //long start = System.currentTimeMillis();
00168                 String G = "NodeArray=[Node], "+getRelationFunctor()+"(Node,Description,_)";
00169                 Object description = getEngine().deterministicGoal(G,"NodeArray",nodeInArray,"[Description]")[0];
00170                 //System.out.println("Exit toString "+ node+":"+ (System.currentTimeMillis()-start) + " mS, "+(dgcalls++)+ " dGcalls");
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 }

Generated on Wed Jul 26 13:30:44 2006 for XSB by  doxygen 1.4.5