001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2003,2004 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba.npe;
021:
022: import edu.umd.cs.findbugs.annotations.CheckForNull;
023: import edu.umd.cs.findbugs.ba.EdgeTypes;
024: import edu.umd.cs.findbugs.ba.vna.ValueNumber;
025: import edu.umd.cs.findbugs.util.Strings;
026: import edu.umd.cs.findbugs.util.Util;
027:
028: /**
029: * A control decision which resulted in information being gained
030: * about whether a particular value is null or non-null
031: * on the IFCMP_EDGE and FALL_THROUGH_EDGE branches.
032: *
033: * @see IsNullValue
034: * @see IsNullValueFrame
035: * @see IsNullValueAnalysis
036: */
037: public class IsNullConditionDecision implements EdgeTypes {
038: private final @CheckForNull
039: ValueNumber value;
040: private final @CheckForNull
041: IsNullValue ifcmpDecision;
042: private final @CheckForNull
043: IsNullValue fallThroughDecision;
044:
045: /**
046: * Constructor.
047: *
048: * @param value the ValueNumber for which we have new information; null if no
049: * new information
050: * @param ifcmpDecision the decision for the IFCMP_EDGE; null if that edge is not feasible
051: * @param fallThroughDecision the decision for the FALL_THROUGH_EDGE; null if that edge is not feasible
052: */
053: public IsNullConditionDecision(@CheckForNull
054: ValueNumber value, @CheckForNull
055: IsNullValue ifcmpDecision, @CheckForNull
056: IsNullValue fallThroughDecision) {
057: this .value = value;
058:
059: // At least one of the edges must be feasible
060: assert !(ifcmpDecision == null && fallThroughDecision == null);
061: this .ifcmpDecision = ifcmpDecision;
062: this .fallThroughDecision = fallThroughDecision;
063: }
064:
065: @Override
066: public int hashCode() {
067: return Util.nullSafeHashcode(value) + 5
068: * Util.nullSafeHashcode(ifcmpDecision) + 17
069: * Util.nullSafeHashcode(fallThroughDecision);
070: }
071:
072: @Override
073: public boolean equals(Object o) {
074: if (!(o instanceof IsNullConditionDecision))
075: return false;
076: IsNullConditionDecision other = (IsNullConditionDecision) o;
077: return Util.nullSafeEquals(value, other.value)
078: && Util.nullSafeEquals(ifcmpDecision,
079: other.ifcmpDecision)
080: && Util.nullSafeEquals(fallThroughDecision,
081: other.fallThroughDecision);
082: }
083:
084: /**
085: * Get the value about which the branch yields information.
086: */
087: public ValueNumber getValue() {
088: return value;
089: }
090:
091: /**
092: * Determine whether or not the comparison is redundant.
093: */
094: public boolean isRedundant() {
095: return ifcmpDecision == null || fallThroughDecision == null;
096: }
097:
098: /**
099: * Determine whether or not the given edge is feasible.
100: * An edge may be infeasible if the comparison is redundant (i.e.,
101: * can only be determined one way)
102: *
103: * @param edgeType the type of edge; must be IFCMP_EDGE or FALL_THROUGH_EDGE
104: * @return true if the edge is feasible, false if infeasible
105: */
106: public boolean isEdgeFeasible(int edgeType) {
107: IsNullValue decision = getDecision(edgeType);
108: return decision != null;
109: }
110:
111: /**
112: * Get the decision reached about the value on outgoing edge of given type.
113: *
114: * @param edgeType the type of edge; must be IFCMP_EDGE or FALL_THROUGH_EDGE
115: * @return the IsNullValue representing the decision, or null
116: * if the edge is infeasible
117: */
118: public @CheckForNull
119: IsNullValue getDecision(int edgeType) {
120: assert edgeType == IFCMP_EDGE || edgeType == FALL_THROUGH_EDGE;
121: if (edgeType == IFCMP_EDGE)
122: return ifcmpDecision;
123: else
124: return fallThroughDecision;
125: }
126:
127: @Override
128: public String toString() {
129: StringBuffer buf = new StringBuffer();
130: buf.append(value != null ? value.toString() : "NoValue,");
131: buf.append("ifcmp=");
132: buf.append(ifcmpDecision != null ? Strings
133: .trimComma(ifcmpDecision.toString()) : "INFEASIBLE");
134: buf.append(",fallthru=");
135: buf.append(fallThroughDecision != null ? Strings
136: .trimComma(fallThroughDecision.toString())
137: : "INFEASIBLE");
138: return buf.toString();
139: }
140: }
141:
142: // vim:ts=4
|