Trying to make the remote Go to Type/Symbol query less intrusive.
authorJan Lahoda <jlahoda@netbeans.org>
Thu, 14 Jul 2011 23:03:50 +0200
changeset 638f1d1f902538a
parent 637 30f9ba213e1a
child 639 b4a40c115309
Trying to make the remote Go to Type/Symbol query less intrusive.
remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/AbstractDescriptor.java
remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteGoToSymbol.java
remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteGoToType.java
remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteQuery.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/AbstractDescriptor.java	Thu Jul 14 23:03:50 2011 +0200
     1.3 @@ -0,0 +1,118 @@
     1.4 +/*
     1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 + *
     1.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
     1.8 + *
     1.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    1.10 + * Other names may be trademarks of their respective owners.
    1.11 + *
    1.12 + * The contents of this file are subject to the terms of either the GNU
    1.13 + * General Public License Version 2 only ("GPL") or the Common
    1.14 + * Development and Distribution License("CDDL") (collectively, the
    1.15 + * "License"). You may not use this file except in compliance with the
    1.16 + * License. You can obtain a copy of the License at
    1.17 + * http://www.netbeans.org/cddl-gplv2.html
    1.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.19 + * specific language governing permissions and limitations under the
    1.20 + * License.  When distributing the software, include this License Header
    1.21 + * Notice in each file and include the License file at
    1.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    1.23 + * particular file as subject to the "Classpath" exception as provided
    1.24 + * by Oracle in the GPL Version 2 section of the License file that
    1.25 + * accompanied this code. If applicable, add the following below the
    1.26 + * License Header, with the fields enclosed by brackets [] replaced by
    1.27 + * your own identifying information:
    1.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    1.29 + *
    1.30 + * If you wish your version of this file to be governed by only the CDDL
    1.31 + * or only the GPL Version 2, indicate your decision by adding
    1.32 + * "[Contributor] elects to include this software in this distribution
    1.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.34 + * single choice of license, a recipient has the option to distribute
    1.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    1.36 + * to extend the choice of license to its licensees as provided above.
    1.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    1.38 + * Version 2 license, then the option applies only if the new code is
    1.39 + * made subject to such option by the copyright holder.
    1.40 + *
    1.41 + * Contributor(s):
    1.42 + *
    1.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    1.44 + */
    1.45 +package org.netbeans.modules.jackpot30.jumpto;
    1.46 +
    1.47 +import java.util.concurrent.atomic.AtomicReference;
    1.48 +import javax.swing.Icon;
    1.49 +import org.netbeans.api.project.FileOwnerQuery;
    1.50 +import org.netbeans.api.project.Project;
    1.51 +import org.netbeans.api.project.ProjectUtils;
    1.52 +import org.openide.filesystems.FileObject;
    1.53 +
    1.54 +/**
    1.55 + *
    1.56 + * @author lahvac
    1.57 + */
    1.58 +public abstract class AbstractDescriptor {
    1.59 +
    1.60 +    private final AtomicReference<String> displayName = new AtomicReference<String>();
    1.61 +    private final AtomicReference<FileObject> file = new AtomicReference<FileObject>();
    1.62 +
    1.63 +    protected AbstractDescriptor() {
    1.64 +    }
    1.65 +
    1.66 +    public String getProjectName() {
    1.67 +        String displayName = this.displayName.get();
    1.68 +
    1.69 +        if (displayName != null) {
    1.70 +            return displayName;
    1.71 +        }
    1.72 +
    1.73 +        FileObject file = getFileObject();
    1.74 +
    1.75 +        if (file == null) {
    1.76 +            return null;
    1.77 +        }
    1.78 +
    1.79 +        Project prj = FileOwnerQuery.getOwner(file);
    1.80 +
    1.81 +        if (prj == null) {
    1.82 +            return null;
    1.83 +        }
    1.84 +
    1.85 +        this.displayName.set(displayName = ProjectUtils.getInformation(prj).getDisplayName());
    1.86 +
    1.87 +        return displayName;
    1.88 +    }
    1.89 +
    1.90 +    public Icon getProjectIcon() {
    1.91 +        FileObject file = getFileObject();
    1.92 +
    1.93 +        if (file == null) {
    1.94 +            return null;
    1.95 +        }
    1.96 +
    1.97 +        Project prj = FileOwnerQuery.getOwner(file);
    1.98 +
    1.99 +        if (prj == null) {
   1.100 +            return null;
   1.101 +        }
   1.102 +
   1.103 +        return ProjectUtils.getInformation(prj).getIcon();
   1.104 +    }
   1.105 +
   1.106 +    public FileObject getFileObject() {
   1.107 +        FileObject f = this.file.get();
   1.108 +
   1.109 +        if (f == null) {
   1.110 +            f = resolveFile();
   1.111 +            
   1.112 +            if (f != null) {
   1.113 +                this.file.set(f);
   1.114 +            }
   1.115 +        }
   1.116 +
   1.117 +        return f;
   1.118 +    }
   1.119 +
   1.120 +    protected abstract FileObject resolveFile();
   1.121 +}
     2.1 --- a/remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteGoToSymbol.java	Thu Jul 14 15:29:41 2011 +0200
     2.2 +++ b/remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteGoToSymbol.java	Thu Jul 14 23:03:50 2011 +0200
     2.3 @@ -44,7 +44,7 @@
     2.4  import java.io.File;
     2.5  import java.net.URI;
     2.6  import java.net.URISyntaxException;
     2.7 -import java.util.Arrays;
     2.8 +import java.util.ArrayList;
     2.9  import java.util.Collection;
    2.10  import java.util.EnumSet;
    2.11  import java.util.HashSet;
    2.12 @@ -53,7 +53,6 @@
    2.13  import java.util.Map;
    2.14  import java.util.Map.Entry;
    2.15  import java.util.Set;
    2.16 -import java.util.concurrent.atomic.AtomicReference;
    2.17  import javax.lang.model.element.ElementKind;
    2.18  import javax.lang.model.element.Modifier;
    2.19  import javax.swing.Icon;
    2.20 @@ -62,17 +61,14 @@
    2.21  import org.netbeans.api.java.source.ElementHandle;
    2.22  import org.netbeans.api.java.source.ui.ElementIcons;
    2.23  import org.netbeans.api.java.source.ui.ElementOpen;
    2.24 -import org.netbeans.api.project.FileOwnerQuery;
    2.25 -import org.netbeans.api.project.Project;
    2.26 -import org.netbeans.api.project.ProjectUtils;
    2.27 +import org.netbeans.modules.jackpot30.jumpto.RemoteGoToSymbol.RemoteSymbolDescriptor;
    2.28 +import org.netbeans.modules.jackpot30.jumpto.RemoteQuery.SimpleNameable;
    2.29  import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
    2.30  import org.netbeans.modules.jackpot30.remoting.api.WebUtilities;
    2.31  import org.netbeans.modules.java.source.ElementHandleAccessor;
    2.32 -import org.netbeans.modules.java.source.usages.ClassFileUtil;
    2.33  import org.netbeans.spi.jumpto.symbol.SymbolDescriptor;
    2.34  import org.netbeans.spi.jumpto.symbol.SymbolProvider;
    2.35 -import org.netbeans.spi.jumpto.type.TypeDescriptor;
    2.36 -import org.netbeans.spi.jumpto.type.TypeProvider;
    2.37 +import org.netbeans.spi.jumpto.type.SearchType;
    2.38  import org.openide.filesystems.FileObject;
    2.39  import org.openide.filesystems.FileUtil;
    2.40  import org.openide.util.Exceptions;
    2.41 @@ -83,7 +79,7 @@
    2.42   * @author lahvac
    2.43   */
    2.44  @ServiceProvider(service=SymbolProvider.class)
    2.45 -public class RemoteGoToSymbol implements SymbolProvider {
    2.46 +public class RemoteGoToSymbol extends RemoteQuery<RemoteSymbolDescriptor> implements SymbolProvider {
    2.47  
    2.48      @Override
    2.49      public String name() {
    2.50 @@ -96,10 +92,22 @@
    2.51      }
    2.52  
    2.53      @Override
    2.54 -    public void computeSymbolNames(Context context, Result result) {
    2.55 +    public void computeSymbolNames(Context context, final Result result) {
    2.56 +        performQuery(context.getText(), context.getSearchType(), new ResultWrapper<RemoteSymbolDescriptor>() {
    2.57 +            @Override public void setMessage(String message) {
    2.58 +                result.setMessage(message);
    2.59 +            }
    2.60 +            @Override public void addResult(RemoteSymbolDescriptor r) {
    2.61 +                result.addResult(r);
    2.62 +            }
    2.63 +        });
    2.64 +    }
    2.65 +
    2.66 +    @Override
    2.67 +    protected void compute(String text, SearchType searchType) {
    2.68          for (RemoteIndex ri : RemoteIndex.loadIndices()) {
    2.69              try {
    2.70 -                URI resolved = new URI(ri.remote.toExternalForm() + "/symbol/search?path=" + WebUtilities.escapeForQuery(ri.remoteSegment) + "&prefix=" + WebUtilities.escapeForQuery(context.getText()) + "&querykind=" + WebUtilities.escapeForQuery(context.getSearchType().name()));
    2.71 +                URI resolved = new URI(ri.remote.toExternalForm() + "/symbol/search?path=" + WebUtilities.escapeForQuery(ri.remoteSegment) + "&prefix=" + WebUtilities.escapeForQuery(text) + "&querykind=" + WebUtilities.escapeForQuery(searchType.name()));
    2.72                  String response = WebUtilities.requestStringResponse(resolved);
    2.73  
    2.74                  if (response == null) continue;
    2.75 @@ -107,34 +115,37 @@
    2.76                  @SuppressWarnings("unchecked") //XXX: should not trust something got from the network!
    2.77                  Map<String, Iterable<Map<String, Object>>> types = Pojson.load(LinkedHashMap.class, response);
    2.78  
    2.79 +                List<RemoteSymbolDescriptor> result = new ArrayList<RemoteSymbolDescriptor>();
    2.80 +
    2.81                  for (Entry<String, Iterable<Map<String, Object>>> e : types.entrySet()) {
    2.82                      for (Map<String, Object> properties : e.getValue()) {
    2.83 -                        result.addResult(new RemoteSymbolDescriptor(ri, properties));
    2.84 +                        result.add(new RemoteSymbolDescriptor(ri, properties));
    2.85                      }
    2.86                  }
    2.87 +
    2.88 +                addResults(result);
    2.89              } catch (URISyntaxException ex) {
    2.90                  Exceptions.printStackTrace(ex);
    2.91              }
    2.92          }
    2.93      }
    2.94  
    2.95 -    @Override
    2.96 -    public void cancel() {
    2.97 -    }
    2.98 +    static final class RemoteSymbolDescriptor extends SymbolDescriptor implements SimpleNameable {
    2.99  
   2.100 -    @Override
   2.101 -    public void cleanup() {
   2.102 -    }
   2.103 +        private final Map<String, Object> properties;
   2.104 +        private final AbstractDescriptor delegate;
   2.105  
   2.106 -    static final class RemoteSymbolDescriptor extends SymbolDescriptor {
   2.107 +        public RemoteSymbolDescriptor(final RemoteIndex origin, final Map<String, Object> properties) {
   2.108 +            this.properties = properties;
   2.109 +            this.delegate = new AbstractDescriptor() {
   2.110 +                @Override
   2.111 +                protected FileObject resolveFile() {
   2.112 +                    String relativePath = (String) properties.get("file");
   2.113 +                    FileObject originFolder = FileUtil.toFileObject(FileUtil.normalizeFile(new File(origin.folder)));
   2.114  
   2.115 -        private final RemoteIndex origin;
   2.116 -        private final Map<String, Object> properties;
   2.117 -        private final AtomicReference<FileObject> file = new AtomicReference<FileObject>();
   2.118 -
   2.119 -        public RemoteSymbolDescriptor(RemoteIndex origin, Map<String, Object> properties) {
   2.120 -            this.origin = origin;
   2.121 -            this.properties = properties;
   2.122 +                    return originFolder != null ? originFolder.getFileObject(relativePath) : null;
   2.123 +                }
   2.124 +            };
   2.125          }
   2.126  
   2.127          @Override
   2.128 @@ -168,43 +179,17 @@
   2.129  
   2.130          @Override
   2.131          public String getProjectName() {
   2.132 -            FileObject file = getFileObject();
   2.133 -
   2.134 -            if (file == null) return null;
   2.135 -
   2.136 -            Project prj = FileOwnerQuery.getOwner(file);
   2.137 -
   2.138 -            if (prj == null) return null;
   2.139 -
   2.140 -            return ProjectUtils.getInformation(prj).getDisplayName();
   2.141 +            return delegate.getProjectName();
   2.142          }
   2.143  
   2.144          @Override
   2.145          public Icon getProjectIcon() {
   2.146 -            FileObject file = getFileObject();
   2.147 -
   2.148 -            if (file == null) return null;
   2.149 -
   2.150 -            Project prj = FileOwnerQuery.getOwner(file);
   2.151 -
   2.152 -            if (prj == null) return null;
   2.153 -
   2.154 -            return ProjectUtils.getInformation(prj).getIcon();
   2.155 +            return delegate.getProjectIcon();
   2.156          }
   2.157  
   2.158          @Override
   2.159          public FileObject getFileObject() {
   2.160 -            FileObject f = this.file.get();
   2.161 -
   2.162 -            if (f == null) {
   2.163 -                String relativePath = (String) properties.get("file");
   2.164 -                FileObject originFolder = FileUtil.toFileObject(FileUtil.normalizeFile(new File(origin.folder)));
   2.165 -
   2.166 -                if (originFolder != null) f = originFolder.getFileObject(relativePath);
   2.167 -                if (f != null) this.file.set(f);
   2.168 -            }
   2.169 -
   2.170 -            return f;
   2.171 +            return delegate.getFileObject();
   2.172          }
   2.173  
   2.174          @Override
   2.175 @@ -242,6 +227,11 @@
   2.176              return (String) properties.get("enclosingFQN");
   2.177          }
   2.178  
   2.179 +        @Override
   2.180 +        public String getSimpleName() {
   2.181 +            return (String) properties.get("simpleName");
   2.182 +        }
   2.183 +
   2.184      }
   2.185  
   2.186      private static char getChar (final String buffer, final int pos) {
     3.1 --- a/remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteGoToType.java	Thu Jul 14 15:29:41 2011 +0200
     3.2 +++ b/remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteGoToType.java	Thu Jul 14 23:03:50 2011 +0200
     3.3 @@ -44,12 +44,12 @@
     3.4  import java.io.File;
     3.5  import java.net.URI;
     3.6  import java.net.URISyntaxException;
     3.7 +import java.util.ArrayList;
     3.8  import java.util.EnumSet;
     3.9  import java.util.LinkedHashMap;
    3.10  import java.util.List;
    3.11  import java.util.Map;
    3.12  import java.util.Map.Entry;
    3.13 -import java.util.concurrent.atomic.AtomicReference;
    3.14  import javax.lang.model.element.ElementKind;
    3.15  import javax.lang.model.element.Modifier;
    3.16  import javax.swing.Icon;
    3.17 @@ -58,12 +58,12 @@
    3.18  import org.netbeans.api.java.source.ElementHandle;
    3.19  import org.netbeans.api.java.source.ui.ElementIcons;
    3.20  import org.netbeans.api.java.source.ui.ElementOpen;
    3.21 -import org.netbeans.api.project.FileOwnerQuery;
    3.22 -import org.netbeans.api.project.Project;
    3.23 -import org.netbeans.api.project.ProjectUtils;
    3.24 +import org.netbeans.modules.jackpot30.jumpto.RemoteGoToType.RemoteTypeDescriptor;
    3.25 +import org.netbeans.modules.jackpot30.jumpto.RemoteQuery.SimpleNameable;
    3.26  import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
    3.27  import org.netbeans.modules.jackpot30.remoting.api.WebUtilities;
    3.28  import org.netbeans.modules.java.source.ElementHandleAccessor;
    3.29 +import org.netbeans.spi.jumpto.type.SearchType;
    3.30  import org.netbeans.spi.jumpto.type.TypeDescriptor;
    3.31  import org.netbeans.spi.jumpto.type.TypeProvider;
    3.32  import org.openide.filesystems.FileObject;
    3.33 @@ -76,7 +76,7 @@
    3.34   * @author lahvac
    3.35   */
    3.36  @ServiceProvider(service=TypeProvider.class)
    3.37 -public class RemoteGoToType implements TypeProvider {
    3.38 +public class RemoteGoToType extends RemoteQuery<RemoteTypeDescriptor> implements TypeProvider {
    3.39  
    3.40      @Override
    3.41      public String name() {
    3.42 @@ -89,10 +89,23 @@
    3.43      }
    3.44  
    3.45      @Override
    3.46 -    public void computeTypeNames(Context context, Result result) {
    3.47 +    public void computeTypeNames(Context context, final Result result) {
    3.48 +        performQuery(context.getText(), context.getSearchType(), new ResultWrapper<RemoteTypeDescriptor>() {
    3.49 +            @Override public void setMessage(String message) {
    3.50 +                result.setMessage(message);
    3.51 +            }
    3.52 +            @Override public void addResult(RemoteTypeDescriptor r) {
    3.53 +                result.addResult(r);
    3.54 +            }
    3.55 +        });
    3.56 +    }
    3.57 +
    3.58 +    @Override
    3.59 +    protected void compute(String text, SearchType searchType) {
    3.60          for (RemoteIndex ri : RemoteIndex.loadIndices()) {
    3.61              try {
    3.62 -                URI resolved = new URI(ri.remote.toExternalForm() + "/type/search?path=" + WebUtilities.escapeForQuery(ri.remoteSegment) + "&prefix=" + WebUtilities.escapeForQuery(context.getText()));
    3.63 +                //XXX: should send exact search type:
    3.64 +                URI resolved = new URI(ri.remote.toExternalForm() + "/type/search?path=" + WebUtilities.escapeForQuery(ri.remoteSegment) + "&prefix=" + WebUtilities.escapeForQuery(text));
    3.65                  String response = WebUtilities.requestStringResponse(resolved);
    3.66  
    3.67                  if (response == null) continue;
    3.68 @@ -100,36 +113,43 @@
    3.69                  @SuppressWarnings("unchecked") //XXX: should not trust something got from the network!
    3.70                  Map<String, List<String>> types = Pojson.load(LinkedHashMap.class, response);
    3.71  
    3.72 +                List<RemoteTypeDescriptor> result = new ArrayList<RemoteTypeDescriptor>();
    3.73 +
    3.74                  for (Entry<String, List<String>> e : types.entrySet()) {
    3.75                      for (String binaryName : e.getValue()) {
    3.76 -                        result.addResult(new RemoteTypeDescriptor(ri, e.getKey(), binaryName));
    3.77 +                        result.add(new RemoteTypeDescriptor(ri, e.getKey(), binaryName));
    3.78                      }
    3.79                  }
    3.80 +
    3.81 +                addResults(result);
    3.82              } catch (URISyntaxException ex) {
    3.83                  Exceptions.printStackTrace(ex);
    3.84              }
    3.85          }
    3.86      }
    3.87  
    3.88 -    @Override
    3.89 -    public void cancel() {
    3.90 -    }
    3.91 +    static final class RemoteTypeDescriptor extends TypeDescriptor implements SimpleNameable {
    3.92  
    3.93 -    @Override
    3.94 -    public void cleanup() {
    3.95 -    }
    3.96 +        private final String binaryName;
    3.97 +        private final AbstractDescriptor delegate;
    3.98  
    3.99 -    private static final class RemoteTypeDescriptor extends TypeDescriptor {
   3.100 +        public RemoteTypeDescriptor(final RemoteIndex origin, final String relativePath, final String binaryName) {
   3.101 +            this.binaryName = binaryName;
   3.102  
   3.103 -        private final RemoteIndex origin;
   3.104 -        private final String relativePath;
   3.105 -        private final String binaryName;
   3.106 -        private final AtomicReference<FileObject> file = new AtomicReference<FileObject>();
   3.107 +            delegate = new AbstractDescriptor() {
   3.108 +                @Override
   3.109 +                protected FileObject resolveFile() {
   3.110 +                    String fqn = binaryName;
   3.111  
   3.112 -        public RemoteTypeDescriptor(RemoteIndex origin, String relativePath, String binaryName) {
   3.113 -            this.origin = origin;
   3.114 -            this.relativePath = relativePath;
   3.115 -            this.binaryName = binaryName;
   3.116 +                    if (fqn.contains("$")) {
   3.117 +                        fqn = fqn.substring(0, fqn.indexOf("$"));
   3.118 +                    }
   3.119 +
   3.120 +                    FileObject originFolder = FileUtil.toFileObject(FileUtil.normalizeFile(new File(origin.folder)));
   3.121 +
   3.122 +                    return originFolder != null ? originFolder.getFileObject(relativePath + "/" + fqn.replace('.', '/') + ".java") : null;
   3.123 +                }
   3.124 +            };
   3.125          }
   3.126  
   3.127          @Override
   3.128 @@ -177,48 +197,17 @@
   3.129  
   3.130          @Override
   3.131          public String getProjectName() {
   3.132 -            FileObject file = getFileObject();
   3.133 -
   3.134 -            if (file == null) return null;
   3.135 -
   3.136 -            Project prj = FileOwnerQuery.getOwner(file);
   3.137 -
   3.138 -            if (prj == null) return null;
   3.139 -
   3.140 -            return ProjectUtils.getInformation(prj).getDisplayName();
   3.141 +            return delegate.getProjectName();
   3.142          }
   3.143  
   3.144          @Override
   3.145          public Icon getProjectIcon() {
   3.146 -            FileObject file = getFileObject();
   3.147 -
   3.148 -            if (file == null) return null;
   3.149 -
   3.150 -            Project prj = FileOwnerQuery.getOwner(file);
   3.151 -
   3.152 -            if (prj == null) return null;
   3.153 -
   3.154 -            return ProjectUtils.getInformation(prj).getIcon();
   3.155 +            return delegate.getProjectIcon();
   3.156          }
   3.157  
   3.158          @Override
   3.159          public FileObject getFileObject() {
   3.160 -            FileObject f = this.file.get();
   3.161 -
   3.162 -            if (f == null) {
   3.163 -                String fqn = binaryName;
   3.164 -
   3.165 -                if (fqn.contains("$")) {
   3.166 -                    fqn = fqn.substring(0, fqn.indexOf("$"));
   3.167 -                }
   3.168 -
   3.169 -                FileObject originFolder = FileUtil.toFileObject(FileUtil.normalizeFile(new File(origin.folder)));
   3.170 -
   3.171 -                if (originFolder != null) f = originFolder.getFileObject(relativePath + "/" + fqn.replace('.', '/') + ".java");
   3.172 -                if (f != null) this.file.set(f);
   3.173 -            }
   3.174 -
   3.175 -            return f;
   3.176 +            return delegate.getFileObject();
   3.177          }
   3.178  
   3.179          @Override
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/remoting/ide/jumpto/src/org/netbeans/modules/jackpot30/jumpto/RemoteQuery.java	Thu Jul 14 23:03:50 2011 +0200
     4.3 @@ -0,0 +1,136 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
     4.8 + *
     4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    4.10 + * Other names may be trademarks of their respective owners.
    4.11 + *
    4.12 + * The contents of this file are subject to the terms of either the GNU
    4.13 + * General Public License Version 2 only ("GPL") or the Common
    4.14 + * Development and Distribution License("CDDL") (collectively, the
    4.15 + * "License"). You may not use this file except in compliance with the
    4.16 + * License. You can obtain a copy of the License at
    4.17 + * http://www.netbeans.org/cddl-gplv2.html
    4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    4.19 + * specific language governing permissions and limitations under the
    4.20 + * License.  When distributing the software, include this License Header
    4.21 + * Notice in each file and include the License file at
    4.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    4.23 + * particular file as subject to the "Classpath" exception as provided
    4.24 + * by Oracle in the GPL Version 2 section of the License file that
    4.25 + * accompanied this code. If applicable, add the following below the
    4.26 + * License Header, with the fields enclosed by brackets [] replaced by
    4.27 + * your own identifying information:
    4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    4.29 + *
    4.30 + * If you wish your version of this file to be governed by only the CDDL
    4.31 + * or only the GPL Version 2, indicate your decision by adding
    4.32 + * "[Contributor] elects to include this software in this distribution
    4.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    4.34 + * single choice of license, a recipient has the option to distribute
    4.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    4.36 + * to extend the choice of license to its licensees as provided above.
    4.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    4.38 + * Version 2 license, then the option applies only if the new code is
    4.39 + * made subject to such option by the copyright holder.
    4.40 + *
    4.41 + * Contributor(s):
    4.42 + *
    4.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    4.44 + */
    4.45 +package org.netbeans.modules.jackpot30.jumpto;
    4.46 +
    4.47 +import java.util.ArrayList;
    4.48 +import java.util.Collection;
    4.49 +import java.util.List;
    4.50 +import java.util.logging.Level;
    4.51 +import java.util.logging.Logger;
    4.52 +import org.netbeans.modules.jackpot30.jumpto.RemoteQuery.SimpleNameable;
    4.53 +import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
    4.54 +import org.netbeans.spi.jumpto.support.NameMatcher;
    4.55 +import org.netbeans.spi.jumpto.support.NameMatcherFactory;
    4.56 +import org.netbeans.spi.jumpto.type.SearchType;
    4.57 +import org.openide.util.RequestProcessor;
    4.58 +import org.openide.util.RequestProcessor.Task;
    4.59 +
    4.60 +/**
    4.61 + *
    4.62 + * @author lahvac
    4.63 + */
    4.64 +public abstract class RemoteQuery<R extends SimpleNameable> {
    4.65 +
    4.66 +    private static final RequestProcessor WORKER = new RequestProcessor(RemoteGoToType.class.getName(), 1, true, false);
    4.67 +
    4.68 +    private String mostGenericQueryText;
    4.69 +    private List<R> results;
    4.70 +    private Task currentWorker;
    4.71 +
    4.72 +    protected final void performQuery(final String text, final SearchType searchType, ResultWrapper<R> result) {
    4.73 +        if (!RemoteIndex.loadIndices().iterator().hasNext()) return; //TODO: optimize!
    4.74 +
    4.75 +        synchronized (this) {
    4.76 +            if (mostGenericQueryText == null || !text.startsWith(mostGenericQueryText)) {
    4.77 +                if (currentWorker != null) currentWorker.cancel();
    4.78 +
    4.79 +                mostGenericQueryText = text;
    4.80 +
    4.81 +                currentWorker = WORKER.create(new Runnable() {
    4.82 +                    @Override public void run() {
    4.83 +                        compute(text, searchType == SearchType.EXACT_NAME ? SearchType.PREFIX : searchType);
    4.84 +                    }
    4.85 +                });
    4.86 +
    4.87 +                currentWorker.schedule(0);
    4.88 +                results = new ArrayList<R>();
    4.89 +            }
    4.90 +        }
    4.91 +
    4.92 +        try {
    4.93 +            currentWorker.waitFinished(100);
    4.94 +        } catch (InterruptedException ex) {
    4.95 +            Logger.getLogger(RemoteGoToType.class.getName()).log(Level.FINE, null, ex);
    4.96 +        }
    4.97 +
    4.98 +        boolean finished = currentWorker.isFinished();
    4.99 +        NameMatcher matcher = NameMatcherFactory.createNameMatcher(text, searchType);
   4.100 +
   4.101 +        synchronized (this) {
   4.102 +            for (R td : results) {
   4.103 +                if (matcher.accept(td.getSimpleName()))
   4.104 +                    result.addResult(td);
   4.105 +            }
   4.106 +        }
   4.107 +
   4.108 +        if (!finished) {
   4.109 +            result.setMessage("Remote query still running, some remote results may be missing");
   4.110 +        }
   4.111 +    }
   4.112 +
   4.113 +    protected abstract void compute(String text, SearchType searchType);
   4.114 +
   4.115 +    protected final synchronized void addResults(Collection<? extends R> r) {
   4.116 +        results.addAll(r);
   4.117 +    }
   4.118 +
   4.119 +    public void cancel() {
   4.120 +    }
   4.121 +
   4.122 +    public void cleanup() {
   4.123 +        mostGenericQueryText = null;
   4.124 +        results = null;
   4.125 +        currentWorker = null;
   4.126 +    }
   4.127 +
   4.128 +    protected static interface ResultWrapper<R> {
   4.129 +
   4.130 +        public void setMessage(String message);
   4.131 +        public void addResult(R r);
   4.132 +
   4.133 +    }
   4.134 +
   4.135 +    protected static interface SimpleNameable {
   4.136 +        public String getSimpleName();
   4.137 +    }
   4.138 +
   4.139 +}