You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by jp...@apache.org on 2018/09/03 12:54:28 UTC

[camel] branch master updated (5f01118 -> 388db1b)

This is an automated email from the ASF dual-hosted git repository.

jpoth pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from 5f01118  Fix typo
     new 6a98e0b  Lets make the camel-api-component-maven-plugin handle generic methods with non generic return types
     new 388db1b  FHIR component add extended operations support

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../camel/util/component/ApiMethodParser.java      |  13 +-
 .../component/ArgumentSubstitutionParserTest.java  |   9 +-
 .../org/apache/camel/util/component/TestProxy.java |   4 +
 components/camel-fhir/camel-fhir-api/pom.xml       |   4 +
 .../camel/component/fhir/api/FhirHistory.java      |   2 +-
 .../camel/component/fhir/api/FhirOperation.java    | 202 +++++++++++++++++++++
 components/camel-fhir/camel-fhir-component/pom.xml |  12 ++
 .../signatures/operation-sig-api.txt               |  21 +++
 .../src/main/docs/fhir-component.adoc              |   1 +
 .../apache/camel/component/fhir/FhirEndpoint.java  |   4 +
 .../camel/component/fhir/FhirOperationIT.java      | 192 ++++++++++++++++++++
 .../apache/camel/component/fhir/FhirPatchIT.java   |   1 -
 12 files changed, 458 insertions(+), 7 deletions(-)
 create mode 100644 components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirOperation.java
 create mode 100644 components/camel-fhir/camel-fhir-component/signatures/operation-sig-api.txt
 create mode 100644 components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirOperationIT.java


[camel] 01/02: Lets make the camel-api-component-maven-plugin handle generic methods with non generic return types

Posted by jp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jpoth pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 6a98e0bbad0fb601d7a906e01884464aa1426d0a
Author: jpoth <po...@gmail.com>
AuthorDate: Fri Aug 31 11:17:46 2018 +0200

    Lets make the camel-api-component-maven-plugin handle generic methods with non generic return types
---
 .../org/apache/camel/util/component/ApiMethodParser.java    | 13 +++++++++----
 .../util/component/ArgumentSubstitutionParserTest.java      |  9 ++++++++-
 .../java/org/apache/camel/util/component/TestProxy.java     |  4 ++++
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
index 70013c8..62850ab 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
@@ -40,7 +40,7 @@ public abstract class ApiMethodParser<T> {
 
     private static final String METHOD_PREFIX = "^(\\s*(public|final|synchronized|native)\\s+)*(\\s*<[^>]>)?\\s*(\\S+)\\s+([^\\(]+\\s*)\\(";
     private static final Pattern METHOD_PATTERN = Pattern.compile("\\s*([^<\\s]+)?\\s*(<[^>]+>)?(<(?<genericTypeParameterName>\\S+)\\s+extends\\s+"
-            + "(?<genericTypeParameterUpperBound>\\S+)>\\s+\\k<genericTypeParameterName>)?\\s+(\\S+)\\s*\\(\\s*(?<signature>[\\S\\s,]*)\\)\\s*;?\\s*");
+            + "(?<genericTypeParameterUpperBound>\\S+)>\\s+(?<returnType>\\S+))?\\s+(\\S+)\\s*\\(\\s*(?<signature>[\\S\\s,]*)\\)\\s*;?\\s*");
 
     private static final String JAVA_LANG = "java.lang.";
     private static final Map<String, Class<?>> PRIMITIVE_TYPES;
@@ -120,16 +120,21 @@ public abstract class ApiMethodParser<T> {
             // handle generic methods with single bounded type parameters
             String genericTypeParameterName = null;
             String genericTypeParameterUpperBound = null;
+            String returnType = null;
             try {
                 genericTypeParameterName = methodMatcher.group("genericTypeParameterName");
                 genericTypeParameterUpperBound = methodMatcher.group("genericTypeParameterUpperBound");
+                returnType = methodMatcher.group("returnType");
+                if (returnType != null && returnType.equals(genericTypeParameterName)) {
+                    returnType = genericTypeParameterUpperBound;
+                }
             } catch (IllegalArgumentException e) {
                 // ignore
             }
 
-            final Class<?> resultType = genericTypeParameterName != null ? forName(genericTypeParameterUpperBound) : forName(methodMatcher.group(1));
-            final String name = methodMatcher.group(6);
-            final String argSignature = methodMatcher.group(7);
+            final Class<?> resultType = returnType != null ? forName(returnType) : forName(methodMatcher.group(1));
+            final String name = methodMatcher.group(7);
+            final String argSignature = methodMatcher.group(8);
 
             final List<ApiMethodArg> arguments = new ArrayList<>();
             final List<Class<?>> argTypes = new ArrayList<>();
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java b/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
index 05515e6..092ef08 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
@@ -17,6 +17,7 @@
 package org.apache.camel.util.component;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import org.apache.camel.util.component.ArgumentSubstitutionParser.Substitution;
@@ -51,10 +52,16 @@ public class ArgumentSubstitutionParserTest {
         signatures.add("public final String greetInnerChild(org.apache.camel.util.component.TestProxy.InnerChild child);");
         signatures.add("public final <T extends java.util.Date> T sayHiResource(java.util.Set<T> resourceType, String resourceId);");
         signatures.add("public final <T extends java.util.Date> T with(T theDate);");
+        signatures.add("public final <T extends java.util.Date> String withDate(T theDate, Class<? extends java.util.Date> dateClass, Class<T> parameter, T parameters);");
+
         parser.setSignatures(signatures);
 
         final List<ApiMethodParser.ApiMethodModel> methodModels = parser.parse();
-        assertEquals(11, methodModels.size());
+        assertEquals(12, methodModels.size());
+
+        final ApiMethodParser.ApiMethodModel withDate = methodModels.get(11);
+        assertEquals(String.class, withDate.getResultType());
+        assertEquals(Date.class, withDate.getArguments().get(0).getType());
 
         final ApiMethodParser.ApiMethodModel sayHi1 = methodModels.get(8);
         assertEquals(PERSON, sayHi1.getArguments().get(0).getName());
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java b/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
index 00bf1c2..0ca09f0 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
@@ -82,6 +82,10 @@ class TestProxy {
         return null;
     }
 
+    public final <T extends java.util.Date> String withDate(T theDate, Class<? extends java.util.Date> dateClass, Class<T> parameter, T parameters) {
+        return null;
+    }
+
     public final String greetInnerChild(InnerChild child) {
         return sayHi(child.getName());
     }


[camel] 02/02: FHIR component add extended operations support

Posted by jp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jpoth pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 388db1bbd1806d167eae9187c37342591a5b594b
Author: jpoth <po...@gmail.com>
AuthorDate: Mon Sep 3 13:37:32 2018 +0200

    FHIR component add extended operations support
---
 components/camel-fhir/camel-fhir-api/pom.xml       |   4 +
 .../camel/component/fhir/api/FhirHistory.java      |   2 +-
 .../camel/component/fhir/api/FhirOperation.java    | 202 +++++++++++++++++++++
 components/camel-fhir/camel-fhir-component/pom.xml |  12 ++
 .../signatures/operation-sig-api.txt               |  21 +++
 .../src/main/docs/fhir-component.adoc              |   1 +
 .../apache/camel/component/fhir/FhirEndpoint.java  |   4 +
 .../camel/component/fhir/FhirOperationIT.java      | 192 ++++++++++++++++++++
 .../apache/camel/component/fhir/FhirPatchIT.java   |   1 -
 9 files changed, 437 insertions(+), 2 deletions(-)

diff --git a/components/camel-fhir/camel-fhir-api/pom.xml b/components/camel-fhir/camel-fhir-api/pom.xml
index ccd42a8..fa3130b 100644
--- a/components/camel-fhir/camel-fhir-api/pom.xml
+++ b/components/camel-fhir/camel-fhir-api/pom.xml
@@ -38,6 +38,10 @@
 
   <dependencies>
     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+    <dependency>
       <groupId>ca.uhn.hapi.fhir</groupId>
       <artifactId>hapi-fhir-base</artifactId>
       <version>${hapi-fhir-version}</version>
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java
index e477c53..7b99c68 100644
--- a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirHistory.java
@@ -89,7 +89,7 @@ public class FhirHistory {
      * @param iCutoff Request that the server return only resource versions that were created at or after the given time (inclusive), may be NULL
      * @param <T> extends {@link IBaseBundle}
      * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
-     * @throws IllegalArgumentException If <code>theId</code> does not contain at least a resource type and ID
+     * @throws IllegalArgumentException If <code>id</code> does not contain at least a resource type and ID
      * @return the {@link IBaseBundle}
      */
     public <T extends IBaseBundle> T onInstance(IIdType id, Class<T> returnType, Integer count, Date cutoff, IPrimitiveType<Date> iCutoff, Map<ExtraParameters, Object> extraParameters) {
diff --git a/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirOperation.java b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirOperation.java
new file mode 100644
index 0000000..69bc1fd
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-api/src/main/java/org/apache/camel/component/fhir/api/FhirOperation.java
@@ -0,0 +1,202 @@
+/**
+ * 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.component.fhir.api;
+
+import java.util.Map;
+import ca.uhn.fhir.rest.client.api.IGenericClient;
+import ca.uhn.fhir.rest.gclient.IOperationProcessMsg;
+import ca.uhn.fhir.rest.gclient.IOperationProcessMsgMode;
+import ca.uhn.fhir.rest.gclient.IOperationUnnamed;
+import ca.uhn.fhir.rest.gclient.IOperationUntyped;
+import ca.uhn.fhir.rest.gclient.IOperationUntypedWithInput;
+
+import org.apache.camel.util.ObjectHelper;
+
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseParameters;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+/**
+ * API for extended FHIR operations https://www.hl7.org/fhir/operations.html
+ */
+public class FhirOperation {
+
+    private final IGenericClient client;
+
+    public FhirOperation(IGenericClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Perform the operation across all versions of all resources of the given type on the server
+     *
+     * @param resourceType The resource type to operate on
+     * @param name Operation name
+     * @param parameters The parameters to use as input. May also be <code>null</code> if the operation
+     * does not require any input parameters.
+     * @param outputParameterType The type to use for the output parameters (this should be set to
+     * <code>Parameters.class</code> drawn from the version of the FHIR structures you are using), may be NULL
+     * @param useHttpGet use HTTP GET verb
+     * @param returnType If this operation returns a single resource body as its return type instead of a <code>Parameters</code>
+     * resource, use this method to specify that resource type. This is useful for certain
+     * operations (e.g. <code>Patient/NNN/$everything</code>) which return a bundle instead of
+     * a Parameters resource, may be NULL
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseParameters}
+     * @return the {@link IBaseResource}
+     */
+    public <T extends IBaseParameters> IBaseResource onType(Class<IBaseResource> resourceType, String name,
+    T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<IBaseResource> returnType, Map<ExtraParameters, Object> extraParameters) {
+        IOperationUnnamed operationUnnamed = client.operation().onType(resourceType);
+        IOperationUntypedWithInput<? extends IBaseResource> operationUntypedWithInput = processNamedOperationParameters(
+                name, parameters, outputParameterType, useHttpGet, returnType, extraParameters, operationUnnamed);
+        return operationUntypedWithInput.execute();
+    }
+
+    /**
+     * Perform the operation across all versions of all resources of all types on the server
+     *
+     * @param name Operation name
+     * @param parameters The parameters to use as input. May also be <code>null</code> if the operation
+     * does not require any input parameters.
+     * @param outputParameterType The type to use for the output parameters (this should be set to
+     * <code>Parameters.class</code> drawn from the version of the FHIR structures you are using), may be NULL
+     * @param useHttpGet use HTTP GET verb
+     * @param returnType If this operation returns a single resource body as its return type instead of a <code>Parameters</code>
+     * resource, use this method to specify that resource type. This is useful for certain
+     * operations (e.g. <code>Patient/NNN/$everything</code>) which return a bundle instead of
+     * a Parameters resource, may be NULL
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseParameters}
+     * @return the {@link IBaseResource}
+     */
+    public <T extends IBaseParameters> IBaseResource onServer(
+            String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<IBaseResource> returnType, Map<ExtraParameters, Object> extraParameters) {
+        IOperationUnnamed operationUnnamed = client.operation().onServer();
+        IOperationUntypedWithInput<? extends IBaseResource> operationUntypedWithInput = processNamedOperationParameters(
+                name, parameters, outputParameterType, useHttpGet, returnType, extraParameters, operationUnnamed);
+        return operationUntypedWithInput.execute();
+    }
+
+    /**
+     * Perform the operation across all versions of a specific resource (by ID and type) on the server.
+     * Note that <code>theId</code> must be populated with both a resource type and a resource ID at
+     * a minimum.
+     *
+     * @param id Resource (version will be stripped)
+     * @param name Operation name
+     * @param parameters The parameters to use as input. May also be <code>null</code> if the operation
+     * does not require any input parameters.
+     * @param outputParameterType The type to use for the output parameters (this should be set to
+     * <code>Parameters.class</code> drawn from the version of the FHIR structures you are using), may be NULL
+     * @param useHttpGet use HTTP GET verb
+     * @param returnType If this operation returns a single resource body as its return type instead of a <code>Parameters</code>
+     * resource, use this method to specify that resource type. This is useful for certain
+     * operations (e.g. <code>Patient/NNN/$everything</code>) which return a bundle instead of
+     * a Parameters resource, may be NULL
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseParameters}
+     *
+     * @throws IllegalArgumentException If <code>theId</code> does not contain at least a resource type and ID
+     *
+     * @return the {@link IBaseResource}
+     */
+    public <T extends IBaseParameters> IBaseResource onInstance(
+            IIdType id, String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<IBaseResource> returnType, Map<ExtraParameters, Object> extraParameters) {
+        IOperationUnnamed operationUnnamed = client.operation().onInstanceVersion(id);
+        IOperationUntypedWithInput<? extends IBaseResource> operationUntypedWithInput = processNamedOperationParameters(
+                name, parameters, outputParameterType, useHttpGet, returnType, extraParameters, operationUnnamed);
+        return operationUntypedWithInput.execute();
+    }
+
+
+    /**
+     * This operation operates on a specific version of a resource
+     *
+     * @param id Resource version
+     * @param name Operation name
+     * @param parameters The parameters to use as input. May also be <code>null</code> if the operation
+     * does not require any input parameters.
+     * @param outputParameterType The type to use for the output parameters (this should be set to
+     * <code>Parameters.class</code> drawn from the version of the FHIR structures you are using), may be NULL
+     * @param useHttpGet use HTTP GET verb
+     * @param returnType If this operation returns a single resource body as its return type instead of a <code>Parameters</code>
+     * resource, use this method to specify that resource type. This is useful for certain
+     * operations (e.g. <code>Patient/NNN/$everything</code>) which return a bundle instead of
+     * a Parameters resource, may be NULL
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseParameters}
+     * @return the {@link IBaseResource}
+     */
+    public <T extends IBaseParameters> IBaseResource onInstanceVersion(
+            IIdType id, String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<IBaseResource> returnType, Map<ExtraParameters, Object> extraParameters) {
+        IOperationUnnamed operationUnnamed = client.operation().onInstanceVersion(id);
+        IOperationUntypedWithInput<? extends IBaseResource> operationUntypedWithInput = processNamedOperationParameters(
+                name, parameters, outputParameterType, useHttpGet, returnType, extraParameters, operationUnnamed);
+        return operationUntypedWithInput.execute();
+    }
+
+    /**
+     * This operation is called <b><a href="https://www.hl7.org/fhir/messaging.html">$process-message</a></b> as defined by the FHIR
+     * specification.<br><br>
+     * @param respondToUri An optional query parameter indicating that responses from the receiving server should be sent to this URI, may be NULL
+     * @param msgBundle Set the Message Bundle to POST to the messaging server
+     * @param asynchronous Whether to process the message asynchronously or synchronously, defaults to synchronous.
+     * @param responseClass the response class
+     * @param extraParameters see {@link ExtraParameters} for a full list of parameters that can be passed, may be NULL
+     * @param <T> extends {@link IBaseBundle}
+     * @return the {@link IBaseBundle}
+     */
+    public <T extends IBaseBundle> T processMessage(String respondToUri, IBaseBundle msgBundle, boolean asynchronous, Class<T> responseClass, Map<ExtraParameters, Object> extraParameters) {
+        IOperationProcessMsg operationProcessMsg = client.operation().processMessage();
+
+        if (ObjectHelper.isNotEmpty(respondToUri)) {
+            operationProcessMsg.setResponseUrlParam(respondToUri);
+        }
+
+        IOperationProcessMsgMode<T> operationProcessMsgMode = operationProcessMsg.setMessageBundle(msgBundle);
+
+        if (asynchronous) {
+            operationProcessMsgMode.asynchronous(responseClass);
+        } else {
+            operationProcessMsgMode.synchronous(responseClass);
+        }
+
+        ExtraParameters.process(extraParameters, operationProcessMsgMode);
+        return operationProcessMsgMode.execute();
+    }
+
+    private <T extends IBaseParameters> IOperationUntypedWithInput<? extends IBaseResource> processNamedOperationParameters(String name, T parameters, Class<T> outputParameterType,
+    boolean useHttpGet, Class<? extends IBaseResource> returnType, Map<ExtraParameters, Object> extraParameters, IOperationUnnamed operationUnnamed) {
+        IOperationUntyped named = operationUnnamed.named(name);
+        IOperationUntypedWithInput<? extends IBaseResource> operationUntypedWithInput;
+        if (outputParameterType != null) {
+            operationUntypedWithInput = named.withNoParameters(outputParameterType);
+        } else {
+            operationUntypedWithInput = named.withParameters(parameters);
+        }
+        if (useHttpGet) {
+            operationUntypedWithInput.useHttpGet();
+        }
+        if (returnType != null) {
+            operationUntypedWithInput.returnResourceType(returnType);
+        }
+        ExtraParameters.process(extraParameters, operationUntypedWithInput);
+        return operationUntypedWithInput;
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/pom.xml b/components/camel-fhir/camel-fhir-component/pom.xml
index 506d117..03a39a1 100644
--- a/components/camel-fhir/camel-fhir-component/pom.xml
+++ b/components/camel-fhir/camel-fhir-component/pom.xml
@@ -208,6 +208,18 @@
                   </nullableOptions>
                 </api>
                 <api>
+                  <apiName>operation</apiName>
+                  <proxyClass>org.apache.camel.component.fhir.api.FhirOperation</proxyClass>
+                  <fromSignatureFile>signatures/operation-sig-api.txt</fromSignatureFile>
+                  <nullableOptions>
+                    <nullableOption>extraParameters</nullableOption>
+                    <nullableOption>parameters</nullableOption>
+                    <nullableOption>outputParameterType</nullableOption>
+                    <nullableOption>returnType</nullableOption>
+                    <nullableOption>respondToUri</nullableOption>
+                  </nullableOptions>
+                </api>
+                <api>
                   <apiName>patch</apiName>
                   <proxyClass>org.apache.camel.component.fhir.api.FhirPatch</proxyClass>
                   <fromJavadoc/>
diff --git a/components/camel-fhir/camel-fhir-component/signatures/operation-sig-api.txt b/components/camel-fhir/camel-fhir-component/signatures/operation-sig-api.txt
new file mode 100644
index 0000000..e6ec415
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/signatures/operation-sig-api.txt
@@ -0,0 +1,21 @@
+## ------------------------------------------------------------------------
+## 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.
+## ------------------------------------------------------------------------
+ <T extends org.hl7.fhir.instance.model.api.IBaseParameters> org.hl7.fhir.instance.model.api.IBaseResource onType(Class<org.hl7.fhir.instance.model.api.IBaseResource> resourceType, String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<org.hl7.fhir.instance.model.api.IBaseResource> returnType, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+  <T extends org.hl7.fhir.instance.model.api.IBaseParameters> org.hl7.fhir.instance.model.api.IBaseResource onServer(String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<org.hl7.fhir.instance.model.api.IBaseResource> returnType, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+  <T extends org.hl7.fhir.instance.model.api.IBaseParameters> org.hl7.fhir.instance.model.api.IBaseResource onInstance(org.hl7.fhir.instance.model.api.IIdType id, String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<org.hl7.fhir.instance.model.api.IBaseResource> returnType, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+  <T extends org.hl7.fhir.instance.model.api.IBaseParameters> org.hl7.fhir.instance.model.api.IBaseResource onInstanceVersion(org.hl7.fhir.instance.model.api.IIdType id, String name, T parameters, Class<T> outputParameterType, boolean useHttpGet, Class<org.hl7.fhir.instance.model.api.IBaseResource> returnType, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
+  <T extends org.hl7.fhir.instance.model.api.IBaseBundle> T processMessage(String respondToUri, org.hl7.fhir.instance.model.api.IBaseBundle msgBundle, boolean asynchronous, Class<T> responseClass, java.util.Map<org.apache.camel.component.fhir.api.ExtraParameters,java.lang.Object> extraParameters);
diff --git a/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc b/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc
index 95a4a61..e2b5fb7 100644
--- a/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc
+++ b/components/camel-fhir/camel-fhir-component/src/main/docs/fhir-component.adoc
@@ -37,6 +37,7 @@ Endpoint prefix can be one of:
 * history
 * load-page
 * meta
+* operation
 * patch
 * read
 * search
diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java
index 01a438f..4670e8d 100644
--- a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java
+++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirEndpoint.java
@@ -29,6 +29,7 @@ import org.apache.camel.component.fhir.api.FhirDelete;
 import org.apache.camel.component.fhir.api.FhirHistory;
 import org.apache.camel.component.fhir.api.FhirLoadPage;
 import org.apache.camel.component.fhir.api.FhirMeta;
+import org.apache.camel.component.fhir.api.FhirOperation;
 import org.apache.camel.component.fhir.api.FhirPatch;
 import org.apache.camel.component.fhir.api.FhirRead;
 import org.apache.camel.component.fhir.api.FhirSearch;
@@ -111,6 +112,9 @@ public class FhirEndpoint extends AbstractApiEndpoint<FhirApiName, FhirConfigura
         case META:
             apiProxy = new FhirMeta(client);
             break;
+        case OPERATION:
+            apiProxy = new FhirOperation(client);
+            break;
         case PATCH:
             apiProxy = new FhirPatch(client);
             break;
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirOperationIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirOperationIT.java
new file mode 100644
index 0000000..1b07839
--- /dev/null
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirOperationIT.java
@@ -0,0 +1,192 @@
+/**
+ * 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.component.fhir;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.fhir.internal.FhirApiCollection;
+import org.apache.camel.component.fhir.internal.FhirOperationApiMethod;
+
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.IntegerType;
+import org.hl7.fhir.dstu3.model.Parameters;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test class for {@link org.apache.camel.component.fhir.api.FhirOperation} APIs.
+ */
+public class FhirOperationIT extends AbstractFhirTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FhirOperationIntegrationTest.class);
+    private static final String PATH_PREFIX = FhirApiCollection.getCollection().getApiName(FhirOperationApiMethod.class).getName();
+
+    @Test
+    public void testOnInstance() throws Exception {
+        final Map<String, Object> headers = new HashMap<String, Object>();
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+        // parameter type is String
+        headers.put("CamelFhir.name", "everything");
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseParameters
+        headers.put("CamelFhir.parameters", null);
+        // parameter type is Class
+        headers.put("CamelFhir.outputParameterType", Parameters.class);
+        headers.put("CamelFhir.useHttpGet", Boolean.FALSE);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", null);
+        // parameter type is java.util.Map
+        headers.put("CamelFhir.extraParameters", null);
+
+        final Parameters result = requestBodyAndHeaders("direct://ON_INSTANCE", null, headers);
+
+        LOG.debug("onInstance: " + result);
+        assertNotNull("onInstance result", result);
+        Bundle bundle = (Bundle) result.getParameter().get(0).getResource();
+        assertNotNull("onInstance result", bundle);
+        IdType id = bundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless();
+        assertEquals(patient.getIdElement().toUnqualifiedVersionless(), id);
+    }
+
+    @Test
+    public void testOnInstanceVersion() throws Exception {
+        final Map<String, Object> headers = new HashMap<String, Object>();
+        // parameter type is org.hl7.fhir.instance.model.api.IIdType
+        headers.put("CamelFhir.id", this.patient.getIdElement());
+        // parameter type is String
+        headers.put("CamelFhir.name", "everything");
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseParameters
+        headers.put("CamelFhir.parameters", null);
+        // parameter type is Class
+        headers.put("CamelFhir.outputParameterType", Parameters.class);
+        headers.put("CamelFhir.useHttpGet", Boolean.FALSE);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", null);
+        // parameter type is java.util.Map
+        headers.put("CamelFhir.extraParameters", null);
+
+        final Parameters result = requestBodyAndHeaders("direct://ON_INSTANCE_VERSION", null, headers);
+
+        LOG.debug("onInstance: " + result);
+        assertNotNull("onInstance result", result);
+        Bundle bundle = (Bundle) result.getParameter().get(0).getResource();
+        assertNotNull("onInstance result", bundle);
+        IdType id = bundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless();
+        assertEquals(patient.getIdElement().toUnqualifiedVersionless(), id);
+    }
+
+    @Test
+    public void testOnServer() throws Exception {
+        final Map<String, Object> headers = new HashMap<>();
+        // parameter type is String
+        headers.put("CamelFhir.name", "get-resource-counts");
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseParameters
+        headers.put("CamelFhir.parameters", null);
+        // parameter type is Class
+        headers.put("CamelFhir.outputParameterType", Parameters.class);
+        headers.put("CamelFhir.useHttpGet", Boolean.TRUE);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", null);
+        // parameter type is java.util.Map
+        headers.put("CamelFhir.extraParameters", null);
+
+        final Parameters result = requestBodyAndHeaders("direct://ON_SERVER", null, headers);
+
+        assertNotNull("onServer result", result);
+        LOG.debug("onServer: " + result);
+        int resourceCount = Integer.valueOf(((IntegerType)result.getParameter().get(0).getValue()).asStringValue());
+        assertTrue(resourceCount > 0);
+    }
+
+    @Test
+    public void testOnType() throws Exception {
+        final Map<String, Object> headers = new HashMap<String, Object>();
+        // parameter type is Class
+        headers.put("CamelFhir.resourceType", Patient.class);
+        // parameter type is String
+        headers.put("CamelFhir.name", "everything");
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseParameters
+        headers.put("CamelFhir.parameters", null);
+        // parameter type is Class
+        headers.put("CamelFhir.outputParameterType", Parameters.class);
+        headers.put("CamelFhir.useHttpGet", Boolean.FALSE);
+        // parameter type is Class
+        headers.put("CamelFhir.returnType", null);
+        // parameter type is java.util.Map
+        headers.put("CamelFhir.extraParameters", null);
+
+        final org.hl7.fhir.instance.model.api.IBaseResource result = requestBodyAndHeaders("direct://ON_TYPE", null, headers);
+
+        assertNotNull("onType result", result);
+        LOG.debug("onType: " + result);
+    }
+
+    @Ignore("Not implemented yet in HAPI FHIR server side, see"
+    + " https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoMessageHeaderDstu3.java#L33")
+    @Test
+    public void testProcessMessage() throws Exception {
+        final Map<String, Object> headers = new HashMap<String, Object>();
+        // parameter type is String
+        headers.put("CamelFhir.respondToUri", null);
+        // parameter type is org.hl7.fhir.instance.model.api.IBaseBundle
+        headers.put("CamelFhir.msgBundle", null);
+        headers.put("CamelFhir.asynchronous", Boolean.FALSE);
+        // parameter type is Class
+        headers.put("CamelFhir.responseClass", null);
+        // parameter type is java.util.Map
+        headers.put("CamelFhir.extraParameters", null);
+
+        final org.hl7.fhir.instance.model.api.IBaseBundle result = requestBodyAndHeaders("direct://PROCESS_MESSAGE", null, headers);
+
+        assertNotNull("processMessage result", result);
+        LOG.debug("processMessage: " + result);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() {
+                // test route for onInstance
+                from("direct://ON_INSTANCE")
+                        .to("fhir://" + PATH_PREFIX + "/onInstance");
+
+                // test route for onInstanceVersion
+                from("direct://ON_INSTANCE_VERSION")
+                        .to("fhir://" + PATH_PREFIX + "/onInstanceVersion");
+
+                // test route for onServer
+                from("direct://ON_SERVER")
+                        .to("fhir://" + PATH_PREFIX + "/onServer");
+
+                // test route for onType
+                from("direct://ON_TYPE")
+                        .to("fhir://" + PATH_PREFIX + "/onType");
+
+                // test route for processMessage
+                from("direct://PROCESS_MESSAGE")
+                        .to("fhir://" + PATH_PREFIX + "/processMessage");
+
+            }
+        };
+    }
+}
diff --git a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java
index 1a7116c..94e260c 100644
--- a/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java
+++ b/components/camel-fhir/camel-fhir-component/src/test/java/org/apache/camel/component/fhir/FhirPatchIT.java
@@ -133,7 +133,6 @@ public class FhirPatchIT extends AbstractFhirTestSupport {
         IIdType id = result.getId();
 
         Patient patient = fhirClient.read().resource(Patient.class).withId(id).preferResponseType(Patient.class).execute();
-        System.out.print(fhirContext.newJsonParser().encodeResourceToString(patient));
         assertTrue(patient.getActive());
     }
 }