Adding web UI for find subclasses and find overriders.
authorJan Lahoda <jlahoda@netbeans.org>
Fri, 06 Jul 2012 23:11:32 +0200
changeset 813cd06de37bc2f
parent 812 8d0ac461ca68
child 814 69a1df845e0b
Adding web UI for find subclasses and find overriders.
remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java
remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/implementors.html
remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/ui-findType.html
     1.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java	Thu Jul 05 23:44:17 2012 +0200
     1.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/UI.java	Fri Jul 06 23:11:32 2012 +0200
     1.3 @@ -214,7 +214,87 @@
     1.4      @GET
     1.5      @Path("/usages")
     1.6      @Produces("text/html")
     1.7 -    public String usages(@QueryParam("path") String segment, @QueryParam("signatures") String signatures) throws URISyntaxException, IOException, TemplateException {
     1.8 +    public String usages(@QueryParam("path") String segment, @QueryParam("signatures") final String signatures) throws URISyntaxException, IOException, TemplateException {
     1.9 +        Map<String, Object> configurationData = usagesSubclassesImpl(segment, signatures, "files", new ComputeSegmentData() {
    1.10 +            @Override public Object compute(String currentSegment) throws URISyntaxException, TemplateException, IOException {
    1.11 +                URI u = new URI(URL_BASE + "/usages/search?path=" + escapeForQuery(currentSegment) + "&signatures=" + escapeForQuery(simplify(signatures)));
    1.12 +                List<String> files = new ArrayList<String>(WebUtilities.requestStringArrayResponse(u));
    1.13 +                Collections.sort(files);
    1.14 +                return files;
    1.15 +            }
    1.16 +        });
    1.17 +
    1.18 +        return FreemarkerUtilities.processTemplate("org/netbeans/modules/jackpot30/backend/ui/usages.html", configurationData);
    1.19 +    }
    1.20 +
    1.21 +    @GET
    1.22 +    @Path("/implements")
    1.23 +    @Produces("text/html")
    1.24 +    public String impl(@QueryParam("path") String segment, @QueryParam("type") String typeSignature, @QueryParam("method") final String methodSignature) throws URISyntaxException, IOException, TemplateException {
    1.25 +        Map<String, Object> configurationData;
    1.26 +
    1.27 +        if (typeSignature != null) {
    1.28 +            final String type = strip(typeSignature, "CLASS:", "INTERFACE:", "ENUM:", "ANNOTATION_TYPE:");
    1.29 +            configurationData = usagesSubclassesImpl(segment, typeSignature, "implementors", new ComputeSegmentData() {
    1.30 +                @Override
    1.31 +                public Object compute(String currentSegment) throws URISyntaxException, TemplateException, IOException {
    1.32 +                    URI u = new URI(URL_BASE + "/implements/search?path=" + escapeForQuery(currentSegment) + "&type=" + escapeForQuery(type));
    1.33 +                    Map<String, List<Map<String, String>>> data = Pojson.load(HashMap.class, u);
    1.34 +                    List<Map<String, String>> implementors = new ArrayList<Map<String, String>>();
    1.35 +                    for (Entry<String, List<Map<String, String>>> relpath2ImplementorsE : data.entrySet()) {
    1.36 +                        for (Map<String, String> implementorData : relpath2ImplementorsE.getValue()) {
    1.37 +                            Map<String, String> implementor = new HashMap<String, String>();
    1.38 +
    1.39 +                            implementor.put("file", implementorData.get("file"));
    1.40 +                            implementor.put("class", implementorData.get("class"));
    1.41 +                            implementors.add(implementor);
    1.42 +                        }
    1.43 +                    }
    1.44 +                    Collections.sort(implementors, new Comparator<Map<String, String>>() {
    1.45 +                        @Override
    1.46 +                        public int compare(Map<String, String> o1, Map<String, String> o2) {
    1.47 +                            return o1.get("class").compareTo(o2.get("class"));
    1.48 +                        }
    1.49 +                    });
    1.50 +                    return implementors;
    1.51 +                }
    1.52 +            });
    1.53 +
    1.54 +            configurationData.put("isSubtypes", true);
    1.55 +        } else {
    1.56 +            final String method = methodSignature.substring(0, methodSignature.length() - 1);
    1.57 +            configurationData = usagesSubclassesImpl(segment, methodSignature, "implementors", new ComputeSegmentData() {
    1.58 +                @Override
    1.59 +                public Object compute(String currentSegment) throws URISyntaxException, TemplateException, IOException {
    1.60 +                    URI u = new URI(URL_BASE + "/implements/search?path=" + escapeForQuery(currentSegment) + "&method=" + escapeForQuery(method));
    1.61 +                    Map<String, List<Map<String, String>>> data = Pojson.load(HashMap.class, u);
    1.62 +                    List<Map<String, String>> implementors = new ArrayList<Map<String, String>>();
    1.63 +                    for (Entry<String, List<Map<String, String>>> relpath2ImplementorsE : data.entrySet()) {
    1.64 +                        for (Map<String, String> implementorData : relpath2ImplementorsE.getValue()) {
    1.65 +                            Map<String, String> implementor = new HashMap<String, String>();
    1.66 +
    1.67 +                            implementor.put("file", implementorData.get("file"));
    1.68 +                            implementor.put("class", implementorData.get("enclosingFQN"));
    1.69 +                            implementors.add(implementor);
    1.70 +                        }
    1.71 +                    }
    1.72 +                    Collections.sort(implementors, new Comparator<Map<String, String>>() {
    1.73 +                        @Override
    1.74 +                        public int compare(Map<String, String> o1, Map<String, String> o2) {
    1.75 +                            return o1.get("class").compareTo(o2.get("class"));
    1.76 +                        }
    1.77 +                    });
    1.78 +                    return implementors;
    1.79 +                }
    1.80 +            });
    1.81 +
    1.82 +            configurationData.put("isSubtypes", false);
    1.83 +        }
    1.84 +
    1.85 +        return FreemarkerUtilities.processTemplate("org/netbeans/modules/jackpot30/backend/ui/implementors.html", configurationData);
    1.86 +    }
    1.87 +
    1.88 +    private Map<String, Object> usagesSubclassesImpl(String segment, String elementSignature, String dataKey, ComputeSegmentData computeSegmentData) throws URISyntaxException, TemplateException, IOException {
    1.89          List<Map<String, String>> segments2Process = new ArrayList<Map<String, String>>();
    1.90  
    1.91          for (Map<String, String> m : list()) {
    1.92 @@ -229,7 +309,7 @@
    1.93  
    1.94          Map<String, Object> configurationData = new HashMap<String, Object>();
    1.95  
    1.96 -        configurationData.put("elementDisplayName", elementDisplayName(signatures)); //TODO
    1.97 +        configurationData.put("elementDisplayName", elementDisplayName(elementSignature)); //TODO
    1.98  
    1.99          List<Map<String, Object>> results = new ArrayList<Map<String, Object>>(segments2Process.size());
   1.100  
   1.101 @@ -239,17 +319,18 @@
   1.102  
   1.103              rootResults.put("rootDisplayName", m.get("displayName"));
   1.104              rootResults.put("rootPath", currentSegment);
   1.105 -            URI u = new URI(URL_BASE + "/usages/search?path=" + escapeForQuery(currentSegment) + "&signatures=" + escapeForQuery(simplify(signatures)));
   1.106 -            List<String> files = new ArrayList<String>(WebUtilities.requestStringArrayResponse(u));
   1.107 -            Collections.sort(files);
   1.108 -            rootResults.put("files", files);
   1.109 +            rootResults.put(dataKey, computeSegmentData.compute(currentSegment));
   1.110  
   1.111              results.add(rootResults);
   1.112          }
   1.113  
   1.114          configurationData.put("results", results);
   1.115  
   1.116 -        return FreemarkerUtilities.processTemplate("org/netbeans/modules/jackpot30/backend/ui/usages.html", configurationData);
   1.117 +        return configurationData;
   1.118 +    }
   1.119 +
   1.120 +    private interface ComputeSegmentData {
   1.121 +        public Object compute(String segment) throws URISyntaxException, TemplateException, IOException;
   1.122      }
   1.123  
   1.124      private static String elementDisplayName(String signatures) {
   1.125 @@ -471,4 +552,14 @@
   1.126  
   1.127          return target.delete(target.length() - 1, target.length()).toString();
   1.128      }
   1.129 +
   1.130 +    static String strip(String originalSignature, String... prefixesToStrip) {
   1.131 +        for (String strip : prefixesToStrip) {
   1.132 +            if (originalSignature.startsWith(strip)) {
   1.133 +                return originalSignature.substring(strip.length());
   1.134 +            }
   1.135 +        }
   1.136 +
   1.137 +        return originalSignature;
   1.138 +    }
   1.139  }
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/implementors.html	Fri Jul 06 23:11:32 2012 +0200
     2.3 @@ -0,0 +1,24 @@
     2.4 +<html>
     2.5 +<head>
     2.6 +    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
     2.7 +    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
     2.8 +    <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" rel="stylesheet" type="text/css">
     2.9 +</head>
    2.10 +<body>
    2.11 +    <#if isSubtypes>
    2.12 +        Subtypes of ${elementDisplayName?replace("&", "&amp;")?replace("<", "&lt;")}:<br>
    2.13 +    <#else>
    2.14 +        Overriders of ${elementDisplayName?replace("&", "&amp;")?replace("<", "&lt;")} found in the following classes:<br>
    2.15 +    </#if>
    2.16 +        <ul>
    2.17 +            <#list results as rootResults>
    2.18 +                <li>${rootResults.rootDisplayName?replace("&", "&amp;")?replace("<", "&lt;")}<br>
    2.19 +                    <#list rootResults.implementors as implementor>
    2.20 +                        <img src="/index/icons/class.png" alt="Java Class"/>
    2.21 +                        <a href='/index/ui/show?path=${rootResults.rootPath}&relative=${implementor.file}'>${implementor.class}</a><br>
    2.22 +                    </#list>
    2.23 +                </li>
    2.24 +            </#list>
    2.25 +        </ul>
    2.26 +</body>
    2.27 +</html>
     3.1 --- a/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/ui-findType.html	Thu Jul 05 23:44:17 2012 +0200
     3.2 +++ b/remoting/server/web/web.ui/src/org/netbeans/modules/jackpot30/backend/ui/ui-findType.html	Fri Jul 06 23:11:32 2012 +0200
     3.3 @@ -7,17 +7,23 @@
     3.4          function methodPopup(relativePath, resultFile, signature) {
     3.5              $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '">Source Code</a><br>' +
     3.6                               '<a href="/index/ui/usages?path=' + relativePath + '&signatures=' + signature + '">Usages in the current project</a><br>' +
     3.7 -                             '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>')
     3.8 +                             '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>' +
     3.9 +                             '<a href="/index/ui/implements?path=' + relativePath + '&method=' + signature + '">Overriders in the current project</a><br>' +
    3.10 +                             '<a href="/index/ui/implements?method=' + signature + '">Overriders in all known projects</a><br>')
    3.11                              .dialog({
    3.12 -                                title: 'Show'
    3.13 +                                title: 'Show',
    3.14 +                                width: 460 //XXX: hardcoded size
    3.15                              });
    3.16          }
    3.17          function classPopup(relativePath, resultFile, signature) {
    3.18              $('#popup').html('<a href="/index/ui/show?path=' + relativePath + '&relative=' + resultFile + '">Source Code</a><br>' +
    3.19                               '<a href="/index/ui/usages?path=' + relativePath + '&signatures=' + signature + '">Usages in the current project</a><br>' +
    3.20 -                             '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>')
    3.21 +                             '<a href="/index/ui/usages?signatures=' + signature + '">Usages in all known projects</a><br>' +
    3.22 +                             '<a href="/index/ui/implements?path=' + relativePath + '&type=' + signature + '">Subtypes in the current project</a><br>' +
    3.23 +                             '<a href="/index/ui/implements?type=' + signature + '">Subtypes in all known projects</a><br>')
    3.24                              .dialog({
    3.25 -                                title: 'Show'
    3.26 +                                title: 'Show',
    3.27 +                                width: 400 //XXX: hardcoded size
    3.28                              });
    3.29          }
    3.30          function otherPopup(relativePath, resultFile, signature) {