SOYC Dashboard
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4221 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java b/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
new file mode 100644
index 0000000..6575008
--- /dev/null
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.soyc;
+
+import java.util.TreeSet;
+
+public class CodeCollection {
+
+ public String codeType = "";
+ public TreeSet<String> classes = new TreeSet<String>();
+ public TreeSet<String> stories = new TreeSet<String>();
+ public float cumPartialSize = 0f;
+ public int cumSize = 0;
+ public CodeCollection(String type){
+ codeType = type;
+ }
+
+
+ public int getCumSize(){
+ cumSize = 0;
+ for (String className : classes){
+ if (! GlobalInformation.classToSize.containsKey(className)){
+ System.err.println("*** NO SIZE FOUND FOR CLASS " + className + " *****");
+ }
+ else{
+ cumSize += GlobalInformation.classToSize.get(className);
+ }
+ }
+ return cumSize;
+ }
+
+ public float getCumPartialSize(){
+ cumPartialSize = 0f;
+ for (String className : classes){
+ if (!GlobalInformation.classToPartialSize.containsKey(className)){
+ System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className + " *****");
+ }
+ else{
+ cumPartialSize += GlobalInformation.classToPartialSize.get(className);
+ }
+ }
+ return cumPartialSize;
+ }
+}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java b/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
new file mode 100644
index 0000000..40b377c
--- /dev/null
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+
+package com.google.gwt.soyc;
+
+import java.util.HashMap;
+import java.util.TreeMap;
+import java.util.HashSet;
+import java.util.TreeSet;
+
+public class GlobalInformation {
+
+ public static HashMap<String, HashSet<String>> storiesToCorrClasses = new HashMap<String, HashSet<String>>();
+ public static HashMap<String, String> storiesToLitType = new HashMap<String, String>();
+
+ public static HashMap<String, Integer> packageToSize = new HashMap<String, Integer>();
+ public static HashMap<String, Float> packageToPartialSize = new HashMap<String, Float>();
+
+ public static HashMap<String, String> classToPackage = new HashMap<String, String>();
+
+ //TODO(kprobst): not currently used, but will be for dependencies
+ //public static HashMap<String, HashSet<String>> classToWhatItDependsOn = new HashMap<String, HashSet<String>>();
+
+ public static HashMap<String, Integer> classToSize = new HashMap<String, Integer>();
+ public static HashMap<String, Float> classToPartialSize = new HashMap<String, Float>();
+ public static TreeMap<String, TreeSet<String>> packageToClasses = new TreeMap<String, TreeSet<String>>();
+
+ public static HashSet<String> nonAttributedStories = new HashSet<String>();
+ public static int nonAttributedBytes = 0;
+ public static int numBytesDoubleCounted = 0;
+
+ public static int cumSizeAllCode = 0;
+ public static float cumPartialSizeFromPackages = 0f;
+ public static int cumSizeFromPackages = 0;
+
+ public static HashMap<Integer, HashSet<String>> fragmentToStories = new HashMap<Integer, HashSet<String>>();
+ public static HashMap<Integer, Float> fragmentToPartialSize = new HashMap<Integer, Float>();
+ public static int numFragments = 0;
+ public static int numSplitPoints = 0;
+ public static int cumSizeInitialFragment = 0;
+
+ public static void computePackageSizes(){
+ cumSizeFromPackages = 0;
+ packageToSize.clear();
+ for (String packageName : packageToClasses.keySet()){
+ packageToSize.put(packageName, 0);
+ for (String className : packageToClasses.get(packageName)){
+ if (! classToSize.containsKey(className)){
+ System.err.println("*** NO SIZE FOUND FOR CLASS " + className + " *****");
+ }
+ else{
+ int curSize = classToSize.get(className);
+ cumSizeFromPackages += curSize;
+ int newSize = curSize + packageToSize.get(packageName);
+ packageToSize.put(packageName, newSize);
+ }
+ }
+ }
+ }
+
+ public static void computePartialPackageSizes(){
+ cumPartialSizeFromPackages = 0;
+ packageToPartialSize.clear();
+ for (String packageName : packageToClasses.keySet()){
+ packageToPartialSize.put(packageName, 0f);
+ for (String className : packageToClasses.get(packageName)){
+ if (! classToPartialSize.containsKey(className)){
+ System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className + " *****");
+ }
+ else{
+ float curSize = classToPartialSize.get(className);
+ cumPartialSizeFromPackages += curSize;
+ float newSize = curSize + packageToPartialSize.get(packageName);
+ packageToPartialSize.put(packageName, newSize);
+ }
+ }
+ }
+ }
+
+}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java b/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java
new file mode 100644
index 0000000..ce17b5d
--- /dev/null
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/LiteralsCollection.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.soyc;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.TreeMap;
+
+public class LiteralsCollection {
+ public String literalType = "";
+ public Map<String, HashSet<String>> literalToLocations = new TreeMap<String, HashSet<String>>();
+ public Map<String, HashSet<String> > storyToLocations = new HashMap<String, HashSet<String>>();
+ public TreeMap<String, String> stringLiteralToType = new TreeMap<String, String>();
+ public Map<String, Integer> stringTypeToSize = new HashMap<String, Integer>();
+ public Map<String, Integer> stringTypeToCount = new HashMap<String, Integer>();
+ public int cumSize = 0;
+ public int cumStringSize = 0;
+
+ public LiteralsCollection(String type){
+ literalType = type;
+ }
+
+ /**
+ * Utility method
+ */
+ public void printAllStrings(){
+ int iSum = 0;
+ System.out.println("--- now printing strings ---");
+ for (String st : stringLiteralToType.keySet()){
+ int numBytes = st.getBytes().length;
+ iSum += numBytes;
+ System.out.println(st + "[" + numBytes + "]");
+ }
+ System.out.println("sum: " + iSum);
+ System.out.println("--- done printing strings ---");
+ }
+
+}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java b/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
new file mode 100644
index 0000000..d538be3
--- /dev/null
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
@@ -0,0 +1,1046 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.soyc;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.TreeMap;
+
+public class MakeTopLevelHtmlForPerm {
+
+ public static void makeHTMLShell(HashMap<String, CodeCollection> nameToCodeColl, TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException{
+ //this will contain the place holder iframes where the actual information is going to go.
+
+ String fileName = "SoycDashboard-index.html";
+
+ final PrintWriter outFile = new PrintWriter(fileName);
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<title>Story of Your Compile - Top Level Dashboard for Permutation</title>");
+
+ outFile.println("<style type=\"text/css\">");
+ outFile.println("body {background-color: #728FCE}");
+ outFile.println("h2 {background-color: transparent}");
+ outFile.println("p {background-color: fuchsia}");
+ outFile.println("</style>");
+ outFile.println("</head>");
+
+
+ outFile.println("<body>");
+ outFile.println("<center>");
+ outFile.println("<h3>Story of Your Compile Dashboard</h3>");
+ outFile.println("<hr>");
+ if (GlobalInformation.cumSizeInitialFragment != 0){
+ outFile.println("<b>Full code size: <span style=\"color:maroon\">" + GlobalInformation.cumSizeAllCode + "</span>, Size of Initial Download: <span style=\"color:maroon\">" + GlobalInformation.cumSizeInitialFragment + "</span></b>");
+ }
+ else{
+ outFile.println("<b>Full code size: <span style=\"color:maroon\">" + GlobalInformation.cumSizeAllCode + "</span></b>");
+ }
+ outFile.println("</center>");
+ outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
+ outFile.println("<b>Package breakdown</b>");
+ outFile.println(" </div>");
+ outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">");
+ outFile.println("<b>Code type breakdown</b>");
+ outFile.println(" </div>");
+
+
+ outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
+ outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
+ outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Package Name</div>");
+ outFile.println(" </div>");
+
+
+ outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px;\">");
+ outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
+ outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Code Type</div>");
+ outFile.println(" </div>");
+
+
+
+ outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:left;\">");
+ outFile.println("<iframe src=\"packageBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println(" </div>");
+ makePackageHtml("packageBreakdown.html");
+
+ outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">");
+ outFile.println("<iframe src=\"codeTypeBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println(" </div>");
+ makeCodeTypeHtml("codeTypeBreakdown.html", nameToCodeColl);
+
+ outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
+ outFile.println("<b>Literals breakdown</b>");
+ outFile.println(" </div>");
+ outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">");
+ outFile.println("<b>String literals breakdown</b>");
+ outFile.println(" </div>");
+
+
+ outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
+ outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
+ outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Literal Type</div>");
+ outFile.println(" </div>");
+
+
+ outFile.println(" <div style=\"width:48%; float:right; padding-top: 10px; \">");
+ outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
+ outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">String Literal Type</div>");
+ outFile.println(" </div>");
+
+
+ outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:left;\">");
+ outFile.println("<iframe src=\"literalsBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println("</div>");
+ makeLiteralsHtml("literalsBreakdown.html", nameToLitColl);
+
+ outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">");
+ outFile.println("<iframe src=\"stringLiteralsBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println(" </div>");
+ makeStringLiteralsHtml("stringLiteralsBreakdown.html", nameToLitColl);
+
+
+
+ if (GlobalInformation.fragmentToStories.size() == 1){
+ outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">");
+ outFile.println("<b>Fragments breakdown</b>");
+ outFile.println(" </div>");
+
+ outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">");
+ outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
+ outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Fragment Name</div>");
+ outFile.println(" </div>");
+
+ outFile.println("<div style=\"height:35%; width:50%; margin:0 auto; background-color:white; float:left;\">");
+ outFile.println("<iframe src=\"fragmentsBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println("</div>");
+ makeFragmentsHtml("fragmentsBreakdown.html");
+ }
+
+ outFile.println(" </body>");
+ outFile.println("</html>");
+ outFile.close();
+
+ }
+
+
+ private static void makePackageHtml(String outFileName) throws IOException{
+
+
+ TreeMap<Float, String> sortedPackages = new TreeMap<Float, String>(Collections.reverseOrder());
+ float maxSize = 0f;
+ float sumSize = 0f;
+ for (String packageName : GlobalInformation.packageToPartialSize.keySet()){
+ sortedPackages.put(GlobalInformation.packageToPartialSize.get(packageName), packageName);
+ sumSize += GlobalInformation.packageToPartialSize.get(packageName);
+ if (GlobalInformation.packageToPartialSize.get(packageName) > maxSize){
+ maxSize = GlobalInformation.packageToPartialSize.get(packageName);
+ }
+ }
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+ int yOffset = 0;
+ for (Float size : sortedPackages.keySet()){
+
+ String packageName = sortedPackages.get(size);
+ String drillDownFileName = packageName + "Classes.html";
+
+ float ratio = (size / maxSize) * 79;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ float perc = (size / sumSize) * 100;
+
+ outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 110px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:70px;\">%.1f", perc);
+ outFile.println("%</div>\n");
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:110px;\"><a href=\"" + drillDownFileName + "\" target=\"_top\">"+packageName+"</a></div>");
+
+ yOffset = yOffset + 25;
+
+ }
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+
+ }
+
+
+ private static void makeFragmentsHtml(String outFileName) throws IOException{
+
+ TreeMap<Float, Integer> sortedFragments = new TreeMap<Float, Integer>(Collections.reverseOrder());
+ float maxSize = 0f;
+ float sumSize = 0f;
+ for (Integer fragmentName : GlobalInformation.fragmentToPartialSize.keySet()){
+ sortedFragments.put(GlobalInformation.fragmentToPartialSize.get(fragmentName), fragmentName);
+ sumSize += GlobalInformation.fragmentToPartialSize.get(fragmentName);
+ if (GlobalInformation.fragmentToPartialSize.get(fragmentName) > maxSize){
+ maxSize = GlobalInformation.fragmentToPartialSize.get(fragmentName);
+ }
+ }
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+ int yOffset = 0;
+ for (Float size : sortedFragments.keySet()){
+
+ Integer fragmentName = sortedFragments.get(size);
+ String drillDownFileName = "fragment" + Integer.toString(fragmentName) + "Classes.html";
+
+ float ratio = (size / maxSize) * 79;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ float perc = (size / sumSize) * 100;
+
+ outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 110px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:80px;\">%.1f", perc);
+ outFile.println("%</div>\n");
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:120px;\"><a href=\"" + drillDownFileName + "\" target=\"_top\">fragment"+ Integer.toString(fragmentName) +"</a></div>");
+
+ yOffset = yOffset + 25;
+
+ }
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+
+ }
+
+
+
+
+ private static void makeCodeTypeHtml(String outFileName, HashMap<String, CodeCollection> nameToCodeColl) throws IOException{
+
+
+ float maxSize = 0f;
+ float sumSize = 0f;
+ TreeMap<Float, String> sortedCodeTypes = new TreeMap<Float, String>(Collections.reverseOrder());
+
+ //TODO(kprobst): turn this into a multimap? com.google.common.collect.TreeMultimap
+ for (String codeType : nameToCodeColl.keySet()){
+ float curSize = nameToCodeColl.get(codeType).getCumPartialSize();
+ sumSize += curSize;
+
+ if (curSize != 0f){
+ sortedCodeTypes.put(curSize, codeType);
+ if (curSize > maxSize){
+ maxSize = curSize;
+ }
+ }
+ }
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+ int yOffset = 0;
+ for (Float size : sortedCodeTypes.keySet()){
+
+ String codeType = sortedCodeTypes.get(size);
+ String drillDownFileName = codeType + "Classes.html";
+
+ float ratio = (size / maxSize) * 79;
+ float perc = (size / sumSize) * 100;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 110px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:70px;\">%.1f", perc);
+ outFile.println("%</div>\n");
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:110px;\"><a href=\"" + drillDownFileName + "\" target=\"_top\">"+codeType+"</a></div>");
+
+ yOffset = yOffset + 25;
+
+ }
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+
+
+ }
+
+
+
+ private static void makeLiteralsHtml(String outFileName, TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException{
+
+
+ float maxSize = 0f;
+ float sumSize = 0f;
+ TreeMap<Float, String> sortedLitTypes = new TreeMap<Float, String>(Collections.reverseOrder());
+
+ for (String literal : nameToLitColl.keySet()){
+ float curSize = nameToLitColl.get(literal).cumSize;
+ sumSize += curSize;
+
+ if (curSize != 0f){
+ sortedLitTypes.put(curSize, literal);
+
+ if (curSize > maxSize){
+ maxSize = curSize;
+ }
+ }
+ }
+
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+ int yOffset = 0;
+ for (Float size : sortedLitTypes.keySet()){
+
+ String literal = sortedLitTypes.get(size);
+ String drillDownFileName = literal + "Lits.html";
+
+ float ratio = (size / maxSize) * 79;
+ float perc = (size / sumSize) * 100;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 110px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:70px;\">%.1f", perc);
+ outFile.println("%</div>\n");
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:110px;\"><a href=\"" + drillDownFileName + "\" target=\"_top\">"+literal+"</a></div>");
+
+ yOffset = yOffset + 25;
+
+ }
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+
+ }
+
+
+ private static void makeStringLiteralsHtml(String outFileName, TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException{
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\" media=\"screen\">");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+
+ if (nameToLitColl.get("string").stringTypeToSize.size() > 0){
+
+ float maxSize = 0f;
+ float sumSize = 0f;
+ TreeMap<Float, String> sortedStLitTypes = new TreeMap<Float, String>(Collections.reverseOrder());
+
+ for (String stringLiteral : nameToLitColl.get("string").stringTypeToSize.keySet()){
+ float curSize = nameToLitColl.get("string").stringTypeToSize.get(stringLiteral);
+ sumSize += curSize;
+
+ if (curSize != 0f){
+ sortedStLitTypes.put(curSize, stringLiteral);
+
+ if (curSize > maxSize){
+ maxSize = curSize;
+ }
+ }
+ }
+
+
+ int yOffset = 0;
+ for (Float size : sortedStLitTypes.keySet()){
+
+ String stringLiteral = sortedStLitTypes.get(size);
+ String drillDownFileName = stringLiteral + "Strings.html";
+
+ float ratio = (size / maxSize) * 79;
+ float perc = (size / sumSize) * 100;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ outFile.println("<div id=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 110px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:70px;\">%.1f", perc);
+ outFile.println("%</div>\n");
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:110px;\"><a href=\"" + drillDownFileName + "\" target=\"_top\">"+stringLiteral+"</a></div>");
+
+ yOffset = yOffset + 25;
+
+ }
+
+ }
+
+ else{
+ outFile.println("No string literals found for this application.");
+
+ }
+
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+ }
+
+
+
+ public static void makePackageClassesHtmls() throws IOException{
+
+ for (String packageName : GlobalInformation.packageToClasses.keySet()){
+
+ String outFileName = packageName + "Classes.html";
+ TreeMap<Float, String> sortedClasses = new TreeMap<Float, String>(Collections.reverseOrder());
+ float maxSize = 0f;
+
+ //TODO(kprobst): not currently used, but will be for dependencies
+ //int maxDepCount = 0;
+
+ for (String className : GlobalInformation.packageToClasses.get(packageName)){
+
+ float curSize = 0f;
+ if (! GlobalInformation.classToPartialSize.containsKey(className)){
+ System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className + " *****");
+ }
+ else{
+ curSize = GlobalInformation.classToPartialSize.get(className);
+ }
+
+ //TODO(kprobst): not currently used, but will be for dependencies
+ /*int depCount = 0;
+ if (GlobalInformation.classToWhatItDependsOn.containsKey(className)){
+ depCount = GlobalInformation.classToWhatItDependsOn.get(className).size();
+ }*/
+
+ if (curSize != 0f){
+
+ sortedClasses.put(curSize, className);
+ if (curSize > maxSize){
+ maxSize = curSize;
+ }
+ //TODO(kprobst): not currently used, but will be for dependencies
+ /*if (depCount > maxDepCount){
+ maxDepCount = depCount;
+ }*/
+ }
+ }
+
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"classLevel.css\" media=\"screen\">");
+ outFile.println("<title>Classes in package \"" + packageName + "\"</title>");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+
+ outFile.println("<center>");
+ outFile.println("<h2>Classes in package \"" + packageName + "\"</h2>");
+ outFile.println("</center>");
+ outFile.println("<hr>");
+
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 90px; left:70px; position:absolute; background-color:white\"");
+
+
+ int yOffset = 0;
+ for (Float size : sortedClasses.keySet()){
+
+ String className = sortedClasses.get(size);
+
+ //TODO(kprobst): switch out the commented/uncommented lines below when showing dependencies
+ //float ratio = (size / maxSize) * 45;
+ float ratio = (size / maxSize) * 85;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ //TODO(kprobst): not currently used, but will be for dependencies
+/* // get the dependency count
+ int depCount = 0;
+ if (GlobalInformation.classToWhatItDependsOn.containsKey(className)){
+ depCount = GlobalInformation.classToWhatItDependsOn.get(className).size();
+ }
+ float depRatio = (depCount / maxDepCount) * 25;
+ if (depRatio < 3){
+ depRatio = 3;
+ }*/
+
+ outFile.println("<div class=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 60px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+
+ //TODO(kprobst): not currently used, but will be for dependencies
+ // place holder for mock-up of dependency display
+/* outFile.println("<div class=\"box-right\" style=\"width:" + depRatio + "%; top: " + yOffset + "px; left: 50%\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+
+ outFile.println("<div class=\"box-right\" style=\"width:10%; top: " + yOffset + "px; left: 75%\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>"); */
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:70px;\">"+className+"</div>");
+
+ yOffset = yOffset + 25;
+
+ }
+
+ outFile.println("</div>");
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+ }
+ }
+
+
+ public static void makeCodeTypeClassesHtmls(HashMap<String, CodeCollection> nameToCodeColl) throws IOException{
+
+ for (String codeType : nameToCodeColl.keySet()){
+
+ //construct file name
+ String outFileName = codeType + "Classes.html";
+
+
+ float maxSize = 0f;
+ TreeMap<Float, String> sortedClasses = new TreeMap<Float, String>(Collections.reverseOrder());
+ for (String className : nameToCodeColl.get(codeType).classes){
+ if (GlobalInformation.classToPartialSize.containsKey(className)){
+
+ float curSize = 0f;
+ if (! GlobalInformation.classToPartialSize.containsKey(className)){
+ System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className + " *****");
+ }
+ else{
+ curSize = GlobalInformation.classToPartialSize.get(className);
+ }
+
+ if (curSize != 0f){
+ sortedClasses.put(curSize, className);
+ if (curSize > maxSize){
+ maxSize = curSize;
+ }
+ }
+ }
+ }
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+
+ outFile.println("<style type=\"text/css\">");
+ outFile.println("body {background-color: #728FCE}");
+ outFile.println("h2 {background-color: transparent}");
+ outFile.println("p {background-color: fuchsia}");
+ outFile.println("</style>");
+
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"classLevel.css\" media=\"screen\">");
+ outFile.println("<title>Classes of type \"" + codeType + "\"</title>");
+ outFile.println("</head>");
+ outFile.println("<body>");
+
+
+
+ outFile.println("<center>");
+ outFile.println("<h2>Classes of type \"" + codeType + "\"</h2>");
+ outFile.println("</center>");
+ outFile.println("<hr>");
+
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 90px; left:70px; position:absolute; background-color:white\"");
+
+
+ int yOffset = 0;
+ for (Float size : sortedClasses.keySet()){
+
+ String className = sortedClasses.get(size);
+
+ float ratio = (size / maxSize) * 85;
+
+ if (ratio < 3){
+ ratio = 3;
+ }
+
+ outFile.println("<div class=\"box\" style=\"width:" + ratio + "%; top: " + yOffset + "px; left: 60px;\">");
+ outFile.println("<div id=\"lb\">");
+ outFile.println("<div id=\"rb\">");
+ outFile.println("<div id=\"bb\"><div id=\"blc\"><div id=\"brc\">");
+ outFile.println("<div id=\"tb\"><div id=\"tlc\"><div id=\"trc\">");
+ outFile.println("<div id=\"content\">");
+ outFile.println("</div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div></div></div></div>");
+ outFile.println("</div>");
+
+ int yOffsetText = yOffset+8;
+ outFile.printf("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:5px;\">%.1f</div>\n", size);
+ outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText + "px; left:70px;\">"+className+"</div>");
+
+ yOffset = yOffset + 25;
+
+ }
+
+ outFile.println("</div>");
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+ }
+ }
+
+
+
+ public static void makeLiteralsClassesHtmls(TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException{
+
+
+ for (String literalType : nameToLitColl.keySet()){
+
+ String outFileName = literalType + "Lits.html";
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<title>Literals of type \"" + literalType + "\"</title>");
+ outFile.println("</head>");
+
+ outFile.println("<style type=\"text/css\">");
+ outFile.println("body {background-color: #728FCE}");
+ outFile.println("h2 {background-color: transparent}");
+ outFile.println("p {background-color: fuchsia}");
+ outFile.println(".tablediv {");
+ outFile.println("display: table;");
+ outFile.println("width:100%;");
+ outFile.println("background-color:#eee;");
+ outFile.println("border:1px solid #666666;");
+ outFile.println("border-spacing:5px;/*cellspacing:poor IE support for this*/");
+ outFile.println("border-collapse:separate;");
+ outFile.println("}");
+ outFile.println(".celldiv {");
+ outFile.println("float:left;/*fix for buggy browsers*/");
+ outFile.println("display: table-cell;");
+ outFile.println("width:50%;");
+ outFile.println("font-size: 14px;");
+ outFile.println("background-color:white;");
+ outFile.println("}");
+ outFile.println(".rowdiv {");
+ outFile.println("display: table-row;");
+ //outFile.println("width:90%;");
+ outFile.println("}");
+ outFile.println("</style>");
+
+ outFile.println("<body>");
+ outFile.println("<center>");
+ outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>");
+ outFile.println("</center>");
+ outFile.println("<hr>");
+
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 30px; left:60px; position:relative; background-color:white\"");
+ outFile.println("<div class=\"tablediv\">");
+ for (String literal : nameToLitColl.get(literalType).literalToLocations.keySet()){
+
+ if (literal.trim().compareTo("") == 0){
+ literal = "[whitespace only string]";
+ }
+
+
+ String newLiteral = "";
+ if(literal.length() > 100){
+ int i;
+ for (i = 100; i < literal.length(); i=i+100){
+ String part1 = literal.substring(i-100, i);
+ newLiteral = newLiteral + part1 + " ";
+ }
+ if (i-100 > 0){
+ newLiteral = newLiteral + literal.substring(i-100);
+ }
+ }
+ else{
+ newLiteral = literal;
+ }
+
+ String escliteral = escapeXml(newLiteral);
+ outFile.println("<div class=\"rowdiv\">");
+ outFile.println("<div class=\"celldiv\">" + escliteral + "</div>");
+
+ for (String location : nameToLitColl.get(literalType).literalToLocations.get(literal)){
+
+ String newLocation = "";
+ if(location.length() > 100){
+ int i;
+ for (i = 100; i < location.length(); i=i+100){
+ String part1 = location.substring(i-100, i);
+ newLocation = newLocation + part1 + " ";
+ }
+ if (i-100 > 0){
+ newLocation = newLocation + location.substring(i-100);
+ }
+ }
+ else{
+ newLocation = location;
+ }
+
+ outFile.println("<div class=\"celldiv\">" + newLocation + "</div>");
+ }
+ outFile.println("</div>");
+ }
+ outFile.println("</div>");
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+ }
+ }
+
+ /**
+ * Makes html file for fragment classes.
+ * TODO(kprobst): update this once we have SOYC updated to supply enough information
+ * @throws IOException
+ */
+ public static void makeFragmentClassesHtmls() throws IOException{
+
+
+ for (Integer fragmentName : GlobalInformation.fragmentToStories.keySet()){
+ HashSet<String> alreadyPrintedClasses = new HashSet<String>();
+
+ String outFileName = "fragment" + Integer.toString(fragmentName) + "Classes.html";
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<title>Classes correlated with fragment " + Integer.toString(fragmentName) + " </title>");
+ outFile.println("</head>");
+
+ outFile.println("<style type=\"text/css\">");
+ outFile.println("body {background-color: #728FCE}");
+ outFile.println("h2 {background-color: transparent}");
+ outFile.println("p {background-color: fuchsia}");
+ outFile.println(".tablediv {");
+ outFile.println("display: table;");
+ outFile.println("width:100%;");
+ outFile.println("background-color:#eee;");
+ outFile.println("border:1px solid #666666;");
+ outFile.println("border-spacing:5px;/*cellspacing:poor IE support for this*/");
+ outFile.println("border-collapse:separate;");
+ outFile.println("}");
+ outFile.println(".celldiv {");
+ outFile.println("float:left;/*fix for buggy browsers*/");
+ outFile.println("display: table-cell;");
+ outFile.println("width:49.5%;");
+ outFile.println("font-size: 14px;");
+ outFile.println("background-color:white;");
+ outFile.println("}");
+ outFile.println(".rowdiv {");
+ outFile.println("display: table-row;");
+ outFile.println("width:100%;");
+ outFile.println("}");
+ outFile.println("</style>");
+
+ outFile.println("<body>");
+ outFile.println("<center>");
+ outFile.println("<h2>Classes correlated with fragment " + Integer.toString(fragmentName) + "</h2>");
+ outFile.println("</center>");
+ outFile.println("<hr>");
+
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 30px; left:60px; position:relative; background-color:white\"");
+ outFile.println("<div class=\"tablediv\">");
+
+ for (String storyName : GlobalInformation.fragmentToStories.get(fragmentName)){
+ if (GlobalInformation.storiesToCorrClasses.containsKey(storyName)){
+ for (String className : GlobalInformation.storiesToCorrClasses.get(storyName)){
+
+ if (! alreadyPrintedClasses.contains(className)){
+ //outFile.println("<div class=\"rowdiv\">");
+ outFile.println("<div class=\"rowdiv\">" + className + "</div>");
+ //outFile.println("</div>");
+ alreadyPrintedClasses.add(className);
+ }
+ }
+ }
+ }
+ outFile.println("</div>");
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+ }
+ }
+
+
+ public static void makeStringLiteralsClassesHtmls(TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException{
+
+
+ for (String literalType : nameToLitColl.get("string").stringTypeToSize.keySet()){
+
+ String outFileName = literalType + "Strings.html";
+
+ final PrintWriter outFile = new PrintWriter(outFileName);
+
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
+ outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
+ outFile.println("<title>Literals of type \"" + literalType + "\"</title>");
+ outFile.println("</head>");
+
+ outFile.println("<style type=\"text/css\">");
+ outFile.println("body {background-color: #728FCE}");
+ outFile.println("h2 {background-color: transparent}");
+ outFile.println("p {background-color: fuchsia}");
+ outFile.println(".tablediv {");
+ outFile.println("display: table;");
+ outFile.println("width:100%;");
+ outFile.println("background-color:#eee;");
+ outFile.println("border:1px solid #666666;");
+ outFile.println("border-spacing:5px;/*cellspacing:poor IE support for this*/");
+ outFile.println("border-collapse:separate;");
+ outFile.println("}");
+ outFile.println(".celldiv {");
+ outFile.println("float:left;/*fix for buggy browsers*/");
+ outFile.println("display: table-cell;");
+ outFile.println("width:49.5%;");
+ outFile.println("font-size: 14px;");
+ outFile.println("background-color:white;");
+ outFile.println("}");
+ outFile.println(".rowdiv {");
+ outFile.println("display: table-row;");
+ outFile.println("width:100%;");
+ outFile.println("}");
+ outFile.println("</style>");
+
+ outFile.println("<body>");
+ outFile.println("<center>");
+ outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>");
+ outFile.println("</center>");
+ outFile.println("<hr>");
+
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 30px; left:60px; position:relative; background-color:white\"");
+ outFile.println("<div class=\"tablediv\">");
+
+
+ for (String literal : nameToLitColl.get("string").stringLiteralToType.keySet()){
+
+ if (nameToLitColl.get("string").stringLiteralToType.get(literal).compareTo(literalType) == 0){
+
+
+ if (literal.trim().compareTo("") == 0){
+ literal = "[whitespace only string]";
+ }
+
+ String newLiteral = "";
+ if(literal.length() > 100){
+ int i;
+ for (i = 100; i < literal.length(); i=i+100){
+ String part1 = literal.substring(i-100, i);
+ newLiteral = newLiteral + part1 + " ";
+ }
+ if (i-100 > 0){
+ newLiteral = newLiteral + literal.substring(i-100);
+ }
+ }
+ else{
+ newLiteral = literal;
+ }
+
+ String escliteral = escapeXml(newLiteral);
+ outFile.println("<div class=\"rowdiv\">");
+ outFile.println("<div class=\"celldiv\">" + escliteral + "</div>");
+
+ for (String location : nameToLitColl.get("string").literalToLocations.get(literal)){
+
+ String newLocation = "";
+ if(location.length() > 100){
+ int i;
+ for (i = 100; i < location.length(); i=i+100){
+ String part1 = location.substring(i-100, i);
+ newLocation = newLocation + part1 + " ";
+ }
+ if (i-100 > 0){
+ newLocation = newLocation + location.substring(i-100);
+ }
+ }
+ else{
+ newLocation = location;
+ }
+
+ outFile.println("<div class=\"celldiv\">" + newLocation + "</div>");
+ }
+ outFile.println("</div>");
+ }
+ }
+ outFile.println("</div>");
+ outFile.println("</body>");
+ outFile.println("</html>");
+ outFile.close();
+ }
+
+
+
+ }
+
+
+
+ public static String escapeXml(String unescaped) {
+ String escaped = unescaped.replaceAll("\\&", "&");
+ escaped = escaped.replaceAll("\\<", "<");
+ escaped = escaped.replaceAll("\\>", ">");
+ escaped = escaped.replaceAll("\\\"", """);
+ escaped = escaped.replaceAll("\\'", "'");
+ return escaped;
+ }
+
+}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java b/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
new file mode 100644
index 0000000..3333352
--- /dev/null
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
@@ -0,0 +1,775 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.soyc;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import org.xml.sax.SAXException;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.TreeSet;
+import java.util.TreeMap;
+import javax.xml.parsers.*;
+
+public class SoycDashboard {
+
+ /**
+ * @param args Input: XML file containing soyc compile output
+ * @throws IOException
+ * @throws SAXException
+ */
+ public static void main(String[] args) {
+
+ if (args.length != 1){
+ System.err.println("Usage: java com/google/gwt/soyc/SoycDashboard soyc-report0.xml");
+ System.exit(1);
+ }
+
+ String inFileName = args[0];
+
+ // to store literals data
+ final TreeMap<String, LiteralsCollection> nameToLitColl = new TreeMap<String, LiteralsCollection>();
+ nameToLitColl.put("long",new LiteralsCollection("long"));
+ nameToLitColl.put("null",new LiteralsCollection("null"));
+ nameToLitColl.put("class",new LiteralsCollection("class"));
+ nameToLitColl.put("int",new LiteralsCollection("int"));
+ nameToLitColl.put("string",new LiteralsCollection("string"));
+ nameToLitColl.put("number",new LiteralsCollection("number"));
+ nameToLitColl.put("boolean",new LiteralsCollection("boolean"));
+ nameToLitColl.put("double",new LiteralsCollection("double"));
+ nameToLitColl.put("char",new LiteralsCollection("char"));
+ nameToLitColl.put("undefined",new LiteralsCollection("undefined"));
+ nameToLitColl.put("float",new LiteralsCollection("float"));
+
+ // to store code data
+ final HashMap<String, CodeCollection> nameToCodeColl = new HashMap<String, CodeCollection>();
+ nameToCodeColl.put("allOther", new CodeCollection("allOther"));
+ nameToCodeColl.put("widget", new CodeCollection("widget"));
+ nameToCodeColl.put("rpcUser", new CodeCollection("rpcUser"));
+ nameToCodeColl.put("rpcGen", new CodeCollection("rpcGen"));
+ nameToCodeColl.put("rpcGwt", new CodeCollection("rpcGwt"));
+ nameToCodeColl.put("gwtLang", new CodeCollection("long"));
+ nameToCodeColl.put("jre", new CodeCollection("jre"));
+
+ // get the number of split points (so we know what code to ignore)
+ DefaultHandler fragmentCountHandler = scanXMLDocument();
+
+ // start parsing
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ try {
+ SAXParser saxParser = factory.newSAXParser();
+ InputStream in = new BufferedInputStream(new FileInputStream(inFileName));
+ saxParser.parse(in,fragmentCountHandler);
+
+
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException("Could not parse document. ", e);
+ } catch (SAXException e) {
+ throw new RuntimeException("Could not create SAX parser. ", e);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not open file. ", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Could not open file. ", e);
+ }
+ GlobalInformation.numSplitPoints = (int)((float)(GlobalInformation.numFragments - 1) / 3f);
+
+ // make the parser handler
+ DefaultHandler handler = parseXMLDocument(nameToLitColl, nameToCodeColl);
+
+
+ // start parsing
+ SAXParserFactory factoryMain = SAXParserFactory.newInstance();
+ factoryMain.setNamespaceAware(true);
+ try {
+ SAXParser saxParser = factoryMain.newSAXParser();
+ InputStream in = new BufferedInputStream(new FileInputStream(inFileName));
+ saxParser.parse(in,handler);
+
+
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException("Could not parse document. ", e);
+ } catch (SAXException e) {
+ throw new RuntimeException("Could not create SAX parser. ", e);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not open file. ", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Could not open file. ", e);
+ }
+
+ // add to "All Other Code" if none of the special categories apply
+ updateAllOtherCodeType(nameToCodeColl);
+
+ // now we need to aggregate numbers
+ GlobalInformation.computePackageSizes();
+ GlobalInformation.computePartialPackageSizes();
+
+ // clean up the RPC categories
+ foldInRPCHeuristic(nameToCodeColl);
+
+ // generate all the html files
+ makeHTMLFiles(nameToLitColl, nameToCodeColl);
+
+ System.out.println("Finished creating reports. To see the dashboard, open SoycDashboard-index.html in your browser.");
+ }
+
+
+ private static DefaultHandler parseXMLDocument(
+ final TreeMap<String, LiteralsCollection> nameToLitColl,
+ final HashMap<String, CodeCollection> nameToCodeColl) {
+
+ DefaultHandler handler = new DefaultHandler() {
+
+ String curStoryId;
+ String curStoryLiteralType;
+ String curLineNumber;
+ String curLocation;
+ String curStoryRef;
+ HashSet<String> curRelevantLitTypes = new HashSet<String>();
+ HashSet<String> curRelevantCodeTypes = new HashSet<String>();
+ String curClassId;
+ String curPackage;
+ Integer curFragment;
+ boolean specialCodeType = false;
+ StringBuilder valueBuilder = new StringBuilder();
+ int ct = 0;
+
+ /**
+ * This method deals with the beginning of the XML element.
+ * It analyzes the XML node and adds its information to the relevant literal or code collection for later analysis.
+ * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement(String nsUri, String strippedName, String tagName, Attributes attributes) {
+
+ if ((ct % 10000) == 0){
+ System.out.println(".");
+ }
+ ct++;
+
+ valueBuilder.delete(0,valueBuilder.length());
+
+ if ((strippedName.compareTo("package") == 0)&&(attributes.getValue("id") != null)){
+ curPackage = attributes.getValue("id");
+
+ if (curPackage.compareTo("") == 0){
+ curPackage = "emptyPackageName";
+ }
+
+ if (! GlobalInformation.packageToClasses.containsKey(curPackage)){
+ TreeSet<String> insertSet = new TreeSet<String>();
+ GlobalInformation.packageToClasses.put(curPackage, insertSet);
+ }
+ }
+
+ else if (strippedName.compareTo("class") == 0){
+
+ parseClass(nameToCodeColl, attributes);
+ }
+
+ //TODO(kprobst): not currently used, but will be for dependencies
+/* else if (strippedName.compareTo("on") == 0){
+ parseDependsOn(nameToCodeColl, attributes);
+ }*/
+
+ else if (strippedName.compareTo("of") == 0){
+ parseOverrides(nameToCodeColl, attributes);
+ }
+
+ else if (strippedName.compareTo("by") == 0){
+ parseCorrelations(nameToCodeColl, attributes);
+ }
+
+ else if (strippedName.compareTo("story") == 0){
+ parseStory(attributes);
+ }
+
+ else if (strippedName.compareTo("origin") == 0){
+ parseOrigins(nameToLitColl, attributes);
+ }
+
+ else if (strippedName.compareTo("js") == 0){
+ if (attributes.getValue("fragment") != null){
+ // ignore all code that is not in the first load order
+
+ curFragment = Integer.parseInt(attributes.getValue("fragment"));
+ if(!((curFragment == 0)||(curFragment == (GlobalInformation.numSplitPoints+1))||(curFragment == (GlobalInformation.numSplitPoints+2))||
+ ((curFragment >= 2) && (curFragment <= GlobalInformation.numSplitPoints)))){
+ curFragment = -1;
+ }
+ }
+ else{
+ curFragment = -2;
+ }
+ }
+
+ else if (strippedName.compareTo("storyref") == 0){
+ parseJs(nameToLitColl, nameToCodeColl, attributes, curFragment);
+ }
+ }
+
+
+ /**
+ * This method collects a block of the value of the current XML node that the SAX parser parses.
+ * It simply adds to the the previous blocks, so that we can collect the entire value block.
+ */
+ @Override
+ public void characters (char ch[], int start, int length){
+ valueBuilder.append(ch, start, length);
+ }
+
+
+ /**
+ * This method marks the end of an XML element that the SAX parser parses.
+ * It has access to the full value of the node and uses it add information to the relevant literal or code collections.
+ * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void endElement (String nsUri, String strippedName, String qName){
+ String value = valueBuilder.toString();
+
+ int numBytes = value.getBytes().length;
+
+ if ((curStoryRef != null)&&(curFragment != -1)){
+
+ if ((!GlobalInformation.storiesToLitType.containsKey(curStoryRef))&&(! GlobalInformation.storiesToCorrClasses.containsKey(curStoryRef))){
+ GlobalInformation.nonAttributedStories.add(curStoryRef);
+ GlobalInformation.nonAttributedBytes += numBytes;
+ }
+
+ GlobalInformation.cumSizeAllCode += numBytes;
+
+ if (curFragment == 0){
+ GlobalInformation.cumSizeInitialFragment += numBytes;
+ }
+
+ // go through all the classes for this story
+ if (GlobalInformation.storiesToCorrClasses.containsKey(curStoryRef)){
+
+
+ if ((GlobalInformation.storiesToLitType.containsKey(curStoryRef))&&(GlobalInformation.storiesToCorrClasses.get(curStoryRef).size() > 0)){
+ GlobalInformation.numBytesDoubleCounted += numBytes;
+ }
+
+ float partialSize = (float)numBytes / (float)GlobalInformation.storiesToCorrClasses.get(curStoryRef).size();
+
+ //add this size to the current fragment
+ if (!GlobalInformation.fragmentToPartialSize.containsKey(curFragment)){
+ GlobalInformation.fragmentToPartialSize.put(curFragment, partialSize);
+ }
+ else{
+ float newSize = GlobalInformation.fragmentToPartialSize.get(curFragment) + partialSize;
+ GlobalInformation.fragmentToPartialSize.put(curFragment, newSize);
+ }
+
+ for (String className : GlobalInformation.storiesToCorrClasses.get(curStoryRef)){
+ // get the corresponding package
+ if (GlobalInformation.classToPackage.containsKey(className)){
+ String packageName = GlobalInformation.classToPackage.get(className);
+
+ if (!GlobalInformation.packageToClasses.containsKey(packageName)){
+ TreeSet<String> insertSet = new TreeSet<String>();
+ insertSet.add(className);
+ GlobalInformation.packageToClasses.put(packageName, insertSet);
+ }
+ else{
+ GlobalInformation.packageToClasses.get(packageName).add(className);
+ }
+
+ if (GlobalInformation.classToSize.containsKey(className)){
+ int newSize = GlobalInformation.classToSize.get(className) + numBytes;
+ GlobalInformation.classToSize.put(className, newSize);
+ }
+ else{
+ GlobalInformation.classToSize.put(className, numBytes);
+ }
+
+ if (GlobalInformation.classToPartialSize.containsKey(className)){
+ float newSize = GlobalInformation.classToPartialSize.get(className) + partialSize;
+ GlobalInformation.classToPartialSize.put(className, newSize);
+ }
+ else{
+ GlobalInformation.classToPartialSize.put(className, partialSize);
+ }
+ }
+ }
+ }
+
+
+/* else{
+ System.err.println("----- NO CORR CLASSES FOUND FOR STORY " + curStoryRef + " ---------");
+ }*/
+
+ updateLitTypes(nameToLitColl, value, numBytes);
+ }
+ }
+
+
+ /*
+ * This method assigns strings to the appropriate category
+ */
+ private void updateLitTypes(
+ final TreeMap<String, LiteralsCollection> nameToLitColl,
+ String value, int numBytes) {
+
+ int iNumCounted = 0;
+
+ for (String relLitType : curRelevantLitTypes){
+
+ iNumCounted++;
+
+ //then give string literals special treatment
+ if (relLitType.compareTo("string") == 0){
+
+
+
+ // note that this will double-count (i.e., it will count a string twice if it's in the output twice), as it should.
+ nameToLitColl.get("string").cumStringSize += numBytes;
+ nameToLitColl.get(relLitType).cumSize += numBytes;
+
+ //get the origins
+ HashSet<String> originSet = nameToLitColl.get("string").storyToLocations.get(curStoryRef);
+
+ // find the most appropriate string literal category
+ String mostAppropriateCategory = "";
+ String mostAppropriateLocation = "";
+ String backupLocation = "";
+ for (String origin : originSet){
+
+ if ((origin.contains("ClassLiteralHolder")) && (mostAppropriateCategory.compareTo("") == 0)){
+ mostAppropriateCategory = "compiler";
+ mostAppropriateLocation = origin;
+ }
+ else if ((origin.startsWith("transient source for"))&&(origin.contains("_TypeSerializer")) && (mostAppropriateCategory.compareTo("") == 0)){
+ mostAppropriateCategory = "transient";
+ mostAppropriateLocation = origin;
+ }
+ else if ((origin.contains("InlineResourceBundleGenerator")) && (mostAppropriateCategory.compareTo("") == 0)){
+ mostAppropriateCategory = "inlinedTextRes";
+ mostAppropriateLocation = origin;
+ }
+ if (origin.compareTo("com.google.gwt.dev.js.ast.JsProgram: Line 0") != 0){
+ backupLocation = origin;
+ }
+ }
+
+ if (backupLocation.compareTo("") == 0){
+ backupLocation = "com.google.gwt.dev.js.ast.JsProgram: Line 0";
+ }
+ if ((((value.startsWith("'")) && (value.endsWith("'"))) ||
+ ((value.startsWith("\""))&&(value.endsWith("\"")))) &&
+ (mostAppropriateCategory.compareTo("") == 0)){
+ mostAppropriateCategory = "user";
+ mostAppropriateLocation = backupLocation;
+ }
+ else if (mostAppropriateCategory.compareTo("") == 0){
+ mostAppropriateCategory = "otherStrings";
+ mostAppropriateLocation = backupLocation;
+ }
+
+ if (!nameToLitColl.get("string").stringLiteralToType.containsKey(value)){
+ nameToLitColl.get("string").stringLiteralToType.put(value, mostAppropriateCategory);
+ if (!nameToLitColl.get("string").stringTypeToCount.containsKey(mostAppropriateCategory)){
+ nameToLitColl.get("string").stringTypeToCount.put(mostAppropriateCategory, 1);
+ }
+ else{
+ int iNewCount = nameToLitColl.get("string").stringTypeToCount.get(mostAppropriateCategory) + 1;
+ nameToLitColl.get("string").stringTypeToCount.put(mostAppropriateCategory, iNewCount);
+ }
+
+
+ int iNewSize = numBytes;
+ if (nameToLitColl.get("string").stringTypeToSize.containsKey(mostAppropriateCategory)){
+ iNewSize += nameToLitColl.get("string").stringTypeToSize.get(mostAppropriateCategory);
+ }
+ nameToLitColl.get("string").stringTypeToSize.put(mostAppropriateCategory, iNewSize);
+
+
+ if (nameToLitColl.get("string").storyToLocations.containsKey(curStoryRef)){
+ HashSet<String> insertSet = new HashSet<String>();
+ insertSet.add(mostAppropriateLocation);
+ nameToLitColl.get(relLitType).literalToLocations.put(value,insertSet);
+
+ }
+ }
+ }
+
+
+
+ else{
+
+ // note that this will double-count (i.e., it will count a literal twice if it's in the output twice), as it should.
+ nameToLitColl.get(relLitType).cumSize += numBytes;
+
+ if (nameToLitColl.get(relLitType).storyToLocations.containsKey(curStoryRef)){
+ if (nameToLitColl.get(relLitType).literalToLocations.containsKey(value)){
+ nameToLitColl.get(relLitType).literalToLocations.get(value).addAll(nameToLitColl.get(relLitType).
+ storyToLocations.get(curStoryRef));
+ }
+ else{
+ HashSet<String> insertSet = nameToLitColl.get(relLitType).storyToLocations.get(curStoryRef);
+ nameToLitColl.get(relLitType).literalToLocations.put(value,insertSet);
+ }
+
+ }
+ }
+ }
+
+ //System.out.println("value: |" + value + "| in story |" + curStoryRef + "| was counted " + iNumCounted + " times.");
+
+ }
+
+ /*
+ * parses the "JS" portion of the XML file
+ */
+ private void parseJs(
+ final TreeMap<String, LiteralsCollection> nameToLitColl,
+ final HashMap<String, CodeCollection> nameToCodeColl,
+ Attributes attributes, Integer curFragment) {
+ curRelevantLitTypes.clear();
+ curRelevantCodeTypes.clear();
+
+ if (attributes.getValue("idref") != null){
+
+ curStoryRef = attributes.getValue("idref");
+
+ if (curFragment != -1){
+ //add this to the stories for this fragment
+ if (!GlobalInformation.fragmentToStories.containsKey(curFragment)){
+ HashSet<String> insertSet = new HashSet<String>();
+ insertSet.add(curStoryRef);
+ GlobalInformation.fragmentToStories.put(curFragment, insertSet);
+ }
+ else{
+ GlobalInformation.fragmentToStories.get(curFragment).add(curStoryRef);
+ }
+ }
+
+ for (String litType : nameToLitColl.keySet()){
+ if (nameToLitColl.get(litType).storyToLocations.containsKey(curStoryRef)){
+ curRelevantLitTypes.add(litType);
+ }
+ }
+
+ specialCodeType = false;
+ for (String codeType : nameToCodeColl.keySet()){
+ if (nameToCodeColl.get(codeType).stories.contains(curStoryRef)){
+ curRelevantCodeTypes.add(codeType);
+ specialCodeType = true;
+ }
+ }
+ if (specialCodeType == false){
+
+ nameToCodeColl.get("allOther").stories.add(curStoryRef);
+ curRelevantCodeTypes.add("allOther");
+ }
+ }
+ }
+
+ /*
+ * parses the "origins" portion of the XML file
+ */
+ private void parseOrigins(
+ final TreeMap<String, LiteralsCollection> nameToLitColl,
+ Attributes attributes) {
+ if ((curStoryLiteralType.compareTo("") != 0)&&
+ (attributes.getValue("lineNumber") != null)&&
+ (attributes.getValue("location") != null)){
+ curLineNumber = attributes.getValue("lineNumber");
+ curLocation = attributes.getValue("location");
+ String curOrigin = curLocation + ": Line " + curLineNumber;
+
+ if (!nameToLitColl.get(curStoryLiteralType).storyToLocations.containsKey(curStoryId)){
+ HashSet<String> insertSet = new HashSet<String>();
+ insertSet.add(curOrigin);
+ nameToLitColl.get(curStoryLiteralType).storyToLocations.put(curStoryId, insertSet);
+ }
+ else{
+ nameToLitColl.get(curStoryLiteralType).storyToLocations.get(curStoryId).add(curOrigin);
+ }
+ }
+ }
+
+ /*
+ * parses the "story" portion of the XML file
+ */
+ private void parseStory(Attributes attributes) {
+ if (attributes.getValue("id") != null){
+ curStoryId = attributes.getValue("id");
+ if (attributes.getValue("literal") != null){
+ curStoryLiteralType = attributes.getValue("literal");
+ GlobalInformation.storiesToLitType.put(curStoryId, curStoryLiteralType);
+ }
+ else{
+ curStoryLiteralType = "";
+ }
+ }
+ }
+
+ /*
+ * parses the "correlations" portion of the XML file
+ */
+ private void parseCorrelations(
+ final HashMap<String, CodeCollection> nameToCodeColl,
+ Attributes attributes) {
+
+ if (attributes.getValue("idref") != null){
+ String corrClass = attributes.getValue("idref");
+
+
+ if (corrClass.contains(":")){
+ corrClass = corrClass.replaceAll(":.*", "");
+ }
+
+ if (GlobalInformation.classToPackage.containsKey(corrClass)){ //if we know about this class
+
+ if (! GlobalInformation.storiesToCorrClasses.containsKey(curStoryId)){
+ HashSet<String> insertSet = new HashSet<String>();
+ insertSet.add(corrClass);
+ GlobalInformation.storiesToCorrClasses.put(curStoryId, insertSet);
+ }
+ else{
+ GlobalInformation.storiesToCorrClasses.get(curStoryId).add(corrClass);
+ }
+
+ for (String codeType : nameToCodeColl.keySet()){
+ if (nameToCodeColl.get(codeType).classes.contains(corrClass)){
+ nameToCodeColl.get(codeType).stories.add(curStoryId);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * parses the "overrides" portion of the XML file
+ */
+ private void parseOverrides(
+ final HashMap<String, CodeCollection> nameToCodeColl,
+ Attributes attributes) {
+ if (attributes.getValue("idref") != null){
+ String overriddenClass = attributes.getValue("idref");
+
+
+ if (overriddenClass.contains(":")){
+ overriddenClass = overriddenClass.replaceAll(":.*", "");
+ }
+ if (overriddenClass.contains("$")){
+ overriddenClass = overriddenClass.replaceAll("\\$.*", "");
+ }
+
+ if (overriddenClass.compareTo("com.google.gwt.user.client.ui.UIObject") == 0){
+ nameToCodeColl.get("widget").classes.add(curClassId);
+ }
+ else if (overriddenClass.contains("java.io.Serializable") ||
+ overriddenClass.contains("IsSerializable")){
+ nameToCodeColl.get("rpcUser").classes.add(curClassId);
+ }
+ else if (overriddenClass.contains("com.google.gwt.user.client.rpc.core.java")){
+ nameToCodeColl.get("rpcGwt").classes.add(curClassId);
+ }
+ }
+ }
+
+ /*
+ * parses the "class" portion of the XML file
+ */
+ private void parseClass(
+ final HashMap<String, CodeCollection> nameToCodeColl,
+ Attributes attributes) {
+ if (attributes.getValue("id") != null){
+ curClassId = attributes.getValue("id");
+
+ GlobalInformation.classToPackage.put(curClassId, curPackage);
+
+ if (curPackage.startsWith("java")){
+ nameToCodeColl.get("jre").classes.add(curClassId);
+ }
+ else if (curPackage.startsWith("com.google.gwt.lang")){
+ nameToCodeColl.get("gwtLang").classes.add(curClassId);
+ }
+ if (curClassId.contains("_CustomFieldSerializer")){
+ nameToCodeColl.get("rpcUser").classes.add(curClassId);
+ }
+ else if (curClassId.endsWith("_FieldSerializer") ||
+ curClassId.endsWith("_Proxy") ||
+ curClassId.endsWith("_TypeSerializer")){
+ nameToCodeColl.get("rpcGen").classes.add(curClassId);
+ }
+ }
+ }
+
+ /*
+ * parses the "depends on" portion of the XML file
+ */
+ //TODO(kprobst): not currently used, but will be for dependencies
+ /*private void parseDependsOn(final HashMap<String, CodeCollection> nameToCodeColl, Attributes attributes) {
+ if (attributes.getValue("idref") != null){
+ String curDepClassId = attributes.getValue("idref");
+
+ if (curDepClassId.contains(":")){
+ // strip everything after the :: (to get to class, even if it's a method)
+ curDepClassId = curDepClassId.replaceAll(":.*", "");
+ }
+ if (curDepClassId.contains("$")){
+ curDepClassId = curDepClassId.replaceAll("\\$.*", "");
+ }
+
+ if (! GlobalInformation.classToWhatItDependsOn.containsKey(curClassId)){
+ HashSet<String> insertSet = new HashSet<String>();
+ GlobalInformation.classToWhatItDependsOn.put(curClassId, insertSet);
+ }
+ else{
+ GlobalInformation.classToWhatItDependsOn.get(curClassId).add(curDepClassId);
+ }
+ }
+ }*/
+ };
+ return handler;
+ }
+
+
+
+
+ private static DefaultHandler scanXMLDocument() {
+
+ DefaultHandler handler = new DefaultHandler() {
+
+
+ /**
+ * This method deals with the beginning of the XML element.
+ * It analyzes the XML node and adds its information to the relevant literal or code collection for later analysis.
+ * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement(String nsUri, String strippedName, String tagName, Attributes attributes) {
+
+ if (strippedName.compareTo("js") == 0){
+ if (attributes.getValue("fragment") != null){
+ GlobalInformation.numFragments++;
+ }
+ }
+ }
+ };
+
+ return handler;
+ }
+
+
+ /*
+ * assigns code to "all other code" if none of the special categories apply
+ */
+ private static void updateAllOtherCodeType(final HashMap<String, CodeCollection> nameToCodeColl){
+ //all classes not in any of the other categories
+ for (String className : GlobalInformation.classToPackage.keySet()){
+ if ( (!nameToCodeColl.get("widget").classes.contains(className))&&
+ (!nameToCodeColl.get("rpcUser").classes.contains(className))&&
+ (!nameToCodeColl.get("rpcGwt").classes.contains(className))&&
+ (!nameToCodeColl.get("rpcGen").classes.contains(className))&&
+ (!nameToCodeColl.get("jre").classes.contains(className))&&
+ (!nameToCodeColl.get("gwtLang").classes.contains(className))){
+ nameToCodeColl.get("allOther").classes.add(className);
+ }
+ }
+ }
+
+ /*
+ * generates all the HTML files
+ */
+ private static void makeHTMLFiles(
+ final TreeMap<String, LiteralsCollection> nameToLitColl,
+ final HashMap<String, CodeCollection> nameToCodeColl) {
+
+ try {
+ MakeTopLevelHtmlForPerm.makePackageClassesHtmls();
+ MakeTopLevelHtmlForPerm.makeCodeTypeClassesHtmls(nameToCodeColl);
+ MakeTopLevelHtmlForPerm.makeLiteralsClassesHtmls(nameToLitColl);
+ MakeTopLevelHtmlForPerm.makeStringLiteralsClassesHtmls(nameToLitColl);
+ MakeTopLevelHtmlForPerm.makeFragmentClassesHtmls();
+
+ //make the shell last so we can display aggregate information here
+ MakeTopLevelHtmlForPerm.makeHTMLShell(nameToCodeColl, nameToLitColl);
+
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot open file. ", e);
+ }
+ }
+
+
+ /*
+ * cleans up the RPC code categories
+ */
+ private static void foldInRPCHeuristic(
+ final HashMap<String, CodeCollection> nameToCodeColl) {
+ /**
+ * Heuristic: this moves all classes that override serializable from RPC to "Other Code" *if* there is no RPC generated code, i.e., if the
+ * application really is not using RPC
+ */
+
+
+ if (nameToCodeColl.get("rpcGen").classes.size() == 0){
+
+ for (String className : nameToCodeColl.get("rpcUser").classes){
+
+ if ((! nameToCodeColl.get("widget").classes.contains(className))&&
+ (! nameToCodeColl.get("jre").classes.contains(className))&&
+ (! nameToCodeColl.get("gwtLang").classes.contains(className))){
+ nameToCodeColl.get("allOther").classes.add(className);
+ }
+ }
+ nameToCodeColl.get("rpcUser").classes.clear();
+
+ for (String className : nameToCodeColl.get("rpcGwt").classes){
+ if ((! nameToCodeColl.get("widget").classes.contains(className))&&
+ (! nameToCodeColl.get("jre").classes.contains(className))&&
+ (! nameToCodeColl.get("gwtLang").classes.contains(className))){
+ nameToCodeColl.get("allOther").classes.add(className);
+ }
+
+ }
+ nameToCodeColl.get("rpcGwt").classes.clear();
+ }
+
+
+ }
+
+
+ /*
+ * unescape the JS snippets - in the XML file they are XML encoded for correct display, but this
+ * will mess up the byte counts
+ */
+ public static String unEscapeXml(String escaped) {
+ String unescaped = escaped.replaceAll("&","\\&");
+ unescaped = unescaped.replaceAll("<","\\<");
+ unescaped = unescaped.replaceAll(">","\\>");
+ unescaped = unescaped.replaceAll(""","\\\"");
+ //escaped = escaped.replaceAll("\\n", "");
+ unescaped = unescaped.replaceAll("'","\\'");
+ return unescaped;
+ }
+
+
+
+
+}
+
+
+
+
+