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
022package net.sourceforge.cobertura.coveragedata;
023
024import java.io.Serializable;
025import java.util.Arrays;
026
027import net.sourceforge.cobertura.CoverageIgnore;
028
029@CoverageIgnore
030public class SwitchData implements BranchCoverageData, Comparable<Object>, Serializable {
031        private static final long serialVersionUID = 9;
032
033        private int switchNumber;
034        
035        private long defaultHits;
036
037        private long[] hits;
038        
039        private int[] keys;
040        
041        private int maxBranches;
042
043        public SwitchData(int switchNumber, int[] keys, int maxBranches) {
044                this.switchNumber = switchNumber;
045                defaultHits = 0;
046                hits = new long[keys.length];
047                Arrays.fill(hits, 0);
048                this.keys = new int[keys.length];
049                System.arraycopy(keys, 0, this.keys, 0, keys.length);
050                this.maxBranches = maxBranches;
051        }
052
053        public SwitchData(int switchNumber, int min, int max, int maxBranches) {
054                this.switchNumber = switchNumber;
055                defaultHits = 0;
056                hits = new long[max - min + 1];
057                Arrays.fill(hits, 0);
058                this.keys = new int[max - min + 1];
059                for (int i = 0; min <= max; keys[i++] = min++);
060                this.maxBranches = maxBranches;         
061        }
062
063        public SwitchData(int switchNumber, int maxBranches) {
064                this(switchNumber, new int[0], maxBranches);
065        }
066
067        public int compareTo(Object o) {
068                if (!o.getClass().equals(SwitchData.class))
069                        return Integer.MAX_VALUE;
070                return this.switchNumber - ((SwitchData) o).switchNumber;
071        }
072        
073        void touchBranch(int branch,int new_hits) {
074                if (branch == -1) {
075                        defaultHits+=new_hits;
076                } else {
077                        if (hits.length <= branch) {
078                                long[] old = hits;
079                                hits = new long[branch + 1];
080                                System.arraycopy(old, 0, hits, 0, old.length);
081                                Arrays.fill(hits, old.length, hits.length - 1, 0);
082                        }
083                        hits[branch]+=new_hits;
084                }
085        }
086        
087        public int getSwitchNumber() {
088                return this.switchNumber;
089        }
090
091        public long getHits(int branch) {
092                return (hits.length > branch) ? hits[branch] : -1;              
093        }
094
095        public long getDefaultHits() {
096                return defaultHits;
097        }
098
099        public double getBranchCoverageRate() {
100                int branches = getNumberOfValidBranches();
101                int hit = (defaultHits > 0) ? 1 : 0;
102                for (int i = hits.length - 1; i >= 0; hit += ((hits[i--] > 0) ? 1 : 0));
103                return ((double) hit) / branches;
104        }
105
106        public boolean equals(Object obj) {
107                if (this == obj)
108                        return true;
109                if ((obj == null) || !(obj.getClass().equals(this.getClass())))
110                        return false;
111
112                SwitchData switchData = (SwitchData) obj;
113                return (this.defaultHits == switchData.defaultHits)
114                                && (Arrays.equals(this.hits, switchData.hits))
115                                && (this.switchNumber == switchData.switchNumber);
116        }
117
118        public int hashCode() {
119                return this.switchNumber;
120        }
121
122        public int getNumberOfCoveredBranches() {
123                int ret = (defaultHits > 0) ? 1 : 0;
124                for (int i = hits.length -1; i >= 0;i--) 
125                {
126                        if (hits[i] > 0) ret++;
127                }
128                return ret;
129        }
130
131        public int getNumberOfValidBranches() {
132                return Math.min(hits.length + 1, maxBranches);          
133        }
134
135        public void merge(BranchCoverageData coverageData) {
136                SwitchData switchData = (SwitchData) coverageData;
137                defaultHits += switchData.defaultHits;
138                for (int i = Math.min(hits.length, switchData.hits.length) - 1; i >= 0; i--)
139                        hits[i] += switchData.hits[i];
140                if (switchData.hits.length > hits.length)
141                {
142                        long[] old = hits;
143                        hits = new long[switchData.hits.length];
144                        System.arraycopy(old, 0, hits, 0, old.length);
145                        System.arraycopy(switchData.hits, old.length, hits, old.length, hits.length - old.length);
146                }
147                if ((this.keys.length == 0) && (switchData.keys.length > 0))
148                        this.keys = switchData.keys;
149                maxBranches = Math.min(maxBranches, switchData.getMaxBranches());
150        }
151        
152        public int getMaxBranches() {
153                return maxBranches;
154        }
155        
156        public void setMaxBranches(int maxBranches) {
157                this.maxBranches = maxBranches;
158        }
159}