1   package com.ontotext.gate.vr;
2   
3   import java.util.*;
4   
5   
6   import com.ontotext.gate.ontology.TaxonomyImpl;
7   import com.ontotext.gate.vr.*;
8   import gate.creole.ontology.*;
9   
10  import gate.util.*;
11  import gate.creole.gazetteer.*;
12  
13  import java.awt.datatransfer.*;
14  import java.io.*;
15  import java.net.URL;
16  
17  import javax.swing.tree.*;
18  
19  
20  /** Represents a single class node from the visualized ontology */
21  public class ClassNode
22      implements IFolder,Transferable,Cloneable, Serializable
23  {
24  
25    /** flavor used for drag and drop */
26    final public static DataFlavor CLASS_NODE_FLAVOR =
27      new DataFlavor(ClassNode.class, "Class Node");
28  
29    static DataFlavor flavors[] = {CLASS_NODE_FLAVOR};
30  
31    private String name;
32    private Vector children = new Vector();
33    private Object source;
34  
35    /** create a structure representing the class hierarchy of an ontology
36     *  @param includeInstances if true, then instances of the ontology
37     *  are also included
38     *  @return the root node of the structure
39     */
40    public static ClassNode createRootNode(Taxonomy o) {
41      return createRootNode(o, false);
42    }
43  
44    public static ClassNode createRootNode(Taxonomy o, boolean includeInstances) {
45      if (null == o)
46        throw new gate.util.LazyProgrammerException("ontology is null.");
47  
48      ClassNode root = new ClassNode(o);
49      Iterator itops = o.getTopClasses().iterator();
50      Vector kids = new Vector();
51      while (itops.hasNext()) {
52        ClassNode node = new ClassNode((TClass)itops.next());
53        kids.add(node);
54      } // while
55  
56      root.source = o;
57      root.setChildren(kids);
58      Vector parents = kids;
59      Vector allKids;
60      do {
61        allKids = new Vector();
62        for ( int i= 0 ; i < parents.size() ; i++ ) {
63          ClassNode parent = (ClassNode)parents.get(i);
64          kids = new Vector();
65  
66          //skip this one if it's an instance
67          if(parent.getSource() instanceof OInstance)
68            continue;
69  
70          TClass ocl = (TClass) parent.getSource();
71  
72          //if we include instances, then get them too
73          if (includeInstances && (o instanceof Ontology)) {
74            Ontology kb = (Ontology) o;
75            Set instances = kb.getDirectInstances((OClass)ocl);
76            if (instances != null && !instances.isEmpty()) {
77              Iterator insti = instances.iterator();
78              while (insti.hasNext())
79                kids.add(new ClassNode( (OInstance) insti.next()));
80            }
81          }
82  
83          if (0 == ocl.getSubClasses(TClass.DIRECT_CLOSURE).size()) {
84            if (! kids.isEmpty())
85              //add the instances as children, but do not add them for future
86              //traversal to allKids
87              parent.setChildren(kids);
88            continue;
89          }  // if 0 children
90  
91          Iterator kidsi = ocl.getSubClasses(TClass.DIRECT_CLOSURE).iterator();
92  
93          while ( kidsi.hasNext()) {
94            kids.add(new ClassNode((TClass)kidsi.next()));
95          } // while kidsi
96          parent.setChildren(kids);
97          allKids.addAll(kids);
98  
99        }   // for i
100       parents = allKids;
101     } while (0 < allKids.size());
102 
103     return root;
104   }//createRootNode()
105 
106   /** Creates a structure representing the class hierarchy of an ontology
107    *  and the gazetteerLists mapped to it.
108    *  @param o an ontology
109    *  @param mapping mapping definition
110    *  @param nameVsNode : this is actually a return value: should be
111    *  initialized before passing to this method and afterwards one can find a mapping
112    *  of class names vs class nodes there.
113    *  @return the root node of the structure
114    */
115   public static ClassNode createRootNode(Taxonomy o, MappingDefinition mapping, Map nameVsNode) {
116     if (null == o || null == nameVsNode || null == mapping)
117       throw new gate.util.LazyProgrammerException("mapping, nameVsNode or ontology-o is null.");
118     ClassNode root = new ClassNode(o);
119     Iterator itops = o.getTopClasses().iterator();
120     Vector kids = new Vector();
121     while (itops.hasNext()) {
122       ClassNode node = new ClassNode((TClass)itops.next());
123       nameVsNode.put(node.toString(),node);
124       kids.add(node);
125     } // while
126 
127     root.source = o;
128     root.setChildren(kids);
129     Vector parents = kids;
130     Vector allKids;
131     do {
132       allKids = new Vector();
133       for ( int i= 0 ; i < parents.size() ; i++ ) {
134         ClassNode parent = (ClassNode)parents.get(i);
135 
136         TClass ocl = (TClass) parent.getSource();
137         if (0 == ocl.getSubClasses(TClass.DIRECT_CLOSURE).size()) {
138           continue;
139         }  // if 0 children
140 
141         Iterator kidsi = ocl.getSubClasses(TClass.DIRECT_CLOSURE).iterator();
142 
143         kids = new Vector();
144         while ( kidsi.hasNext()) {
145           ClassNode cn = new ClassNode((TClass)kidsi.next());
146           kids.add(cn);
147           nameVsNode.put(cn.toString(),cn);
148         } // while kidsi
149         parent.setChildren(kids);
150         allKids.addAll(kids);
151 
152       }   // for i
153       parents = allKids;
154     } while (0 < allKids.size());
155 
156     // display mapping
157     Iterator inodes = mapping.iterator();
158     MappingNode mn;
159     while (inodes.hasNext()) {
160       mn = (MappingNode)inodes.next();
161       URL turl = null;
162       try { turl = new URL(mn.getOntologyID());
163       } catch (java.net.MalformedURLException x) {
164       }
165       if ( null != turl ){
166         Taxonomy o2 = null;
167         try { o2 = TaxonomyImpl.getOntology(turl);
168         } catch (gate.creole.ResourceInstantiationException x) {
169         }
170         if ( o2 != null && o2.equals(o) ) {
171           ClassNode cmn = new ClassNode(mn);
172           ClassNode cn = (ClassNode)nameVsNode.get(mn.getClassID());
173           if (null!= cn) {
174             cn.children.add(cn.children.size(),cmn);
175           }
176         }// if from the same ontology
177       } // turl != null
178     }// while inodes
179 
180 
181     return root;
182   }//createRootNode()
183 
184   /**Constructs a root class node from an ontology
185    * @param o the ontology    */
186   public ClassNode(Taxonomy o) {
187     name = o.getName();
188   }
189 
190   /**Constructs a class node given an ontology class
191    * @param clas ontology class   */
192   public ClassNode(TClass clas) {
193     name = clas.getName();
194     source = clas;
195   }
196 
197   /**Constructs a class node given an ontology instance
198    * @param instance ontology instance   */
199   public ClassNode(OInstance instance) {
200     name = instance.getName();
201     source = instance;
202   }
203 
204   /**
205    * Constructs a class node given a mapping node
206    * @param mapNode mapping node    */
207   public ClassNode(MappingNode mapNode) {
208     name = mapNode.getList();
209     source = mapNode;
210   }
211 
212   public int getIndexOfChild(Object child) {
213     return children.indexOf(child);
214   }
215 
216   public Iterator getChildren() {
217     return children.iterator();
218   }
219 
220   public void setChildren(Vector chldrn ) {
221     children = chldrn;
222   }
223 
224   public Vector children() {
225     return children;
226   }
227 
228   public String toString() {
229     return name;
230   }
231 
232   public int getChildCount() {
233     return children.size();
234   }
235 
236   public IFolder getChild(int index) {
237     return (IFolder)children.get(index);
238   }
239 
240   public boolean equals(Object o) {
241     boolean result = false;
242     if (o instanceof ClassNode) {
243       ClassNode node = (ClassNode) o;
244       result = node.source.equals(this.source);
245     }
246     return result;
247   }
248 
249   /**Gets the Source object
250    * @return the source object e.g. an gate.creole.TClass
251    * or a gate.creole.Ontology   */
252   public Object getSource(){
253     return source;
254   }
255 
256   /**Sets the source object
257    * @param o the source object to be set   */
258   public void setSource(Object o)  {
259     source = o;
260   }
261 
262   /**Renames this class node
263    * @param newName the new name of the node   */
264   public void rename(String newName) {
265     name = newName;
266   }
267 
268   /**Removes a sub class
269    * @param sub the sub class to be removed*/
270   public void removeSubNode(ClassNode sub) {
271     if ( children.contains(sub) ) {
272       children.remove(sub);
273       Object source = this.getSource();
274       if (source instanceof TClass) {
275         TClass c = (TClass) source;
276         if (sub.getSource() instanceof TClass)
277           c.removeSubClass((TClass)sub.getSource());
278         else if (sub.getSource() instanceof OInstance &&
279                  c.getOntology() instanceof Ontology)
280           ((Ontology)c.getOntology()).removeInstance((OInstance) sub.getSource());
281       } else if ( source instanceof Taxonomy ) {
282           Taxonomy o = (Taxonomy) source;
283           o.removeClass((TClass)sub.getSource());
284         } else if (source instanceof OInstance) {
285           //cannot remove anything from an instance
286           return;
287         } else {
288           throw new GateRuntimeException(
289           "Can not remove a sub node from a classnode.\n"
290           +"The source is neither an Ontology neither TClass");
291         } // else
292     } // if contains
293   } // removeSubNode
294 
295   /**Adds a sub node
296    * @param sub the sub node to be added    */
297   public void addSubNode(ClassNode sub) {
298     if ( ! children.contains(sub) )  {
299       Object source = this.getSource();
300       if ( source instanceof TClass) {
301         TClass c = (TClass)source;
302         if (!(sub.getSource() instanceof TClass) ||
303             !(sub.getSource() instanceof OInstance))
304           throw new GateRuntimeException(
305           "The sub node's source is not an instance of TClass or OInstance");
306         if (sub.getSource() instanceof TClass) {
307           TClass sc = (TClass) sub.getSource();
308           c.addSubClass(sc);
309           c.getOntology().addClass(sc);
310           children.add(sub);
311         }
312         if (sub.getSource() instanceof OInstance &&
313             c.getOntology() instanceof Ontology){
314           OInstance inst = (OInstance) sub.getSource();
315           ((Ontology)c.getOntology()).addInstance(inst);
316           children.add(sub);
317         }
318 
319       } else {
320         if (source instanceof Taxonomy) {
321           Taxonomy o = (Taxonomy) source;
322           if (!(sub.getSource() instanceof TClass))
323             throw new GateRuntimeException("The sub node's source is not an instance of TClass");
324           TClass sc = (TClass)sub.getSource();
325           o.addClass(sc);
326           children.add(sub);
327         } else  {
328           throw new GateRuntimeException(
329           "cannot add a sub node to something which "
330           +"is neither an Ontology neither an TClass");
331         } // else
332       } // else
333     } // if ! contains
334   } // addSubNode()
335 
336   /*--- Transferable interface implementation ---*/
337   public boolean isDataFlavorSupported(DataFlavor df) {
338     return df.equals(CLASS_NODE_FLAVOR);
339   }
340 
341   public Object getTransferData(DataFlavor df)
342       throws UnsupportedFlavorException, IOException {
343     if (df.equals(CLASS_NODE_FLAVOR)) {
344       return this;
345     }
346     else throw new UnsupportedFlavorException(df);
347   }
348 
349   public DataFlavor[] getTransferDataFlavors() {
350     return flavors;
351   }
352 
353 
354 } // class ClassNode