/**
   * Add an IN or OUT interface object
   *
   * @param inter a COPSInterface
   * @throws COPSException
   */
  public void add(COPSInterface inter) throws COPSException {
    if (!(inter.isInInterface() || inter.isOutInterface())) throw new COPSException("No Interface");

    // Message integrity object should be the very last one
    // If it is already added
    if (_integrity != null) throw new COPSException("Integrity should be the last one");

    if (inter.isInInterface()) {
      if (_inInterface != null) throw new COPSException("Object inInterface exits");

      if (inter.isIpv4Address()) {
        COPSIpv4InInterface inInter = (COPSIpv4InInterface) inter;
        _inInterface = inInter;
      } else {
        COPSIpv6InInterface inInter = (COPSIpv6InInterface) inter;
        _inInterface = inInter;
      }
    } else {
      if (_outInterface != null) throw new COPSException("Object outInterface exits");

      if (inter.isIpv4Address()) {
        COPSIpv4OutInterface outInter = (COPSIpv4OutInterface) inter;
        _outInterface = outInter;
      } else {
        COPSIpv6OutInterface outInter = (COPSIpv6OutInterface) inter;
        _outInterface = outInter;
      }
    }
    setMsgLength();
  }
  /**
   * 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();
  }