
org.tango.utils.TangoUtil Maven / Gradle / Ivy
/*
* (c) Copyright 2004, iSencia Belgium NV
* All Rights Reserved.
*
* This software is the proprietary information of iSencia Belgium NV.
* Use is subject to license terms.
*/
package org.tango.utils;
import fr.esrf.Tango.AttrDataFormat;
import fr.esrf.Tango.AttrWriteType;
import fr.esrf.Tango.DevFailed;
import fr.esrf.TangoApi.ApiUtil;
import fr.esrf.TangoApi.Database;
import fr.esrf.TangoDs.TangoConst;
import java.util.AbstractMap.SimpleEntry;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Some utilities for tango
*/
public final class TangoUtil {
public static final String DEVICE_SEPARATOR = "/";
public static final int EXPECTED_FULL_NAME_FIELDS = 4;
public static final String DEVICE_PATTERN = "*";
/**
* Contains all tango types for scalar commands
*/
public static final List SCALARS;
/**
* Contains all tango types for spectrum commands
*/
public static final List SPECTRUMS;
public static final Map WRITABLE_MAP;
public static final Map FORMAT_MAP;
public static final Map TYPE_MAP;
public static final String DBASE_NO = "#dbase=no";
private static final Pattern ENTITY_SPLIT_PATTERN;
private static final int PREFIX_INDEX = 1;
private static final int ATTRIBUTE_ALIAS_INDEX = 2;
private static final int DEVICE_NAME_INDEX = 3;
private static final int DEVICE_ALIAS_INDEX = 4;
/*
* http://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/ds_prog/node13.html
*
* [protocol://][host:port/]device_name[/attribute][->property][#dbase=xx]
*
* From the naming schema described above, the reserved characters are :,#,/ and the reserved string is : ->.
*/
private static final int ENTITY_INDEX = 5;
private static final int NO_DB_INDEX = 6;
static {
final List tempList = new ArrayList<>();
tempList.add(TangoConst.Tango_DEV_BOOLEAN);
tempList.add(TangoConst.Tango_DEV_DOUBLE);
tempList.add(TangoConst.Tango_DEV_FLOAT);
tempList.add(TangoConst.Tango_DEV_LONG);
tempList.add(TangoConst.Tango_DEV_SHORT);
tempList.add(TangoConst.Tango_DEV_UCHAR);
tempList.add(TangoConst.Tango_DEV_ULONG);
tempList.add(TangoConst.Tango_DEV_USHORT);
tempList.add(TangoConst.Tango_DEV_STRING);
tempList.add(TangoConst.Tango_DEV_UCHAR);
tempList.add(TangoConst.Tango_DEV_ULONG64);
tempList.add(TangoConst.Tango_DEV_LONG64);
tempList.add(TangoConst.Tango_DEV_ENCODED);
tempList.add(TangoConst.Tango_DEV_STATE);
SCALARS = Collections.unmodifiableList(tempList);
}
static {
final List tempList2 = new ArrayList<>();
tempList2.add(TangoConst.Tango_DEVVAR_CHARARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_SHORTARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_LONGARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_FLOATARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_DOUBLEARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_USHORTARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_ULONGARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_STRINGARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_LONG64ARRAY);
tempList2.add(TangoConst.Tango_DEVVAR_ULONG64ARRAY);
SPECTRUMS = Collections.unmodifiableList(tempList2);
}
static {
final Map tmpMap1 = new HashMap<>();
tmpMap1.put(AttrWriteType.READ.toString(), AttrWriteType.READ);
tmpMap1.put(AttrWriteType.READ_WITH_WRITE.toString(), AttrWriteType.READ_WITH_WRITE);
tmpMap1.put(AttrWriteType.WRITE.toString(), AttrWriteType.WRITE);
tmpMap1.put(AttrWriteType.READ_WRITE.toString(), AttrWriteType.READ_WRITE);
WRITABLE_MAP = Collections.unmodifiableMap(tmpMap1);
}
static {
final Map tmpMap2 = new HashMap<>();
tmpMap2.put(AttrDataFormat.SCALAR.toString(), AttrDataFormat.SCALAR);
tmpMap2.put(AttrDataFormat.SPECTRUM.toString(), AttrDataFormat.SPECTRUM);
tmpMap2.put(AttrDataFormat.IMAGE.toString(), AttrDataFormat.IMAGE);
tmpMap2.put(AttrDataFormat.FMT_UNKNOWN.toString(), AttrDataFormat.FMT_UNKNOWN);
FORMAT_MAP = Collections.unmodifiableMap(tmpMap2);
}
static {
final Map tmpMap3 = new HashMap<>();
tmpMap3.put("VOID", 0);
tmpMap3.put("BOOLEAN", 1);
tmpMap3.put("SHORT", 2);
tmpMap3.put("LONG", 3);
tmpMap3.put("FLOAT", 4);
tmpMap3.put("DOUBLE", 5);
tmpMap3.put("USHORT", 6);
tmpMap3.put("ULONG", 7);
tmpMap3.put("STRING", 8);
tmpMap3.put("STATE", 19);
tmpMap3.put("CONST_STRING", 20);
tmpMap3.put("CHAR", 21);
tmpMap3.put("UCHAR", 22);
tmpMap3.put("LONG64", 23);
tmpMap3.put("ULONG64", 24);
tmpMap3.put("INT", 27);
tmpMap3.put("ENCODED", 28);
TYPE_MAP = Collections.unmodifiableMap(tmpMap3);
}
static {
// (?: xxx ) = non capturing group
// ( xxx ) = capturing group. Group content is "xxx" once the matcher is finished
final String nameR = "[\\w\\-\\.]+";// ie [a-zA-Z_0-9-.]
final String protocolR = "(?:(?:(?:tango|taco):)?//)";// not interested in protocol
final String hostPortR = "(?:" + nameR + ":\\d+/)";// not interested in host and port
final String prefixR = "(" + protocolR + "?" + hostPortR + "?)";// interested in prefix
final String deviceAliasR = "(" + nameR + ")";
final String attributeAliasR = "(" + nameR + ")";
final String deviceR = "(" + nameR + "/" + nameR + "/" + nameR + ")";
final String attributeR = "(?:/(" + nameR + "))";// interested in attribute's name
final String propertyR = "(?:->" + nameR + ")?";// not interested in property
final String dbaseR = "(?:#dbase=(yes|(no)))?";// interested in 'no' only
// prefix is always in a group, can be empty
// attribute is mandatory for the purpose of splitting to "device/entity"
final String entityR = prefixR + "(?:" + attributeAliasR + "|(?:(?:" + deviceR + "|" + deviceAliasR + ")"
+ attributeR + "))" + propertyR + dbaseR;
// This pattern is designed for splitting full device name and entity name.
// It cannot be used for syntax validation.
ENTITY_SPLIT_PATTERN = Pattern.compile(entityR, Pattern.CASE_INSENSITIVE);
}
private TangoUtil() {
}
/**
* Splits an entity name into full device name and attribute name. Aliases will be resolved against tango db first.
*
* @param entityName the entity name to split. It can contain aliases for device or attribute
* @return a Map.Entry containing the full device name as key and the attribute name as value, or null if split was
* not possible
* @throws DevFailed in case of DB access problem
*/
public static final Entry splitDeviceEntity(final String entityName) throws DevFailed {
Entry result = null;
final Matcher matcher = ENTITY_SPLIT_PATTERN.matcher(entityName.trim());
if (matcher.matches()) {
String device = null;
String entity = null;
final String prefixGroup = matcher.group(PREFIX_INDEX);
final boolean noDb = matcher.group(NO_DB_INDEX) != null;
if (noDb) {
// TODO cas device alias qui marche soleil
if (matcher.group(DEVICE_NAME_INDEX) != null && matcher.group(ENTITY_INDEX) != null) {
final String deviceNameGroup = matcher.group(DEVICE_NAME_INDEX);
final String entityGroup = matcher.group(ENTITY_INDEX);
device = prefixGroup + deviceNameGroup;
entity = entityGroup;
}
} else {
if (matcher.group(ATTRIBUTE_ALIAS_INDEX) != null) {
final String attributeAliasGroup = matcher.group(ATTRIBUTE_ALIAS_INDEX);
final String fullAttributeName = ApiUtil.get_db_obj().get_attribute_from_alias(attributeAliasGroup);
final int lastIndexOf = fullAttributeName.lastIndexOf(DEVICE_SEPARATOR);
device = prefixGroup + fullAttributeName.substring(0, lastIndexOf);// TODO exception ?
entity = fullAttributeName.substring(lastIndexOf + 1);
} else if (matcher.group(DEVICE_ALIAS_INDEX) != null) {
final String deviceAliasGroup = matcher.group(DEVICE_ALIAS_INDEX);
final String entityGroup = matcher.group(ENTITY_INDEX);
final String fullDeviceName = ApiUtil.get_db_obj().get_device_from_alias(deviceAliasGroup);
device = prefixGroup + fullDeviceName;
entity = entityGroup;
} else {
final String deviceNameGroup = matcher.group(DEVICE_NAME_INDEX);
final String entityGroup = matcher.group(ENTITY_INDEX);
device = prefixGroup + deviceNameGroup;
entity = entityGroup;
}
}
if (device != null && entity != null) {
result = new SimpleEntry<>(device, entity);
}
}
return result;
}
/**
* Splits a collection of entity names and group attributes by device.
*
* @param entityNames a list of entity names to split
* @return a map containing a list of attributes for each device.
*/
public static Map> splitDeviceEntities(final Collection entityNames) {
final Map> result = new HashMap<>();
String device;
String entity;
for (final String entityName : entityNames) {
try {
final Entry deviceEntity = splitDeviceEntity(entityName);
if (deviceEntity != null) {
device = deviceEntity.getKey();
entity = deviceEntity.getValue();
if (device != null && entity != null) {
Collection attributes = result.get(device);
if (attributes == null) {
attributes = new HashSet<>();
result.put(device, attributes);
}
attributes.add(entity);
}
}
} catch (final DevFailed e) {
// nop
}
}
return result;
}
/**
* Get the full device name for an attribute
*
* @param attributeName
* @return
* @throws DevFailed
*/
public static String getfullDeviceNameForAttribute(final String attributeName) throws DevFailed {
checkNullOrEmptyString(attributeName);
String result;
if (attributeName.contains(DBASE_NO)) {
result = attributeName.substring(0, attributeName.lastIndexOf(DEVICE_SEPARATOR));
} else {
final String[] fields = attributeName.split(DEVICE_SEPARATOR);
if (fields.length == 1) {
result = getfullDeviceNameForAttribute(ApiUtil.get_db_obj().get_attribute_from_alias(fields[0]));
} else if (fields.length == 2) {
result = ApiUtil.get_db_obj().get_device_from_alias(fields[0]);
} else if (fields.length == 4) {
result = fields[0] + DEVICE_SEPARATOR + fields[1] + DEVICE_SEPARATOR + fields[2];
} else {
throw DevFailedUtils.newDevFailed("TANGO_WRONG_DATA_ERROR", "cannot retrieve device name");
}
}
return result;
}
/**
* Get the full attribute name
*
* @param attributeName
* @return
* @throws DevFailed
*/
public static String getfullAttributeNameForAttribute(final String attributeName) throws DevFailed {
checkNullOrEmptyString(attributeName);
String result;
if (attributeName.contains(DBASE_NO)) {
result = attributeName;
} else {
final String[] fields = attributeName.split(DEVICE_SEPARATOR);
final Database db = ApiUtil.get_db_obj();
if (fields.length == 1) {
result = db.get_attribute_from_alias(fields[0]);
} else if (fields.length == 2) {
result = db.get_device_from_alias(fields[0]) + DEVICE_SEPARATOR + fields[1];
} else {
result = attributeName;
}
}
return result;
}
public static String getFullDeviceNameForCommand(final String commandName) throws DevFailed {
checkNullOrEmptyString(commandName);
return getfullNameForDevice(commandName.substring(0, commandName.lastIndexOf('/')));
}
public static void checkFullCommandName(String fullCommandName) throws DevFailed {
checkNullOrEmptyString(fullCommandName);
if (!fullCommandName.contains(DBASE_NO) &&
getDeviceSubstring(fullCommandName).split(TangoUtil.DEVICE_SEPARATOR).length != EXPECTED_FULL_NAME_FIELDS) {
throw DevFailedUtils.newDevFailed(fullCommandName + " command must contain 4 fields");
}
}
private static String getDeviceSubstring(String fullCommandName) {
String deviceSubstring = fullCommandName;
if (fullCommandName.contains("://")) {
deviceSubstring = fullCommandName.split("://", 2)[1];
}
String regex = ":\\d+/"; // regex for matching ":/"
if (deviceSubstring.matches(".*" + regex + ".*")) {
deviceSubstring = deviceSubstring.split(TangoUtil.DEVICE_SEPARATOR, 2)[1];
}
return deviceSubstring;
}
/**
* Get the full device name
*
* @param deviceName
* @return
* @throws DevFailed
*/
public static String getfullNameForDevice(final String deviceName) throws DevFailed {
checkNullOrEmptyString(deviceName);
final String[] fields = deviceName.split(DEVICE_SEPARATOR);
if (deviceName.contains(DBASE_NO) || fields.length != 1) {
return deviceName;
} else {
final Database db = ApiUtil.get_db_obj();
return db.get_device_from_alias(fields[0]);
}
}
/**
* Get the list of device names which matches the pattern p
*
* @param deviceNamePattern The pattern. The wild char is *
* @return A list of device names
* @throws DevFailed
*/
public static String[] getDevicesForPattern(final String deviceNamePattern) throws DevFailed {
checkNullOrEmptyString(deviceNamePattern);
String[] devices;
// is p a device name or a device name pattern ?
if (!deviceNamePattern.contains(DEVICE_PATTERN)) {
// p is a pure device name
devices = new String[1];
devices[0] = getfullNameForDevice(deviceNamePattern);
} else {
// ask the db the list of device matching pattern p
final Database db = ApiUtil.get_db_obj();
devices = db.get_device_exported(deviceNamePattern);
}
return devices;
}
/**
* Get the list of device names which matches the pattern p
*
* @param deviceNamePattern The pattern. The wild char is *
* @param exported to get the exported device
* @return A list of device names
* @throws DevFailed
*/
public static String[] getDevicesForPattern(final String deviceNamePattern, final boolean exported)
throws DevFailed {
checkNullOrEmptyString(deviceNamePattern);
String[] devices;
if (exported) {
devices = getDevicesForPattern(deviceNamePattern);
} else {
if (!deviceNamePattern.contains(DEVICE_PATTERN)) {
// p is a pure device name
devices = new String[1];
devices[0] = getfullNameForDevice(deviceNamePattern);
} else {
// ask the db the list of device matching pattern p
final Database db = ApiUtil.get_db_obj();
devices = db.get_device_list(deviceNamePattern);
}
}
return devices;
}
/**
* Return the attribute name part without device name
* It is able to resolve attribute alias before
*
* @param fullname
* @return
* @throws DevFailed
*/
public static String getAttributeName(final String fullname) throws DevFailed {
final String s = getfullAttributeNameForAttribute(fullname);
return s.substring(s.lastIndexOf(DEVICE_SEPARATOR) + 1);
}
private static void checkNullOrEmptyString(final String s) throws DevFailed {
if (s == null || s.isEmpty()) {
throw DevFailedUtils.newDevFailed("string is null or empty");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy