001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.loadtest.data;
014:
015: import java.beans.PropertyChangeEvent;
016: import java.beans.PropertyChangeListener;
017: import java.util.ArrayList;
018: import java.util.HashMap;
019: import java.util.List;
020: import java.util.Map;
021:
022: import javax.swing.table.AbstractTableModel;
023:
024: import org.apache.log4j.Logger;
025:
026: import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
027: import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
028: import com.eviware.soapui.model.testsuite.LoadTest;
029: import com.eviware.soapui.model.testsuite.LoadTestRunContext;
030: import com.eviware.soapui.model.testsuite.LoadTestRunner;
031: import com.eviware.soapui.model.testsuite.TestCase;
032: import com.eviware.soapui.model.testsuite.TestRunContext;
033: import com.eviware.soapui.model.testsuite.TestRunner;
034: import com.eviware.soapui.model.testsuite.TestStep;
035: import com.eviware.soapui.model.testsuite.TestStepResult;
036:
037: /**
038: * TableModel holding loadtest samples
039: */
040:
041: public class SamplesModel extends AbstractTableModel {
042: private final LoadTest loadTest;
043: private List<TestSample[]> samples = new ArrayList<TestSample[]>();
044: private InternalTestRunListener testRunListener;
045: private InternalTestSuiteListener testSuiteListener;
046: private InternalPropertyChangeListener propertyChangeListener;
047: private TestCase testCase;
048: private final static Logger log = Logger
049: .getLogger(SamplesModel.class);
050:
051: public SamplesModel(LoadTest loadTest) {
052: this .loadTest = loadTest;
053:
054: testRunListener = new InternalTestRunListener();
055: testSuiteListener = new InternalTestSuiteListener();
056: propertyChangeListener = new InternalPropertyChangeListener();
057:
058: testCase = loadTest.getTestCase();
059: loadTest.addLoadTestRunListener(testRunListener);
060: testCase.getTestSuite().addTestSuiteListener(testSuiteListener);
061:
062: for (TestStep testStep : testCase.getTestStepList()) {
063: testStep.addPropertyChangeListener(TestStep.NAME_PROPERTY,
064: propertyChangeListener);
065: }
066: }
067:
068: public int getRowCount() {
069: return samples.size();
070: }
071:
072: public int getColumnCount() {
073: return testCase.getTestStepCount();
074: }
075:
076: public Object getValueAt(int rowIndex, int columnIndex) {
077: TestSample[] testSamples = samples.get(rowIndex);
078: return testSamples == null ? "discarded"
079: : testSamples[columnIndex];
080: }
081:
082: public void addSamples(TestSample[] newSamples) {
083: if (newSamples.length != getColumnCount())
084: throw new RuntimeException(
085: "Invalid number of samples reported: "
086: + newSamples.length + ", expected "
087: + getColumnCount());
088:
089: samples.add(newSamples);
090:
091: fireTableRowsInserted(samples.size() - 1, samples.size() - 1);
092: }
093:
094: public Class<?> getColumnClass(int columnIndex) {
095: return TestSample.class;
096: }
097:
098: public String getColumnName(int column) {
099: return testCase.getTestStepAt(column).getName();
100: }
101:
102: public void clear() {
103: int size = samples.size();
104: if (size > 0) {
105: samples.clear();
106: fireTableRowsDeleted(0, size);
107: }
108: }
109:
110: /**
111: * Listener for collecting samples
112: *
113: * @author Ole.Matzura
114: */
115:
116: private class InternalTestRunListener extends
117: LoadTestRunListenerAdapter {
118: public void afterTestCase(LoadTestRunner loadTestRunner,
119: LoadTestRunContext context, TestRunner testRunner,
120: TestRunContext runContext) {
121: Map<TestStep, TestSample> samplesMap = new HashMap<TestStep, TestSample>();
122: List<TestStepResult> results = testRunner.getResults();
123:
124: for (int c = 0; c < results.size(); c++) {
125: TestStepResult result = results.get(c);
126: if (result == null) {
127: log.warn("Result [" + c + "] is null in TestCase ["
128: + testCase.getName() + "]");
129: continue;
130: }
131:
132: TestStep testStep = result.getTestStep();
133:
134: if (!samplesMap.containsKey(testStep)) {
135: samplesMap.put(testStep, new TestSample(testStep));
136: }
137:
138: samplesMap.get(testStep).addTestStepResult(result);
139: }
140:
141: TestCase testCase = loadTest.getTestCase();
142:
143: TestSample[] samples = new TestSample[testCase
144: .getTestStepCount()];
145: for (int c = 0; c < samples.length; c++) {
146: samples[c] = samplesMap.get(testCase.getTestStepAt(c));
147: }
148:
149: addSamples(samples);
150: }
151: }
152:
153: public List<TestSample[]> getSamples() {
154: return samples;
155: }
156:
157: public void release() {
158: loadTest.removeLoadTestRunListener(testRunListener);
159: loadTest.getTestCase().getTestSuite().removeTestSuiteListener(
160: testSuiteListener);
161:
162: for (TestStep testStep : loadTest.getTestCase()
163: .getTestStepList()) {
164: testStep
165: .removePropertyChangeListener(propertyChangeListener);
166: }
167: }
168:
169: /**
170: * Holder for a TestSample
171: *
172: * @author ole.matzura
173: */
174:
175: public static final class TestSample {
176: private final TestStep testStep;
177: private List<TestStepResult> results;
178:
179: public TestSample(TestStep testStep) {
180: this .testStep = testStep;
181: }
182:
183: public void addTestStepResult(TestStepResult result) {
184: if (result.getTestStep() != testStep)
185: throw new RuntimeException(
186: "Trying to add sample for false testStep ["
187: + result.getTestStep().getName()
188: + "], " + "expecting ["
189: + testStep.getName() + "]");
190:
191: if (results == null)
192: results = new ArrayList<TestStepResult>();
193:
194: results.add(result);
195: }
196:
197: public List<TestStepResult> getResults() {
198: return results;
199: }
200:
201: public int getResultCount() {
202: return results == null ? 0 : results.size();
203: }
204:
205: public long getResultAverage() {
206: if (results == null)
207: return 0;
208:
209: if (results.size() == 1)
210: return results.get(0).getTimeTaken();
211:
212: long sum = 0;
213: for (TestStepResult result : results)
214: sum += result.getTimeTaken();
215:
216: return sum / results.size();
217: }
218: }
219:
220: private class InternalTestSuiteListener extends
221: TestSuiteListenerAdapter {
222: public void testStepAdded(TestStep testStep, int index) {
223: if (testStep.getTestCase() == testCase) {
224: testStep.addPropertyChangeListener(
225: TestStep.NAME_PROPERTY, propertyChangeListener);
226:
227: // insert null entry in existing samples
228: for (int i = 0; i < samples.size(); i++) {
229: TestSample[] testSamples = samples.get(i);
230: TestSample[] newSamples = new TestSample[testSamples.length + 1];
231: for (int c = 0; c < testSamples.length; c++) {
232: if (c < index) {
233: newSamples[c] = testSamples[c];
234: } else {
235: newSamples[c + 1] = testSamples[c];
236: }
237: }
238:
239: samples.set(i, newSamples);
240: }
241:
242: fireTableStructureChanged();
243: }
244: }
245:
246: public void testStepRemoved(TestStep testStep, int index) {
247: if (testStep.getTestCase() == testCase) {
248: testStep
249: .removePropertyChangeListener(propertyChangeListener);
250:
251: // remove from samples
252: for (int i = 0; i < samples.size(); i++) {
253: TestSample[] testSamples = samples.get(i);
254: TestSample[] newSamples = new TestSample[testSamples.length - 1];
255: for (int c = 0; c < testSamples.length; c++) {
256: if (c < index) {
257: newSamples[c] = testSamples[c];
258: } else if (c > index) {
259: newSamples[c - 1] = testSamples[c];
260: }
261: }
262:
263: samples.set(i, newSamples);
264: }
265:
266: fireTableStructureChanged();
267: }
268: }
269: }
270:
271: private class InternalPropertyChangeListener implements
272: PropertyChangeListener {
273: public void propertyChange(PropertyChangeEvent evt) {
274: fireTableStructureChanged();
275: }
276: }
277:
278: }
|