Merge pull request #621 from ppalaga/200114-service-renaming

Fix #620 Introduce CamelServiceInfo transformers
diff --git a/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/BuildProcessor.java b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/BuildProcessor.java
index 594ec28..154a816 100644
--- a/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/BuildProcessor.java
+++ b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/BuildProcessor.java
@@ -21,10 +21,12 @@
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
@@ -125,6 +127,12 @@
                     new CamelServiceFilterBuildItem(CamelServiceFilter.forService("properties-component-factory")));
         }
 
+        @BuildStep
+        void serviceInfoTransformers(BuildProducer<CamelServiceInfoTransformerBuildItem> mapperBuildItems) {
+            mapperBuildItems.produce(
+                    new CamelServiceInfoTransformerBuildItem(CamelServiceInfoTransformers::configurer));
+        }
+
         /*
          * Discover {@link TypeConverterLoader}.
          */
@@ -185,7 +193,8 @@
                 ApplicationArchivesBuildItem applicationArchives,
                 ContainerBeansBuildItem containerBeans,
                 List<CamelBeanBuildItem> registryItems,
-                List<CamelServiceFilterBuildItem> serviceFilters) {
+                List<CamelServiceFilterBuildItem> serviceFilters,
+                List<CamelServiceInfoTransformerBuildItem> serviceMappers) {
 
             final RuntimeValue<org.apache.camel.spi.Registry> registry = recorder.createRegistry();
 
@@ -205,6 +214,12 @@
 
                         return !blacklisted;
                     })
+                    .map(
+                            /* apply the CamelServiceInfo transformers */
+                            serviceMappers.stream()
+                                    .map(CamelServiceInfoTransformerBuildItem::getTransformer)
+                                    .reduce(Function::andThen)
+                                    .orElse(Function.identity()))
                     .forEach(si -> {
                         LOGGER.debug("Binding bean with name: {}, type {}", si.name, si.type);
 
diff --git a/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfo.java b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfo.java
index 8c46e13..2b6a2cf 100644
--- a/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfo.java
+++ b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfo.java
@@ -30,9 +30,8 @@
     public final Path path;
 
     /**
-     * The name of the service entry which is derived from the service path. As example the
-     * name for a service with path <code>META-INF/services/org/apache/camel/component/file</code>
-     * will be <code>file</code>
+     * The name under which this service will be registered in the Camel registry.
+     * This name may or may not be the same as the last segment of {@link #path}.
      */
     public final String name;
 
@@ -61,6 +60,15 @@
         return this.type;
     }
 
+    /**
+     * @param  newName the overriding name
+     * @return         a new {@link CamelServiceInfo} having all fields the same as the current {@link CamelServiceInfo}
+     *                 except for {@link #name} which is set to the given {@code newName}
+     */
+    public CamelServiceInfo withName(String newName) {
+        return new CamelServiceInfo(path, newName, type);
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
diff --git a/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformerBuildItem.java b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformerBuildItem.java
new file mode 100644
index 0000000..4da677a
--- /dev/null
+++ b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformerBuildItem.java
@@ -0,0 +1,42 @@
+/*
+ * 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.core.deployment;
+
+import java.util.function.Function;
+
+import io.quarkus.builder.item.MultiBuildItem;
+
+/**
+ * A {@link MultiBuildItem} holding a transformer function to be used to transform {@link CamelServiceInfo}s discovered
+ * in the classpath. This can be used e.g. for changing the name under which some particular service will be registered
+ * in the Camel registry.
+ */
+public final class CamelServiceInfoTransformerBuildItem extends MultiBuildItem {
+    private final Function<CamelServiceInfo, CamelServiceInfo> transformer;
+
+    public CamelServiceInfoTransformerBuildItem(Function<CamelServiceInfo, CamelServiceInfo> mapper) {
+        this.transformer = mapper;
+    }
+
+    /**
+     * @return the transformer function
+     */
+    public Function<CamelServiceInfo, CamelServiceInfo> getTransformer() {
+        return transformer;
+    }
+
+}
diff --git a/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformers.java b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformers.java
new file mode 100644
index 0000000..5d2db73
--- /dev/null
+++ b/extensions/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformers.java
@@ -0,0 +1,43 @@
+/*
+ * 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.core.deployment;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public final class CamelServiceInfoTransformers {
+
+    private static final Path CONFIGURER_PATH = Paths.get("configurer");
+
+    private CamelServiceInfoTransformers() {
+    }
+
+    /**
+     * Configurers need to get registered under a different name in the registry than the name of
+     * the service file
+     *
+     * @param  serviceInfo the {@link CamelServiceInfo} that will possibly be transformed
+     * @return             the given {@code serviceInfo} or a new {@link CamelServiceInfo}
+     */
+    public static CamelServiceInfo configurer(CamelServiceInfo serviceInfo) {
+        final Path path = serviceInfo.path;
+        final int pathLen = path.getNameCount();
+        return (pathLen >= 2 && CONFIGURER_PATH.equals(path.getName(pathLen - 2)))
+                ? serviceInfo.withName(path.getFileName().toString() + "-configurer")
+                : serviceInfo;
+    }
+}
diff --git a/extensions/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformersTest.java b/extensions/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformersTest.java
new file mode 100644
index 0000000..cdef8db
--- /dev/null
+++ b/extensions/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/CamelServiceInfoTransformersTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.deployment;
+
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class CamelServiceInfoTransformersTest {
+
+    @Test
+    void configurer() {
+        {
+            final CamelServiceInfo info = new CamelServiceInfo(Paths.get(""), "foo", "org.foo.Foo");
+            Assertions.assertEquals(info, CamelServiceInfoTransformers.configurer(info));
+        }
+        {
+            final CamelServiceInfo info = new CamelServiceInfo(Paths.get("foo"), "foo", "org.foo.Foo");
+            Assertions.assertEquals(info, CamelServiceInfoTransformers.configurer(info));
+        }
+        {
+            final CamelServiceInfo info = new CamelServiceInfo(Paths.get("foo/bar/baz"), "foo", "org.foo.Foo");
+            Assertions.assertEquals(info, CamelServiceInfoTransformers.configurer(info));
+        }
+        {
+            final CamelServiceInfo info = new CamelServiceInfo(Paths.get("foo/configurer/baz"), "foo", "org.foo.Foo");
+            Assertions.assertEquals(new CamelServiceInfo(Paths.get("foo/configurer/baz"), "baz-configurer", "org.foo.Foo"),
+                    CamelServiceInfoTransformers.configurer(info));
+        }
+    }
+}