/*
* ComponentDescription.java
*
* Created on April 16, 2001, 11:27 AM
*/
package context.arch.discoverer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import context.arch.comm.DataObject;
import context.arch.comm.DataObjects;
import context.arch.service.helper.ServiceDescription;
import context.arch.storage.Attribute;
import context.arch.storage.AttributeNameValue;
import context.arch.storage.AttributeNameValuePin;
import context.arch.storage.Attributes;
import context.arch.subscriber.Callback;
import context.arch.subscriber.Subscriber;
import context.arch.subscriber.Subscribers;
import context.arch.util.Error;
/**
* This class allows to store a component's description
*
* Has changed Vectors into ArrayList
* all server and widget att merged
* all callback / service of widget and server merged
*
* @author Agathe
* @author Brian Y. Lim
* @see context.arch.BaseObject
*
*/
public class ComponentDescription extends Object implements Cloneable {
/*
* The following are name tags for elements of ComponentDescription that may be used by the query system.
* Note that applications may define other novel elements to deal with interesting combinations
* (e.g. multidimensional, hypotenuse calculations)
*/
public static final String ID_ELEMENT = "id";
public static final String CLASSNAME_ELEMENT = "classname";
public static final String HOSTNAME_ELEMENT = "hostname";
public static final String PORT_ELEMENT = "port";
public static final String TYPE_ELEMENT = "type";
public static final String CONST_ATT_ELEMENT = "constAtt";
public static final String NON_CONST_ATT_ELEMENT = "nonConstAtt";
public static final String NON_CONST_ATT_NAME_ELEMENT = "nonConstAttName";
public static final String SERVICE_ELEMENT = "service";
public static final String SUBSCRIBER_ELEMENT = "subscriber";
public static final String CALLBACK_ELEMENT = "callback";
/**
* The component id
*/
public String id;
/**
* To component classname
*/
public String classname;
/**
* The component hostname
*/
public String hostname;
/**
* The component hostaddress
*/
public String hostaddress;
/**
* The component type : Discoverer.APPLICATION or Discoverer.WIDGET or Discoverer.SERVER
* or Discoverer.INTERPRETER
*/
public String type;
/**
* The component version
*/
public String version;
/**
* The component port
*/
public int port;
private Attributes constantAttributes;
private Attributes nonConstantAttributes;
private ArrayList<String> callbacks;
private ArrayList<String> services;
private ArrayList<String> subscribers;
private Attributes inAttributes;
private Attributes outAttributes;
/**
* The constructor that creates a new ComponentDescription with no parameters
*/
public ComponentDescription() {
constantAttributes = new Attributes();
nonConstantAttributes = new Attributes();
callbacks = new ArrayList<String>();
services = new ArrayList<String>();
subscribers = new ArrayList<String>();
inAttributes = new Attributes();
outAttributes = new Attributes();
}
/**
* This method allows to return the ComponentDescription version of a DataObject
*
* @param dataObject The DataObject containing the description of a context object
* @return ComponentDescription The ComponentDescription version
*/
public static ComponentDescription fromDataObject(DataObject dataObject) {
DataObject data = dataObject;
if (data == null) return null;
ComponentDescription comp = new ComponentDescription();
comp.setId(data.getDataObject(Discoverer.ID));
comp.setClassname(data.getDataObject(Discoverer.COMPONENT_CLASSNAME));
comp.setHostname(data.getDataObject(Discoverer.HOSTNAME));
comp.setHostaddress(data.getDataObject(Discoverer.HOSTADDRESS));
comp.setPort(data.getDataObject(Discoverer.PORT));
comp.setVersion(data.getDataObject(Discoverer.VERSION));
comp.setType(data.getDataObject(Discoverer.TYPE));
comp.setConstantAttributes(data.getDataObject(Discoverer.CONSTANT_ATTRIBUTE_NAME_VALUES));
comp.setNonConstantAttributes(data.getDataObject(Discoverer.NON_CONSTANT_ATTRIBUTE_NAME_VALUES));
comp.setSubscribers(data.getDataObject(Subscribers.SUBSCRIBERS));
comp.setWidgetCallbacks(data.getDataObject(Discoverer.WIDGET_CALLBACKS));
comp.setWidgetServices(data.getDataObject(Discoverer.WIDGET_SERVICES));
comp.setServerCallbacks(data.getDataObject(Discoverer.SERVER_CALLBACKS));
comp.setServerServices(data.getDataObject(Discoverer.SERVER_SERVICES));
comp.setInAttributes(data.getDataObject(Discoverer.INCOMING_ATTRIBUTE_NAME_VALUES));
comp.setOutAttributes(data.getDataObject(Discoverer.OUTGOING_ATTRIBUTE_NAME_VALUES));
return comp;
}
public DataObject toDataObject() {
DataObjects v1 = new DataObjects();
v1.addElement(new DataObject(Discoverer.ID, id));
v1.addElement(new DataObject(Discoverer.COMPONENT_CLASSNAME, classname));
v1.addElement(new DataObject(Discoverer.HOSTNAME, hostname));
v1.addElement(new DataObject(Discoverer.HOSTADDRESS, hostaddress));
v1.addElement(new DataObject(Discoverer.PORT, String.valueOf(port)));
v1.addElement(new DataObject(Discoverer.VERSION, version));
v1.addElement(new DataObject(Discoverer.TYPE, type));
// constant attributes
Attributes atts = new Attributes(this.constantAttributes);
DataObjects v = new DataObjects();
v.addElement(atts.toDataObject ());
v1.addElement(new DataObject(Discoverer.CONSTANT_ATTRIBUTE_NAME_VALUES, v));
// non-constant attributes
atts = new Attributes(this.nonConstantAttributes);
v = new DataObjects();
v.addElement(atts.toDataObject ());
v1.addElement(new DataObject (Discoverer.NON_CONSTANT_ATTRIBUTE_NAME_VALUES, v));
// subscribers
v = new DataObjects();
for (String subscriber : this.subscribers) {
v.addElement(new DataObject(Subscriber.SUBSCRIBER, subscriber));
}
v1.addElement(new DataObject(Subscribers.SUBSCRIBERS, v));
// callbacks
v = new DataObjects();
for (String callback : this.callbacks) {
v.addElement(new DataObject(Callback.CALLBACK_NAME, callback));
}
v1.addElement(new DataObject(Discoverer.WIDGET_CALLBACKS, v));
// services
v = new DataObjects();
for (String service : this.services) {
v.addElement(new DataObject(ServiceDescription.SERVICE_NAME, service));
}
v1.addElement (new DataObject (Discoverer.WIDGET_SERVICES, v));
v = new DataObjects();
for (Attribute<?> att : this.inAttributes.values()) {
v.addElement(att.toDataObject());
}
v1.addElement (new DataObject(Discoverer.INCOMING_ATTRIBUTE_NAME_VALUES, v));
v = new DataObjects();
for (Attribute<?> att : this.outAttributes.values()) {
v.addElement (att.toDataObject ());
}
v1.addElement (new DataObject(Discoverer.OUTGOING_ATTRIBUTE_NAME_VALUES, v));
DataObject res = new DataObject(Discoverer.REGISTERER, v1);
return res;
}
/**
* Returns a printable version of ComponentDescription
*
* @return String The string version of the ComponentDescription
*/
public String toString(){
StringBuffer s = new StringBuffer();
s.append("Id : "+id);
s.append(" - Classname : " + classname);
s.append(" - Hostname : " + hostname + " " + hostaddress);
s.append(" - Port : " + port);
s.append(" - Type : " + type);
s.append(" - Constant Attribute : " + constantAttributes);
//s.append(" - Constant Attribute Values : " + constantAttributeValues);
//s.append(" - Constant Attribute NamesValues : " + constantAttributeNamesValues);
s.append(" - Non Constant Attribute : " + nonConstantAttributes);
s.append(" - Incoming attributes : " + inAttributes);
s.append(" - Outgoing attributes : " + outAttributes);
s.append(" - Callbacks : " + callbacks);
s.append(" - Services : " + services);
s.append(" - Subscribers : " + subscribers);
return s.toString();
}
public String toSmallString(){
StringBuffer s = new StringBuffer();
s.append("Id : "+id);
s.append(" - Classname : " + classname);
s.append(" - Hostname : " + hostname + " " + hostaddress);
s.append(" - Port : " + port);
s.append(" - Type : " + type);
return s.toString();
}
public String toSmallStringNL(){
StringBuffer s = new StringBuffer();
s.append("Id : " + id);
s.append("\n - Hostname : " + hostname + " " + hostaddress);
s.append("\n - Port : " + port);
s.append("\n - Type : " + type);
return s.toString();
}
/**
* Returns a printable version of ComponentDescription with new lines
*
* @return String The string version of the ComponentDescription
*/
public String toStringNL(){
StringBuffer s = new StringBuffer();
s.append("\n- Id : " + id);
s.append("\n- Classname : " + classname);
s.append("\n- Hostname : " + hostname + " " + hostaddress);
s.append("\n- Port : " + port);
s.append("\n- Type : " + type);
s.append("\n- Constant Attribute : " + constantAttributes);
s.append("\n- Non Constant Attribute : " + nonConstantAttributes);
s.append("\n - Incoming attributes : " + inAttributes);
s.append("\n - Outgoing attributes : " + outAttributes);
s.append("\n - Widget callbacks : " + callbacks);
s.append("\n - Widget services : " + services);
s.append("\n - Subscribers : " + subscribers);
return s.toString();
}
/**
* Adds the data parameter to the constant attributes
*
* @param data The name of the constant attribute
* @see context.arch.storage.Attributes
*/
public void addConstantAttribute(AttributeNameValue<?> att) {
constantAttributes.put(att.getName(), att); // TODO should match both name and value
}
/**
* Adds a set of attribute names to the constant attributes. Gets a
* DISCOVERER_CONSTANT_ATTRIBUTE_NAME_VALUES DataObject
*
* @param data The DataObject containing a set of constant attribute names
* @return Error The error code
* @see context.arch.storage.Attributes
*/
public Error setConstantAttributes(DataObject data) {
Error err = new Error();
if (data != null) {
// Gets the ATTRIBUTE_NAME_VALUES data object's content
DataObject doAtt = data.getChildren().firstElement();
//Retrieve the attributeNameValues object
Attributes atts = Attributes.fromDataObject(doAtt);
setConstantAttributes(atts);
err.setError(Error.NO_ERROR);
}
else {
err.setError(Error.INVALID_DATA_ERROR);
}
return err;
}
public void setConstantAttributes(Attributes atts) {
this.constantAttributes = atts;
}
/**
* Adds the data parameter to the non constant attributes.
* May actually replace if already existent.
*
* @param att The non constant attribute
* @see context.arch.storage.Attribute
*/
public void addNonConstantAttribute(Attribute<?> att) {
nonConstantAttributes.put(att.getName(), att);
}
/**
* May actually replace if already existent.
* @param atts
*/
public void addNonConstantAttributes(Attributes atts) {
nonConstantAttributes.putAll(atts);
}
/**
* Adds a set of attribute names to the non constant attributes. Gets a
* DISCOVERER_NON_CONSTANT_ATTRIBUTE_NAME_VALUES DataObject
*
* @param data The DataObject containing a set of non constant attribute names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setNonConstantAttributes(DataObject data) {
Error err = new Error();
if (data != null) {
DataObjects vTemp = data.getChildren();
if (!vTemp.isEmpty()) {
DataObject doNCAtt = (DataObject) vTemp.firstElement();
Attributes NCatts = Attributes.fromDataObject(doNCAtt);
setNonConstantAttributes(NCatts);
}
// There is no error if the field is empty
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
public void setNonConstantAttributes(Attributes atts) {
this.nonConstantAttributes = atts;
}
/**
* Adds the data parameter to the incoming attributes
*
* @param data The incoming attribute
* @see context.arch.storage.Attribute
*/
public void setInAttribute(Attribute<?> data){
if (data != null){
inAttributes.add(data);
}
}
/**
* Adds a set of incoming attribute names to the cincoming attributes. Gets a
* INCOMING_DISCOVERER_ATTRIBUTE_NAME_VALUES DataObject
*
* @param data The DataObject containing a set of incoming attribute names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setInAttributes(DataObject data){
Error err = new Error();
if (data != null) {
DataObjects vTemp = data.getChildren();
if ( ! vTemp.isEmpty()) {
DataObject doInAtt = vTemp.firstElement();
for (DataObject InattValue : doInAtt.getChildren()) {
setInAttribute(Attribute.fromDataObject(InattValue));
}
}
// There is no error if the field is empty
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds the data parameter to the outgoing attributes
*
* @param data The outgoing attribute
* @see context.arch.storage.Attribute
*/
public void setOutAttribute (Attribute<?> data){
if (data != null ){
outAttributes.add(data);
}
}
/**
* Adds a set of outgoing attributes to the outgoing attributes. Gets a
* OUTGOING_DISCOVERER_CONSTANT_ATTRIBUTE_NAME_VALUES DataObject
*
* @param data The DataObject containing a set of outgoing attribute names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setOutAttributes(DataObject data){
Error err = new Error();
if (data != null) {
DataObjects vTemp = data.getChildren();
if ( ! vTemp.isEmpty()) {
DataObject doAtt = vTemp.firstElement();
for (DataObject attValue : doAtt.getChildren()) {
setOutAttribute(Attribute.fromDataObject(attValue));
}
}
// There is no error if the field is empty
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds a set of server non constant attributes to the server attributes. Gets a
* Discoverer.SERVER_NON_CONSTANT_ATTRIBUTES DataObject
*
* @param data The DataObject containing a set of server attribute names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setServerNonConstantAttributes(DataObject data) {
Error err = new Error();
DataObjects vTemp;
if ( (data != null) && ((vTemp = data.getChildren()) != null)) {
DataObject doAtt = (DataObject) vTemp.firstElement();
for (DataObject attValue : doAtt.getChildren()) {
// System.out.println("ComponentDescription.setServerNonConstantAttributes");
// System.out.println("\tattValue = " + attValue);
setServerNonConstantAttribute(Attribute.fromDataObject(attValue)); // TODO: note that NonConstants are only Attribute? Why no value?
}
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds the data parameter to the server non constant attributes
*
* @param data The servernopn constant attribute
* @see context.arch.storage.Attribute
*/
public void setServerNonConstantAttribute(Attribute<?> data) {
if (data != null) {
nonConstantAttributes.put(data.getName(), data);
}
}
/**
* Adds the data parameter to the subscriber attributes
*
* @param data The name of the subscriber attribute
* @see context.arch.storage.Attribute
*/
public void setSubscriber (String data){
if (data != null && ! data.trim().equals("")){
subscribers.add(data);
}
}
/**
* Adds a set of subscriber names to the subscriber attributes. Gets a
* DISCOVERER_CONSTANT_ATTRIBUTE_NAME_VALUES DataObject
*
* @param data The DataObject containing a set of subscriber attribute names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setSubscribers(DataObject data){
Error err = new Error();
DataObjects vTemp;
if (data != null) {
vTemp = data.getChildren();
if (! vTemp.isEmpty()) {
for (DataObject subValue : vTemp) {
if (! subValue.getValue().isEmpty()){
setSubscriber(subValue.getValue());
}
}
}
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds the data parameter to the server services
*
* @param data The name of the server services
* @see context.arch.storage.Attribute
*/
public void setServerService (String data){
if (data != null && ! data.trim().equals("")){
services.add(data);
}
}
/**
* Adds a set of server service names. Gets a
* SERVER_SERVICES DataObject
*
* @param data The DataObject containing a set of server services names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setServerServices(DataObject data){
Error err = new Error();
DataObjects vTemp;
if (data != null) {
vTemp = data.getChildren();
if ( ! vTemp.isEmpty() ) {
for (DataObject value : vTemp) {
if (! value.getValue().isEmpty()){
setServerService(value.getValue());
}
}
}
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds the data parameter to the widget callbacks
*
* @param data The name of the widget callbacks
* @see context.arch.storage.Attribute
*/
public void setWidgetCallback (String data){
if (data != null && ! data.trim().equals("")){
callbacks.add(data);
}
}
/**
* Adds a set of widget callback names to the callback. Gets a
* WIDGET_CALLBACKS DataObject
*
* @param data The DataObject containing a set of widget callback names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setWidgetCallbacks(DataObject data){
Error err = new Error();
DataObjects vTemp;
if (data != null) {
vTemp = data.getChildren();
if ( ! vTemp.isEmpty() ) {
for (DataObject callValue : vTemp) {
if (! callValue.getValue().isEmpty()){
setWidgetCallback(callValue.getValue());
}
}
}
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds the data parameter to the widget services
*
* @param data The name of the widget services
* @see context.arch.storage.Attribute
*/
public void setWidgetService (String data){
if (data != null && ! data.trim().equals("")){
services.add(data);
}
}
/**
* Adds a set of service names. Gets a
* WIDGET_SERVICES DataObject
*
* @param data The DataObject containing a set of widget services names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setWidgetServices(DataObject data){
Error err = new Error();
DataObjects vTemp;
if (data != null) {
vTemp = data.getChildren();
if ( ! vTemp.isEmpty() ) {
Enumeration<DataObject> list = vTemp.elements();
DataObject value;
while (list.hasMoreElements()){
value = list.nextElement();
if (!value.getValue().isEmpty()){
setWidgetService(value.getValue());
}
}
}
err.setError(Error.NO_ERROR);
}
else
err.setError(Error.INVALID_DATA_ERROR);
return err;
}
/**
* Adds the data parameter to the server callbacks
*
* @param data The name of the server callbacks
* @see context.arch.storage.Attribute
*/
public void setServerCallback(String data) {
if (data != null && ! data.trim().equals("")){
callbacks.add(data);
}
}
/**
* Adds a set of server callback names. Gets a
* SERVER_CALLBACKS DataObject
*
* @param data The DataObject containing a set of server callback names
* @return Error The error code
* @see context.arch.storage.Attribute
*/
public Error setServerCallbacks(DataObject data){
Error err = new Error();
DataObjects vTemp;
if (data != null) {
vTemp = data.getChildren();
if ( ! vTemp.isEmpty() ) {
Enumeration<DataObject> list = vTemp.elements();
DataObject value;
while (list.hasMoreElements()){
value = list.nextElement();
if (! value.getValue().isEmpty()) {
setServerCallback(value.getValue());
}
}
}
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the id. Gets an ID DataObject
*
* @param data The DataObject containing the id
* @return Error The error code
* @see context.arch.BaseObject#ID
*/
public Error setId(DataObject data) {
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()) {
id = data.getValue();
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the classname. Gets a
* COMPONENT_CLASSNAME DataObject
*
* @param data The DataObject containing the classname
* @return Error The error code
* @see context.arch.discoverer.Discoverer
*/
public Error setClassname(DataObject data) {
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()) {
classname = data.getValue();
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the component type. Gets a
* TYPE DataObject
*
* @param data The DataObject containing the type
* @return Error The error code
* @see context.arch.discoverer.Discoverer
*/
public Error setType(DataObject data){
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()) {
type = data.getValue();
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the component hostname. Gets a
* HOSTNAME DataObject
*
* @param data The DataObject containing the hostname
* @return Error The error code
* @see context.arch.discoverer.Discoverer
*/
public Error setHostname(DataObject data) {
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()) {
hostname = data.getValue();
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the component hostaddress. Gets a
* HOSTADDRESS DataObject
*
* @param data The DataObject containing the hostaddress
* @return Error The error code
* @see context.arch.discoverer.Discoverer
*/
public Error setHostaddress(DataObject data){
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()) {
hostaddress = data.getValue();
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the component port. Gets a
* PORT DataObject
*
* @param data The DataObject containing the port
* @return Error The error code
* @see context.arch.discoverer.Discoverer
*/
public Error setPort(DataObject data) {
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()){
try {
this.port = Integer.valueOf(data.getValue());
err.setError(Error.NO_ERROR);
}catch (NumberFormatException nfe) {
System.out.println("Discoverer - addComponent - NumberFormatException " + nfe);
err.setError(Error.INVALID_DATA_ERROR);
}
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* Sets the component version. Gets a
* VERSION DataObject
*
* @param data The DataObject containing the version
* @return Error The error code
* @see context.arch.discoverer.Discoverer
*/
public Error setVersion(DataObject data){
Error err = new Error();
if (data != null && ! data.getValue().isEmpty()) {
version = data.getValue();
err.setError(Error.NO_ERROR);
}
else { err.setError(Error.INVALID_DATA_ERROR); }
return err;
}
/**
* This method allows to get the modified descriptions fields and update the component
* Fields that can be modified : the non constant attributes (widget, server) and the subscribers,
* It gets a NON_CONSTANT_ATTRIBUTE_NAME_VALUES
* The default update type is the add type (Discoverer.UPDATE_ADD_TYPE)
*
* @param data The DataObject containing the modified fields
* @return Error The error code
* @see context.arch.comm.DataObject
* @see context.arch.discoverer.Discoverer
*/
public Error updateDescription(DataObject data) {
Error err = updateDescription(data, Discoverer.UPDATE_ADD_TYPE);
return err;
}
/**
* This method allows to get the modified descriptions fields and update the component
* Fields that can be modified : the non constant attributes (widget, server) and the subscribers,
* It gets a NON_CONSTANT_ATTRIBUTE_NAME_VALUES
*
* @param data The DataObject containing the modified fields
* @return Error The error code
* @see context.arch.comm.DataObject
* @see context.arch.discoverer.Discoverer
*/
public Error updateDescription(DataObject data, String updateType) {
Error error = new Error();
if (data != null) {
if (updateType == null){
updateType = Discoverer.UPDATE_ADD_TYPE;
}
//Test the widget non constant attributes
DataObject nonCAtt = data.getDataObject(Discoverer.NON_CONSTANT_ATTRIBUTE_NAME_VALUES);
if (updateType.equalsIgnoreCase(Discoverer.UPDATE_REPLACE_TYPE) && nonCAtt != null) {
// nonConstantAttributes = null; // don't need to nullify when assigning to new instance
nonConstantAttributes = new Attributes();
}
setNonConstantAttributes(nonCAtt);
// Test the subscribers
DataObject subs = data.getDataObject(Subscribers.SUBSCRIBERS);
if (updateType.equalsIgnoreCase(Discoverer.UPDATE_REPLACE_TYPE) && subs != null){
subscribers = new ArrayList<String>();
}
setSubscribers(subs);
error.setError(Error.NO_ERROR);
}
else
error.setError(Error.INVALID_DATA_ERROR);
return error ;
}
/**
* Returns an enumeration of the constant attribute names
*
* @return Enumeration The list of constant attribute names
*
public Enumeration getConstantAttributeNames(){
return constantAttributeNames.elements();
}
*/
/**
* Returns an enumeration of the constant attribute values
*
* @return Enumeration The list of constant attribute values
*
public Enumeration getConstantAttributeValues(){
return constantAttributeValues.elements();
}
*/
/**
* Returns an enumeration of the constant attribute names&values
*
* @return Enumeration The list of constant attribute objects, as a list of Attribute objects
*/
public Collection<AttributeNameValue<?>> getConstantAttributes() {
Collection<AttributeNameValue<?>> c = new ArrayList<AttributeNameValue<?>>();
for (Attribute<?> att : constantAttributes.values()) {
c.add((AttributeNameValue<?>)att);
}
// TODO: alternative method: just natively store list of AttributeNameValue<?>
return c;
}
public AttributeNameValue<?> getConstantAttribute(String name) {
return (AttributeNameValue<?>)constantAttributes.get(name);
}
/**
* Returns an enumeration of the non constant attributes
*
* @return Collection The list of non constant attributes, as a list of Attribute objects
*/
public Attributes getNonConstantAttributes() {
return nonConstantAttributes;
}
/**
* Return non-constant attributes as a collection of AttributeNameValue<?>,
* including only those with values (i.e. AttributeNameValue<?> not just Attribute<?>).
* So if a non-constant value had not had its value set, it would be omitted.
* @return
*/
public Collection<AttributeNameValue<?>> getNonConstantAttributeNameValues() {
Collection<AttributeNameValue<?>> atts = new ArrayList<AttributeNameValue<?>>();
for (Attribute<?> att : nonConstantAttributes.values()) {
if (att instanceof AttributeNameValue<?>) {
atts.add((AttributeNameValue<?>) att);
}
}
return atts;
}
public AttributeNameValue<?> getNonConstantAttributeNameValue(String name) {
return (AttributeNameValue<?>) nonConstantAttributes.get(name);
}
public Attribute<?> getNonConstantAttribute(String name) {
return nonConstantAttributes.get(name);
}
/**
* Returns all non constant attributes (non constant and constant)
*
* @return
*/
public Attributes getAllAttributes() {
Attributes all = new Attributes();
all.putAll(nonConstantAttributes);
all.putAll(constantAttributes);
return all;
}
/**
* Search for attribute with name from all attributes
* @param name
* @return
*/
@SuppressWarnings("unchecked")
public <T extends Comparable<? super T>> Attribute<T> getAttribute(String name) {
// try searching non-constant attributes first
Attribute<T> att = (Attribute<T>) nonConstantAttributes.get(name);
// then try constants if not yet found
if (att == null) {
att = (Attribute<T>) constantAttributes.get(name);
}
return att;
}
public <T extends Comparable<? super T>> T getAttributeValue(String name) {
T value = nonConstantAttributes.getAttributeValue(name);
if (value == null) {
value = constantAttributes.getAttributeValue(name);
}
return value;
}
/**
* Returns an enumeration of the incoming attributes
*
* @return Enumeration The list of incoming attributes, as a list of Attribute objects
*/
public Collection<Attribute<?>> getInAttributes() {
return inAttributes.values();
}
public Attribute<?> getInAttribute(String name) {
return inAttributes.get(name);
}
/**
* Returns an enumeration of the outgoing attributes
*
* @return Enumeration The list of outgoing attributes, as a list of Attribute objects
*/
public Collection<Attribute<?>> getOutAttributes() {
return outAttributes.values();
}
public Attribute<?> getOutAttribute(String name) {
return outAttributes.get(name);
}
/**
* To retrieve just the names of constant attributes for matching.
*
* @return Enumeration The list of widget/server constant attributes names
*/
public Collection<String> getConstantAttributeNames() {
return constantAttributes.keySet();
}
/**
* To retrieve just the values of constant attributes for matching.
*/
public Collection<String> getConstantAttributeValues() {
Collection<String> result = new ArrayList<String>();
for (AttributeNameValue<?> att : this.getConstantAttributes()) {
result.add(att.getValue().toString()); // TODO storing value as string is a waste of bytes and may have problems if a custom object does not have a proper toString method
// is the reason for using String to support data portability through the network protocol?
// result.add(att.getValue()); // changed value from String to Object; not sure if this breaks anything
}
return result;
}
/**
* To retrieve the names and values of constant attributes for matching.
*/
public Collection<String> getConstantAttributeNameValues() {
Collection<String> result = new ArrayList<String>();
for (AttributeNameValue<?> att : this.getConstantAttributes()) {
result.add(att.getName() + Discoverer.FIELD_SEPARATOR + att.getValue().toString());
}
return result;
}
public Collection<String> getNonConstantAttributeNames() {
Collection<String> result = new ArrayList<String>();
for (Attribute<?> att : nonConstantAttributes.values()) {
result.add(att.getName());
}
return result;
}
public Collection<Object> getNonConstantAttributeValues() {
Collection<Object> result = new ArrayList<Object>();
for (Attribute<?> a : nonConstantAttributes.values()) {
if (a instanceof AttributeNameValue<?>) { // TODO: would there be a case when these are not AttributeNameValue?
AttributeNameValue<?> att = (AttributeNameValue<?>) a;
result.add(att.getValue());
}
}
return result;
}
/**
* Returns an enumeration of the callbacks
*
* @return Enumeration The list of callbacks
*/
public Collection<String> getCallbacks(){
return callbacks;
}
/**
* Returns an enumeration of the widget callbacks,
* but if the callback name contains an underscore,
* then it returns just the last word.
* For example : for widgetName_callbackName we just
* return callbackName
*
* @return Enumeration The list of callbacks
*/
public SortedSet<String> getJustNameOfWidgetCallbacks() {
TreeSet<String> v = new TreeSet<String>();
Iterator<String> list = getCallbacks().iterator();
while (list.hasNext ()){
String call = (String) list.next();
// String underscore = "_";
int lastIndex = call.lastIndexOf ("_");
try {
String res = call.substring (lastIndex + 1, call.length ());
v.add (res);
}
catch(IndexOutOfBoundsException ioobe) {
System.out.println("ComponentDescription - getJustNameOfWidgetCallbacks - no underscore");
v.add (call);
}
}
return v;
}
/**
* Returns an enumeration of the widget services
*
* @return Enumeration The list of widget services
*/
public Collection<String> getServices() {
return services;
}
/**
* Returns an enumeration of the subscribers
*
* @return Enumeration The list of subscribers
*/
public Collection<String> getSubscribers() {
return subscribers;
}
/**
* This method allows to return a DataObject containing information that should be constant to the original component:
* <ul>
* <li>Discoverer.ID</li>
* <li>Discoverer.HOSTNAME</li>
* <li>Discoverer.PORT</li>
* <li>Discoverer.TYPE</li>
* <li>Discoverer.CONSTANT_ATTRIBUTE_NAME_VALUES</li>
* </ul>
*
* @return DataObject The data object containing the information
*/
public DataObject getBasicDataObject() {
DataObjects v1 = new DataObjects();
v1.add(new DataObject(Discoverer.ID, this.id));
v1.add(new DataObject(Discoverer.COMPONENT_CLASSNAME, this.classname)); // adicionado o valor do classe name que sera usado na verificacao do subscribe
v1.add(new DataObject(Discoverer.HOSTNAME, this.hostname));
v1.add(new DataObject(Discoverer.PORT, Integer.toString(this.port)));
v1.add(new DataObject(Discoverer.TYPE, this.type));
// constant attributes
Attributes atts = new Attributes(this.constantAttributes);
DataObjects v = new DataObjects();
v.addElement(atts.toDataObject());
v1.addElement(new DataObject(Discoverer.CONSTANT_ATTRIBUTE_NAME_VALUES, v));
return new DataObject(Discoverer.DISCOVERER_QUERY_REPLY_CONTENT, v1);
// ArrayList<DataObject> v1 = new ArrayList<DataObject>(); // TODO: why is this an ArrayList?
// v1.add(new DataObject(Discoverer.ID, this.id));
// v1.add(new DataObject(Discoverer.HOSTNAME, this.hostname));
// v1.add(new DataObject(Discoverer.PORT, Integer.toString(this.port)));
// v1.add(new DataObject(Discoverer.TYPE, this.type));
//
// DataObjects v = new DataObjects();
// v.addAll(v1);
// return new DataObject(Discoverer.DISCOVERER_QUERY_REPLY_CONTENT, v);
}
/**
* This method allows to compare 2 ComponentDescription objects.
* TODO: note that this equals comparison is very shallow and would not be good enough for comparing the data content
*
* @param otherComponent The ComponentDescription to compare to
* @return boolean The result of the comparison
*/
public boolean equals(ComponentDescription otherComponent) {
ComponentDescription c1 = this;
ComponentDescription c2 = otherComponent;
if (
!((c1.id == null && c2.id == null) || (c1.id != null && c2.id != null && c1.id.equals(c2.id)))
|| !((c1.classname == null && c2.classname == null) || (c1.classname != null && c2.classname != null && c1.classname.equals(c2.classname)))
|| !((c1.hostaddress == null && c2.hostaddress == null) || (c1.hostaddress != null && c2.hostaddress != null && c1.hostaddress.equals(c2.hostaddress)))
|| !((c1.hostname == null && c2.hostname == null) || (c1.hostname != null && c2.hostname != null && c1.hostname.equals(c2.hostname)))
|| !((c1.type == null && c2.type == null) || (c1.type != null && c2.type != null && c1.type.equals(c2.type)))
|| !((c1.version == null && c2.version == null) || (c1.version != null && c2.version != null && c1.version.equals(c2.version)))
// || c1.port != c2.port
) {
return false;
}
return true;
}
@Override
public boolean equals(Object o) {
return equals((ComponentDescription) o);
}
@Override
public ComponentDescription clone() {
ComponentDescription comp = new ComponentDescription();
comp.id = id;
comp.classname = classname;
comp.hostname = hostname;
comp.hostaddress = hostaddress;
comp.port = port;
comp.version = version;
comp.type = type;
comp.constantAttributes.putAll(constantAttributes);
comp.nonConstantAttributes.putAll(nonConstantAttributes);
comp.subscribers.addAll(subscribers);
comp.callbacks.addAll(callbacks);
comp.services.addAll(services);
comp.inAttributes.putAll(inAttributes);
comp.outAttributes.putAll(outAttributes);
return comp;
}
public ComponentDescription updateAttributes(ComponentDescription cd) {
Attribute<?> current_timestamp = nonConstantAttributes.get("timestamp");
Attribute<?> new_timestamp = cd.getNonConstantAttributes().get("timestamp");
if (new_timestamp instanceof AttributeNameValue<?> && current_timestamp instanceof AttributeNameValue<?> && ((AttributeNameValue<Long>) new_timestamp).getValue() >= ((AttributeNameValue<Long>) current_timestamp).getValue()) {
for (Attribute<?> current : cd.getNonConstantAttributes().values()) {
if (current instanceof AttributeNameValuePin<?> || current instanceof AttributeNameValue<?>) {
Attribute<?> target = nonConstantAttributes.get(current.getName());
if (target instanceof AttributeNameValuePin<?>) {
nonConstantAttributes.put(current.getName(), ((AttributeNameValuePin<?>) target).cloneWithNewValue(((AttributeNameValue<?>) current).getValue()));
} else if (target instanceof AttributeNameValue<?>) {
nonConstantAttributes.put(current.getName(), ((AttributeNameValue<?>) target).cloneWithNewValue(((AttributeNameValue<?>) current).getValue()));
} else {
nonConstantAttributes.put(current.getName(), current);
}
}
}
}
// for (Attribute<?> attribute : cd.getAllAttributes().values()) {
// if(this.getAllAttributes().containsName(attribute.getName())) {
// if (this.getAllAttributes().get(attribute.getName()) instanceof AttributeNameValue<?> && attribute instanceof AttributeNameValue<?>) {
// ((AttributeNameValue) this.getAllAttributes().get(attribute.getName())).setValue(((AttributeNameValue) attribute).getValue());
// }
// }
// }
return this;
}
public Attributes getConstantAttributesFull() {
return constantAttributes;
}
}