001: /*
002: * Copyright (c) 2001-2007, Jean Tessier
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * * Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * * Neither the name of Jean Tessier nor the names of his contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032:
033: package com.jeantessier.metrics;
034:
035: import java.io.*;
036:
037: import org.apache.log4j.*;
038:
039: /**
040: * <p>Divides one measurement (base) by another (divider). Both
041: * must be in the same context.</p>
042: *
043: * <p>This is the syntax for initializing this type of
044: * measurement:</p>
045: *
046: * <pre>
047: * <init>
048: * base measurement name [DISPOSE_x]
049: * divider measurement name [DISPOSE_x]
050: * </init>
051: * </pre>
052: *
053: * <p>If either is missing, this measurement will be NaN.</p>
054: */
055: public class RatioMeasurement extends MeasurementBase {
056: private String baseName;
057: private int baseDispose;
058: private String dividerName;
059: private int dividerDispose;
060:
061: private double value = 0.0;
062:
063: public RatioMeasurement(MeasurementDescriptor descriptor,
064: Metrics context, String initText) {
065: super (descriptor, context, initText);
066:
067: try {
068: BufferedReader in = new BufferedReader(new StringReader(
069: initText));
070:
071: synchronized (perl()) {
072: baseName = in.readLine().trim();
073: if (perl()
074: .match("/(.*)\\s+(dispose_\\w+)$/i", baseName)) {
075: baseName = perl().group(1);
076:
077: String disposeText = perl().group(2);
078:
079: if (disposeText.equalsIgnoreCase("DISPOSE_IGNORE")) {
080: baseDispose = StatisticalMeasurement.DISPOSE_IGNORE;
081: } else if (disposeText
082: .equalsIgnoreCase("DISPOSE_MINIMUM")) {
083: baseDispose = StatisticalMeasurement.DISPOSE_MINIMUM;
084: } else if (disposeText
085: .equalsIgnoreCase("DISPOSE_MEDIAN")) {
086: baseDispose = StatisticalMeasurement.DISPOSE_MEDIAN;
087: } else if (disposeText
088: .equalsIgnoreCase("DISPOSE_AVERAGE")) {
089: baseDispose = StatisticalMeasurement.DISPOSE_AVERAGE;
090: } else if (disposeText
091: .equalsIgnoreCase("DISPOSE_STANDARD_DEVIATION")) {
092: baseDispose = StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION;
093: } else if (disposeText
094: .equalsIgnoreCase("DISPOSE_MAXIMUM")) {
095: baseDispose = StatisticalMeasurement.DISPOSE_MAXIMUM;
096: } else if (disposeText
097: .equalsIgnoreCase("DISPOSE_SUM")) {
098: baseDispose = StatisticalMeasurement.DISPOSE_SUM;
099: } else if (disposeText
100: .equalsIgnoreCase("DISPOSE_NB_DATA_POINTS")) {
101: baseDispose = StatisticalMeasurement.DISPOSE_NB_DATA_POINTS;
102: } else {
103: baseDispose = StatisticalMeasurement.DISPOSE_IGNORE;
104: }
105: } else {
106: baseDispose = StatisticalMeasurement.DISPOSE_IGNORE;
107: }
108:
109: dividerName = in.readLine().trim();
110: if (perl().match("/(.*)\\s+(dispose_\\w+)$/i",
111: dividerName)) {
112: dividerName = perl().group(1);
113:
114: String disposeText = perl().group(2);
115:
116: if (disposeText.equalsIgnoreCase("DISPOSE_IGNORE")) {
117: dividerDispose = StatisticalMeasurement.DISPOSE_IGNORE;
118: } else if (disposeText
119: .equalsIgnoreCase("DISPOSE_MINIMUM")) {
120: dividerDispose = StatisticalMeasurement.DISPOSE_MINIMUM;
121: } else if (disposeText
122: .equalsIgnoreCase("DISPOSE_MEDIAN")) {
123: dividerDispose = StatisticalMeasurement.DISPOSE_MEDIAN;
124: } else if (disposeText
125: .equalsIgnoreCase("DISPOSE_AVERAGE")) {
126: dividerDispose = StatisticalMeasurement.DISPOSE_AVERAGE;
127: } else if (disposeText
128: .equalsIgnoreCase("DISPOSE_STANDARD_DEVIATION")) {
129: dividerDispose = StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION;
130: } else if (disposeText
131: .equalsIgnoreCase("DISPOSE_MAXIMUM")) {
132: dividerDispose = StatisticalMeasurement.DISPOSE_MAXIMUM;
133: } else if (disposeText
134: .equalsIgnoreCase("DISPOSE_SUM")) {
135: dividerDispose = StatisticalMeasurement.DISPOSE_SUM;
136: } else if (disposeText
137: .equalsIgnoreCase("DISPOSE_NB_DATA_POINTS")) {
138: dividerDispose = StatisticalMeasurement.DISPOSE_NB_DATA_POINTS;
139: } else {
140: dividerDispose = StatisticalMeasurement.DISPOSE_IGNORE;
141: }
142: } else {
143: dividerDispose = StatisticalMeasurement.DISPOSE_IGNORE;
144: }
145: }
146:
147: in.close();
148: } catch (Exception ex) {
149: Logger.getLogger(getClass()).debug(
150: "Cannot initialize with \"" + initText + "\"", ex);
151: baseName = null;
152: dividerName = null;
153: }
154: }
155:
156: public String getBaseName() {
157: return baseName;
158: }
159:
160: public int getBaseDispose() {
161: return baseDispose;
162: }
163:
164: public String getDividerName() {
165: return dividerName;
166: }
167:
168: public int getDividerDispose() {
169: return dividerDispose;
170: }
171:
172: public void accept(MeasurementVisitor visitor) {
173: visitor.visitRatioMeasurement(this );
174: }
175:
176: public boolean isEmpty() {
177: if (!isCached()) {
178: compute();
179: }
180:
181: return super .isEmpty();
182: }
183:
184: protected double compute() {
185: if (!isCached()) {
186: value = Double.NaN;
187:
188: if (getContext() != null && getBaseName() != null
189: && getDividerName() != null) {
190: Measurement base = getContext().getMeasurement(
191: getBaseName());
192: Measurement divider = getContext().getMeasurement(
193: getDividerName());
194:
195: double baseValue = Double.NaN;
196: double dividerValue = Double.NaN;
197:
198: if (base instanceof StatisticalMeasurement) {
199: StatisticalMeasurement stats = (StatisticalMeasurement) base;
200:
201: switch (getBaseDispose()) {
202: case StatisticalMeasurement.DISPOSE_MINIMUM:
203: baseValue = stats.getMinimum();
204: break;
205: case StatisticalMeasurement.DISPOSE_MEDIAN:
206: baseValue = stats.getMedian();
207: break;
208: case StatisticalMeasurement.DISPOSE_AVERAGE:
209: baseValue = stats.getAverage();
210: break;
211: case StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION:
212: baseValue = stats.getStandardDeviation();
213: break;
214: case StatisticalMeasurement.DISPOSE_MAXIMUM:
215: baseValue = stats.getMaximum();
216: break;
217: case StatisticalMeasurement.DISPOSE_SUM:
218: baseValue = stats.getSum();
219: break;
220: case StatisticalMeasurement.DISPOSE_NB_DATA_POINTS:
221: baseValue = stats.getNbDataPoints();
222: break;
223: case StatisticalMeasurement.DISPOSE_IGNORE:
224: default:
225: baseValue = stats.doubleValue();
226: break;
227: }
228: } else if (base != null) {
229: baseValue = base.doubleValue();
230: }
231:
232: if (divider instanceof StatisticalMeasurement) {
233: StatisticalMeasurement stats = (StatisticalMeasurement) divider;
234:
235: switch (getDividerDispose()) {
236: case StatisticalMeasurement.DISPOSE_MINIMUM:
237: dividerValue = stats.getMinimum();
238: break;
239: case StatisticalMeasurement.DISPOSE_MEDIAN:
240: dividerValue = stats.getMedian();
241: break;
242: case StatisticalMeasurement.DISPOSE_AVERAGE:
243: dividerValue = stats.getAverage();
244: break;
245: case StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION:
246: dividerValue = stats.getStandardDeviation();
247: break;
248: case StatisticalMeasurement.DISPOSE_MAXIMUM:
249: dividerValue = stats.getMaximum();
250: break;
251: case StatisticalMeasurement.DISPOSE_SUM:
252: dividerValue = stats.getSum();
253: break;
254: case StatisticalMeasurement.DISPOSE_NB_DATA_POINTS:
255: dividerValue = stats.getNbDataPoints();
256: break;
257: case StatisticalMeasurement.DISPOSE_IGNORE:
258: default:
259: dividerValue = stats.doubleValue();
260: break;
261: }
262: } else if (divider != null) {
263: dividerValue = divider.doubleValue();
264: }
265:
266: value = baseValue / dividerValue;
267: }
268:
269: setEmpty(Double.isNaN(value) || Double.isInfinite(value));
270:
271: setCached(true);
272: }
273:
274: return value;
275: }
276: }
|