tags:

views:

130

answers:

1

So, I'm working on a plugin at work and I've run into a situation where I could use a ContentProposalAdapter to my benefit. Basically, a person will start typing in someone's name and then a list of names matching the current query will be returned in a type-ahead manner (a la Google). So, I created a class IContentProposalProvider which, upon calling it's getProposals() method fires off a thread which handles getting the proposals in the background. The problem I am having is that I run into a race condition, where the processing for getting the proposals via HTTP happens and I try to get the proposals before they have actually been retrieved.

Now, I'm trying not to run into an issue of Thread hell, and that isn't getting me very far anyway. So, here is what I've done so far. Does anyone have any suggestions as to what I can do?

public class ProfilesProposalProvider implements IContentProposalProvider, PropertyChangeListener {

     private IContentProposal[] props;

     @Override
     public IContentProposal[] getProposals(String arg0, int arg1) {
      Display display = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getDisplay();

      RunProfilesJobThread t1 = new RunProfilesJobThread(arg0, display);
      t1.run();

      return props;
     }

     @Override
     public void propertyChange(PropertyChangeEvent arg0) {
      if (arg0.getSource() instanceof RunProfilesJobThread){
       RunProfilesJobThread thread = (RunProfilesJobThread)arg0.getSource();
       props = thread.getProps();

      }
     }
    }



public class RunProfilesJobThread extends Thread {

 private ProfileProposal[] props;
 private Display display;
 private String query;

 public RunProfilesJobThread(String query, Display display){
  this.query = query;
 }

 @Override
 public void run() {
  if (!(query.equals(""))){
   GetProfilesJob job = new GetProfilesJob("profiles", query);
   job.schedule();

   try {
    job.join();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }

   GetProfilesJobInfoThread thread = new GetProfilesJobInfoThread(job.getResults());

   try {
    thread.join();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }


   props = thread.getProps();
  }
 }

 public ProfileProposal[] getProps(){
  return props;
 }
}

public class GetProfilesJobInfoThread extends Thread {

     private ArrayList<String> names;
     private ProfileProposal[] props;

     public GetProfilesJobInfoThread(ArrayList<String> names){
      this.names = names;
     }

     @Override
     public void run() {
      if (names != null){
       props = new ProfileProposal[names.size()];
       for (int i = 0; i < props.length - 1; i++){
        ProfileProposal temp = new ProfileProposal(names.get(i), names.get(i));
        props[i] = temp;
       }
      }
     }

     public ProfileProposal[] getProps(){
      return props;
     }
    }
A: 

Ok, i'll try it...

I haven't tried to run it, but it should work more or less. At least it's a good start. If you have any questions, feel free to ask.

public class ProfilesProposalProvider implements IContentProposalProvider {
 private List<IContentProposal> proposals;
 private String proposalQuery;
 private Thread retrievalThread;

 public void setProposals( List<IContentProposal> proposals, String query ) {
  synchronized( this ) {
   this.proposals = proposals;
   this.proposalQuery = query;
  }
 }

 public IContentProposal[] getProposals( String contents, int position ) {
  // Synchronize incoming thread and retrieval thread, so that the proposal list
  // is not replaced while we're processing it.
  synchronized( this ) {
   /**
    * Get proposals if query is longer than one char, or if the current list of proposals does with a different
    * prefix than the new query, and only if the current retrieval thread is finished.
    */
   if ( retrievalThread == null && contents.length() > 1 && ( proposals == null || !contents.startsWith( proposalQuery ) ) ) {
    getProposals( contents );
   }

   /**
    * Select valid proposals from retrieved list.
    */
   if ( proposals != null ) {
    List<IContentProposal> validProposals = new ArrayList<IContentProposal>();
    for ( IContentProposal prop : proposals ) {
     if(prop == null) {
      continue;
     }
     String propVal = prop.getContent();
     if ( isProposalValid( propVal, contents )) {
      validProposals.add( prop );
     }
    }
    return validProposals.toArray( new IContentProposal[ validProposals.size() ] );
   }
  }

  return new IContentProposal[0];
 }

 protected void getProposals( final String query ) {
  retrievalThread = new Thread() {
   @Override
   public void run() {
    GetProfilesJob job = new GetProfilesJob("profiles", query);
    job.schedule();

    try {
     job.join();

     ArrayList<String> names = job.getResults();
     if (names != null){
      List<IContentProposal> props = new ArrayList<IContentProposal>();
         for ( String name : names ) {
          props.add( new ProfileProposal( name, name ) );
         }
         setProposals( props, query );
     }
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    retrievalThread = null;
   }
  };
  retrievalThread.start();
 }

 protected boolean isProposalValid( String proposalValue, String contents ) {
  return ( proposalValue.length() >= contents.length() && proposalValue.substring(0, contents.length()).equalsIgnoreCase(contents));
 }
}
derBiggi