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: import java.util.*;
037:
038: import org.apache.log4j.*;
039:
040: /**
041: * <p>Adds up numerical values. Use it with just one term to alias
042: * other measurements.</p>
043: *
044: * <p>This is the syntax for initializing this type of
045: * measurement:</p>
046: *
047: * <pre>
048: * <init>
049: * number | measurement name [DISPOSE_x]
050: * ...
051: * </init>
052: * </pre>
053: */
054: public class SumMeasurement extends MeasurementBase {
055: private List<String> terms = new LinkedList<String>();
056:
057: private double value = 0.0;
058:
059: public SumMeasurement(MeasurementDescriptor descriptor,
060: Metrics context, String initText) {
061: super (descriptor, context, initText);
062:
063: try {
064: BufferedReader in = new BufferedReader(new StringReader(
065: initText));
066: String line;
067:
068: while ((line = in.readLine()) != null) {
069: terms.add(line.trim());
070: }
071:
072: in.close();
073: } catch (Exception ex) {
074: Logger.getLogger(getClass()).debug(
075: "Cannot initialize with \"" + initText + "\"", ex);
076: terms.clear();
077: }
078: }
079:
080: public List<String> getTerms() {
081: return terms;
082: }
083:
084: public boolean isEmpty() {
085: compute();
086:
087: return super .isEmpty();
088: }
089:
090: public void accept(MeasurementVisitor visitor) {
091: visitor.visitSumMeasurement(this );
092: }
093:
094: protected double compute() {
095: if (!isCached()) {
096: synchronized (this ) {
097: if (!isCached()) {
098: value = 0.0;
099: setEmpty(true);
100:
101: if (getContext() != null) {
102: Logger.getLogger(getClass()).debug(
103: "Start computing \"" + getShortName()
104: + "\" on \""
105: + getContext().getName()
106: + "\": value=" + value);
107: } else {
108: Logger.getLogger(getClass()).debug(
109: "Start computing \"" + getShortName()
110: + "\" on null: value=" + value);
111: }
112:
113: for (String term : getTerms()) {
114: Logger.getLogger(getClass()).debug(
115: "Evaluating term \"" + term + "\"");
116:
117: double termValue = Double.NaN;
118:
119: try {
120: termValue = Double.parseDouble(term);
121: } catch (NumberFormatException ex) {
122: if (term.startsWith("-")) {
123: termValue = -1
124: * evaluateMeasurement(term
125: .substring(1));
126: } else {
127: termValue = evaluateMeasurement(term);
128: }
129: }
130:
131: Logger.getLogger(getClass())
132: .debug(
133: "term \"" + term + "\" is "
134: + termValue);
135:
136: value += termValue;
137:
138: Logger.getLogger(getClass()).debug(
139: "value=" + value);
140: }
141:
142: if (getContext() != null) {
143: Logger.getLogger(getClass()).debug(
144: "Stop computing \"" + getShortName()
145: + "\" on \""
146: + getContext().getName()
147: + "\": value=" + value);
148: } else {
149: Logger.getLogger(getClass()).debug(
150: "Stop computing \"" + getShortName()
151: + "\" on null: value=" + value);
152: }
153:
154: setCached(true);
155: }
156: }
157: }
158:
159: if (getContext() != null) {
160: Logger.getLogger(getClass()).debug(
161: "\"" + getShortName() + "\" on \""
162: + getContext().getName() + "\": value="
163: + value);
164: } else {
165: Logger.getLogger(getClass()).debug(
166: "\"" + getShortName() + "\" on null: value="
167: + value);
168: }
169:
170: return value;
171: }
172:
173: private double evaluateMeasurement(String name) {
174: double result = 0;
175:
176: if (name.length() != 0) {
177: int dispose;
178:
179: synchronized (perl()) {
180: if (perl().match("/(.*)\\s+(dispose_\\w+)$/i", name)) {
181: name = perl().group(1);
182:
183: String disposeText = perl().group(2);
184:
185: if (disposeText.equalsIgnoreCase("DISPOSE_IGNORE")) {
186: dispose = StatisticalMeasurement.DISPOSE_IGNORE;
187: } else if (disposeText
188: .equalsIgnoreCase("DISPOSE_MINIMUM")) {
189: dispose = StatisticalMeasurement.DISPOSE_MINIMUM;
190: } else if (disposeText
191: .equalsIgnoreCase("DISPOSE_MEDIAN")) {
192: dispose = StatisticalMeasurement.DISPOSE_MEDIAN;
193: } else if (disposeText
194: .equalsIgnoreCase("DISPOSE_AVERAGE")) {
195: dispose = StatisticalMeasurement.DISPOSE_AVERAGE;
196: } else if (disposeText
197: .equalsIgnoreCase("DISPOSE_STANDARD_DEVIATION")) {
198: dispose = StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION;
199: } else if (disposeText
200: .equalsIgnoreCase("DISPOSE_MAXIMUM")) {
201: dispose = StatisticalMeasurement.DISPOSE_MAXIMUM;
202: } else if (disposeText
203: .equalsIgnoreCase("DISPOSE_SUM")) {
204: dispose = StatisticalMeasurement.DISPOSE_SUM;
205: } else if (disposeText
206: .equalsIgnoreCase("DISPOSE_NB_DATA_POINTS")) {
207: dispose = StatisticalMeasurement.DISPOSE_NB_DATA_POINTS;
208: } else {
209: dispose = StatisticalMeasurement.DISPOSE_IGNORE;
210: }
211: } else {
212: dispose = StatisticalMeasurement.DISPOSE_IGNORE;
213: }
214: }
215:
216: Measurement measurement = getContext().getMeasurement(name);
217:
218: if (measurement instanceof StatisticalMeasurement) {
219: StatisticalMeasurement stats = (StatisticalMeasurement) measurement;
220:
221: switch (dispose) {
222: case StatisticalMeasurement.DISPOSE_MINIMUM:
223: result = stats.getMinimum();
224: break;
225: case StatisticalMeasurement.DISPOSE_MEDIAN:
226: result = stats.getMedian();
227: break;
228: case StatisticalMeasurement.DISPOSE_AVERAGE:
229: result = stats.getAverage();
230: break;
231: case StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION:
232: result = stats.getStandardDeviation();
233: break;
234: case StatisticalMeasurement.DISPOSE_MAXIMUM:
235: result = stats.getMaximum();
236: break;
237: case StatisticalMeasurement.DISPOSE_SUM:
238: result = stats.getSum();
239: break;
240: case StatisticalMeasurement.DISPOSE_NB_DATA_POINTS:
241: result = stats.getNbDataPoints();
242: break;
243: case StatisticalMeasurement.DISPOSE_IGNORE:
244: default:
245: result = stats.doubleValue();
246: break;
247: }
248: } else {
249: result = measurement.doubleValue();
250: }
251:
252: if (super.isEmpty()) {
253: setEmpty(measurement.isEmpty());
254: }
255: }
256:
257: return result;
258: }
259: }
|