All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.dyade.aaa.agent.Notification Maven / Gradle / Ivy

There is a newer version: 5.22.0-EFLUID
Show newest version
/*
 * Copyright (C) 2001 - 2024 ScalAgent Distributed Technologies 
 * Copyright (C) 1996 - 2000 BULL
 * Copyright (C) 1996 - 2000 INRIA
 *
 * This library 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 2.1 of the License, or any later version.
 * 
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA.
 */
package fr.dyade.aaa.agent;

import java.io.IOException;
import java.io.Serializable;

import fr.dyade.aaa.common.encoding.Decoder;
import fr.dyade.aaa.common.encoding.Encodable;
import fr.dyade.aaa.common.encoding.EncodableFactory;
import fr.dyade.aaa.common.encoding.EncodableFactoryRepository;
import fr.dyade.aaa.common.encoding.Encoder;

/**
 * Class Notification is the root of the notifications hierarchy. Every
 * notification's class has Notification as a superclass.
 */
public class Notification implements Serializable, Cloneable, Encodable {
  /** define serialVersionUID for interoperability */
  static final long serialVersionUID = 1L;

  /**
   * True if the notification is persistent, false otherwise. By default, this
   * field is set to true during object creation and disk loading. This field
   * is carry by network protocol.
   * 
   * There is no public setter for this attribute. According the fact that a
   * notification class is or not persistent this attribute should be statically
   * fixed in the subclass constructor.
   */
  protected transient boolean persistent = true;

  /**
   * True if the notification is detachable, false otherwise. A detachable
   * notification is saved in a different object that its containing
   * message.
   */
  protected transient boolean detachable = false;

  /**
   * True if the notification is detached, false otherwise. A detached
   * notification is not destroyed in the same way that its containing
   * message.
   */
  protected transient boolean detached = false;

  /**
   * The expiration date for this notification.
   * 
   * This field is handled by the network protocol in order to fit the time
   * synchronization problem.
   */
  long expiration = 0L;

  /**
   * Sets the expiration date for this notification.
   * 
   * A value of 0L (default) indicates that the notification does not expire.
   * 
   * @param expiration
   *            the expiration date for this notification.
   */
  public void setExpiration(long expiration) {
    this.expiration = expiration;
  }

  /**
   * Gets the notification's expiration value.
   *
   * This field is handled by the network protocol in order to fit
   * the time synchronization problem.
   *
   * If the expiration date is set to 0L (default), it indicates that
   * the notification does not expire.
   *
   * When a notification's expiration time is reached, the MOM should
   * discard it without any form of notification of message expiration.
   * Agents should not receive messages that have expired; however, the
   * MOM does not guarantee that this will not happen.
   *
   * @return The notification's expiration value.
   */
  public long getExpiration() {
    return expiration;
  }

  /**
   * The priority for this notification from 0 to 9, 9 being the highest. By
   * default, the priority is 4
   */
  int priority = (byte) 4;
  
  /**
   * Sets the priority for this notification.
   * 
   * A value between 0 (lowest) and 9 (highest), by default 4 (normal).
   * 
   * @param priority
   *            the priority for this notification.
   */
  public void setPriority(int priority) {
    if ((priority >= 0) && (priority <= 9))
      this.priority = (byte) priority;
  }
  
  /**
   * Gets the notification's priority value.
   * 
   * @return The notification's priority value.
   */
  public int getPriority() {
    return priority;
  }

  /**
   * The agentId identifying the agent to which the notification is sent when it
   * is expired.
* Default value is null, which means the expired notification is lost. */ AgentId deadNotificationAgentId = null; /** * If the notification is stored independently that its containing message * messageId contains the persistent name of this notification. */ transient String messageId = null; public String getMessageId() { return messageId; } /** * Context of the notification. * * /!\ Be careful, the related object must be serialized either through Serializable or Encodable interfaces, * depending of the notification serialization mode. * It seems difficult to use, may be we should use a byte array handled by the application. * * TODO (AF): It seems never used in Joram/JoramMQ. */ private Object context; /** * Sets the context of the notification. * * @param context the context of the notification. */ public final void setContext(Object context) { this.context = context; } /** * Returns the context of the notification. * * @return the context of the notification. */ public final Object getContext() { return context; } /** * Returns a clone of this notification. * * @return a clone of this notification. */ public synchronized Object clone() { try { Notification dup = (Notification) super.clone(); dup.detached = false; dup.messageId = null; return dup; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } } /** * Return true if notification is persistent. * * @return persistent of this notification. */ public boolean isPersistent() { return persistent; } /** * * @return The agentId identifying the agent to which the notification is sent * when it is expired. */ public AgentId getDeadNotificationAgentId() { return deadNotificationAgentId; } /** * Sets the forwardExpiredNotAgentId value which enable sending expired * notifications to a specific agent * * @param deadNotificationAgentId * the AgentId to which the dead notification is forwarded */ public void setDeadNotificationAgentId(AgentId deadNotificationAgentId) { this.deadNotificationAgentId = deadNotificationAgentId; } private static final byte ExpirationSet = 0x10; private static final byte ContextSet = 0x20; private static final byte DeadNotificationAgentIdSet = 0x40; /** * The writeObject method is responsible for writing the state of the * object for its particular class so that the corresponding readObject * method can restore it. * * @param out The stream to write out. * @throws IOException if an errors occurs. */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { out.writeByte((priority&0x0F)| // 4 bits ((expiration > 0)?ExpirationSet:0x00)| ((context!=null)?ContextSet:0x00)| ((deadNotificationAgentId!=null)?DeadNotificationAgentIdSet:0x00)); if (expiration > 0) out.writeLong(expiration); if(context != null) { if (context instanceof Serializable) { Serializable serializable = (Serializable) context; out.writeObject(serializable); } else { throw new IOException("Context is not Serializable"); } } if (deadNotificationAgentId!=null) out.writeObject(deadNotificationAgentId); } /** * The readObject method is responsible for reading from the stream and * restoring the classes fields. * * @param in the stream to read from. * @throws IOException if an errors occurs during read. * @throws ClassNotFoundException a needed class cannot be found. */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { byte tmp = in.readByte(); priority = tmp & 0x0F; // 4 bits if ((tmp & ExpirationSet) != 0) expiration = in.readLong(); if ((tmp & ContextSet) != 0) context = in.readObject(); if ((tmp & DeadNotificationAgentIdSet) != 0) deadNotificationAgentId = (AgentId) in.readObject(); } /** * Appends a string image for this object to the StringBuffer parameter. * * @param output buffer to fill in. * @return the resulting buffer. */ public StringBuffer toString(StringBuffer output) { output.append('('); output.append(super.toString()); output.append(",messageId=").append(messageId); output.append(",persistent=").append(persistent); output.append(",detachable=").append(detachable); output.append(",detached=").append(detached); output.append(",context=").append(context); output.append(",expiration=").append(expiration); output.append(",priority=").append(priority); output.append(",deadNotificationAgentId=").append(deadNotificationAgentId); output.append(')'); return output; } /** * Provides a string image for this object. * * @return a string representation for this object. */ public final String toString() { StringBuffer output = new StringBuffer(); return toString(output).toString(); } /* ************************************************************ * Encodable interface. * ************************************************************/ /** * The class id is still not defined. */ @Override public int getEncodableClassId() { return -1; } /** * Returns the size of the encoded object. * @return the size of the encoded object * @exception Exception if an error occurs */ @Override public int getEncodedSize() throws Exception { int encodedSize = BYTE_ENCODED_SIZE; if (expiration > 0) encodedSize += LONG_ENCODED_SIZE; if (context != null) { if (context instanceof Encodable) { encodedSize += INT_ENCODED_SIZE; encodedSize += ((Encodable) context).getEncodedSize(); } else { throw new Exception("Context is not Encodable"); } } if (deadNotificationAgentId != null) encodedSize += deadNotificationAgentId.getEncodedSize(); return encodedSize; } /** * Encodes the object. * @param encoder the encoder * @exception Exception if an error occurs */ @Override public void encode(Encoder encoder) throws Exception { encoder.encodeByte((byte) ((priority & 0x0F) // 4 bits | ((expiration > 0) ? ExpirationSet : 0x00) | ((context != null) ? ContextSet : 0x00) | ((deadNotificationAgentId != null) ? DeadNotificationAgentIdSet : 0x00))); if (expiration > 0) encoder.encodeUnsignedLong(expiration); if (context != null) { if (context instanceof Encodable) { Encodable encodable = (Encodable) context; encoder.encodeUnsignedInt(encodable.getEncodableClassId()); encodable.encode(encoder); } else { throw new Exception("Context is not Encodable"); } } if (deadNotificationAgentId != null) deadNotificationAgentId.encode(encoder); } /** * Decodes the object. * @param decoder the encoder * @exception Exception if an error occurs */ @Override public void decode(Decoder decoder) throws Exception { byte tmp = decoder.decodeByte(); priority = tmp & 0x0F; // 4 bits if ((tmp & ExpirationSet) != 0) expiration = decoder.decodeUnsignedLong(); if ((tmp & ContextSet) != 0) { int classId = decoder.decodeUnsignedInt(); EncodableFactory factory = EncodableFactoryRepository.getFactory(classId); Encodable encodable = factory.createEncodable(); encodable.decode(decoder); context = encodable; } if ((tmp & DeadNotificationAgentIdSet) != 0) { deadNotificationAgentId = new AgentId(); deadNotificationAgentId.decode(decoder); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy