/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration),
* and Cosylab
* All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package com.cosylab.acs.laser.dao.utils;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import cern.laser.business.data.Alarm;
import cern.laser.business.data.Triplet;
import com.cosylab.util.WildcharMatcher;
/**
* <p>Utility class to check if an alarm matches an alarm reference specification.
* Given a fault family, a fault member, and a fault code specification (that is,
* an alarm reference), it is able to decide if a given {@link Alarm} matches
* with that definition. Alarm references are present, for example, under the
* <code>parent</code> and <code>child</code> elements of each <code>reduction-link</code>,
* which represents a Reduction Rule on the Alarm System.
*
* <p>Alarm references might use either wildcards or regular expressions to specify
* several alarms at a time. The <code>alma.acs.alarms.refpattern</code> property
* controls whether the strings stored in the CDB should be interpreted as wildcards
* (like <code>'ab*cd??d'</code>) or as Java regular expressions (like<code>'^ab.*cd..d$'</code>).
* It can take the following values: <code>wildcard</code> or <code>regexp</code> values
*
* <p>This class was originally embedded in the ACSAlarmDAOImpl class. Most of the
* following commented code was thought for handling also code ranges. This was
* designed to be specified as a String, but since the current
* schema for the RRs defines the "fault-code" field in the "alarm-definition"
* node as "xs:int", the received value is always an integer, which then was
* being String.valueOf()-ed to get it as String and pass it to this class constructor.
*
* @author acaproni, rtobar
* @TODO: only compile patterns when adequate,
* check http://almasw.hq.eso.org/almasw/bin/view/Main/RodrigoTobarDailyWorklog#08_02_11
* for details
*/
public class AlarmRefMatcher
{
/**
* Reduction rules might use either wildcards or regular expressions to specify several reduction rules at a time.
* The <code>alma.acs.alarms.reductionrulepattern</code> property controls whether the strings stored in the CDB
* should be interpreted as wildcards (like <code>'ab*cd??d'</code>), or as Java regular expressions (like
* <code>'^ab.*cd..d$'</code>). It can take the following values: <code>wildcard</code> or <code>regexp</code> values.
*/
private final String _reduction_rule_patter = System.getProperty("alma.acs.alarms.reductionrulepattern", "wildcard");
private final Pattern _familyPattern;
private final Pattern _memberPattern;
private final int _code;
private final String matcherAlarmID;
/*public final int minCode, maxCode;*/
public AlarmRefMatcher(String familySpec, String memberSpec, int code, boolean interpretStringsAsPatterns) throws IllegalArgumentException
{
matcherAlarmID=familySpec+":"+memberSpec+":"+code;
// TODO: only compile patterns when adequate, check:
// http://almasw.hq.eso.org/almasw/bin/view/Main/RodrigoTobarDailyWorklog#08_02_11
// for details
if (familySpec==null || memberSpec==null /*|| code==null*/)
throw new IllegalArgumentException();
if( _reduction_rule_patter.equals("wildcard") ) {
_familyPattern = Pattern.compile(WildcharMatcher.simpleWildcardToRegex(familySpec));
_memberPattern = Pattern.compile(WildcharMatcher.simpleWildcardToRegex(memberSpec));
}
else {
_familyPattern = Pattern.compile(familySpec);
_memberPattern = Pattern.compile(memberSpec);
}
_code = code;
// try {
// int minus=codeSpec.indexOf('-');
// if (codeSpec.lastIndexOf('-')!=minus)
// throw new IllegalArgumentException("Only a single - allowed in code spec");
// if (minus<0) {
// minCode=maxCode=Integer.parseInt(codeSpec);
// } else {
// if (minus==0) {
// minCode=Integer.MIN_VALUE;
// maxCode=Integer.parseInt(codeSpec.substring(1));
// } else
// if (minus==codeSpec.length()-1) {
// minCode=Integer.parseInt(codeSpec.substring(0, codeSpec.length()-1));
// maxCode=Integer.MAX_VALUE;
// } else {
// minCode=Integer.parseInt(codeSpec.substring(0, minus));
// maxCode=Integer.parseInt(codeSpec.substring(minus+1));
// }
// }
// } catch (NumberFormatException e) {
// throw new IllegalArgumentException("Invalid code spec");
// }
}
public boolean isMatch(Alarm a)
{
if (a==null)
throw new IllegalArgumentException();
// Checks in order of speed, so failure happens ASAP
Triplet t=a.getTriplet();
int code=t.getFaultCode().intValue();
boolean ret;
if ( code != _code ||
!_familyPattern.matcher(t.getFaultFamily()).matches() ||
!_memberPattern.matcher(t.getFaultMember()).matches() ) {
ret= false;
} else {
ret= true;
}
//System.out.println("\t\t\tMatch "+a.getAlarmId()+" with ["+_familyPattern.toString()+","+_memberPattern.toString()+", "+_code+"] retuned "+ret);
return ret;
}
/**
* Return the ID of the alarm. Note that this
* ID could contains wildcards and regular expression.
* <P>
* Parent alarms in reduction rules do not contain regular
* expression neither wildcards.
*
* @return The ID of the alarm
*/
public String getMatcherAlarmID() {
return matcherAlarmID;
}
@Override
public String toString() {
StringBuilder ret = new StringBuilder("AlarmRefMatcher [FF=");
ret.append(_familyPattern.toString());
ret.append(", ");
ret.append(_memberPattern.toString());
ret.append(", ");
ret.append(_code);
ret.append(']');
return ret.toString();
}
}