/* * 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.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; /** * Compile Report information about a compiled module. */ public class GlobalInformation { private static final SizeBreakdown[] EMPTY_SIZE_BREAKDOWN = new SizeBreakdown[0]; public Map<String, Map<String, String>> dependencies = null; private Map<String, String> classToPackage = new TreeMap<String, String>(); private HashMap<String, HashSet<String>> classToWhatItDependsOn = new HashMap<String, HashSet<String>>(); private Map<Integer, SizeBreakdown> exclusiveCodeBreakdowns = new HashMap<Integer, SizeBreakdown>(); private SizeBreakdown initialCodeBreakdown = new SizeBreakdown( "Initially downloaded code", "initial"); private SizeBreakdown leftoversBreakdown = new SizeBreakdown( "Leftovers code, code not in any other fragment", "leftovers"); private Map<String, TreeSet<String>> packageToClasses = new TreeMap<String, TreeSet<String>>(); private final String permutationId; private ArrayList<Integer> initialFragmentLoadSequence = new ArrayList<Integer>(); private HashMap<Integer, List<String>> fragmentDescriptors = new HashMap<Integer, List<String>>(); private SizeBreakdown totalCodeBreakdown = new SizeBreakdown("Total program", "total"); public GlobalInformation(String permutationId) { this.permutationId = permutationId; } public SizeBreakdown[] allSizeBreakdowns() { List<SizeBreakdown> breakdowns = new ArrayList<SizeBreakdown>(); breakdowns.add(totalCodeBreakdown); breakdowns.add(initialCodeBreakdown); if (getNumFragments() > 0) { breakdowns.add(leftoversBreakdown); for (int fragment = 1; fragment <= getNumFragments(); fragment++) { breakdowns.add(fragmentCodeBreakdown(fragment)); } } return breakdowns.toArray(EMPTY_SIZE_BREAKDOWN); } /** * Computes all package sizes. */ public void computePackageSizes() { for (SizeBreakdown breakdown : allSizeBreakdowns()) { computePackageSizes(breakdown.packageToSize, breakdown.classToSize); } } /** * Gets the mapping from each class to its package. * * @return classToPackage */ public final Map<String, String> getClassToPackage() { return classToPackage; } /** * Gets the mapping from a class to what it depends on. * * @return classToWhatItDependsOn */ public final HashMap<String, HashSet<String>> getClassToWhatItDependsOn() { return classToWhatItDependsOn; } /** * Gets the exclusive code breakdown. * * @return exclusiveCodeBreakdown */ public final Map<Integer, SizeBreakdown> getExclusiveCodeBreakdowns() { return exclusiveCodeBreakdowns; } /** * Gets the initial fragment size breakdown. * * @return initialCodeBreakdown */ public final SizeBreakdown getInitialCodeBreakdown() { return initialCodeBreakdown; } /** * Gets the leftovers fragment size breakdown. * * @return leftoversCodeBreakdown */ public final SizeBreakdown getLeftoversBreakdown() { return leftoversBreakdown; } /** * Gets the number of fragments.. * * @return the number of fragments. */ public final int getNumFragments() { return fragmentDescriptors.size(); } /** * Gets the mapping from packages to classes. * * @return packageToClasses */ public final Map<String, TreeSet<String>> getPackageToClasses() { return packageToClasses; } public String getPermutationId() { return permutationId; } /** * Gets the initial load sequence. * * @return initialFragmentLoadSequence */ public final ArrayList<Integer> getInitialFragmentLoadSequence() { return initialFragmentLoadSequence; } /** * Adds a descriptor (a split point) to a fragment. * * @param fragment the fragment number. * @param desc a string describing a split point for fragment <code>fragment</code> * */ public final void addFragmentDescriptor(int fragment, String desc) { List<String> descriptions = fragmentDescriptors.get(fragment); if (descriptions == null) { descriptions = new ArrayList<String>(); fragmentDescriptors.put(fragment, descriptions); } descriptions.add(desc); } /** * Gets the descriptors associated with a * fragment. * * @param fragment the fragment number * @return a list of descriptors (each representing a single split point. */ public final List<String> getFragmentDescriptors(int fragment) { return fragmentDescriptors.get(fragment); } /** * Gets the total code breakdown. * * @return totalCodeBreakdown */ public final SizeBreakdown getTotalCodeBreakdown() { return totalCodeBreakdown; } /** * Gets an exclusive code breakdown for a fragment. * * @param fragment the fragment id * @return exlusive code breakdown for fragment */ public SizeBreakdown fragmentCodeBreakdown(int fragment) { assert fragment >= 1 && fragment <= getNumFragments(); if (!exclusiveCodeBreakdowns.containsKey(fragment)) { exclusiveCodeBreakdowns.put(fragment, new SizeBreakdown("split point " + fragment + ": " + fragmentDescriptors.get(fragment), "fragment" + fragment)); } return exclusiveCodeBreakdowns.get(fragment); } /** * Computes package sizes from class sizes. TODO(spoon) move this to the * SizeBreakdown class. * * @param packageToSize mapping from packages to their sizes * @param classToSize mapping from classes to their sizes */ private void computePackageSizes(Map<String, Integer> packageToSize, Map<String, Integer> classToSize) { packageToSize.clear(); for (String packageName : packageToClasses.keySet()) { packageToSize.put(packageName, 0); for (String className : packageToClasses.get(packageName)) { if (classToSize.containsKey(className)) { int curSize = classToSize.get(className); int newSize = curSize + packageToSize.get(packageName); packageToSize.put(packageName, newSize); } } } } }