package chat;



/**
 * Classe che identifica un messaggio scambiato fra utenti adatto
 * alle esigenze della <i>chat</i>: interpreta il contenuto del
 * <i>buffer</i> interno di <code>MessaggioBase</code> per ottenere
 * un <i>sequence number</i>, un <code>byte</code> che assegna il
 * "tipo" di segmento informativo, un'eventuale firma digitale del
 * testo vero e prorio incluso nella busta rappresentata.
 * <p>
 * Più precisamente, il <i>buffer</i> interno alla super-classe viene
 * così interpretato da <code>Messaggio</code>:
 * <ul>
 *   <li>i primi 4 byte contengono un <code>int</code> che viene
 *       riconosciuto come <i>sequence number</i> del messaggio;
 *       tale intero viene serializzato secondo la semantica di
 *       <code>Utili.intToArray(...)</code> e <code>Utili.intFromArray(...)</code>;</li>
 *   <li>ulteriori 4 byte contengono l'<code>int</code> che tiene
 *       traccia della lunghezza della firma inclusa; sia <i>n</i>
 *       tale valore, maggiore o uguale a zero;</li>
 *   <li>un byte che rappresenta il "tipo" di datagramma;</li>
 *   <li>di seguito c'é il vero contenuto testuale di questa busta,
 *       inteso come successione di zero o più <code>byte</code>;</li>
 *   <li>gli ultimi <i>n</i> byte del <i>buffer</i> vengono considerati
 *       come campo "firma digitale" del suddetto testo.</li>
 * </ul>
 * Globalmente la cosa può esser vista in questo modo: un <i>header</i>
 * iniziale composto da 4 + 4 + 1 = 9 byte, il testo vero e proprio,
 * quindi un <i>footer</i> costituito dalla firma digitale del testo.
 * La lunghezza del <i>footer</i> è maggiore o uguale a zero, e tale
 * valore è mantenuto nell'<i>header</i>, mentre la lunghezza del testo
 * viene calcolata per differenza fra la lunghezza dell'intero <i>buffer</i>
 * e quella di <i>header+footer</i>.
 * <p>
 *
 * @author    <em>Alessandro Gaspari</em>
 * @version   1.0
 * @see       MessaggioBase
 * @see       MessaggioBase#che_cosa
 * @see       Utili#intToArray(int, byte[], int)
 * @see       Utili#intFromArray(byte[], int)
 */
public class Messaggio extends MessaggioBase {

  /**
   * Costruttore che richiama quello della super-classe.
   *
   * @param   da     il mittente del messaggio.
   * @param   a      il destinatario del suddetto.
   * @param   cosa   le informazioni da inserire nella busta.
   * @see     MessaggioBase#MessaggioBase(String, String, byte[])
   */
  public Messaggio(String da, String a, byte[] cosa) {
    super(da, a, cosa);
  }

  /**
   * Costruttore che permette di assegnare un valore specifico a
   * tutti i campi dell'istanza di <code>Messaggio</code>.
   *
   * @param   da        il mittente del messaggio.
   * @param   a         il destinatario del suddetto.
   * @param   seq_num   il <i>sequence number</i> da assegnargli.
   * @param   tipo      il "tipo" del segmento informativo.
   * @param   testo     le informazioni testuali da inserire nella busta.
   * @param   firma     la firma digitale relativa a <code>testo</code>.
   */
  public Messaggio(String da, String a, int seq_num, byte tipo, byte[] testo, byte[] firma) {
    super(da, a, new byte[4 + 4 + 1 + (testo == null ? 0 : testo.length) + (firma == null ? 0 : firma.length)]);
    scriviSeqNum(seq_num);
    Utili.intToArray(firma == null ? 0 : firma.length, che_cosa, 4);
    che_cosa[8] = tipo;
    if (testo != null)
      System.arraycopy(testo, 0, che_cosa, 4 + 4 + 1, testo.length);
    if (firma != null)
      System.arraycopy(firma, 0, che_cosa, che_cosa.length - firma.length, firma.length);
  }

  /**
   * Costruttore più semplice che assegna un valore ai campi più
   * usati dell'istanza di <code>Messaggio</code>. Equivale a:
   * <p>
   * <code>Messaggio(da, a, 0, tipo, testo, null);</code>
   *
   * @param   da        il mittente del messaggio.
   * @param   a         il destinatario del suddetto.
   * @param   tipo      il "tipo" del segmento informativo.
   * @param   testo     le informazioni testuali da inserire nella busta.
   * @see     #Messaggio(String, String, int, byte, byte[], byte[])
   */
  public Messaggio(String da, String a, byte tipo, byte[] testo) {
    this(da, a, 0, tipo, testo, null);
  }

  /**
   * <b>Modificatore primitiva</b> che scrive il <i>sequence number</i>.
   *
   * @param   seq_num   il numero di sequenza da assegnare al messaggio.
   */
  public void scriviSeqNum(int seq_num) {
    Utili.intToArray(seq_num, che_cosa, 0);
  }

  /**
   * <b>Selettore primitiva</b> che legge il <i>sequence number</i>.
   *
   * @return   il numero di sequenza del messaggio.
   */
  public int seqNum() { return Utili.intFromArray(che_cosa, 0); }

  /**
   * <b>Selettore primitiva</b> che ritorna il "tipo" del messaggio.
   *
   * @return   il tipo assegnato al <code>Messaggio</code>.
   */
  public byte tipo() {
    return che_cosa[8];
  }

  /**
   * <b>Selettore primitiva</b> per accedere al testo del messaggio.
   * <u>ATTENZIONE</u>: il contenuto del messaggio viene estratto
   * per copia, quindi non è possibile invocare questo metodo per
   * poi accedere in scrittura al messaggio stesso.
   *
   * @return   il testo del messaggio; può essere un <code>byte[]</code>
   *           avente lunghezza nulla, ma non <code>null</code>.
   */
  public byte[] testo() {
    byte[] ret = new byte[che_cosa.length - 4 - 4 - 1 - Utili.intFromArray(che_cosa, 4)];
    System.arraycopy(che_cosa, 4 + 4 + 1, ret, 0, ret.length);
    return ret;
  }

  /**
   * <b>Selettore primitiva</b> per ottenere il campo "firma digitale".
   * <u>ATTENZIONE</u>: il contenuto della firma viene estratto per
   * copia, quindi non è possibile invocare questo metodo per poi
   * modificare la firma contenuta nel messaggio.
   *
   * @return   il campo "firma"; può essere un <code>byte[]</code>
   *           avente lunghezza nulla, ma non <code>null</code>.
   */
  public byte[] firma() {
    byte[] ret = new byte[Utili.intFromArray(che_cosa, 4)];
    System.arraycopy(che_cosa, che_cosa.length - ret.length, ret, 0, ret.length);
    return ret;
  }
}


syntax highlighted by Code2HTML, v. 0.8.11