/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.eventd.datablock;
import java.util.ArrayList;
import java.util.Collection;
/**
* The maskelement values in a 'EventKey' are stored in this ArrayList subclass
* This list is pretty much constant once it constructed - so the hashcode is
* evaluated once at construction and reused(if new values are added or values
* changed, hashcode is re-evaluated)
*
* @author <A HREF="mailto:sowmya@opennms.org">Sowmya Nataraj </A>
* @author <A HREF="http://www.opennms.org">OpenNMS.org </A>
* @author <A HREF="mailto:sowmya@opennms.org">Sowmya Nataraj </A>
* @author <A HREF="http://www.opennms.org">OpenNMS.org </A>
* @version $Id: $
*/
public class EventMaskValueList extends ArrayList<String> {
private static final long serialVersionUID = -7375744883429450497L;
/**
* The hash code calculated from the elements
*/
private int m_hashCode;
/**
* Default constructor for this class
*/
public EventMaskValueList() {
super();
m_hashCode = -1111;
}
/**
* constructor for this class
*
* @param c a {@link java.util.Collection} object.
*/
public EventMaskValueList(Collection<String> c) {
super(c);
evaluateHashCode();
}
/**
* constructor for this class
*
* @param initCapacity a int.
*/
public EventMaskValueList(int initCapacity) {
super(initCapacity);
m_hashCode = -1111;
}
/**
* the constructor for this class
*
* @param value
* the string to be added to this list.
*/
public EventMaskValueList(String value) {
super();
add(value);
evaluateHashCode();
}
/*
* Following methods are to ensure hashcode is not out of sync with elements
*/
/**
* Override to re-evaluate hashcode
*
* @see java.util.ArrayList#add(Object)
* @param o a {@link java.lang.String} object.
* @return a boolean.
*/
public boolean add(String o) {
boolean ret = super.add(o);
evaluateHashCode();
return ret;
}
/**
* Override to re-evaluate hashcode
*
* @see java.util.ArrayList#add(int, Object)
* @param index a int.
* @param o a {@link java.lang.String} object.
*/
public void add(int index, String o) {
super.add(index, o);
evaluateHashCode();
}
/**
* {@inheritDoc}
*
* Override to re-evaluate hashcode
* @see java.util.ArrayList#addAll(Collection)
*/
public boolean addAll(Collection<? extends String> o) {
boolean ret = super.addAll(o);
evaluateHashCode();
return ret;
}
/**
* {@inheritDoc}
*
* Override to re-evaluate hashcode
* @see java.util.ArrayList#addAll(int, Collection)
*/
public boolean addAll(int index, Collection<? extends String> o) {
boolean ret = super.addAll(index, o);
evaluateHashCode();
return ret;
}
/**
* Override to re-evaluate hashcode
*
* @see java.util.ArrayList#clear()
*/
public void clear() {
super.clear();
evaluateHashCode();
}
/**
* {@inheritDoc}
*
* Override to re-evaluate hashcode
* @see java.util.ArrayList#remove(int)
*/
public String remove(int index) {
String obj = super.remove(index);
evaluateHashCode();
return obj;
}
/**
* {@inheritDoc}
*
* Override to re-evaluate hashcode
* @see java.util.ArrayList#removeRange(int,int)
*/
protected void removeRange(int from, int to) {
super.removeRange(from, to);
evaluateHashCode();
}
/**
* Override to re-evaluate hashcode
*
* @see java.util.ArrayList#remove(Object)
* @param o a {@link java.lang.String} object.
* @return a boolean.
*/
public boolean remove(String o) {
boolean ret = super.remove(o);
evaluateHashCode();
return ret;
}
/**
* {@inheritDoc}
*
* Override to re-evaluate hashcode
* @see java.util.ArrayList#removeAll(Collection)
*/
public boolean removeAll(Collection<?> o) {
boolean ret = super.removeAll(o);
evaluateHashCode();
return ret;
}
/**
* Override to re-evaluate hashcode
*
* @see java.util.ArrayList#set(int,Object)
* @param index a int.
* @param o a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
public String set(int index, String o) {
String old = super.set(index, o);
evaluateHashCode();
return old;
}
/*
* End methods to ensure hashcode is not out of sync with elements
*/
/**
* <p>
* Handling the mask values ending with '%' is a pain since the hashcodes
* will need to work in reverse!
*
* <p>
* For e.g. consider mask values '.1.3.6.1.4.1.9%' and '.1.3.6.1.4.1.%'
* normal hashcodes will mean '.1.3.6.1.4.1.9%' will have a larger hashcode.
* However when we try a match in the eventconf(which uses a treemap of
* eventkeys to get the event keys in an ordered fashion), we want
* '.1.3.6.1.4.1.9%' to be a better match than '.1.3.6.1.4.1.%' - i.e.we
* want '.1.3.6.1.4.1.9%' to have a lesser hashcode than '.1.3.6.1.4.1.%' -
* hence this method. Only a lot of testing will reveal conflicts etc.
* though
* </p>
*/
private int evaluateHashCode(String value) {
int h = 0;
if (value == null) {
return h;
}
int length = value.length();
if (value.startsWith(".1.")) {
// eid?
StringBuffer newValue = new StringBuffer();
for (int i = 0; i < length; i++) {
char tc = value.charAt(i);
if (tc != '.') {
newValue.append(tc);
}
}
value = newValue.toString();
length = value.length();
}
if (value.endsWith("%")) {
char val[] = value.toCharArray();
int len = value.length();
int lastIndex = len - 1;
for (int i = 0; i <= lastIndex; i++) {
if (i != 0) {
h = 31 * h / i - val[i];
} else {
h = 31 * h - val[i];
}
}
} else {
h = value.hashCode();
}
return h;
}
/**
* Evaluate the hash code for this object
*/
public void evaluateHashCode() {
int hashCode = 1;
for (String str : this) {
m_hashCode = 31 * hashCode;
if (str != null) {
m_hashCode += evaluateHashCode(str);
}
}
}
/**
* Overrides the 'hashCode()' method in the superclass.
*
* @return a hash code for this object
*/
public int hashCode() {
if (m_hashCode != -1111) {
return m_hashCode;
} else {
evaluateHashCode();
return m_hashCode;
}
}
}