TermModel.java

00001 /* 
00002 ** Author(s): Miguel Calejo
00003 ** Contact:   interprolog@declarativa.com, http://www.declarativa.com
00004 ** Copyright (C) Declarativa, Portugal, 2000-2002
00005 ** Use and distribution, without any warranties, under the terms of the 
00006 ** GNU Library General Public License, readable in http://www.fsf.org/copyleft/lgpl.html
00007 */
00008 package com.declarativa.interprolog;
00009 import com.declarativa.interprolog.util.*;
00010 import javax.swing.*;
00011 import javax.swing.tree.*;
00012 import javax.swing.event.*;
00013 import java.io.*;
00014 import java.util.*;
00015 
00020 public class TermModel implements Serializable,TreeModel{
00022         public Object node;
00025         public TermModel[] children; 
00026         private transient Vector treeListeners=null /*new Vector() here doesn't work on deserialization...*/;
00027         private transient Vector termListeners;
00030         public transient TermModel root; 
00031         
00032         static PrologOperatorsContext defaultOperatorContext = new PrologOperatorsContext();
00033         
00034         public static ObjectExamplePair example(){
00035                 return new ObjectExamplePair("TermModel",
00036                         new TermModel(new Integer(1),(TermModel[])null),
00037                         new TermModel("functor",new TermModel[1])
00038                         );
00039         }
00040         
00043         public Object clone(){
00044                 Object x = null;
00045                 try{
00046                         ByteArrayOutputStream buffer = new ByteArrayOutputStream(100);
00047                         ObjectOutputStream oos = new ObjectOutputStream(buffer);
00048                         oos.writeObject(this); oos.close();
00049                         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
00050                         x = ois.readObject();
00051                         ois.close();
00052                 } catch (Exception e){
00053                         throw new IPException("Failed to clone");
00054                 }
00055                 return x;
00056         }
00057         
00059         public boolean equals(Object x){
00060                 if (!(x instanceof TermModel)) return false;
00061                 TermModel tx = (TermModel)x;
00062                 if (!(node.equals(tx.node))) return false;
00063                 if (getChildCount()!=tx.getChildCount()) return false;
00064                 for (int c=0; c<getChildCount(); c++)
00065                         if (!(getChild(c).equals(tx.getChild(c)))) return false;
00066                 return true;
00067         }
00068         
00070         public void setNodeValue(Object v){
00071                 if (v!=null) {
00072                         if (!(v instanceof Serializable))
00073                         throw new IPException("TermModel nodes must be Serializable");
00074                         if (!((v instanceof Number)||(v instanceof String)||(v instanceof VariableNode)))
00075                         throw new IPException("Bad TermModel node type");
00076                 }
00077                 boolean changed = !(v==node);
00078                 node=v;
00079                 if (changed) fireTermChanged();
00080         }
00081         
00083         public void setChild(int index,TermModel child){
00084                 boolean changed = !(child==children[index]);
00085                 children[index] = child;
00086                 if (changed) fireTermChanged();
00087         }
00088         
00090         public void setChildren(TermModel[] c){
00091                 boolean changed = !(children==c);
00092                 children=c;
00093                 if (changed) fireTermChanged();
00094         }
00095         
00096         public TermModel[] getChildren(){
00097                 return children;
00098         }
00099         
00101         public void addChildren(TermModel[] more){
00102                 if (more.length==0) return;
00103                 TermModel[] newChildren = new TermModel[getChildCount()+more.length];
00104                 for (int i=0;i<getChildCount();i++)
00105                         newChildren[i] = children[i];
00106                 for (int i=getChildCount();i<getChildCount()+more.length;i++)
00107                         newChildren[i] = more[i-getChildCount()];
00108                 setChildren(newChildren);
00109         }
00110         
00112         public void deleteChildren(int[] less){
00113                 if (less.length==0) return;
00114                 TermModel[] newChildren = new TermModel[getChildCount()-less.length];
00115                 int oldIndex=0;
00116                 for (int newIndex=0;newIndex<newChildren.length;newIndex++){
00117                         while (inArray(oldIndex,less)) oldIndex++;
00118                         newChildren[newIndex] = children[oldIndex];
00119                         oldIndex++;
00120                 }
00121                 setChildren(newChildren);
00122         }
00123         
00125         public void deleteChildren(TermModel[] less){
00126                 if (less.length==0) return;
00127                 TermModel[] newChildren = new TermModel[getChildCount()-less.length];
00128                 int oldIndex=0;
00129                 for (int newIndex=0;newIndex<newChildren.length;newIndex++){
00130                         while (inArray(children[oldIndex],less)) oldIndex++;
00131                         newChildren[newIndex] = children[oldIndex];
00132                         oldIndex++;
00133                 }
00134                 setChildren(newChildren);
00135         }
00136         
00137         static boolean inArray(int x,int[] a){
00138                 for(int i=0;i<a.length;i++)
00139                         if (x==a[i]) return true;
00140                 return false;
00141         }
00142         
00143         static boolean inArray(Object x,Object[] a){
00144                 for(int i=0;i<a.length;i++)
00145                         if (x.equals(a[i])) return true;
00146                 return false;
00147         }
00148         
00150         public void assignToVar(VariableNode v,Object value){
00151                 if (v.equals(node)) {
00152                         setNodeValue(value);
00153                 }
00154                 for (int i=0; i<getChildCount(); i++)
00155                         children[i].assignToVar(v,value);
00156         }
00157 
00159         public void setRoot(){
00160                 setRoot(this);
00161         }
00162                 
00164         public void setRoot(TermModel r){
00165                 if (root!=null) return; // subtree already set, ignore "new" root
00166                 root=r;
00167                 propagateRoot();
00168         }
00169         
00171         public boolean isRoot(){ return root==this;}
00172         
00173         protected void propagateRoot(){
00174                 for(int i=0;i<getChildCount();i++)
00175                         children[i].setRoot(root);
00176         }
00177         
00179         public String getTemplate(){
00180                 StringBuffer temp = new StringBuffer(node.toString());
00181                 for (int i=0; i<getChildCount(); i++) {
00182                         if (i==0) temp.append("(");
00183                         if (i>0) temp.append(",");
00184                         temp.append("_");
00185                 }
00186                 if (getChildCount()>0) temp.append(")");
00187                 return temp.toString();
00188         }
00189 
00191         public String getFunctorArity(){
00192                 return node+"/"+getChildCount();
00193         }
00194         
00195         // Swing TreeModel methods:
00196         
00198         public Object getRoot() {
00199                 return this;
00200         }
00202         public Object getChild(Object parent,int index) {
00203                 return ((TermModel)parent).children[index];
00204         }
00206     public int getChildCount(Object parent){
00207         TermModel[] c = ((TermModel)parent).children;
00208         if (c==null) return 0;
00209                 else return c.length;
00210     }
00212     public boolean isLeaf(Object node){
00213         return (getChildCount(node) == 0);
00214     }
00216     public void valueForPathChanged(TreePath path,Object newValue) {
00217         throw new RuntimeException("I can not handle term edition!");
00218     }   
00220     public int getIndexOfChild(Object parent,Object child){
00221         TermModel[] c = ((TermModel)parent).children;
00222         if (c==null) return 0;
00223         for (int i=0; i<c.length; i++)
00224                 if (c[i]==child) return i+1;
00225         return 0;
00226     }
00228         public void addTreeModelListener(TreeModelListener l){
00229                 if (treeListeners==null) treeListeners = new Vector();
00230                 treeListeners.addElement(l);
00231         }
00233         public void removeTreeModelListener(TreeModelListener l){
00234                 if (!treeListeners.removeElement(l)) 
00235                 throw new IPException("Bad removal of TermModel listener");
00236         }
00237         
00238         // simpler versions
00239         public Object getChild(int index) {
00240                 return getChild(this,index);
00241         }       
00242     public int getChildCount(){
00243                 return getChildCount(this);
00244     }
00245         public boolean isLeaf(){
00246         return isLeaf(this);
00247     }
00248         
00252         public void addTermModelListener(TermModelListener l){
00253                 if (!isRoot())
00254                         throw new IPException("addTermModelListener can be sent to the TermModel root only");
00255                 if (termListeners==null) termListeners = new Vector();
00256                 termListeners.addElement(l);
00257         }
00258         public void removeTermModelListener(TermModelListener l){
00259                 if (!termListeners.removeElement(l)) 
00260                 throw new IPException("Bad removal of TermModelListener");
00261         }
00262         public void fireTermChanged(){
00263                 if (isRoot()) {
00264                         if (termListeners!=null)
00265                                 for (int l=0;l<termListeners.size();l++)
00266                                         ((TermModelListener)termListeners.elementAt(l)).termChanged(this);
00267                 } else if (root!=null) root.fireTermChanged();
00268         }
00269     // two convenience methods for simple node searching
00270     
00271         public static TreePath findPathForNode(String label,TermModel tree,boolean exactMatch){
00272                 Vector subtrees = new Vector();
00273                 foundPathForNode(label, tree, exactMatch, subtrees);
00274                 if (subtrees.size()==0) return null;
00275                 Object[] path = new Object[subtrees.size()];
00276                 for (int n=0; n<path.length; n++)
00277                         path[n] = subtrees.elementAt(path.length-n-1);
00278                 return new TreePath(path);                              
00279         }
00280         
00281         static boolean foundPathForNode(String label,TermModel tree,boolean exactMatch,Vector bag){
00282                 if ((exactMatch?tree.node.equals(label):tree.node.toString().startsWith(label))){
00283                         bag.addElement(tree);
00284                         return true;
00285                 } else{
00286                         for (int c=0;c<tree.getChildCount();c++){
00287                                 if (foundPathForNode(label,(TermModel)(tree.getChild(c)),exactMatch,bag)){
00288                                         bag.addElement(tree); return true;
00289                                 }
00290                         }
00291                         return false;
00292                 }
00293         }
00294         
00295         public TermModel(){}
00296         
00297         public TermModel(Object n){this(n,(TermModel[])null);}
00298         
00299         public TermModel(Object n,TermModel[] c){
00300                 children=c;
00301                 node=n; 
00302         }
00303         
00304         public TermModel(Object n,Vector v){
00305                 node=n; 
00306                 if (v.size()==0) children=null;
00307                 else {
00308                         children = new TermModel[v.size()];
00309                         for(int c=0;c<children.length;c++)
00310                                 children[c] = (TermModel)v.elementAt(c);
00311                 }
00312         }
00313         
00314         public static TermModel makeList(TermModel[] terms){
00315                 if (terms==null) return new TermModel(".");
00316                 else return makeList(0,terms);
00317         }
00318         
00319         public static TermModel makeList(Vector terms){
00320                 if (terms==null) return new TermModel(".");
00321                 else return makeList(0,terms);
00322         }
00323         
00324         protected static TermModel makeList(int t, TermModel[] terms){
00325                 TermModel[] cc = new TermModel[2];
00326                 cc[0] = terms[t];
00327                 if (t == terms.length - 1) {
00328                         cc[1] = new TermModel("[]");
00329                 } else {
00330                         cc[1] = makeList(t+1,terms);
00331                 }
00332                 return new TermModel(".",cc);
00333         }
00334         
00335         protected static TermModel makeList(int t, Vector terms){
00336                 TermModel[] cc = new TermModel[2];
00337                 cc[0] = (TermModel)terms.elementAt(t);
00338                 if (t == terms.size() - 1) {
00339                         cc[1] = new TermModel("[]");
00340                 } else {
00341                         cc[1] = makeList(t+1,terms);
00342                 }
00343                 return new TermModel(".",cc);
00344         }
00345         
00347         public Vector makeIntegerVector(){
00348                 TermModel[] elements = flatList(this);
00349                 Vector iv = new Vector();
00350                 for(int i=0;i<elements.length;i++)
00351                         iv.addElement(new Integer(elements[i].intValue()));
00352                 return iv;
00353         }
00354         
00356         public int intValue(){
00357                 if (! isLeaf() || !(node instanceof Number))
00358                         throw new RuntimeException("intValue() requires a Number leaf");
00359                 return ((Number)node).intValue();
00360         }
00361         
00362         public String toString(){
00363                 return toString(defaultOperatorContext);
00364                 // return node.toString(); // For a plain JTree...
00365         }
00366         
00367         public String toString(PrologOperatorsContext ops){
00368                 if (getChildCount()==0) 
00369                         return node.toString();
00370                 else if (isList()) return listToString(ops);
00371                 else if (children.length==1){
00372                         if (ops.prefixOperator(node))
00373                                 return node+" "+children[0].toString(ops);
00374                         else if (ops.postfixOperator(node))
00375                                 return children[0].toString(ops)+" "+node;
00376                         else
00377                                 return node+"("+children[0].toString(ops)+")";
00378                 } else if (children.length==2 && ops.infixOperator(node)) {
00379                     //return children[0].toString(ops)+node+children[1].toString(ops);
00380                     return "("+children[0].toString(ops)+node+children[1].toString(ops)+")";
00381                 } else { // children.lenght>=2
00382                     StringBuffer s= new StringBuffer(node.toString()+"("+children[0].toString(ops));
00383                         for (int i=1;i<children.length;i++){
00384                                 s.append(","+children[i].toString(ops));
00385                         }
00386                         return s+")";
00387                 }
00388         }
00389         
00390         public static final int listMaxLength=100;
00391         
00392         public String listToString(PrologOperatorsContext ops){
00393                 int i;
00394                 StringBuffer s = new StringBuffer("[");
00395                 TermModel temp = this;
00396                 for( i = 0 ; i < listMaxLength ; i++ ){
00397                         s.append(temp.children[0].toString(ops)); // head
00398                         temp = temp.children[1];
00399                         if( ! temp.isList() ) break ; // tail is not a list
00400                         s.append(',') ;
00401                 }
00402                 if( i == listMaxLength )
00403                         s.append("...");
00404                 else if ( ! temp.isListEnd() )
00405                 {
00406                         s.append('|') ;
00407                         s.append(temp.toString(ops)); 
00408                 }
00409                 return s + "]";
00410         }
00411         
00412         public boolean isListEnd(){
00413                 return (isLeaf() && node.equals("[]"));
00414         }
00415         
00416         public boolean isList(){
00417                 // return (children.length==2 && node.equals("."));
00418                 return node.equals(".");
00419         }
00420         
00421         public boolean isAtom(){
00422                 return (isLeaf() && node instanceof String);
00423         }
00424         
00425         public boolean isNumber(){
00426                 return (isLeaf() && node instanceof Number);
00427         }
00428         
00429         public boolean isInteger(){
00430                 return (isLeaf() && node instanceof Integer);
00431         }
00432         
00433         public boolean isVar(){
00434                 return (isLeaf() && nodeIsVar());
00435         }
00436         
00437         public boolean nodeIsVar(){
00438                 return (node instanceof VariableNode);
00439         }
00440         
00443         public TermModel[] flatList(){
00444                 return flatList(this);
00445         }
00446         
00449         public static TermModel[] flatList(TermModel list){
00450                 Vector temp = new Vector();
00451                 flatList(list,temp);
00452                 TermModel[] result = new TermModel[temp.size()];
00453                 for (int i=0;i<result.length;i++)
00454                         result[i] = (TermModel) (temp.elementAt(i));
00455                 return result;
00456         }
00457         static void flatList(TermModel x,Vector bag){
00458                 if (x.isList()) {
00459                         if (x.children!=null){
00460                                 bag.addElement(x.children[0]);
00461                                 flatList(x.children[1],bag);
00462                         } // else it's an empty list
00463                 } else if (!x.isListEnd()) {
00464                         bag.addElement(x);
00465                 }
00466         }
00467         
00468         public static Hashtable props2Hashtable(TermModel[] terms){
00469                 Hashtable result = new Hashtable();
00470                 for (int t=0;t<terms.length;t++){
00471                         TermModel term = terms[t];
00472                         if (term.isLeaf()) result.put(term.node.toString(),term.node);
00473                         else if ((!term.node.equals("=") || term.getChildCount()!=2)) 
00474                                 throw new RuntimeException("bad proplist");
00475                         else result.put(term.children[0].toString(),term.children[1]);
00476                 }
00477                 return result;
00478         }
00479 }
00480 
00481 

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