1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.shrink; 22 23import proguard.classfile.*; 24import proguard.classfile.visitor.*; 25 26 27/** 28 * This class can be used as a mark when keeping classes, class members, and 29 * other elements. It can be certain or preliminary. It also contains additional 30 * information about the reasons why an element is being kept. 31 * 32 * @see ClassShrinker 33 * 34 * @author Eric Lafortune 35 */ 36final class ShortestUsageMark 37{ 38 private final boolean certain; 39 private final String reason; 40 private final int depth; 41 private Clazz clazz; 42 private Member member; 43 44 45 /** 46 * Creates a new certain ShortestUsageMark. 47 * @param reason the reason for this mark. 48 */ 49 public ShortestUsageMark(String reason) 50 { 51 this.certain = true; 52 this.reason = reason; 53 this.depth = 0; 54 } 55 56 57 /** 58 * Creates a new certain ShortestUsageMark. 59 * @param previousUsageMark the previous mark to which this one is linked. 60 * @param reason the reason for this mark. 61 * @param clazz the class causing this mark. 62 */ 63 public ShortestUsageMark(ShortestUsageMark previousUsageMark, 64 String reason, 65 int cost, 66 Clazz clazz) 67 { 68 this(previousUsageMark, reason, cost, clazz, null); 69 } 70 71 72 /** 73 * Creates a new certain ShortestUsageMark. 74 * @param previousUsageMark the previous mark to which this one is linked. 75 * @param reason the reason for this mark. 76 * @param clazz the class causing this mark. 77 * @param member the member in the above class causing this mark. 78 * @param cost the added cost of following this path. 79 */ 80 public ShortestUsageMark(ShortestUsageMark previousUsageMark, 81 String reason, 82 int cost, 83 Clazz clazz, 84 Member member) 85 { 86 this.certain = true; 87 this.reason = reason; 88 this.depth = previousUsageMark.depth + cost; 89 this.clazz = clazz; 90 this.member = member; 91 } 92 93 94 /** 95 * Creates a new ShortestUsageMark, based on another mark. 96 * @param otherUsageMark the other mark, whose properties will be copied. 97 * @param certain specifies whether this is a certain mark. 98 */ 99 public ShortestUsageMark(ShortestUsageMark otherUsageMark, 100 boolean certain) 101 { 102 this.certain = certain; 103 this.reason = otherUsageMark.reason; 104 this.depth = otherUsageMark.depth; 105 this.clazz = otherUsageMark.clazz; 106 this.member = otherUsageMark.member; 107 } 108 109 110 /** 111 * Returns whether this is a certain mark. 112 */ 113 public boolean isCertain() 114 { 115 return certain; 116 } 117 118 119 /** 120 * Returns the reason for this mark. 121 */ 122 public String getReason() 123 { 124 return reason; 125 } 126 127 128 /** 129 * Returns whether this mark has a shorter chain of reasons than the 130 * given mark. 131 */ 132 public boolean isShorter(ShortestUsageMark otherUsageMark) 133 { 134 return this.depth < otherUsageMark.depth; 135 } 136 137 138 /** 139 * Returns whether this is mark is caused by the given class. 140 */ 141 public boolean isCausedBy(Clazz clazz) 142 { 143 return clazz.equals(this.clazz); 144 } 145 146 147 /** 148 * Applies the given class visitor to this mark's class, if any, 149 * and if this mark doesn't have a member. 150 */ 151 public void acceptClassVisitor(ClassVisitor classVisitor) 152 { 153 if (clazz != null && 154 member == null) 155 { 156 clazz.accept(classVisitor); 157 } 158 } 159 160 161 /** 162 * Applies the given class visitor to this mark's member, if any. 163 */ 164 public void acceptMemberVisitor(MemberVisitor memberVisitor) 165 { 166 if (clazz != null && 167 member != null) 168 { 169 member.accept(clazz, memberVisitor); 170 } 171 } 172 173 174 // Implementations for Object. 175 176 public String toString() 177 { 178 return "certain=" + certain + ", depth="+depth+": " + 179 reason + 180 (clazz != null ? clazz.getName() : "(none)") + ": " + 181 (member != null ? member.getName(clazz) : "(none)"); 182 } 183} 184