View Javadoc

1   /*
2    * $Id: DefaultNamespaceSuggester.java,v 1.13 2005/09/06 22:12:09 jlerner Exp $
3    *
4    * Copyright (c) 1999-2004, BBN Technologies, LLC.
5    * All rights reserved.
6    * http://www.daml.org/legal/opensource/bbn_license.html
7    */
8   
9   package com.bbn.swede.editor.contentassist;
10  
11  import java.util.ArrayList;
12  import java.util.Collections;
13  import java.util.Iterator;
14  import java.util.List;
15  
16  import com.bbn.swede.core.dom.IOASTChangeListener;
17  import com.bbn.swede.core.dom.IOWLAbstractSyntaxTree;
18  import com.bbn.swede.core.dom.OAST;
19  import com.bbn.swede.core.dom.OASTEvent;
20  import com.hp.hpl.jena.ontology.OntModel;
21  import com.hp.hpl.jena.rdf.model.Resource;
22  import com.hp.hpl.jena.rdql.Query;
23  import com.hp.hpl.jena.rdql.QueryResults;
24  import com.hp.hpl.jena.rdql.ResultBinding;
25  
26  /***
27   * This class represents a default implementation of a NamespaceSuggester. It
28   * will, given a URI and an OAST, provide suggestions for strings presented to
29   * it based on the classes and properties present in the OAST at any particular
30   * time.
31   * 
32   * This class implements IOASTChangeListener, and will monitor the relevant OAST
33   * to ensure that new classes and properties are available for suggestion.
34   * 
35   * @see com.bbn.swede.core.dom.IOASTChangeListener
36   * @see com.bbn.swede.editor.contentassist.INamespaceSuggester
37   * @see com.bbn.swede.editor.contentassist.ISuggestionCandidate
38   * @author aperezlo
39   */
40  
41  class DefaultNamespaceSuggester implements IOASTChangeListener,
42     INamespaceSuggester
43  {
44  
45     /***
46      * Returns those instances in this suggester's namespace which start with
47      * what the user has already typed.
48      * 
49      * @param alreadyTyped The text that has been typed so far
50      * @return a list of ISuggestionCandidate objects representing instance
51      *         objects
52      * @see com.bbn.swede.editor.contentassist.INamespaceSuggester#getInstanceSuggestions(java.lang.String)
53      */
54     public List getInstanceSuggestions(String alreadyTyped)
55     {
56        List toReturn = new ArrayList();
57        List allStrings = new ArrayList();
58  
59        ISuggestionCandidate temp = null;
60        Iterator i = null;
61        i = _instances.iterator();
62        while (i.hasNext())
63        {
64           temp = (ISuggestionCandidate)i.next();
65           if(temp.getName().startsWith(alreadyTyped))
66           {
67              toReturn.add(temp);
68           }
69        }
70  
71        Collections.sort(toReturn);
72        return toReturn;
73  
74     }
75  
76     /***
77      * <code>_elements</code> represents a listing of all of the classes and
78      * properties in the OAST <code>_tree</code>.
79      */
80     protected List _elements;
81  
82     /***
83      * <code>_tree</code> a reference to the OAST which maintains the internal
84      * representation of the URI for this suggester. The suggester handles
85      * OASTChangeEvents to stay current.
86      */
87     protected IOWLAbstractSyntaxTree _tree;
88  
89     /***
90      * <code>_uri</code>- the URI for which this suggester will make
91      * suggestions.
92      */
93     protected String _uri;
94  
95     /***
96      * <code>_instances</code> is a list of all the instance data in a
97      * particular URI.
98      */
99     protected List _instances;
100 
101    /***
102     * Default constructor.
103     */
104    public DefaultNamespaceSuggester()
105    {
106       _elements = new ArrayList();
107       _instances = new ArrayList();
108    }
109 
110 
111    
112    /***
113     * Given an OAST, this constructor will populate the suggester with all
114     * available classes and properties, and will register for change updates.
115     * 
116     * @param tree the OAST of the URI for which this suggester will make
117     *        suggestions
118     */
119    public DefaultNamespaceSuggester(IOWLAbstractSyntaxTree tree)
120    {
121       this();
122       _tree = tree;
123       _uri = _tree.getBaseURI();
124       if (_tree instanceof OAST)
125       {
126          ((OAST)_tree).addOASTChangeListener(this);
127       }
128       init();
129    }
130 
131    /*
132     * (non-Javadoc)
133     * 
134     * @see com.bbn.swede.core.dom.IOASTChangeListener#oastChanged(com.bbn.swede.core.dom.OASTEvent)
135     */
136    /***
137     * As per the IOASTChangeListener interface, this method is used to update
138     * the listing in the suggester of classes and properties.
139     * 
140     * @see com.bbn.swede.core.dom.IOASTChangeListener#oastChanged(com.bbn.swede.core.dom.OASTEvent)
141     */
142    public void oastChanged(OASTEvent event)
143    {
144       boolean justInsert = false;
145       if(event.isInsert())
146       {
147          if(!event.isRemove()) // just a straight insert...
148          {
149             justInsert = true;
150          }
151       }
152       if(_tree != null)
153       {
154          synch(!justInsert);
155       }
156    }
157 
158    /***
159     * Retrieves suggestion candidates from the OAST.
160     * @return a list ISuggestionCandidates of all of the named individuals from
161     *         the OAST (i.e. individuals, not classes or properties)
162     */
163    private List getInstancesFromTree()
164    {
165       ArrayList toReturn = new ArrayList();
166       String name = null;
167       Iterator iterator = null;
168       ISuggestionCandidate candidate = null;
169       Resource[] namedInds = _tree.getRoot().getOWLDocument().getDocumentInfo()
170          .getNamedIndividuals();
171       for(int i = 0; i < namedInds.length; i++)
172       {
173          name = namedInds[i].getLocalName();
174          if(name != null)
175          {
176             iterator = _elements.iterator();
177             while (iterator.hasNext())
178             {
179                candidate = (ISuggestionCandidate)iterator.next();
180                if(candidate.getName().equals(name))
181                {
182                   break;
183                }
184             }
185             if(!((candidate != null) &&  (name.equals(candidate.getName()))))
186             {
187                toReturn.add(new DefaultSuggestionCandidate(name,
188                   ISuggestionCandidate.ELEMENT));
189             }
190          }
191       }
192 
193       return toReturn;
194    }
195 
196 
197    private String removeURI(String in)
198    {
199       String toReturn = in.replaceAll(".*?#", "");
200       return toReturn;
201    }
202    
203    private List getClassesFromTree()
204    {
205       ArrayList toReturn = new ArrayList();
206       ISuggestionCandidate tempCandidate = null;
207       OntModel jenaModel = _tree.getJenaModel();  
208       QueryResults classQueryResults = null;
209       
210       classQueryResults = Query.exec("SELECT ?className WHERE (?className rdf:type owl:Class)", jenaModel);
211       ResultBinding rb = null;
212       while(classQueryResults.hasNext())
213       {
214          rb = (ResultBinding) classQueryResults.next();
215          if(!((Resource) rb.get("className")).isAnon())
216          {
217             tempCandidate = new DefaultSuggestionCandidate(removeURI(rb.get(
218                "className").toString()), ISuggestionCandidate.CLASS);
219             if(!toReturn.contains(tempCandidate))
220             {
221                toReturn.add(tempCandidate);
222             }
223          }
224       }
225       classQueryResults = Query.exec("SELECT ?className WHERE (?className rdf:type rdfs:Class)", jenaModel);
226       while(classQueryResults.hasNext())
227       {
228          rb = (ResultBinding) classQueryResults.next();
229          if(!((Resource) rb.get("className")).isAnon())
230          {
231             tempCandidate = new DefaultSuggestionCandidate(removeURI(rb.get(
232                "className").toString()), ISuggestionCandidate.CLASS);
233             if(!toReturn.contains(tempCandidate))
234             {
235                toReturn.add(tempCandidate);
236             }
237          }
238       }
239       
240       return toReturn;
241    }
242    private List getPropertiesFromTree()
243    {
244       ArrayList toReturn = new ArrayList();
245       OntModel jenaModel = _tree.getJenaModel();
246       ISuggestionCandidate tempCandidate = null;
247       QueryResults propertyQueryResults = null;
248       
249       ResultBinding rb = null;
250       propertyQueryResults = Query
251          .exec(
252             "SELECT ?propertyName WHERE (?propertyName rdf:type owl:ObjectProperty)",
253             jenaModel);
254       while(propertyQueryResults.hasNext())
255       {
256          rb = (ResultBinding) propertyQueryResults.next();
257          if(!((Resource) rb.get("propertyName")).isAnon())
258          {
259             tempCandidate = new DefaultSuggestionCandidate(removeURI(rb.get(
260                "propertyName").toString()), ISuggestionCandidate.PROPERTY);
261             if(!toReturn.contains(tempCandidate))
262             {
263                toReturn.add(tempCandidate);
264             }
265          }
266       }
267       propertyQueryResults = Query.exec("SELECT ?propertyName WHERE (?propertyName rdf:type rdf:Property)", jenaModel);
268       while(propertyQueryResults.hasNext())
269       {
270          rb = (ResultBinding) propertyQueryResults.next();
271          if(!((Resource) rb.get("propertyName")).isAnon())
272          {
273             tempCandidate = new DefaultSuggestionCandidate(removeURI(rb.get(
274                "propertyName").toString()), ISuggestionCandidate.PROPERTY);
275             if(!toReturn.contains(tempCandidate))
276             {
277                toReturn.add(tempCandidate);
278             }
279          }
280       }
281       propertyQueryResults = Query
282          .exec(
283             "SELECT ?propertyName WHERE (?propertyName rdf:type owl:DatatypeProperty)",
284             jenaModel);
285       while(propertyQueryResults.hasNext())
286       {
287          rb = (ResultBinding) propertyQueryResults.next();
288          if(!((Resource) rb.get("propertyName")).isAnon())
289          {
290             tempCandidate = new DefaultSuggestionCandidate(removeURI(rb.get(
291                "propertyName").toString()), ISuggestionCandidate.PROPERTY);
292             if(!toReturn.contains(tempCandidate))
293             {
294                toReturn.add(tempCandidate);
295             }
296          }
297       }
298       
299       return toReturn;
300    }
301    
302    /***
303     * Retrieves class and property suggestion candidates from the OAST.
304     * @return a list of all of ISuggestionCandidates for each class and property
305     *         in the OAST.
306     */
307    private List getCandidatesFromTree()
308    {
309       ArrayList toReturn = new ArrayList();
310       String name = null;
311 
312       List classes = getClassesFromTree();
313       List props = getPropertiesFromTree();
314       
315       Collections.sort(classes);
316       Collections.sort(props);
317       
318       toReturn.addAll(classes);
319       toReturn.addAll(props);
320 
321       return toReturn;
322    }
323 
324    /***
325     * Synchronize the internal state of the suggester with that of its OAST.
326     * @param checkForRemovedOrReplaced <code>true</code> to check for changes
327     *                                  in the OAST, <code>false</code> if not.
328     */
329    protected void synch(boolean checkForRemovedOrReplaced)
330    {
331       List fromTree = null;
332       List instances = null;
333       fromTree = getCandidatesFromTree();
334       Collections.sort(fromTree);
335       _elements = fromTree;
336       instances = getInstancesFromTree();
337       Collections.sort(instances);
338       _instances = instances;
339    }
340 
341    /***
342     * Unregisters the suggester from its OAST and performs other housekeeping
343     * type chores to ready itself for deletion.
344     */
345    public void cleanup()
346    {
347       if(_tree != null && _tree instanceof OAST)
348       {
349          ((OAST)_tree).removeOASTChangeListener(this);
350       }
351    }
352 
353    /***
354     * Retrieves the URI of this suggester.
355     * @return the URI for which this suggester makes suggestions
356     */
357    public String getURI()
358    {
359       return _uri;
360    }
361 
362    /***
363     * As per the INamespaceSuggester interface, this method can be called to
364     * populate the suggester with classes and properties from which it will make
365     * suggestions.
366     * 
367     * @see com.bbn.swede.editor.contentassist.INamespaceSuggester#init()
368     */
369    public void init()
370    {
371       if(_tree != null)
372       {
373          synch(false);
374       }
375    }
376 
377    /***
378     * Indicates whether this suggester has any suggestions for the text typed
379     * so far.
380     * @param alreadyTyped The text typed so far
381     * @see com.bbn.swede.editor.contentassist.INamespaceSuggester#hasSuggestions(java.lang.String)
382     * @return true if this suggester should be consulted for suggestions, given
383     *         what has already been typed, false otherwise
384     */
385    public boolean hasSuggestions(String alreadyTyped)
386    {
387       boolean toReturn = false;
388       if(_tree != null)
389       {
390          toReturn = true;
391       }
392       return toReturn;
393    }
394 
395    /***
396     * Returns those classes and properties from the suggester's namespace that
397     * start with what has already been typed.
398     * 
399     * @param alreadyTyped the text that precedes the present cursor position
400     * @return a List of ISuggestionCandidate objects representing strings that
401     *         should be suggested
402     */
403    public List getSuggestions(String alreadyTyped)
404    {
405       List allStrings = new ArrayList();
406       List toReturn = new ArrayList();
407       ISuggestionCandidate temp = null;
408       Iterator i = null;
409       alreadyTyped = (alreadyTyped.startsWith("<")) ? alreadyTyped.substring(1)
410          : alreadyTyped;
411       i = _elements.iterator();
412       while (i.hasNext())
413       {
414          temp = (ISuggestionCandidate)i.next();
415          if(temp.getName().startsWith(alreadyTyped))
416          {
417             toReturn.add(temp);
418          }
419       }
420 
421       Collections.sort(toReturn);
422       return toReturn;
423    }
424 
425 }