package javax.slee.usage;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.slee.SbbID;
import javax.slee.ServiceID;
import javax.slee.management.NotificationSource;
/**
* A notification filter that only allows through {@link UsageNotification}s where the
* notification source usage parameter name match specified values, and the value of the
* usage parameter has crossed a specified threshold (in either the positive or negative
* direction).
* <p>
* Each time a usage notification is seen for the specified usage parameter, the current
* value of the usage parameter is stored. If the previous value and the current value
* lie on opposite sides of the threshold, the notification is passed to notification
* listeners. If the previous value was equal to the threshold value, the notification
* is only passed to notification listeners if the direction on the real axis from the
* previous value to the current value is the same as the approach made to the threshold
* value.
* <p>
* For example, if the threshold value is set to 10, and three usage notifications with
* the values 9, 10, and 9 respectively are generated by the SLEE, this notification
* filter would not pass any of the usage notifications to notification listeners as the
* threshold has not been crossed. However if three usage notifications with the values
* 9, 10, and 11 respectively are generated by the SLEE, this notification filter would
* pass only the last usage notification to notification listeners, as this represents
* the point when the threshold has been crossed.
* <p>
* In any other situation where the threshold value is not crossed, the notification is
* suppressed.
* <p>
* If the notification contains usage information for some other notification source or
* usage parameter, it is also suppressed.
* <p>
* Notifications that are not instances of {@link UsageNotification} are also suppressed
* by this filter.
*/
public class UsageThresholdFilter implements NotificationFilter {
/**
* Create a <code>UsageThresholdFilter</code>. A filter created using this constructor will
* only allow SLEE 1.0-compliant usage notifications to pass through where they otherwise
* satisfy the filtering criteria.
* @param service the component identifier of the Service whose usage parameter
* should be monitored.
* @param sbb the component identifier of the SBB whose usage parameter should be
* monitored.
* @param paramName the name of a usage parameter defined by the SBB.
* @param threshold the threshold value.
* @throws NullPointerException if <code>service</code>, <code>sbb</code>, or
* <code>paramName</code> is <code>null</code>.
* @deprecated Replaced with {@link #UsageThresholdFilter(NotificationSource, String, long)}
* as usage collecting has been expanded to include SLEE components other than SBBs.
*/
public UsageThresholdFilter(ServiceID service, SbbID sbb, String paramName, long threshold) throws NullPointerException {
if (service == null) throw new NullPointerException("service is null");
if (sbb == null) throw new NullPointerException("sbb is null");
if (paramName == null) throw new NullPointerException("paramName is null");
this.service = service;
this.sbb = sbb;
this.paramName = paramName;
this.threshold = threshold;
// forward compatibiltiy
this.notificationSource = null;
}
/**
* Create a <code>UsageThresholdFilter</code>. A filter created using this constructor will
* only allow SLEE 1.1-compliant usage notifications to pass through where they otherwise
* satisfy the filtering criteria.
* @param notificationSource the notification source whose usage parameter should be
* monitored.
* @param paramName the name of a usage parameter defined by the SBB.
* @param threshold the threshold value.
* @throws NullPointerException if <code>notificationSource</code> or <code>paramName</code>
* is <code>null</code>.
*/
public UsageThresholdFilter(NotificationSource notificationSource, String paramName, long threshold) throws NullPointerException {
if (notificationSource == null) throw new NullPointerException("notificationSource is null");
if (paramName == null) throw new NullPointerException("paramName is null");
this.notificationSource = notificationSource;
this.paramName = paramName;
this.threshold = threshold;
// backward compatibiltiy
this.service = null;
this.sbb = null;
}
/**
* Determine whether the specified notification should be delivered to notification
* listeners using this notification filter.
* @param notification the notification to be sent.
* @return <code>true</code> if the notification should be delivered to notification
* listeners, <code>false</code> otherwise. This method always returns
* <code>false</code> if <code>notification</code> is not an instance of
* {@link UsageNotification}.
*/
public boolean isNotificationEnabled(Notification notification) {
if (!(notification instanceof UsageNotification)) return false;
UsageNotification usageNotification = (UsageNotification)notification;
if (service != null) {
// SLEE 1.0 comparison
if (!service.equals(usageNotification.getService())) return false;
if (!sbb.equals(usageNotification.getSbb())) return false;
}
else {
// SLEE 1.1 comparison
if (!notificationSource.equals(usageNotification.getNotificationSource())) return false;
}
if (!usageNotification.getUsageParameterName().equals(paramName)) return false;
long current = usageNotification.getValue();
try {
return (previous != threshold)
? ((previous < threshold && current > threshold) || // crossed +ve dir
(previous > threshold && current < threshold)) // crossed -ve dir
: (getDirection(previous, current) == lastDir); // crossed in last dir
}
finally {
if (previous != current) {
lastDir = getDirection(previous, current);
previous = current;
}
}
}
/**
* Get the axial direction of movement from <code>x</code> to <code>y</code>.
* @return 1 if <code>x<y</code>, -1 if <code>x>y</code>, or 0 if <code>x==y</code>.
*/
private int getDirection(long x, long y) {
return x == y ? 0 : (x < y ? 1 : -1);
}
private final ServiceID service;
private final SbbID sbb;
private final NotificationSource notificationSource;
private final String paramName;
private final long threshold;
private long previous = 0;
private long lastDir = 0;
}