View Javadoc

1   /*
2    * $Id: DefaultOWLContentAssistProcessor.java,v 1.24 2005/06/01 14:35:58 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.HashMap;
14  import java.util.HashSet;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.Map;
18  import java.util.Set;
19  
20  import org.eclipse.core.resources.IResourceChangeEvent;
21  import org.eclipse.core.resources.IResourceChangeListener;
22  import org.eclipse.core.resources.IResourceDelta;
23  import org.eclipse.core.runtime.IPath;
24  import org.eclipse.jface.text.BadLocationException;
25  import org.eclipse.jface.text.IDocument;
26  import org.eclipse.jface.text.ITextViewer;
27  import org.eclipse.jface.text.contentassist.CompletionProposal;
28  import org.eclipse.jface.text.contentassist.ICompletionProposal;
29  import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
30  import org.eclipse.jface.text.contentassist.IContextInformation;
31  import org.eclipse.jface.text.contentassist.IContextInformationValidator;
32  import org.eclipse.swt.graphics.Image;
33  
34  import com.bbn.swede.core.IOWLDocument;
35  import com.bbn.swede.core.IOWLProject;
36  import com.bbn.swede.core.OWLCore;
37  import com.bbn.swede.core.config.SWProjectInfo;
38  import com.bbn.swede.core.dom.AttributeNode;
39  import com.bbn.swede.core.dom.IOASTChangeListener;
40  import com.bbn.swede.core.dom.IOASTDelta;
41  import com.bbn.swede.core.dom.IOASTDeltaVisitor;
42  import com.bbn.swede.core.dom.IOWLAbstractSyntaxTree;
43  import com.bbn.swede.core.dom.Namespace;
44  import com.bbn.swede.core.dom.OAST;
45  import com.bbn.swede.core.dom.OASTEvent;
46  import com.bbn.swede.core.dom.OASTNode;
47  import com.bbn.swede.core.libraries.ILibraryChangeListener;
48  import com.bbn.swede.core.libraries.ILibraryDescriptor;
49  import com.bbn.swede.core.libraries.LibraryChangeEvent;
50  import com.bbn.swede.core.resources.OWLProject;
51  import com.bbn.swede.core.resources.SWResourceManager;
52  import com.bbn.swede.editor.OWLDocumentPartitioner;
53  import com.bbn.swede.ui.OWLImages;
54  
55  /***
56   * A revision of the content assist processor for the SWeDE editor.
57   * 
58   * @author aperezlo
59   * @author jlerner
60   * @author damoore
61   */
62  public class DefaultOWLContentAssistProcessor implements
63     IContentAssistProcessor, IOASTChangeListener, IResourceChangeListener, ILibraryChangeListener
64  {
65     /***
66      * Proposal type constant indicating a tag proposal.  Tag proposals are
67      * triggered when "<foo:" is typed, where "foo" is a known namespace
68      * abbreviation, or when < is typed and there are classes or properties
69      * defined in the default namespace.
70      */
71     protected static final int TAG_PROPOSAL = 1;
72  
73     /***
74      * Proposal type constant indicating an attribute proposal.  Attribute 
75      * proposals are triggered when "foo:" is typed, where "foo" is a known
76      * namespace abbreviation.
77      */
78     protected static final int ATTRIBUTE_PROPOSAL = 2;
79  
80     /***
81      * Proposal type constant indicating a namespace proposal.  Namespace
82      * proposals are triggered when "<" is typed.
83      */
84     protected static final int NAMESPACE_PROPOSAL = 4;
85  
86     /***
87      * Proposal type constant indicating a fragment proposal.  Fragment proposals
88      * are triggered when "#" is typed within an attribute value after a URI 
89      * known to the project, or immediately after the " for fragment suggestions
90      * within the default namespace.
91      */
92     protected static final int POUND_PROPOSAL = 8;
93  
94     /***
95      * Proposal type constant indicating a URI proposal.  URI proposals are
96      * triggered when '="' is typed.
97      */
98     protected static final int URI_PROPOSAL = 16;
99  
100    /***
101     * Proposal type constant indicating a singleton tag proposal.  Singleton
102     * tag proposals are triggered at the same time as regular tag proposals.
103     */
104    protected static final int SINGLETON_TAG_PROPOSAL = 32;
105 
106    /***
107     * Proposal type constant indicating an invalid proposal.
108     */
109    protected static final int INVALID_PROPOSAL = -1;
110 
111    /***
112     * The containing project of the document being content assisted.
113     */
114    protected IOWLProject _parentProject;
115    
116    /***
117     * <code>_mapUriToSuggester</code> represents a mapping from URIs to
118     * INamespaceSuggester objects monitoring those namespaces.
119     */
120    protected Map _mapURIToSuggester;
121 
122    /***
123     * <code>_namespaceToURI</code> represents a set of mappings between
124     * namespace abbreviations and fully qualified URIs. In general, a namespace
125     * is mapped to a URI in <code>_namespaceToURI</code>, and that same URI
126     * has a mapping to a suggester in <code>_mapURIToSuggester</code>
127     */
128    protected NamespaceManager _namespaceToURI;
129 
130    /***
131     * The OAST for the currently edited document.
132     */
133    protected IOWLAbstractSyntaxTree _tree;
134 
135    /***
136     * Default constructor.
137     */
138    public DefaultOWLContentAssistProcessor()
139    {
140       _mapURIToSuggester = Collections.synchronizedMap(new HashMap());
141       _namespaceToURI = new NamespaceManager();
142    }
143 
144    /* (non-Javadoc)
145     * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(
146     *    org.eclipse.core.resources.IResourceChangeEvent)
147     */
148    public void resourceChanged(IResourceChangeEvent event)
149    {
150       IResourceDelta delta = event.getDelta();
151       IPath projectInfoPath = null;
152       IResourceDelta ourProjectDelta = null;
153       OASTNode[] namespaceNodes = null;
154       Namespace namespace = null;
155       Map documentNamespaces = new HashMap();
156       Map.Entry steve = null;
157       INamespaceSuggester sugg = null;
158       String sUri = null;
159       if(_tree != null)
160       {
161          if(_tree.getRoot().getOWLDocument() != null)
162          {
163             projectInfoPath = _tree.getRoot().getOWLDocument().getFile()
164                .getProject().getFullPath().append(SWProjectInfo.S_FILE_NAME);
165             if((delta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED)) != 0)
166             {
167                ourProjectDelta = delta.findMember(projectInfoPath);
168                if(ourProjectDelta != null)
169                {
170                   namespaceNodes = _tree.getRoot().getNodesOfType(OASTNode.NAMESPACE);
171                   for (int i = 0; i < namespaceNodes.length; i++)
172                   {
173                      namespace = (Namespace)namespaceNodes[i];
174                      documentNamespaces.put(namespace.getAbbreviation(),
175                         namespace.getValue().replaceAll("#", ""));
176                   }
177                   
178                   synchronized (_mapURIToSuggester)
179                   {
180                      // adding new stuff...
181                      Iterator it = documentNamespaces.entrySet().iterator();
182                      while(it.hasNext())
183                      {
184                         steve = (Map.Entry) it.next();
185                         sUri = (String) steve.getValue();
186                         if(_mapURIToSuggester.get(sUri) == null)
187                         {
188                            if(_tree.getNamespace(sUri) != null)
189                            {
190                               sugg = new DefaultNamespaceSuggester(_tree
191                                  .getNamespace(sUri).getDocumentInfo()
192                                  .getOAST());
193                               _mapURIToSuggester.put(sUri, sugg);
194                            }
195                         }
196                         else
197                         {
198                            if(!sUri.equals(OASTNode.S_XSD_URI)
199                               && !sUri.equals(OASTNode.S_OWL_URI)
200                               && !sUri.equals(OASTNode.S_RDF_URI)
201                               && !sUri.equals(OASTNode.S_RDFS_URI))
202                            {
203                               if(_tree.getNamespace(sUri) == null)
204                               {
205                                  _mapURIToSuggester.remove(sUri);
206                               }
207                            }
208                         }
209                      }
210                   }
211                   
212                }
213             }
214          }
215       }
216    }
217    
218    
219    /***
220     * Convenience method to handle adding a new namespace to the management of
221     * this ContentAssistProcessor. If the URI is not currently known by the
222     * processor, a new NamespaceSuggester object is created and populated.
223     * 
224     * @param namespace the namespace assigned to the URI of the new namespace
225     * @param sURI the URI assigned to the namespace.
226     * @return true if a new namespace was added, false otherwise
227     */
228    private boolean addNamespace(String namespace, String sURI)
229    {
230       boolean toReturn = false;
231       DefaultNamespaceSuggester tempSuggester = (DefaultNamespaceSuggester)_mapURIToSuggester
232          .get(sURI);
233       String tempURI = (String)_namespaceToURI.getURI(namespace);
234       String tempNamespace = null;
235       IOWLAbstractSyntaxTree tempOAST = null;
236       IOWLDocument tempDocument = null;
237       Iterator i = null;
238       boolean found = false;
239 
240       if(tempSuggester == null)
241       { // new namespace!
242          try
243          {
244             tempDocument = _tree.getNamespace(sURI);
245             _namespaceToURI.addNamespace(namespace, sURI);
246             if(tempDocument != null)
247             {
248                tempOAST = tempDocument.getDocumentInfo().getOAST();
249                tempSuggester = new DefaultNamespaceSuggester(tempOAST);
250                _mapURIToSuggester.put(sURI, tempSuggester);
251                toReturn = true;
252             }
253             else
254             {
255                if(OASTNode.S_XSD_URI.equals(sURI))
256                {
257                   tempSuggester = new XSDNamespaceSuggester();
258                   _mapURIToSuggester.put(sURI, tempSuggester);
259                   toReturn = true;
260                }
261                
262                if(OASTNode.S_OWL_URI.equals(sURI))
263                {
264                   tempSuggester = new OWLNamespaceSuggester();
265                   _mapURIToSuggester.put(sURI, tempSuggester);
266                   toReturn = true;
267                }
268                if(OASTNode.S_RDF_URI.equals(sURI))
269                {
270                   tempSuggester = new RDFNamespaceSuggester();
271                   _mapURIToSuggester.put(sURI, tempSuggester);
272                   toReturn = true;
273                }
274                if(OASTNode.S_RDFS_URI.equals(sURI))
275                {
276                   tempSuggester = new RDFSNamespaceSuggester();
277                   _mapURIToSuggester.put(sURI, tempSuggester);
278                   toReturn = true;
279                }
280                
281             }
282          }
283          catch (Exception e) // cannot load the indicated URI - it's not in the
284                              // project!
285          {
286             toReturn = false;
287          }
288       }
289       else
290       { // we've seen this one before - don't reparse the document, but
291          // add a namespace mapping the local naming scheme
292          _namespaceToURI.addNamespace(namespace, sURI);
293       }
294 
295       return toReturn;
296    }
297 
298    /***
299     * This method is different than remove URI. <code>removeURI</code> finds
300     * the first mapping of the given URI to a namespace and a suggester and
301     * removes them both. This method takes a namespace -> URI mapping indexed by
302     * the namespace and removes it. If this namespace is the last namespace to
303     * reference this URI, then the removeURI is called on the URI.
304     * 
305     * @param namespace the namespace to remove
306     * @return true if this namespace was the last reference to its URI, false if
307     *         the URI still remains within scope under a different name
308     */
309    private boolean removeNamespace(String namespace)
310    {
311       boolean toReturn = false;
312       String sURI = (String)_namespaceToURI.getURI(namespace);
313 
314       _namespaceToURI.removeNamespace(namespace);
315       if(sURI != null)
316       {
317          if(!_namespaceToURI.containsURI(sURI))
318          {
319             removeURI(sURI);
320             toReturn = true;
321          }
322       }
323 
324       return toReturn;
325    }
326 
327    /***
328     * This method removes a namespace from the processor's notice, in which case
329     * the elements of that namespace will no longer be proferred as suggestions
330     * by this processor when prompted.
331     * 
332     * @param sURI the URI of the namespace to be removed from the processor's
333     *             notice
334     * @return true if the namespace was successfully removed from the
335     *         processor's management
336     */
337    private boolean removeURI(String sURI)
338    {
339       boolean toReturn = true;
340       String namespace = null;
341       DefaultNamespaceSuggester tempSuggester = (DefaultNamespaceSuggester)_mapURIToSuggester
342          .get(sURI);
343 
344       if(tempSuggester != null)
345       {
346          tempSuggester.cleanup();
347          synchronized (_mapURIToSuggester)
348          {
349             _mapURIToSuggester.remove(sURI);
350          }
351          _namespaceToURI.removeURI(sURI);
352 
353          toReturn = true;
354       }
355 
356       return toReturn;
357    }
358 
359    private final class NamespaceChangedVisitor implements IOASTDeltaVisitor 
360    {
361       private HashSet _namespaceDeltas = new HashSet(); 
362       /***
363        * Retrieves the changed namespaces found by the visitor.
364        * @return A HashSet containing all changed namespaces found.
365        */
366       public HashSet getNamespaceDeltas()
367       {
368          return _namespaceDeltas;
369       }
370       public boolean visit(IOASTDelta delta)
371       {
372          boolean shouldKeepGoing = true;
373          OASTNode node = null;
374          if((delta.getType() & (IOASTDelta.CHANGED | IOASTDelta.REMOVED | IOASTDelta.INSERTED)) != 0)
375          {
376             node = delta.getNodeAfter();
377             if(node != null)
378             {
379                if(node.getNodeType() == OASTNode.NAMESPACE)
380                {
381                   _namespaceDeltas.add(delta);
382                   shouldKeepGoing = false;
383                }
384             }
385             else
386             {
387                node = delta.getNodeBefore();
388                if(node != null)
389                {
390                   if(node.getNodeType() == OASTNode.NAMESPACE)
391                   {
392                      _namespaceDeltas.add(delta);
393                      shouldKeepGoing = false;
394                   }
395                }
396             }
397          }
398          return shouldKeepGoing;
399       }
400    }   
401    
402    private String yoinkURI(OASTNode node)
403    {
404       String toReturn = null;
405       try
406       {
407          if(node.getNodeType() == OASTNode.NAMESPACE)
408          {
409             toReturn = ((Namespace) node).getValue();
410          }
411          else if(node.getNodeType() == OASTNode.RDF_RESOURCE)
412          {
413             toReturn = ((AttributeNode) node).getValue();
414          }
415       }
416       catch(Exception e)
417       {
418          //Nothing to see here.  Move along.
419       }
420       if((toReturn != null) && (!toReturn.endsWith("#")))
421       {
422          toReturn += "#";
423       }
424       return toReturn;
425    }
426    
427    /***
428     * This method responds to changes in the underlying OAST of the current
429     * document to ensure that changes made to the namespace declarations are
430     * current. This allows users to add, remove, or alter namespace declarations
431     * and still have up-to-date content assist support.
432     * 
433     * @see com.bbn.swede.core.dom.IOASTChangeListener#oastChanged(com.bbn.swede.core.dom.OASTEvent)
434     */
435    public void oastChanged(OASTEvent event)
436    {
437       IOASTDelta delta = null;
438       NamespaceChangedVisitor ncv = new NamespaceChangedVisitor();
439       event.getDelta().accept(ncv);
440       Set namespaceDeltas = ncv.getNamespaceDeltas();
441       Namespace ns = null;
442       if(!namespaceDeltas.isEmpty())
443       {
444          Iterator i = namespaceDeltas.iterator();
445          while(i.hasNext())
446          {
447             delta = (IOASTDelta) i.next();
448             if(delta.typeMatches(IOASTDelta.REMOVED))
449             {
450                ns = (Namespace) delta.getNodeBefore();
451                removeNamespace(ns.getAbbreviation());
452                OWLCore.trace("DefaultOWLContentAssistProcessor.oastChanged()",
453                   "REMOVED! - " + delta.getNodeBefore(), false);
454             }
455             if(delta.typeMatches(IOASTDelta.CHANGED))
456             {
457                ns = (Namespace) delta.getNodeBefore();
458                removeNamespace(ns.getAbbreviation());
459                ns = (Namespace) delta.getNodeAfter();
460                addNamespace(ns.getAbbreviation(), ns.getValue().replaceAll("#", ""));
461                OWLCore.trace("DefaultOWLContentAssistProcessor.oastChanged()",
462                   "CHANGED! - " + delta.getNodeAfter(), false);
463             }
464             if(delta.typeMatches(IOASTDelta.INSERTED))
465             {
466                ns = (Namespace) delta.getNodeAfter();
467                addNamespace(ns.getAbbreviation(), ns.getValue().replaceAll("#", ""));
468                OWLCore.trace("DefaultOWLContentAssistProcessor.oastChanged()",
469                   "INSERTED! - " + delta.getNodeAfter(), false);
470             }
471          }
472       }
473    }
474    
475 //   public void oastChanged(OASTEvent event)
476 //   {
477 //      List changedNodes = null;
478 //      OASTNode tempNode = null;
479 //      Namespace tempNamespace = null;
480 //      Iterator it = null;
481 //      Map documentNamespaces = new HashMap();
482 //      OASTNode[] singleNodeNamespaces;
483 //      boolean namespacesChanged = false;
484 //      String tempURI = null;
485 //      String tempNS = null;
486 //      List urisToRemove = null;
487 //      boolean explicitDefaultNamespace = false;
488 //
489 //      changedNodes = new ArrayList();
490 //      if(event.isRemove() || event.isInsert())
491 //      {
492 //         if(event.getRemoved() != null)
493 //         {
494 //            changedNodes.addAll(Arrays.asList(event.getRemoved()));
495 //         }
496 //         if(event.getInserted() != null)
497 //         {
498 //            changedNodes.addAll(Arrays.asList(event.getInserted()));
499 //         }
500 //         it = changedNodes.iterator();
501 //         while (it.hasNext())
502 //         {
503 //            tempNode = (OASTNode)it.next();
504 //            if(tempNode.getNodesOfType(OASTNode.NAMESPACE).length > 0)
505 //            {
506 //               namespacesChanged = true;
507 //               break;
508 //            }
509 //         }
510 //         if(namespacesChanged)
511 //         {
512 //            changedNodes.clear();
513 //            // we only care about the nodes to be inserted, as they are the
514 //            // ones that will be in the document when the dust settles...
515 //            _namespaceToURI.setBaseURI(_tree.getBaseURI());
516 //            changedNodes = Arrays.asList(event.getInserted());
517 //            it = changedNodes.iterator();
518 //            while (it.hasNext())
519 //            {
520 //               tempNode = (OASTNode)it.next();
521 //               singleNodeNamespaces = tempNode
522 //                  .getNodesOfType(OASTNode.NAMESPACE);
523 //               for (int i = 0; i < singleNodeNamespaces.length; i++)
524 //               {
525 //                  tempNamespace = (Namespace)singleNodeNamespaces[i];
526 //                  if(tempNamespace.getAbbreviation().equals(""))
527 //                  {
528 //                     explicitDefaultNamespace = true;
529 //                     documentNamespaces.put("", tempNamespace.getValue()
530 //                        .replaceAll("#", ""));
531 //                  }
532 //                  documentNamespaces.put(tempNamespace.getAbbreviation(),
533 //                     tempNamespace.getValue().replaceAll("#", ""));
534 //               }
535 //            }
536 //            if((_tree.getBaseURI() != null) && (!explicitDefaultNamespace))
537 //            {
538 //               documentNamespaces.put("", _tree.getBaseURI());
539 //            }
540 //            urisToRemove = new ArrayList();
541 //            synchronized (_mapURIToSuggester)
542 //            {
543 //               // documentNamespaces should now hold all the namespaces in the
544 //               // tree
545 //               it = _mapURIToSuggester.keySet().iterator();
546 //               while (it.hasNext())
547 //               {
548 //                  tempURI = (String)it.next();
549 //                  if(!documentNamespaces.values().contains(tempURI))
550 //                  {
551 //                     urisToRemove.add(tempURI);
552 //                  }
553 //               }
554 //            }
555 //            it = urisToRemove.iterator();
556 //            while (it.hasNext())
557 //            {
558 //               tempURI = (String)it.next();
559 //               removeURI(tempURI);
560 //            }
561 //
562 //            it = _namespaceToURI.getAllNamespaces().iterator();
563 //            while (it.hasNext())
564 //            {
565 //               tempNS = (String)it.next();
566 //               if(!documentNamespaces.keySet().contains(tempNS))
567 //               {
568 //                  _namespaceToURI.removeNamespace(tempNS);
569 //               }
570 //            }
571 //            it = documentNamespaces.keySet().iterator();
572 //            while (it.hasNext())
573 //            {
574 //               tempNS = (String)it.next();
575 //               addNamespace(tempNS, (String)documentNamespaces.get(tempNS));
576 //            }
577 //         }
578 //      }
579 //   }
580 
581    /***
582     * Fetches the autocomplete qualifier from the document. The qualifier is
583     * determined by searching backwards in <code>doc</code> from
584     * <code>documentOffset</code> until one of the characters ' <', '#', '\'',
585     * or '\"' is found at position <code>off</code>. The resulting qualifier
586     * is the string that starts at <code>off + 1</code> and ends at
587     * <code>documentOffset</code>, which may be the empty string.
588     * 
589     * @param doc The current org.eclipse.jface.text.IDocument
590     * @param documentOffset The current cursor position in <code>doc</code>
591     * @return The qualifier, or an empty string if no qualifier is found
592     */
593    private String getQualifier(IDocument doc, int documentOffset)
594    {
595       // Use string buffer to collect characters
596       StringBuffer buf = new StringBuffer();
597       char c = 0;
598       while (true)
599       {
600          try
601          {
602             // Read character backwards
603             c = doc.getChar(--documentOffset);
604             // This was not the start of a tag...but I don't care!
605             if(c == '>' || Character.isWhitespace(c)) //|| c == '\"')
606             {
607                // no open tag was found.
608                return buf.reverse().toString();
609             }
610             // Collect character
611             buf.append(c);
612             // Start of tag or attribute value. Return qualifier
613             if(c == '<' || /* c == '#' || */c == '\'' || c == '\"')
614             {
615                if(c == '\"')
616                {
617                   // We only want to offer autocomplete for '"' if it's preceded
618                   // by an '='
619                   // so that you don't get rampant autocomplete all over the
620                   // document...
621                   if(doc.getChar(documentOffset - 1) == '=')
622                   {
623                      return buf.reverse().toString();
624                   }
625                   else
626                   {
627                      return "";
628                   }
629                }
630                else
631                {
632                   return buf.reverse().toString();
633                }
634             }
635          }
636          catch (BadLocationException e)
637          {
638             // Document start reached, no tag found
639             return "";
640          }
641       }
642    }
643 
644    /***
645     * Utility method to extract portion of a String after a special character -
646     * either a "#" or a ":".
647     * 
648     * @param alreadyTyped the text that has been typed at the time of a content
649     *        assist invocation.
650     * @return any text following a # or : scope resolution character
651     */
652    private String extractAfterNamespaceOrURI(String alreadyTyped)
653    {
654       String toReturn = "";
655       int index = -1;
656 
657       index = alreadyTyped.lastIndexOf("#");
658       if(index < 0) // this is not a URI!
659       {
660          index = alreadyTyped.lastIndexOf(":");
661       }
662       if(index > -1)
663       {
664          toReturn = alreadyTyped.substring(index + 1);
665       }
666 
667       return toReturn;
668    }
669 
670    /***
671     * Utility method to check for a namespace abbreviation or URI at the
672     * beginning of a string.
673     * 
674     * @param alreadyTyped the text that has been typed at the time of a content
675     *        assist invocation.
676     * @return any namespace or URI present in the string, or "" if none is
677     *         present
678     */
679    private String extractNamespaceOrURI(String alreadyTyped)
680    {
681       String toReturn = null;
682       if(alreadyTyped.length() != 0)
683       {
684          if(alreadyTyped.startsWith("\""))
685          {
686             alreadyTyped = alreadyTyped.substring(1);
687          }
688 
689          if(alreadyTyped.lastIndexOf("\"") > -1)
690          {
691             if(!alreadyTyped.startsWith("\""))
692             {
693                toReturn = alreadyTyped.substring(0, alreadyTyped
694                   .lastIndexOf("\""));
695             }
696          }
697          if(alreadyTyped.lastIndexOf("#") > -1)
698          {
699             if(!alreadyTyped.startsWith("#"))
700             {
701                toReturn = alreadyTyped.substring(0, alreadyTyped
702                   .lastIndexOf("#"));
703             }
704             else
705             {
706                toReturn = "";
707             }
708          }
709          else
710          {
711             if(alreadyTyped.startsWith("<"))
712             {
713                if(alreadyTyped.length() > 1)
714                {
715                   if(alreadyTyped.indexOf(":") > -1)
716                   {
717                      toReturn = alreadyTyped.substring(1, alreadyTyped
718                         .indexOf(":"));
719                   }
720                   else
721                   {
722                      toReturn = alreadyTyped.substring(1);
723                   }
724                }
725                else
726                {
727                   toReturn = "";
728                }
729             }
730             else
731             {
732                if((alreadyTyped.lastIndexOf(":") > -1)
733                   && (alreadyTyped.length() > 1))
734                {
735                   toReturn = alreadyTyped.substring(0, alreadyTyped
736                      .lastIndexOf(":"));
737                }
738             }
739          }
740       }
741       return toReturn;
742    }
743 
744    /***
745     * This code is called to handle the a request for autocompletion assistence
746     * between two quotation marks - the suggestions offered consist of each URI
747     * available in the project.
748     * 
749     * @param offset location of the cursor in the document at the time of the
750     *        content assist invocation
751     * @return a list of ICompletionProposals representing available URIs in the
752     *         project.
753     */
754    private List handleQuote(String alreadyTyped, int offset, boolean hasEndQuote)
755    {
756       List toReturn = new ArrayList();
757       List namespaces = _tree.listNamespaces();
758       Iterator i = namespaces.iterator();
759       String namespace = null;
760       List strings = new ArrayList();
761       String beginning = alreadyTyped.substring(1);
762 
763       while (i.hasNext())
764       {
765          namespace = (String)i.next();
766          if(namespace.startsWith(beginning))
767          {
768             strings.add(new DefaultSuggestionCandidate(namespace
769                + (!hasEndQuote ? "\"" : ""), ISuggestionCandidate.NAMESPACE));
770          }
771       }
772       
773       if(OASTNode.S_OWL_URI.startsWith(beginning))
774       {
775          strings.add(new DefaultSuggestionCandidate(OASTNode.S_OWL_URI
776             + (!hasEndQuote ? "\"" : ""), ISuggestionCandidate.NAMESPACE));
777       }
778       if(OASTNode.S_RDF_URI.startsWith(beginning))
779       {
780          strings.add(new DefaultSuggestionCandidate(OASTNode.S_RDF_URI
781             + (!hasEndQuote ? "\"" : ""), ISuggestionCandidate.NAMESPACE));
782       }
783       if(OASTNode.S_RDFS_URI.startsWith(beginning))
784       {
785          strings.add(new DefaultSuggestionCandidate(OASTNode.S_RDFS_URI
786             + (!hasEndQuote ? "\"" : ""), ISuggestionCandidate.NAMESPACE));
787       }
788       
789       if(OASTNode.S_XSD_URI.startsWith(beginning))
790       {
791          if(!namespaces.contains(OASTNode.S_XSD_URI))
792          {
793             strings.add(new DefaultSuggestionCandidate(
794                OASTNode.S_XSD_URI + (!hasEndQuote ? "\"" : ""),
795                ISuggestionCandidate.NAMESPACE));
796          }
797       }
798 
799       Collections.sort(strings);
800       toReturn.addAll(makeProposals(URI_PROPOSAL, alreadyTyped, "", strings,
801          offset));
802 
803       return toReturn;
804    }
805 
806    /***
807     * This code is called to handle the a request for autocompletion assistence
808     * after a # sign - the elements (both classes and properties, as well as
809     * individuals) in a particular namespace. Just a #, without a preceding
810     * fully qualified URI will give the items in the base URI.
811     * 
812     * 
813     * 
814     * @param alreadyTyped the text already typed at the time of the content
815     *        assist invocation
816     * @param sURI the URI preceding the # character
817     * @param offset the cursor location in the document at the time of the
818     *        content assist invocation
819     * @return a list of ICompletionProposal objects containing available classes
820     *         and properties within the URI
821     */
822    private List handlePound(String alreadyTyped, String sURI, int offset)
823    {
824       List toReturn = new ArrayList();
825       List strings = new ArrayList();
826       DefaultNamespaceSuggester sugg = null;
827       IOWLDocument tempDocument = null;
828       IOWLAbstractSyntaxTree tempOAST = null;
829 
830       if(sURI.equals(""))
831       {
832          sURI = _namespaceToURI.getBaseURI();
833       }
834       sugg = (DefaultNamespaceSuggester)_mapURIToSuggester.get(sURI);
835       if(sugg == null)
836       {
837          try
838          {
839             tempDocument = _tree.getNamespace(sURI);
840             if(tempDocument != null)
841             {
842                tempOAST = tempDocument.getDocumentInfo().getOAST();
843                sugg = new DefaultNamespaceSuggester(tempOAST);
844                _mapURIToSuggester.put(sURI, sugg);
845             }
846             
847             if(OASTNode.S_OWL_URI.equals(sURI))
848             {
849                sugg = new OWLNamespaceSuggester();
850                _mapURIToSuggester.put(sURI, sugg);
851             }
852             if(OASTNode.S_RDF_URI.equals(sURI))
853             {
854                sugg = new RDFNamespaceSuggester();
855                _mapURIToSuggester.put(sURI, sugg);
856             }
857             if(OASTNode.S_RDFS_URI.equals(sURI))
858             {
859                sugg = new RDFSNamespaceSuggester();
860                _mapURIToSuggester.put(sURI, sugg);
861             }
862             
863             if(OASTNode.S_XSD_URI.equals(sURI))
864             {
865                sugg = new XSDNamespaceSuggester();
866                _mapURIToSuggester.put(sURI, sugg);
867             }
868          }
869          catch (Exception e)
870          {
871             //Nothing to see here.  Move along.
872          }
873       }
874       if(sugg != null)
875       {
876          strings.addAll(sugg
877             .getSuggestions(extractAfterNamespaceOrURI(alreadyTyped)));
878          strings.addAll(sugg
879             .getInstanceSuggestions(extractAfterNamespaceOrURI(alreadyTyped)));
880       }
881       sURI = _namespaceToURI.getBaseURI() == sURI ? "" : sURI;
882       toReturn.addAll(makeProposals(POUND_PROPOSAL, alreadyTyped, sURI, strings,
883          offset));
884 
885       return toReturn;
886    }
887 
888    /***
889     * This code is called to handle the a request for autocompletion assistence
890     * after a : sign - the elements (just classes and properties, not
891     * individuals) in a particular namespace.
892     * 
893     * @param alreadyTyped the text already typed at the time of the content
894     *        assist invocation
895     * @param namespace the namespace preceding the : character
896     * @param offset the cursor location in the document at the time of the
897     *        content assist invocation
898     * @return a listing of possible completions, presented as attributes
899     */
900    private List handleColon(String alreadyTyped, String namespace, int offset)
901    {
902       List toReturn = new ArrayList();
903       DefaultNamespaceSuggester sugg = null;
904       String sURI = null;
905       List proposalStrings = null;
906 
907       if(namespace.length() > 1)
908       {
909          sURI = _namespaceToURI.getURI(namespace);
910          if(sURI != null)
911          {
912             sugg = (DefaultNamespaceSuggester)_mapURIToSuggester.get(sURI);
913             if(sugg != null)
914             {
915                if(sugg.hasSuggestions(alreadyTyped))
916                {
917                   proposalStrings = sugg
918                      .getSuggestions(extractAfterNamespaceOrURI(alreadyTyped));
919                   Collections.sort(proposalStrings);
920                   toReturn.addAll(makeProposals(ATTRIBUTE_PROPOSAL, alreadyTyped,
921                      namespace, proposalStrings, offset));
922                }
923             }
924          }
925       }
926 
927       return toReturn;
928    }
929 
930    /***
931     * This code is called to handle the a request for autocompletion assistence
932     * after a &gt; character - suitable namespace abbrieviations, as well as
933     * classes and properties in the default namespace. Can be used in
934     * conjunction with a ":" (e.g. &gt;owl:Class&lt;)
935     * 
936     * @param alreadyTyped the text already typed at the time of the content
937     *        assist invocation
938     * @param namespace the namespace preceding the : character, if any
939     * @param offset the cursor location in the document at the time of the
940     *        content assist invocation
941     * @return a listing of namespaces and elements of the default namespace
942     *         which match the text already typed.
943     */
944    private List handleLessThan(String alreadyTyped, String namespace, int offset)
945    {
946       List proposalStrings = new ArrayList();
947       List toReturn = new ArrayList();
948       Iterator i = null;
949       String tempNamespace = null;
950       DefaultNamespaceSuggester tempNamespaceSuggestions = null;
951 
952       //no need to look for namespaces if one's already been specified...
953       if(alreadyTyped.indexOf(":") < 0)
954       {
955          i = _namespaceToURI.getAllNamespaces().iterator();
956          while (i.hasNext())
957          {
958             tempNamespace = (String)i.next();
959             if(tempNamespace.length() > 0)
960             {
961                if(tempNamespace.startsWith(namespace))
962                {
963                   proposalStrings.add(new DefaultSuggestionCandidate(
964                      tempNamespace, ISuggestionCandidate.NAMESPACE));
965                }
966             }
967          }
968          Collections.sort(proposalStrings);
969          toReturn.addAll(makeProposals(NAMESPACE_PROPOSAL, alreadyTyped, "",
970             proposalStrings, offset));
971       }
972       // done w/ all the namespace proposals for the "<" case, now onto
973       // elements...
974       proposalStrings.clear();
975       if(alreadyTyped.indexOf(":") > -1) // check to see which namespace
976                                          // matches...
977       {
978          tempNamespaceSuggestions = (DefaultNamespaceSuggester)_mapURIToSuggester
979             .get(_namespaceToURI.getURI(namespace));
980          if(tempNamespaceSuggestions != null)
981          {
982             if(tempNamespaceSuggestions
983                .hasSuggestions(extractAfterNamespaceOrURI(alreadyTyped)))
984             {
985                proposalStrings.addAll(tempNamespaceSuggestions
986                   .getSuggestions(extractAfterNamespaceOrURI(alreadyTyped)));
987                Collections.sort(proposalStrings);
988                toReturn.addAll(makeProposals(TAG_PROPOSAL, alreadyTyped,
989                   namespace, proposalStrings, offset));
990                toReturn.addAll(makeProposals(SINGLETON_TAG_PROPOSAL,
991                   alreadyTyped, namespace, proposalStrings, offset));
992             }
993          }
994       }
995       else
996       // just check the default namespace
997       {
998          tempNamespaceSuggestions = (((DefaultNamespaceSuggester)_mapURIToSuggester
999             .get(_namespaceToURI.getURI(NamespaceManager.DEFAULT_NAMESPACE))));
1000          if(tempNamespaceSuggestions != null)
1001          {
1002             if(tempNamespaceSuggestions.hasSuggestions(alreadyTyped))
1003             {
1004                proposalStrings.addAll(tempNamespaceSuggestions
1005                   .getSuggestions(alreadyTyped));
1006                Collections.sort(proposalStrings);
1007                toReturn.addAll(makeProposals(TAG_PROPOSAL, alreadyTyped, "",
1008                   proposalStrings, offset));
1009                toReturn.addAll(makeProposals(SINGLETON_TAG_PROPOSAL,
1010                   alreadyTyped, "", proposalStrings, offset));
1011             }
1012          }
1013       }
1014       return toReturn;
1015    }
1016 
1017    /*
1018     * 
1019     * 
1020     * @return an array of ICompletionProposal objects that should be displayed
1021     *         to the user.
1022     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(
1023     *    org.eclipse.jface.text.ITextViewer,
1024     *      int)
1025     * @see org.eclipse.jface.text.contentassist.ICompletionProposal
1026     */
1027    public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
1028       int offset)
1029    {
1030       // What we're going to do is to extract the namespace, such as it is,
1031       // from what has already been typed, and then check to see which URIs
1032       // are associated with possible namespace completions. Then we take the
1033       // part of what's already been typed past the namespace, and offer it to
1034       // the suggesters. What is returned will be recombined w/ the namespaces
1035       // that we know to create the final proposals.
1036 
1037       ICompletionProposal[] toReturn = null;
1038       IDocument document = viewer.getDocument();
1039       OWLDocumentPartitioner odp = (OWLDocumentPartitioner)document
1040          .getDocumentPartitioner();
1041       String alreadyTyped = getQualifier(document, offset);
1042       String namespace = extractNamespaceOrURI(alreadyTyped);
1043       Iterator i = null;
1044       String tempNamespace = null;
1045       DefaultNamespaceSuggester tempNamespaceSuggestions = null;
1046       Object[] tempArray = null;
1047       List proposalStrings = new ArrayList();
1048       List proposals = new ArrayList();
1049       int type = INVALID_PROPOSAL;
1050       boolean hasEndQuote = false;
1051 
1052       if(_tree == null)
1053       {
1054          _tree = odp.getOAST();
1055          if (_tree instanceof OAST)
1056          {
1057             ((OAST)_tree).addOASTChangeListener(this);
1058             _parentProject = SWResourceManager.getModel().getOWLProject(
1059                _tree.getRoot().getOWLDocument().getPath().makeRelative()
1060                   .segment(0));
1061             ((OWLProject) _parentProject).addLibraryChangeListener(this);
1062          }
1063          init();
1064       }
1065 
1066       try
1067       {
1068          if(document.getChar(offset) == '\"')
1069          {
1070             hasEndQuote = true;
1071          }
1072       }
1073       catch (BadLocationException ble)
1074       {
1075          //Nothing to see here.  Move along.
1076       }
1077 
1078       if(alreadyTyped.startsWith("\""))
1079       {
1080          proposals.addAll(handleQuote(alreadyTyped, offset, hasEndQuote));
1081       }
1082       if(namespace != null)
1083       {
1084          //  we want the namespaces, and also the elements from the default
1085          // namespace
1086          if(alreadyTyped.startsWith("<"))
1087          {
1088             proposals.addAll(handleLessThan(alreadyTyped, namespace, offset));
1089          }
1090          else if(alreadyTyped.indexOf("#") > -1)
1091          {
1092             proposals.addAll(handlePound(alreadyTyped, namespace, offset));
1093          }
1094          else if(alreadyTyped.indexOf(":") > -1)
1095          {
1096             proposals.addAll(handleColon(alreadyTyped, namespace, offset));
1097          }
1098       }
1099 
1100       tempArray = proposals.toArray();
1101       toReturn = new ICompletionProposal[tempArray.length];
1102       for(int k = 0; k < tempArray.length; k++)
1103       {
1104          toReturn[k] = (ICompletionProposal)tempArray[k];
1105       }
1106 
1107       return toReturn;
1108    }
1109 
1110    /*
1111     *  (non-Javadoc)
1112     * @see com.bbn.swede.core.libraries.ILibraryChangeListener#libraryChanged(
1113     *    com.bbn.swede.core.libraries.LibraryChangeEvent)
1114     */
1115    public void libraryChanged(LibraryChangeEvent lce)
1116    {
1117       ILibraryDescriptor library = lce.getLibrary();
1118       List lUris = new ArrayList();
1119       List requireUpdating = new ArrayList();
1120       String aURI = null;
1121       Iterator i = null;
1122       IOWLDocument tempDocument = null;
1123       IOWLAbstractSyntaxTree tempOAST = null;
1124       INamespaceSuggester tempSuggester = null;
1125       synchronized (_namespaceToURI)
1126       {
1127          if (((lce.getType() & (LibraryChangeEvent.REFRESHED | LibraryChangeEvent.CHANGED)) != 0))
1128          {
1129             lUris.addAll(_namespaceToURI.getAllURIs());
1130          }
1131       }
1132       synchronized (_mapURIToSuggester)
1133       {
1134          if (((lce.getType() & (LibraryChangeEvent.REFRESHED | LibraryChangeEvent.CHANGED)) != 0))
1135          {
1136             i = lUris.iterator();
1137             while(i.hasNext())
1138             {
1139                aURI = (String) i.next();
1140 
1141                // This line keeps us from rescanning all the documents every time
1142                // a library is changed.  The downside is that we cannot remove 
1143                // content-assist for namespaces that have been taken out of a 
1144                // library, because we can't tell that it's been removed 
1145                // after the fact.  So commenting it out means that whenever a 
1146                // library is refreshed or changed, we do a full reshuffling of 
1147                // which suggesters are around and what-not, which can be
1148                // a little slow...
1149                //if(library.containsURI(aURI))
1150                {
1151                   requireUpdating.add(aURI);
1152                }
1153             }
1154             i = requireUpdating.iterator();
1155             while(i.hasNext())
1156             {
1157                aURI = (String) i.next();
1158                tempDocument = _parentProject.getDocument(aURI);
1159                if(tempDocument == null)  // the file we used to have has been removed!
1160                {
1161                   _mapURIToSuggester.remove(aURI);
1162                }
1163                else
1164                {
1165                   tempOAST = tempDocument.getDocumentInfo().getOAST();
1166                   if(tempOAST != null)
1167                   {
1168                      tempSuggester = ((INamespaceSuggester) _mapURIToSuggester.get(aURI));
1169                      if(tempSuggester != null)
1170                      {
1171                         tempSuggester.cleanup();
1172                      }
1173                      tempSuggester = new DefaultNamespaceSuggester(tempOAST);
1174                      _mapURIToSuggester.put(aURI, tempSuggester);
1175                   }
1176                }
1177             }
1178          }
1179       }
1180 
1181    }
1182    
1183    
1184    
1185    /***
1186     * Convenience method to convert a List of strings into a List of proposals.
1187     * 
1188     * @param proposalType
1189     * @param alreadyTyped
1190     * @param namespace
1191     * @param bodies
1192     * @param offset
1193     * @return a list of ICompletionProposal objects
1194     */
1195    private List makeProposals(int proposalType, String alreadyTyped,
1196       String namespace, List bodies, int offset)
1197    {
1198       List toReturn = new ArrayList();
1199 
1200       Iterator i = bodies.iterator();
1201       while (i.hasNext())
1202       {
1203          toReturn.add(makeProposal(proposalType, alreadyTyped, namespace,
1204             (ISuggestionCandidate)i.next(), offset));
1205       }
1206 
1207       return toReturn;
1208    }
1209 
1210    /***
1211     * Convenience method to produce a ICompletionProposal object from a set of
1212     * data.
1213     * 
1214     * @param proposalType the type of proposal, see constants defined in this
1215     *        class
1216     * @param alreadyTyped the text already typed at the time of the invocation
1217     * @param namespace the namespace or URI
1218     * @param body the suggested replacement string
1219     * @param offset the location of the curstor in the document at the time of
1220     *        the content assist invocation.
1221     * @return a Completion Proposal populated in the style defined by
1222     *         <code>proposalType</code>, containing the information specified
1223     *         by the other parameters.
1224     */
1225    private ICompletionProposal makeProposal(int proposalType,
1226       String alreadyTyped, String namespace, ISuggestionCandidate body,
1227       int offset)
1228    {
1229       ICompletionProposal toReturn = null;
1230       String imageString = OWLImages.IMG_UNPARSEABLE;
1231       Image icon = null;
1232       String suggestionString = null;
1233       int cursorPosition = 0;
1234       String alternateText = null;
1235 
1236       if(proposalType == ATTRIBUTE_PROPOSAL)
1237       {
1238          imageString = OWLImages.IMG_ATTRIB_OBJ;
1239          suggestionString = body.getName() + "=\"\"";
1240          if(namespace.length() > 0)
1241          {
1242             suggestionString = namespace + ":" + suggestionString;
1243          }
1244          cursorPosition = suggestionString.length() - 1;
1245          toReturn = new CompletionProposal(suggestionString, offset
1246             - alreadyTyped.length(), alreadyTyped.length(), cursorPosition,
1247             OWLImages.getSharedImage(imageString), null, null, null);
1248       }
1249       if(proposalType == NAMESPACE_PROPOSAL)
1250       {
1251          suggestionString = "<" + body.getName();
1252          cursorPosition = suggestionString.length();
1253          imageString = OWLImages.IMG_ONTOLOGY;
1254          toReturn = new CompletionProposal(suggestionString, offset
1255             - alreadyTyped.length(), alreadyTyped.length(), cursorPosition,
1256             OWLImages.getSharedImage(imageString), null, null, null);
1257       }
1258       if(proposalType == TAG_PROPOSAL)
1259       {
1260          imageString = (body.getType() == ISuggestionCandidate.CLASS) ? OWLImages.IMG_CLASS_OBJ
1261             : (body.getType() == ISuggestionCandidate.PROPERTY) ? OWLImages.IMG_PROP_OBJ
1262                : OWLImages.IMG_THING;
1263          suggestionString = "<"
1264             + ((namespace.length() > 0) ? namespace + ":" : "")
1265             + body.getName() + "></"
1266             + ((namespace.length() > 0) ? namespace + ":" : "")
1267             + body.getName() + ">";
1268          cursorPosition = suggestionString.length() / 2 - 1;
1269          alternateText = suggestionString.replaceAll("\n", "");
1270          toReturn = new CompletionProposal(suggestionString, offset
1271             - alreadyTyped.length(), alreadyTyped.length(), cursorPosition,
1272             OWLImages.getSharedImage(imageString), alternateText, null, null);
1273       }
1274       if(proposalType == SINGLETON_TAG_PROPOSAL)
1275       {
1276          imageString = (body.getType() == ISuggestionCandidate.CLASS) ? OWLImages.IMG_CLASS_OBJ
1277             : (body.getType() == ISuggestionCandidate.PROPERTY) ? OWLImages.IMG_PROP_OBJ
1278                : OWLImages.IMG_THING;
1279          suggestionString = "<"
1280             + ((namespace.length() > 0) ? namespace + ":" : "")
1281             + body.getName() + " />";
1282          cursorPosition = suggestionString.length() - 2;
1283          toReturn = new CompletionProposal(suggestionString, offset
1284             - alreadyTyped.length(), alreadyTyped.length(), cursorPosition,
1285             OWLImages.getSharedImage(imageString), alternateText, null, null);
1286       }
1287       if(proposalType == POUND_PROPOSAL)
1288       {
1289          imageString = (body.getType() == ISuggestionCandidate.CLASS) ? OWLImages.IMG_CLASS_OBJ
1290             : (body.getType() == ISuggestionCandidate.PROPERTY) ? OWLImages.IMG_PROP_OBJ
1291                : OWLImages.IMG_OWL_INST;
1292          suggestionString = (alreadyTyped.startsWith("\"") ? "\"" : "")
1293             + namespace + "#" + body.getName();
1294          cursorPosition = suggestionString.length();
1295          toReturn = new CompletionProposal(suggestionString, offset
1296             - alreadyTyped.length(), alreadyTyped.length(), cursorPosition,
1297             OWLImages.getSharedImage(imageString), body.getName(), null, null);
1298       }
1299       if(proposalType == URI_PROPOSAL)
1300       {
1301          imageString = OWLImages.IMG_ONTOLOGY;
1302          suggestionString = (alreadyTyped.startsWith("\"") ? "\"" : "")
1303             + body.getName();
1304          // if there's an end quote on the suggestion, move the cursor back so
1305          // that it
1306          // appears before the end quote...
1307          cursorPosition = body.getName().endsWith("\"") ? suggestionString
1308             .length() - 1 : suggestionString.length();
1309          if(alreadyTyped.startsWith("\""))
1310          {
1311             // take the end quote off of a suggestions displayed text if we're
1312             // going to add it
1313             alternateText = body.getName().endsWith("\"") ? body.getName()
1314                .substring(0, body.getName().length() - 1) : body.getName();
1315          }
1316          toReturn = new CompletionProposal(suggestionString, offset
1317             - alreadyTyped.length(), alreadyTyped.length(), cursorPosition,
1318             OWLImages.getSharedImage(imageString), alternateText, null, null);
1319       }
1320 
1321       return toReturn;
1322    }
1323 
1324    /***
1325     * This method populates the processor with namespaces and suggesters, and
1326     * hooks it into the OAST of the current document so that it will be able to
1327     * stay current.
1328     */
1329    private void init()
1330    {
1331       OASTNode[] namespaces = null;
1332       Namespace tempNode = null;
1333 
1334       
1335       _mapURIToSuggester.put(OASTNode.S_OWL_URI, new OWLNamespaceSuggester());
1336       _mapURIToSuggester.put(OASTNode.S_RDF_URI, new RDFNamespaceSuggester());
1337       _mapURIToSuggester.put(OASTNode.S_RDFS_URI, new RDFSNamespaceSuggester());
1338       
1339       _mapURIToSuggester.put(OASTNode.S_XSD_URI,
1340          new XSDNamespaceSuggester());
1341 
1342       _namespaceToURI.setBaseURI(_tree.getBaseURI());
1343       _mapURIToSuggester.put(_tree.getBaseURI(), new DefaultNamespaceSuggester(
1344          _tree));
1345       namespaces = _tree.getRoot().getNodesOfType(OASTNode.NAMESPACE);
1346       for (int i = 0; i < namespaces.length; i++)
1347       {
1348          tempNode = (Namespace)namespaces[i];
1349          if(!_mapURIToSuggester.keySet().contains(
1350             (tempNode.getValue().replaceAll("#", ""))))
1351          {
1352             addNamespace(tempNode.getAbbreviation(), tempNode.getValue()
1353                .replaceAll("#", ""));
1354          }
1355          if(!_namespaceToURI.getAllNamespaces().contains(
1356             tempNode.getAbbreviation()))
1357          {
1358             _namespaceToURI.addNamespace(tempNode);
1359          }
1360       }
1361    }
1362 
1363    /***
1364     * As per IContentAssistProcessor. In this implementation, this method does
1365     * nothing and returns null.
1366     * 
1367     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(
1368     *    org.eclipse.jface.text.ITextViewer,int)
1369     */
1370    public IContextInformation[] computeContextInformation(ITextViewer viewer,
1371       int offset)
1372    {
1373       return null;
1374    }
1375 
1376    /***
1377     * As per IContentAssistProcessor. In this implementation, returns ['#',
1378     * '&gt;', ':', '"']
1379     * 
1380     * 
1381     * 
1382     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
1383     */
1384    public char[] getCompletionProposalAutoActivationCharacters()
1385    {
1386       return new char[] {'#', '<', ':', '"'};
1387    }
1388 
1389    /***
1390     * As per IContentAssistProcessor. In this implementation, this method does
1391     * nothing and returns null.
1392     * 
1393     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
1394     */
1395    public char[] getContextInformationAutoActivationCharacters()
1396    {
1397       // we don't do context information, so we return null...
1398       return null;
1399    }
1400 
1401    /***
1402     * As per IContentAssistProcessor. In this implementation, this method does
1403     * nothing and returns null.
1404     * 
1405     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
1406     */
1407    public IContextInformationValidator getContextInformationValidator()
1408    {
1409       // we don't do context information, so we return null...
1410       return null;
1411    }
1412 
1413    /***
1414     * As per IContentAssistProcessor. In this implementation, this method does
1415     * nothing and returns null.
1416     * 
1417     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
1418     */
1419    public String getErrorMessage()
1420    {
1421       return null;
1422    }
1423 
1424 }