/* * Cobertura - http://cobertura.sourceforge.net/ * * Copyright (C) 2011 Piotr Tabor * * Note: This file is dual licensed under the GPL and the Apache * Source License (so that it can be used from both the main * Cobertura classes and the ant tasks). * * Cobertura is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Cobertura is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cobertura; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ package net.sourceforge.cobertura.instrument.tp; import net.sourceforge.cobertura.coveragedata.LineData; import org.objectweb.asm.Label; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** * Class representing a touch-point connected to a a SWITCH instruction in a source-code * <p/> * <p>A SWITCH touch-point uses one more counter then distinct number destination labels ({@link #getCountersForLabelsCnt()}).<br/> * One 'internal' counterId ({@link #counterId}) is a special identifier of SWITCH statement (used in runtime), but in fact we don't expect any * incrementation of the counter. We implemented this to use a counterId because we are storing the value inside 'internal variable' and we need to be sure * that the value is connected to the last seen SWITCH statement.<br/> * <p/> * Or other counterIds represents different branches (different destination labels of the switch). * </p> * <p/> * <p>We also storing a {@link #methodName} and a {@link #methodSignature} (consider to move this fields into {@link TouchPointDescriptor}). * Those fields are needed to properly create instance of {@link LineData}. </p> * * @author piotr.tabor@gmail.com */ public class SwitchTouchPointDescriptor extends TouchPointDescriptor { private final Label defaultDestinationLabel; private final Label[] labels; /** * Encoded as: {@link org.objectweb.asm.commons#AnalyzerAdapter#stack} */ private final String enum_type; private Integer counterId; private Map<Label, Integer> label2counterId; /** * Creates o new switch-touch point. * * @param eventId - eventId connected to the SWITCH instruction * @param currentLine - line number of the switch * @param def - internal identifier of a default destination label * @param labels - table of other destination labels for different values (duplicates allowed) */ public SwitchTouchPointDescriptor(int eventId, int currentLine, Label def, Label[] labels, String enum_type) { super(eventId, currentLine); this.labels = labels; this.defaultDestinationLabel = def; this.enum_type = enum_type; } public Integer getCounterId() { return counterId; } public void setCounterId(Integer counterId) { this.counterId = counterId; } @Override public int assignCounters(AtomicInteger idGenerator) { counterId = idGenerator.incrementAndGet(); label2counterId = new HashMap<Label, Integer>(); int idp = idGenerator.incrementAndGet(); label2counterId.put(defaultDestinationLabel, idp); int i = 0; for (Label l : labels) { i++; idp = idGenerator.incrementAndGet(); label2counterId.put(l, idp); } return i + 2; } public Integer getCounterIdForLabel(Label label) { return label2counterId.get(label); } public Collection<Integer> getCountersForLabels() { return label2counterId.values(); } /** * <p>Works before calling 'assignCounters'</p> * * @return Number of distinct destination labels of the SWITCH (It's the same as number of branches supported by the switch). */ public int getCountersForLabelsCnt() { Set<Label> l = new HashSet<Label>(Arrays.asList(labels)); l.add(defaultDestinationLabel); return l.size(); } public String getEnumType() { return enum_type; } }