/**
   * Write an object textual description in the output stream
   *
   * @param os an OutputStream
   * @throws IOException
   */
  public void dump(OutputStream os) throws IOException {
    _hdr.dump(os);

    if (_clientHandle != null) _clientHandle.dump(os);

    if (_context != null) _context.dump(os);

    for (Enumeration e = _clientSIs.elements(); e.hasMoreElements(); ) {
      COPSClientSI clientSI = (COPSClientSI) e.nextElement();
      clientSI.dump(os);
    }

    // Display any local decisions
    for (Enumeration e = _decisions.keys(); e.hasMoreElements(); ) {

      COPSContext context = (COPSContext) e.nextElement();
      Vector v = (Vector) _decisions.get(context);
      context.dump(os);

      for (Enumeration ee = v.elements(); e.hasMoreElements(); ) {
        COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();
        decision.dump(os);
      }
    }

    if (_integrity != null) {
      _integrity.dump(os);
    }
  }
  /**
   * Set the message length, base on the set of objects it contains
   *
   * @throws COPSException
   */
  protected void setMsgLength() throws COPSException {
    short len = 0;

    if (_clientHandle != null) len += _clientHandle.getDataLength();

    if (_context != null) len += _context.getDataLength();

    for (Enumeration e = _clientSIs.elements(); e.hasMoreElements(); ) {
      COPSClientSI clientSI = (COPSClientSI) e.nextElement();
      len += clientSI.getDataLength();
    }

    // Display any local decisions
    for (Enumeration e = _decisions.keys(); e.hasMoreElements(); ) {

      COPSContext context = (COPSContext) e.nextElement();
      Vector v = (Vector) _decisions.get(context);
      len += context.getDataLength();

      for (Enumeration ee = v.elements(); e.hasMoreElements(); ) {
        COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();
        len += decision.getDataLength();
      }
    }

    if (_integrity != null) {
      len += _integrity.getDataLength();
    }

    _hdr.setMsgLength((int) len);
  }
  /**
   * Writes data to given socket
   *
   * @param id a Socket
   * @throws IOException
   */
  public void writeData(Socket id) throws IOException {
    // checkSanity();
    if (_hdr != null) _hdr.writeData(id);
    if (_clientHandle != null) _clientHandle.writeData(id);
    if (_context != null) _context.writeData(id);

    for (Enumeration e = _clientSIs.elements(); e.hasMoreElements(); ) {
      COPSClientSI clientSI = (COPSClientSI) e.nextElement();
      clientSI.writeData(id);
    }

    // Display any local decisions
    for (Enumeration e = _decisions.keys(); e.hasMoreElements(); ) {

      COPSContext context = (COPSContext) e.nextElement();
      Vector v = (Vector) _decisions.get(context);
      context.writeData(id);

      for (Enumeration ee = v.elements(); e.hasMoreElements(); ) {
        COPSLPDPDecision decision = (COPSLPDPDecision) ee.nextElement();
        decision.writeData(id);
      }
    }

    if (_integrity != null) _integrity.writeData(id);
  }
  /**
   * Parses the data and fills COPSReqMsg with its constituents
   *
   * @param data a byte[]
   * @throws COPSException
   */
  protected void parse(byte[] data) throws COPSException {
    super.parseHeader(data);

    while (_dataStart < _dataLength) {
      byte[] buf = new byte[data.length - _dataStart];
      System.arraycopy(data, _dataStart, buf, 0, data.length - _dataStart);

      COPSObjHeader objHdr = new COPSObjHeader(buf);
      switch (objHdr.getCNum()) {
        case COPSObjHeader.COPS_HANDLE:
          {
            _clientHandle = new COPSHandle(buf);
            _dataStart += _clientHandle.getDataLength();
          }
          break;
        case COPSObjHeader.COPS_CONTEXT:
          {
            if (_context == null) {
              // Message context
              _context = new COPSContext(buf);
              _dataStart += _context.getDataLength();
            } else {
              // lpdp context
              _lpdpContext = new COPSContext(buf);
              _dataStart += _lpdpContext.getDataLength();
            }
          }
          break;
        case COPSObjHeader.COPS_ININTF:
          {
            if (objHdr.getCType() == 1) {
              _inInterface = new COPSIpv4InInterface(buf);
            } else {
              _inInterface = new COPSIpv6InInterface(buf);
            }
            _dataStart += _inInterface.getDataLength();
          }
          break;
        case COPSObjHeader.COPS_OUTINTF:
          {
            if (objHdr.getCType() == 1) {
              _outInterface = new COPSIpv4OutInterface(buf);
            } else {
              _outInterface = new COPSIpv6OutInterface(buf);
            }
            _dataStart += _outInterface.getDataLength();
          }
          break;
        case COPSObjHeader.COPS_LPDP_DEC:
          {
            COPSLPDPDecision lpdp = new COPSLPDPDecision(buf);
            _dataStart += lpdp.getDataLength();
            addLocalDecision(lpdp, _lpdpContext);
          }
          break;
        case COPSObjHeader.COPS_CSI:
          {
            COPSClientSI csi = new COPSClientSI(buf);
            _dataStart += csi.getDataLength();
            _clientSIs.add(csi);
          }
          break;
        case COPSObjHeader.COPS_MSG_INTEGRITY:
          {
            _integrity = new COPSIntegrity(buf);
            _dataStart += _integrity.getDataLength();
          }
          break;
        default:
          {
            throw new COPSException("Bad Message format, unknown object type");
          }
      }
    }
    checkSanity();
  }
 /**
  * Add integrity object
  *
  * @param integrity a COPSIntegrity
  * @throws COPSException
  */
 public void add(COPSIntegrity integrity) throws COPSException {
   if (integrity == null) throw new COPSException("Null Integrity");
   if (!integrity.isMessageIntegrity()) throw new COPSException("Error Integrity");
   _integrity = integrity;
   setMsgLength();
 }