00001
00002
00003
00004
00005
00006
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 ;
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;
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
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
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
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
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
00380 return "("+children[0].toString(ops)+node+children[1].toString(ops)+")";
00381 } else {
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));
00398 temp = temp.children[1];
00399 if( ! temp.isList() ) break ;
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
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 }
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