
fr.esrf.TangoApi.Group.Group Maven / Gradle / Ivy
//+======================================================================
// $Source$
//
// Project: Tango
//
// Description: java source code for the TANGO client/server API.
//
// $Author: pascal_verdier $
//
// Copyright (C) : 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This file is part of Tango.
//
// Tango 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 3 of the License, or
// (at your option) any later version.
//
// Tango 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 Tango. If not, see .
//
// $Revision: 25296 $
//
//-======================================================================
package fr.esrf.TangoApi.Group;
//- Import Java stuffs
import fr.esrf.Tango.DevFailed;
import fr.esrf.TangoApi.*;
import fr.esrf.TangoDs.Except;
import java.io.Serializable;
import java.util.*;
/**
* TANGO group abstraction main class
*/
public class Group extends GroupElement implements java.io.Serializable {
/**
* Group's elements repository
*/
private final List elements;
// -- PUBLIC INTERFACE -----------------------------------------------------
// -------------------------------------------------------------------------
/**
* Group element factory
*/
private final GroupElementFactory factory;
/**
* Asynch request repository
*/
private final TreeMap arp;
/**
* Pseudo asynch. request id generator
*/
private int asynch_req_id;
private static final String API_BAD_ASYN_POLL_ID = "API_BadAsynPollId";
private static final String API_BAD_ASYN_POLL_ID_DESC = "Invalid asynch. request identifier specified";
/**
* Creates a new instance of Group
*/
public Group(final String name) {
super(name);
asynch_req_id = 0;
elements = new ArrayList<>();
factory = new GroupElementFactory();
arp = new TreeMap<>();
}
/**
* Dump group
*/
public void dump() {
synchronized (this) {
dump_i(0);
}
}
/**
* Ping the group returns true if all device alive, false otherwise
*/
public boolean ping(final boolean fwd) {
synchronized (this) {
return ping_i(fwd);
}
}
/**
* Returns the group's device list
*/
public String[] get_device_list(final boolean fwd) {
return get_device_name_list(fwd);
}
/**
* Returns the first group named in the hierarchy
*/
public Group get_group(final String n) {
synchronized (this) {
return get_group_i(n, true);
}
}
/**
* Returns the device named in the hierarchy
*/
public DeviceProxy get_device(final String n) {
synchronized (this) {
return get_device_i(n);
}
}
/**
* Returns the th device in the hierarchy
*/
public DeviceProxy get_device(final int i) {
synchronized (this) {
return get_device_i(i);
}
}
/**
* Returns the group's size
*/
@Override
public int get_size(final boolean fwd) {
synchronized (this) {
return get_size_i(fwd);
}
}
/**
* Adds a group to the group
*/
public void add(final Group g) {
if (g == null) {
return;
}
synchronized (this) {
add_i(g);
}
}
/**
* Adds devices matching pattern
*
* to the group
*
* @throws DevFailed
*/
public void add(final String p) throws DevFailed {
synchronized (this) {
final List v = factory.instantiate(p);
for (Object o : v) {
add_i((GroupElement) o);
}
}
}
/**
* Adds devices matching patterns to the group
*
* @throws DevFailed
*/
public void add(final String[] pl) throws DevFailed {
synchronized (this) {
for (final String element : pl) {
if (element != null) {
final List v = factory.instantiate(element);
for (GroupDeviceElement o : v) {
add_i(o);
}
}
}
}
}
/**
* Remove elements matching pattern
*
* from the group
*/
public void remove(final String p, final boolean fwd) {
synchronized (this) {
remove_i(p, fwd);
}
}
/**
* Remove elements matching patterns from the group
*/
public void remove(final String[] pl, final boolean fwd) {
synchronized (this) {
for (final String element : pl) {
remove_i(element, fwd);
}
}
}
/**
* Remove all elements from the group
*/
public void remove_all() {
synchronized (this) {
remove_all(false);
}
}
public void remove_all(boolean fwd) {
synchronized (this) {
remove_fwd("*", fwd);
elements.clear();
}
}
/**
* Returns true if the group contains an element named , false otherwise
*/
public boolean contains(final String n, final boolean fwd) {
synchronized (this) {
return find_i(n, fwd) != null;
}
}
/**
* set_timeout_millis
*/
@Override
public void set_timeout_millis(final int timeout, final boolean fwd) throws DevFailed {
synchronized (this) {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
e.set_timeout_millis(timeout, fwd);
}
}
}
}
/**
* command_inout
*/
public GroupCmdReplyList command_inout(final String c, final boolean fwd) throws DevFailed {
synchronized (this) {
final int rid = command_inout_asynch_i(c, false, fwd, next_req_id());
return command_inout_reply_i(rid, 0, fwd);
}
}
/**
* command_inout
*/
public GroupCmdReplyList command_inout(final String c, final DeviceData dd, final boolean fwd) throws DevFailed {
synchronized (this) {
final int rid = command_inout_asynch_i(c, dd, false, fwd, next_req_id());
return command_inout_reply_i(rid, 0, fwd);
}
}
/**
* get_command_argument_list
*/
public DeviceData[] get_command_specific_argument_list(final boolean fwd) throws DevFailed {
final int al_size = get_size(fwd);
final DeviceData[] al = new DeviceData[al_size];
for (int i = 0; i < al_size; i++) {
al[i] = new DeviceData();
}
return al;
}
/**
* command_inout
*/
public GroupCmdReplyList command_inout(final String c, final DeviceData[] dd, final boolean fwd) throws DevFailed {
synchronized (this) {
final int rid = command_inout_asynch_i(c, dd, false, fwd, next_req_id());
return command_inout_reply_i(rid, 0, fwd);
}
}
/**
* command_inout_asynch
*/
public int command_inout_asynch(final String c, final boolean fgt, final boolean fwd) throws DevFailed {
final int rid = command_inout_asynch_i(c, fgt, fwd, next_req_id());
if (!fgt) {
arp.put(rid, fwd);
}
return rid;
}
/**
* command_inout_asynch
*/
public int command_inout_asynch(final String c, final DeviceData dd, final boolean fgt, final boolean fwd)
throws DevFailed {
final int rid = command_inout_asynch_i(c, dd, fgt, fwd, next_req_id());
if (!fgt) {
arp.put(rid, fwd);
}
return rid;
}
/**
* command_inout_asynch
*/
public int command_inout_asynch(final String c, final DeviceData[] dd, final boolean fgt, final boolean fwd)
throws DevFailed {
final int rid = command_inout_asynch_i(c, dd, fgt, fwd, next_req_id());
if (!fgt) {
arp.put(rid, fwd);
}
return rid;
}
/**
* command_inout_reply
*/
public GroupCmdReplyList command_inout_reply(final int rid, final int tmo) throws DevFailed {
final Boolean fwd = arp.get(rid);
if (fwd == null) {
throw new CommonDevFailed(API_BAD_ASYN_POLL_ID, API_BAD_ASYN_POLL_ID_DESC,
"Group.command_inout_reply");
}
arp.remove(rid);
return command_inout_reply_i(rid, tmo, fwd);
}
/**
* read_attribute
*/
public GroupAttrReplyList read_attribute(final String a, final boolean fwd) throws DevFailed {
synchronized (this) {
final int rid = read_attribute_asynch_i(a, fwd, next_req_id());
return read_attribute_reply_i(rid, 0, fwd);
}
}
/**
* read_attribute_asynch
*/
public int read_attribute_asynch(final String a, final boolean fwd) throws DevFailed {
final int rid = read_attribute_asynch_i(a, fwd, next_req_id());
arp.put(rid, fwd);
return rid;
}
/**
* read_attribute_reply
*/
public GroupAttrReplyList read_attribute_reply(final int rid, final int tmo) throws DevFailed {
final Boolean fwd = arp.get(rid);
if (fwd == null) {
throw new CommonDevFailed(API_BAD_ASYN_POLL_ID, API_BAD_ASYN_POLL_ID_DESC,
"Group.read_inout_reply");
}
arp.remove(rid);
return read_attribute_reply_i(rid, tmo, fwd);
}
/**
* write_attribute
*/
public GroupReplyList write_attribute(final DeviceAttribute da, final boolean fwd) throws DevFailed {
synchronized (this) {
final int rid = write_attribute_asynch_i(da, fwd, next_req_id());
return write_attribute_reply_i(rid, 0, fwd);
}
}
/**
* get_command_argument_list
*/
public DeviceAttribute[] get_attribute_specific_value_list(final boolean fwd) {
synchronized (this) {
int i = 0;
final int av_size = get_size_i(fwd);
final DeviceAttribute[] av = new DeviceAttribute[av_size];
if (fwd) {
final List h = get_hierarchy();
for (GroupDeviceElement groupDeviceElement : h) {
av[i++] = new DeviceAttribute(groupDeviceElement.get_name());
}
} else {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement) {
av[i++] = new DeviceAttribute(e.get_name());
}
}
}
return av;
}
}
/**
* write_attribute
*/
public GroupReplyList write_attribute(final DeviceAttribute[] da, final boolean fwd) throws DevFailed {
synchronized (this) {
final int rid = write_attribute_asynch_i(da, fwd, next_req_id());
return write_attribute_reply_i(rid, 0, fwd);
}
}
// -- PRIVATE INTERFACE ----------------------------------------------------
// -------------------------------------------------------------------------
/**
* write_attribute_asynch
*/
public int write_attribute_asynch(final DeviceAttribute da, final boolean fwd) throws DevFailed {
final int rid = write_attribute_asynch_i(da, fwd, next_req_id());
arp.put(rid, fwd);
return rid;
}
/**
* write_attribute_asynch
*/
public int write_attribute_asynch(final DeviceAttribute[] da, final boolean fwd) throws DevFailed {
final int rid = write_attribute_asynch_i(da, fwd, next_req_id());
arp.put(rid, fwd);
return rid;
}
/**
* write_attribute_reply
*/
public GroupReplyList write_attribute_reply(final int rid, final int tmo) throws DevFailed {
final Boolean fwd = arp.get(rid);
if (fwd == null) {
throw new CommonDevFailed(API_BAD_ASYN_POLL_ID, API_BAD_ASYN_POLL_ID_DESC,
"Group.write_attribute_reply");
}
arp.remove(rid);
return write_attribute_reply_i(rid, tmo, fwd);
}
/**
* Returns the group's device list - access limited to package Group
*/
@Override
String[] get_device_name_list(final boolean fwd) {
synchronized (this) {
int i = 0;
final String[] dl = new String[get_size_i(fwd)];
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
final String[] sub_dl = e.get_device_name_list(fwd);
for (int j = 0; j < sub_dl.length; j++, i++) {
dl[i] = sub_dl[j];
}
}
}
return dl;
}
}
/**
* Returns the group's hierarchy
*/
private List get_hierarchy() {
synchronized (this) {
final List h = new ArrayList<>();
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement) {
h.add((GroupDeviceElement) e);
} else {
h.addAll(((Group) e).get_hierarchy());
}
}
return h;
}
}
/**
* Returns the group's size - internal impl
*/
private int get_size_i(final boolean fwd) {
int size = 0;
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
size += e.get_size(true);
}
}
return size;
}
/**
* Returns the group named or null if no such group - internal impl
*/
private Group get_group_i(final String n, final boolean fwd) {
final GroupElement e = find_i(n, fwd);
return e instanceof Group ? (Group) e : null;
}
/**
* Returns the first element named or null if no such element
*/
@Override
GroupElement find(final String n, final boolean fwd) {
synchronized (this) {
return find_i(n, fwd);
}
}
/**
* Returns the element named or null if no such element - internal impl
*/
private GroupElement find_i(final String n, final boolean fwd) {
if (name_equals(n)) {
return this;
}
GroupElement e;
for (GroupElement element : elements) {
e = element;
if (e.name_equals(n)) {
return e;
}
}
if (fwd) {
for (GroupElement element : elements) {
e = element.find(n, fwd);
if (e != null) {
return e;
}
}
}
return null;
}
/**
* Adds an element to the group
*/
private boolean add_i(final GroupElement e) {
if (e == null || e == this) {
// -DEBUG
String name = e == this ? e.get_name() : "";
System.out.println("Group::add_i::failed to add " + name + " (null or self)");
return false;
}
final GroupElement ge = find_i(e.get_name(), !(e instanceof Group));
if (ge != null && ge != this) {
// -DEBUG
System.out.println("Group::add_i::failed to add " + e.get_name() + " (already attached)");
return false;
}
elements.add(e);
e.set_parent(this);
return true;
}
/**
* Remove elements matching pattern
*
* from the group
*/
private void remove_i(final String p, final boolean fwd) {
if (name_equals(p)) {
System.out.println("Group::remove_i::failed to remove " + p + " (can't remove self)");
return;
}
if (p.indexOf('*') == -1) {
for (GroupElement e : elements) {
if (e.name_equals(p)) {
elements.remove(e);
break;
}
}
} else {
final List remove_list = new ArrayList<>();
Iterator it = elements.iterator();
remove_fwd("*", fwd);
while (it.hasNext()) {
final GroupElement e = it.next();
if (e.name_matches(p)) {
remove_list.add(e);
}
}
it = remove_list.iterator();
while (it.hasNext()) {
elements.remove(it.next());
}
}
remove_fwd(p, fwd);
}
private void remove_fwd(final String p, final boolean fwd) {
if (fwd) {
for (GroupElement e : elements) {
if (e instanceof Group) {
((Group) e).remove(p, fwd);
}
}
}
}
/**
* Returns the th device in the hierarchy - access limited to package
* Group
*/
@Override
DeviceProxy get_device_i(int i) {
synchronized (this) {
DeviceProxy dp = null;
final Iterator it = elements.iterator();
while (dp == null && it.hasNext()) {
final GroupElement e = it.next();
dp = e.get_device_i(i--);
if (e instanceof Group) {
i--;
}
}
return dp;
}
}
/**
* Returns device in the hierarchy - access limited to package Group
*/
@Override
DeviceProxy get_device_i(final String n) {
DeviceProxy dp = null;
final Iterator it = elements.iterator();
while (dp == null && it.hasNext()) {
final GroupElement e = it.next();
dp = e.get_device_i(n);
}
return dp;
}
/**
* Dump group - access limited to package Group
*/
@Override
void dump_i(final int indent_level) {
for (int i = 0; i < indent_level; i++) {
System.out.print(" ");
}
System.out.println("|- Group: " + get_name() + " [" + get_size_i(true) + ":" + get_size_i(false) + "]");
for (GroupElement element : elements) {
element.dump_i(indent_level + 1);
}
}
/**
* Ping the group - access limited to package Group
*/
@Override
boolean ping_i(final boolean fwd) {
boolean all_alive = true;
final Iterator it = elements.iterator();
while (it.hasNext() && all_alive) {
final GroupElement e = it.next();
if (e instanceof GroupDeviceElement || fwd) {
all_alive = e.ping_i(fwd);
}
}
return all_alive;
}
/**
* command_inout_asynch_i - access limited to package Group
*/
@Override
int command_inout_asynch_i(final String c, final boolean fgt, final boolean fwd, final int rid) throws DevFailed {
synchronized (this) {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
e.command_inout_asynch_i(c, fgt, fwd, rid);
}
}
return rid;
}
}
/**
* command_inout_i - access limited to package Group
*/
@Override
int command_inout_asynch_i(final String c, final DeviceData dd, final boolean fgt, final boolean fwd, final int rid)
throws DevFailed {
synchronized (this) {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
e.command_inout_asynch_i(c, dd, fgt, fwd, rid);
}
}
return rid;
}
}
/**
* command_inout_asynch_i - access limited to package Group
*/
private int command_inout_asynch_i(final String c, final DeviceData[] dd, final boolean fgt, final boolean fwd,
final int rid) throws DevFailed {
synchronized (this) {
final int gsize = get_size_i(fwd);
if (gsize != dd.length) {
final String desc = "the size of the input argument list must equal the number of device in the group"
+ " [expected:" + gsize + " - got:" + dd.length + "]";
throw new CommonDevFailed("API_MethodArgument", desc, "Group.command_inout_asynch");
}
int i = 0;
if (fwd) {
final List h = get_hierarchy();
for (GroupDeviceElement groupDeviceElement : h) {
groupDeviceElement.command_inout_asynch_i(c, dd[i++], fgt, fwd, rid);
}
} else {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement) {
e.command_inout_asynch_i(c, dd[i++], fgt, fwd, rid);
}
}
}
return rid;
}
}
/**
* command_inout_reply_i - access limited to package Group
*/
@Override
GroupCmdReplyList command_inout_reply_i(final int rid, final int tmo, final boolean fwd) throws DevFailed {
synchronized (this) {
final GroupCmdReplyList reply = new GroupCmdReplyList();
GroupCmdReplyList sub_reply;
for (GroupElement ge : elements) {
if (ge instanceof GroupDeviceElement || fwd) {
sub_reply = ge.command_inout_reply_i(rid, tmo, fwd);
if (!sub_reply.isEmpty()) {
reply.addAll(sub_reply);
}
if (sub_reply.has_failed()) {
reply.has_failed = true;
}
}
}
return reply;
}
}
/**
* read_attribute_asynch_i - access limited to package Group
*/
@Override
int read_attribute_asynch_i(final String a, final boolean fwd, final int rid) throws DevFailed {
synchronized (this) {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
e.read_attribute_asynch_i(a, fwd, rid);
}
}
return rid;
}
}
/**
* read_attribute_reply_i - access limited to package Group
*/
@Override
GroupAttrReplyList read_attribute_reply_i(final int rid, final int tmo, final boolean fwd) throws DevFailed {
synchronized (this) {
final GroupAttrReplyList reply = new GroupAttrReplyList();
GroupAttrReplyList sub_reply;
for (GroupElement ge : elements) {
if (ge instanceof GroupDeviceElement || fwd) {
sub_reply = ge.read_attribute_reply_i(rid, tmo, fwd);
if (!sub_reply.isEmpty()) {
reply.addAll(sub_reply);
}
if (sub_reply.has_failed()) {
reply.has_failed = true;
}
}
}
return reply;
}
}
/**
* write_attribute_asynch_i - access limited to package Group
*/
@Override
int write_attribute_asynch_i(final DeviceAttribute da, final boolean fwd, final int rid) throws DevFailed {
synchronized (this) {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement || fwd) {
e.write_attribute_asynch_i(da, fwd, rid);
}
}
return rid;
}
}
/**
* write_attribute_asynch_i - access limited to package Group
*/
private int write_attribute_asynch_i(final DeviceAttribute[] da, final boolean fwd, final int rid) throws DevFailed {
synchronized (this) {
final int gsize = get_size_i(fwd);
if (gsize != da.length) {
final String desc = "the size of the input argument list must equal the number of device in the group"
+ " [expected:" + gsize + " - got:" + da.length + "]";
throw new CommonDevFailed("API_MethodArgument", desc, "Group.write_attribute_asynch");
}
int i = 0;
if (fwd) {
final List h = get_hierarchy();
for (GroupDeviceElement groupDeviceElement : h) {
groupDeviceElement.write_attribute_asynch_i(da[i++], fwd, rid);
}
} else {
for (GroupElement e : elements) {
if (e instanceof GroupDeviceElement) {
e.write_attribute_asynch_i(da[i++], fwd, rid);
}
}
}
return rid;
}
}
/**
* write_attribute_reply_i - access limited to package Group
*/
@Override
GroupReplyList write_attribute_reply_i(final int rid, final int tmo, final boolean fwd) throws DevFailed {
synchronized (this) {
final GroupReplyList reply = new GroupReplyList();
GroupReplyList sub_reply;
for (GroupElement ge : elements) {
if (ge instanceof GroupDeviceElement || fwd) {
sub_reply = ge.write_attribute_reply_i(rid, tmo, fwd);
if (!sub_reply.isEmpty()) {
reply.addAll(sub_reply);
}
if (sub_reply.has_failed()) {
reply.has_failed = true;
}
}
}
return reply;
}
}
/**
* Pseudo asynch. request generator
*/
private int next_req_id() {
asynch_req_id = asynch_req_id++ % java.lang.Integer.MAX_VALUE;
return asynch_req_id;
}
@Override
int read_attribute_asynch_i(final String[] a, final boolean fwd, final int rid) throws DevFailed {
return 0;
}
// -- PRIVATE INNER CLASS: GroupElementFactory -----------------------------
// -------------------------------------------------------------------------
private final class GroupElementFactory {
// ======================================================================
/**
* Instanciate the TangoElements which name matches the pattern p
*
* @param p the device name pattern (wild card).
* @return a list of GroupElement.
*/
// ======================================================================
public List instantiate(final String p) throws DevFailed {
// - a array to store GroupElement
String[] dnl;
// - is a device name or a device name pattern ?
if (p.indexOf('*') == -1) {
// -
is a pure device name
dnl = new String[1];
dnl[0] = p;
} else {
// - ask the db the list of device matching pattern p
final Database db = new Database();
dnl = db.get_device_exported(p);
}
if (dnl.length == 0) {
return Collections.emptyList();
}
final List ge = new ArrayList<>();
for (final String element : dnl) {
ge.add(new GroupDeviceElement(element));
}
return ge;
}
}
}