001    /*
002     * Cobertura - http://cobertura.sourceforge.net/
003     *
004     * Copyright (C) 2006 Jiri Mares
005     *
006     * Cobertura is free software; you can redistribute it and/or modify
007     * it under the terms of the GNU General Public License as published
008     * by the Free Software Foundation; either version 2 of the License,
009     * or (at your option) any later version.
010     *
011     * Cobertura is distributed in the hope that it will be useful, but
012     * WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014     * General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with Cobertura; if not, write to the Free Software
018     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019     * USA
020     */
021    
022    package net.sourceforge.cobertura.coveragedata;
023    
024    import java.io.Serializable;
025    import java.util.Arrays;
026    
027    /**
028     * <p>
029     * This class implements HasBeenInstrumented so that when cobertura instruments
030     * itself, it will omit this class. It does this to avoid an infinite recursion
031     * problem because instrumented classes make use of this class.
032     * </p>
033     */
034    public class SwitchData implements BranchCoverageData, Comparable, Serializable,
035                    HasBeenInstrumented
036    {
037            private static final long serialVersionUID = 9;
038    
039            private int switchNumber;
040            
041            private long defaultHits;
042    
043            private long[] hits;
044            
045            private int[] keys;
046    
047            public SwitchData(int switchNumber, int[] keys)
048            {
049                    super();
050                    this.switchNumber = switchNumber;
051                    defaultHits = 0;
052                    hits = new long[keys.length];
053                    Arrays.fill(hits, 0);
054                    this.keys = new int[keys.length];
055                    System.arraycopy(keys, 0, this.keys, 0, keys.length);
056            }
057    
058            public SwitchData(int switchNumber, int min, int max)
059            {
060                    super();
061                    this.switchNumber = switchNumber;
062                    defaultHits = 0;
063                    hits = new long[max - min + 1];
064                    Arrays.fill(hits, 0);
065                    this.keys = new int[max - min + 1];
066                    for (int i = 0; min <= max; keys[i++] = min++);
067            }
068    
069            public SwitchData(int switchNumber)
070            {
071                    this(switchNumber, new int[0]);
072            }
073    
074            public int compareTo(Object o)
075            {
076                    if (!o.getClass().equals(SwitchData.class))
077                            return Integer.MAX_VALUE;
078                    return this.switchNumber - ((SwitchData) o).switchNumber;
079            }
080            
081            void touchBranch(int branch) 
082            {
083                    if (branch == -1)
084                            defaultHits++;
085                    else 
086                    {
087                            if (hits.length <= branch)
088                            {
089                                    long[] old = hits;
090                                    hits = new long[branch + 1];
091                                    System.arraycopy(old, 0, hits, 0, old.length);
092                                    Arrays.fill(hits, old.length, hits.length - 1, 0);
093                            }
094                            hits[branch]++;
095                    }
096            }
097            
098            public int getSwitchNumber()
099            {
100                    return this.switchNumber;
101            }
102    
103            public long getHits(int branch)
104            {
105                    if (hits.length > branch)
106                            return hits[branch];
107                    return -1;
108            }
109    
110            public long getDefaultHits()
111            {
112                    return defaultHits;
113            }
114    
115            public double getBranchCoverageRate()
116            {
117                    int branches = hits.length + 1;
118                    int hit = (defaultHits > 0) ? 1 : 0;
119                    for (int i = hits.length - 1; i >= 0; hit += ((hits[i--] > 0) ? 1 : 0));
120                    return ((double) hit) / branches;
121            }
122    
123            public boolean equals(Object obj)
124            {
125                    if (this == obj)
126                            return true;
127                    if ((obj == null) || !(obj.getClass().equals(this.getClass())))
128                            return false;
129    
130                    SwitchData switchData = (SwitchData) obj;
131                    return (this.defaultHits == switchData.defaultHits)
132                                    && (Arrays.equals(this.hits, switchData.hits))
133                                    && (this.switchNumber == switchData.switchNumber);
134            }
135    
136            public int hashCode()
137            {
138                    return this.switchNumber;
139            }
140    
141            public int getNumberOfCoveredBranches()
142            {
143                    int ret = (defaultHits > 0) ? 1 : 0;
144                    for (int i = hits.length -1; i >= 0;i--) 
145                    {
146                            if (hits[i] > 0) ret++;
147                    }
148                    return ret;
149            }
150    
151            public int getNumberOfValidBranches()
152            {
153                    return hits.length + 1;
154            }
155    
156            public void merge(BranchCoverageData coverageData)
157            {
158                    SwitchData switchData = (SwitchData) coverageData;
159                    defaultHits += switchData.defaultHits;
160                    for (int i = Math.min(hits.length, switchData.hits.length) - 1; i >= 0; i--)
161                            hits[i] += switchData.hits[i];
162                    if (switchData.hits.length > hits.length)
163                    {
164                            long[] old = hits;
165                            hits = new long[switchData.hits.length];
166                            System.arraycopy(old, 0, hits, 0, old.length);
167                            System.arraycopy(switchData.hits, old.length, hits, old.length, hits.length - old.length);
168                    }
169                    if ((this.keys.length == 0) && (switchData.keys.length > 0))
170                            this.keys = switchData.keys;
171            }
172    
173    }