content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.camel.quarkus.component.smallrye.reactive.messaging.deployment;
  
  import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
  import io.quarkus.arc.processor.DotNames;
  import io.quarkus.deployment.annotations.BuildProducer;
  import io.quarkus.deployment.annotations.BuildStep;
  import io.quarkus.deployment.builditem.FeatureBuildItem;
  import io.smallrye.reactive.messaging.camel.CamelConnector;
  import org.jboss.jandex.AnnotationInstance;
  import org.jboss.jandex.AnnotationTarget;
  import org.jboss.jandex.AnnotationTransformation;
  import org.jboss.jandex.AnnotationValue;
  import org.jboss.jandex.ClassInfo;
  import org.jboss.jandex.Declaration;
  import org.jboss.jandex.DotName;
  import org.jboss.jandex.FieldInfo;
  import org.jboss.jandex.MethodInfo;
  
  class SmallRyeReactiveMessagingProcessor {
  
      private static final DotName CAMEL_CONNECTOR_DOTNAME = DotName.createSimple(CamelConnector.class.getName());
      private static final String FEATURE = "camel-smallrye-reactive-messaging";
  
      @BuildStep
      FeatureBuildItem feature() {
          return new FeatureBuildItem(FEATURE);
      }
  
      @BuildStep
      void overrideSmallRyeReactiveMessagingConfiguration(BuildProducer<AnnotationsTransformerBuildItem> transformers) {
          // Veto setup & configuration logic that is already handled by the camel-quarkus-reactive-streams extension
          transformers.produce(new AnnotationsTransformerBuildItem(new AnnotationTransformation() {
              @Override
              public void apply(TransformationContext context) {
                  Declaration declaration = context.declaration();
                  if (declaration.kind().equals(AnnotationTarget.Kind.FIELD)) {
                      FieldInfo fieldInfo = declaration.asField();
                      ClassInfo classInfo = fieldInfo.declaringClass();
  
                      // Make CamelReactiveStreamsService injectable from producers configured in the reactive-streams extension
                      if (classInfo.name().equals(CAMEL_CONNECTOR_DOTNAME) && fieldInfo.name().equals("reactive")) {
                          AnnotationInstance injectAnnotation = getAnnotationInstance(DotNames.INJECT, fieldInfo);
                          context.add(injectAnnotation);
                      }
                  }
  
                  if (context.declaration().kind().equals(AnnotationTarget.Kind.METHOD)) {
                      MethodInfo methodInfo = declaration.asMethod();
                      ClassInfo classInfo = methodInfo.declaringClass();
  
                      if (classInfo.name().equals(CAMEL_CONNECTOR_DOTNAME)) {
                          // Disable CamelReactiveStreamsService producer since the reactive-streams extension handles this
                          if (methodInfo.name().equals("getCamelReactive")) {
                              AnnotationInstance producesAnnotation = getAnnotationInstance(DotNames.PRODUCES, methodInfo);
                              context.remove(
                                      annotationInstance -> annotationInstance.target().equals(producesAnnotation.target()));
                          }
                      }
                  }
              }
          }));
      }
  
      private AnnotationInstance getAnnotationInstance(DotName dotName, AnnotationTarget target) {
          return AnnotationInstance.create(dotName, target, new AnnotationValue[0]);
      }
  }
  