/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2008-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.provision;
import java.net.InetAddress;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.core.utils.LogUtils;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.provision.annotations.Require;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.PropertyAccessorFactory;
/**
* <p>Abstract BasePolicy class.</p>
*
* @author ranger
* @version $Id: $
*/
public abstract class BasePolicy<T> {
public static enum Match { ANY_PARAMETER, ALL_PARAMETERS, NO_PARAMETERS }
private Match m_match = Match.ANY_PARAMETER;
private final LinkedHashMap<String, String> m_criteria = new LinkedHashMap<String, String>();;
/**
* <p>match</p>
*
* @param s a {@link java.lang.String} object.
* @param matcher a {@link java.lang.String} object.
* @param <T> a T object.
* @return a boolean.
*/
protected boolean match(final String s, final String matcher) {
if (s == null) {
return false;
}
if (matcher.startsWith("~")) {
return s.matches(matcher.replaceFirst("~", ""));
} else {
return s.equals(matcher);
}
}
/**
* <p>getMatchBehavior</p>
*
* @return a {@link java.lang.String} object.
*/
@Require( { "ANY_PARAMETER", "ALL_PARAMETERS", "NO_PARAMETERS" })
public String getMatchBehavior() {
return getMatch().toString();
}
/**
* <p>setMatchBehavior</p>
*
* @param matchBehavior a {@link java.lang.String} object.
*/
public void setMatchBehavior(final String matchBehavior) {
final String upperMatchBehavior = matchBehavior.toUpperCase();
if (matchBehavior != null && upperMatchBehavior.contains("ALL")) {
setMatch(Match.ALL_PARAMETERS);
} else if (matchBehavior != null && upperMatchBehavior.contains("NO")) {
setMatch(Match.NO_PARAMETERS);
} else {
setMatch(Match.ANY_PARAMETER);
}
}
/**
* <p>setMatch</p>
*
* @param match the match to set
*/
protected void setMatch(final Match match) {
m_match = match;
}
/**
* <p>getMatch</p>
*
* @return the match
*/
protected Match getMatch() {
return m_match;
}
/**
* <p>getCriteria</p>
*
* @param key a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
protected String getCriteria(final String key) {
return getCriteria().get(key);
}
/**
* <p>putCriteria</p>
*
* @param key a {@link java.lang.String} object.
* @param expression a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
protected String putCriteria(final String key, final String expression) {
return getCriteria().put(key, expression);
}
/**
* <p>getCriteria</p>
*
* @return the criteria
*/
protected LinkedHashMap<String, String> getCriteria() {
return m_criteria;
}
/**
* <p>matches</p>
*
* @param iface a T object.
* @return a boolean.
*/
protected boolean matches(final T iface) {
switch (getMatch()) {
case ALL_PARAMETERS:
return matchAll(iface);
case NO_PARAMETERS:
return matchNone(iface);
case ANY_PARAMETER:
default:
return matchAny(iface);
}
}
private boolean matchAll(final T iface) {
final BeanWrapper bean = PropertyAccessorFactory.forBeanPropertyAccess(iface);
for(final Entry<String, String> term : getCriteria().entrySet()) {
final String val = getPropertyValueAsString(bean, term.getKey());
final String matchExpression = term.getValue();
if (!match(val, matchExpression)) {
return false;
}
}
return true;
}
private boolean matchAny(final T iface) {
final BeanWrapper bean = PropertyAccessorFactory.forBeanPropertyAccess(iface);
for(final Entry<String, String> term : getCriteria().entrySet()) {
final String val = getPropertyValueAsString(bean, term.getKey());
final String matchExpression = term.getValue();
if (match(val, matchExpression)) {
return true;
}
}
return false;
}
private boolean matchNone(final T iface) {
return !matchAny(iface);
}
private static String getPropertyValueAsString(final BeanWrapper bean, final String propertyName) {
Object value = null;
try {
value = bean.getPropertyValue(propertyName);
} catch (BeansException e) {
ThreadCategory.getInstance(BasePolicy.class).warn("Could not find property \"" + propertyName + "\" on object of type " + bean.getWrappedClass().getName() + ", returning null", e);
return null;
}
try {
return bean.convertIfNecessary(value, String.class);
} catch (ConversionNotSupportedException e) {
if (value instanceof InetAddress) {
return InetAddressUtils.toIpAddrString((InetAddress) value);
} else {
throw e;
}
}
}
/**
* <p>act</p>
*
* @param iface a T object.
* @return a T object.
*/
public abstract T act(final T iface);
/**
* <p>apply</p>
*
* @param iface a T object.
* @return a T object.
*/
public T apply(final T iface) {
if (iface == null) {
return null;
}
if (matches(iface)) {
LogUtils.debugf(this, "Found Match %s for %s", iface, this);
return act(iface);
}
LogUtils.debugf(this, "No Match Found: %s for %s", iface, this);
return iface;
}
}