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