1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package zeus.concepts;
29
30 import java.io.*;
31 import java.util.*;
32 import javax.swing.event.*;
33
34 import zeus.util.*;
35 import zeus.concepts.fn.*;
36
37
38
39 /***
40 * This implements the Ontology Database component, which has two main roles:
41 * <ul>
42 * <li> database - to store the conceptual descriptions that make up an ontology
43 * <li> factory - to create new {@link Fact} objects from the stored fact descriptions
44 * </ul> <p>
45 *
46 * Aside from the fact creation and query methods, developers are unlikely to
47 * need the other methods of this class.
48 * Change Log
49 * 26/06/01 introduced allAncestors method which returns an interator containing all
50 * ancestors of a type - Simon Thompson
51 */
52
53
54 public class OntologyDb extends Tree {
55 /*** OntologyDbChangeEvent types */
56
57 public static final int RELOAD = 0;
58 public static final int FACT_ADDED = 1;
59 public static final int FACT_REMOVED = 2;
60 public static final int FACT_RENAMED = 3;
61 public static final int ATTRIBUTES_CHANGED = 4;
62 public static final int RESTRICTION_ADDED = 5;
63 public static final int RESTRICTION_REMOVED = 6;
64 public static final int RESTRICTION_CHANGED = 7;
65
66
67
68
69
70 public static final String ROOT = "ZeusFact";
71 public static final String ABSTRACT = "Abstract";
72 public static final String ENTITY = "Entity";
73 public static final String MESSAGE = "Message";
74 public static final String MONEY = "Money";
75
76 public static final String AMOUNT = "amount";
77 public static final String NUMBER = "number";
78 public static final String COST = "unit_cost";
79 public static final String GOAL_FACT = "fact";
80
81 public static final int WARNING_MASK = 1;
82 public static final int ERROR_MASK = 2;
83
84 static final String BEGIN_ONTOLOGY = "BEGIN_ONTOLOGY";
85 static final String BEGIN_PREAMBLE = "BEGIN_PREAMBLE";
86 static final String BEGIN_RESTRICTIONS = "BEGIN_RESTRICTIONS";
87 static final String BEGIN_RESTRICTION_ITEM = "BEGIN_RESTRICTION_ITEM";
88 static final String BEGIN_FACTS = "BEGIN_FACTS";
89 static final String BEGIN_FACT_ITEM = "BEGIN_FACT_ITEM";
90 static final String BEGIN_ATTRIBUTE_LIST = "BEGIN_ATTRIBUTE_LIST";
91 static final String BEGIN_ATTRIBUTE_ITEM = "BEGIN_ATTRIBUTE_ITEM";
92
93 static final String END_PREAMBLE = "END_PREAMBLE";
94 static final String END_RESTRICTION_ITEM = "END_RESTRICTION_ITEM";
95 static final String END_RESTRICTIONS = "END_RESTRICTIONS";
96 static final String END_ATTRIBUTE_ITEM = "END_ATTRIBUTE_ITEM";
97 static final String END_ATTRIBUTE_LIST = "END_ATTRIBUTE_LIST";
98 static final String END_FACT_ITEM = "END_FACT_ITEM";
99 static final String END_FACTS = "END_FACTS";
100 static final String END_ONTOLOGY = "END_ONTOLOGY";
101
102 static final String SYSTEM_NAME = "ZEUS-Ontology-Editor";
103
104 static final String SYSTEM = ":system";
105 static final String VERSION = ":version";
106 static final String NAME_TAG = ":name";
107 static final String PARENT_TAG = ":parent";
108 static final String TYPE_TAG = ":type";
109 static final String VALUE_TAG = ":value";
110 static final String REST_TAG = ":restriction";
111 static final String DEFA_TAG = ":default";
112 static final String QUOTE = "\"";
113
114 static final int NAME = 0;
115 static final int TYPE = 1;
116 static final int RESTRICTION = 2;
117 static final int DEFAULT = 3;
118
119 protected static final String FACT_STR = "Fact";
120 protected static final String NAME_STR = "name";
121 protected static final String CSEP = "$";
122 protected static final String TFILE = "oetf22";
123
124 public static final String STRING = "String";
125 public static final String INTEGER = "Integer";
126 public static final String REAL = "Real";
127 public static final String BOOLEAN = "Boolean";
128 public static final String DATE = "Date";
129 public static final String TIME = "Time";
130 public static final String LIST = "List";
131
132 public static final String OBJECT_TYPE = "JavaObject";
133
134 public static final String[] BASIC_TYPES = {
135 STRING, INTEGER, REAL, BOOLEAN, DATE, TIME, LIST
136 };
137
138 static final String[] PREDEFINED_FACTS = {
139 ROOT, MONEY, ABSTRACT, MESSAGE, ENTITY
140 };
141
142 public static final String[] GOAL_ATTRIBUTES = {
143 GOAL_FACT, "end_time", "cost", "confirm_time"
144 };
145
146
147 protected EventListenerList changeListeners = new EventListenerList();
148 protected Hashtable factIndex;
149 protected OrderedHashtable restrictions;
150 protected int editableLimit;
151
152 protected boolean save_needed = false;
153 protected String error = null;
154 protected String warning = null;
155 protected String filename = null;
156 protected String ontologyName = null;
157 protected GenSym genSym = null;
158
159 public OntologyDb () {
160 super (new FactDescription (ROOT));
161 }
162
163 public OntologyDb(GenSym genSym) {
164 super(new FactDescription(ROOT));
165
166 Assert.notNull(genSym);
167 this.genSym = genSym;
168
169 factIndex = new Hashtable();
170 restrictions = new OrderedHashtable();
171 clear();
172 }
173
174 public GenSym GenSym() { return genSym; }
175
176
177 /***
178 *return the actual user defined name of the ontology
179 */
180 public String getOntologyName () {
181 return ontologyName;
182 }
183
184
185
186 public void clear() {
187 factIndex.clear();
188 restrictions.clear();
189
190 root = new TreeNode(new FactDescription(ROOT));
191 factIndex.put(ROOT,root);
192
193 TreeNode node, leaf;
194 node = root.addChild(new FactDescription(ABSTRACT));
195 factIndex.put(ABSTRACT,node);
196
197 leaf = node.addChild(new FactDescription(MONEY));
198 factIndex.put(MONEY,leaf);
199 __addNewAttributeRow(MONEY, AMOUNT, REAL, "", "0");
200
201 leaf = node.addChild(new FactDescription(MESSAGE));
202 factIndex.put(MESSAGE,leaf);
203 for(int i = 0; i < Performative.ATTRIBUTE_TYPES.length; i++ )
204 __addNewAttributeRow(MESSAGE, Performative.ATTRIBUTE_TYPES[i], STRING, "", "");
205
206 node = root.addChild(new FactDescription(ENTITY));
207 factIndex.put(ENTITY,node);
208 __addNewAttributeRow(ENTITY, NUMBER, INTEGER, "", "1");
209 __addNewAttributeRow(ENTITY, COST, REAL, "", "0");
210
211 editableLimit = 0;
212
213 error = null;
214 warning = null;
215 filename = null;
216 fireChanged(RELOAD,null);
217 save_needed = false;
218 }
219
220
221
222 public boolean isSaveNeeded() { return save_needed; }
223 public String getError() { return error; }
224 public String getWarning() { return warning; }
225 public String getFilename() { return filename; }
226
227 public void __setWarning(String info) {
228 if ( warning == null )
229 warning = info;
230 else
231 warning += "\n" + info;
232 }
233
234 public int saveDAML(File file) {
235
236
237 return (0);
238 }
239
240
241
242 static final String HEADER = "<?xml version=\"1.0\">";
243 static final String ELEMENT_TAG = "!ELEMENT";
244 static final String ATTRIBUTE_TAG = "!ATTLIST";
245 static final String LT = "<";
246 static final String GT = ">";
247 static final String SPACE = " ";
248 static final String OPEN_BRACKET = "(";
249 static final String CLOSE_BRACKET = ")";
250 static final String COMMA = ",";
251 static final String PCDATA = "#PCDATA";
252 static final String CDATA = "CDATA";
253
254 public int saveXML(File file)
255 {
256 Assert.notNull(file);
257 int status = 0;
258 int num = 0;
259 error = null;
260 String dir, temp, fsep;
261 Enumeration enum;
262 FactDescription desc;
263 TreeNode node;
264 String name, output, default_info, restriction_info;
265 String[][] attributes;
266 Vector elementNodes;
267
268 try {
269 dir = file.getParent();
270 temp = (dir != null) ? dir + File.separator + TFILE : TFILE;
271 File f1 = new File(temp);
272
273 while( f1.exists() )
274 f1 = new File(temp + (num++));
275
276 String filename = file.getName();
277 int index = filename.indexOf('.');
278 String documentName = (index == -1) ? filename : filename.substring(0,index);
279
280 PrettyPrintWriter out = new PrettyPrintWriter(f1);
281 out.pprint(0,HEADER);
282 out.pprint(0,"<!DOCTYPE" + SPACE + documentName + SPACE + "[");
283
284 enum = this.nodes();
285 while( enum.hasMoreElements() ) {
286 node = (TreeNode)enum.nextElement();
287 desc = (FactDescription)node.getValue();
288 name = desc.getName();
289 if ( !Misc.member(name,PREDEFINED_FACTS) ) {
290 attributes = desc.getAttributes();
291
292
293 output = LT + ELEMENT_TAG + SPACE + name + SPACE + OPEN_BRACKET;
294
295 elementNodes = getElementNodes(desc);
296
297 if ( !elementNodes.isEmpty() ) {
298 for(int i = 0; i < elementNodes.size(); i++ ) {
299 output += elementNodes.elementAt(i);
300 if ( i < elementNodes.size() - 1 )
301 output += COMMA;
302 }
303 }
304 else {
305 output += PCDATA;
306 }
307 output += CLOSE_BRACKET + GT;
308 out.pprint(2,output);
309
310
311 if ( hasBasicAttributes(desc) ) {
312 out.pprint(2, LT + ATTRIBUTE_TAG + SPACE + name);
313 for(int i = 0; i < attributes.length; i++ ) {
314 if ( !elementNodes.contains(attributes[i][NAME]) ) {
315
316 restriction_info = default_info = "";
317 if (attributes[i][RESTRICTION] != null )
318 restriction_info = attributes[i][RESTRICTION].trim();
319
320 if (attributes[i][DEFAULT] != null )
321 default_info = attributes[i][DEFAULT].trim();
322
323 if ( restriction_info.indexOf('|') == -1 ||
324 restriction_info.indexOf('(') != -1 )
325 output = SPACE + CDATA;
326 else
327 output = SPACE + OPEN_BRACKET + restriction_info + CLOSE_BRACKET;
328
329 if ( default_info.length() > 0 )
330 output += SPACE + "\"" + default_info + "\"";
331
332 out.pprint(4, attributes[i][NAME] + output);
333 }
334 }
335 out.pprint(2,GT);
336 }
337 out.println();
338 }
339 }
340 out.pprint(0,"]>");
341
342 out.flush();
343 out.close();
344
345 if ( file.exists() ) file.delete();
346 f1.renameTo(file);
347 }
348 catch(Exception e) {
349 error = e.toString();
350 status |= ERROR_MASK;
351 }
352 return status;
353
354 }
355
356 protected Vector getElementNodes(FactDescription desc) {
357 String[][] attributes = desc.getAttributes();
358 Vector output = new Vector();
359 for(int i = 0; i < attributes.length; i++ ) {
360 if ( factIndex.containsKey(attributes[i][TYPE]) )
361 output.addElement(attributes[i][NAME]);
362 }
363 return output;
364 }
365
366 protected boolean hasBasicAttributes(FactDescription desc) {
367 String[][] attributes = desc.getAttributes();
368 Vector output = new Vector();
369 for(int i = 0; i < attributes.length; i++ ) {
370 if ( Misc.member(attributes[i][TYPE],BASIC_TYPES) )
371 return true;
372 }
373 return false;
374 }
375
376
377
378
379 public int saveFile(File file)
380 {
381 Assert.notNull(file);
382
383 String dir, temp, fsep;
384 int status = 0;
385 error = null;
386 warning = null;
387 int num = 0;
388
389 dir = file.getParent();
390 temp = (dir != null) ? dir + File.separator + TFILE : TFILE;
391 File f1 = new File(temp);
392
393 while( f1.exists() )
394 f1 = new File(temp + (num++));
395
396 try
397 {
398 String[][] attributes;
399 String[] entry;
400 String value;
401 Enumeration enum;
402 TreeNode node, parent;
403 FactDescription desc, parent_desc;
404 PrettyPrintWriter out = new PrettyPrintWriter(f1);
405
406 out.pprint(0,BEGIN_ONTOLOGY);
407 out.pprint(1,BEGIN_PREAMBLE);
408 out.pprint(2,SYSTEM + " " + SYSTEM_NAME);
409 out.pprint(2,VERSION + " \"" + SystemProps.getProperty("version.id") + "\"");
410 out.pprint(1,END_PREAMBLE);
411
412 enum = restrictions.elements();
413 if ( enum.hasMoreElements() )
414 {
415 out.pprint(1,BEGIN_RESTRICTIONS);
416 while( enum.hasMoreElements() )
417 {
418 out.pprint(2,BEGIN_RESTRICTION_ITEM);
419 entry = (String[])enum.nextElement();
420 value = (entry[2] != null) ? entry[2] : "";
421 out.pprint(3,NAME_TAG + " " + entry[0]);
422 out.pprint(3,TYPE_TAG + " " + entry[1]);
423 out.pprint(3,VALUE_TAG + " " + QUOTE + value + QUOTE);
424 out.pprint(2,END_RESTRICTION_ITEM);
425 }
426 out.pprint(1,END_RESTRICTIONS);
427 }
428
429 enum = this.nodes();
430 if ( enum.hasMoreElements() )
431 {
432 out.pprint(1,BEGIN_FACTS);
433 while( enum.hasMoreElements() )
434 {
435 node = (TreeNode)enum.nextElement();
436 desc = (FactDescription)node.getValue();
437
438 if ( !Misc.member(desc.getName(),PREDEFINED_FACTS) )
439 {
440 out.pprint(2,BEGIN_FACT_ITEM);
441 out.pprint(3,NAME_TAG + " " + desc.getName());
442 parent = node.getParent();
443 parent_desc = (FactDescription)parent.getValue();
444 out.pprint(3,PARENT_TAG + " " + parent_desc.getName());
445
446 attributes = desc.getAttributes();
447 if ( attributes.length > 0 )
448 {
449 out.pprint(3,BEGIN_ATTRIBUTE_LIST);
450 for(int i = 0; i < attributes.length; i++ )
451 {
452 for(int j = 0; j < attributes[i].length; j++ )
453 if ( attributes[i][j] == null ) attributes[i][j] = "";
454
455 attributes[i][RESTRICTION] = QUOTE + attributes[i][RESTRICTION] + QUOTE;
456 attributes[i][DEFAULT] = QUOTE + attributes[i][DEFAULT] + QUOTE;
457
458 out.pprint(4,BEGIN_ATTRIBUTE_ITEM);
459 out.pprint(5,NAME_TAG + " " + attributes[i][NAME]);
460 out.pprint(5,TYPE_TAG + " " + attributes[i][TYPE]);
461 out.pprint(5,REST_TAG + " " + attributes[i][RESTRICTION]);
462 out.pprint(5,DEFA_TAG + " " + attributes[i][DEFAULT]);
463 out.pprint(4,END_ATTRIBUTE_ITEM);
464 }
465 out.pprint(3,END_ATTRIBUTE_LIST);
466 }
467 out.pprint(2,END_FACT_ITEM);
468 }
469 }
470 out.pprint(1,END_FACTS);
471 }
472
473 out.pprint(0,END_ONTOLOGY);
474 out.flush();
475 out.close();
476
477 if ( file.exists() ) file.delete();
478 f1.renameTo(file);
479 save_needed = false;
480 }
481 catch(Exception e) {
482 error = e.toString();
483 status |= ERROR_MASK;
484 }
485 setFilename(file);
486 return status;
487 }
488
489 public int openFile(File file) {
490
491 Assert.notNull(file);
492 int status = 0;
493 clear();
494
495 try {
496 OntologyParser parser = new OntologyParser(new FileInputStream(file));
497 parser.parse(this);
498 }
499 catch(TokenMgrError t) {
500
501
502 clear();
503 error = t.toString();
504 status |= ERROR_MASK;
505 }
506 catch(Exception e) {
507 clear();
508 error = e.toString();
509 status |= ERROR_MASK;
510 }
511 if ( warning != null ) status |= WARNING_MASK;
512 setFilename(file);
513 fireChanged(RELOAD,file.getName());
514 save_needed = false;
515 return status;
516 }
517
518 private void setFilename(File file) {
519 try {
520 ontologyName = file.getName();
521 filename = file.getCanonicalPath();
522 }
523 catch(IOException e) {
524 ontologyName = file.getName();
525 filename = file.getAbsolutePath();
526 }
527 }
528
529
530 public boolean isAncestorOf(String name, String parent) {
531 FactDescription fd;
532 TreeNode node = (TreeNode)factIndex.get(name);
533 while( node != null ) {
534 fd = (FactDescription)node.getValue();
535 if ( fd.getName().equals(parent) ) return true;
536 node = node.getParent();
537 }
538 return false;
539 }
540
541
542 /***
543 * get a list of the ancestors of a type
544 *@since 1.2.2
545 *@author Simon Thompson
546 */
547 public Iterator allAncestors (String name) {
548 ArrayList list = new ArrayList ();
549 FactDescription fd;
550 TreeNode node = (TreeNode)factIndex.get(name);
551 while( node != null ) {
552 fd = (FactDescription)node.getValue();
553 list.add(fd.getName());
554 node = node.getParent();
555 }
556 return list.iterator();
557 }
558
559
560 public TreeNode addChildFact(TreeNode parent) {
561 String name = genSym.plainId(FACT_STR);
562 while( factIndex.containsKey(name) )
563 name = genSym.plainId(FACT_STR);
564 TreeNode node = parent.addChild(new FactDescription(name));
565 factIndex.put(name, node);
566 fireChanged(FACT_ADDED,name);
567 return node;
568 }
569
570 /***
571 * New method added by Jaron to allow named facts to be added through an
572 * API call rather than the FactTable GUI
573 */
574 public boolean addNamedChildFact(TreeNode parent, String name)
575 {
576 if (factIndex.containsKey(name))
577 return false;
578 TreeNode node = parent.addChild(new FactDescription(name));
579 factIndex.put(name, node);
580 fireChanged(OntologyDb.RELOAD, name);
581 return true;
582 }
583
584 public void __addChildFact(String parent, String name) {
585 TreeNode parentNode = (TreeNode)factIndex.get(parent);
586 TreeNode node = parentNode.addChild(new FactDescription(name));
587 factIndex.put(name, node);
588 }
589
590 public Object renameFact(String previous, String current) {
591 if ( factIndex.containsKey(current) ) return null;
592 if ( Misc.member(previous,PREDEFINED_FACTS) ) return null;
593
594 TreeNode node = (TreeNode)factIndex.remove(previous);
595 Assert.notNull(node);
596 FactDescription desc = (FactDescription)node.getValue();
597 desc.setName(current);
598 factIndex.put(current,node);
599 fireChanged(FACT_RENAMED,current);
600
601 return node;
602 }
603
604 public boolean isFactEditable(String name) {
605 return !Misc.member(name,PREDEFINED_FACTS);
606 }
607
608 public void removeFact(TreeNode node) {
609
610 TreeNode parent = node.getParent();
611 parent.removeChild(node);
612
613
614 FactDescription desc;
615 Enumeration enum = node.values();
616 while(enum.hasMoreElements()) {
617 desc = (FactDescription)enum.nextElement();
618 factIndex.remove(desc.getName());
619 }
620 desc = (FactDescription)node.getValue();
621 fireChanged(FACT_REMOVED,desc.getName());
622 }
623
624 public TreeNode copyFactTree(TreeNode node) {
625 FactDescription desc1 = (FactDescription)node.getValue();
626 FactDescription desc2 = new FactDescription(desc1);
627 TreeNode top_node = new TreeNode(desc2);
628 copyFactTree1(top_node,node);
629 return top_node;
630 }
631
632 protected void copyFactTree1(TreeNode top_node, TreeNode node) {
633 FactDescription desc1, desc2;
634 Vector children = node.getChildren();
635 TreeNode lhs_node, rhs_node;
636 for(int i = 0; i < children.size(); i++ ) {
637 rhs_node = (TreeNode)children.elementAt(i);
638 desc1 = (FactDescription)rhs_node.getValue();
639 desc2 = new FactDescription(desc1);
640 lhs_node = new TreeNode(desc2);
641 top_node.addChild(lhs_node);
642 copyFactTree1(lhs_node,rhs_node);
643 }
644 }
645
646 public TreeNode pasteFactTree(TreeNode parent, TreeNode node) {
647 TreeNode copy = copyFactTree(node);
648 TreeNode a_node;
649 FactDescription desc;
650 String name;
651 Enumeration enum = copy.nodes();
652 while(enum.hasMoreElements()) {
653 a_node = (TreeNode)enum.nextElement();
654 desc = (FactDescription)a_node.getValue();
655 name = desc.getName();
656 while( factIndex.containsKey(name) )
657 name = genSym.plainId(desc.getName() + CSEP);
658 desc.setName(name);
659 factIndex.put(name,a_node);
660 }
661 parent.addChild(copy);
662 desc = (FactDescription)copy.getValue();
663 fireChanged(FACT_ADDED,desc.getName());
664 return copy;
665 }
666
667 public boolean hasFact(String fact) { return factIndex.containsKey(fact); }
668
669
670 /***
671 * This method is used to create a new Fact from its ontology description
672 */
673 public Fact getFact(boolean is_variable, String type) {
674 if ( !factIndex.containsKey(type) ) {
675 Core.USER_ERROR("Fact type: " + type +
676 " does not exist in current ontology");
677 return null;
678 }
679 ValueFunction fn;
680 Fact f1 = new Fact(is_variable,type,this,genSym);
681 AttributeList attrList = new AttributeList();
682 String[][] entry = getNetAttributeEntriesFor(type);
683 String value;
684 for(int i = 0; i < entry.length; i++ ) {
685 value = entry[i][1];
686 if ( is_variable || value == null || value.equals("") )
687 value = Fact.newVar(genSym);
688 fn = ZeusParser.Expression(this,value);
689 attrList.put(entry[i][0],fn);
690 }
691 f1.setAttributeList(attrList);
692 return f1;
693 }
694
695
696
697 public String[][] getAttributeEntriesFor(String fact) {
698 if ( fact == null || fact.equals("") ) return new String[0][4];
699
700 TreeNode node = (TreeNode)factIndex.get(fact);
701 FactDescription desc = (FactDescription)node.getValue();
702 String[][] result = desc.getAttributes();
703
704 editableLimit = Misc.member(fact,PREDEFINED_FACTS)
705 ? result.length : 0;
706
707 return result;
708 }
709 public String[][] getAllAttributeEntriesFor(String fact) {
710 if ( fact == null || fact.equals("") ) return new String[0][4];
711
712
713
714
715 FactDescription desc;
716 Vector temp = new Vector();
717 int sum = 0;
718 String[][] attributes;
719 TreeNode node = (TreeNode)factIndex.get(fact);
720 while( node != null ) {
721 desc = (FactDescription)node.getValue();
722 attributes = desc.getAttributes();
723 sum += attributes.length;
724 temp.addElement(attributes);
725 node = node.getParent();
726 }
727
728 String[][] result = new String[sum][4];
729 int k = 0;
730 for(int i = temp.size() - 1; i >= 0; i-- ) {
731 attributes = (String[][])temp.elementAt(i);
732 for(int j = 0; j < attributes.length; j++ )
733 result[k++] = attributes[j];
734 }
735
736 if ( Misc.member(fact,PREDEFINED_FACTS) )
737 editableLimit = result.length;
738 else
739 editableLimit = result.length -
740 ((String[][])temp.elementAt(0)).length;
741
742 return result;
743 }
744 public int getEditableLimit() {
745 return editableLimit;
746 }
747
748 String[][] getNetAttributeEntriesFor(String fact) {
749 if ( fact == null || fact.equals("") ) return new String[0][2];
750
751
752 FactDescription desc;
753 Hashtable temp = new Hashtable();
754 TreeNode node = (TreeNode)factIndex.get(fact);
755 String[][] attributes;
756 String default_value;
757 while( node != null ) {
758 desc = (FactDescription)node.getValue();
759 attributes = desc.getAttributes();
760 for(int j = 0; j < attributes.length; j++ ) {
761 if ( attributes[j][DEFAULT] == null )
762 attributes[j][DEFAULT] = "";
763 default_value = (String)temp.get(attributes[j][NAME]);
764 if ( default_value == null || default_value.equals("") )
765 default_value = attributes[j][DEFAULT];
766 temp.put(attributes[j][NAME],default_value);
767 }
768 node = node.getParent();
769 }
770
771 String[][] result = new String[temp.size()][2];
772 Enumeration enum = temp.keys();
773 for(int i = 0; enum.hasMoreElements(); i++ ) {
774 result[i][0] = (String)enum.nextElement();
775 result[i][1] = (String)temp.get(result[i][0]);
776 }
777 return result;
778 }
779
780 String[] getNetAttributesOnlyFor(String fact) {
781 if ( fact == null || fact.equals("") ) return new String[0];
782
783
784 FactDescription desc;
785 HSet temp = new HSet();
786 TreeNode node = (TreeNode)factIndex.get(fact);
787 String[][] attributes;
788 while( node != null ) {
789 desc = (FactDescription)node.getValue();
790 attributes = desc.getAttributes();
791 for(int j = 0; j < attributes.length; j++ )
792 temp.add(attributes[j][NAME]);
793 node = node.getParent();
794 }
795
796 String[] result = new String[temp.size()];
797 Enumeration enum = temp.elements();
798 for(int i = 0; enum.hasMoreElements(); i++ )
799 result[i] = (String)enum.nextElement();
800 return result;
801 }
802
803 public String setAttribute(String fact, String attribute,
804 int column, String value) {
805 TreeNode node = (TreeNode)factIndex.get(fact);
806 FactDescription desc = (FactDescription)node.getValue();
807 String[] entry = desc.removeAttributeEntry(attribute);
808 switch(column) {
809 case NAME:
810 String value1 = value;
811 while( desc.containsAttribute(value1) )
812 value1 = genSym.plainId(value + CSEP);
813 entry[NAME] = value1;
814 desc.setAttributeEntry(entry);
815 break;
816
817 case TYPE:
818 case RESTRICTION:
819 case DEFAULT:
820 entry[column] = value;
821 desc.setAttributeEntry(entry);
822 break;
823
824 default:
825 Core.FAIL("Unknown type in OntologyDb.setAttribute()");
826 }
827 fireChanged(ATTRIBUTES_CHANGED,fact);
828 return value;
829 }
830
831 public void addNewAttributeRow(String fact)
832 {
833 TreeNode node = (TreeNode)factIndex.get(fact);
834 FactDescription desc = (FactDescription)node.getValue();
835
836 String name = genSym.plainId(NAME_STR);
837 while( desc.containsAttribute(name) )
838 name = genSym.plainId(NAME_STR);
839
840 String[] entry = { name, STRING, "", "" };
841 desc.setAttributeEntry(entry);
842 fireChanged(ATTRIBUTES_CHANGED,fact);
843 }
844
845 public void addNewAttribute(String fact, String name, String type)
846 {
847 TreeNode node = (TreeNode)factIndex.get(fact);
848 FactDescription desc = (FactDescription)node.getValue();
849 String[] entry = { name, type, "", "" };
850 desc.setAttributeEntry(entry);
851 }
852
853
854 public void __addNewAttributeRow(String fact, String name, String type,
855 String restriction, String default_value) {
856 TreeNode node = (TreeNode)factIndex.get(fact);
857 FactDescription desc = (FactDescription)node.getValue();
858 String[] entry = { name, type, restriction, default_value };
859 desc.setAttributeEntry(entry);
860 }
861
862 public void deleteAttributes(String fact, String[] attributes) {
863 TreeNode node = (TreeNode)factIndex.get(fact);
864 FactDescription desc = (FactDescription)node.getValue();
865 for(int i = 0; i < attributes.length; i++ )
866 desc.removeAttributeEntry((String)attributes[i]);
867 fireChanged(ATTRIBUTES_CHANGED,fact);
868 }
869
870 public void addAttributeRows(String fact, String[][] input) {
871 TreeNode node = (TreeNode)factIndex.get(fact);
872 FactDescription desc = (FactDescription)node.getValue();
873 for(int i = 0; i < input.length; i++) {
874 String name = input[i][NAME];
875 while( desc.containsAttribute(name) )
876 name = genSym.plainId(input[i][NAME] + CSEP);
877 input[i][NAME] = name;
878 desc.setAttributeEntry(input[i]);
879 }
880 fireChanged(ATTRIBUTES_CHANGED,fact);
881 }
882
883 public TreeNode createAttributeTree(String fact, String name) {
884 Core.ERROR(factIndex.containsKey(fact),1,this);
885 TreeNode node = new TreeNode(name);
886 createAttributeTreeNodes(fact,node);
887 return node;
888 }
889
890 protected void createAttributeTreeNodes(String fact, TreeNode base) {
891
892 FactDescription desc;
893 Vector temp = new Vector();
894 TreeNode node = (TreeNode)factIndex.get(fact);
895 String[][] attributes;
896 while( node != null ) {
897 desc = (FactDescription)node.getValue();
898 attributes = desc.getAttributes();
899 temp.addElement(attributes);
900 node = node.getParent();
901 }
902
903
904 OrderedHashtable temp2 = new OrderedHashtable();
905 for(int i = 0; i < temp.size(); i++ ) {
906 attributes = (String[][])temp.elementAt(i);
907 for(int j = 0; j < attributes.length; j++ )
908 temp2.put(attributes[j][NAME],attributes[j][TYPE]);
909 }
910
911 String name, type;
912 TreeNode child;
913 Enumeration enum = temp2.keys();
914 for(int i = 0; enum.hasMoreElements(); i++ ) {
915 name = (String)enum.nextElement();
916 child = base.addChild(name);
917
918 type = (String)temp2.get(name);
919 if ( factIndex.containsKey(type) )
920 createAttributeTreeNodes(type,child);
921 }
922 }
923
924
925
926 public String[][] getAllRestrictions() {
927 String[][] data = new String[restrictions.size()][3];
928 Enumeration elements = restrictions.elements();
929 for(int i = 0; i < data.length; i++ )
930 data[i] = (String[])elements.nextElement();
931 return data;
932 }
933 public String[] getAllRestrictionNames() {
934 String[] data = new String[restrictions.size()];
935 String[] temp;
936 Enumeration elements = restrictions.elements();
937 for(int i = 0; i < data.length; i++ ) {
938 temp = (String[])elements.nextElement();
939 data[i] = temp[NAME];
940 }
941 return data;
942 }
943 public String setRestrictionData(String name, int column, Object aValue) {
944 String[] entry = null;
945 String value = (String)aValue;
946 switch(column) {
947 case NAME:
948 while( restrictions.containsKey(value) )
949 value = genSym.plainId((String)aValue + CSEP);
950 entry = (String[])restrictions.get(name);
951 String previousKey = entry[NAME];
952 entry[column] = value;
953 restrictions.reKey(previousKey,entry[NAME],entry);
954
955 break;
956
957 case TYPE:
958 case RESTRICTION:
959 entry = (String[])restrictions.get(name);
960 entry[column] = value;
961 break;
962 }
963 fireChanged(RESTRICTION_CHANGED,entry[NAME]);
964 return entry[column];
965 }
966 public void addNewRestriction() {
967 String name = genSym.plainId(NAME_STR);
968 while( restrictions.containsKey(name) )
969 name = genSym.plainId(NAME_STR);
970 String[] entry = { name, STRING, "" };
971 restrictions.put(entry[NAME],entry);
972 fireChanged(RESTRICTION_ADDED,name);
973 }
974 public void deleteRestrictions(String[] names) {
975 for(int i = 0; i < names.length; i++ ) {
976 restrictions.remove(names[i]);
977 fireChanged(RESTRICTION_REMOVED,names);
978 }
979 }
980 public void addRestrictions(String[][] input) {
981 for(int i = 0; i < input.length; i++) {
982 String name = input[i][NAME];
983 while( restrictions.containsKey(name) )
984 name = genSym.plainId(input[i][NAME] + CSEP);
985 input[i][NAME] = name;
986 restrictions.put(input[i][NAME],input[i]);
987 fireChanged(RESTRICTION_ADDED,input[i][NAME]);
988 }
989 }
990 public void __addRestriction(String name, String type, String value) {
991 String[] input = { name, type, value };
992 restrictions.put(input[NAME],input);
993 }
994
995
996
997 public boolean[] validateFact(Fact f1) {
998 String[] attributes = f1.listAttributes();
999 ValueFunction[] values = f1.listValues();
1000 boolean[] result = new boolean[values.length];
1001
1002 for(int i = 0; i < result.length; i++ )
1003 result[i] = validate(f1.getType(),attributes[i],values[i]);
1004 return result;
1005 }
1006
1007 boolean validate(String fact, String attribute, ValueFunction value) {
1008
1009 TreeNode node = (TreeNode)factIndex.get(fact);
1010 if ( node == null ) {
1011
1012 return false;
1013 }
1014
1015 FactDescription desc = (FactDescription)node.getValue();
1016 while( !desc.containsAttribute(attribute) && node != null &&
1017 (node = node.getParent()) != null ) {
1018 desc = (FactDescription)node.getValue();
1019 }
1020
1021 if ( node == null ) {
1022
1023 return false;
1024 }
1025
1026 String[] entry = desc.getAttributeEntry(attribute);
1027 String type = entry[TYPE];
1028 String b_type = getBasicType(type);
1029 ValueFunction v0 = null;
1030
1031 String restriction = entry[RESTRICTION];
1032 if ( Misc.member(b_type,BASIC_TYPES) ) {
1033 v0 = checkRestrictionEntry(b_type,restriction);
1034 if ( v0 != null && !Misc.member(type,BASIC_TYPES) )
1035 v0 = checkRestriction(v0,type);
1036
1037 if ( v0 == null ) {
1038
1039 return false;
1040 }
1041 }
1042 else {
1043 if ( !restriction.equals("") ) {
1044
1045 return false;
1046 }
1047 v0 = new VarFn(Fact.newVar(genSym));
1048
1049 }
1050
1051 value = value.unifiesWith(v0,new Bindings());
1052
1053
1054
1055 return (value != null);
1056 }
1057
1058 public boolean[][] getAllRestrictionValidityInfo() {
1059 boolean[][] output = new boolean[restrictions.size()][3];
1060 String name;
1061 Enumeration keys = restrictions.keys();
1062 for(int i = 0; i < output.length; i++ ) {
1063 name = (String)keys.nextElement();
1064 output[i] = isRestrictionValid(name);
1065 }
1066 return output;
1067 }
1068 public boolean[] isRestrictionValid(String name) {
1069 boolean[] output = new boolean[3];
1070 for(int i = 0; i < output.length; i++ )
1071 output[i] = true;
1072
1073 if ( !restrictions.containsKey(name) )
1074 return output;
1075
1076 output[RESTRICTION] = checkRestriction(null,name) != null;
1077 return output;
1078 }
1079
1080 protected ValueFunction checkRestriction(ValueFunction child, String name) {
1081 String[] entry = (String[])restrictions.get(name);
1082 String basic_type = getRestrictionBasicType(name);
1083 ValueFunction v0 = checkRestrictionEntry(basic_type,entry[RESTRICTION]);
1084
1085 if ( v0 != null && child != null )
1086 v0 = v0.unifiesWith(child,new Bindings());
1087
1088 if ( basic_type.equals(entry[TYPE]) || (v0 == null) )
1089 return v0;
1090
1091 return checkRestriction(v0,entry[TYPE]);
1092 }
1093
1094 protected ValueFunction checkDefaultValue(String type, String value) {
1095 value = value.trim();
1096 if ( value.equals("") )
1097 return new VarFn(Fact.newVar(genSym));
1098
1099 try {
1100 RestrictionParser parser;
1101 parser = new RestrictionParser(
1102 new ByteArrayInputStream(value.getBytes())
1103 );
1104
1105 switch( Misc.whichPosition(type,BASIC_TYPES) ) {
1106 case 0:
1107 return parser.StringLiteral();
1108 case 1:
1109 return parser.IntegerExpression();
1110 case 2:
1111 return parser.RealExpression();
1112 case 3:
1113 return parser.BooleanLiteral();
1114 case 4:
1115 return parser.DateLiteral();
1116 case 5:
1117 return parser.TimeLiteral();
1118 case 6:
1119 return parser.VectorLiteral();
1120 default:
1121 return null;
1122 }
1123 }
1124 catch(Exception e) {
1125 return null;
1126 }
1127 }
1128 protected ValueFunction checkRestrictionEntry(String type, String value) {
1129 value = value.trim();
1130 if ( value.equals("") )
1131 return new VarFn(Fact.newVar(genSym));
1132
1133 try {
1134 RestrictionParser parser;
1135 parser = new RestrictionParser(
1136 new ByteArrayInputStream(value.getBytes())
1137 );
1138
1139 switch( Misc.whichPosition(type,BASIC_TYPES) ) {
1140 case 0:
1141 return parser.StringExpression();
1142 case 1:
1143 return parser.IntegerExpression();
1144 case 2:
1145 return parser.RealExpression();
1146 case 3:
1147 return parser.BooleanLiteral();
1148 case 4:
1149 return parser.DateExpression();
1150 case 5:
1151 return parser.TimeExpression();
1152 case 6:
1153 return parser.VectorLiteral();
1154 default:
1155 return null;
1156 }
1157 }
1158 catch(Exception e) {
1159 return null;
1160 }
1161 }
1162
1163 protected String getRestrictionBasicType(String restriction) {
1164 String[] entry = (String[])restrictions.get(restriction);
1165 String type = entry[TYPE];
1166 if ( Misc.member(type,BASIC_TYPES) )
1167 return type;
1168 else
1169 return getRestrictionBasicType(type);
1170 }
1171
1172 protected String getBasicType(String type) {
1173 if ( Misc.member(type,BASIC_TYPES) )
1174 return type;
1175 else if ( type.equals(OBJECT_TYPE) )
1176 return type;
1177 else if ( restrictions.containsKey(type) )
1178 return getRestrictionBasicType(type);
1179 else
1180 return type;
1181 }
1182
1183 public boolean[] isAttributeValid(String fact, String name) {
1184 boolean output[] = new boolean[4];
1185 for(int i = 0; i < output.length; i++ )
1186 output[i] = true;
1187
1188 if ( fact == null || fact.equals("") ) return output;
1189
1190
1191 TreeNode node = (TreeNode)factIndex.get(fact);
1192 FactDescription desc = (FactDescription)node.getValue();
1193 String[] entry = desc.getAttributeEntry(name);
1194 String type = entry[TYPE];
1195 String inherited_type = getInheritedTypeFor(fact,name);
1196
1197 String b_type = getBasicType(type);
1198 String b_inherited_type = getBasicType(inherited_type);
1199
1200 ValueFunction v0 = null;
1201 ValueFunction v1 = null;
1202
1203
1204 if ( !b_type.equals(b_inherited_type) && !hasFact(b_type) &&
1205 !isAncestorOf(type,b_inherited_type) )
1206 output[TYPE] = false;
1207
1208 String restriction = entry[RESTRICTION];
1209 if ( Misc.member(b_type,BASIC_TYPES) ) {
1210 v0 = checkRestrictionEntry(b_type,restriction);
1211 if ( v0 != null && !Misc.member(type,BASIC_TYPES) )
1212 v0 = checkRestriction(v0,type);
1213 output[RESTRICTION] = (v0 != null);
1214 }
1215 else {
1216 output[RESTRICTION] = restriction.equals("");
1217 }
1218
1219 String value = entry[DEFAULT];
1220 if ( Misc.member(b_type,BASIC_TYPES) ) {
1221 v1 = checkDefaultValue(b_type,value);
1222 if ( v1 != null && v0 != null )
1223 v1 = v1.unifiesWith(v0,new Bindings());
1224 output[DEFAULT] = (v1 != null);
1225 }
1226 else {
1227 output[DEFAULT] = value.equals("");
1228 }
1229
1230 return output;
1231 }
1232
1233 protected String getInheritedTypeFor(String fact, String name)
1234 {
1235 FactDescription desc;
1236 String type = null;
1237 String[] entry;
1238 TreeNode node = (TreeNode)factIndex.get(fact);
1239 while( node != null )
1240 {
1241 desc = (FactDescription)node.getValue();
1242 if ( !desc.containsAttribute(name) )
1243 return type;
1244 entry = desc.getAttributeEntry(name);
1245 type = entry[TYPE];
1246 node = node.getParent();
1247 }
1248 return type;
1249 }
1250
1251 public boolean[][] getValidityInfoFor(String fact) {
1252 if ( fact == null || fact.equals("") ) return new boolean[0][4];
1253
1254 TreeNode node = (TreeNode)factIndex.get(fact);
1255 FactDescription desc = (FactDescription)node.getValue();
1256 String[][] data = desc.getAttributes();
1257 boolean[][] output = new boolean[data.length][];
1258 for(int i = 0; i < output.length; i++ )
1259 output[i] = isAttributeValid(fact,data[i][NAME]);
1260 return output;
1261 }
1262
1263 public boolean[][] getAllValidityInfoFor(String fact) {
1264 if ( fact == null || fact.equals("") ) return new boolean[0][4];
1265
1266
1267
1268
1269 FactDescription desc;
1270 Vector temp = new Vector();
1271 int sum = 0;
1272 boolean[][] attributes;
1273 String name;
1274 TreeNode node = (TreeNode)factIndex.get(fact);
1275 while( node != null ) {
1276 desc = (FactDescription)node.getValue();
1277 name = desc.getName();
1278 attributes = getValidityInfoFor(name);
1279 sum += attributes.length;
1280 temp.addElement(attributes);
1281 node = node.getParent();
1282 }
1283
1284 boolean[][] result = new boolean[sum][4];
1285 int k = 0;
1286 for(int i = temp.size() - 1; i >= 0; i-- ) {
1287 attributes = (boolean[][])temp.elementAt(i);
1288 for(int j = 0; j < attributes.length; j++ )
1289 result[k++] = attributes[j];
1290 }
1291 return result;
1292 }
1293
1294
1295
1296 public void addChangeListener(ChangeListener x) {
1297 changeListeners.add(ChangeListener.class, x);
1298 }
1299
1300 public void removeChangeListener(ChangeListener x) {
1301 changeListeners.remove(ChangeListener.class, x);
1302 }
1303
1304
1305
1306 protected void fireChanged(int type, Object data) {
1307 save_needed = true;
1308 OntologyDbChangeEvent c = new OntologyDbChangeEvent(this,type,data);
1309 Object[] listeners = changeListeners.getListenerList();
1310 for (int i= listeners.length-2; i >= 0; i -=2) {
1311 if (listeners[i] == ChangeListener.class) {
1312 ChangeListener cl = (ChangeListener)listeners[i+1];
1313 cl.stateChanged(c);
1314 }
1315 }
1316 }
1317
1318 public static void main(String[] arg) {
1319 String file = null;
1320
1321 OntologyDb z = new OntologyDb(new GenSym("sym"));
1322
1323 String dir = System.getProperty("user.dir") +
1324 System.getProperty("file.separator");
1325 z.openFile(new File(dir + arg[0]));
1326 }
1327
1328 public Hashtable getFactIndex() {
1329 return factIndex;
1330 }
1331
1332 }