/**
   * Write a object instance to data output stream
   *
   * @param o the instance to be marshaled
   * @param dataOut the output stream
   * @throws IOException thrown if an error occurs
   */
  public void tightMarshal2(
      OpenWireFormat wireFormat, Object o, DataOutput dataOut, BooleanStream bs)
      throws IOException {
    super.tightMarshal2(wireFormat, o, dataOut, bs);

    ConsumerInfo info = (ConsumerInfo) o;
    tightMarshalCachedObject2(wireFormat, (DataStructure) info.getConsumerId(), dataOut, bs);
    bs.readBoolean();
    tightMarshalCachedObject2(wireFormat, (DataStructure) info.getDestination(), dataOut, bs);
    dataOut.writeInt(info.getPrefetchSize());
    dataOut.writeInt(info.getMaximumPendingMessageLimit());
    bs.readBoolean();
    tightMarshalString2(info.getSelector(), dataOut, bs);
    tightMarshalString2(info.getSubscriptionName(), dataOut, bs);
    bs.readBoolean();
    bs.readBoolean();
    bs.readBoolean();
    dataOut.writeByte(info.getPriority());
    tightMarshalObjectArray2(wireFormat, info.getBrokerPath(), dataOut, bs);
    tightMarshalNestedObject2(
        wireFormat, (DataStructure) info.getAdditionalPredicate(), dataOut, bs);
    bs.readBoolean();
    bs.readBoolean();
    bs.readBoolean();
    tightMarshalObjectArray2(wireFormat, info.getNetworkConsumerPath(), dataOut, bs);
  }
  /** Write the booleans that this object uses to a BooleanStream */
  public void looseMarshal(OpenWireFormat wireFormat, Object o, DataOutput dataOut)
      throws IOException {

    ConsumerInfo info = (ConsumerInfo) o;

    super.looseMarshal(wireFormat, o, dataOut);
    looseMarshalCachedObject(wireFormat, (DataStructure) info.getConsumerId(), dataOut);
    dataOut.writeBoolean(info.isBrowser());
    looseMarshalCachedObject(wireFormat, (DataStructure) info.getDestination(), dataOut);
    dataOut.writeInt(info.getPrefetchSize());
    dataOut.writeInt(info.getMaximumPendingMessageLimit());
    dataOut.writeBoolean(info.isDispatchAsync());
    looseMarshalString(info.getSelector(), dataOut);
    looseMarshalString(info.getSubscriptionName(), dataOut);
    dataOut.writeBoolean(info.isNoLocal());
    dataOut.writeBoolean(info.isExclusive());
    dataOut.writeBoolean(info.isRetroactive());
    dataOut.writeByte(info.getPriority());
    looseMarshalObjectArray(wireFormat, info.getBrokerPath(), dataOut);
    looseMarshalNestedObject(wireFormat, (DataStructure) info.getAdditionalPredicate(), dataOut);
    dataOut.writeBoolean(info.isNetworkSubscription());
    dataOut.writeBoolean(info.isOptimizedAcknowledge());
    dataOut.writeBoolean(info.isNoRangeAcks());
    looseMarshalObjectArray(wireFormat, info.getNetworkConsumerPath(), dataOut);
  }
  /** Write the booleans that this object uses to a BooleanStream */
  public int tightMarshal1(OpenWireFormat wireFormat, Object o, BooleanStream bs)
      throws IOException {

    ConsumerInfo info = (ConsumerInfo) o;

    int rc = super.tightMarshal1(wireFormat, o, bs);
    rc += tightMarshalCachedObject1(wireFormat, (DataStructure) info.getConsumerId(), bs);
    bs.writeBoolean(info.isBrowser());
    rc += tightMarshalCachedObject1(wireFormat, (DataStructure) info.getDestination(), bs);
    bs.writeBoolean(info.isDispatchAsync());
    rc += tightMarshalString1(info.getSelector(), bs);
    rc += tightMarshalString1(info.getSubscriptionName(), bs);
    bs.writeBoolean(info.isNoLocal());
    bs.writeBoolean(info.isExclusive());
    bs.writeBoolean(info.isRetroactive());
    rc += tightMarshalObjectArray1(wireFormat, info.getBrokerPath(), bs);
    rc += tightMarshalNestedObject1(wireFormat, (DataStructure) info.getAdditionalPredicate(), bs);
    bs.writeBoolean(info.isNetworkSubscription());
    bs.writeBoolean(info.isOptimizedAcknowledge());
    bs.writeBoolean(info.isNoRangeAcks());
    rc += tightMarshalObjectArray1(wireFormat, info.getNetworkConsumerPath(), bs);

    return rc + 9;
  }
  public void init() throws Exception {
    AMQServerSession coreSession = session.getCoreSession();

    SimpleString selector =
        info.getSelector() == null ? null : new SimpleString(info.getSelector());

    nativeId = session.getCoreServer().getStorageManager().generateID();

    SimpleString address = new SimpleString(this.actualDest.getPhysicalName());

    if (this.actualDest.isTopic()) {
      String physicalName = this.actualDest.getPhysicalName();
      if (physicalName.contains(".>")) {
        // wildcard
        physicalName = OpenWireUtil.convertWildcard(physicalName);
      }

      // on recreate we don't need to create queues
      address = new SimpleString("jms.topic." + physicalName);
      if (info.isDurable()) {
        subQueueName =
            new SimpleString(
                ActiveMQDestination.createQueueNameForDurableSubscription(
                    true, info.getClientId(), info.getSubscriptionName()));

        QueueQueryResult result = coreSession.executeQueueQuery(subQueueName);
        if (result.isExists()) {
          // Already exists
          if (result.getConsumerCount() > 0) {
            throw new IllegalStateException(
                "Cannot create a subscriber on the durable subscription since it already has subscriber(s)");
          }

          SimpleString oldFilterString = result.getFilterString();

          boolean selectorChanged =
              selector == null && oldFilterString != null
                  || oldFilterString == null && selector != null
                  || oldFilterString != null
                      && selector != null
                      && !oldFilterString.equals(selector);

          SimpleString oldTopicName = result.getAddress();

          boolean topicChanged = !oldTopicName.equals(address);

          if (selectorChanged || topicChanged) {
            // Delete the old durable sub
            coreSession.deleteQueue(subQueueName);

            // Create the new one
            coreSession.createQueue(address, subQueueName, selector, false, true);
          }

        } else {
          coreSession.createQueue(address, subQueueName, selector, false, true);
        }
      } else {
        subQueueName = new SimpleString(UUID.randomUUID().toString());

        coreSession.createQueue(address, subQueueName, selector, true, false);
      }

      coreSession.createConsumer(nativeId, subQueueName, null, info.isBrowser(), false, -1);
    } else {
      SimpleString queueName = new SimpleString("jms.queue." + this.actualDest.getPhysicalName());
      coreSession.createConsumer(nativeId, queueName, selector, info.isBrowser(), false, -1);
    }

    if (info.isBrowser()) {
      AMQServerConsumer coreConsumer = coreSession.getConsumer(nativeId);
      coreConsumer.setBrowserListener(this);
    }
  }