/** @deprecated since 0.7.0 only {@link AbstractEnricher} has emit convenience */
  protected <T> void emit(Sensor<T> sensor, Object val) {
    checkState(entity != null, "entity must first be set");
    if (val == Entities.UNCHANGED) {
      return;
    }
    if (val == Entities.REMOVE) {
      ((EntityInternal) entity).removeAttribute((AttributeSensor<T>) sensor);
      return;
    }

    T newVal = TypeCoercions.coerce(val, sensor.getTypeToken());
    if (sensor instanceof AttributeSensor) {
      entity.sensors().set((AttributeSensor<T>) sensor, newVal);
    } else {
      entity.sensors().emit(sensor, newVal);
    }
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Override
  public void setEntity(EntityLocal entity) {
    super.setEntity(entity);

    this.producer = getConfig(PRODUCER) == null ? entity : getConfig(PRODUCER);
    this.sourceSensor = (Sensor<T>) getConfig(SOURCE_SENSOR);
    Sensor<?> targetSensorSpecified = getConfig(TARGET_SENSOR);
    List<? extends Sensor<?>> triggerSensorsSpecified = getConfig(TRIGGER_SENSORS);
    List<? extends Sensor<?>> triggerSensors =
        triggerSensorsSpecified != null ? triggerSensorsSpecified : ImmutableList.<Sensor<?>>of();
    this.targetSensor =
        targetSensorSpecified != null
            ? (Sensor<U>) targetSensorSpecified
            : (Sensor<U>) this.sourceSensor;
    if (targetSensor == null) {
      throw new IllegalArgumentException(
          "Enricher "
              + JavaClassNames.simpleClassName(this)
              + " has no "
              + TARGET_SENSOR.getName()
              + ", and it cannot be inferred as "
              + SOURCE_SENSOR.getName()
              + " is also not set");
    }
    if (sourceSensor == null && triggerSensors.isEmpty()) {
      throw new IllegalArgumentException(
          "Enricher "
              + JavaClassNames.simpleClassName(this)
              + " has no "
              + SOURCE_SENSOR.getName()
              + " and no "
              + TRIGGER_SENSORS.getName());
    }
    if (producer.equals(entity)
        && (targetSensor.equals(sourceSensor) || triggerSensors.contains(targetSensor))) {
      // We cannot call getTransformation() here to log the tranformation, as it will attempt
      // to resolve the transformation, which will cause the entity initialization thread to block
      LOG.error(
          "Refusing to add an enricher which reads and publishes on the same sensor: "
              + producer
              + "->"
              + targetSensor
              + " (computing transformation with "
              + JavaClassNames.simpleClassName(this)
              + ")");
      // we don't throw because this error may manifest itself after a lengthy deployment,
      // and failing it at that point simply because of an enricher is not very pleasant
      // (at least not until we have good re-run support across the board)
      return;
    }

    if (sourceSensor != null) {
      subscriptions()
          .subscribe(MutableMap.of("notifyOfInitialValue", true), producer, sourceSensor, this);
    }

    if (triggerSensors.size() > 0) {
      SensorEventListener<Object> triggerListener =
          new SensorEventListener<Object>() {
            @Override
            public void onEvent(SensorEvent<Object> event) {
              if (sourceSensor != null) {
                // Simulate an event, as though our sourceSensor changed
                Object value = producer.getAttribute((AttributeSensor<?>) sourceSensor);
                AbstractTransformer.this.onEvent(
                    new BasicSensorEvent(sourceSensor, producer, value, event.getTimestamp()));
              } else {
                // Assume the transform doesn't care about the value - otherwise it would
                // have declared a sourceSensor!
                AbstractTransformer.this.onEvent(null);
              }
            }
          };
      for (Object sensor : triggerSensors) {
        if (sensor instanceof String) {
          Sensor<?> resolvedSensor = entity.getEntityType().getSensor((String) sensor);
          if (resolvedSensor == null) {
            resolvedSensor = Sensors.newSensor(Object.class, (String) sensor);
          }
          sensor = resolvedSensor;
        }
        subscriptions()
            .subscribe(
                MutableMap.of("notifyOfInitialValue", true),
                producer,
                (Sensor<?>) sensor,
                triggerListener);
      }
    }
  }