/* * ALMA - Atacama Large Millimeter Array * (c) Universidad Tecnica Federico Santa Maria, 2009 * Copyright by ESO (in the framework of the ALMA collaboration), * 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 cl.utfsm.acs.acg.core; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; import org.exolab.castor.xml.ValidationException; import alma.alarmsystem.alarmmessage.generated.AlarmDefinition; import alma.alarmsystem.alarmmessage.generated.Child; import alma.alarmsystem.alarmmessage.generated.Parent; import alma.alarmsystem.alarmmessage.generated.ReductionDefinitions; import alma.alarmsystem.alarmmessage.generated.ReductionLinkType; import alma.alarmsystem.alarmmessage.generated.Threshold; import alma.alarmsystem.alarmmessage.generated.types.ReductionLinkTypeTypeType; import cl.utfsm.acs.acg.dao.ACSAlarmDAOImpl; import cern.laser.business.dao.AlarmDAO; import cern.laser.business.data.Alarm; import cern.laser.business.data.Triplet; /** * @author rtobar * */ public class ReductionManager implements EntityManager { /** * The singleton instance shared across the project */ private static ReductionManager _instance; private List<ReductionRule> _nodeReductionRules; private List<ReductionRule> _multiReductionRules; private HashMap<String, ObjectState> _objState; private HashMap<String, ObjectState> _thrState; private AlarmDAO _alarmDAO; private ReductionManager(AlarmDAO alarmDAO) { _alarmDAO = alarmDAO; _nodeReductionRules = new ArrayList<ReductionRule>(); _multiReductionRules = new ArrayList<ReductionRule>(); _objState = new HashMap<String, ObjectState>(); _thrState = new HashMap<String, ObjectState>(); } public static ReductionManager getInstance(AlarmDAO alarmDAO) { if( _instance == null ) { _instance = new ReductionManager(alarmDAO); } return _instance; } public List<ReductionRule> getNodeReductionRules() { return _nodeReductionRules; } public List<ReductionRule> getMultiReductionRules() { return _multiReductionRules; } /* (non-Javadoc) * @see cl.utfsm.acs.acg.core.EntityManager#loadFromCDB() */ public void loadFromCDB() { String[] ids = ((ACSAlarmDAOImpl)_alarmDAO).getAllAlarmIDs(); String[] children = null; Alarm alarm = null; ReductionRule rr = null; _nodeReductionRules.clear(); _multiReductionRules.clear(); _objState.clear(); _thrState.clear(); /* Add the reduction rules defined in the CDB */ for (int i = 0; i < ids.length; i++) { alarm = ((ACSAlarmDAOImpl)_alarmDAO).getAlarm(ids[i]); /* First the Node Reduction rules */ children = alarm.getNodeChildren(); if( children.length > 0 ) { rr = new ReductionRule(alarm); rr.setIsNodeReduction(true); } for (int j = 0; j < children.length; j++) { rr.addChild(((ACSAlarmDAOImpl)_alarmDAO).getAlarm(children[j])); _objState.put(new String(ids[i] + "," + children[j]+",n"), new ObjectState(false)); } if( children.length > 0 ) _nodeReductionRules.add(rr); /* And the Multiplicity Reduction rules */ children = alarm.getMultiplicityChildren(); if( children.length > 0 ) { rr = new ReductionRule(((ACSAlarmDAOImpl)_alarmDAO).getAlarm(ids[i])); rr.setIsNodeReduction(false); if(alarm.getMultiplicityThreshold() == null) { System.out.println("Skipping Multi Reduction Rule: No Threshold set."); continue; } rr.setThreshold(alarm.getMultiplicityThreshold().intValue()); } for (int j = 0; j < children.length; j++) { rr.addChild(((ACSAlarmDAOImpl)_alarmDAO).getAlarm(children[j])); _objState.put(new String(ids[i] + "," + children[j]+",m"), new ObjectState(false)); _thrState.put(ids[i], new ObjectState(false)); } if( children.length > 0 ) _multiReductionRules.add(rr); } } public String checkCDB() { String error = ""; List<ReductionRule> nrrs = _nodeReductionRules; List<ReductionRule> mrrs = _multiReductionRules; for(ReductionRule rr: nrrs) { Alarm p = rr.getParent(); List<Alarm> chs = rr.getChildren(); if(_alarmDAO.getAlarm(p.getAlarmId()) == null) error += "Node Reduction Rule Parent Alarm "+p.getAlarmId()+" doesn't exist.\n"; for(Alarm ch: chs) if(_alarmDAO.getAlarm(ch.getAlarmId()) == null) error += "Node Reduction Rule Chid Alarm "+ch.getAlarmId()+" with Parent "+p.getAlarmId()+" doesn't exist.\n"; } for(ReductionRule rr: mrrs) { Alarm p = rr.getParent(); List<Alarm> chs = rr.getChildren(); if(_alarmDAO.getAlarm(p.getAlarmId()) == null) error += "Multi Reduction Rule Parent Alarm "+p.getAlarmId()+" doesn't exist.\n"; for(Alarm ch: chs) if(_alarmDAO.getAlarm(ch.getAlarmId()) == null) error += "Multi Reduction Rule Chid Alarm "+ch.getAlarmId()+" with Parent "+p.getAlarmId()+" doesn't exist.\n"; if(rr.getThreshold() <= 0) error += "Multi Reduction Rule Threshold for Parent "+p.getAlarmId()+" is invalid (Must be > 0).\n"; } return error; } /** * Destroys the singleton instance of this class. This is needed to renew the internal reference to * the AlarmDAO if a new connection to the DAL and the ACS Manager has been performed */ public static void destroy() { _instance = null; } /** * Returns an Alarm which is parent in a Node Reduction Rule, constrained to the given triplet values. * @param ff The Fault Family of the Alarm * @param fm The Fault Member of the Alarm * @param fc The Fault Code of the Alarm * @return The Alarm described by the triplet, and which is a parent alarm in a Node Reduction Rule */ public ReductionRule getNRParentByTriplet(String ff, String fm, int fc) { for (Iterator<ReductionRule> iterator = _nodeReductionRules.iterator(); iterator.hasNext();) { ReductionRule nrr = (ReductionRule) iterator.next(); Triplet triplet = nrr.getParent().getTriplet(); if( triplet.getFaultFamily().compareTo(ff) == 0 && triplet.getFaultMember().compareTo(fm) == 0 && triplet.getFaultCode().intValue() == fc ) { return nrr; } } return null; } /** * Returns an Alarm which is parent in a Multiplicity Reduction Rule, constrained to the given triplet values. * @param ff The Fault Family of the Alarm * @param fm The Fault Member of the Alarm * @param fc The Fault Code of the Alarm * @return The Alarm described by the triplet, and which is a parent alarm in a Multiplicity Reduction Rule */ public ReductionRule getMRParentByTriplet(String ff, String fm, int fc) { for (Iterator<ReductionRule> iterator = _multiReductionRules.iterator(); iterator.hasNext();) { ReductionRule mrr = (ReductionRule) iterator.next(); Triplet triplet = mrr.getParent().getTriplet(); if( triplet.getFaultFamily().compareTo(ff) == 0 && triplet.getFaultMember().compareTo(fm) == 0 && triplet.getFaultCode().intValue() == fc ) { return mrr; } } return null; } /** * Deletes a Reduction Rule * @param rrL List of Reduction Rules to remove from. * @param rr Reduction Rule to remove from. * @param p Parent of the Rule to be deleted * @param c Child of the Rule to be deleted */ private boolean deleteReductionRule(List<ReductionRule> rrL, ReductionRule rr, Alarm p, Alarm c){ if(rr == null) throw new NullPointerException("The Reduction Rule to be deleted is null"); if(!rr.removeChild(c)) return false; ObjectState os; if(rr.getIsNodeReduction()) os = _objState.get(new String(p.getAlarmId()+","+c.getAlarmId()+",n")); else os = _objState.get(new String(p.getAlarmId()+","+c.getAlarmId()+",m")); if(os != null) os.delete(); if(rr.getChildrenCount() > 0) return true; for (Iterator<ReductionRule> iterator = rrL.iterator(); iterator.hasNext();) { ReductionRule trr = iterator.next(); if(p.getAlarmId().compareTo(trr.getParent().getAlarmId()) == 0){ iterator.remove(); if(!rr.getIsNodeReduction()) { ObjectState ts = _thrState.get(p.getAlarmId()); if(ts != null) ts.delete(); } break; } } return true; } /** * Deletes a Node Reduction Rule * @param p Parent of the Rule to be deleted * @param c Child of the Rule to be deleted */ public boolean deleteNodeReductionRule(Alarm p, Alarm c) throws IllegalOperationException { ReductionRule rr = getNRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); if(rr == null) throw new IllegalOperationException("The Reduction Rule to be deleted doesn't exist"); return deleteReductionRule(_nodeReductionRules, rr, p, c); } /** * Deletes a Node Reduction Rule * @param p Parent of the Rule to be deleted * @param c Child of the Rule to be deleted */ public boolean deleteMultiReductionRule(Alarm p, Alarm c) throws IllegalOperationException { ReductionRule rr = getMRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); if(rr == null) throw new IllegalOperationException("The Reduction Rule to be deleted doesn't exist"); return deleteReductionRule(_multiReductionRules, rr, p, c); } /** * Adds a Reduction Rule * @param rrL List of Reduction Rules where the rule will be added (if it is null). * @param rr Reduction Rule to add to (if not null). * @param p Parent of the Rule to be added * @param c Child of the Rule to be added */ private void addReductionRule(List<ReductionRule> rrL, ReductionRule rr, Alarm p, Alarm c, boolean isNodeReductionRule) throws IllegalOperationException, NullPointerException{ if(rr == null){ rr = new ReductionRule(p); rr.setIsNodeReduction(isNodeReductionRule); rrL.add(rr); } List<Alarm> chL = rr.getChildren(); for (Alarm alarm : chL) { if(alarm.getAlarmId().compareTo(c.getAlarmId()) == 0){ throw new IllegalOperationException("The reduction rule already exists"); } } rr.addChild(c); ObjectState os; if(rr.getIsNodeReduction()) os = _objState.get(new String(p.getAlarmId()+","+c.getAlarmId()+",n")); else os = _objState.get(new String(p.getAlarmId()+","+c.getAlarmId()+",m")); if(os == null) { os = new ObjectState(true); os.create(); if(rr.getIsNodeReduction()) _objState.put(new String(p.getAlarmId()+","+c.getAlarmId()+",n"),os); else _objState.put(new String(p.getAlarmId()+","+c.getAlarmId()+",m"),os); } else os.update(); } /** * Adds a Node Reduction Rule * @param p Alarm parent of this Node Reduction Rule * @param a Alarm child of this Node Reduction Rule * @throws IllegalOperationException if is not a Node Reduction Rule */ public void addNodeReductionRule(Alarm p, Alarm c) throws IllegalOperationException, NullPointerException { ReductionRule rr = getNRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); addReductionRule(_nodeReductionRules, rr, p, c,true); if(rr == null) rr = getNRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); rr.setIsNodeReduction(true); } /** * Adds a Multiplicity Reduction Rule * @param p Alarm parent of this Multi Reduction Rule * @param a Alarm child of this Multi Reduction Rule * @throws IllegalOperationException if is not a Multi Reduction Rule */ public void addMultiReductionRule(Alarm p, Alarm c) throws IllegalOperationException, NullPointerException { ReductionRule rr = getMRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); addReductionRule(_multiReductionRules, rr, p, c,false); if(rr == null) { rr = getMRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); rr.setThreshold(0); ObjectState ts = _thrState.get(p.getAlarmId()); if(ts == null) { ts = new ObjectState(true); ts.create(); _thrState.put(p.getAlarmId(), ts); } else ts.update(); } rr.setIsNodeReduction(false); } public void updateMultiThreshold(Alarm p, int v) throws IllegalOperationException, NullPointerException { if(p == null) throw new NullPointerException("Null Alarm argument"); ReductionRule rr = getMRParentByTriplet(p.getTriplet().getFaultFamily(), p.getTriplet().getFaultMember(), p.getTriplet().getFaultCode()); if(rr == null) throw new IllegalOperationException("The Reduction Rule doesn't exist"); rr.setThreshold(v); ObjectState ts = _thrState.get(p.getAlarmId()); if(ts == null) throw new IllegalOperationException("There is no threshold ObjectState for this Alarm"); ts.update(); } public void saveToCDB(){ Set<String> keyset = _objState.keySet(); String[] objs = new String[keyset.size()]; keyset.toArray(objs); ReductionDefinitions rds = ((ACSAlarmDAOImpl)_alarmDAO).getReductionRules(); boolean flush = false; try { for (int i = 0; i < objs.length; i++) { ObjectState os = _objState.get(objs[i]); String[] spl = objs[i].split(","); String[] p = spl[0].split(":"); String[] c = spl[1].split(":"); ReductionLinkType rl = new ReductionLinkType(); AlarmDefinition ad; Parent gp = new Parent(); ad = new AlarmDefinition(); ad.setFaultFamily(p[0]); ad.setFaultMember(p[1]); ad.setFaultCode(Integer.parseInt(p[2])); gp.setAlarmDefinition(ad); Child gc = new Child(); ad = new AlarmDefinition(); ad.setFaultFamily(c[0]); ad.setFaultMember(c[1]); ad.setFaultCode(Integer.parseInt(c[2])); gc.setAlarmDefinition(ad); rl.setParent(gp); rl.setChild(gc); if(spl[2].compareTo("n") == 0) rl.setType(ReductionLinkTypeTypeType.NODE); else rl.setType(ReductionLinkTypeTypeType.MULTIPLICITY); rl.validate(); switch(os.getAction()){ case -1: //Error, no state assigned. break; case 0: break; case 1: ((ACSAlarmDAOImpl)_alarmDAO).addReductionRule(rds, rl); flush = true; break; case 2: ((ACSAlarmDAOImpl)_alarmDAO).updateReductionRule(rds, rl); flush = true; break; case 3: ((ACSAlarmDAOImpl)_alarmDAO).deleteReductionRule(rds, rl); flush = true; break; default: //Shouldn't happen. break; } } keyset = _thrState.keySet(); objs = new String[keyset.size()]; keyset.toArray(objs); for (int i = 0; i < objs.length; i++) { AlarmDefinition al; String[] p = objs[i].split(":"); al = new AlarmDefinition(); al.setFaultFamily(p[0]); al.setFaultMember(p[1]); al.setFaultCode(Integer.parseInt(p[2])); ReductionRule rr = getMRParentByTriplet(p[0], p[1], Integer.parseInt(p[2])); Threshold th = new Threshold(); th.setAlarmDefinition(al); if(rr == null) th.setValue(0); else th.setValue(rr.getThreshold()); ObjectState ts = _thrState.get(objs[i]); th.validate(); switch(ts.getAction()){ case -1: //Error, no state assigned. break; case 0: break; case 1: ((ACSAlarmDAOImpl)_alarmDAO).addThreshold(rds, th); flush = true; break; case 2: ((ACSAlarmDAOImpl)_alarmDAO).updateThreshold(rds, th); flush = true; break; case 3: ((ACSAlarmDAOImpl)_alarmDAO).deleteThreshold(rds, th); flush = true; break; default: //Shouldn't happen. break; } } _objState.clear(); _thrState.clear(); if(flush) ((ACSAlarmDAOImpl)_alarmDAO).flushReductionRules(rds); for (ReductionRule rr : _nodeReductionRules) for(Alarm al : rr.getChildren()) if(rr.getIsNodeReduction()) _objState.put(new String(rr.getParent().getAlarmId()+","+al.getAlarmId()+",n"), new ObjectState(false)); for (ReductionRule rr : _multiReductionRules) { for(Alarm al : rr.getChildren()) if(!rr.getIsNodeReduction()) _objState.put(new String(rr.getParent().getAlarmId()+","+al.getAlarmId()+",m"), new ObjectState(false)); _thrState.put(rr.getParent().getAlarmId(), new ObjectState(false)); } } catch (ValidationException e) { e.printStackTrace(); } } }