Skip to content

Commit

Permalink
Merge pull request #2902 from ControlSystemStudio/CSSTDUIO-1621
Browse files Browse the repository at this point in the history
Save&restore support for NTTable
  • Loading branch information
shroffk authored Jan 16, 2024
2 parents f58535b + d0f0a6b commit e4ba86a
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
package org.phoebus.applications.saveandrestore.ui;

import org.epics.pva.data.*;
import org.epics.pva.data.nt.PVATable;
import org.epics.util.array.*;
import org.epics.util.number.*;
import org.epics.util.text.NumberFormats;
Expand Down Expand Up @@ -100,7 +102,7 @@ public double getAbsoluteDelta() {
/**
* The character code for the greek delta letter
*/
public static final char DELTA_CHAR = '\u0394';
public static final char DELTA_CHAR = 'Δ';

private static final char COMMA = ',';
// All formats use thread locals, to avoid problems if any of the static methods are invoked concurrently
Expand Down Expand Up @@ -145,7 +147,7 @@ public static VType valueFromString(String indata, VType type) throws IllegalArg
Time time = Time.now();
if (type instanceof VNumberArray) {
ListNumber list = null;
String[] elements = data.split("\\,");
String[] elements = data.split(",");
if (((VNumberArray) type).getData().size() != elements.length) {
throw new IllegalArgumentException("The number of array elements is different from the original.");
}
Expand Down Expand Up @@ -213,12 +215,12 @@ public static VType valueFromString(String indata, VType type) throws IllegalArg

return VNumberArray.of(list, alarm, time, Display.none());
} else if (type instanceof VStringArray) {
String[] elements = data.split("\\,");
String[] elements = data.split(",");
List<String> list = Arrays.stream(elements).map(String::trim).collect(Collectors.toList());
list = list.stream().map(s -> s.substring(1, s.length() - 1)).collect(Collectors.toList());
return VStringArray.of(list, alarm, time);
} else if (type instanceof VBooleanArray) {
String[] elements = data.split("\\,");
String[] elements = data.split(",");
List<String> list = Arrays.stream(elements).map(String::trim).collect(Collectors.toList());
boolean[] booleans = new boolean[list.size()];
for (int i = 0; i < list.size(); i++) {
Expand Down Expand Up @@ -281,7 +283,7 @@ public static VType valueFromString(String indata, VType type) throws IllegalArg

/**
* Extracts the raw value from the given data object. The raw value is either one of the primitive wrappers or some
* kind of a list type if the value is an {@link Array}.
* list type if the value is an {@link Array}.
*
* @param type the value to extract the raw data from
* @return the raw data
Expand Down Expand Up @@ -320,12 +322,20 @@ public static Object toRawValue(VType type) {
return ((VString) type).getValue();
} else if (type instanceof VBoolean) {
return ((VBoolean) type).getValue();
} else if (type instanceof VTable) {
VTable vTable = (VTable) type;
int columnCount = vTable.getColumnCount();
List dataArrays = new ArrayList();
for (int i = 0; i < columnCount; i++) {
dataArrays.add(toPVArrayType("Col " + i, vTable.getColumnData(i)));
}
return new PVAStructure(PVATable.STRUCT_NAME, "", dataArrays);
}
return null;
}

/**
* Transforms the value of the given {@link VType} to a human readable string. This method uses formatting to format
* Transforms the value of the given {@link VType} to a human-readable string. This method uses formatting to format
* all values, which may result in the arrays being truncated.
*
* @param type the data to transform
Expand Down Expand Up @@ -353,16 +363,16 @@ public static String valueToString(VType type, int arrayLimit) {
int size = Math.min(arrayLimit, list.size());
StringBuilder sb = new StringBuilder(size * 15 + 2);
sb.append('[');
Pattern pattern = Pattern.compile("\\,");
Pattern pattern = Pattern.compile(",");
NumberFormat formatter = ((SimpleValueFormat) FORMAT.get()).getNumberFormat();
if (type instanceof VDoubleArray) {
for (int i = 0; i < size; i++) {
sb.append(pattern.matcher(formatter.format(list.getDouble(i))).replaceAll("\\.")).append(COMMA)
sb.append(pattern.matcher(formatter.format(list.getDouble(i))).replaceAll(".")).append(COMMA)
.append(' ');
}
} else if (type instanceof VFloatArray) {
for (int i = 0; i < size; i++) {
sb.append(pattern.matcher(formatter.format(list.getFloat(i))).replaceAll("\\.")).append(COMMA)
sb.append(pattern.matcher(formatter.format(list.getFloat(i))).replaceAll(".")).append(COMMA)
.append(' ');
}
} else if (type instanceof VULongArray) {
Expand Down Expand Up @@ -451,8 +461,10 @@ public static String valueToString(VType type, int arrayLimit) {
return ((VString) type).getValue();
} else if (type instanceof VBoolean) {
return String.valueOf(((VBoolean) type).getValue());
} else if (type instanceof VTable) {
return "[VTable]";
}
// no support for MultiScalars (VMultiDouble, VMultiInt, VMultiString, VMultiEnum), VStatistics, VTable and
// no support for MultiScalars (VMultiDouble, VMultiInt, VMultiString, VMultiEnum), VStatistics and
// VImage)
return "Type " + VType.typeOf(type).getSimpleName() + " not supported";
}
Expand Down Expand Up @@ -886,6 +898,9 @@ public static VTypeComparison deltaValueToString(VType value, VType baseValue, O
} else if (value instanceof VBooleanArray && baseValue instanceof VBooleanArray) {
boolean equal = areValuesEqual(value, baseValue, Optional.empty());
return new VTypeComparison(equal ? "---" : "NOT EQUAL", equal ? 0 : 1, equal);
} else if (value instanceof VTable && baseValue instanceof VTable) {
boolean equal = areValuesEqual(value, baseValue, Optional.empty());
return new VTypeComparison(equal ? "---" : "NOT EQUAL", equal ? 0 : 1, equal);
} else {
String str = valueToString(value);
boolean valuesEqual = areValuesEqual(value, baseValue, Optional.empty());
Expand Down Expand Up @@ -928,7 +943,7 @@ public static String deltaValueToPercentage(VType value, VType baseValue) {
}

/**
* Checks if the values of the given vtype are equal and returns true if they are or false if they are not.
* Checks if the values of the given {@link VType} are equal and returns true if they are or false if they are not.
* Timestamps, alarms and other parameters are ignored.
*
* @param v1 the first value to check
Expand Down Expand Up @@ -1115,12 +1130,63 @@ public static boolean areValuesEqual(VType v1, VType v2, Optional<Threshold<?>>
}
}
return true;
} else if (v1 instanceof VTable && v2 instanceof VTable) {
VTable vTable1 = (VTable) v1;
VTable vTable2 = (VTable) v2;
if (vTable1.getColumnCount() != vTable2.getColumnCount() ||
vTable1.getRowCount() != vTable2.getRowCount()) {
return false;
}
for (int i = 0; i < vTable1.getColumnCount(); i++) {
if (!vTable1.getColumnType(i).equals(vTable2.getColumnType(i))) {
return false;
}
if (!vTable1.getColumnName(i).equals(vTable2.getColumnName(i))) {
return false;
}
if (!areVTypeArraysEqual(vTable1.getColumnType(i), vTable1.getColumnData(i), vTable2.getColumnData(i))) {
return false;
}
}
return true;
}
// no support for MultiScalars (VMultiDouble, VMultiInt, VMultiString, VMultiEnum), VStatistics, VTable,
// VImage
return false;
}

/**
* Compares array objects
*
* @param clazz Class of the input data objects
* @param a1 First object
* @param a2 Second object
* @return <code>true</code> if all elements in arrays are equal.
*/
public static boolean areVTypeArraysEqual(Class clazz, Object a1, Object a2) {
switch (clazz.getName()) {
case "int":
case "long":
case "double":
case "float":
case "short":
case "byte":
return areValuesEqual(VNumberArray.of((ListNumber) a1, Alarm.none(), Time.now(), Display.none()),
VNumberArray.of((ListNumber) a2, Alarm.none(), Time.now(), Display.none()),
Optional.empty());
case "boolean":
return areValuesEqual(VBooleanArray.of((ListBoolean) a1, Alarm.none(), Time.now()),
VBooleanArray.of((ListBoolean) a2, Alarm.none(), Time.now()),
Optional.empty());
case "java.lang.String":
return areValuesEqual(VStringArray.of((List) a1, Alarm.none(), Time.now()),
VStringArray.of((List) a2, Alarm.none(), Time.now()),
Optional.empty());
default:
return false;
}
}

/**
* Compares two instances of {@link VType} and returns true if they are identical or false of they are not. Values
* are identical if their alarm signatures are identical, timestamps are the same, values are the same and in case
Expand Down Expand Up @@ -1286,4 +1352,66 @@ private static boolean isAlarmAndTimeEqual(VType a1, VType a2) {
}
return false;
}

/**
* @param name Data item name
* @param object The object subject to conversion
* @return Converted object
*/
public static Object toPVArrayType(String name, Object object) {
if (object instanceof ListBoolean) {
ListBoolean listBoolean = (ListBoolean) object;
boolean[] booleans = new boolean[listBoolean.size()];
for (int i = 0; i < listBoolean.size(); i++) {
booleans[i] = listBoolean.getBoolean(i);
}
return new PVABoolArray(name, booleans);
} else if (object instanceof ListNumber) {
ListNumber listNumber = (ListNumber) object;
if (object instanceof ArrayByte || object instanceof ArrayUByte) {
byte[] bytes = new byte[listNumber.size()];
for (int i = 0; i < listNumber.size(); i++) {
bytes[i] = listNumber.getByte(i);
}
return new PVAByteArray(name, object instanceof ArrayUByte, bytes);
} else if (object instanceof ArrayShort || object instanceof ArrayUShort) {
short[] shorts = new short[listNumber.size()];
for (int i = 0; i < listNumber.size(); i++) {
shorts[i] = listNumber.getShort(i);
}
return new PVAShortArray(name, object instanceof ArrayUShort, shorts);
} else if (object instanceof ArrayInteger || object instanceof ArrayUInteger) {
int[] ints = new int[listNumber.size()];
for (int i = 0; i < listNumber.size(); i++) {
ints[i] = listNumber.getInt(i);
}
return new PVAIntArray(name, object instanceof ArrayUInteger, ints);
} else if (object instanceof ArrayLong || object instanceof ArrayULong) {
long[] longs = new long[listNumber.size()];
for (int i = 0; i < listNumber.size(); i++) {
longs[i] = listNumber.getLong(i);
}
return new PVALongArray(name, object instanceof ArrayULong, longs);
} else if (object instanceof ArrayFloat) {
float[] floats = new float[listNumber.size()];
for (int i = 0; i < listNumber.size(); i++) {
floats[i] = listNumber.getFloat(i);
}
return new PVAFloatArray(name, floats);
} else if (object instanceof ArrayDouble) {
double[] doubles = new double[listNumber.size()];
for (int i = 0; i < listNumber.size(); i++) {
doubles[i] = listNumber.getDouble(i);
}
return new PVADoubleArray(name, doubles);
} else {
throw new IllegalArgumentException("Conversion of type " + object.getClass().getCanonicalName() + " not supported");
}
} else { // Assume this always is for string arrays
Collection<String> list = (Collection<String>) object;
String[] strings = new String[list.size()];
strings = list.toArray(strings);
return new PVAStringArray(name, strings);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ protected SaveAndRestorePV(TableEntry snapshotTableEntry) {
this.snapshotTableEntry.setReadbackValue(this.readbackValue);
});
} else {
// If configuration does not define readback PV, then UI should show "no data" rather than "disconnected"
// If configuration does not define read-back PV, then UI should show "no data" rather than "disconnected"
this.snapshotTableEntry.setReadbackValue(VNoData.INSTANCE);
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ public void restore(Snapshot snapshot, Consumer<List<String>> completion) {
}

try {
countDownLatch.await();
countDownLatch.await(10, TimeUnit.MINUTES);
} catch (InterruptedException e) {
LOGGER.log(Level.INFO, "Encountered InterruptedException", e);
}
Expand Down
Loading

0 comments on commit e4ba86a

Please sign in to comment.