/******************************************************************************* * Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University * as Operator of the SLAC National Accelerator Laboratory. * Copyright (c) 2011 Brookhaven National Laboratory. * EPICS archiver appliance is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. *******************************************************************************/ package org.epics.archiverappliance.retrieval.channelarchiver; import java.sql.Timestamp; import java.util.HashMap; import java.util.LinkedList; import org.epics.archiverappliance.ByteArray; import org.epics.archiverappliance.Event; import org.epics.archiverappliance.config.ArchDBRTypes; import org.epics.archiverappliance.data.DBRTimeEvent; import org.epics.archiverappliance.data.SampleValue; import org.epics.archiverappliance.data.ScalarStringSampleValue; import org.epics.archiverappliance.data.ScalarValue; import org.epics.archiverappliance.data.VectorStringSampleValue; import org.epics.archiverappliance.data.VectorValue; /** * We get a HashMap of NVPairs from the Channel Archiver - this class exposes these as an archiver Event * We typically get secs=1250696265, value=70.9337, sevr=0, nano=267115322, stat=0 * @author mshankar * */ public class HashMapEvent implements DBRTimeEvent { public static final String SECS_FIELD_NAME = "secs"; public static final String NANO_FIELD_NAME = "nano"; public static final String VALUE_FIELD_NAME = "value"; public static final String STAT_FIELD_NAME = "stat"; public static final String SEVR_FIELD_NAME = "sevr"; public static final String FIELD_VALUES_FIELD_NAME = "fields"; public static final String FIELD_VALUES_ACTUAL_CHANGE = "fieldsAreActualChange"; private HashMap<String, Object> values; private ArchDBRTypes type; public HashMapEvent(ArchDBRTypes type, HashMap<String, Object> values) { this.values = values; this.type = type; } public HashMapEvent(ArchDBRTypes type, DBRTimeEvent event) { this.type = type; values = new HashMap<String, Object>(); values.put(HashMapEvent.SECS_FIELD_NAME, Long.toString(event.getEpochSeconds())); values.put(HashMapEvent.NANO_FIELD_NAME, Integer.toString(event.getEventTimeStamp().getNanos())); values.put(HashMapEvent.STAT_FIELD_NAME, Integer.toString(event.getStatus())); values.put(HashMapEvent.SEVR_FIELD_NAME, Integer.toString(event.getSeverity())); if(event.hasFieldValues()) { values.put(FIELD_VALUES_FIELD_NAME, event.getFields()); } if(event.isActualChange()) { values.put(FIELD_VALUES_ACTUAL_CHANGE, Boolean.TRUE.toString()); } values.put(VALUE_FIELD_NAME, event.getSampleValue().toString()); } public void setValue(String name, String newValue) { this.values.put(name, newValue); } @Override public Event makeClone() { return new HashMapEvent(this.type, new HashMap<String, Object>(this.values)); } @Override public int getRepeatCount() { return 0; } @Override public void setRepeatCount(int repeatCount) { } @Override public int getStatus() { return Integer.parseInt((String)values.get(STAT_FIELD_NAME)); } @Override public int getSeverity() { return Integer.parseInt((String)values.get(SEVR_FIELD_NAME)); } @Override public long getEpochSeconds() { return Long.parseLong((String)values.get(SECS_FIELD_NAME)); } @Override public Timestamp getEventTimeStamp() { Timestamp ret = new Timestamp(Long.parseLong((String)values.get(SECS_FIELD_NAME))*1000); ret.setNanos(Integer.parseInt((String)values.get(NANO_FIELD_NAME))); return ret; } @Override public ByteArray getRawForm() { throw new UnsupportedOperationException("There should be no need to support a raw form here."); } @Override public SampleValue getSampleValue() { switch(type) { case DBR_SCALAR_FLOAT: case DBR_SCALAR_DOUBLE: { String strValue = (String)values.get(VALUE_FIELD_NAME); try { return new ScalarValue<Double>(Double.parseDouble(strValue)); } catch(NumberFormatException nex) { if(strValue.equals("nan")) { // logger.debug("Got a nan from the ChannelArchiver; returning Double.Nan instead"); return new ScalarValue<Double>(Double.NaN); } else { throw nex; } } } case DBR_SCALAR_BYTE: case DBR_SCALAR_SHORT: case DBR_SCALAR_ENUM: case DBR_SCALAR_INT: { String strValue = (String)values.get(VALUE_FIELD_NAME); return new ScalarValue<Integer>(Integer.parseInt(strValue)); } case DBR_SCALAR_STRING: { String strValue = (String)values.get(VALUE_FIELD_NAME); return new ScalarStringSampleValue(strValue); } case DBR_WAVEFORM_FLOAT: case DBR_WAVEFORM_DOUBLE: { // No choice but to add this SuppressWarnings here. @SuppressWarnings("unchecked") LinkedList<String> vals = (LinkedList<String>) values.get(VALUE_FIELD_NAME); LinkedList<Double> dvals = new LinkedList<Double>(); for(String val : vals) dvals.add(Double.parseDouble(val)); return new VectorValue<Double>(dvals); } case DBR_WAVEFORM_ENUM: case DBR_WAVEFORM_SHORT: case DBR_WAVEFORM_BYTE: case DBR_WAVEFORM_INT: { // No choice but to add this SuppressWarnings here. @SuppressWarnings("unchecked") LinkedList<String> vals = (LinkedList<String>) values.get(VALUE_FIELD_NAME); LinkedList<Integer> ivals = new LinkedList<Integer>(); for(String val : vals) ivals.add(Integer.parseInt(val)); return new VectorValue<Integer>(ivals); } case DBR_WAVEFORM_STRING: { // No choice but to add this SuppressWarnings here. @SuppressWarnings("unchecked") LinkedList<String> vals = (LinkedList<String>) values.get(VALUE_FIELD_NAME); return new VectorStringSampleValue(vals); } case DBR_V4_GENERIC_BYTES: { throw new UnsupportedOperationException("Channel Archiver does not support V4 yet."); } default: throw new UnsupportedOperationException("Unknown DBR type " + type); } } @Override public boolean hasFieldValues() { return this.values.containsKey(FIELD_VALUES_FIELD_NAME); } @Override public boolean isActualChange() { return this.values.containsKey(FIELD_VALUES_ACTUAL_CHANGE) && Boolean.valueOf((String)this.values.get(FIELD_VALUES_ACTUAL_CHANGE)); } @SuppressWarnings("unchecked") @Override public HashMap<String, String> getFields() { return (HashMap<String, String>) this.values.get(FIELD_VALUES_FIELD_NAME); } @SuppressWarnings("unchecked") @Override public String getFieldValue(String fieldName) { return ((HashMap<String, String>) this.values.get(FIELD_VALUES_FIELD_NAME)).get(fieldName); } @SuppressWarnings("unchecked") @Override public void addFieldValue(String fieldName, String fieldValue) { ((HashMap<String, String>) this.values.get(FIELD_VALUES_FIELD_NAME)).put(fieldName, fieldValue); } @Override public void markAsActualChange() { this.values.put(FIELD_VALUES_ACTUAL_CHANGE, Boolean.TRUE.toString()); } @Override public void setFieldValues(HashMap<String, String> fieldValues, boolean markAsActualChange) { this.values.put(FIELD_VALUES_FIELD_NAME, fieldValues); if(markAsActualChange) { this.values.put(FIELD_VALUES_ACTUAL_CHANGE, Boolean.TRUE.toString()); } } @Override public ArchDBRTypes getDBRType() { return this.type; } @Override public void setStatus(int status) { values.put(STAT_FIELD_NAME, new Integer(status).toString()); } @Override public void setSeverity(int severity) { values.put(SEVR_FIELD_NAME, new Integer(severity).toString()); } }