/* Copyright (c) 2008-2009 HomeAway, Inc.
* All rights reserved. http://www.perf4j.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.perf4j.helpers;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Instances of this class are used by the StatisticsExposingMBean to determine if JMX notifications should be sent if
* timing statistics fall outside a specified acceptable range.
*
* @author Alex Devine
*/
public class AcceptableRangeConfiguration implements Serializable, Cloneable {
private static final long serialVersionUID = -1386668939617425680L;
private String attributeName;
private double minValue = Double.NEGATIVE_INFINITY;
private double maxValue = Double.POSITIVE_INFINITY;
protected static final Pattern CONFIG_STRING_PATTERN = Pattern.compile("(.+?)\\((<(.+?)|>(.+?)|(.+?)-(.+?))\\)");
// --- Constructors ---
/**
* Default constructor allows the attributeName, minValue and maxValue properties to be set later with
* the setter methods.
*/
public AcceptableRangeConfiguration() { }
/**
* Parses a configuration string to get the attributeName, minValue and maxValue properties. The format of the
* config string should be one of:
* <ul>
* <li>attributeName(<maxValue), where maxValue is the maximum possible acceptable value.
* <li>attributeName(>minValue), where minValue is the maximum possible acceptable value.
* <li>attributeName(minValue-maxValue), to specify a range for acceptable values.
* </ul>
*
* @param configString The configString to parse
* @throws IllegalArgumentException Thrown if the configString did not use the acceptable format.
*/
public AcceptableRangeConfiguration(String configString) {
Matcher matcher = CONFIG_STRING_PATTERN.matcher(configString);
if (matcher.matches()) {
attributeName = matcher.group(1).trim();
try {
String rangeString = matcher.group(2).trim();
if (rangeString.startsWith("<")) {
maxValue = Double.parseDouble(matcher.group(3).trim());
} else if (rangeString.startsWith(">")) {
minValue = Double.parseDouble(matcher.group(4).trim());
} else {
minValue = Double.parseDouble(matcher.group(5).trim());
maxValue = Double.parseDouble(matcher.group(6).trim());
}
} catch (Exception e) {
throw new IllegalArgumentException("Invalid acceptable range config string: " + configString);
}
} else {
throw new IllegalArgumentException("Invalid acceptable range config string: " + configString);
}
}
/**
* Creates a new AcceptableRangeConfiguration with the specified attributeName, min and max values.
*
* @param attributeName The name of the MBean attribute that is being constrained.
* @param minValue The minimum acceptable value
* @param maxValue The maximum acceptable value
*/
public AcceptableRangeConfiguration(String attributeName, double minValue, double maxValue) {
this.attributeName = attributeName;
this.minValue = minValue;
this.maxValue = maxValue;
}
// --- Bean Methods ---
public String getAttributeName() { return attributeName; }
public void setAttributeName(String attributeName) { this.attributeName = attributeName; }
public double getMinValue() { return minValue; }
public void setMinValue(double minValue) { this.minValue = minValue; }
public double getMaxValue() { return maxValue; }
public void setMaxValue(double maxValue) { this.maxValue = maxValue; }
// --- Utility Methods ---
/**
* Determines whether or not the specified value is within the acceptable range.
*
* @param value The value to check
* @return returns true if value >= minValue && value <= maxValue, false otherwise
*/
public boolean isInRange(double value) {
return value >= minValue && value <= maxValue;
}
// --- Object Methods ---
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof AcceptableRangeConfiguration)) {
return false;
}
AcceptableRangeConfiguration that = (AcceptableRangeConfiguration) o;
return Double.compare(that.maxValue, maxValue) == 0 &&
Double.compare(that.minValue, minValue) == 0 &&
(attributeName == null ? that.attributeName == null : attributeName.equals(that.attributeName));
}
public int hashCode() {
int result;
long temp;
result = (attributeName != null ? attributeName.hashCode() : 0);
temp = minValue != +0.0d ? Double.doubleToLongBits(minValue) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = maxValue != +0.0d ? Double.doubleToLongBits(maxValue) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
public String toString() {
if (minValue == Double.NEGATIVE_INFINITY) {
return attributeName + "(<" + maxValue + ")";
} else if (maxValue == Double.POSITIVE_INFINITY) {
return attributeName + "(>" + minValue + ")";
} else {
return attributeName + "(" + minValue + "-" + maxValue + ")";
}
}
public AcceptableRangeConfiguration clone() {
try {
return (AcceptableRangeConfiguration) super.clone();
} catch (Exception e) {
throw new Error("Unexpected CloneNotSupportedException");
}
}
}